0

I am trying to use the Windows Event Logging service and in struggle with RegisterEventSource owing to the insufficient/ambiguous description.

Let's assume "App1.exe" is the event source name that will be used from an application program App1.exe. And I will use my own custom event log subkey named "MyCustLog" under which "App1.exe" subkey will be created. So, my custom event log subkey for App1.exe will look like "... \MyCustLog\App1.exe" under which EventMessageFile/CategoryMessageFile/CategoryCount will be set as "App1.exe"/"App1.exe"/3, respectively.

Now, there happens and/or will happen to be another "App1.exe" event source name registered under a 3rd party custom event log key as shown below:

HKEY_LOCAL_MACHINE
   SYSTEM
      CurrentControlSet
         Services
            Eventlog
               Application
               Security
               System
               3rdPartyLog
                 App1.exe

After I create my own custom event log key it looks like:

HKEY_LOCAL_MACHINE
   SYSTEM
      CurrentControlSet
         Services
            Eventlog
               Application
               Security
               System
               3rdPartyLog
                 App1.exe
               MyCustLog
                 App1.exe

Now, I call RegisterEventSource follows:

HANDLE hEvtSrc = RegisterEventSource(0, "App1.exe");

=> returns an event log handle to hEvtSrc, but how can I be sure that the handle is returned for MyCustLog's App1.exe, not 3rdPartyLog's App1.exe?

What I have tried:

I tried the following:

HANDLE hEvtSrc2 = RegisterEventSource(0, "MyCustLog\\App1.exe");

=> this also successfully returns an event log handle but not sure if it is for MyCustLog's App1.exe, nonetheless. Moreover, an event fired by the following ReportEvent with this handle shows failure description in its property window from Windows Event Log Viewer.

CONST LPCTSTR pBadCommand = _T("The command that was not valid");
DWORD dwEventDataSize = ((DWORD)_tcslen(pBadCommand) + 1) * sizeof(TCHAR);
BOOL bRet = ReportEvent(hEventLog, EVENTLOG_ERROR_TYPE, UI_CATEGORY, MSG_INVALID_COMMAND, NULL, 0, dwEventDataSize, NULL, (LPVOID)pBadCommand);

The failure message says: The description for event id MSG_INVALID_COMMAND cannot be found from the source MyCustLog\App1.exe

I also tried the third way:

HANDLE hEvtSrc3 = RegisterEventSource(0, "MyCustLog/App1.exe");

=> this again successfully returns an event log handle, but still an event fired by ReportEvent with this handle shows the almost the same failure description in its property window from event viewer. The only difference in failure message is MyCustLog/App1.exe instead of MyCustLog\App1.exe.

Therefore, "MyCustLog\App1.exe" or "MyCustLog/App1.exe" cannot be used instead of "App1.exe" to get the right handle of my own for RegisterEventSource. So we are back to the square one again.

So, once again, how can I be sure the returned handle for RegisterEventSource(0, "App1.exe") is for MyCustLog\App1.exe, not for 3rdPartyLog\App1.exe?

Below is shown the .mc file in use for App1.exe. [Message file]

; // App1.mc 

; // This is the header section.


SeverityNames=(Success=0x0:STATUS_SEVERITY_SUCCESS
               Informational=0x1:STATUS_SEVERITY_INFORMATIONAL
               Warning=0x2:STATUS_SEVERITY_WARNING
               Error=0x3:STATUS_SEVERITY_ERROR
              )


FacilityNames=(System=0x0:FACILITY_SYSTEM
               Runtime=0x2:FACILITY_RUNTIME
               Stubs=0x3:FACILITY_STUBS
               Io=0x4:FACILITY_IO_ERROR_CODE
              )

LanguageNames=(English=0x409:MSG00409)


; // The following are the categories of events.

MessageIdTypedef=WORD

MessageId=0x1
SymbolicName=NETWORK_CATEGORY
Language=English
Network Events
.

MessageId=0x2
SymbolicName=DATABASE_CATEGORY
Language=English
Database Events
.

MessageId=0x3
SymbolicName=UI_CATEGORY
Language=English
UI Events
.


; // The following are the message definitions.

MessageIdTypedef=DWORD

MessageId=0x100
Severity=Error
Facility=Runtime
SymbolicName=MSG_INVALID_COMMAND
Language=English
The command is not valid.
.


MessageId=0x101
Severity=Error
Facility=System
SymbolicName=MSG_BAD_FILE_CONTENTS
Language=English
File %1 contains content that is not valid.
.

