The wonderful world of shell bind context strings


Some time ago, we saw how the IBindCtx parameter to IShell­Folder::Parse­Display­Name can be used to modify how the parse takes place. More generally, the IBindCtx parameter to a function is a catch-all miscellaneous options parameter.

The interesting part of the bind context is all the stuff that has been added to it via the IBindCtx::Register­Object­Param method. You can attach arbitrary objects to the bind context, using a string to identify each one.

Some bind context parameters are like Boolean parameters that simply change some default behavior of the operation. For these operations, the object that is associated with the bind context string is not important; the important thing is that there is something associated with it. Traditionally, you just connect a dummy object that implements just IUnknown.

In the most general case, the object associated with a bind context string implements some operation-specific interface. For example, the STR_BIND_DELEGATE_CREATE_OBJECT bind context string expects you to associate an object that implements the ICreate­Object interface, because the whole point of the STR_BIND_DELEGATE_CREATE_OBJECT bind context string is to say, "Hey, I want to create objects in a nonstandard way," so you need to tell it what that nonstandard way is.

At the other extreme, you may have a chunk of data that you want to associate with the bind context string. Since bind contexts want to associate objects, you need to wrap the data inside a COM object. We saw this earlier when we had to create an object that implemented the IFile­System­Bind­Data interface in order to babysit a WIN32_FIND_DATA structure.

Rather than having to create a separate interface for each data type (hello, IObject­With­Folder­Enum­Mode), and rather than going to the opposite extreme and just using IStream to pass arbitrary unstructured data, the shell folks decided to take a middle-ground approach: Use a common interface that still has a modicum of type safety, namely, IProperty­Bag. Other nice things about this approach is that there are a lot of pre-existing helper functions for property bags and property variants. Also, you need to attach only one object instead of a whole bunch of tiny little ones.

Under this new regime (which took hold in Windows 8), the bind context has an associated property bag, and you put your data in that property bag.

In pictures:

  IBindCtx::Register­Object­Param IProperty­Bag::Write
IBindCtx Boolean parameter IUnknown
Interface parameter object with custom interface
STR_PROPERTY­BAG_PARAM IPropertyBag Property bag DWORD parameter VT_UI4
Property bag string parameter VT_BSTR
Property bag Boolean parameter VT_BOOL

If you want a Boolean-style parameter to be true, then set it in the bind context with a dummy object that implements IUnknown. If you want a Boolean-style parameter to false, then omit it from the bind context entirely.

To set an interface-style parameter, set it in the bind context with an object that implements the desired interface.

To set a property bag-based parameter, set it in the property bag with the appropriate variant type.

Here are the bind context strings defined up through Windows 8.1 and the way you set them into the bind context.

Bind context string Model Operation
STR_AVOID_DRIVE_RESTRICTION_POLICY Boolean Binding
STR_BIND_DELEGATE_CREATE_OBJECT Interface ICreateObject Binding
STR_BIND_FOLDER_ENUM_MODE Interface IObjectWith­FolderEnumMode Parsing
STR_BIND_FOLDERS_READ_ONLY Boolean Parsing
STR_BIND_FORCE_FOLDER_SHORTCUT_RESOLVE Boolean Binding
STR_DONT_PARSE_RELATIVE Boolean Parsing
STR_DONT_RESOLVE_LINK Boolean Binding
STR_ENUM_ITEMS_FLAGS Property bag: VT_UI4 Binding for enumeration
STR_FILE_SYS_FIND_DATA Interface IFileSys­BindData or IFileSys­BindData2 Parsing
STR_FILE_SYS_BIND_DATA_WIN7_FORMAT Boolean Parsing
STR_GET_ASYNC_HANDLER Boolean GetUIObjectOf
STR_GPS_BEST­EFFORT Boolean Binding for IProperty­Store
STR_GPS_DELAY­CREATION Boolean Binding for IProperty­Store
STR_GPS_FAST­PROPERTIES­ONLY Boolean Binding for IProperty­Store
STR_GPS_HANDLER­PROPERTIES­ONLY Boolean Binding for IProperty­Store
STR_GPS_NO_OPLOCK Boolean Binding for IProperty­Store
STR_GPS_OPEN­SLOW­ITEM Boolean Binding for IProperty­Store
STR_IFILTER_FORCE_TEXT_FILTER_FALLBACK Boolean Binding for IFilter
STR_IFILTER_LOAD_DEFINED_FILTER Boolean Binding for IFilter
STR_INTERNAL_NAVIGATE Boolean Loading history
STR_INTERNET­FOLDER_PARSE_ONLY_URLMON_BINDABLE Boolean Parsing
STR_ITEM_CACHE_CONTEXT Interface IBindCtx Parsing and initiailzing
STR_NO_VALIDATE_FILE­NAME_CHARS Boolean Parsing
STR_PARSE_ALLOW_INTERNET_SHELL_FOLDERS Boolean Parsing
STR_PARSE_AND_CREATE_ITEM Interface IParse­And­Create­Item Parsing
STR_PARSE_DONT_REQUIRE_VALIDATED_URLS Boolean Parsing
STR_PARSE_EXPLICIT_ASSOCIATION_SUCCESSFUL Property bag: VT_BOOL Parsing
STR_PARSE_PARTIAL_IDLIST Interface IShell­Item Parsing
STR_PARSE_PREFER_FOLDER_BROWSING Boolean Parsing
STR_PARSE_PREFER_WEB_BROWSING Boolean Parsing
STR_PARSE_PROPERTY­STORE Interface IProperty­Bag Parsing
STR_PARSE_SHELL_PROTOCOL_TO_FILE_OBJECTS Boolean Parsing
STR_PARSE_SHOW_NET_DIAGNOSTICS_UI Boolean Parsing
STR_PARSE_SKIP_NET_CACHE Boolean Parsing
STR_PARSE_TRANSLATE_ALIASES Boolean Parsing
STR_PARSE_WITH_EXPLICIT_ASSOCAPP Property bag: VT_BSTR Parsing
STR_PARSE_WITH_EXPLICIT_PROGID Property bag: VT_BSTR Parsing
STR_PARSE_WITH_PROPERTIES Interface IProperty­Store Parsing
STR_PROPERTYBAG_PARAM Interface IProperty­Bag holds property bag parameters
STR_SKIP_BINDING_CLSID Interface IPersist Parsing and binding

