About the Shell's Namespace

The shell uses a single hierarchical namespace to organize all objects of interest to the user: files, storage devices, printers, network resources, and anything else that can be viewed using Windows Explorer. The root of this unified namespace is the desktop.

In many ways, the shell's namespace is analogous to a file system's directory structure. However, the namespace contains more types of objects than just files and directories. Familiar file system concepts, such as filename and path, have been replaced by more general and powerful associations. This overview discusses some of these associations, outlines the organization of the shell's namespace, and describes the functions and interfaces associated with the namespace.

Folders and File Objects

A folder is a collection of items in the shell's namespace. A folder is analogous to a file system directory, and many folders are, in fact, directories. However, there are also other types of folders, such as remote computers, storage devices, the desktop folder, the Control Panel, the Printers folder, and the Fonts folder. A folder may contain other folders as well as items called file objects. A file object may be an actual file, or it can be a Control Panel application, a printer, or another type of object. Each type of folder can only contain certain kinds of file objects; for example, you cannot move a Control Panel application into a file system directory.

Because there are many kinds of folders and file objects, each folder is a OLE component object model (COM) object that "knows" how to enumerate its contents and carry out other actions. More precisely, each folder implements the IShellFolder interface. Retrieving the IShellFolder object for a shell folder is referred to as binding to the folder. An application that binds to a folder must eventually free the IShellFolder interface object by calling its Release member function.

You can bind to the desktop folder (retrieve the folder's IShellFolder interface) by using the SHGetDesktopFolder member function. You can enumerate subfolders by using the IShellFolder::EnumObjects member function. You can bind to a subfolder of any given folder by using the IShellFolder::BindToObject member function. Using these three functions, an application can navigate throughout the shell's entire namespace.

Item Identifiers and Pointers to Item Identifier Lists

Objects in the shell's namespace are assigned item identifiers and item identifier lists. An item identifier uniquely identifies an item within its parent folder. An item identifier list uniquely identifies an item within the shell's namespace by tracing a path to the item from the desktop. A pointer to an item identifier list, which is sometimes called a PIDL (pronounced piddle), is used with many functions.

Item identifiers and PIDLs are much like the filenames and paths used in a file system. However, they share this important difference: item identifiers and PIDLs are binary data structures that never appear to the user. Item names that can be shown to the user (called display names) are described in Display Names and Filenames.

An item identifier is defined by the variable-length SHITEMID structure. The first two bytes of this structure specify its size, and the format of the remaining bytes depends on the parent folder, or more precisely on the software that implements the parent folder's IShellFolder interface. Except for the first two bytes, item identifiers are not strictly defined, and applications should make no assumptions about their format. To determine whether two item identifiers are equal, an application can use the IShellFolder::CompareIDs member function.

The ITEMIDLIST structure defines an element in an item identifier list (the only member of this structure is an SHITEMID structure). An item identifier list consists of one or more consecutive ITEMIDLIST structures packed on byte boundaries, followed by a 16-bit zero value. An application can walk a list of item identifiers by examining the size specified in each SHITEMID structure and stopping when it finds a size of zero.

Item identifier lists are almost always allocated using the shell's allocator (an IMalloc interface that you can retrieve by using the SHGetMalloc function). For example, some shell functions create an item identifier list and return a PIDL to it. In such cases, it is usually the application's responsibility to free the PIDL using the shell's allocator. Note that the SHGetMalloc function retrieves the task allocator for OLE applications.

Folder Locations

Certain folders have special meanings for the shell. An application can use shell functions to retrieve the locations of these special folders and to enable the user to browse for specific folders.

Some special folders are virtual folders ¾ so called because they are not actual directories on any storage device, local or remote. Virtual folders like the desktop folder, the My Computer folder, and the Network Neighborhood folder make a unified namespace possible by serving as containers for any number of storage devices and network resources. Other virtual folders contain file objects, such as printers, that are not part of the file system.

File system directories that the shell uses for specific purposes are also considered special folders. Examples include the Programs folder (which contains the user's program groups) and the desktop directory (which is used to physically store files that have been copied to the desktop folder). The locations of special file system folders are stored in the registry under the HKEY_CURRENT_USER / Software / Microsoft / Windows / CurrentVersion / Explorer / Shell Folders key.

You can use the SHGetSpecialFolderLocation function to retrieve the location of a special folder, which can be virtual or part of the file system. The function returns a PIDL, which the application must eventually free using the shell's allocator. If the folder is part of the file system, you can convert the PIDL to a file system path by using the SHGetPathFromIDList function. For a list of special folders, see the description of the SHGetSpecialFolderLocation function.

To display a dialog box that enables the user to browse for a folder, you can use the SHBrowseForFolder function. An application might use this function to prompt the user for a directory or remote computer. This function can also be used to browse for network printers, even though printers are not considered folders. An application can specify the root folder to browse from. For example, to prompt the user for a program group, you might call SHBrowseForFolder specifying the PIDL for the Programs folder as the root.

Item Enumeration

An application that uses the IShellFolder interface for a folder can determine the folder's contents by using the EnumObjects member function. This member function creates an item enumeration object, which is a set of item identifiers that can be retrieved by using the IEnumIDList interface.

One or more item identifiers can be retrieved from the enumeration object by using the IEnumIDList::Next member function. Calling this function repeatedly allows an application to retrieve all of the item identifiers one or more at a time. Using other member functions, you can skip items in the sequence, return to the beginning of the sequence, or "clone" the enumeration object to save its state.

When you are finished using the enumeration object, you must free it by calling the IEnumIDList::Release member function.

Display Names and Filenames

Because item identifiers are binary data structures, each item in a shell folder also has a display name, which is a string that can be shown to the user. You can use member functions in the IShellFolder interface to retrieve an item's display name, to find an item with the specified display name, or to change an item's display name.

The IShellFolder::GetDisplayNameOf member function can be used to retrieve a display name. The actual string returned depends on the type of display name specified. Values identifying the different types of display names are defined by the SHGNO enumerated type and have the SHGDN prefix. The type of display name that an application requests might depend on whether an item is shown by itself or within its parent folder. (A shared directory might be labeled Public on 'bill' in the former case and simply Public in the latter case.)

A special type of display name is one that can be converted back to an item identifier by using the IShellFolder::ParseDisplayName member function. You might use this type of display name as a parameter to the ShellExecute function or as a command-line argument for an application. For items within the file system, the display name for parsing is the same as the file system path. You can also convert a PIDL to a file system path by using the SHGetPathFromIDList function.

The IShellFolder::SetNameOf member function can be used to change the display name of a file object or subfolder. Changing an item's display name also changes its item identifier, so the function returns a PIDL containing the new item identifier. For file objects or folders within the file system, changing the display name renames the file or directory.

Object Attributes and Interfaces

Every file object and folder has attributes that determine, among other things, what actions can be carried out on it. An application can determine the attributes of any file object or folder and can retrieve interfaces for items in a shell folder.

To determine the attributes of a file object or folder, an application can use the IShellFolder::GetAttributesOf member function. Attributes include capabilities (such as whether a file object can be deleted or can be a drop target), display attributes (such as whether a folder is shared), contents flags (such as whether a folder has subfolders), as well as other attributes (such as whether an object is a folder, whether it is part of the file system, and so on). For a list of attributes, see the description of the IShellFolder::GetAttributesOf member function.

An application can retrieve interfaces that can be used to carry out actions on a file object or folder by using the IShellFolder::GetUIObjectOf member function. For example, the application can display the property sheets for a file object by retrieving the object's IContextMenu interface and activating the Properties command.