Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Windows: ReportEvent function

As far as I understood, the ReportEvent function requires Message Text Files associated through the registry to receive properly formatted messages. Is there any common Event Ids or any simple way to report an event with no Message Text Files associated?

Or may be, is there special common Event Source which I can use in my application? Something like RegisterEventSource(NULL, "Application")?

like image 523
Sergey Shandar Avatar asked Mar 22 '11 23:03

Sergey Shandar


1 Answers

You don't have to register your messages in HKLM. (Which is a good thing, because you can't register messages if you're not an administrator).

But that doesn't stop you from writing events to the Windows Application event log. The only downside is that starting with Windows Vista you'll just get some ugly text along with it.

HRESULT LogToEventLog(String Source, String EventText, int EventType, DWORD EventID)
{
   /*
      EventType is one of:
         EVENTLOG_ERROR_TYPE       = $0001;
         EVENTLOG_WARNING_TYPE     = $0002;
         EVENTLOG_INFORMATION_TYPE = $0004;
         EVENTLOG_AUDIT_SUCCESS    = $0008;
         EVENTLOG_AUDIT_FAILURE    = $0010;

      Source is your name for your app or feature, e.g.:
         "My Cool App"
         "Outlook"    
         "ESENT"
         "Chrome"
   */

   HANDLE h = RegisterEventSource(null, Source); //null --> local computer
   if (h == 0) 
      return HResultFromWin32(GetLastError);
   try
   {       
      PChar[1] ss;
      ss[0] = PChar(EventText);

      if (!ReportEvent(
            h,         // event log handle
            EventType, // event type
            0,         // category zero
            EventID,   // event identifier
            null,      // no user security identifier
            1,         // one substitution string
            0,         // no data
            @ss,       // pointer to string array
            null       // pointer to data
      ))
      {
         return HResultFromWin32(GetLastError);
      }
   }
   finally
   {
      DeregisterEventSource(h);
   }
   return S_OK;
}

And so now you can log events to the Application event log:

LogToEventLog("Stackoverflow", "Question 5399066 was answered by Ian Boyd", 
      EVENTLOG_INFORMATION_TYPE, 0x45);

Steal someone else's registration

Unfortunately, starting with Windows Vista, Windows will give ugly complaints that you didn't register the event beforehand:

The description for Event ID 69 from source Stackoverflow cannot be found. Either the component that raises this event is not installed on your local computer or the installation is corrupted. You can install or repair the component on the local computer.

If the event originated on another computer, the display information had to be saved with the event.

The following information was included with the event:

Question 5399066 was answered by Ian Boyd

But you don't have to live with it. Just because you didn't register an message source file in HKLM, doesn't mean nobody else did.

Notice, for example, a message from the Outlook source in the Event log:

  • Source: Outlook
  • EventID: 0x40000020
  • Event Data: D:\win32app\Exchange\Outlook2003.pst
  • Message: The store D:\win32app\Exchange\Outlook2003.pst has detected a catalog checkpoint.

You can check registration information for Outlook in:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\Application\Outlook

And see:

MessageEventFile: REG_SZ = "D:\Programs\MICROS~4\Office14\1033\MAPIR.DLL"

If you peek into the resources of MAPIR.dll binary, you'll see its Message Table:

1 MESSAGETABLE
{
0x12,       "Connection stats for server (%1).  Rpcs Attempted (%2), Rpcs Succeeded (%3), Rpcs Failed (%4), Rpcs Canceled (%5), Rpc UI shown (%6), Avg request time (%7) ms, Min request time (%8) ms, Max request time (%9) ms.\r\n"
0x14,       "Cancelable RPC started.\r\n"
0x15,       "Cancelable RPC shutdown.\r\n"
0x40000010,     "Cancelable RPC dialog shown for server (%1), total wait time was (%2) ms, result was (%3).\r\n"
0x40000011,     "User canceled request against server (%1) after waiting (%2) ms.\r\n"
0x40000013,     "Rpc call (%1) on transport (%2) to server (%3) failed with error code (%4) after waiting (%5) ms; eeInfo (%6).\r\n"
0x40000016,     "There was a problem reading one or more of your reminders. Some reminders may not appear.\r\n"
0x40000017,     "Unable to update public free/busy data.\r\n"
0x4000001A,     "%1\r\n"
0x4000001B,     "%1\r\n"
0x4000001D,     "The store %1 is being re-pushed to the indexer for the following reason: %2.\r\n"
0x4000001E,     "Starting reconciliation for the store %1 for the following reason: %2.\r\n"
0x4000001F,     "The store %1 has detected a catalog rebuild.\r\n"
0x40000020,     "The store %1 has detected a catalog checkpoint.\r\n"
...
}

You can see that eventid 0x40000020 is assocated with a formatting string:

"The store %1 has detected a catalog checkpoint.\r\n"

You can hijack Outlook's registration:

LogToEventLog("Outlook", "Your mom", EVENTLOG_INFORMATION_TYPE, $40000020);

and you'll get your event added to the event log without all the ugly warnings:

enter image description here

like image 198
Ian Boyd Avatar answered Sep 26 '22 16:09

Ian Boyd