///////////////////////////////////////////////////////////////////////////// // // Copyright: Microsoft Corp. 1997-1999. All rights reserved // ///////////////////////////////////////////////////////////////////////////// // Event.cpp : Implementation of CEvent #include "stdafx.h" #include "Evntutl.h" #include "Event.h" ///////////////////////////////////////////////////////////////////////////// // CEvent STDMETHODIMP CEvent::InterfaceSupportsErrorInfo(REFIID riid) { static const IID* arr[] = { &IID_IEvent }; for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++) { if (InlineIsEqualGUID(*arr[i],riid)) return S_OK; } return S_FALSE; } /* Function: get_Server Inputs: empty BSTR Outputs: BSTR containing the Description for the Event (calculated) Purpose: Allows user to access the description for an Event */ STDMETHODIMP CEvent::get_Description(BSTR *pVal) { HRESULT hr = S_OK; unsigned int i; if (pVal) { if (m_Description.length() == 0) { hr = CheckDefaultDescription(m_ppArgList); if (SUCCEEDED(hr)) *pVal = m_Description.copy(); if (m_ppArgList) { // delete the ArgList for (i=0;ivt = VT_ARRAY | VT_UI1; pVal->parray = m_pDataArray; } else hr = E_POINTER; return hr; } /* Function: Init Inputs: pointer to an EVENTLOGRECORD structure Outputs: does not modify input Purpose: fill Event object properties which do not require loading external libs */ HRESULT CEvent::Init(EVENTLOGRECORD* pEventStructure, const LPCTSTR szEventLogName) { HRESULT hr = S_OK; m_EventLogName = szEventLogName; hr = ParseEventBlob(pEventStructure); return hr; } /* Function: ParseEventBlob Inputs: pointer to an EVENTLOGRECORD structure Outputs: does not modify input Purpose: Parse an EVENTLOGRECORD and set the appropriate internal structures of Event */ HRESULT CEvent::ParseEventBlob(EVENTLOGRECORD* pEventStructure) { HRESULT hr = S_OK; wchar_t* wTempString; BYTE* pSourceName; BYTE* pComputerName; SAFEARRAYBOUND rgsabound[1]; ULONG StringsToRetrieve = 0, CharsRead = 0, i = 0; long Index[1]; BYTE pTemp; m_EventID = pEventStructure->EventID; m_EventCategory = pEventStructure->EventCategory; switch (pEventStructure->EventType) { case EVENTLOG_ERROR_TYPE: m_EventType = ErrorEvent; break; case EVENTLOG_WARNING_TYPE: m_EventType = WarningEvent; break; case EVENTLOG_INFORMATION_TYPE: m_EventType = InformationEvent; break; case EVENTLOG_AUDIT_SUCCESS: m_EventType = AuditSuccess; break; case EVENTLOG_AUDIT_FAILURE: m_EventType = AuditFailure; break; default: hr = E_FAIL; } // parse strings from the memory blob // Set source name pSourceName = (BYTE*) &(pEventStructure->DataOffset) + sizeof(pEventStructure->DataOffset); wTempString = (wchar_t*)pSourceName; m_SourceName = wTempString; // Set computer name pComputerName = (BYTE*)pSourceName + ((wcslen(wTempString)+1) * sizeof(wchar_t)); wTempString = (wchar_t*)pComputerName; m_ComputerName = wTempString; // Set SID if ((pEventStructure->StringOffset - pEventStructure->UserSidOffset) != 0) { m_pSid = new BYTE[pEventStructure->UserSidLength]; // scope = CEvent, deleted in ~CEvent() or SetSID() whichever comes first if (m_pSid != NULL) { for (i = 0; iUserSidLength; i++) m_pSid[i] = (BYTE)(*((BYTE*)pEventStructure + pEventStructure->UserSidOffset + i * sizeof(BYTE))); } } // Set Occurence time // this code is copied from MSDN FILETIME FileTime, LocalFileTime; SYSTEMTIME SysTime; __int64 lgTemp; __int64 SecsTo1970 = 116444736000000000; lgTemp = Int32x32To64(pEventStructure->TimeGenerated,10000000) + SecsTo1970; FileTime.dwLowDateTime = (DWORD) lgTemp; FileTime.dwHighDateTime = (DWORD)(lgTemp >> 32); FileTimeToLocalFileTime(&FileTime, &LocalFileTime); FileTimeToSystemTime(&LocalFileTime, &SysTime); if(!SystemTimeToVariantTime(&SysTime, &m_OccurrenceTime)) hr = GetLastError(); // Set Data (create and fill a SafeArray) if (pEventStructure->DataLength>0) { rgsabound[0].lLbound = 0; rgsabound[0].cElements = pEventStructure->DataLength; m_pDataArray = SafeArrayCreate(VT_UI1, 1, rgsabound); for (i=0;iDataLength;i++) { Index[0] = i; pTemp = (BYTE) (pEventStructure->DataOffset + i * sizeof(BYTE)); hr = SafeArrayPutElement(m_pDataArray, Index, &pTemp); if (FAILED(hr)) i = pEventStructure->DataLength; } } // Set the description m_Description = ""; if (m_SourceName.length() != 0) { // prepare the ArgList m_NumberOfStrings = pEventStructure->NumStrings; m_ppArgList = new wchar_t*[m_NumberOfStrings]; // scope = CEvent, deleted when ~CEvent or get_Description is called whichever is first for (i=0;iDataOffset - pEventStructure->StringOffset)]; // can't be larger than the length of all the strings we got for (i=0;iStringOffset + CharsRead * sizeof(wchar_t)); wcscpy(m_ppArgList[i], wTempString); CharsRead = CharsRead + wcslen(wTempString) + 1; // + 1 for the null } } else // if there is no module to load a default description, just put all the string args in the description { StringsToRetrieve = pEventStructure->NumStrings; while (StringsToRetrieve > 0) { wTempString = (wchar_t*) (((BYTE*)(pEventStructure)) + pEventStructure->StringOffset + CharsRead * sizeof(wchar_t)); m_Description = m_Description + " " + wTempString; CharsRead = CharsRead + wcslen(wTempString) + 1; // + 1 for the null StringsToRetrieve--; } } return hr; } /* Function: CheckDefaultDescription Inputs: pointer pointer to a wide character Outputs: does not modify input Purpose: format a message from an EventID, set of input strings, and a source module */ HRESULT CEvent::CheckDefaultDescription(wchar_t** Arguments) { HRESULT hr = S_OK; BYTE* wMessagePath = NULL; ULONG BufferSize = 40000; ULONG* lPathLength = NULL; wchar_t* wOrigionalPath = NULL; wchar_t* wExpandedPath = NULL; wchar_t* pBuffer = NULL; _bstr_t btRegKey; _bstr_t btTempString; HMODULE hiLib; HKEY hKey; try{ lPathLength = new ULONG; if (lPathLength) { *lPathLength = 256*2; wMessagePath = new BYTE[*lPathLength]; if (wMessagePath) { // get registry value for Source module path btRegKey = "SYSTEM\\CurrentControlSet\\Services\\Eventlog\\" + m_EventLogName; btRegKey = btRegKey + "\\"; btRegKey = btRegKey + m_SourceName; hr = RegOpenKey(HKEY_LOCAL_MACHINE, btRegKey, &hKey); if (hKey) { hr = RegQueryValueEx(hKey, L"EventMessageFile", NULL, NULL, wMessagePath, lPathLength); if (hr == 0) { wOrigionalPath = (wchar_t*) wMessagePath; wExpandedPath = new wchar_t[(int)*lPathLength]; if (wExpandedPath) { ExpandEnvironmentStrings(wOrigionalPath, wExpandedPath, *lPathLength); btTempString = wExpandedPath; // open the Source module hiLib = LoadLibraryEx(btTempString, NULL, LOAD_LIBRARY_AS_DATAFILE); hr = GetLastError(); if (hiLib) { pBuffer = new wchar_t[BufferSize]; if (pBuffer) { SetLastError(0); FormatMessage(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY, hiLib, m_EventID, 0, pBuffer, BufferSize, reinterpret_cast(Arguments)); hr = HRESULT_FROM_WIN32(GetLastError()); m_Description = m_Description + pBuffer; delete []pBuffer; pBuffer = NULL; } else hr = E_OUTOFMEMORY; FreeLibrary(hiLib); } delete [] wExpandedPath; wExpandedPath = NULL; } else hr = E_OUTOFMEMORY; } else hr = HRESULT_FROM_WIN32(hr); RegCloseKey(hKey); } else hr = HRESULT_FROM_WIN32(hr); delete []wMessagePath; wMessagePath = NULL; } else hr = E_OUTOFMEMORY; delete lPathLength; lPathLength = NULL; } else hr = E_OUTOFMEMORY; } catch(...){ if (lPathLength != NULL) { delete lPathLength; } if (wMessagePath != NULL) { delete []wMessagePath; } if (wExpandedPath != NULL) { delete [] wExpandedPath; } if (pBuffer != NULL) { delete []pBuffer; } } return hr; } /* Function: SetUser Inputs: none Outputs: HRESULT indicating what error if any occured Purpose: finds alias and domain for a given SID */ HRESULT CEvent::SetUser() { HRESULT hr = S_OK; SID_NAME_USE SidNameUse; wchar_t* wUserName; wchar_t* wDomainName; SID* pSid; unsigned long UserNameLength = 256; // Set user name and sid if (m_pSid !=NULL) { pSid = (SID*)m_pSid; wUserName = new wchar_t[UserNameLength]; if (wUserName) { wDomainName = new wchar_t[UserNameLength]; if (wDomainName) { m_UserName = ""; if (LookupAccountSid(NULL, pSid, wUserName, &UserNameLength, wDomainName, &UserNameLength, &SidNameUse)) m_UserName = m_UserName + wDomainName + L"\\" + wUserName; else hr = HRESULT_FROM_WIN32(GetLastError()); delete []wDomainName; } else hr = E_OUTOFMEMORY; delete []wUserName; } else hr = E_OUTOFMEMORY; delete []m_pSid; m_pSid = NULL; } return hr; }