Free Associations

A historical perspective for current events.

  • How do explorer context menus sort verbs?

    Windows Explorer has a default implementation for IContextMenu commonly called DefCM that has been used since Win95. It has many clients and has evolved over time, of course, but its primary focus has always been to support the most important of shell folders: File System Folder. A big part of this support revolves around extensibility. Raymond has been talking about hosting IContextMenu, I am going to talk about how IContextMenu extensions interact with DefCM. And while I may call out the behavior of older versions of Windows to explain things, I am going to focus on the behavior of WinXP.

    The first thing to read is Verbs and File Associations on MSDN. The section on "Static vs. Dynamic Verbs" explains that there are really two extensibility methods. this is important since they will be aggregated together by DefCM.  DefCM enumerates verbs from a set of registry hkeys typically generated from file associations. For more details about these keys look here.

    DefCM starts by gathering all of the IContextMenu extensions which are registered under the "shellex\contextmenuhandlers" subkeys. There is also one implicit object for file associations that handles static verb registration which is added first. The result of this enumeration is an array of objects starting with the static verb implementation, followed by each of the registered ContextMenuHandlers in order of the keys above.  Handlers that are registered under two keys are pruned to a single entry.

    In order to get the expected menu order, DefCM calls QueryContextMenu() on each of these objects to insert verbs in reverse order, and has each one insert at the top of the menu (zeroth position). As a result the static verbs are inserted last and end up at the top, which is good since usually these guys are the default.

    So the sorting is based on the following elements in decision order:

    1. Key priority (eg, txtfile, *, AFSO)
    2. Registry Enumeration order of shellex\contextmenuhandlers with a special case for static verbs always being first
    3. IContextMenu Implementation order

    So if there is any contention for position, there is no consistent way for an extension to guarantee their relative position within the menu.

  • The Bizarre and Unhappy Story of 'file:' URLs

    For my first blog entry, I will start with something I wrote for my team back in 1997 (reedited for this blog) that has been helpful to generations of subsequently bewildered developers:

    Go back to 1995 and a small team dreaming an impossible dream of the Internet on Windows!  URLs were young, so young they still hadn't been seen in a television ad.... 

    IE1.0 was just a fledgling trying to get some features that Mosaic (or the looming competitor) didn't have.  Since we shipped with Win95 and a big feature for Win95 was Long File Names, so IE needed to have support for spaces in names.  Since there was no spec for the "file" protocol scheme (heck there was practically no spec for any protocol) we added automagical escaping spaces.  We happily escaped spaces all over the place, and since nobody used our browser it didnt make a whits difference.

     Now IE began to mature and grew into a precocious 3-year-old, and when the powers that be noticed this, they decided that 3 was such a big number that the browser needed a new image.  That image was componentization.  The browser was taken and split in three major parts.  One part became mshtml (for rendering HTML) another shdocvw (for hosting DocObjects), and the third was wininet and urlmon (two binaries that were basically inseparable for downloading and caching content).  Unfortunately a key component from the platform was missing, so it was replicated into each of the other components.  That was an URL parsing platform. 

    No one component could agree with the others about the best way to handle the wild URLs that were so plentiful.  So each component came up with slightly different rules, although very logical, based on its personal fantasies of the one true URL.  The fantasies were fairly similar but the devil is in the details and these URLs went through a lot of metamorphoses on each trip down the stack to the wire.  Now each breed of URL had its own issues with these transformations, but in the end all children must be pushed from the nest to learn to fly on their own. 

    Enter IE4, Nashville, Win98, the next generation of everything.  And with it the new patron saint of URL parsing.  Now someone undertook the plight of the underrepresented URLs very seriously and wished to give them the respect they deserved.  Some cried with fear, and others with joy, but none could debate the necessity of a savior.  So the little URLs were taken and given a safe place to live and be loved:  shlwapi.dll.  And the saint went amongst the browser and the browser's friends and said, "Let no one but the chosen ones touch or talk or molest these URLs, and there will be a peace among us."  Some resisted, but they were put down as heretics should be and a peace came upon the land.  Except for the one abused problem URL:  file:.

    No one had been quite as abused as the the little file: URL.  This URL was special because we had always used files and DOS paths (and no one at the time knew about path canonicalization attacks), everyone was quite sure what they looked like , acted like, and even tasted like.  It didn't help that the file: protocol remained in RFC limbo as a platform/OS specific protocol.  So the browser and the browser's little friends would take turns dressing a DOS path like an URL in a pink bunny suit and undressing the URL with a pair of rusty scissors, pretending it was the same DOS path they started with.  Only the simplest of URLs was able to withstand this abuse, and it soon became clear that something would have to be done, lest the little file: URLs go off on their own and be lost forever.

    After much praying and meditation and consultation, it was finally decided that file: URLs must have two forms, one being the well formed easily communicable URL form and the other a legacy mutant form of a DOS path.  These two forms had different purposes, and soon different personalities.  The URL form lived happily inside the browser, but any time the browser needed to talk about the file: URL with its friends, it would clone and mutate the URL into its ugly half DOS form.

    What this MEANS:

    There are two kinds of file: URLs.  The first is the well formed URL style.  This is allowed query strings, fragment IDs, escape sequences and all the other goodies that URLs are supposed to support.  We call this a healthy file: URL.  The other kind is basically a DOS path with "file://" stuck on the front.  We use this for legacy communication with outsiders only.  We call this the legacy file: URL. Examples:

    
    DOSPATH:         c:\windows\My Documents 100%20\foo.txt 
    HEALTHY:         file:///c:/windows/My%20Documents%20100%2520/foo.txt
    LEGACY:          file://c:\windows\My Documents 100%20\foo.txt

    DOSPATH:         \\server\share\My Documents 100%20\foo.txt
    HEALTHY:         file://server/share/My%20Documents%20100%2520/foo.txt
    LEGACY:          file://\\server\share\My Documents 100%20\foo.txt

    NOW all of the Url* APIs in shlwapi, and thus everyone in IE4, understand the difference between these two types of URLs and act accordingly.  as long as a client of the APIs, doesn’t try to access the data directly, there is no issue whatsoever.  in other words as long as you dont have code anywhere that looks like this:

    LPTSTR GetFilePath(pszUrl)
    
    {
         if (0 == lstrcmpn("file://", pszUrl, sizeof("file://")))
         {
              return pszUrl + sizeof("file://");
         }
         return NULL;
    }

    but instead always call shlwapi like this:

    PathCreateFromUrl(pszUrl, pszPath, cchPath, dwFlags);

    You will always be happy and golden.  Straying from the path is straying into unknown lands.  There are of course flags that you can pass into some of the APIs that will change the form the file: URLs when they come out, but I highly recommend not using it for any reason, as it just increases the chances of creating more bizarre unsupportable behavior.


© 2008 Microsoft Corporation. All rights reserved. Terms of Use  |  Trademarks  |  Privacy Statement
Microsoft
Page view tracker