Click here to Skip to main content
Click here to Skip to main content

Tagged as

Go to top

WindowsNT Event Log Viewer

, 30 Nov 1999
Rate this:
Please Sign up or sign in to vote.
  • Download demo executable - 17 Kb
  • Download source files - 43 Kb
  • Sample Image

    <!-- Article Starts -->

    The Event Viewer is intended to be run under WindowsNT System Manager (check the submission with the same name). This sample application uses (more or less) the same policy regarding MDI, child dialog encapsulation, controls etc., and these things are treated there. In this article you can see two thread routines which you may find interesting.
    1. The first is the routine which enumerates event entries, FillEventLogList. The structure passed as parameter to this thread routine is

    typedef struct _tagEVENTLOGFILTER
    {
       BOOL      fApplication;            /* 'Application' entries       */
       BOOL      fSecurity;            /* 'Security' entries       */
       BOOL      fSystem;               /* 'System' entries       */
       BOOL      fCustom;               /* 'Custom' entries: unused      */
       TCHAR      lpszComputerName[_MAX_PATH + 1];      /* computer name         */
       HWND      hwndLV;               /* list view handle      */
       HWND      hwndDlg;               /* encapsulated dialog handle   */
       HWND      hwndProgr;            /* progress bar handle      */
       HANDLE      hCancelEvent;            /* 'Cancel' event handle      */
       HANDLE      hCloseEvent;            /* 'Close' event handle      */
       unsigned   uThreadId;               /* thread ID         */
       TCHAR      lpszCustomEventFileName[_MAX_PATH + 1];   /* Custom file name: unused      */
    } EVENTLOGFILTER, *LPEVENTLOGFILTER;
    
    The routine looks like this:
    unsigned int __stdcall 
    FillEventLogList(LPVOID lpParam)
    {
       EVENTLOGFILTER *pelf = 0;
       int nRetVal = 0;
       HWND hParentWnd = 0, hwndDlg = 0, hwndLV = 0, hwndProgr = 0;
       HANDLE hEventLog = 0;
       DWORD dwEventLogRecords = 0, dwOldestEventLogRecord = 0, dwEvLogCounter = 0, dwNumberOfBytesToRead = 0, 
          dwBytesRead = 0, dwMinNumberOfBytesNeeded = 0, dwCancel = 0, dwClose = 0;
       LPVOID lpEventLogRecordBuffer = 0;
       TCHAR chFakeBuffer;
       BOOL bRetVal = FALSE;
       BOOL fExit = FALSE;
       UINT uStep = 0, uStepAt = 0, uPos = 0, uOffset = 0;
       TCHAR lpUNCServerName[_MAX_PATH + 1], lpszEventLogSourceName[_MAX_PATH + 1], lpszErrMsg[1024];
    
       // get thread parameter structure address...
       pelf = (EVENTLOGFILTER *)lpParam;
       // ...and retrieve the appropriate handles
       hwndDlg   = pelf->hwndDlg;
       hwndLV   = pelf->hwndLV;
       hwndProgr = pelf->hwndProgr;
    
       // get parent window...
       hParentWnd = GetParent(hwndDlg);
       // ...and set user data to 1 (the window has thread running) - will be reset to 0 when thread will terminate
       SetWindowLong(hParentWnd, GWL_USERDATA, (LONG)pelf); 
    
       // resize dialog
       MDIChild_ResizeDlg(hwndDlg, TRUE);
    
       // format UNC machine name to work with
       wsprintf(lpUNCServerName, _T("\\\\%s"), pelf->lpszComputerName);
    
       // establish what kind of event log section will show the list
       if(g_fApplication)
          _tcscpy(lpszEventLogSourceName, _T("Application"));            //   APPLICATION
       else if(g_fSystem)
          _tcscpy(lpszEventLogSourceName, _T("System"));               //   SYSTEM
       else if(g_fSecurity)
          _tcscpy(lpszEventLogSourceName, _T("Security"));            //   SECURITY
       else if(g_fCustom)
          _tcscpy(lpszEventLogSourceName, pelf->lpszCustomEventFileName);   //   CUSTOM
       else
       {
          nRetVal = -1;
          goto _cleanup_;
       }
    
       //   lookup for close or cancel (ESC pressed) attempts to intrrerupt thread
       dwCancel = WaitForSingleObject(pelf->hCancelEvent, 0);
       dwClose = WaitForSingleObject(pelf->hCloseEvent, 0);
    
       while(!fExit)
       {
          if(g_fCustom)   //   never reached
             hEventLog = OpenBackupEventLog((LPCTSTR)lpUNCServerName, (LPCTSTR)lpszEventLogSourceName);
          else
             hEventLog = OpenEventLog((LPCTSTR)lpUNCServerName, (LPCTSTR)lpszEventLogSourceName);
    
          if(hEventLog)
          {
             if(GetNumberOfEventLogRecords(hEventLog, &dwEventLogRecords) && 
                GetOldestEventLogRecord(hEventLog, &dwOldestEventLogRecord))
             {
                //   establish step fro progress bar
                SendMessage(hwndProgr, PBM_SETRANGE, (WPARAM)0, (LPARAM)MAKELPARAM(0, 100));
                uStepAt = (dwEventLogRecords / 100) + 1;
    
                for(dwEvLogCounter = dwOldestEventLogRecord; 
                   dwEvLogCounter < (dwOldestEventLogRecord + dwEventLogRecords); 
                   dwEvLogCounter++)
                {
                   //   advance progress bar with step
                   uStep++;
                   if(uStep % uStepAt == 0)
                      hwndProgr && SendMessage(hwndProgr, PBM_SETPOS, (WPARAM)++uPos, 0);
    
                   dwCancel = WaitForSingleObject(pelf->hCancelEvent, 0);
                   if(dwCancel == WAIT_OBJECT_0)
                      goto _canceled_;
                   dwClose = WaitForSingleObject(pelf->hCloseEvent, 0);
                   if(dwClose == WAIT_OBJECT_0)
                      goto _close_;
    
                   //   this is a false call (intended to get the real structure size)
                   lpEventLogRecordBuffer      = (LPVOID)&chFakeBuffer;
                   dwNumberOfBytesToRead      = 1;
                   dwMinNumberOfBytesNeeded   = 1;
    
       _retry_:
                   bRetVal = ReadEventLog(hEventLog, EVENTLOG_SEEK_READ | EVENTLOG_FORWARDS_READ, dwEvLogCounter, 
                      lpEventLogRecordBuffer, dwNumberOfBytesToRead, &dwBytesRead, &dwMinNumberOfBytesNeeded);
    
                   if(!bRetVal)
                   {
                      g_dwLastError = GetLastError();
    
                      if(g_dwLastError == ERROR_INSUFFICIENT_BUFFER)
                      {
                         lpEventLogRecordBuffer = (LPVOID)GlobalAlloc(GPTR, dwMinNumberOfBytesNeeded);
                         if(lpEventLogRecordBuffer == (void *)0)
                            goto _allocationfailure_;
    
                         dwNumberOfBytesToRead = dwMinNumberOfBytesNeeded;
                         goto _retry_;
                      }
                      else
                         goto _unknownerror_;
                   }
                   else   //   here we are with complete structure filled; proceed
                   {
                      PEVENTLOGRECORD pELR = 0;
                      TCHAR *lpszSourceName = 0, lpszUserName[_MAX_PATH + 1], *lpszComputerName = 0,
                         lpszRefDomainName[_MAX_PATH + 1], *szSIDType = 0, *szSIDName = 0, sz2[32],
                         *szExpandedString = 0, szSubmitTime[32], szWriteTime[32];
                      DWORD dwSourceNameLen = 0, dwComputerNameLen = 0, cbName = _MAX_PATH + 1, 
                         cbRefDomainName = _MAX_PATH + 1, dwSIDTypeLen = 0, dwSidSize = 0, dwEventTypeLen = 0;
                      PSID pUserSID = 0;
                      SID_NAME_USE _SidNameUse = (SID_NAME_USE)(SidTypeUser - 1);
                      BOOL bRetVal = FALSE;
                      LPBYTE pStrings = 0, pData = 0;
                      UINT x = 0, uSize, uStringOffset, uStepOfString = 0, uImage = 0;
    
                      //   the buffer
                      pELR   = (PEVENTLOGRECORD)lpEventLogRecordBuffer;
    
                      //   source name and advance offset
                      uOffset   = sizeof(EVENTLOGRECORD);
                      lpszSourceName = (TCHAR *)GlobalAlloc(GPTR, (_MAX_PATH + 1) * sizeof(TCHAR));
                      strcpy(lpszSourceName, (LPTSTR)((LPBYTE)pELR + uOffset));
                      dwSourceNameLen = strlen(lpszSourceName);
    
                      //   computer name and advance offset
                      uOffset   += strlen(lpszSourceName) + sizeof(TCHAR);
                      lpszComputerName = (TCHAR *)GlobalAlloc(GPTR, (_MAX_PATH + 1) * sizeof(TCHAR));
                      strcpy(lpszComputerName, (LPTSTR)((LPBYTE)pELR + uOffset));
                      dwComputerNameLen = strlen(lpszComputerName);
    
                      uOffset += strlen(lpszComputerName) + sizeof(TCHAR);
    
                      //   SID
                      dwSIDTypeLen = 32;
                      szSIDType = (TCHAR *)GlobalAlloc(GPTR, (dwSIDTypeLen + 1) * sizeof(TCHAR));
    
                      //   retrieve SID
                      if(pELR->UserSidLength > 0)
                      {
                         pUserSID = (SID *)GlobalAlloc(GPTR, pELR->UserSidLength);
                         memcpy(pUserSID, (PSID)((LPBYTE)pELR + pELR->UserSidOffset), pELR->UserSidLength);
                         
                         cbName = cbRefDomainName = _MAX_PATH + 1;
                         *lpszRefDomainName = *lpszUserName = '\0';
    
                         bRetVal = LookupAccountSid(0, pUserSID, 
                            lpszUserName, &cbName, 
                            lpszRefDomainName, &cbRefDomainName, 
                            &_SidNameUse);
    
                         if(bRetVal)
                         {
                            if(bRetVal)
                            {
                               dwSIDTypeLen = 32;
                               GetNameUse(_SidNameUse, szSIDType, &dwSIDTypeLen);
    
                               dwSidSize = (15 + 12 + (12 * (*GetSidSubAuthorityCount(pUserSID))) + 1) * sizeof(TCHAR);
                               szSIDName = (TCHAR *)GlobalAlloc(GPTR, (dwSidSize + 1) * sizeof(TCHAR));
                               ConvertSid(pUserSID, szSIDName, &dwSidSize); 
                            }
                            else
                            {
                               strcpy(lpszRefDomainName, "N/A");
                               strcpy(lpszUserName, "N/A");
                               strcpy(szSIDType, "N/A");
                            }
                         }
                         else
                         {
                         }
                      }
                      else
                      {
                         strcpy(lpszRefDomainName, "N/A");
                         strcpy(lpszUserName, "N/A");
                         strcpy(szSIDType, "N/A");
                      }
    
                      //   Now we have to get the description strings.
                      uSize = 0, uStringOffset = pELR->StringOffset;
                      uSize = pELR->DataOffset - pELR->StringOffset;
    
                      // Strings
                      if(uSize > 0)
                      {
                         pStrings = (LPBYTE)GlobalAlloc(GPTR, uSize * sizeof(BYTE));
                         memcpy(pStrings, (LPBYTE)pELR + uStringOffset, uSize);
    
                         //   Strings
                         uStepOfString = 0;
                         szExpandedString = (TCHAR *)GlobalAlloc(GPTR, (uSize + MAX_MSG_LENGTH) * sizeof(TCHAR));
                         for(x = 0; x < pELR->NumStrings; x++)
                         {
                            if(x == 0)
                            {
                               strcpy(szExpandedString, (TCHAR *)pStrings + uStepOfString);
                               if(x < (UINT)pELR->NumStrings - 1)
                                  strcat(szExpandedString, ",");
                            }
                            else
                               strcat(szExpandedString, (TCHAR *)pStrings + uStepOfString);
    
                            uStepOfString = strlen((TCHAR *)pStrings + uStepOfString) + 1;
                         }
                      }
    
                      //   Data
                      pData = (LPBYTE)GlobalAlloc(GPTR, pELR->DataLength * sizeof(BYTE));
                      memcpy(pData, (LPBYTE)((LPBYTE)pELR + pELR->DataOffset), pELR->DataLength);
    
                      dwEventTypeLen = 32;
                      GetEventLogType(sz2, pELR->EventType, &dwEventTypeLen);
                      GetEventLogImage(&uImage, pELR->EventType);
    
                      lstrcpyn(szSubmitTime, asctime(localtime((time_t *)&(pELR->TimeGenerated))), 25);
                      lstrcpyn(szWriteTime, asctime(localtime((time_t *)&(pELR->TimeWritten))), 25);
    
                      InsertRowInList(hwndLV, 9, &dwEvLogCounter, 
                         lpszSourceName, 
                         lpszUserName, 
                         szSIDName, 
                         lpszRefDomainName, 
                         sz2, uImage, 
                         szSubmitTime, szWriteTime);
    
                      SafeDeletePointer(pData, pELR->DataLength);
                      SafeDeletePointer(szExpandedString, uSize); 
                      SafeDeletePointer(pStrings, pELR->DataOffset - pELR->StringOffset);
                      SafeDeletePointer(szSIDName, dwSidSize + 1);
                      SafeDeletePointer(szSIDType, dwSIDTypeLen + 1);
                      SafeDeletePointer(lpszSourceName, dwSourceNameLen);
                      SafeDeletePointer(lpszComputerName, dwComputerNameLen);
                      SafeDeletePointer(pUserSID, pELR->UserSidLength);
                      SafeDeletePointer(lpEventLogRecordBuffer, dwNumberOfBytesToRead);
                   }
                }
    
                goto _cleanup_;
             }
             else
                ReportLastError(0, 0, TRUE);
    
       _unknownerror_:
             ReportLastError(lpszErrMsg, 0, TRUE);
             goto _cleanup_;
    
       _allocationfailure_:
             LoadString(g_hInstance, IDS_ERR_ALLOCATIONFAILURE, lpszErrMsg, 1024);
             MessageBox(0, lpszErrMsg, 0, MB_OK | MB_ICONSTOP);
             goto _cleanup_;
    
       _canceled_:
             nRetVal = 1;
             goto _cleanup_;
    
       _close_:
             nRetVal = 2;
             goto _cleanup_;
    
       _cleanup_:
             fExit = TRUE;
    
             CloseEventLog(hEventLog);
             hEventLog = 0;
          }
          else
          {
             fExit = TRUE;
             ReportLastError(0, 0, TRUE);
          }
       }
    
       // final cleanup on dialog
       if(nRetVal != 2)
       {
          if(IsWindow(hwndDlg))
             MDIChild_ResizeDlg(hwndDlg, FALSE);
          if(IsWindow(hParentWnd))
             SetWindowLong(hParentWnd, GWL_USERDATA, (LONG)0);
       }
    
       CloseHandle(pelf->hCancelEvent);
       CloseHandle(pelf->hCloseEvent);
    
       GlobalFree(pelf);
       pelf = 0;
    
       return nRetVal;
    }
    

    The key to understanding this king of enumeration and especially the using of structure PEVENTLOGRECORD resides in its definition:

    typedef struct _EVENTLOGRECORD { 
        DWORD  Length; 
        DWORD  Reserved; 
        DWORD  RecordNumber; 
        DWORD  TimeGenerated; 
        DWORD  TimeWritten; 
        DWORD  EventID; 
        WORD   EventType; 
        WORD   NumStrings; 
        WORD   EventCategory; 
        WORD   ReservedFlags; 
        DWORD  ClosingRecordNumber; 
        DWORD  StringOffset; 
        DWORD  UserSidLength; 
        DWORD  UserSidOffset; 
        DWORD  DataLength; 
        DWORD  DataOffset; 
        // 
        // Then follow: 
        // 
        // TCHAR SourceName[] 
        // TCHAR Computername[] 
        // SID   UserSid 
        // TCHAR Strings[] 
        // BYTE  Data[] 
        // CHAR  Pad[] 
        // DWORD Length; 
        // 
    } EVENTLOGRECORD; 
    

    Because this is a variable-length structure, the using of offsets, conversion and allocations seems to me the best approach. (By the way, spending more time you can easily rewrite a better routine).
    Also, you could spend some time reading the ConvertSid function, which retrieves the name of SID looking in some weird registry key. Again you have to deal with a nonstandard structure, SID, which cannot be manipulated manually, but only using the API specific routines.

    BOOL 
    ConvertSid(PSID pSid, LPTSTR pszSidText, LPDWORD dwBufferLen) 
    { 
         DWORD                     dwSubAuthorities; 
         DWORD                     dwSidRev = SID_REVISION; 
         DWORD                     dwCounter; 
         DWORD                     dwSidSize; 
         PSID_IDENTIFIER_AUTHORITY psia; 
     
         if(!IsValidSid(pSid))  
              return FALSE; 
     
         psia = GetSidIdentifierAuthority(pSid); 
    
         dwSubAuthorities =* GetSidSubAuthorityCount(pSid); 
     
         dwSidSize = (15 + 12 + (12 * dwSubAuthorities) + 1) * sizeof(TCHAR); 
     
         if (*dwBufferLen < dwSidSize)
        { 
              *dwBufferLen = dwSidSize; 
              SetLastError(ERROR_INSUFFICIENT_BUFFER); 
              return FALSE; 
        } 
     
         dwSidSize=wsprintf(pszSidText, TEXT("S-%lu-"), dwSidRev ); 
     
         if((psia->Value[0] != 0) || (psia->Value[1] != 0))
              dwSidSize += wsprintf(pszSidText + lstrlen(pszSidText), 
              TEXT("0x%02hx%02hx%02hx%02hx%02hx%02hx"), 
              (USHORT)psia->Value[0], 
              (USHORT)psia->Value[1], 
              (USHORT)psia->Value[2], 
              (USHORT)psia->Value[3], 
              (USHORT)psia->Value[4], 
              (USHORT)psia->Value[5]); 
         else 
              dwSidSize += wsprintf(pszSidText + lstrlen(pszSidText), 
                                   TEXT("%lu"), 
                                   (ULONG)(psia->Value[5]      )   + 
                                   (ULONG)(psia->Value[4] <<  8)   + 
                                   (ULONG)(psia->Value[3] << 16)   + 
                                   (ULONG)(psia->Value[2] << 24)   ); 
     
         for (dwCounter=0 ; dwCounter < dwSubAuthorities ; dwCounter++)
              dwSidSize+=wsprintf(pszSidText + dwSidSize, TEXT("-%lu"), *GetSidSubAuthority(pSid, dwCounter)); 
     
         return TRUE; 
    } 
    

    Double-clicking on an event log entry represented by a row in list, the data window appears, showing more detailed data about the entry you choose. You have to excuse me for the resize problems (sometimes - or I must say often? - resizing parent data window does not resize encapsulated dialog). Again, the job is done via another thread, which use the EVENTID structure

    typedef struct _tagEVENTID
    {
       TCHAR lpszMachineName[_MAX_PATH + 1];
       TCHAR lpszEventName[_MAX_PATH + 1];
       DWORD   dwEventId;
       HWND  hwndDlg;
    } EVENTID, *LPEVENTID;
    
    which simply identifies the record entry, and the routine:
    unsigned int __stdcall 
    ShowEventData(LPVOID lpParam)
    {
       LPEVENTID peid = (LPEVENTID)lpParam;
    
       int   nRetVal = 0;
    
       HWND  hwndDlg      = peid->hwndDlg;
       HWND  hwndEditStrings   = GetDlgItem(hwndDlg, IDE_STRINGS);
       HWND  hwndEditData      = GetDlgItem(hwndDlg, IDE_DATA);
       DWORD dwRecId      = peid->dwEventId;
    
       TCHAR  lpUNCServerName[_MAX_PATH + 1];
       TCHAR  lpSourceName[_MAX_PATH + 1];
    
       HANDLE  hEventLog         = 0;
       
       DWORD  dwEventLogRecords      = 0;
       DWORD  dwOldestEventLogRecord   = 0;
       DWORD  dwEvLogCounter      = 0;
    
       LPVOID lpEventLogRecordBuffer   = 0;
       char   chFakeBuffer      = ' ';
       DWORD  dwNumberOfBytesToRead   = 0;
       DWORD  dwBytesRead         = 0;
       DWORD  dwMinNumberOfBytesNeeded   = 0;
       BOOL    bRetVal         = FALSE;
       TCHAR   lpszEventLogSourceName[_MAX_PATH + 1];
    
       wsprintf(lpUNCServerName, _T("\\\\%s"), peid->lpszMachineName);
       wsprintf(lpSourceName, _T("%s"), peid->lpszEventName);
    
       if(g_fApplication)
          _tcscpy(lpszEventLogSourceName, _T("Application"));
       else if(g_fSystem)
          _tcscpy(lpszEventLogSourceName, _T("System"));
       else if(g_fSecurity)
          _tcscpy(lpszEventLogSourceName, _T("Security"));
    //   else if(g_fCustom)
    //      _tcscpy(lpszEventLogSourceName, _T("Application"));
       else
       {
          nRetVal = -1;
          goto _cleanup_;
       }
    
       hEventLog = OpenEventLog((LPCTSTR)lpUNCServerName, (LPCTSTR)lpszEventLogSourceName);
       if(hEventLog)
       {
          if(GetNumberOfEventLogRecords(hEventLog, &dwEventLogRecords) && 
             GetOldestEventLogRecord(hEventLog, &dwOldestEventLogRecord))
          {
             for(dwEvLogCounter = dwOldestEventLogRecord; 
                dwEvLogCounter <= (dwOldestEventLogRecord + dwEventLogRecords); 
                dwEvLogCounter++)
             {
                if(dwEvLogCounter != dwRecId)
                   continue;
    
                lpEventLogRecordBuffer      = (LPVOID)&chFakeBuffer;
                dwNumberOfBytesToRead      = 1;
                dwMinNumberOfBytesNeeded   = 0;
    
    _retry_:
                bRetVal = ReadEventLog(hEventLog, EVENTLOG_SEEK_READ | EVENTLOG_FORWARDS_READ,
                          dwEvLogCounter, lpEventLogRecordBuffer, dwNumberOfBytesToRead, 
                          &dwBytesRead, &dwMinNumberOfBytesNeeded);
    
                if(!bRetVal)
                {
                   g_dwLastError = GetLastError();
    
                   if(g_dwLastError == ERROR_INSUFFICIENT_BUFFER)
                   {
                      lpEventLogRecordBuffer = (LPVOID)GlobalAlloc(GPTR, dwMinNumberOfBytesNeeded);
                      if(lpEventLogRecordBuffer == (void *)0)
                         goto _allocationfailure_;
    
                      dwNumberOfBytesToRead = dwMinNumberOfBytesNeeded;
                      goto _retry_;
                   }
                   else
                      goto _unknownerror_;
                }
                else
                {
                   PEVENTLOGRECORD pELR = 0;
                   LPBYTE         pData = 0;
                   HMODULE hModule = 0;
                   TCHAR szExeFile[_MAX_PATH + 1], szExeFilePath[_MAX_PATH + 1];
                   HKEY   hk                  = (HKEY)0;
                   TCHAR  szKeyName[_MAX_PATH + 1];
                   DWORD dwMaxPath;
                   DWORD dwType;
                   LPBYTE         pStrings = 0;
                   UINT uStringOffset;
                   TCHAR *szExpandedString;
                   LPVOID lpszBuffer = 0;
                   
                   pELR   = (PEVENTLOGRECORD)lpEventLogRecordBuffer;
    
                   pData = (LPBYTE)GlobalAlloc(GPTR, pELR->DataLength * sizeof(BYTE));
                   memcpy(pData, (LPBYTE)((LPBYTE)pELR + pELR->DataOffset), pELR->DataLength);
    
                   {
                      UINT x, uStepOfString = 0;
    
                      pStrings = (LPBYTE)GlobalAlloc(GPTR, pELR->DataOffset - pELR->StringOffse
                                                     * sizeof(BYTE));
                      memcpy(pStrings, (LPBYTE)pELR + pELR->StringOffset, pELR->DataOffset
                                                      - pELR->StringOffset);
    
                      szExpandedString = (TCHAR *)GlobalAlloc(GPTR, (pELR->DataOffset
                                                    - pELR->StringOffset + 1024) * sizeof(TCHAR));
                      for(x = 0; x < pELR->NumStrings; x++)
                      {
                         if(x == 0)
                         {
                            strcpy(szExpandedString, (TCHAR *)pStrings + uStepOfString);
                            if(x < (UINT)pELR->NumStrings - 1)
                               strcat(szExpandedString, ",");
                         }
                         else
                            strcat(szExpandedString, (TCHAR *)pStrings + uStepOfString);
    
                         uStepOfString = strlen((TCHAR *)pStrings + uStepOfString) + 1;
                      }
    
                      wsprintf(szKeyName, _T("SYSTEM\\CurrentControlSet\\Services\\EventLog\\%s\\%s"), 
                         lpszEventLogSourceName, peid->lpszEventName);
                      if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0L, KEY_READ, &hk) == NOERROR)
                      {
                         dwMaxPath = _MAX_PATH + 1;
                         if(RegQueryValueEx(hk, _T("EventMessageFile"), 0, &dwType, 
                                            (LPBYTE)szExeFile, &dwMaxPath) == NOERROR)
                         {
                            if(ExpandEnvironmentStrings(szExeFile, szExeFilePath, _MAX_PATH + 1) == 0)
                               strcpy(szExeFilePath, szExeFile);
    
                            hModule = LoadLibraryEx(szExeFilePath, 0, DONT_RESOLVE_DLL_REFERENCES);
                            if(hModule)
                            {
                               TCHAR **_sz = (TCHAR**)GlobalAlloc(GPTR, (pELR->NumStrings) 
                                                                     * sizeof(TCHAR *));
                               register UINT z;
    
                               uStringOffset = 0;
                               for(z = 0; z < pELR->NumStrings; z++)
                               {
                                  _sz[z] = (TCHAR *)GlobalAlloc(GPTR, 
                                     (strlen((TCHAR *)pStrings + uStringOffset) + 1) * sizeof(TCHAR));
                                  strcpy(_sz[z], (TCHAR *)pStrings + uStringOffset);
    
                                  uStringOffset += strlen((TCHAR *)pStrings + uStringOffset) + 1;
                               }
    
                               FormatMessage(
                                  FORMAT_MESSAGE_ALLOCATE_BUFFER | 
                                  FORMAT_MESSAGE_FROM_HMODULE | 
                                  FORMAT_MESSAGE_FROM_SYSTEM | 
                                  FORMAT_MESSAGE_ARGUMENT_ARRAY,
                                  hModule, pELR->EventID, 0, (LPTSTR)&lpszBuffer, 1024, 
                                  _sz
                               );
    
                               for(z = 0; z < pELR->NumStrings; z++)
                               {
                                  SafeDeletePointer(_sz[z], strlen(_sz[z]));
                                  _sz[z] = 0;
                               }
                               SafeDeletePointer(_sz, (pELR->NumStrings) * sizeof(TCHAR *));
                               _sz = 0;
    
                               if(lpszBuffer)
                               {
                                  strcpy(szExpandedString, (TCHAR *)lpszBuffer);
                                  uStringOffset = strlen(szExpandedString);
                               }
    
                               if(lpszBuffer)
                                  LocalFree(lpszBuffer);
    
                               FreeLibrary(hModule);
                            }
                         }                  
                         RegCloseKey(hk);
                      }
    
                      SendMessage(hwndEditStrings, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)szExpandedString);
    
                      SafeDeletePointer(szExpandedString, strlen(szExpandedString));
                   }
    
                   {
                      TCHAR _str[1024];
                      _tcscpy(_str, _T(""));
                      if(pELR->DataLength > 0)
                      {
                         register UINT x;
    
                         for(x = 0; x < pELR->DataLength; x += 8)
                         {
                            TCHAR _strAux[1024];
                            register UINT y;
    
                            wsprintf(_strAux, "%.4x: ", x);
                            _tcscat(_str, _strAux);
    
                            for(y = x; y < x + 8; y++)
                            {
                               wsprintf(_strAux, "%.2x ", pData[y]);
                               _tcscat(_str, _strAux);
                            }
                            _tcscat(_str, _T("  "));
    
                            for(y = x; y < x + 8; y++)
                            {
                               if(!isprint((int)pData[y]))
                                  _tcscat(_str, _T("."));
                               else
                               {
                                  TCHAR s[2];
                                  s[0] = (TCHAR)pData[y];
                                  s[1] = '\0';
                                  _tcscat(_str, s);
                               }
                            }
                            _tcscat(_str, _T("\r\n"));
                         }
                      }
                      else
                         _tcscat(_str, _T("No data available."));
    
                      SendMessage(hwndEditData, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)_str);
                   }
                }
             }
    
             goto _cleanup_;
          }
          else
             ReportLastError(0, 0, TRUE);
    
    _unknownerror_:
          MessageBox(0, TEXT("Unknown error."), 0, MB_OK | MB_ICONSTOP);
          goto _cleanup_;
    
    _allocationfailure_:
          MessageBox(0, TEXT("Allocation failure."), 0, MB_OK | MB_ICONSTOP);
          goto _cleanup_;
    
    _cleanup_:
          CloseEventLog(hEventLog);
          hEventLog = 0;
       }
       else
          ReportLastError(0, 0, TRUE);
    
       #pragma warning(disable:4127)
       SafeDeletePointer(peid, sizeof(EVENTID));
    
       return 0L;
    }
    
    Although the string szExpandedString is allocated with only 1024 length (so can truncate sometimes thre REAL value), again you can easily replace with the correct size doing some checkings before. The construction key is now a registry key specific to the record entry, located under SYSTEM\CurrentControlSet\Sevices\EventLog key. If opening of this key succeeds and the call of ExpandEnvironmentStrings leads to the binary file where .mc message entry resides, then a LoadLibraryEx call with the DONT_RESOLVE_DLL_REFERENCES flag set (to do not load other DLLs, but rather resource section) will lead us to the necessary .mc resource entry, which is a entry in the message table (usually created with message compiler tool). Now, the call
       FormatMessage
       (
          FORMAT_MESSAGE_ALLOCATE_BUFFER | 
          FORMAT_MESSAGE_FROM_HMODULE | 
          FORMAT_MESSAGE_FROM_SYSTEM | 
          FORMAT_MESSAGE_ARGUMENT_ARRAY,
          hModule, 
          pELR->EventID, 
          0, 
          (LPTSTR)&lpszBuffer, 
          1024, 
          _sz
       );
    
    will offers us the message bound with this particular event log entry. The rest is history (hexa formatting, dialog stuff).

    License

    This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

    A list of licenses authors might use can be found here

    Share

    About the Author

    Sardaukar
    Web Developer
    Romania Romania
    No Biography provided

    Comments and Discussions

     
    QuestionHow do i detect the status of the hardware Pinmemberpaul100016-Sep-08 20:50 
    AnswerRe: How do i detect the status of the hardware PinmemberCristian Amarie11-Feb-09 6:43 
    QuestionHow to get Administration/User subscribe logging? PinmemberIngenious00131-Aug-07 2:23 
    Questionit's wrong, geting particular description of a record in windows vista Pinmemberraopeitao2-Aug-07 16:57 
    AnswerRe: it's wrong, geting particular description of a record in windows vista PinmemberCristian Amarie8-Sep-07 0:00 
    QuestionRegarding // CHAR Pad[] PinmemberAmit Papriwal22-Jul-07 23:56 
    AnswerRe: Regarding // CHAR Pad[] Pinmemberraopeitao2-Aug-07 17:12 
    GeneralVery cool :) PinmemberOddArne14-Oct-04 9:39 
    GeneralEvent loging on PDC Pinmembervijayv6-Feb-04 0:49 
    GeneralXP Pro PinmemberNeilDevlin6-Jun-03 7:05 
    Hi,
    Is there a way to getting it to run on XP pro?
    I cant open any windows when building the application.
     
    Neil
    GeneralRe: XP Pro PinmemberSardaukar21-Sep-03 19:59 
    GeneralThe RPC server is unavailable. PinmemberPravinu6-Jun-03 1:13 
    GeneralRe: The RPC server is unavailable. PinmemberSardaukar6-Jun-03 1:30 
    GeneralRe: The RPC server is unavailable. PinmemberPravinu8-Jun-03 22:31 
    GeneralRe: The RPC server is unavailable. PinmemberSardaukar9-Jun-03 2:41 
    GeneralReadEventLog: Invalid Parameter Pinmembermassel17-Feb-03 2:04 
    GeneralRe: ReadEventLog: Invalid Parameter Pinmembermassel19-Feb-03 3:18 
    GeneralRe: ReadEventLog: Invalid Parameter Pinmembermassel20-Feb-03 3:40 
    GeneralRe: ReadEventLog: Invalid Parameter PinmemberTClegg29-Jan-04 7:26 
    QuestionHot to get the description text of an event? PinmemberRalph6-Feb-03 0:57 
    AnswerRe: Hot to get the description text of an event? PinsussMaria Jose21-Sep-03 7:53 
    GeneralRe: Hot to get the description text of an event? Pinmembergino_d_animal11-Mar-04 4:06 
    GeneralRe: Hot to get the description text of an event? Pinmembergino_d_animal6-Apr-04 11:10 
    GeneralRe: Hot to get the description text of an event? PinsussBrooks Younce14-May-05 3:45 
    GeneralRe: Hot to get the description text of an event? PinmemberTorben_Surmer7-Nov-05 22:39 

    General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

    Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

    | Advertise | Privacy | Mobile
    Web03 | 2.8.140916.1 | Last Updated 1 Dec 1999
    Article Copyright 1999 by Sardaukar
    Everything else Copyright © CodeProject, 1999-2014
    Terms of Service
    Layout: fixed | fluid