123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503 |
- /////////////////////////////////////////////////////////////////////////////
- // AGCEventDef.cpp : Implementation of CAGCEventDef
- //
- #include "pch.h"
- #include <AGC.h>
- #include "AGCEventDef.h"
- #include "resource.h"
- #include <..\TCLib\ObjectLock.h>
- /////////////////////////////////////////////////////////////////////////////
- // TCSimpleLock Adaptor
- class TCSimpleLock
- {
- // Construction
- public:
- TCSimpleLock(LONG& nSync) :
- m_nSync(nSync) {}
- // Operations
- public:
- void Lock()
- {
- while (InterlockedExchange(&m_nSync, 1))
- Sleep(10);
- }
- void Unlock()
- {
- InterlockedExchange(&m_nSync, 0);
- }
- // Data Members
- protected:
- LONG& m_nSync;
- };
- /////////////////////////////////////////////////////////////////////////////
- // CAGCEventDef
- /////////////////////////////////////////////////////////////////////////////
- // Include the XML/XSL-generated files
- #include <AGCEventsRCH.h>
- #include <AGCEventsCPP.h>
- /////////////////////////////////////////////////////////////////////////////
- // Static Initialization
- LONG CAGCEventDef::s_nInitSync = 0;
- bool CAGCEventDef::s_bInitialized = false;
- CAGCEventDef::XNameMap* CAGCEventDef::s_pNameMap = NULL;
- CAGCEventDef CAGCEventDef::s_Instance;
- ///////////////////////////////////////////////////////////////////////////
- // Construction / Destruction
- CAGCEventDef::CAGCEventDef()
- {
- // Debug-only data verification
- #ifdef _DEBUG
- {
- // Validate that all table entries are in ascending order
- const XEventDef* a = begin();
- const XEventDef* b = a + 1;
- while (end() != b)
- assert(XLess()(*a++, *b++));
- // Validate that all group scopes match
- int nIndent = 0;
- for (const XEventDef* it = begin(); end() != it; ++it)
- {
- assert(-1 <= it->m_nIndent && it->m_nIndent <= 1);
- nIndent += it->m_nIndent;
- assert(0 <= nIndent);
- }
- assert(0 == nIndent);
- }
- #endif // _DEBUG
- }
- void CAGCEventDef::Initialize()
- {
- TCSimpleLock spinLock(s_nInitSync);
- TCObjectLock<TCSimpleLock> lock(&spinLock);
- if (s_bInitialized)
- return;
- // Map all of the event names to ID's
- s_pNameMap = new XNameMap;
- for (const XEventDef* it = begin(); end() != it; ++it)
- {
- if (HIWORD(reinterpret_cast<DWORD>(it->m_pszName)))
- (*s_pNameMap)[it->m_pszName] = it->m_id;
- else
- {
- BSTR bstrName;
- ZSucceeded(GetString(it->m_pszName, &bstrName));
- (*s_pNameMap)[bstrName] = it->m_id;
- }
- }
- s_bInitialized = true;
- }
- void CAGCEventDef::Terminate()
- {
- TCSimpleLock spinLock(s_nInitSync);
- TCObjectLock<TCSimpleLock> lock(&spinLock);
- if (!s_bInitialized)
- return;
- // Free each BSTR in the name map
- for (XNameMapIt it = s_pNameMap->begin(); it != s_pNameMap->end(); ++it)
- {
- const XEventDef* itFind = find(it->second);
- assert(itFind != end());
- if (!HIWORD(reinterpret_cast<DWORD>(itFind->m_pszName)))
- SysFreeString(const_cast<BSTR>(it->first));
- }
- delete s_pNameMap;
- s_pNameMap = NULL;
- s_bInitialized = false;
- }
- /////////////////////////////////////////////////////////////////////////////
- // Attributes
- HRESULT CAGCEventDef::GetEventName(AGCEventID idEvent, BSTR* pbstrOut)
- {
- // Initialize the [out] parameter
- *pbstrOut = NULL;
- // Find the definition of the event ID
- const XEventDef* it = find(idEvent);
- if (end() == it)
- return E_INVALIDARG;
- // Get the event name string
- HRESULT hr = GetString(it->m_pszName, pbstrOut);
- // Indicate success
- return S_OK;
- }
- HRESULT CAGCEventDef::GetEventDescription(AGCEventID idEvent, BSTR* pbstrOut)
- {
- // Initialize the [out] parameter
- *pbstrOut = NULL;
- // Find the definition of the event ID
- const XEventDef* it = find(idEvent);
- if (end() == it)
- return E_INVALIDARG;
- // Get the event description string
- HRESULT hr = GetString(it->m_pszEventDescription, pbstrOut);
- // If not specified, use the event name string
- return (S_FALSE != hr) ? hr : GetEventName(it->m_id, pbstrOut);
- }
- HRESULT CAGCEventDef::GetEventDescription(IAGCEvent* pEvent, BSTR* pbstrOut,
- const XEventDef* pDefHint)
- {
- // Initialize the [out] parameter
- *pbstrOut = NULL;
- assert(pEvent);
- // Find the definition of the event ID, if not specified
- if (!pDefHint)
- {
- // Get the specified event's ID
- AGCEventID idEvent;
- RETURN_FAILED(pEvent->get_ID(&idEvent));
- // Lookup the event ID in the table
- const XEventDef* it = find(idEvent);
- if (end() == it)
- return E_INVALIDARG;
- pDefHint = it;
- }
- else
- {
- #ifdef _DEBUG
- // Get the specified event's ID
- AGCEventID idEvent;
- RETURN_FAILED(pEvent->get_ID(&idEvent));
- assert(pDefHint->m_id == idEvent);
- #endif // _DEBUG
- }
- // Get the event description formatting string
- CComBSTR bstrFmt;
- HRESULT hr = GetString(pDefHint->m_pszFormatDescription, &bstrFmt);
- RETURN_FAILED(hr);
- if (S_FALSE == hr)
- {
- // Use the static description
- return GetEventDescription(pDefHint->m_id, pbstrOut);
- }
- // Format the event
- assert(pEvent);
- return ExpandFmtString(bstrFmt, pEvent, pbstrOut);
- }
- HRESULT CAGCEventDef::GetEventParameters (IAGCEvent* pEvent,
- CAGCEventDef::XParamStrings& rParamStrings, const XEventDef* pDefHint)
- {
- assert(pEvent);
- // Find the definition of the event ID, if not specified
- if (!pDefHint)
- {
- // Get the specified event's ID
- AGCEventID idEvent;
- RETURN_FAILED(pEvent->get_ID(&idEvent));
- // Lookup the event ID in the table
- const XEventDef* it = find(idEvent);
- if (end() == it)
- return E_INVALIDARG;
- pDefHint = it;
- }
- else
- {
- #ifdef _DEBUG
- // Get the specified event's ID
- AGCEventID idEvent;
- RETURN_FAILED(pEvent->get_ID(&idEvent));
- assert(pDefHint->m_id == idEvent);
- #endif // _DEBUG
- }
- // Get the event description formatting string
- CComBSTR bstrFmt;
- HRESULT hr = GetString(pDefHint->m_pszFormatDescription, &bstrFmt);
- if (S_OK != hr)
- return hr;
- // Get the event parameters
- return ExpandParams(bstrFmt, pEvent, rParamStrings);
- }
- /////////////////////////////////////////////////////////////////////////////
- // Implementation
- HRESULT CAGCEventDef::GetString(LPCOLESTR psz, BSTR* pbstrOut)
- {
- // Get the specified string as a DWORD
- DWORD dw = reinterpret_cast<DWORD>(psz);
- // If HIWORD is non-null, this is a string pointer
- if (HIWORD(dw))
- {
- USES_CONVERSION;
- *pbstrOut = SysAllocString(psz);
- return *pbstrOut ? (SysStringLen(*pbstrOut) ? S_OK : S_FALSE)
- : E_OUTOFMEMORY;
- }
- return TCLoadBSTR(_Module.GetResourceInstance(), dw, pbstrOut);
- }
- HRESULT CAGCEventDef::ExpandFmtString(BSTR bstrFmt, IAGCEvent* pEvent,
- BSTR* pbstrOut)
- {
- assert(BSTRLen(bstrFmt));
- assert(pbstrOut);
- // Create a growable stream into which we'll write
- IStreamPtr spStm;
- RETURN_FAILED(CreateStreamOnHGlobal(NULL, true, &spStm));
- // Initialize the parsing data
- XParseData data =
- {pEvent, spStm, NULL, NULL, NULL, bstrFmt, NULL, false};
- // Iterate through the characters of the format string
- XStateProc pfnState = ParseState_Base;
- for (UINT cch = SysStringLen(bstrFmt); cch && pfnState; --cch)
- {
- RETURN_FAILED(pfnState(data));
- pfnState = data.m_pfnNextState;
- ++data.m_pszInput;
- }
- data.m_bEndOfString = true;
- while (pfnState)
- {
- RETURN_FAILED(pfnState(data));
- pfnState = data.m_pfnNextState;
- }
- // Get the current seek pointer of the stream (which is it's size)
- LARGE_INTEGER li = {0};
- ULARGE_INTEGER uli;
- RETURN_FAILED(spStm->Seek(li, STREAM_SEEK_CUR, &uli));
- UINT cchStream = uli.QuadPart / sizeof(OLECHAR);
- // Get the HGLOBAL underlying the stream
- HGLOBAL hGlobal = NULL;
- RETURN_FAILED(GetHGlobalFromStream(spStm, &hGlobal));
- assert(hGlobal);
- // Lock the HGLOBAL
- LPCOLESTR pszOut = reinterpret_cast<LPCOLESTR>(GlobalLock(hGlobal));
- assert(pszOut);
- // Create a BSTR from the byte stream
- *pbstrOut = SysAllocStringLen(pszOut, cchStream);
- // Unlock the HGLOBAL
- GlobalUnlock(hGlobal);
- // Indicate success or failure
- return *pbstrOut ? S_OK : E_OUTOFMEMORY;
- }
- HRESULT CAGCEventDef::ExpandParams(BSTR bstrFmt, IAGCEvent* pEvent,
- CAGCEventDef::XParamStrings& rParams)
- {
- assert(BSTRLen(bstrFmt));
- // Initialize the parsing data
- XParseData data =
- {pEvent, NULL, &rParams, NULL, NULL, bstrFmt, NULL, false};
- // Iterate through the characters of the format string
- XStateProc pfnState = ParseState_Base;
- for (UINT cch = SysStringLen(bstrFmt); cch && pfnState; --cch)
- {
- RETURN_FAILED(pfnState(data));
- pfnState = data.m_pfnNextState;
- ++data.m_pszInput;
- }
- data.m_bEndOfString = true;
- while (pfnState)
- {
- RETURN_FAILED(pfnState(data));
- pfnState = data.m_pfnNextState;
- }
- // Indicate success
- return S_OK;
- }
- HRESULT __fastcall
- CAGCEventDef::ParseState_WriteInput(CAGCEventDef::XParseData& data)
- {
- HRESULT hr = S_OK;
- if (data.m_pStm)
- hr = data.m_pStm->Write(data.m_pszInput, sizeof(*data.m_pszInput), NULL);
- data.m_pfnNextState = SUCCEEDED(hr) ? ParseState_Base : NULL;
- return hr;
- }
- HRESULT __fastcall
- CAGCEventDef::ParseState_WriteVar(CAGCEventDef::XParseData& data)
- {
- UINT cch = data.m_pszVarEnd - data.m_pszVarBegin;
- UINT cb = cch * sizeof(*data.m_pszVarEnd);
- HRESULT hr = S_OK;
- if (data.m_pStm)
- hr = data.m_pStm->Write(data.m_pszVarBegin, cb, NULL);
- data.m_pfnNextState = SUCCEEDED(hr) ? ParseState_Base : NULL;
- return hr;
- }
- HRESULT __fastcall
- CAGCEventDef::ParseState_End(CAGCEventDef::XParseData& data)
- {
- assert(data.m_bEndOfString);
- data.m_pfnNextState = NULL;
- return S_OK;
- }
- HRESULT __fastcall
- CAGCEventDef::ParseState_Base(CAGCEventDef::XParseData& data)
- {
- if (data.m_bEndOfString)
- return ParseState_End(data);
- if (OLESTR('%') != *data.m_pszInput)
- return ParseState_WriteInput(data);
- data.m_pszVarBegin = data.m_pszInput + 1;
- data.m_pfnNextState = ParseState_InVar;
- return S_OK;
- }
- HRESULT __fastcall
- CAGCEventDef::ParseState_InVar(CAGCEventDef::XParseData& data)
- {
- if (data.m_bEndOfString)
- {
- --data.m_pszVarBegin;
- data.m_pszVarEnd = data.m_pszInput;
- RETURN_FAILED(ParseState_WriteVar(data));
- return ParseState_End(data);
- }
- if (OLESTR('%') == *data.m_pszInput)
- {
- if (data.m_pszInput == data.m_pszVarBegin)
- return ParseState_WriteInput(data);
- data.m_pszVarEnd = data.m_pszInput;
- return ParseState_ProcessVar(data);
- }
- return S_OK;
- }
- HRESULT __fastcall
- CAGCEventDef::ParseState_ProcessVar(CAGCEventDef::XParseData& data)
- {
- // Get the variable as a VT_BSTR variant
- UINT cch = data.m_pszVarEnd - data.m_pszVarBegin;
- CComVariant varKey;
- V_VT(&varKey) = VT_BSTR;
- V_BSTR(&varKey) = ::SysAllocStringLen(data.m_pszVarBegin, cch);
- if (!V_BSTR(&varKey))
- {
- data.m_pfnNextState = NULL;
- return E_OUTOFMEMORY;
- }
- // Lookup the variable in the event's properties
- CComVariant varValue;
- HRESULT hr = data.m_pEvent->get_Property(&varKey, &varValue);
- if (FAILED(hr))
- {
- data.m_pfnNextState = NULL;
- return hr;
- }
- // Just write the variable name as-is if it doesn't exist in the event
- if (VT_EMPTY == V_VT(&varValue))
- {
- // Include the leading and trailing '%' characters
- --data.m_pszVarBegin;
- ++data.m_pszVarEnd;
- if (data.m_pParams)
- {
- cch = data.m_pszVarEnd - data.m_pszVarBegin;
- BSTR bstrValue = SysAllocStringLen(data.m_pszVarBegin, cch);
- if (!bstrValue)
- {
- data.m_pfnNextState = NULL;
- return E_OUTOFMEMORY;
- }
- data.m_pParams->push_back(bstrValue);
- }
- return ParseState_WriteVar(data);
- }
- // Convert the variant to a string
- if (VT_BSTR != V_VT(&varValue))
- {
- VariantChangeTypeEx(&varValue, &varValue, GetThreadLocale(),
- VARIANT_LOCALBOOL | VARIANT_ALPHABOOL, VT_BSTR);
- if (VT_BSTR != V_VT(&varValue))
- {
- data.m_pfnNextState = ParseState_Base;
- return S_OK;
- }
- }
- UINT cchValue = BSTRLen(V_BSTR(&varValue));
- if (!cchValue)
- {
- if (data.m_pParams)
- {
- BSTR bstrValue = SysAllocString(L"");
- if (!bstrValue)
- {
- data.m_pfnNextState = NULL;
- return E_OUTOFMEMORY;
- }
- data.m_pParams->push_back(bstrValue);
- }
- data.m_pfnNextState = ParseState_Base;
- return S_OK;
- }
- // Write the value string
- data.m_pszVarBegin = V_BSTR(&varValue);
- data.m_pszVarEnd = data.m_pszVarBegin + cchValue;
- RETURN_FAILED(ParseState_WriteVar(data));
- if (data.m_pParams)
- {
- data.m_pParams->push_back(V_BSTR(&varValue));
- V_VT(&varValue) = VT_EMPTY; // Detaches the BSTR from the VARIANT
- }
- // Indicate success
- return S_OK;
- }
|