Supplemental Registrations (aka. Context Menu Handers (etc) - where are they loaded from...)

I've been thinking about the registration problem where you want to add a context menu (much of this applies to static verbs as well) to a file type (we'll say .ogg).  You don't want the default verb, you just want to add some verbs.  Because you don't want the default, you shouldn't put your progid in the HKCR\.ogg default value, so you put an entry under HKCR\.ogg\shellex\ContextMenuHandler.  And this works great.. until someone comes along and puts a progid in HKCR\.ogg's default value.  Look at the fallthrough logic below - #2 (where we registered), and #3 are only used if there is no progid! 

Fallthrough logic when loading context menu handlers (static verbs and then context menu handlers are collected from the following places):

(DO NOT USE THIS LOGIC IN YOUR CODE - it is a simplification of the real logic and it will change. Instead, use IQueryAssociations or AssocQuery* for all these kinds of file association related things.)

  1. HKCR\<ProgID>
  2. HKCR\<.ext> (only if #1 does not exist)
  3. HKCR\Unknown (only if #1 does not exist)
  4. HKCR\SystemFileAssociations\<.ext>
  5. HKCR\SystemFileAssociations\<PerceivedType>
  6. HKCR\Folder (only used if the selected item has the SFGAO_FOLDER attribute, such as a folder, zip, cab, etc.)
  7. HKCR\*
  8. HKCR\AllFilesystemObjects

But there is a way!  You can register supplemental verbs associated with the SystemFileAssociations key.  Note that those keys (#4 and #5) are folded in regardless of the association having a progid registered.  In our example, that would be HKCR\SystemFileAssociations\.ogg\shellex\ContextMenuHandler

The important thing here is that you should never put the registration under HKCR\<.ext>(!) because you should either be putting it under your progid (#1), or in SystemFileAssociations (#4).  Why do we disable #2 and #3 in those cases?  If folks are interested, I'll talk more about that later - or feel free to guess. :)

(A quick comment about #5 - I think it is often misused.  Applications don't know how to handle very many perceived types (one exception is text).  How are you going to handle the "video" perceived type?  I guarantee that we'll come out with more codecs/container formats, etc.  Unless you can guarantee that you can handle everything that will map into the perceived type, don't register for it - instead register for the individual associations that you really can handle.)

This technique is used for a lot of other things besides context menu handlers.  It's also used for Property Handlers for Windows Search, Windows Imaging Component codecs, etc, etc, etc.


[Update: finished the sentence beginning "In our example, that would be..."]