There are some oddities in the above table.

  • All of the STR_GPS_* values would be more conveniently expressed as a single VT_UI4 property bag-based value. (Exercise: Why isn't it?)
  • The STR_ITEM_CACHE_CONTEXT bind context parameter is itself another bind context! The idea here is that you, the caller, are enabling caching during the parse, and the inner bind context acts as the cache.
  • The STR_PARSE_EXPLICIT_ASSOCIATION_SUCCESSFUL value is unusual in that it is something set by the parser and passed back to the caller.
  • As we have been discussing, STR_PROPERTY­BAG_PARAM is a bind context string that doesn't mean anything on its own. Rather, it provides a property bag into which more parameters can be stored.

Next time, I'll write some helper functions to make all this slightly more manageable.

Comments (6)
  1. skSdnW says:

    I have always found these hard to work with and there are lot's of undocumented strings that you run across when debugging IShellFolder and friends. That being said, this table is going to be really useful as a quick reference so on behalf of shell developers everywhere, thank you!

  2. Gabe says:

    I'd have to imagine that the only reason the STR_GPS_* values exist is that they predated the idea of having a standard property bag.

    You could do it now, but prior to Win8 it was a lot easier to create a trivial object to represent a bool than to create an object to hold an int.

  3. nikos z says:

    I always puzzled why such an over the top method like bind contexts was used to pass effectively 0-1 bits of information (mostly). So what if you want to activate 2 behaviours simultaneously (of the boolean type), you call Register­Object­Param twice with the same dummy IUnknown?

    [You'll have to ask the COM folks why they chose to use a bind context to pass binding parameters. Sure, you could have a standard dummy IUnknown that you use. -Raymond]
  4. CarlD says:

    @nikos – my understanding is the bind context was meant for more than just passing extra parameters.  In particular, during moniker binding, the bind context can also be used for internal communication between the objects that are performing the parse/bind operations as a composite moniker is processed.  For example, an expensive-to-create resource that might be needed more than once could be cached in the binding context to allow simple monikers later in the pipeline to avoid the cost of re-creating it.

    Or at least that what I've understood.  In all my years of COM programming (not with the shell APIs), I don't recall ever actually using the bind context for anything at all – it was just another object to haul around and pass long.

  5. Joshua says:

    [You'll have to ask the COM folks why they chose to use a bind context to pass binding parameters. Sure, you could have a standard dummy IUnknown that you use. -Raymond]

    Would passing the IBindCtx itself be correct?

    [From the API's standpoint, you can put anything you want. But putting the bind context inside itself would create a circular reference and therefore a memory leak. -Raymond]
  6. Joshua says:

    Ohhh I missed the critical part. The boolean is evaluated later.

Comments are closed.

Skip to main content