#include "pch.h"
#include <..\TCLib\AutoHandle.h>
#include <..\TCLib\UtilImpl.h>
#include <..\TCLib\WinApp.h>
#include <..\TCAtl\SimpleStream.h>
#include "AGCEventLogger.h"
#include "AGCEventDef.h"
TC_OBJECT_EXTERN_IMPL(CAGCEventLogger)
CAGCEventLogger::CAGCEventLogger() :
m_bInitializing(true),
m_bstrID(L"id"),
m_bstrLogAsNTEvent(L"LogAsNTEvent"),
m_bstrLogAsDBEvent(L"LogAsDBEvent"),
m_bLoggingToNTEnabled(true),
m_bLoggingToDBEnabled(true)
{
TCZeroMemory(&m_idTable);
}
IUnknown* CAGCEventLogger::OnGetUnknown()
{
return GetUnknown();
}
TC_WorkItemRelProc CAGCEventLogger::OnGetWorkItemRelProc()
{
return ReleaseWorkItem;
}
void CAGCEventLogger::OnMessage(UINT idMsg, int cParams, LPARAM* rgParams)
{
switch (idMsg)
{
case e_LogEvent:
{
PRIVATE_ASSERTE(2 <= cParams);
IAGCEvent* pEvent = reinterpret_cast<IAGCEvent*>(rgParams[0]);
HANDLE hevt = reinterpret_cast<HANDLE >(rgParams[1]);
LogEvent(pEvent, !!hevt);
break;
};
case e_CloseNTEventLog:
{
PRIVATE_ASSERTE(2 <= cParams);
HANDLE hevt = reinterpret_cast<HANDLE >(rgParams[0]);
HRESULT* phr = reinterpret_cast<HRESULT*>(rgParams[1]);
*phr = CloseNTEventLog();
break;
}
case e_ChangeNTEventLog:
{
PRIVATE_ASSERTE(3 <= cParams);
BSTR bstr = reinterpret_cast<BSTR >(rgParams[0]);
HANDLE hevt = reinterpret_cast<HANDLE >(rgParams[1]);
HRESULT* phr = reinterpret_cast<HRESULT*>(rgParams[2]);
*phr = ChangeNTEventLog(bstr);
break;
}
case e_CloseDatabase:
{
PRIVATE_ASSERTE(2 <= cParams);
HANDLE hevt = reinterpret_cast<HANDLE >(rgParams[0]);
HRESULT* phr = reinterpret_cast<HRESULT*>(rgParams[1]);
*phr = CloseDatabase();
break;
}
case e_ChangeDatabase:
{
PRIVATE_ASSERTE(5 <= cParams);
IDBInitialize* pInit = reinterpret_cast<IDBInitialize*>(rgParams[0]);
DBID* pidTable = reinterpret_cast<DBID* >(rgParams[1]);
CDBPropSet* pPropSet = reinterpret_cast<CDBPropSet* >(rgParams[2]);
HANDLE hevt = reinterpret_cast<HANDLE >(rgParams[3]);
HRESULT* phr = reinterpret_cast<HRESULT* >(rgParams[4]);
*phr = ChangeDatabase(pInit, pidTable, pPropSet);
break;
}
}
}
void WINAPI CAGCEventLogger::ReleaseWorkItem(UINT idMsg, int cParams, LPARAM* rgParams)
{
switch (idMsg)
{
case e_LogEvent:
{
PRIVATE_ASSERTE(2 <= cParams);
IAGCEvent* pEvent = reinterpret_cast<IAGCEvent*>(rgParams[0]);
HANDLE hevt = reinterpret_cast<HANDLE >(rgParams[1]);
pEvent->Release();
if (hevt)
::SetEvent(hevt);
break;
};
case e_CloseNTEventLog:
{
PRIVATE_ASSERTE(2 <= cParams);
HANDLE hevt = reinterpret_cast<HANDLE >(rgParams[0]);
HRESULT* phr = reinterpret_cast<HRESULT*>(rgParams[1]);
SetEvent(hevt);
break;
}
case e_ChangeNTEventLog:
{
PRIVATE_ASSERTE(3 <= cParams);
BSTR bstr = reinterpret_cast<BSTR >(rgParams[0]);
HANDLE hevt = reinterpret_cast<HANDLE >(rgParams[1]);
HRESULT* phr = reinterpret_cast<HRESULT*>(rgParams[2]);
SetEvent(hevt);
break;
}
case e_CloseDatabase:
{
PRIVATE_ASSERTE(2 <= cParams);
HANDLE hevt = reinterpret_cast<HANDLE >(rgParams[0]);
HRESULT* phr = reinterpret_cast<HRESULT*>(rgParams[1]);
SetEvent(hevt);
break;
}
case e_ChangeDatabase:
{
PRIVATE_ASSERTE(5 <= cParams);
IDBInitialize* pInit = reinterpret_cast<IDBInitialize*>(rgParams[0]);
DBID* pidTable = reinterpret_cast<DBID* >(rgParams[1]);
CDBPropSet* pPropSet = reinterpret_cast<CDBPropSet* >(rgParams[2]);
HANDLE hevt = reinterpret_cast<HANDLE >(rgParams[3]);
HRESULT* phr = reinterpret_cast<HRESULT* >(rgParams[4]);
pInit->Release();
SetEvent(hevt);
break;
}
}
}
void DisplayOLEDBErrorRecords(HRESULT hrErr = S_OK)
{
CDBErrorInfo ErrorInfo;
ULONG cRecords;
HRESULT hr;
ULONG i;
CComBSTR bstrDesc, bstrHelpFile, bstrSource;
GUID guid;
DWORD dwHelpContext;
WCHAR wszGuid[40];
USES_CONVERSION;
TCERRLOG_BEGIN_SIZE(_MAX_PATH * 8);
if (hrErr != S_OK)
{
TCERRLOG_PART1("OLE DB Error Record dump for hr = 0x%x\n", hrErr);
}
LCID lcLocale = GetSystemDefaultLCID();
hr = ErrorInfo.GetErrorRecords(&cRecords);
if (FAILED(hr) && ErrorInfo.m_spErrorInfo == NULL)
{
TCERRLOG_PART1("No OLE DB Error Information found: hr = 0x%x\n", hr);
}
else
{
for (i = 0; i < cRecords; i++)
{
hr = ErrorInfo.GetAllErrorInfo(i, lcLocale, &bstrDesc, &bstrSource, &guid,
&dwHelpContext, &bstrHelpFile);
if (FAILED(hr))
{
TCERRLOG_PART1("OLE DB Error Record dump retrieval failed: hr = 0x%x\n", hr );
return;
}
StringFromGUID2(guid, wszGuid, sizeof(wszGuid) / sizeof(WCHAR));
TCERRLOG_PART5(
"Source:\"%ls\"\nDescription:\"%ls\"\nHelp File:\"%ls\"\nHelp Context:%4d\nGUID:%ls\n",
bstrSource, bstrDesc, bstrHelpFile, dwHelpContext, wszGuid);
bstrSource.Empty();
bstrDesc.Empty();
bstrHelpFile.Empty();
}
}
TCERRLOG_END
}
void CAGCEventLogger::LogEvent(IAGCEvent* pEvent, bool bSynchronous)
{
PRIVATE_ASSERTE(pEvent);
XLock lock(this);
bool bLogToNT = m_bLoggingToNTEnabled && !m_shEventLog.IsNull();
bool bLogToDB = m_bLoggingToDBEnabled && m_ds.m_spInit != NULL;
AGCEventID idEvent;
PRIVATE_VERIFYE(SUCCEEDED(pEvent->get_ID(&idEvent)));
VARIANT_BOOL bEnabled;
if (bLogToNT && NULL != m_spRangesNT
&& SUCCEEDED(m_spRangesNT->get_IntersectsWithValue(idEvent, &bEnabled)))
bLogToNT = !!bEnabled;
if (bLogToDB && NULL != m_spRangesDB
&& SUCCEEDED(m_spRangesDB->get_IntersectsWithValue(idEvent, &bEnabled)))
bLogToDB = !!bEnabled;
lock.Unlock();
if (!bLogToNT && !bLogToDB)
return;
const CAGCEventDef::XEventDef* pEventDef = CAGCEventDef::find(idEvent);
PRIVATE_ASSERTE(pEventDef);
#if 0 && defined(_DEBUG)
{
CComBSTR bstrDescription, bstrSubjectName;
PRIVATE_VERIFYE(SUCCEEDED(pEvent->get_Description(&bstrDescription)));
PRIVATE_VERIFYE(SUCCEEDED(pEvent->get_SubjectName (&bstrSubjectName)));
int cchDbg = bstrSubjectName.Length() + bstrDescription.Length() + 16;
_TRACE_BEGIN_SIZE(cchDbg)
if (bstrSubjectName.Length())
_TRACE_PART1("%ls:\n", (BSTR)bstrSubjectName);
if (bstrDescription.Length())
_TRACE_PART1("%ls\n" , (BSTR)bstrDescription);
_TRACE_END
}
#endif if (bLogToNT)
{
PRIVATE_ASSERTE(IsWinNT());
IAGCEventLoggerHookPtr spHook;
get_HookForNTLogging(&spHook);
if (NULL == spHook || S_FALSE == spHook->LogEvent(pEvent, VARBOOL(bSynchronous)))
{
XLock lockNT(this);
if (m_bLoggingToNTEnabled && !m_shEventLog.IsNull())
{
WORD wSeverity = pEventDef->m_wSeverity;
UINT nBits;
switch (wSeverity)
{
case EVENTLOG_INFORMATION_TYPE: nBits = 0x01 << 30; break;
case EVENTLOG_WARNING_TYPE : nBits = 0x02 << 30; break;
case EVENTLOG_ERROR_TYPE : nBits = 0x03 << 30; break;
case EVENTLOG_SUCCESS : nBits = 0x00 << 30; break;
default : PRIVATE_ASSERTE(!"Bad severity code.");
}
DWORD dwEventID = nBits | idEvent;
CAGCEventDef::XParamStrings vecParamStrings;
PRIVATE_VERIFYE(SUCCEEDED(CAGCEventDef::GetEventParameters(pEvent,
vecParamStrings, pEventDef)));
WORD NumStrings = vecParamStrings.size();
LPCWSTR* lpStrings = NULL;
if(NumStrings)
lpStrings = (LPCWSTR*)(&(*vecParamStrings.begin()));
ReportEventW(m_shEventLog, wSeverity, 0, dwEventID, NULL,
vecParamStrings.size(), 0,
#if _MSC_VER >= 1310
lpStrings, NULL);
#else
(LPCWSTR*)(vecParamStrings.begin()), NULL);
#endif
for (CAGCEventDef::XParamStrings::iterator it = vecParamStrings.begin();
it != vecParamStrings.end(); ++it)
SysFreeString(*it);
}
}
}
if (bLogToDB)
{
IAGCEventLoggerHookPtr spHook;
get_HookForDBLogging(&spHook);
if (NULL == spHook || S_FALSE == spHook->LogEvent(pEvent, VARBOOL(bSynchronous)))
{
XLock lockDB(this);
if (m_bLoggingToDBEnabled && m_ds.m_spInit != NULL)
{
long idSubject;
CComBSTR bstrComputerName, bstrSubjectName, bstrContext;
PRIVATE_VERIFYE(SUCCEEDED(pEvent->get_SubjectID (&idSubject )));
PRIVATE_VERIFYE(SUCCEEDED(pEvent->get_ComputerName(&bstrComputerName)));
PRIVATE_VERIFYE(SUCCEEDED(pEvent->get_SubjectName (&bstrSubjectName )));
PRIVATE_VERIFYE(SUCCEEDED(pEvent->get_Context (&bstrContext )));
HRESULT hr;
if (SUCCEEDED(hr = m_session.Open(m_ds)))
{
if (SUCCEEDED(hr = m_table.Open(m_session, m_idTable, &m_propset)))
{
USES_CONVERSION;
m_table.m_idEvent = idEvent;
m_table.m_idSubject = idSubject;
if (bstrComputerName.Length())
lstrcpyn(m_table.m_szComputerName, OLE2CT(bstrComputerName),
sizeofArray(m_table.m_szComputerName));
else
*m_table.m_szComputerName = TEXT('\0');
if (bstrSubjectName.Length())
lstrcpyn(m_table.m_szSubjectName, OLE2CT(bstrSubjectName),
sizeofArray(m_table.m_szSubjectName));
else
*m_table.m_szSubjectName = TEXT('\0');
if (bstrContext.Length())
lstrcpyn(m_table.m_szContext, OLE2CT(bstrContext),
sizeofArray(m_table.m_szContext));
else
*m_table.m_szContext = TEXT('\0');
PRIVATE_ASSERTE(IPersistStreamInitPtr(pEvent) != NULL || IPersistStreamPtr(pEvent) != NULL);
PRIVATE_ASSERTE(IMarshalPtr(pEvent) != NULL);
CComBSTR bstrTemp;
PRIVATE_VERIFYE(SUCCEEDED(pEvent->SaveToString(&bstrTemp)));
WideCharToMultiByte(CP_ACP, 0, bstrTemp, -1,
m_table.m_szObjRef, sizeof(m_table.m_szObjRef), 0, 0);
hr = m_table.Insert();
}
}
if (FAILED(hr))
DisplayOLEDBErrorRecords(hr);
m_table.Close();
m_session.Close();
}
}
}
}
HRESULT CAGCEventLogger::CloseDatabase()
{
XLock lock(this);
m_table.Close();
m_session.Close();
m_ds.Close();
return S_OK;
}
HRESULT CAGCEventLogger::ChangeDatabase(IDBInitialize* pInit,
DBID* pidTable, CDBPropSet* pPropSet)
{
XLock lock(this);
CloseDatabase();
m_ds.m_spInit = pInit;
m_bstrTableName = pidTable->uName.pwszName;
m_idTable.eKind = DBKIND_NAME;
m_idTable.uName.pwszName = m_bstrTableName;
m_propset = *pPropSet;
m_session.Open(m_ds);
HRESULT hr = m_table.Open(m_session, m_idTable, &m_propset);
if (FAILED(hr))
m_bstrTableName.Empty();
m_table.Close();
m_session.Close();
return hr;
}
HRESULT CAGCEventLogger::CloseNTEventLog()
{
XLock lock(this);
m_shEventLog = NULL;
return S_OK;
}
HRESULT CAGCEventLogger::ChangeNTEventLog(BSTR bstrComputer)
{
XLock lock(this);
CloseNTEventLog();
BSTR bstr = BSTRLen(bstrComputer) ? bstrComputer : NULL;
m_shEventLog = RegisterEventSourceW(bstr, m_bstrSourceApp);
return !m_shEventLog.IsNull() ? S_OK : HRESULT_FROM_WIN32(GetLastError());
}
HKEY CAGCEventLogger::RootKeyFromString(BSTR bstrRegKey, DWORD* cchEaten)
{
struct XRootKeys
{
LPCOLESTR pszName;
DWORD cchName;
HKEY hkey;
};
const static XRootKeys s_table[] =
{
{L"HKCR\\" , 5, HKEY_CLASSES_ROOT },
{L"HKCU\\" , 5, HKEY_CURRENT_USER },
{L"HKLM\\" , 5, HKEY_LOCAL_MACHINE },
{L"HKCC\\" , 5, HKEY_CURRENT_CONFIG },
{L"HKPD\\" , 5, HKEY_PERFORMANCE_DATA},
{L"HKDD\\" , 5, HKEY_DYN_DATA },
{L"HKEY_CLASSES_ROOT\\" , 18, HKEY_CLASSES_ROOT },
{L"HKEY_CURRENT_USER\\" , 18, HKEY_CURRENT_USER },
{L"HKEY_LOCAL_MACHINE\\" , 19, HKEY_LOCAL_MACHINE },
{L"HKEY_CURRENT_CONFIG\\" , 20, HKEY_CURRENT_CONFIG },
{L"HKEY_PERFORMANCE_DATA\\", 22, HKEY_PERFORMANCE_DATA},
{L"HKEY_DYN_DATA\\" , 14, HKEY_DYN_DATA },
};
const static long s_cEntries = sizeofArray(s_table);
if (BSTRLen(bstrRegKey))
{
for (long i = 0; i < s_cEntries; ++i)
{
if (!_wcsnicmp(s_table[i].pszName, bstrRegKey, s_table[i].cchName))
{
*cchEaten = s_table[i].cchName;
return s_table[i].hkey;
}
}
}
*cchEaten = 0;
return NULL;
}
HRESULT CAGCEventLogger::ReadStringValueFromRegistry(LPCTSTR pszValueName,
CComBSTR& bstrOut)
{
bstrOut.Empty();
DWORD cbData = 0;
long lr = RegQueryValueEx(m_key, pszValueName, NULL, NULL, NULL, &cbData);
if (ERROR_SUCCESS != lr)
return HRESULT_FROM_WIN32(lr);
if (!cbData)
return S_OK;
LPTSTR pszValue = (LPTSTR)_alloca(cbData);
lr = m_key.QueryValue(pszValue, pszValueName, &cbData);
bstrOut = pszValue;
return S_OK;
}
HRESULT CAGCEventLogger::OpenWriteableRegKey(CRegKey& keyWrite)
{
keyWrite.Close();
XLock lock(this);
if (m_bInitializing)
return S_FALSE;
if (!m_key.m_hKey)
return E_UNEXPECTED;
long lr = keyWrite.Create(m_key, TEXT(""));
return (ERROR_SUCCESS == lr) ? S_OK : HRESULT_FROM_WIN32(lr);
}
void CAGCEventLogger::FireNTEventLogStopped()
{
bool bLogIsOpen;
{
XLock lock(this);
bLogIsOpen = !m_shEventLog.IsNull();
}
if (bLogIsOpen)
{
GetAGCGlobal()->TriggerEventSynchronous(NULL, EventID_NTEventLogStopped,
NULL, NULL, -1, -1, -1, 0, NULL);
}
}
void CAGCEventLogger::FireDBEventLogStopped()
{
bool bLogIsOpen;
{
XLock lock(this);
bLogIsOpen = m_ds.m_spInit != NULL;
}
if (bLogIsOpen)
{
GetAGCGlobal()->TriggerEventSynchronous(NULL, EventID_DBEventLogStopped,
NULL, NULL, -1, -1, -1, 0, NULL);
}
}
HRESULT CAGCEventLogger::CopyChildNodes(IXMLDOMNode* pNode,
CAGCEventLogger::XNodes& nodes)
{
IXMLDOMNodeListPtr spChildren;
RETURN_FAILED(pNode->get_childNodes(&spChildren));
long cChildren;
RETURN_FAILED(spChildren->get_length(&cChildren));
nodes.resize(cChildren);
for (long nIndex = 0; nIndex < cChildren; ++nIndex)
{
IXMLDOMNodePtr spChild;
RETURN_FAILED(spChildren->nextNode(&spChild))
assert(NULL != spChild);
nodes[nIndex] = spChild;
}
return S_OK;
}
HRESULT CAGCEventLogger::RemoveStyleSheetPIs(IXMLDOMNode* pNode)
{
XNodes nodes;
RETURN_FAILED(CopyChildNodes(pNode, nodes));
for (XNodeIt it = nodes.begin(); it != nodes.end(); ++it)
{
DOMNodeType type;
RETURN_FAILED((*it)->get_nodeType(&type));
if (NODE_PROCESSING_INSTRUCTION == type)
{
CComBSTR bstrName;
RETURN_FAILED((*it)->get_nodeName(&bstrName));
if (0 == wcscmp(bstrName, L"xml-stylesheet"))
{
IXMLDOMNodePtr spNodeRemoved;
RETURN_FAILED(pNode->removeChild(*it, &spNodeRemoved));
}
}
}
return S_OK;
}
HRESULT CAGCEventLogger::ProcessXMLNode(IXMLDOMNode* pNode,
IXMLDOMNode* pNodeParent)
{
XNodes nodes;
RETURN_FAILED(CopyChildNodes(pNode, nodes));
IAGCEventIDRangesPtr spRangesHost;
GetAGCGlobal()->GetAvailableEventIDRanges(&spRangesHost);
for (XNodeIt it = nodes.begin(); it != nodes.end(); ++it)
{
IXMLDOMElementPtr spElement(*it);
if (spElement == NULL)
{
IXMLDOMCommentPtr spComment(*it);
if (spComment != NULL)
{
IXMLDOMNodePtr spNodeRemoved;
RETURN_FAILED(pNode->removeChild(spComment, &spNodeRemoved));
}
continue;
}
CComBSTR bstrTag;
RETURN_FAILED(spElement->get_tagName(&bstrTag));
if (0 == wcscmp(bstrTag, L"Event"))
{
CComVariant varValue;
RETURN_FAILED(spElement->getAttribute(m_bstrID, &varValue));
RETURN_FAILED(varValue.ChangeType(VT_I4));
AGCEventID idEvent = static_cast<AGCEventID>(V_I4(&varValue));
VARIANT_BOOL bInRange;
ZSucceeded(spRangesHost->get_IntersectsWithValue(idEvent, &bInRange));
if (!bInRange)
{
IXMLDOMNodePtr spNodeRemoved;
RETURN_FAILED(pNode->removeChild(spElement, &spNodeRemoved));
}
else
{
ZSucceeded(m_spRangesNT->get_IntersectsWithValue(idEvent, &bInRange));
varValue = !!bInRange;
RETURN_FAILED(spElement->setAttribute(m_bstrLogAsNTEvent, varValue));
ZSucceeded(m_spRangesDB->get_IntersectsWithValue(idEvent, &bInRange));
varValue = !!bInRange;
RETURN_FAILED(spElement->setAttribute(m_bstrLogAsDBEvent, varValue));
}
}
else if (0 == wcscmp(bstrTag, L"EventGroup"))
{
RETURN_FAILED(ProcessXMLNode(*it, pNode));
}
}
if (pNodeParent)
{
IXMLDOMNodeListPtr spChildren;
RETURN_FAILED(pNode->get_childNodes(&spChildren));
long cChildren;
RETURN_FAILED(spChildren->get_length(&cChildren));
if (!cChildren)
{
IXMLDOMNodePtr spNodeRemoved;
RETURN_FAILED(pNodeParent->removeChild(pNode, &spNodeRemoved));
}
}
return S_OK;
}
STDMETHODIMP CAGCEventLogger::OnEventTriggered(IAGCEvent* pEvent)
{
pEvent->AddRef();
PostMessage(e_LogEvent, 2, pEvent, NULL);
return S_OK;
}
STDMETHODIMP CAGCEventLogger::OnEventTriggeredSynchronous(IAGCEvent* pEvent)
{
TCHandle shEvent = ::CreateEvent(NULL, false, false, NULL);
pEvent->AddRef();
PostMessage(e_LogEvent, 2, pEvent, shEvent.GetHandle());
WaitForSingleObject(shEvent, INFINITE);
return S_OK;
}
STDMETHODIMP CAGCEventLogger::get_EventList(BSTR* pbstrEventListXML)
{
IXMLDOMDocumentPtr spXMLDoc;
RETURN_FAILED(spXMLDoc.CreateInstance(L"Microsoft.FreeThreadedXMLDOM"));
void* pXMLData = NULL;
DWORD cbXMLData = 0;
RETURN_FAILED(LockAndLoadResource(GetAGCGlobal()->GetResourceInstance(),
TEXT("AGCEventsXML"), MAKEINTRESOURCE(1), &pXMLData, &cbXMLData));
TCSimpleStream stm;
stm.Init(cbXMLData, pXMLData);
CComVariant varXML((IStream*)&stm);
VARIANT_BOOL bLoaded;
ZSucceeded(spXMLDoc->load(varXML, &bLoaded));
ZSucceeded(RemoveStyleSheetPIs(spXMLDoc));
IXMLDOMElementPtr spRoot;
ZSucceeded(spXMLDoc->get_documentElement(&spRoot));
#ifdef _DEBUG
{
CComBSTR bstrRoot;
ZSucceeded(spRoot->get_tagName(&bstrRoot));
assert(0 == wcscmp(bstrRoot, L"AGCEvents"));
}
#endif RETURN_FAILED(ProcessXMLNode(spRoot, NULL));
return spXMLDoc->get_xml(pbstrEventListXML);
}
STDMETHODIMP CAGCEventLogger::put_NTEventLog(BSTR bstrComputer)
{
if (!IsWinNT())
return Error(IDS_E_NTEVENTLOG_WIN9X, IID_IAGCEventLogger);
CRegKey keyWrite;
RETURN_FAILED(OpenWriteableRegKey(keyWrite));
FireNTEventLogStopped();
if (keyWrite.m_hKey)
{
USES_CONVERSION;
long lr = keyWrite.SetValue(OLE2CT(bstrComputer), TEXT("NTEventLog"));
assert(ERROR_SUCCESS == lr);
}
TCHandle hevt = CreateEvent(NULL, false, false, NULL);
assert(!hevt.IsNull());
HRESULT hr = S_OK;
PostMessage(e_ChangeNTEventLog, 3, bstrComputer, hevt, &hr);
WaitForSingleObject(hevt, INFINITE);
RETURN_FAILED(hr);
{
XLock lock(this);
m_bstrNTEventLog = bstrComputer;
}
IAGCVersionInfoPtr spVersionInfo;
ZSucceeded(spVersionInfo.CreateInstance("AGC.AGCVersionInfo"));
WORD wProductBuildNumber;
CComBSTR bstrProductVersion;
ZSucceeded(spVersionInfo->get_ProductBuildNumber(&wProductBuildNumber));
ZSucceeded(spVersionInfo->get_ProductVersionString(&bstrProductVersion));
_AGCModule.TriggerEvent(NULL, EventID_NTEventLogStarted,
bstrProductVersion, wProductBuildNumber, -1, -1, 0);
return S_OK;
}
STDMETHODIMP CAGCEventLogger::get_NTEventLog(BSTR* pbstrComputer)
{
CComBSTR bstr(m_bstrNTEventLog);
CLEAROUT(pbstrComputer, (BSTR)bstr);
bstr.Detach();
return S_OK;
}
STDMETHODIMP CAGCEventLogger::put_DBEventLog(IAGCDBParams* pDBParams)
{
USES_CONVERSION;
CRegKey keyWrite;
RETURN_FAILED(OpenWriteableRegKey(keyWrite));
CComBSTR bstrConnectionString;
CComBSTR bstrTableName;
if (pDBParams)
{
RETURN_FAILED(pDBParams->get_ConnectionString(&bstrConnectionString));
RETURN_FAILED(pDBParams->get_TableName(&bstrTableName));
}
CDataSource ds;
CSession session;
DBID idTable;
CDBPropSet propset(DBPROPSET_ROWSET);
if (bstrConnectionString.Length() && bstrTableName.Length())
{
RETURN_FAILED(ds.OpenFromInitializationString(bstrConnectionString));
RETURN_FAILED(session.Open(ds));
idTable.eKind = DBKIND_NAME;
idTable.uName.pwszName = bstrTableName;
propset.AddProperty(DBPROP_IRowsetChange, true);
propset.AddProperty(DBPROP_UPDATABILITY, DBPROPVAL_UP_INSERT);
CTable<CAccessor<XEvent> > table;
RETURN_FAILED(table.Open(session, idTable, &propset));
table.Close();
session.Close();
}
FireDBEventLogStopped();
if (keyWrite.m_hKey)
{
USES_CONVERSION;
long lr = keyWrite.SetValue(OLE2CT(bstrConnectionString), TEXT("ConnectionString"));
assert(ERROR_SUCCESS == lr);
lr = keyWrite.SetValue(OLE2CT(bstrTableName), TEXT("TableName"));
assert(ERROR_SUCCESS == lr);
}
TCHandle hevt = CreateEvent(NULL, false, false, NULL);
assert(!hevt.IsNull());
HRESULT hr = S_OK;
if (bstrConnectionString.Length() && bstrTableName.Length())
PostMessage(e_ChangeDatabase, 5, ds.m_spInit.Detach(),
&idTable, &propset, hevt, &hr);
else
PostMessage(e_CloseDatabase, 2, hevt, &hr);
WaitForSingleObject(hevt, INFINITE);
RETURN_FAILED(hr);
{
XLock lock(this);
m_bstrTableName = bstrTableName;
}
if (!bstrConnectionString.Length() || !bstrTableName.Length())
return S_OK;
IAGCVersionInfoPtr spVersionInfo;
ZSucceeded(spVersionInfo.CreateInstance("AGC.AGCVersionInfo"));
WORD wProductBuildNumber;
CComBSTR bstrProductVersion;
ZSucceeded(spVersionInfo->get_ProductBuildNumber(&wProductBuildNumber));
ZSucceeded(spVersionInfo->get_ProductVersionString(&bstrProductVersion));
_AGCModule.TriggerEvent(NULL, EventID_DBEventLogStarted,
bstrProductVersion, wProductBuildNumber, -1, -1, 0);
return S_OK;
}
STDMETHODIMP CAGCEventLogger::get_DBEventLog(IAGCDBParams** ppDBParams)
{
IAGCDBParamsPtr spParams;
RETURN_FAILED(spParams.CreateInstance("AGC.DBParams"));
CComBSTR bstrConnectionString;
XLock lock(this);
if (m_ds.m_spInit != NULL)
RETURN_FAILED(m_ds.GetInitializationString(&bstrConnectionString, true))
lock.Unlock();
RETURN_FAILED(spParams->put_ConnectionString(bstrConnectionString));
RETURN_FAILED(spParams->put_TableName(m_bstrTableName));
CLEAROUT(ppDBParams, (IAGCDBParams*)spParams);
spParams.Detach();
return S_OK;
}
STDMETHODIMP CAGCEventLogger::put_EnabledNTEvents(IAGCEventIDRanges* pEvents)
{
if (!IsWinNT())
return Error(IDS_E_NTEVENTLOG_WIN9X, IID_IAGCEventLogger);
XLock lock(this);
CRegKey keyWrite;
RETURN_FAILED(OpenWriteableRegKey(keyWrite));
if (NULL != m_spRangesNT)
GetAGCGlobal()->RevokeEventRanges(m_spRangesNT, AGC_Any_Objects,
static_cast<IAGCEventSink*>(this));
IAGCEventIDRangesPtr spRanges;
if (!pEvents)
{
RETURN_FAILED(get_EnabledNTEvents(&spRanges));
pEvents = spRanges;
}
m_spRangesNT = pEvents;
CComBSTR bstrEventRanges;
if (NULL != m_spRangesNT)
{
GetAGCGlobal()->RegisterEventRanges(m_spRangesNT, AGC_Any_Objects,
static_cast<IAGCEventSink*>(this));
ZSucceeded(m_spRangesNT->get_DisplayString(&bstrEventRanges));
}
if (keyWrite.m_hKey)
{
USES_CONVERSION;
LPCTSTR pszValue = bstrEventRanges ? OLE2CT(bstrEventRanges) : TEXT("");
long lr = keyWrite.SetValue(pszValue, TEXT("EnabledNTEvents"));
assert(ERROR_SUCCESS == lr);
}
return S_OK;
}
STDMETHODIMP CAGCEventLogger::get_EnabledNTEvents(IAGCEventIDRanges** ppEvents)
{
XLock lock(this);
CLEAROUT(ppEvents, (IAGCEventIDRanges*)m_spRangesNT);
(*ppEvents)->AddRef();
return S_OK;
}
STDMETHODIMP CAGCEventLogger::put_EnabledDBEvents(IAGCEventIDRanges* pEvents)
{
XLock lock(this);
CRegKey keyWrite;
RETURN_FAILED(OpenWriteableRegKey(keyWrite));
if (NULL != m_spRangesDB)
GetAGCGlobal()->RevokeEventRanges(m_spRangesDB, AGC_Any_Objects,
static_cast<IAGCEventSink*>(this));
IAGCEventIDRangesPtr spRanges;
if (!pEvents)
{
RETURN_FAILED(get_EnabledDBEvents(&spRanges));
pEvents = spRanges;
}
m_spRangesDB = pEvents;
CComBSTR bstrEventRanges;
if (NULL != m_spRangesDB)
{
GetAGCGlobal()->RegisterEventRanges(m_spRangesDB, AGC_Any_Objects,
static_cast<IAGCEventSink*>(this));
ZSucceeded(m_spRangesDB->get_DisplayString(&bstrEventRanges));
}
if (keyWrite.m_hKey)
{
USES_CONVERSION;
LPCTSTR pszValue = bstrEventRanges ? OLE2CT(bstrEventRanges) : TEXT("");
long lr = keyWrite.SetValue(pszValue, TEXT("EnabledDBEvents"));
assert(ERROR_SUCCESS == lr);
}
return S_OK;
}
STDMETHODIMP CAGCEventLogger::get_EnabledDBEvents(IAGCEventIDRanges** ppEvents)
{
XLock lock(this);
CLEAROUT(ppEvents, (IAGCEventIDRanges*)m_spRangesDB);
(*ppEvents)->AddRef();
return S_OK;
}
STDMETHODIMP CAGCEventLogger::get_DefaultEnabledNTEvents(
IAGCEventIDRanges** ppEvents)
{
CLEAROUT(ppEvents, (IAGCEventIDRanges*)NULL);
IAGCEventIDRangesPtr spRanges;
RETURN_FAILED(spRanges.CreateInstance("AGC.EventIDRanges"));
IAGCEventIDRangesPtr spRangesHost;
GetAGCGlobal()->GetAvailableEventIDRanges(&spRangesHost);
for (const CAGCEventDef::XEventDef* it = CAGCEventDef::begin();
it != CAGCEventDef::end(); ++it)
{
if (0 == it->m_nIndent && it->m_bLogAsNTEvent)
{
VARIANT_BOOL bInRange;
ZSucceeded(spRangesHost->get_IntersectsWithValue(it->m_id, &bInRange));
if (bInRange)
ZSucceeded(spRanges->AddByValues(it->m_id, AGCEventID(it->m_id + 1)));
}
}
*ppEvents = spRanges.Detach();
return S_OK;
}
STDMETHODIMP CAGCEventLogger::get_DefaultEnabledDBEvents(
IAGCEventIDRanges** ppEvents)
{
CLEAROUT(ppEvents, (IAGCEventIDRanges*)NULL);
IAGCEventIDRangesPtr spRanges;
RETURN_FAILED(spRanges.CreateInstance("AGC.EventIDRanges"));
IAGCEventIDRangesPtr spRangesHost;
GetAGCGlobal()->GetAvailableEventIDRanges(&spRangesHost);
for (const CAGCEventDef::XEventDef* it = CAGCEventDef::begin();
it != CAGCEventDef::end(); ++it)
{
if (0 == it->m_nIndent && it->m_bLogAsDBEvent)
{
VARIANT_BOOL bInRange;
ZSucceeded(spRangesHost->get_IntersectsWithValue(it->m_id, &bInRange));
if (bInRange)
ZSucceeded(spRanges->AddByValues(it->m_id, AGCEventID(it->m_id + 1)));
}
}
*ppEvents = spRanges.Detach();
return S_OK;
}
STDMETHODIMP CAGCEventLogger::Initialize(BSTR bstrSourceApp, BSTR bstrRegKey)
{
assert(BSTRLen(bstrSourceApp));
assert(BSTRLen(bstrRegKey));
DWORD cchEaten;
HKEY hkeyRoot = RootKeyFromString(bstrRegKey, &cchEaten);
if (!hkeyRoot)
{
ZError("CAGCEventLogger::Initialize(): Invalid registry key name specified.");
return E_INVALIDARG;
}
USES_CONVERSION;
LONG lr = m_key.Open(hkeyRoot, OLE2CT(bstrRegKey + cchEaten), KEY_READ);
CComBSTR bstrNTEventLog;
IAGCEventIDRangesPtr spRangesNT;
if (IsWinNT())
{
ReadStringValueFromRegistry(TEXT("NTEventLog"), bstrNTEventLog);
CComBSTR bstrEnabledEvents;
HRESULT hr = ReadStringValueFromRegistry(TEXT("EnabledNTEvents"),
bstrEnabledEvents);
if (SUCCEEDED(hr) &&
(!bstrEnabledEvents.Length() ||
_wcsicmp(bstrEnabledEvents, L"default")))
{
RETURN_FAILED(spRangesNT.CreateInstance("AGC.EventIDRanges"));
RETURN_FAILED(spRangesNT->put_DisplayString(bstrEnabledEvents));
}
else
{
RETURN_FAILED(get_DefaultEnabledNTEvents(&spRangesNT));
}
}
CComBSTR bstrConnectionString;
CComBSTR bstrTableName;
IAGCEventIDRangesPtr spRangesDB;
ReadStringValueFromRegistry(TEXT("ConnectionString"),
bstrConnectionString);
ReadStringValueFromRegistry(TEXT("TableName"), bstrTableName);
IAGCDBParamsPtr spDBParams;
RETURN_FAILED(spDBParams.CreateInstance("AGC.DBParams"));
RETURN_FAILED(spDBParams->put_ConnectionString(bstrConnectionString));
RETURN_FAILED(spDBParams->put_TableName(bstrTableName));
CComBSTR bstrEnabledEvents;
HRESULT hr = ReadStringValueFromRegistry(TEXT("EnabledDBEvents"),
bstrEnabledEvents);
if (SUCCEEDED(hr) &&
(!bstrEnabledEvents.Length() ||
_wcsicmp(bstrEnabledEvents, L"default")))
{
RETURN_FAILED(spRangesDB.CreateInstance("AGC.EventIDRanges"));
RETURN_FAILED(spRangesDB->put_DisplayString(bstrEnabledEvents));
}
else
{
RETURN_FAILED(get_DefaultEnabledDBEvents(&spRangesDB));
}
if (IsWinNT())
{
ZSucceeded(put_EnabledNTEvents(spRangesNT));
}
ZSucceeded(put_EnabledDBEvents(spRangesDB));
m_bstrSourceApp = bstrSourceApp;
if (IsWinNT())
{
RETURN_FAILED(put_NTEventLog(bstrNTEventLog));
}
RETURN_FAILED(put_DBEventLog(spDBParams));
m_bInitializing = false;
return S_OK;
}
STDMETHODIMP CAGCEventLogger::Terminate()
{
TCHandle hevt = CreateEvent(NULL, false, false, NULL);
assert(!hevt.IsNull());
FireDBEventLogStopped();
HRESULT hr = S_OK;
PostMessage(e_CloseDatabase, 2, hevt, &hr);
WaitForSingleObject(hevt, INFINITE);
RETURN_FAILED(hr);
FireNTEventLogStopped();
PostMessage(e_CloseNTEventLog, 2, hevt, &hr);
WaitForSingleObject(hevt, INFINITE);
RETURN_FAILED(hr);
IUnknownPtr spUnk(GetUnknown());
{
XLock lock(this);
ZSucceeded(GetAGCGlobal()->RevokeAllEvents(
static_cast<IAGCEventSink*>(this)));
}
TCWorkerThread::Close();
return S_OK;
}
STDMETHODIMP CAGCEventLogger::put_LoggingToNTEnabled(VARIANT_BOOL bEnabled)
{
XLock lock(this);
m_bLoggingToNTEnabled = !!bEnabled;
return S_OK;
}
STDMETHODIMP CAGCEventLogger::get_LoggingToNTEnabled(VARIANT_BOOL* pbEnabled)
{
XLock lock(this);
CLEAROUT(pbEnabled, VARBOOL(m_bLoggingToNTEnabled));
return S_OK;
}
STDMETHODIMP CAGCEventLogger::put_LoggingToDBEnabled(VARIANT_BOOL bEnabled)
{
XLock lock(this);
m_bLoggingToDBEnabled = !!bEnabled;
return S_OK;
}
STDMETHODIMP CAGCEventLogger::get_LoggingToDBEnabled(VARIANT_BOOL* pbEnabled)
{
XLock lock(this);
CLEAROUT(pbEnabled, VARBOOL(m_bLoggingToDBEnabled));
return S_OK;
}
STDMETHODIMP CAGCEventLogger::put_HookForNTLogging(IAGCEventLoggerHook* pHook)
{
XLock lock(this);
m_spHookNT = pHook;
return S_OK;
}
STDMETHODIMP CAGCEventLogger::get_HookForNTLogging(IAGCEventLoggerHook** ppHook)
{
XLock lock(this);
CLEAROUT(ppHook, (IAGCEventLoggerHook*)m_spHookNT);
return S_OK;
}
STDMETHODIMP CAGCEventLogger::put_HookForDBLogging(IAGCEventLoggerHook* pHook)
{
XLock lock(this);
m_spHookDB = pHook;
return S_OK;
}
STDMETHODIMP CAGCEventLogger::get_HookForDBLogging(IAGCEventLoggerHook** ppHook)
{
XLock lock(this);
CLEAROUT(ppHook, (IAGCEventLoggerHook*)m_spHookDB);
return S_OK;
}