EventCreate.exe creates a "CustomSource" value, what does it mean? - winapi

The command-line EventCreate.exe tool registers a user-defined event source in the Registry for the Windows Event Log Viewer to use, like this:
eventcreate /t INFORMATION /ID 100 /L "Application" /SO [SourceName] /D "Description"
I wrote an app that has its own Event Log resource strings and is registered as an event source, per MSDN, but it doesn't use the CustomSource value and works fine.
I can't find any documentation on MSDN, or elsewhere online, on what CustomSource is meant for exactly. None of the registered sources on my machines use it.
Does anyone know what CustomSource is meant for, and how it works? Is it just something internal to EventCreate.exe, or does the Windows Event Log actually use it for something?

Thanks to #RbMm for pointing out this blog article:
EventCreate and "ERROR: Source parameter is used to identify custom applications/scripts only"
For whatever reason, EventCreate was designed only to log events that are associated with event log sources that EventCreate created.  It does this by adding a REG_DWORD value called CustomSource in the source's registry key when it creates a new source, and checking for that value for a source that already exists.  So in the above example, if the "MyStuff" source didn't already exist in the Application log, the above command would have created it and configured its key with a CustomSource value.  Subsequent calls to EventCreate with the same source would succeed after verifying the existence of the CustomSource value.  If, however, the "MyStuff" source had been created through another mechanism that didn't create a CustomSource flag, such as with the PowerShell New-EventLog cmdlet, then you'd get the error message.  If you create a CustomSource value in an event source's key, then EventCreate will work with that source.

Related

xperf -providers doesn't show the name of TraceLoggingProvider defined by TRACELOGGING_DEFINE_PROVIDER

I follow the tutorial to set up a TraceLoggingProvider in my application.
During the application runs, I try to use xperf -providers to see if my user event provider is there:
I cannot see the name I defined in TRACELOGGING_DEFINE_PROVIDER but only the defined GUID is shown. Is it intended?
Instead following another tutorial with WPRP file, I just use xperf -start to capture events. And the same: I can only use GUID as parameter, not the defined name! is it also intended?
Anyway, at the end I can view the result properly in WPA and the defined name of my user event provider is visible.
are all my observaton intended?
The name you use in the C++ code is unrelated to the display name on your pc.
You'd have a displayed name (instead of GUID) if this was a manifested installed provider, but TraceLogging isn't manifested (at least, not in the classical sense - an impromptu manifest is embedded into the image, and sent in the messages).

IPropertyStore interface not called in a property handler

I am developing a property handler implementing IPropertyStore and IInitializeWithFile, testing on Win 8.1 x64. Property names were previously added to the system using a .propdesc file properly registered using prop.exe.
I used PROCMON.EXE to monitor the events when I re-indexed my files on disk. SearchPrototocolHost.exe loads the protocol handler, initializes it properly with IInitializeWithFile (the properties from the file seem to load OK from the file) then proceeds with PSCreatePropertyStoreFromObject presumably to retrieve the IPropertyStore interface and start retrieving the properties from the file.
Then nothing else happens, the methods from IPropertyStore are never called. Instead, SearchPrototocolHost.exe issues a CreateFile on the file to be indexed again with "Open Reparse Point", fails at getting a QueryRemoteProtocolInformation, closes the file then proceed with the next file to index.
Why does my property handler fail (is it a security issue, etc.?)?
It looks like one needs to add to the registry entry:
"HKLM" "SOFTWARE\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved" {My_CLSID}
where My_CLSID is the GUID of my property handler!
I don't know if this is a specific requirement for handlers using IInitializeWithFile as an extra security precaution.
After three weeks of banging my head against walls, now I can "hear" the IPropertyStore methods (using MessageBeep...) when they are called by Explorer. Never mind that they crash Explorer, at least I know that IPropertyStore is not blocked!

How exactly do I config DCOM to load my DLL into a separate process?

I'm trying to force an existing native C++ ATL in-proc COM server into a separate process. I hope DCOM can do this for me without changing the COM server.
I started with a usual registry setup - I have a HKCR\CLSID{classId} entry and an InProcServer32 key there specifying the path to the .dll file.
I generated an application id (GUID) and added it here and there. Specifically I added a string value "AppId" under HKCR\CLSID{classId} equal to the application id. I also added a HKCR\AppId{applicationId} key and a string value "DllSurrogate" equal to an empty string. I thought it would be enough for forcing my COM server into a default system-provided surrogate.
The DCOM application appears in the DCOM configuration console. However when I call CoCreateInstance() or CoGetClassObject() and provide the class id and CLSCTX_LOCAL_SERVER it returns "Class not registered". What am I doing wrong?
UPD: Resolved. The steps taken were enough to make it work except that I was editing the registry for the wrong class id that for some reason had the same path under InProcServer32 key - perhaps that was a COM hell issue.
Follow the check list:
There must be an AppID value specified under the CLSID key in the registry, and a corresponding AppID key. (checked)
In an activation call, the CLSCTX_LOCAL_SERVER bit is set and the CLSID key does not specify LocalServer32, LocalServer, or LocalService. (checked)
The CLSID key contains the InprocServer32 subkey. (checked)
The proxy/stub DLL specified in the InprocServer32 key exists. ???
The DllSurrogate value exists under the AppID key. (checked)
wrong registry key. you need to set LocalServer32, not InProcServer32 in HKCR\CLSID{classId}.
However, windows cannot instantiate a DLL. So you need to change your program into a full COM server exe. Windows will start your EXE and send in the argument /embedding. You can then create the CComModule and start your program.
Isn't this what DLLHOST.EXE was made for?