MessageId=0x102
Severity=Warning
Facility=System
SymbolicName=MSG_RETRIES
Language=English
There have been %1 retries with %2 success! Disconnect from
the server and try again later.
.

MessageId=0x103
Severity=Informational
Facility=System
SymbolicName=MSG_COMPUTE_CONVERSION
Language=English
%1 %%4096 = %2 %%4097. 
.


; // The following are the parameter strings */


MessageId=0x1000
Severity=Success
Facility=System
SymbolicName=QUARTS_UNITS
Language=English
quarts%0
.

MessageId=0x1001
Severity=Success
Facility=System
SymbolicName=GALLONS_UNITS
Language=English
gallons%0
.
HaeRim Lee
  • 53
  • 6

1 Answers1

0

If there are multiple App1.exe event sources, there is no way to tell RegisterEventSource() which source to use. RegisterEventSource() only accepts a source name, not a log name.

In fact, the Event Sources documentation says:

You cannot use a source name that has already been used as a log name. In addition, source names cannot be hierarchical; that is, they cannot contain the backslash character ("").

Which is why registering MyCustLog\App1.exe doesn't work, as it is an illegal source name. And why registering MyCustLog/App1.exe doesn't differentiate App1.exe between multiple logs, as / is not a hierarchy delimiter so RegisterEventSource() treats MyCustLog/App1.exe as the entire source name, not as App1.exe underneath MyCustLog.

So, since the source name for both logs is just App1.exe, you must use RegisterEventSource("App1.exe"), and so it will use the the first App1.exe it finds. And if it doesn't find any, it will fallback to using the Application log, which doesn't support category/message files.

So, make sure your event source is named uniquely. For instance, by NOT using your app's filename, but rather more descriptive names, eg:

HKEY_LOCAL_MACHINE
   SYSTEM
      CurrentControlSet
         Services
            Eventlog
               My Custom Log
                  My Custom App Name

You can point My Custom App Name to the actual App1.exe file in its EventMessageFile/CategoryMessageFile values as needed.

And then you can use RegisterEventSource("My Custom App Name").

You should have a look at your local Registry to see how other apps register their event sources. It is actually rare for filenames to be used as key names. For example, here is what is registered in the eventlog key on my local system. As you can see, none of the log keys or app keys use filenames for their names:

