0

I'm trying to implement a shell namespace extension, for the sole purpose of overriding the thumbnail handler (IExtractImage) in a specific folder. I want everything else to be the same as in a normal folder, and I'd rather not have to reimplement everything that is done in the default implementation of IShellFolder...

So, is it possible to inherit from this default implementation? If so, how?

Using composition would also be an acceptable solution, but how can I get an instance of the class for a given folder?

Thomas Levesque
  • 286,951
  • 70
  • 623
  • 758
  • 1
    You need to obtain default implementation interface pointer, and then in your implementation of the interface you forward all method calls except the one you are altering behavior for. [To retrieve a pointer to a namespace object's IShellFolder interface, you must...](http://msdn.microsoft.com/en-us/library/windows/desktop/bb776885%28v=vs.85%29.aspx) – Roman R. Dec 03 '14 at 10:54
  • Register an IThumbnailProvider for your filetype? – patthoyts Dec 03 '14 at 11:10
  • @patthoyts, no, it won't work for me; that's why I have to create a namespace extension (see [this question](http://stackoverflow.com/questions/26933625/register-a-thumbnail-handler-for-a-folder-rather-than-a-specific-file-type) for more details) – Thomas Levesque Dec 03 '14 at 12:54
  • @RomanR., yes, that's what I meant by "composition". But I'm still working out how to get an instance of the default `IShellFolder` implementation for my folder. Apparently the relevant class is "Shell File System Folder" (CLSID `{F3364BA0-65B9-11CE-A9BA-00AA004AE837}`). – Thomas Levesque Dec 03 '14 at 12:56
  • You seem to start from CLSID, while MSDN article (see link above) suggests to start with `SHGetDesktopFolder` or `SHGetFolderLocation`. – Roman R. Dec 03 '14 at 13:01
  • @RomanR., yes, that's what I'm doing; I just noted which class I was getting when I called `BindObject` on the desktop `IShellFolder` – Thomas Levesque Dec 03 '14 at 13:03
  • IMHO it's almost impossible to do. It would be a huge task, the shell is very undocumented, and it changes all the time from Windows version to Windows version. I understand it's not a cool answer :-) – Simon Mourier Dec 04 '14 at 09:12

1 Answers1

3

1) There many shell extensions which can request your files content. For example .ico-file icon handler. Also user can install for example info tip extension which shows ID3 tag from mp3 file and it requests file content too. User can setup additional columns in detail view and some of them request file content. So you must control a lot of details in your shell name space extension.

2) To create a default implementation just call CoCreateInstance(CLSID_ShellFileSystemFolder, nil, CLSCTX_INPROC_SERVER, IID_IShellFolder, ShellFolder).

3) There is a problem. For example:

  1. Shell queries unknown IShellFolder3 from your NSE.
  2. Your NSE does not implement IShellFolder3 and NSE queries IShellFolder3 from default implementation and returns the result.
  3. Shell call IShellFolder3.GetUIObject with IID_IExtractImage and default IShellFolder3 will return installed thumbnail handler.

Also such methods can lead to AV inside Explorer (from my practice).

So I believe that your NSE must implement all known interfaces implemented by default implementation. If you don`t want to change behavior of method just pass the parameters to default implementation. Known (by me) interfaces: IBrowserFrameOptions, IOleCommandTarget, IPersist, IPersistIDList, IPersistFolder, IPersistFolder2, IPersistFolder3, IParentAndItem, IShellFolder, IShellFolder2, IObjectWithFolderEnumMode, IShellDetails, IShellFolderViewCB, IFolderFilter, INameSpaceTreeControlFolderCapabilities, IShellIcon, IShellIconOverlay, IFolderType, IFolderViewSettings, IExplorerPaneVisibility, IPropertyStoreFactory, IPropertyStore, IItemNameLimits, IThumbnailFactory.

4) As i understand you must control requests of following interfaces: IDataObject, IDropTarget, IExtractIconA(W), IExtractImage, IPropertyStore, IPropertyStoreFactory, IShellFolder(2), IQueryInfo.

5) IShellIcon.GetIconOf must return default icon of extension.

6) Also if your folder contains subfolders don`t forget to return your implementation when shell requests IShellFolder(2) of subfolder.

Denis Anisimov
  • 3,297
  • 1
  • 10
  • 18
  • 1
    It is hard only at beginning. – Denis Anisimov Dec 03 '14 at 16:21
  • OK, the basic principle seems to work... The main thing I was missing was how to create an instance of ShellFileSystemFolder (I'm not familiar at all with COM). Now I have to implement all those interfaces ;) – Thomas Levesque Dec 04 '14 at 13:56
  • Some of the interfaces you mention don't seem to be implemented by `ShellFSFolder`; should I implement them somewhere else, perhaps in a class returned by `BindToObject` or `GetUIObjectOf`? – Thomas Levesque Dec 05 '14 at 10:55
  • What interfaces do you mean? – Denis Anisimov Dec 05 '14 at 12:21
  • IBrowserFrameOptions, IPersistIDList, IObjectWithFolderEnumMode, IShellDetails, IShellFolderViewCB, IFolderFilter, IFolderViewSettings, IPropertyStoreFactory, IPropertyStore, IExtractIconA/W are not implemented in ShellFSFolder. Also, I can't find anything about IFolderType; it doesn't seem to exist anywhere. – Thomas Levesque Dec 05 '14 at 13:08
  • I copied list of interfaces from my NSE so just ignore them. IFolderType - http://www.geoffchappell.com/studies/windows/shell/shell32/interfaces/ifoldertype.htm. IPropertyStoreFactory, IPropertyStore, IExtractIconA/W can be queried throw BindToObject, BindToStorage or GetUIObjectOf. – Denis Anisimov Dec 05 '14 at 17:11
  • OK, thanks. I had checked by calling `QueryInterface` on ShellFSFolder for each interface, and it returned E_NOINTERFACE for the ones I mentioned. – Thomas Levesque Dec 05 '14 at 18:01
  • I forgot about very important interface IObjectWithSite. Please check it too. – Denis Anisimov Dec 11 '14 at 08:10
  • Thanks! I'll have a look – Thomas Levesque Dec 11 '14 at 09:54