IPropertyStore interface not called in a property handler - windows

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!

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).

How to make a Finder Sync Extension change badges in response to outside events

I have a Finder Sync Extension that will display a badge on a file based on the state of a local database. It's straightforward enough to query this database in the requestBadgeIdentifierForURL function, but what if I want the badge to change for a Finder item that's already visible if the state of that database has changed (which can be via a notification through any variety of mechanisms). The documentation (https://developer.apple.com/library/content/documentation/General/Conceptual/ExtensibilityPG/Finder.html) would seem to imply this is possible with this statement:
You might also want to track these URLs, in order to update their
badges whenever their state changes.
The only ways I can imagine this would be possible (and most seem wrong) would be:
call setBadgeIdentifier:forURL from another application that is aware of the change
Launch a thread in the init function of my extension which listens for notifications and calls setBadgeIdentifier:forURL when it receives them
Call some OS API that prompts Finder that the extension should be triggered via requestBadgeIdentifierForURL.
Only the last one seems feasible, and could be managed via the extension informing the outside resource what needs refreshing via the beginObservingDirectoryAtURL/endObservingDirectoryAtURL callbacks, but i don't know what mechanism could do this.

Getting a notification when a local file is accessed in windows

I'd like to get notified when a specific file get accessed (AFAIK, most generally for a Userland code - by CreateFile() / NtCreateFile())
I already know about FileSystemWatcher which should do the same within the .NET environment, But I'm working in plain C + WinAPI.
As for the type of notification , raising a specified Event would be perfect, but sending a callback to be called , will also work.
See FindFirstChangeNotification function in WinAPI and related links.
Alternatively, when functionality of that function is not enough, you can use a filesystem filter driver (write yours or use our CallbackFilter product).

FSEvents weirdness on OS X Leopard

I want to monitor file-system events for a couple of directories on the mac. The directories I want to monitor might change at runtime, so using FSEvents here's what my app does:
creates a global callback function to handle callbacks
create a new FSEventStreamRef per folder, associating it with the callback created above and adding a context to the eventStream that helps me associate the change callback with this folder
Stuff seems to mostly work, but I've noticed some weirdness in when the callbacks are invoked and the 'eventPaths' values being sent to the callback.
For instance, if I've created StreamRefs for /Foo and /Bar, if I add a file in /Bar my callback is invoked almost immediately but the eventPaths points to a location in /Foo, and the context I associated with the StreamRef is also that of /Foo.
Or, say I'm monitoring /Foo and /Bar and then remove /Bar (by stopping and closing the StreamRef for /Bar correctly). I now create a new FSEventStreamRef for /Fee and associate with the same callback. Any changes I make to /Fee don't cause the callback to be invoked but changes to /Foo continue raising the callback.
Any example or documentation I've seen online only talks of monitoring a single folder. Is something busted with how I'm associating the single callbacks with multiple FSEventStreamRefs? It sounds like that shouldn't be a problem though...
Has anyone done something similar in a way that works reliably, or any suggestions for what I might try differently?
One thing I did attempt to do as I was experimenting with this is use a single FSEventStreamRef and pass it a CFArrayRef with all the paths I wanted, and when my watch list changes close and re-create a new FSEventStreamRef - this works even worse that the above.
Works for me. I emulated these characteristics:
One path per stream
One context per path/stream
One callback for all streams
Can you show the code that's failing?

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