event sources

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Thank you for your detail answer. However, I have my own reasons to use the executable file name as a source name and to avoid using backslash, I replace all back slashes to forward slashes. So the actual registry looks like: HKEY_LOCAL_MACHINE SYSTEM CurrentControlSet Services Eventlog Application Security System MyCustLog C/:App1.exe – HaeRim Lee Nov 16 '21 at 19:00
  • You cannot use a source name that has already been used as a log name. => Here a log name means a source name? => So, App1.exe cannot be used for both MyCustLog and 3rdPartyLog at the same time? => In such case, which one will be chosen among the MyCustLog and 3rdPartyLog? – HaeRim Lee Nov 16 '21 at 19:08
  • I would have to check what happens if you use `C/:App1.exe` as the source name. But it would be very easy for you to validate this yourself. Simply configure `MyCustLog` to save to its own log file, and then see whether `ReportEvent()` writes to your log file or to the `Application` log file when using `RegisterEventSource()` with `App1.exe` vs `C/:App1.exe` vs `MyCustLog\C/:App1.exe`, and then you can add a custom `3rdPartyLog` with its own log file and repeat the test. But, I *strongly* urge you to use more unique source names to avoid this dilemna in the first place. – Remy Lebeau Nov 16 '21 at 19:44
  • After setting HKLM\...\EventLog\MyCustLog\C:/App1.exe as my source subkey, and then calling h=RegisterEventSource(0, "C:/App1.exe") and ReportEvent(h, ..., EVT_ID, ...) resulted in adding an event log entry under Applications & Services-MyCustLog pane, but not under Applications pane. Note that I have tested this with MyCustLog alone, that is, without 3rdPartyLog custom key and its source name with "C:/App1.exe". – HaeRim Lee Nov 16 '21 at 21:41
  • Next, After setting HKLM\...\EventLog\MyCustLog\C:/App1.exe as my source subkey, and then calling h=RegisterEventSource(0, "MYcUSTlOG\\C:/App1.exe") and ReportEvent(h, ..., EVT_ID, ...) resulted in adding an event log entry under Applications pane, not under Applications & Services-MyCustLog pane. But this time the log entry description shows a message to fail to find the description from MyCustLog\C:/App1.exe source. Not that I have tested this with MyCustLog alone, not together with 3rdPartyLog custom key and its source name with "C:/App1.exe". – HaeRim Lee Nov 16 '21 at 21:44
  • "*calling `h=RegisterEventSource(0, "MYcUSTlOG\\C:/App1.exe")`*" - that is not legal. The documentation is very clear that you can't use ```\``` in event source names. "*ReportEvent() resulted in adding an event log entry under Applications pane*"- makes sense, since you used an illegal source name, so it fell back to the `Application` log. "*the log entry description shows a message to fail to find the description from MyCustLog\C:/App1.exe source*" - yes, because that is not a legal source, and the `Application` log doesn't support descriptions, like the documentation clearly says. – Remy Lebeau Nov 16 '21 at 21:49
  • Finally, after setting HKLM\...\EventLog\MyCustLog\C:/App1.exe as my source subkey, and then calling h=RegisterEventSource(0, "MYcUSTlOG/C:/App1.exe") and ReportEvent(h, ..., EVT_ID, ...) resulted in adding an event log entry under Applications pane, not under Applications & Services-MyCustLog pane. But this time the log entry description shows a message to fail to find the description from MyCustLog/C:/App1.exe source. It only differs in using '\' or '/'. Note that I have tested this with MyCustLog alone, not together with 3rdPartyLog custom key and its source name with "C:/App1.exe". – HaeRim Lee Nov 16 '21 at 21:55
  • My next test would be testing the same with 3rdPartyLog added. It will need a bit of time to prepare. In the mean time, what results would you expect in this case? – HaeRim Lee Nov 16 '21 at 21:59
  • "*calling `h=RegisterEventSource(0, "MYcUSTlOG/C:/App1.exe")` and `ReportEvent()` resulted in adding an event log entry under Applications pan*" - makes sense, since the log name is `MYcUSTlOG` and the source name is only `C:/App1.exe`, and `RegisterEventSource()` only accepts a source name. So this goes right back to my original answer, that the issue of having multiple logs with the same source name causes `RegisterEventSource()` to randomly pick one or the other, you can't tell it which one to use. And since it can't find a source named `MYcUSTlOG/C:/App1.exe`, it fell back to `Application` – Remy Lebeau Nov 16 '21 at 22:02
  • Your keys are hierarchical, a source named `C:/App1.exe` underneath a log named `MYcUSTlOG`, but `/` is not a hierarchy delimiter in this situation, so `MYcUSTlOG/C:/App1.exe` is treated as the entire source name, which doesn't exist. – Remy Lebeau Nov 16 '21 at 22:06
  • RegisterEventSource() only accepts a source name => interesting fact that I didn't know and never seen it anywhere. Can you tell me where this is written? – HaeRim Lee Nov 16 '21 at 22:16
  • It is not explicitly written as such, but it is pretty clear that is what is happening based on your test results, and a decent interpretation of the documentation. – Remy Lebeau Nov 16 '21 at 22:19
  • that the issue of having multiple logs with the same source name causes RegisterEventSource() to randomly pick one or the other, => Also I'd like to see where this documentation is written if any. – HaeRim Lee Nov 16 '21 at 22:21
  • I have another question about the "EventMessageFile" value names location in the registry key name. For example, Chrome under Application has EventMessageFile Valuename right under Chrome subkey, while Windows PowerShell has it under one lower level, that is under under 'Windows PowerShell\PowerShell' subkey. My question is this: Will RegisterEventSource search through all the deepest levels until it finds EventMessageFile valuename? Neither MSDN nor internet tells anyting about this. – HaeRim Lee Nov 16 '21 at 23:21
  • "*I'd like to see where this documentation is written if any*" - I already said it is not documented, not explicitly anyway. You kind of have to infer the behavior – Remy Lebeau Nov 16 '21 at 23:27
  • Another question about the "EventMessageFile" value names in the registry. For example, Chrome has EventMessageFile Valuename right under Chrome subkey, while Windows PowerShell has it under one lower level, that is under 'Windows PowerShell\PowerShell' subkey. My question is this: Will RegisterEventSource search through all the deepest levels until it finds the first EventMessageFile valuename? What if there exist multiple EventMessageFile valuenames under the same log? Will it search depth first or width first? Neither MSDN nor internet tells anything about this. – HaeRim Lee Nov 16 '21 at 23:29
  • I've answered those questions [here](https://stackoverflow.com/questions/69997319/). – Remy Lebeau Nov 16 '21 at 23:43