/* * An event log wrapper to simplify event logging for DLLs and to add * a few extra features. */ #ifndef __EVENTWRAP_H__ #define __EVENTWRAP_H__ #include #include #define LOGEVENT_DEBUGLEVEL_HIGH 1 #define LOGEVENT_DEBUGLEVEL_MEDIUM 2^15 #define LOGEVENT_DEBUGLEVEL_LOW 2^16 #define LOGEVENT_FLAG_ALWAYS 0x00000001 #define LOGEVENT_FLAG_ONETIME 0x00000002 #define LOGEVENT_FLAG_PERIODIC 0x00000003 // we use the lower 8 bits for various logging modes, and reserve the // other 24 for flags #define LOGEVENT_FLAG_MODEMASK 0x000000ff // // This object is the key for the eventlog hash table // class CEventLogHashKey { public: char *m_szKey; DWORD m_idMessage; BOOL m_fAllocKey; CEventLogHashKey() { m_fAllocKey = FALSE; m_szKey = NULL; m_idMessage = 0; } HRESULT Init(const char *szKey, DWORD idMessage) { m_idMessage = idMessage; m_szKey = new char[strlen(szKey) + 1]; if (m_szKey) { m_fAllocKey = TRUE; strcpy(m_szKey, szKey); } else { return E_OUTOFMEMORY; } return S_OK; } ~CEventLogHashKey() { if (m_fAllocKey && m_szKey) { delete[] m_szKey; m_szKey = NULL; m_fAllocKey = FALSE; } m_idMessage = 0; } }; // Time to wait between periodic event logs in 100ns units. Note that this // is larger than 32 bits (it is 8'61c46800). const __int64 LOGEVENT_PERIOD = 36000000000; // 60 minutes // // For each unique idMessage/szKey event that is logged we insert one // of these objects into a hash table. This allows us to support the // LOGEVENT_FLAG_ONETIME and LOGEVENT_FLAG_PERIODIC flags // class CEventLogHashItem { public: CEventLogHashItem *m_pNext; CEventLogHashItem() { m_pNext = NULL; ZeroMemory(&m_timeLastLog, sizeof(FILETIME)); UpdateLogTime(); } CEventLogHashKey *GetKey() { return &(m_key); } int MatchKey(CEventLogHashKey *pOtherKey) { return (m_key.m_idMessage == pOtherKey->m_idMessage && strcmp(m_key.m_szKey, pOtherKey->m_szKey) == 0); } HRESULT InitializeKey(const char *szKey, DWORD idMessage) { return m_key.Init(szKey, idMessage); } BOOL PeriodicLogOkay() { FILETIME timeCurrent; GetSystemTimeAsFileTime(&timeCurrent); LARGE_INTEGER liCurrent = { timeCurrent.dwLowDateTime, timeCurrent.dwHighDateTime }; LARGE_INTEGER liLastLog = { m_timeLastLog.dwLowDateTime, m_timeLastLog.dwHighDateTime }; LARGE_INTEGER liDifference; liDifference.QuadPart = liCurrent.QuadPart - liLastLog.QuadPart; return (liDifference.QuadPart > LOGEVENT_PERIOD); } void UpdateLogTime() { GetSystemTimeAsFileTime(&m_timeLastLog); } private: CEventLogHashKey m_key; FILETIME m_timeLastLog; }; class CEventLogWrapper { public: CEventLogWrapper() { m_hEventLog = NULL; } // // Register your event source in the registry. // // Parameters: // szEventSource - the name of the eventsource // szMessageFile - the full path to the DLL which contains the // eventlog strings // fApplication - The eventsource is an application, not a system // component // static HRESULT AddEventSourceToRegistry(char *szEventSource, char *szMessageFile, BOOL fApplication = FALSE); // // Unregister your event source in the registry. // // Parameters: // szEventSource - the name of the eventsource // fApplication - The eventsource is an application, not a system // component // static HRESULT RemoveEventSourceFromRegistry(char *szEventSource, BOOL fApplication = FALSE); // // Initialize the event logging library. // // Parameters: // szEventSource - the name of the eventsource // HRESULT Initialize(char *szEventSource); // // Write an event to the event log // // Parameters: // idMessage - the eventlog ID // cSubstrings - count of strings in rgszSubstrings // rgszSubstrings - substrings for the eventlog text // wType - eventlog error type. Should be EVENTLOG_WARNING_TYPE, // EVENTLOG_INFORMATION_TYPE or EVENTLOG_ERROR_TYPE. // errCode - Win32 error code to log (or 0) // iDebugLevel - debug level of the event. 1 = highest priority, // 2^16 = lowest priority. normally anything above 2^15 isn't // logged. // szKey - a key which is used along with idMessage to uniquely // identify this eventlog. It is used to control the options. // dwOptions - options for logging this event. // Optional Parameters: // iMessageString - call FormatMessage on errCode and save // the string into rgszSubstrings[iMessageString]. // HMODULE hModule - module with extra error codes for // FormatMessage. // HRESULT LogEvent(DWORD idMessage, WORD cSubstrings, LPCSTR *rgszSubstrings, WORD wType, DWORD errCode, WORD iDebugLevel, LPCSTR szKey, DWORD dwOptions, DWORD iMessageString = 0xffffffff, HMODULE hModule = NULL); // // Reset any history about events using this message and key, // so that the next LogEvent with one-time or periodic logging // will cause the event to be logged. // // Parameters: // idMessage - the eventlog ID // szKey - a key which is used along with idMessage to uniquely // identify this eventlog. // HRESULT ResetEvent(DWORD idMessage, LPCSTR szKey); ~CEventLogWrapper(); private: // the handle returned from RegisterEventSource HANDLE m_hEventLog; // this hash table is used to remember which keys we have // used to support PERIODIC and ONETIME options TFHashEx m_hash; }; #endif