Creating Shell Extensions with Shell Instance Objects

 

Raymond Chen
Microsoft Corporation

February 2000

Summary: A traditional shell namespace extension requires the implementation of a COM in-process server. Shell instance objects allow you to create simple shell extensions without having to write a single line of code. This article describes how shell instance objects and shell command objects can be used to easily deploy simple shell extensions. (5 printed pages)

Contents

What Is a Shell Namespace Extension? What Is a Shell Instance Object? Shell Objects That Can Be Created as Shell Instance Objects How About an Example? Shell Command Objects Conclusion

What Is a Shell Namespace Extension?

Shell namespace extensions allow you to create "virtual folders" in the shell. For example, the Recycle Bin icon on the desktop is not an actual file system directory, but rather represents a collection of items that is maintained by the Recycle Bin shell extension.

Details on creating shell namespace extensions can be found in the Platform SDK section of the MSDN Online Library.

Writing a shell namespace extension can be quite an ordeal. Fortunately, the shell provides an easy way to create certain types of simple shell namespace extensions, as this article will show.

What Is a Shell Instance Object?

A shell instance object is a special kind of shell extension provided by the shdocvw.dll component. Whereas a traditional shell extension requires a DLL to implement the object, a shell instance object retrieves everything it needs to know from the registry.

How the shell creates a shell instance object

  1. The shdocvw.dll component is loaded by virtue of being registered as the InProcServer32 for the shell instance object.
  2. When shdocvw.dll is asked to create an object it does not otherwise recognize, it checks the registry key for a subkey named Instance. If found, it reads the CLSID value of that subkey and passes that CLSID to the CoCreateInstance function. (For lack of a better term, let's call this the "host" object.)
  3. Next, shdocvw.dll looks for a subkey of Instance named InitPropertyBag or InitStream. If found, it then creates an IPropertyBag or IStream (accordingly) based on the contents of the registry key and passes it to the IPersistPropertyBag::Load or IPersistStream::Load method (accordingly).
  4. Finally, shdocvw.dll returns the now-initialized host object as the shell instance object.

Shell Objects That Can Be Created as Shell Instance Objects

There are two shell objects that support being the host object of a shell instance object, namely the Shell link object and the Shell folder shortcut object.

Both of these objects support the IPersistPropertyBag interface, so you can use the InitPropertyBag method of initializing them. (It so happens that both objects also support IPersistStream, but initializing a shortcut from a registry stream is much more cumbersome.)

The property bag you provide in the registry describes the target of the shell link or shell folder shortcut object. There are three supported forms for this property bag.

Targeting a shell special folder

InitPropertyBag
    TargetSpecialFolder=REG_SZ:"<special folder number>"

Notice that this is a REG_SZ registry value even though it represents an integer. Both decimal and hex notation are supported.

Targeting a directory inside a shell special folder

InitPropertyBag
    TargetSpecialFolder=REG_SZ:"<special folder number>"
    Target=REG_SZ:"<subdirectory name>"

The subdirectory name can contain embedded backslashes.

Targeting a directory by explicit path

InitPropertyBag
    Target=REG_SZ:"<full path to target directory>"

How About an Example?

Here's a copy of the registration that creates the Fonts folder icon in Control Panel:

HKEY_CLASSES_ROOT
  CLSID
    {D20EA4E1-3957-11D2-A40B-0C5020524152}=REG_SZ:"Fonts"
      InfoTip=REG_SZ:"Displays and manages fonts on your computer"
      DefaultIcon=REG_EXPAND_SZ:"%SystemRoot%\system32\main.cpl,9"
      InProcServer32=REG_EXPAND_SZ:"%SystemRoot%\system32\shdocvw.dll"
        ThreadingModel=REG_SZ:"Apartment"
      ShellFolder
        Attributes=REG_DWORD:0x60000000
        WantsFORPARSING=REG_SZ:""
      Instance
        CLSID=REG_SZ:"{0AFACED1-E828-11D1-9187-B532F1E9575D}"
        InitPropertyBag
          TargetSpecialFolder=REG_SZ:"0x0024"
          Target=REG_SZ:"Fonts"

Because {D20EA4E1-3957-11D2-A40B-0C5020524152} is registered in the Control Panel namespace, a Fonts folder shortcut is installed in Control Panel.

Let's go through this registry key step by step.

  • The GUID {D20EA4E1-3957-11D2-A40B-0C5020524152} was generated by running the uuidgen program found in the Platform SDK. Of course, when you create your own instance objects, you should run uuidgen and use your own GUID. The name of the icon as it appears in the namespace is also provided here.
  • The optional InfoTip string is displayed when the user hovers over the icon.
  • The DefaultIcon string provides the name and icon index for the icon to display for this item.
  • The InProcServer32 key must be set to the shdocvw.dll file, and the threading model must be set to Apartment.
  • The ShellFolder key sets the Attributes to a collection of SFGAO_ values, which we wish to apply to the folder shortcut. The SFGAO_FOLDER flag must always be set. Because the target is a file system folder, the SFGAO_FILESYSTEM flag is also set in the Attributes, and the WantsFORPARSING value is set to an empty string. (If the target is not a file system folder, the WantsFORPARSING value should not be created.)
  • The Instance key sets the CLSID value to the string representation of CLSID_FolderShortcut. This indicates that the object instance should create a folder shortcut.
  • The InitPropertyBag key indicates that the folder shortcut will be initialized with the IPersistPropertyBag interface. The two values inside the property bag specify that the target is the subdirectory "Fonts" in the special folder 0x0024, which is CSIDL_WINDOWS.

Shell Command Objects

Another type of shell extension object is an icon that when double-clicked runs a command. This, too, can be created without having to write a COM server. For example, here is a command object that is used by the My Network Places folder:

HKEY_CLASSES_ROOT
  CLSID
    {D4480A50-BA28-11d1-8E75-00C04FA31A86}=REG_SZ:"Add Network Place"
      InfoTip=REG_SZ:"Connects to shared folders, Web folders, and FTP sites."
      DefaultIcon=REG_EXPAND_SZ:"%SystemRoot%\System32\netplwiz.dll,-107"
      ShellFolder
        Attributes=REG_DWORD:0x00000000
      Shell
        Open
          Command=REG_EXPAND_SZ:"rundll32 ..."

Most of this registry key should look familiar, so I will only highlight the differences from shell instance objects:

  • There is no InProcServer32 key.
  • The Attributes of the ShellFolder key should omit the SFGAO_FOLDER flag because this item is not a folder.
  • Instead of an Instance key, we have a Shell key, which has the same structure as a progid key. The "Open" verb is the default action for double-clicking. You can also create other verbs, which will appear on the context menu. For example, the Internet Explorer icon creates a custom verb called "Open Home Page."

Details on the structure of the Shell key can be found in the Platform SDK section of the MSDN Online Library under the topic heading "Extending Context Menus."

Conclusion

Shell instance objects and shell command objects allow you to deploy simple shell extensions with a minimum amount of work. For example, you might create a command object in the Control Panel folder called "Troubleshoot," which runs a troubleshoot program. Or you might create a shell instance object that hosts a folder shortcut to a collection of system administrative tools on a shared network server. Shell instance objects and shell command objects allow you to easily deploy these types of shell extensions.