Geoff Chappell - Software Analyst
In addition to numerous creatable COM classes that SHDOCVW supports explcitly, each with its own CLSID, SHDOCVW also has a general type of class that is here called an instance class. An instance class acts as a sort of CLSID shortcut. The instance class is registered under one CLSID, but when a client creates an instance, what it actually gets is an instance of some other class, here called a target class. The target class may be any class that implements either an IPropertyBag or IPersistStream interface. The value of instance classes as a feature depends largely on the existence of target classes that usefully let their instances be configured from data loaded through these interfaces.
The details of the redirection are taken from the instance class’s registry key, which must have a subkey named Instance which in turn has a value named CLSID:
| Key: | HKEY_CLASSES_ROOT\CLSID\{InstanceClassClsid}\Instance |
| Value: | CLSID |
The data may be any type but is treated as a string (with an implied expansion of REG_EXPAND_SZ data). Specifically, the data is interpreted as the string representation of a second CLSID, which specifies the target class. When a client creates an instance of the class whose CLSID is InstanceClassClsid, it gets an instance of the target class, and this instance is initialised with data loaded from either of two expected subkeys.
If the target class implements an IPropertyBag interface, it gets initialised with properties loaded from the InitPropertyBag subkey:
| Key: | HKEY_CLASSES_ROOT\CLSID\{InstanceClassClsid}\Instance\InitPropertyBag |
| Value: | PropertyName |
| Data: | PropertyValue |
Each value in this subkey names a property. Each value’s data, of whatever type, is the property’s value. The meaningfulness of these named properties is entirely a matter for the target class.
If properties cannot be so loaded but the target class has an IPersistStream interface, then initialisation is instead sought from the default value of the InitStream subkey:
| Key: | HKEY_CLASSES_ROOT\CLSID\{InstanceClassClsid}\Instance\InitStream |
| Value: | default |
| Data: | InitialisationData |
The default value provides data, presumably meant to be stored as the REG_BINARY type, from which to initialise the target class. The meaningfulness of this initialisation data is entirely a matter for the target class.
Though they may seem obscure, instance classes are used in the vast majority of real-world Windows sessions.
If nothing else, amost every user of Windows XP and higher has at least two instance classes created when first running Windows. When the Start Menu is prepared for a new user, it ordinarily begins with pinned shortcuts for the Internet and for E-mail. These shortcuts are hard-coded in SHELL32 as
respectively. These two CLSIDs are set up in the registry as representing instance classes. Both have the same target class, namely ClientExtractIcon, which is implemented in SHELL32. Among other things, the named properties for the instance class tell SHELL32 what type of client to look up. Thus do the shortcuts resolve to the default StartMenuInternet and Mail clients, respectively. Note the irony: even to have the pinned Start Menu shortcut for the Internet resolve to a browser that is not Internet Explorer, you must execute code from the main executable of Internet Explorer.
All the new-look folders in the Windows Vista Control Panel are set up as instance classes with LayoutFolder as the target class. It expects two properties, which tell it where to find an XML template for the layout.
The Fonts and Administrative Tools folders have long been set up as instance classes with FolderShortcut as the target class. (At least this class is documented.) In Windows Vista, folders such as Network, Printers and Public are instance classes with ShellFSFolder as the target class.
Instance classes are supported by SHDOCVW.DLL version 5.00 and higher and IEFRAME.DLL version 7.00 and higher.
Although there is no formal documentation from Microsoft, there is a Windows User Interface Technical Article called Creating Shell Extensions with Shell Instance Objects. It has perhaps not been updated since its creation in 2000. It talks specifically of “two shell objects that support being the host object of a shell instance object”, but there are many others, as noted above. Any creatable COM class, no matter who implements it, is suitable provided that it has either an IPropertyBag or IPersistStream interface.