How can I fix this Event Log problem?

I keep getting the following event log descriptions for "svcListener" and "svcListener - Prof" in my Event log. Does anyone know where this comes from and how I can fix this?
svcListener
The description for Event ID ( 0 ) in Source ( svcListener ) cannot be found.
The local computer may not have the necessary registry information or message DLL files to display messages from a remote computer.
You may be able to use the /AUXSOURCE= flag to retrieve this description; see Help and Support for details.
The following information is part of the event: Cannot perform this operation on a closed dataset.
svcListener - Prof
The description for Event ID ( 0 ) in Source ( svcListener- Prof ) cannot be found.
The local computer may not have the necessary registry information or message DLL files to display messages from a remote computer.
You may be able to use the /AUXSOURCE= flag to retrieve this description; see Help and Support for details.
The following information is part of the event: Exception in Oracle Connection- 12560 EOracleEr
It looks like svcListener and svcListener-Prof are trying to write to the event log using an Event Source that does not exist. (or they do not have permissions to create it)
In code, you would do something like this before writing to the event log:
if(!EventLog.SourceExists("myService")){EventLog.CreateEventSource("myService","Application");}
And you would make sure that the first time "svcListener" ran, it had the permissions necessary to create the Event Source.
To fix it, you can create the source yourself. Just write a short program to do it, like the above, and run it just once from an Admin account.

Launching a registered mime helper application

I used to be able to launch a locally installed helper application by registering a given mime-type in the Windows registry. This enabled me to allow users to be able to click once on a link to the current install of our internal browser application. This worked fine in Internet Explorer 5 (most of the time) and Firefox but now does not work in Internet Explorer 7.
The filename passed to my shell/open/command is not the full physical path to the downloaded install package. The path parameter I am handed by IE is
"C:\Document and Settings\chq-tomc\Local Settings\Temporary Internet Files\
EIPortal_DEV_2_0_5_4[1].expd"
This unfortunately does not resolve to the physical file when calling FileExists() or when attempting to create a TFileStream object.
The physical path is missing the Internet Explorer hidden caching sub-directory for Temporary Internet Files of "Content.IE5\ALBKHO3Q" whose absolute path would be expressed as
"C:\Document and Settings\chq-tomc\Local Settings\Temporary Internet Files\
Content.IE5\ALBKHO3Q\EIPortal_DEV_2_0_5_4[1].expd"
Yes, the sub-directories are randomly generated by IE and that should not be a concern so long as IE passes the full path to my helper application, which it unfortunately is not doing.
Installation of the mime helper application is not a concern. It is installed/updated by a global login script for all 10,000+ users worldwide. The mime helper is only invoked when the user clicks on an internal web page with a link to an installation of our Desktop browser application. That install is served back with a mime-type of "application/x-expeditors". The registration of the ".expd" / "application/x-expeditors" mime-type looks like this.
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\.expd]
#="ExpeditorsInstaller"
"Content Type"="application/x-expeditors"
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\ExpeditorsInstaller]
"EditFlags"=hex:00,00,01,00
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\ExpeditorsInstaller\shell]
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\ExpeditorsInstaller\shell\open]
#=""
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\ExpeditorsInstaller\shell\open\command]
#="\"C:\\projects\\desktop2\\WebInstaller\\WebInstaller.exe\" \"%1\""
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\MIME\Database\Content Type\application/x-expeditors]
"Extension"=".expd"
I had considered enumerating all of a user's IE cache entries but I would be concerned with how long it may take to examine them all or that I may end up finding an older cache entry before the current entry I am looking for. However, the bracketed filename suffix "[n]" may be the unique key.
I have tried wininet method GetUrlCacheEntryInfo but that requires the URL, not the virtual path handed over by IE.
My hope is that there is a Shell function that given a virtual path will hand back the physical path.
I believe the sub-directories created by IE are randomly generated, so you won't be able guarantee that it will be named the same every time, and the problem I see with the registry method is that it only works when the file is still in the cache...emptying the cache would purge the file requiring yet another installation.
Would it not be better to install this helper into application data?
I'm not sure about this but perhaps this may lead you in the right direction: try using URL cache functions from the wininet DLL: FindFirstUrlCacheEntry, FindNextUrlCacheEntry, FindCloseUrlCache for enumeration and when you locate an entry whose local file name matches the given path maybe you can use RetrieveUrlCacheEntryFile to retrieve the file.
I am using a similar system with the X-Appl browser to display WAML web applications and it works perfectly. Maybe you should have a look at how they managed to do it.
It looks like iexplore is passing the shell namespace "name" of the file rather than the filesystem name.
I dont think there is a documented way to be passed a shell item id on the command line - explorer does it to itself, but there are marshaling considerations as shell item ids are (pointers to) binary data structures that are only valid in a single process.
What I might try doing is:
1. Call SHGetDesktopFolder which will return the root IShellFolder object of the shell namespace.
2. Call the IShellFolder::ParseDisplayName to turn the name you are given back into a shell item id list.
3. Try the IShellFolder::GetDisplayNameOF with the SHGDN_FORPARSING flag - which, frankly, feels like w'eve just gone in a complete circle and are back where we started. Because I think its this API thats ultimately responsible for returning the "wrong" filesystem relative path.
Some follow-up to close out this question.
Turned out the real issue was how I was creating the file handle using TFileStream. I changed to open with fmOpenRead or fmShareDenyWrite which solved what turned out to be a file locking issue.
srcFile := TFileStream.Create(physicalFilename, fmOpenRead or fmShareDenyWrite);

Resources