**SetParent Function The SetParent function changes the parent window of the specified child window. Syntax HWND SetParent( HWND hWndChild, HWND hWndNewParent ); Parameters hWndChild [in] Handle to the child window. hWndNewParent [in] Handle to the new parent window. If this parameter is NULL, the desktop window becomes the new parent window. Windows 2000/XP: If this parameter is HWND_MESSAGE, the child window becomes a message-only window. Return Value If the function succeeds, the return value is a handle to the previous parent window. If the function fails, the return value is NULL. To get extended error information, call GetLastError. Remarks An application can use the SetParent function to set the parent window of a pop-up, overlapped, or child window. The new parent window and the child window must belong to the same application. If the window identified by the hWndChild parameter is visible, the system performs the appropriate redrawing and repainting. For compatibility reasons, SetParent does not modify the WS_CHILD or WS_POPUP window styles of the window whose parent is being changed. Therefore, if hWndNewParent is NULL, you should also clear the WS_CHILD bit and set the WS_POPUP style after calling SetParent. Conversely, if hWndNewParent is not NULL and the window was previously a child of the desktop, you should clear the WS_POPUP style and set the WS_CHILD style before calling SetParent. Windows 2000/XP: When you change the parent of a window, you should synchronize the UISTATE of both windows. For more information, see WM_CHANGEUISTATE and WM_UPDATEUISTATE. Function Information Table with 2 columns and 5 rows Minimum DLL Version user32.dll Header Declared in Winuser.h, include Windows.h Import library User32.lib Minimum operating systems Windows 95, Windows NT 3.1 Unicode Implemented as Unicode version. table end Shell Programmer's Guide The Microsoft Windows user interface (UI) provides users with access to a wide variety of objects necessary for running applications and managing the operating system. The most numerous and familiar of these objects are the folders and files that reside on computer disk drives. There are also a number of virtual objects that allow the user to do tasks such as sending files to remote printers or accessing the Recycle Bin. The Shell organizes these objects into a hierarchical namespace, and provides users and applications with a consistent and efficient way to access and manage objects. The Shell Programmer's Guide describes how the Shell works and how to use the Shell's application programming interface (API) in your application. This document provides a brief overview of its contents. Document Conventions How the Shell Programmer's Guide Is Organized Overview of Shell Basics Overview of Intermediate Shell Techniques Overview of Advanced Shell Techniques Document Conventions The Shell Programmer's Guide follows the usual Microsoft Platform Software Development Kit (SDK) document conventions. Two conventions in particular should be noted: Sample code omits normal error-correction code. This code has been removed only to make the code more readable. You should include all appropriate error-correction code in your own applications. To make sample registry entries clear, key names are displayed with a bold font. Value names and data are displayed with a standard font. How the Shell Programmer's Guide Is Organized The Shell Programmer's Guide is organized into three sections: Shell Basics, Intermediate Shell Techniques, and Advanced Shell Techniques. The Shell Basics section contains information that all Shell programmers should be familiar with. The remaining two sections discuss more sophisticated or specialized Shell features. The Shell Basics and Intermediate Shell Techniques sections are divided into two subsections that reflect the distinctly different ways that developers can interact with the Shell: Programming the Shell. The Shell API can be used by applications to perform a variety of tasks. In this context, Shell programming is similar to other types of Windows programming. Extending the Shell. There are a number of ways that you can customize or extend the behavior of the Shell. For instance, you can modify the shortcut menus that the Shell displays when a user right-clicks a particular file, or you can change the file's icon. The simplest Shell extensions can be implemented by modifying the registry. More sophisticated Shell extensions require you to implement a dynamic-link library (DLL), which is loaded by the Shell. Overview of Shell Basics The Shell Basics section provides an introduction to the Shell. It includes discussions of those features of the Shell that most developers should be familiar with. If you are unfamiliar with the Shell, you should read through Shell Basics before going on to the remaining sections. The initial document in Shell Basics is The Shell Namespace. It discusses the architecture of the Shell namespace and how Shell objects are identified. This section is a must-read, as it introduces concepts and vocabulary that are fundamental to Shell programming. Familiarity with this document is assumed for all subsequent documents in the Shell Programmer's Guide. The Shell Basics: Programming the Shell section discusses how to do a number of basic tasks, including: How to navigate the namespace and find files and folders. How to launch applications. How to transfer Shell objects with Clipboard and drag-and-drop operations. How to debug applications that use the Shell. Using the Shell API with scripting languages and Microsoft Visual Basic. The Shell Basics: Extending the Shell section discusses how you can extend the Shell by modifying the registry or creating special files, including: How to define a file name extension as a file class and associate it with an application. How to customize a file class's icon and shortcut menu. How to customize the appearance of a folder. How to use Autorun to automatically launch a CD-ROM application. Overview of Intermediate Shell Techniques The Intermediate Shell Techniques section covers a number of the more sophisticated Shell features. Some of the topics in this section discuss more powerful and flexible ways to do some of the tasks discussed in Shell Basics. Other topics introduce Shell features that were not discussed in Shell Basics. The Intermediate Shell Techniques: Programming the Shell section includes a document that outlines which interfaces are exposed by the standard Shell folders. The remaining topics discuss how to do a number of tasks, including: How to create links and shortcuts. How to use the taskbar. How to use application desktop toolbars. The bulk of the Intermediate Shell Techniques: Extending the Shell section discusses how to create Shell extension handlers. These handlers allow you to dynamically modify a variety of Shell behaviors, including the icons and shortcut menus associated with a class of files. Other sections discuss: How to integrate your application's cleanup procedures with the Shell's disk cleanup manager. How to customize the way Webview displays the contents of a folder. Overview of Advanced Shell Techniques The Advanced Shell Techniques section covers a variety of additional ways to extend the Shell. The bulk of the section discusses how to create a custom virtual folder, or namespace extension, and integrate it into the Shell's namespace. The remaining sections discuss some specialized Shell topics, including: Creating custom explorer bars, tool bands, and desk bands. Using the Active Desktop object. Creating Control Panel applications. **Shell Basics The Microsoft Windowsuser interface (UI) gives users access to a wide variety of objects necessary for running applications and managing the operating system. The most numerous and familiar of these objects are the folders and files that reside on computer disk drives. There are also a number of virtual objects that allow the user to do tasks, such as send files to remote printers or access the Recycle Bin. The Shell organizes these objects into a hierarchical structure called the namespace, which provides users and applications with a consistent and efficient way to access and manage objects. Users interact with the namespace through the Shell's graphical UI or through an application. Applications interact with the namespace through the Shell's application programming interface (API). This section is an introduction to the Shell API. The Shell API consists of a collection of functions, Component Object Model (COM) interfaces, and COM objects that provide applications with a rich set of tools to access and manage the namespace. The Shell API can be used anywhere in an application, with one important exception: Like all COM-based services, the Shell API should not be used within a dynamic-link library (DLL)'s DllMain entry point function. Doing so can cause unpredictable behavior. To use the Shell API effectively in an application, you should first read The Shell Namespace section. This document describes the structure of the namespace and how namespace objects are identified. Programming the Shell The Shell API allows applications to perform a variety of tasks. Some of the more common tasks are discussed in the following documentation. Getting a Folder's ID Getting Information About the Contents of a Folder Navigating the Namespace Launching Applications Managing the File System Managing Printers Transferring Shell Objects with Drag-and-Drop and the Clipboard Debugging with the Shell Scriptable Shell Objects Extending the Shell By integrating your application with the Shell, you can extend the Shell's functionality and customize certain aspects of its behavior. In order of increasing complexity, you can extend the Shell by: Putting information in the registry or in special files. Implementing a Shell extension handler. Implementing a namespace extension. The first approach, which is used by many applications, is discussed in the following documentation. Creating a File Association Customizing Icons Extending Shortcut Menus Customizing Folders with Desktop.ini Creating an AutoRun-enabled CD-ROM Application Using AutoPlay For a discussion of how to write extension handlers, see Creating Shell Extension Handlers. For a discussion of how to write namespace extensions, see Creating a Shell Namespace Extension. Note To improve the readability of the sample code in the Shell Basics documentation, most of the normal error-correction code has been removed. You should add error code, as appropriate, to your own applications. To make registry samples more readable, key names are in a bold font and values and data are in a normal font. **The Shell Namespace The Shell namespace organizes the file system and other objects managed by the Shell into a single tree-structured hierarchy. Conceptually, it is a larger and more inclusive version of the file system. Introduction Identifying Namespace Objects Introduction One of the primary responsibilities of the Shell is managing and providing access to the wide variety of objects that make up the system. The most numerous and familiar of these objects are the folders and files that reside on computer disk drives. However, the Shell manages a number of nonfile system, or virtual objects, as well. Some examples include: Network printers Other networked computers Control Panel applications The Recycle Bin Some virtual objects do not involve physical storage at all. The printer object, for instance, contains a collection of links to networked printers. Other virtual objects, such as the Recycle Bin, may contain data that is stored on a disk drive, but needs to be handled differently than normal files. For example, a virtual object can be used to represent data stored in a database. In terms of the namespace, the various items in the database could appear in the Windows Explorer as separate objects, even though they are all stored in a single disk file. Virtual objects may even be located on remote computers. For instance, to facilitate roaming, a user's document files might be stored on a server. To give users access to their files from multiple desktop PCs, the My Documents folder on the desktop PC they are currently using will point to the server, not the hard disk of the desktop PC. Its path will include either a mapped network drive or a UNC path name. Like the file system, the namespace includes two basic types of object: folders and files. Folder objects are the nodes of the tree; they are containers for file objects and other folders. File objects are the leaves of the tree; they are either normal disk files or virtual objects, such as printer links. Folders that are not part of the file system are sometimes referred to as virtual folders. Like file system folders, the collection of virtual folders generally varies from system to system. There are three classes of virtual folders: Standard virtual folders, such as the Recycle Bin, that are found on all systems. Optional virtual folders that have standard names and functionality, but may not be present on all systems. Non-standard folders that are installed by the user. Unlike file system folders, users cannot create new virtual folders themselves. They can only install ones created by non-Microsoft developers. The number of virtual folders is thus normally much fewer than the number of file system folders. For a discussion of how to implement virtual folders see Creating a Shell Namespace Extension. You can see a visual representation of how the namespace is structured in the Explorer Bar of the Windows Explorer. For example, the following screenshot of Windows Explorer shows a relatively simple namespace. A view of the Shell namespace The ultimate root of the namespace hierarchy is the desktop. Immediately below the root are several virtual folders such as My Computer and the Recycle Bin. The file systems of the various disk drives can be seen to be subsets of the larger namespace hierarchy. The roots of these file systems are subfolders of the My Computer folder. My Computer also includes the roots of any mapped network drives. Other nodes in the tree, such as My Documents, are virtual folders. Identifying Namespace Objects Before you can use a namespace object, you must first have a way of identifying it. An object in the file system could have a name such as MyFile.htm. Because there might be other files with that name elsewhere in the system, uniquely identifying a file or folder requires a fully-qualified path such as "C:\MyDocs\MyFile.htm". This path is basically an ordered list of all folders in a path from the file system root, C:\, ending with the file. In the context of the namespace, paths are still quite useful for identifying objects located in the file system part of the namespace. However, they cannot be used for virtual objects. Instead, the Shell provides an alternative means of identification that can be used with any namespace object. Item IDs Within a folder, each object has an item ID, which is the functional equivalent of a file or folder name. The item ID is actually a SHITEMID structure: typedef struct _SHITEMID { USHORT cb; BYTE abID[1]; } SHITEMID, * LPSHITEMID; The abID member is the object's identifier. The length of abID is not defined, and its value is determined by the folder that contains the object. Because there is no standard definition for how abID values are assigned by folders, they are only meaningful to the associated folder object. Applications should simply treat them as a token that identifies an object in a particular folder. Because the length of abID varies, the cb member holds the size of the SHITEMID structure, in bytes. Because item IDs aren't useful for display purposes, the folder that contains the object normally assigns it a display name. This is the name that is used by Windows Explorer when it displays the contents of a folder. For more information on how display names are handled, see Getting Information From a Folder. Item ID Lists The item ID is rarely used by itself. Normally, it is part of an item ID list, which serves the same purpose as a file system path. However, instead of the character string used for paths, an item ID list is an ITEMIDLIST structure. This structure is an ordered sequence of one or more item IDs, terminated by a two-byte NULL. Each item ID in the item ID list corresponds to a namespace object. Their order defines a path in the namespace, much like a file system path. The following illustration shows a schematic representation of the ITEMIDLIST structure that corresponds to C:\MyDocs\MyFile.htm. The display name of each item ID is shown above it. The varying widths of the abID members are arbitrary; they illustrate the fact that the size of this member can vary. A schematic illustration of a PIDL PIDLs For the Shell application programming interface (API), namespace objects are usually identified by a pointer to their ITEMIDLIST structure, or pointer to an item identifier list (PIDL). For convenience, the term PIDL will generally refer in this documentation to the structure itself rather than the pointer to it. The PIDL shown in the preceding illustration is referred to as a full, or absolute, PIDL. A full PIDL starts from the desktop, and contains the item IDs of all intermediate folders in the path. It ends with the object's item ID followed by a terminating two-byte NULL. A full PIDL is similar to a fully qualified path and uniquely identifies the object in the Shell namespace. Full PIDLs are used infrequently. Many functions and methods expect a relative PIDL. The root of a relative PIDL is a folder, not the desktop. As with relative paths, the series of item IDs that make up the structure define a path in the namespace between two objects. Although they do not uniquely identify the object, they are usually smaller than a full PIDL and sufficient for many purposes. The most commonly used relative PIDLs, single-level PIDLs, are relative to the object's parent folder. They contain only the object's item ID and a terminating NULL. Multi-level PIDLs are also used for many purposes. They contain two or more item IDs and typically define a path from a parent folder to an object through a series of one or more subfolders. Note that a single-level PIDL can still be a fully-qualified PIDL. In particular, desktop objects are children of the desktop, so their fully-qualified PIDLs contain only one item ID. As discussed in Getting a Folder's ID, the Shell API provides a number of ways to retrieve an object's PIDL. Once you have it, you commonly just use it to identify the object when you call other Shell API functions and methods. In this context, a PIDL's internal contents are opaque and irrelevant. For the purposes of this discussion, think of PIDLs as tokens that represent particular namespace objects, and focus on how to use them for common tasks. Allocating PIDLs Although PIDLs have some similarity to paths, using them requires a somewhat different approach. The primary difference is in how to allocate and deallocate memory for them. Like the string used for a path, memory must be allocated for a PIDL. If an application creates a PIDL, it must allocate sufficient memory for the ITEMIDLIST structure. For most of the cases discussed here, the Shell creates the PIDL and handles memory allocation. Regardless of what allocated the PIDL, the application is usually responsible for deallocating the PIDL when it is no longer needed. To allocate and deallocate PIDLs, you must use the IMalloc interface exposed by the Shell's allocator. To retrieve a pointer to this interface, call SHGetMalloc. Use the IMalloc::Alloc method to allocate the PIDL, and the IMalloc::Free method to deallocate it. For an example of how to use this interface to handle Shell memory allocation, see Getting a Folder's ID. **Shell Basics: Programming the Shell The Shell application programming interface (API) allows applications to perform a variety of tasks. Some of the more common tasks are discussed in the following documentation. Getting a Folder's ID Getting Information About the Contents of a Folder Navigating the Namespace Launching Applications Managing the File System Managing Printers Transferring Shell Objects with Drag-and-Drop and the Clipboard Debugging with the Shell Scriptable Shell Objects Note To improve the readability of the sample code in the Shell Basics documentation, most of the normal error-correction code has been removed. You should add error code, as appropriate, to your own applications. To make registry samples more readable, key names are in a bold font and values are in a normal font. **Getting a Folder's ID Before you can make use of a namespace object, you need a way to identify it. This means obtaining either its pointer to an item identifier list (PIDL) or, in the case of file system objects, its path. This section discusses two of the simpler ways to obtain object IDs. For a more powerful approach that will work with any folder, use the IShellFolder interface. See Getting Information About the Contents of a Folder for more details. The SHBrowseForFolder Dialog Box Special Folders and CSIDLs A Simple Example of How to Use CSIDLs and SHBrowseForFolder The SHBrowseForFolder Dialog Box To enable the user to navigate the namespace and select a folder, your application can simply invoke SHBrowseForFolder. Calling this function launches a dialog box with a user interface (UI) that works somewhat like the Open or SaveAs common dialog boxes. When the user selects a folder, SHBrowseForFolder returns the folder's fully-qualified PIDL and its display name. If the folder is in the file system, the application can convert the PIDL to a path by calling SHGetPathFromIDList. The application can also restrict the range of folders that the user can select from by specifying a root folder. Only folders that are below that root in the namespace will appear. The following illustration shows the SHBrowseForFolder dialog box, with the root folder set to Program Files. Browse for Folder Dialog Box A simple example of how to use SHBrowseForFolder is provided later. Special Folders and CSIDLs A number of commonly used folders are designated as special by the system. These folders have a well-defined purpose, and most of them are present on all systems. Even if they are not present initially, their names and locations are still defined, so they can be added later. The collection of special folders includes all of the system's standard virtual folders, such as Printers, My Documents, and Network Neighborhood. It also includes a number of standard file system folders, such as Program Files and System. Even though the folders are a standard component of all systems, their names and locations in the namespace can vary. For example, the System directory is C:\Winnt\System32 on some systems and C:\Windows\System32 on others. In the past, environment variables provided a way to determine the name and location of a special folder on any particular system. The Shell now provides a more robust and flexible way to identify special folders, CSIDLs. You should generally use them instead of environment variables. CSIDLs provide a uniform way of identifying and locating special folders, regardless of their name or location on a particular system. Unlike environment variables, CSIDLs can be used with virtual folders as well as file system folders. Each special folder has a unique CSIDL assigned to it. For example, the Program Files file system folder has a CSIDL of CSIDL_PROGRAM_FILES, and the Network Neighborhood virtual folder has a CSIDL of CSIDL_NETWORK. A CSIDL is used in conjunction with one of several Shell functions to retrieve a special folder's PIDL, or a special file system folder's path. If the folder doesn't exist on a system, your application can force it to be created by combining its CSIDL with CSIDL_FLAG_CREATE. The CSIDL can be passed to the following functions: SHGetFolderLocation, which retrieves the PIDL of a special folder. SHGetFolderPath, which retrieves the path of a file system special folder. Note that these two functions were introduced with version 5.0 of the Shell and supersede the SHGetSpecialFolderLocation and SHGetSpecialFolderPath functions. To use SHGetFolderPath with earlier versions of the Shell, you can include the redistributable DLL, Shfolder.dll. A Simple Example of How to Use CSIDLs and SHBrowseForFolder The following sample function, PidlBrowse, illustrates how retrieve a pointer to the Shell allocator's IMalloc interface, use CSIDLs to retrieve a folder's PIDL, and use SHBrowseForFolder to have the user select a folder. It returns the PIDL and display name of the selected folder. Show Example LPITEMIDLIST PidlBrowse(HWND hwnd, int nCSIDL, LPSTR pszDisplayName) { LPITEMIDLIST pidlRoot = NULL; LPITEMIDLIST pidlSelected = NULL; BROWSEINFO bi = {0}; LPMALLOC pMalloc = NULL; SHGetMalloc(&pMalloc); if(nCSIDL) { SHGetFolderLocation(hwnd, nCSIDL, NULL, NULL, &pidlRoot); } else { pidlRoot = NULL; } bi.hwndOwner = hwnd; bi.pidlRoot = pidlRoot; bi.pszDisplayName = pszDisplayName; bi.lpszTitle = "Choose a folder"; bi.ulFlags = 0; bi.lpfn = NULL; bi.lParam = 0; pidlSelected = SHBrowseForFolder(&bi); if(pidlRoot) { pMalloc->Free(pidlRoot); } pMalloc->Release(); return pidlSelected; } The calling application passes in a window handle, which is needed by SHBrowseForFolder. The nCSIDL parameter is an optional CSIDL that is used to specify a root folder. Only folders below the root folder in the hierarchy will be displayed. The illustration shown earlier was generated by calling this function with nCSIDL set to CSIDL_PROGRAM_FILES. The calling application also passes in a string buffer, pszDisplayName, to hold the display name of the selected folder when PidlBrowse returns. PidlBrowse first calls SHGetMalloc to retrieve a pointer to the Shell's allocator. Although no PIDLs are allocated by the function itself, the IMalloc interface will be needed later to deallocate them. If the calling application specifies a root folder by passing in its CSIDL, PidlBrowse calls SHGetFolderLocation to retrieve the folder's PIDL. The function then assigns appropriate values to a BROWSEINFO structure, and passes it to SHBrowseForFolder. After the user selects a folder, SHBrowseForFolder returns its PIDL. The folder's display name is returned in the pszDisplayName member of the BROWSEINFO structure, and is passed back to the calling application through the pszDisplayName parameter. Finally, PidlBrowse deallocates the root PIDL, releases the IMalloc interface, and returns the selected folder's PIDL to the calling application. **Getting Information About the Contents of a Folder The Getting a Folder's ID section discussed two approaches to getting a namespace object's pointer to an item identifier list (PIDL). One obvious question is: Once you have a PIDL, what can you do with it? A related question is: What if neither approach works, or is suitable for your application? The answer to both questions requires taking a closer look at how the namespace is implemented. The key is the IShellFolder interface. Using the IShellFolder Interface Enumerating the Contents of a Folder Determining Display Names and Other Properties Getting a Pointer to a Subfolder's IShellFolder Interface Determining an Object's Parent Folder Using the IShellFolder Interface Earlier in this documentation, namespace folders were referred to as objects. Although, at that point, the term was used in a loose sense, it is actually true in a strict sense as well. Every namespace folder is represented by a Component Object Model (COM) object. Each folder object exposes a number of interfaces that can be used for a wide variety of tasks. Some interfaces that are optional may not be exposed by all folders. However, all folders must expose the fundamental interface, IShellFolder. The first step in using a folder object is to retrieve a pointer to its IShellFolder interface. In addition to providing access to the object's other interfaces, IShellFolder exposes a group of methods that handle a number of common tasks, several of which are discussed in this section. To retrieve a pointer to a namespace object's IShellFolder interface, you must first call SHGetDesktopFolder. This function returns a pointer to the IShellFolder interface of the namespace root, the desktop. Once you have the desktop's IShellFolder interface, there a variety of ways to proceed. If you already have the PIDL of the folder you are interested in—for instance, by calling SHGetFolderLocation— you can retrieve its IShellFolder interface by calling the desktop's BindToObject method. If you have the path of a file system object, you must first obtain its PIDL by calling the desktop's ParseDisplayName method and then call BindToObject. If neither of these approaches is applicable, you can use other IShellFolder methods to navigate the namespace. For more information, see Navigating the Namespace. Enumerating the Contents of a Folder The first thing you usually want to do with a folder is to find out what it contains. You must first call the folder's EnumObjects method. The folder will create a standard OLE enumeration object and return its IEnumIDList interface. This interface exposes four standard methods— Clone, Next, Reset, and Skip— that can be used to enumerate the contents of the folder. The basic procedure for enumerating a folder's contents is: Call the folders EnumObjects method to retrieve a pointer to an enumeration object's IEnumIDList interface. Pass an unallocated PIDL to Next. Next takes care of allocating the PIDL, but the application must deallocate it when it is no longer needed. When Next returns, the PIDL will contain just the object's item ID and the terminating NULL characters. In other words, it is a single-level PIDL, relative to the folder, not a fully-qualified PIDL. Repeat step 2 until Next returns S_FALSE to indicate that all items have been enumerated. Call IEnumIDList::Release to release the enumeration object. Note It is important to keep track of whether you are working with a full or relative PIDL. Some functions and methods will accept either, but others will only take one or the other. The remaining three IEnumIDList methods (Reset, Skip, and Clone) are useful if you need to do repeated enumerations of the folder. They allow you to reset the enumeration, skip one or more objects, and make a copy of the enumeration object to preserve its state. Determining Display Names and Other Properties Once you have enumerated all the PIDLs that are contained by a folder, you can find out what sort of objects they represent. The IShellFolder interface provides a number of useful methods, two of which are discussed here. Other IShellFolder methods and other Shell folder interfaces are discussed later. One of the most useful properties is the object's display name. To retrieve the display name of an object, pass its PIDL to GetDisplayNameOf. Although the object can be located anywhere below the parent folder in the namespace, its PIDL must be relative to the folder. GetDisplayNameOf returns the display name as part of of a STRRET structure. Because extracting the display name from a STRRET structure can be a little tricky, the Shell provides two functions that do the job for you, StrRetToStr and StrRetToBuf. Both functions take a STRRET structure, and return the display name as a normal string. They differ only in how the string is allocated. In addition to its display name, an object can have a number of attributes, such as whether it is a folder or whether it can be moved. You can retrieve an object's attributes by passing its PIDL to GetAttributesOf. The complete list of attributes is quite large, so you should see the reference for details. Note that the PIDL that you pass to GetAttributesOf must be single-level. In particular, GetAttributesOf will accept the PIDLs returned by Next. You can pass in an array of PIDLs, and GetAttributesOf will return those attributes that all objects in the array have in common. If you have an object's fully-qualified path or PIDL, SHGetFileInfo provides a simple way to retrieve information about an object that is sufficient for many purposes. SHGetFileInfo takes a fully-qualified path or PIDL, and returns a variety of information about the object including: The object's display name The object's attributes Handles to the object's icons A handle to the system image list The path of the file containing the object's icon Getting a Pointer to a Subfolder's IShellFolder Interface You can determine whether your folder contains any subfolders by calling GetAttributesOf and checking to see if the SFGAO_FOLDER flag is set. If an object is a folder, you can bind to it, which provides you with a pointer to its IShellFolder interface. To bind to a subfolder, call the parent folder's BindToObject method. This method takes the subfolder's PIDL and returns a pointer to its IShellFolder interface. Once you have this pointer, you can use the IShellFolder methods to enumerate the subfolders contents, determine their properties, and so on. Determining an Object's Parent Folder If you have an object's PIDL, you may need a handle to one of the interfaces exposed by its parent folder. For example, if you want to determine the display name associated with a PIDL by using GetDisplayNameOf, you must first retrieve the IShellFolder interface of the object's parent. It is possible to do this with the techniques discussed in the previous sections. However, a much simpler approach is to use the Shell function, SHBindToParent. This function takes the fully-qualified PIDL of an object and returns a specified interface pointer on the parent folder. Optionally, it also returns the item's single-level PIDL for use in methods such as GetAttributesOf. The following sample console application retrieves the PIDL of the System special folder and returns its display name. #include #include #include int main() { LPMALLOC pMalloc = NULL; IShellFolder *psfParent = NULL; LPITEMIDLIST pidlSystem = NULL; LPCITEMIDLIST pidlRelative = NULL; STRRET strDispName; TCHAR szDisplayName[MAX_PATH]; HRESULT hr; hr = SHGetMalloc(&pMalloc); hr = SHGetFolderLocation(NULL, CSIDL_SYSTEM, NULL, NULL, &pidlSystem); hr = SHBindToParent(pidlSystem, IID_IShellFolder, (void **) &psfParent, &pidlRelative); if(SUCCEEDED(hr)) { hr = psfParent->GetDisplayNameOf(pidlRelative, SHGDN_NORMAL, &strDispName); hr = StrRetToBuf(&strDispName, pidlSystem, szDisplayName, sizeof(szDisplayName)); cout << "SHGDN_NORMAL - " <Release(); pMalloc->Free(pidlSystem); pMalloc->Release(); return 0; } The application first retrieves a pointer to the Shell allocator's IMalloc interface and uses SHGetFolderLocation to retrieve the System folder's PIDL. It then calls SHBindToParent, which returns a pointer to the parent folder's IShellFolder interface, and the System folder's PIDL relative to its parent. It then uses the parent folder's GetDisplayNameOf method to retrieve the display name of the System folder. Because GetDisplayNameOf returns a STRRET structure, StrRetToBuf is used to convert the display name into a normal string. After displaying the display name, the interface pointers are released and the System PIDL freed. Note that you must not free the relative PIDL returned by SHBindToParent. **Navigating the Namespace You now have all the essential elements needed to navigate anywhere in the namespace. The simplest way to start is to have your application call SHGetDesktopFolder to retrieve the desktop's IShellFolder interface. Then, to navigate downward through the namespace, your application can follow these steps: Enumerate the folder's contents. Determine which objects are subfolders, and select one. Bind to the subfolder to retrieve its IShellFolder interface. Repeat these steps as often as necessary to reach the target. A Simple Example of Namespace Navigation The following piece of sample code is a simple console application that illustrates a number of the procedures discussed in the preceding sections. Error checking has been omitted for clarity. The application performs the following tasks: Retrieves the Program Files folder's IShellFolder interface ( Using the IShellFolder Interface). Enumerates the contents of the folder ( Enumerating the Contents of a Folder). Determines all the display names and prints them ( Determining Display Names and Other Properties). Looks for a subfolder ( Getting a Pointer to a Subfolder's IShellFolder Interface). Binds to the first subfolder it finds ( Getting a Pointer to a Subfolder's IShellFolder Interface). Prints the display names of the objects in the subfolder. Show Example #include #include #include main() { LPMALLOC pMalloc; LPITEMIDLIST pidlProgFiles = NULL; LPITEMIDLIST pidlItems = NULL; IShellFolder *psfFirstFolder = NULL; IShellFolder *psfDeskTop = NULL; IShellFolder *psfProgFiles = NULL; LPENUMIDLIST ppenum = NULL; ULONG celtFetched; HRESULT hr; STRRET strDispName; TCHAR pszDisplayName[MAX_PATH]; ULONG uAttr; CoInitialize( NULL ); hr = SHGetMalloc(&pMalloc); hr = SHGetFolderLocation(NULL, CSIDL_PROGRAM_FILES, NULL, NULL, &pidlProgFiles); hr = SHGetDesktopFolder(&psfDeskTop); hr = psfDeskTop->BindToObject(pidlProgFiles, NULL, IID_IShellFolder, (LPVOID *) &psfProgFiles); psfDeskTop->Release(); hr = psfProgFiles->EnumObjects(NULL,SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &ppenum); while( hr = ppenum->Next(1,&pidlItems, &celtFetched) == S_OK && (celtFetched) == 1) { psfProgFiles->GetDisplayNameOf(pidlItems, SHGDN_INFOLDER, &strDispName); StrRetToBuf(&strDispName, pidlItems, pszDisplayName, MAX_PATH); cout << pszDisplayName << '\n'; if(!psfFirstFolder) { uAttr = SFGAO_FOLDER; psfProgFiles->GetAttributesOf(1, (LPCITEMIDLIST *) &pidlItems, &uAttr); if(uAttr & SFGAO_FOLDER) { hr = psfProgFiles->BindToObject(pidlItems, NULL, IID_IShellFolder, (LPVOID *) &psfFirstFolder); } } pMalloc->Free(pidlItems); } cout << "\n\n"; ppenum->Release(); if(psfFirstFolder) { hr = psfFirstFolder->EnumObjects(NULL,SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &ppenum); while( hr = ppenum->Next(1,&pidlItems, &celtFetched) == S_OK && (celtFetched) == 1) { psfFirstFolder->GetDisplayNameOf(pidlItems, SHGDN_INFOLDER, &strDispName); StrRetToBuf(&strDispName, pidlItems, pszDisplayName, MAX_PATH); cout << pszDisplayName << '\n'; pMalloc->Free(pidlItems); } } ppenum->Release(); pMalloc->Free(pidlProgFiles); pMalloc->Release(); psfProgFiles->Release(); psfFirstFolder->Release(); CoUninitialize(); return 0; } **Launching Applications Once your application has located a file object, the next step is often to act on it in some way. For instance, your application might want to launch another application that allows the user to modify a data file. If the file of interest is an executable, your application might want to simply launch it. This document discusses how to use ShellExecute or ShellExecuteEx to perform these tasks. Using ShellExecute and ShellExecuteEx A Simple Example of How to Use ShellExecuteEx Using ShellExecute and ShellExecuteEx To use ShellExecute or ShellExecuteEx, your application must specify the file or folder object that is to be acted on, and a verb that specifies the operation. For ShellExecute, assign these values to the appropriate parameters. For ShellExecuteEx, fill in the appropriate members of a SHELLEXECUTEINFO structure. There are also several other members or parameters that can be used to fine-tune the behavior of the two functions. File and folder objects can be part of the file system or virtual objects, and they can be identified by either paths or pointers to item identifier lists (PIDLs). Object Verbs The verbs available for an object are essentially the items that you find on an object's shortcut menu. To find which verbs are available, look in the registry under HKEY_CLASSES_ROOT\CLSID\{object_clsid}\Shell\verb where object_clsid is the class identifier (CLSID) of the object, and verb is the name of the available verb. The verb\command subkey contains the data indicating what happens when that verb is invoked. To find out which verbs are available for Predefined Shell Objects, look in the registry under HKEY_CLASSES_ROOT\object_name\shell\verb where object_name is the name of the predefined Shell object. Again, the verb\command subkey contains the data indicating what happens when that verb is invoked. Commonly available verbs include: Table with 2 columns and 6 rows Verb Description edit Launches an editor and opens the document for editing. find Initiates a search starting from the specified directory. open Launches an application. If this file is not an executable file, its associated application is launched. print Prints the document file. properties Displays the object's properties. table end Each verb corresponds to the command that would be used to launch the application from a console window. The open verb is a good example, as it is commonly supported. For .exe files, open simply launches the application. However, it is more commonly used to launch an application that operates on a particular file. For instance, .txt files can be opened by Microsoft WordPad. The open verb for a .txt file would thus correspond to something like the following command: "C:\Program Files\Windows NT\Accessories\Wordpad.exe" "%1" When you use ShellExecute or ShellExecuteEx to open a .txt file, Wordpad.exe is launched with the specified file as its argument. Some commands can have additional arguments, such as flags, that can be added as needed to launch the application properly. For further discussion of shortcut menus and verbs, see Extending Shortcut Menus. In general, trying to determine the list of available verbs for a particular file is somewhat complicated. In many cases, you can simply set the lpVerb parameter to NULL, which invokes the default command for the file class. This procedure is usually equivalent to setting lpVerb to "open", but some file classes may have a different default command. For further information, see Extending Shortcut Menus and the ShellExecuteEx reference documentation. Using ShellExecute to Launch the Search Dialog Box When a user right-clicks a folder icon in Microsoft Windows Explorer, one of the menu items is "Search". If they select that item, the Shell launches its Search utility. This utility displays a dialog box that can be used to search files for a specified text string. An application can programmatically launch the Search utility for a directory by calling ShellExecute, with "find" as the lpVerb parameter, and the directory path as the lpFile parameter. For instance, the following line of code launches the Search utility for the c:\MyPrograms directory. ShellExecute(hwnd, "find", "c:\\MyPrograms", NULL, NULL, 0); A Simple Example of How to Use ShellExecuteEx The following sample console application illustrates the use of ShellExecuteEx. Most error checking code has been omitted for clarity. Show Example #include #include main() { LPMALLOC pMalloc; LPITEMIDLIST pidlWinFiles = NULL; LPITEMIDLIST pidlItems = NULL; IShellFolder *psfWinFiles = NULL; IShellFolder *psfDeskTop = NULL; LPENUMIDLIST ppenum = NULL; STRRET strDispName; TCHAR pszParseName[MAX_PATH]; ULONG celtFetched; SHELLEXECUTEINFO ShExecInfo; HRESULT hr; BOOL fBitmap = FALSE; hr = SHGetMalloc(&pMalloc); hr = SHGetFolderLocation(NULL, CSIDL_WINDOWS, NULL, NULL, &pidlWinFiles); hr = SHGetDesktopFolder(&psfDeskTop); hr = psfDeskTop->BindToObject(pidlWinFiles, NULL, IID_IShellFolder, (LPVOID *) &psfWinFiles); hr = psfDeskTop->Release(); hr = psfWinFiles->EnumObjects(NULL,SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &ppenum); while( hr = ppenum->Next(1,&pidlItems, &celtFetched) == S_OK && (celtFetched) == 1) { psfWinFiles->GetDisplayNameOf(pidlItems, SHGDN_FORPARSING, &strDispName); StrRetToBuf(&strDispName, pidlItems, pszParseName, MAX_PATH); pMalloc->Free(pidlItems); if(StrCmpI(PathFindExtension(pszParseName), TEXT( ".bmp")) == 0) { fBitmap = TRUE; break; } } ppenum->Release(); if(fBitmap) { ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO); ShExecInfo.fMask = NULL; ShExecInfo.hwnd = NULL; ShExecInfo.lpVerb = NULL; ShExecInfo.lpFile = pszParseName; ShExecInfo.lpParameters = NULL; ShExecInfo.lpDirectory = NULL; ShExecInfo.nShow = SW_MAXIMIZE; ShExecInfo.hInstApp = NULL; ShellExecuteEx(&ShExecInfo); } pMalloc->Free(pidlWinFiles); pMalloc->Release(); psfWinFiles->Release(); return 0; } The application first retrieves the PIDL of the Windows directory, and enumerates its contents until it finds the first .bmp file. Unlike the earlier example, IShellFolder::GetDisplayNameOf is used to retrieve the file's parsing name instead of its display name. Because this is a file system folder, the parsing name is a fully qualified path, which is what is needed for ShellExecuteEx. Once the first .bmp file has been located, appropriate values are assigned to the members of a SHELLEXECUTEINFO structure. The lpFile member is set to the parsing name of the file, and the lpVerb member to NULL, to begin the default operation. In this case, the default operation is "open". The structure is then passed to ShellExecuteEx, which launches the default handler for bitmap files, typically MSPaint.exe, to open the file. After the function returns, the PIDLs are freed and the Windows folder's IShellFolder interface is released. **Managing the File System The Shell provides a number of ways to manage file systems. The Shell provides a function, SHFileOperation, that allows an application to programmatically move, copy, rename, and delete files. The Shell also supports some additional file management capabilities. HTML documents can be connected to related files, such as graphics files or style sheets. When the document is moved or copied, the connected files are automatically moved or copied as well. For systems that are available to more than one user, files can be managed on a per-user basis. Users have easy access to their data files, but not to files belonging to other users. If document files are added or modified, they can be added to the Shell's list of recent documents. When the user clicks the Documents command on the Start menu, a list of links to the documents appears. This document discusses how these file management technologies work. It then outlines how to use the Shell to move, copy, rename, and delete files, and how to manage objects in the Recycle Bin. Per-User File Management My Documents and My Pictures Folders Connected Files Moving, Copying, Renaming, and Deleting Files Simple Example of Managing Files with SHFileOperation Adding Files to the Shell's List of Recent Documents Per-User File Management The Microsoft Windows 2000 Shell allows files to be associated with a particular user so the files remain hidden from other users. In terms of the file system, the files are stored under the user's profile folder, typically C:\Documents and Settings\Username\ on Windows 2000 systems. This feature allows many individuals to use the same computer, while maintaining the privacy of their files from other users. Different users can have different programs available. It also provides a straightforward way for administrators and applications to store such things as initialization (.ini) or link (.lnk) files. Applications can thus preserve a different state for each user and easily recover that particular state when needed. There is also a profile folder for storing information that is common to all users. Because it is inconvenient to determine which user is logged in and where their files are located, the standard per-user folders are special folders and are identified by a CSIDL. For instance, the CSIDL for the per-user Program Files folder is CSIDL_PROGRAMS. If your application calls SHGetFolderLocation or SHGetFolderPath with one of the per-user CSIDLs, the function returns the pointer to an item identifier list (PIDL) or path appropriate to the currently logged-in user. If your application needs to retrieve the path or PIDL of the profile folder, its CSIDL is CSIDL_PROFILE. My Documents and My Pictures Folders One of the standard icons found on the desktop is My Documents. When you open this folder, it contains the current user's document files. The desktop instance of My Documents is a virtual folder—an alias to the file system location used to physically store the user's documents—located immediately below the desktop in the namespace hierarchy. The purpose of the My Documents and My Pictures folders is to provide a straightforward and secure way for users to access their document and picture files on a system that might have multiple users. Each user is assigned separate file system folders for his or her files. For example, the location of a user's documents folder in the file system is typically something like C:\Documents and Settings\username\My Documents. There is no need for users to know anything about the physical location of their file system folders. They simply access their files through the My Documents icon. Note My Documents allows a user to access his or her own files but not those of any other user. If multiple individuals use the same computer, an administrator can lock users out of the part of the file system where the actual files are stored. Users will thus be able to work on their own documents through the My Documents folder but not on documents that belong to any other users. There is usually no need for an application to know which user is logged in or where in the file system that user's My Documents folder is located. Instead, your application can retrieve the PIDL of the My Documents desktop icon by calling the desktop's ParseDisplayName method. The parsing name used to identify the My Documents folder is not a file path but rather ::{450d8fba-ad25-11d0-98a8-0800361b1103}. The bracketed expression is the text form of the My Documents globally unique identifier (GUID). For example, to retrieve the PIDL of My Documents, your application should use this call to ParseDisplayName. hr = psfDeskTop->ParseDisplayName(NULL, NULL, L"::{450d8fba-ad25-11d0-98a8-0800361b1103}", &chEaten, &pidlDocFiles, NULL); The same location can also be obtained by calling SHGetFolderLocation using the CSIDL_MYDOCUMENTS constant, as shown here. hr = SHGetFolderLocation(NULL, CSIDL_MYDOCUMENTS, NULL, 0, &pidlDocFiles); Once your application has the My Documents PIDL, it can handle the folder just as it would a normal file system folder—enumerating items, parsing, binding, and performing any other valid folder operations. The Shell automatically maps changes in My Documents or its subfolders to the appropriate file system folders. If your application needs access to the actual file system folder that contains the current user's documents, pass CSIDL_PERSONAL to SHGetFolderLocation. The function returns the PIDL of the file system folder that is displayed in the current user's My Documents folder. Connected Files HTML documents often have a number of associated graphics files, a style sheet file, several Microsoft JScript (compatible with ECMA 262 language specification ) files, and so on. When you move or copy the primary HTML document, you also usually want to move or copy its associated files to avoid breaking links. Unfortunately, there has been no easy way until now to determine which files are related to any given HTML document other than by analyzing their contents. To alleviate this problem, Windows 2000 provides a simple way to connect a primary HTML document to its group of associated files. If file connection is enabled, when the document is moved or copied all its connected files go with it. To create a group of connected files, the primary document must have an .htm or .html file name extension. Create a subfolder of the primary document's parent folder. The subfolder's name must be the name of the primary document, minus the .htm or .html extension, followed by one of the extensions listed below. The most commonly used extensions are ".files" or "_files". For instance, if the primary document is named MyDoc.htm, naming the subfolder "MyDoc_files" defines the subfolder as the container for the document's connected files. If the primary document is moved or copied, the subfolder and its files are moved or copied as well. For some languages, it is possible to use a localized equivalent of "_files" to create a subfolder for connected files. The following table lists the valid strings that can be appended to a document name to create a connected files subfolder. Note that some of these strings have '-' as their first character rather than '_' or '.'. Table with 4 columns and 6 rows "_archivos" "_arquivos" "_bestanden" "_bylos" "-Dateien" "_datoteke" "_dosyalar" "_elemei" "_failid" "_fails" "_fajlovi" "_ficheiros" "_fichiers" "-filer" ".files" "_files" "_file" "_fitxers" "_fitxategiak" "_pliki" "_soubory" "_tiedostot" table end Note This feature is sensitive to the case of the extension. For instance, for the example given above, a subfolder named "MyDoc_Files" will not be connected to MyDoc.htm. Whether file connection is enabled or disabled is controlled by a REG_DWORD value, NoFileFolderConnection, of the following registry key. HKEY_CURRENT_USER Software Microsoft Windows CurrentVersion Explorer This value normally is not defined, and file connection is enabled. If necessary, you can disable file connection by adding this value to the key and setting it to 1. To enable file connection again, set NoFileFolderConnection to zero. Note File connection should normally be enabled because other applications might depend on it. Disable file connection only if absolutely necessary. Moving, Copying, Renaming, and Deleting Files The namespace is not static, and applications commonly need to manage the file system by performing one of the following operations. Copying an object to another folder. Moving an object to another folder. Deleting an object. Renaming an object. These operations are all performed with SHFileOperation. This function takes one or more source files and produces corresponding destination files. In the case of the delete operation, the system attempts to put the deleted files into the Recycle Bin. It is also possible to move files using the drag-and-drop functionality. To use the function, you must fill in the members of an SHFILEOPSTRUCT structure and pass it to SHFileOperation. The key members of the structure are pFrom and pTo. The pFrom member is a double null-terminated string that contains one or more source file names. These names can be either fully qualified paths or standard DOS wildcards such as *.*. Although this member is declared as a null-terminated string, it is used as a buffer to hold multiple file names. Each file name must be terminated by the usual single NULL character. An additional NULL character must be appended to the end of the final name to indicate the end of pFrom. The pTo member is a double null-terminated string, much like pFrom. The pTo member contains the names of one or more fully qualified destination names. They are packed into pTo in the same way as they are for pFrom. If pTo contains multiple names, you must also set the FOF_MULTIDESTFILES flag in the fFlags member. The usage of pTo depends on the operation as described here. For copy and move operations, if all the files are going to a single directory, pTo contains the fully qualified directory name. If the files are going to different destinations, pTo can also contain one fully qualified directory or file name for each source file. If a directory doesn't exist, the system creates it. For rename operations, pTo contains one fully qualified path for each source file in pFrom. For delete operations, pTo is not used. Notifying the Shell Notify the Shell of the change after using SHFileOperation to move, copy, rename, or delete files, or after taking any other action that affects the namespace. Actions that should be accompanied by notification include the following: Adding or deleting files or folders. Moving, copying, or renaming files or folders. Changing a file association. Changing file attributes. Adding or removing drives or storage media. Creating or disabling a shared folder. Changing the system image list. An application notifies the Shell by calling SHChangeNotify with the details of what has changed. The Shell can then update its image of the namespace to accurately reflect its new state. Simple Example of Managing Files with SHFileOperation The following sample console application illustrates the use of SHFileOperation to copy files from one directory to another. The source and destination directories, C:\My_Docs and C:\My_Docs2, are hard-coded into the application for simplicity. Show Example #include #include int main(void) { IShellFolder *psfDeskTop = NULL; IShellFolder *psfDocFiles = NULL; IMalloc *pMalloc = NULL; LPITEMIDLIST pidlDocFiles = NULL; LPITEMIDLIST pidlItems = NULL; IEnumIDList *ppenum = NULL; SHFILEOPSTRUCT sfo; STRRET strDispName; TCHAR szParseName[MAX_PATH]; TCHAR szSourceFiles[256]; int i; int iBufPos = 0; ULONG chEaten; ULONG celtFetched; size_t ParseNameSize = 0; HRESULT hr; pzSourceFiles[0] = '\0'; hr = SHGetMalloc(&pMalloc); hr = SHGetDesktopFolder(&psfDeskTop); hr = psfDeskTop->ParseDisplayName(NULL, NULL, L"c:\\My_Docs", &chEaten, &pidlDocFiles, NULL); hr = psfDeskTop->BindToObject(pidlDocFiles, NULL, IID_IShellFolder, (LPVOID *) &psfDocFiles); hr = psfDeskTop->Release(); hr = psfDocFiles->EnumObjects(NULL,SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &ppenum); while( (hr = ppenum->Next(1,&pidlItems, &celtFetched)) == S_OK && (celtFetched) == 1) { psfDocFiles->GetDisplayNameOf(pidlItems, SHGDN_FORPARSING, &strDispName); StrRetToBuf(&strDispName, pidlItems, szParseName, MAX_PATH); hr = StringCchLength(szParseName, MAX_PATH, &ParseNameSize); if (SUCCEEDED(hr)) { for(i=0; i<=ParseNameSize, i++) { szSourceFiles[iBufPos++] = szParseName[i]; } pMalloc->Free(pidlItems); } } ppenum->Release(); szSourceFiles[iBufPos] = '\0'; sfo.hwnd = NULL; sfo.wFunc = FO_COPY; sfo.pFrom = szSourceFiles; sfo.pTo = "c:\\My_Docs2\0"; sfo.fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOCONFIRMMKDIR; hr = SHFileOperation(&sfo); SHChangeNotify(SHCNE_UPDATEDIR, SHCNF_PATH, (LPCVOID) "c:\My_Docs2", 0); pMalloc->Free(pidlDocFiles); pMalloc->Release(); psfDocFiles->Release(); return 0; } The application first retrieves a pointer to the desktop's IShellFolder interface. It then retrieves the source directory's PIDL by passing its fully qualified path to ParseDisplayName. Note that ParseDisplayName requires the directory's path to be a Unicode string. The application then binds to the source directory and uses its IShellFolder interface to retrieve an enumerator object's IEnumIDList interface. As each file in the source directory is enumerated, GetDisplayNameOf is used to retrieve its name. The SHGDN_FORPARSING flag is set, which causes GetDisplayNameOf to return the file's fully qualified path. The file paths, including the terminating NULL characters, are concatenated into a single array, szSourceFiles. A second NULL character is appended to the final path to terminate the array properly. Once the enumeration is complete, the application assigns values to an SHFILEOPSTRUCT structure. Note that the array assigned to pTo to specify the destination must also be terminated by a double NULL. In this case, it is simply included in the string that is assigned to pTo. Because this is a console application, the FOF_SILENT, FOF_NOCONFIRMATION, and FOF_NOCONFIRMMKDIR flags are set to suppress any dialog boxes that might appear. After SHFileOperation returns, SHChangeNotify is called to notify the Shell of the change. Then the application performs the usual cleanup and returns. Adding Files to the Shell's List of Recent Documents The Shell maintains a list of recently added or modified documents for each user. The user can display a list of links to these files by clicking Documents on the Start menu. As with My Documents, each user has a file system directory to hold the actual links. To retrieve the PIDL of the current user's Recent directory, your application can call SHGetFolderLocation with CSIDL_RECENT, or call SHGetFolderPath to retrieve its path. Your application can enumerate the contents of the Recent folder using the techniques discussed earlier in this document. However, an application should not modify the contents of the folder as if it were a normal file system folder. If it does so, the Shell's list of recent documents will not be updated properly, and the changes will not be reflected in the Start menu. Instead, to add a document link to a user's Recent folder, your application can call SHAddToRecentDocs. The Shell will add a link to the appropriate file system folder, as well as updating its list of recent documents and the Start menu. You can also use this function to clear the folder. **Managing Printers The Shell application programming interface (API) provides functions that you can use to manage networked printers. If a file has the print verb associated with it, you can use the ShellExecuteEx command to print it. For further discussion of printing, see Printing and Print Spooler. Printer Management Printing Files with ShellExecuteEx Printer Management You can manage printers on a system with the SHInvokePrinterCommand function. This function allows you to: Install printers. Open printers. Get printer properties. Create printer links. Print a test page. Printing Files with ShellExecuteEx If a file type has a print command associated with it, you can print the file by calling ShellExecuteEx with print as the verb. This command is often the same as that used for the open verb, with the addition of a flag to tell the application to print the file. For instance, .txt files can be printed by Microsoft WordPad. The open verb for a .txt file would thus correspond to something like the following command: "C:\Program Files\Windows NT\Accessories\Wordpad.exe" /p "%1" When you use ShellExecuteEx to print a .txt file, WordPad opens the file, prints it, and then closes, returning control to the application. The following sample function takes a fully qualified path, and uses ShellExecuteEx to print it, using the print command associated with its file name extension. Show Example #include HINSTANCE PrintFile(LPCTSTR pszFileName) { SHELLEXECUTEINFO ShExecInfo; HINSTANCE hInst; // Fill the SHELLEXECUTEINFO array. ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO); ShExecInfo.fMask = NULL; ShExecInfo.hwnd = NULL; ShExecInfo.lpVerb = "print"; ShExecInfo.lpFile = pszFileName; // a fully qualified path ShExecInfo.lpParameters = NULL; ShExecInfo.lpDirectory = NULL; ShExecInfo.nShow = SW_MAXIMIZE; ShExecInfo.hInstApp = NULL; hInst = ShellExecuteEx(&ShExecInfo); return hInst; } **Transferring Shell Objects with Drag-and-Drop and the Clipboard Many applications allow users to transfer data to another application by dragging and dropping the data with the mouse, or by using the Clipboard. Among the many types of data that can be transferred are Shell objects such as files or folders. Shell data transfer can take place between two applications, but users can also transfer Shell data to or from the desktop or Microsoft Windows Explorer. Although files are the most commonly transferred Shell object, Shell data transfer can involve any of the variety of objects found in the Shell namespace. For instance, your application might need to transfer a file to a virtual folder such as the Recycle Bin, or accept an object from a non-Microsoft namespace extension. If you are implementing a namespace extension, it must be able to behave properly as a drop source and target. This document discusses how applications can implement drag-and-drop and Clipboard data transfers with Shell objects. The Shell Data Object Shell Clipboard Formats Handling Shell Data Transfer Scenarios How Drag-and-Drop Works with Shell Objects Applications often need to provide users with a way to transfer Shell data. Some examples are: Dragging a file from Windows Explorer or the desktop and dropping it on an application. Copying a file to the Clipboard in Windows Explorer and pasting it into an application. Dragging a file from an application to the Recycle Bin. For a detailed discussion of how to handle these and other scenarios, see Handling Shell Data Transfer Scenarios. This document focuses on the general principles behind Shell data transfer. Windows provides two standard ways for applications to transfer Shell data: A user cuts or copies Shell data, such as one or more files, to the Clipboard. The other application retrieves the data from the Clipboard. A user drags an icon that represents the data from the source application and drops the icon on a window owned by the target. In both cases, the transferred data is contained in a data object. Data objects are Component Object Model (COM) objects that expose the IDataObject interface. Schematically, there are three essential steps that all Shell data transfers must follow: The source creates a data object that represents the data that is to be transferred. The target receives a pointer to the data object's IDataObject interface. The target calls the IDataObject interface to extract the data from it. The difference between Clipboard and drag-and-drop data transfers lies primarily in how the IDataObject pointer gets from the source to the target. Clipboard Data Transfers The Clipboard is the simplest way to transfer Shell data. The basic procedure is similar to standard Clipboard data transfers. However, because you are transferring a pointer to a data object, not the data itself, you must use the OLE clipboard application programming interface (API) instead of the standard clipboard API. The following procedure outlines how to use the OLE clipboard API to transfer Shell data with the Clipboard: The data source creates a data object to contain the data. The data source calls OleSetClipboard, which places a pointer to the data object's IDataObject interface on the Clipboard. The target calls OleGetClipboard to retrieve the pointer to the data object's IDataObject interface. The target extracts the data by calling the IDataObject::GetData method. With some Shell data transfers, the target might also need to call the data object's IDataObject::SetData method to provide feedback to the data object on the outcome of the data transfer. See Handling Optimized Move Operations for an example of this type of operation. Drag-and-Drop Data Transfers While somewhat more complex to implement, drag-and-drop data transfer has some significant advantages over the Clipboard: Drag-and-drop transfers can be done with a simple mouse movement, making operation more flexible and intuitive to use than the Clipboard. Drag-and-drop provides the user with a visual representation of the operation. The user can follow the icon as it moves from source to target. Drag-and-drop notifies the target when the data is available. Drag-and-drop operations also use data objects to transfer data. However, the drop source must provide functionality beyond that required for Clipboard transfers: The drop source must also create an object that exposes an IDropSource interface. The system uses IDropSource to communicate with the source while the operation is in progress. The drag-and-drop data object is responsible for tracking cursor movement and displaying an icon to represent the data object. Drop targets must also provide more functionality than is needed to handle Clipboard transfers: The drop target must expose an IDropTarget interface. When the cursor is over a target window, the system uses IDropTarget to provide the target with information such as the cursor position, and to notify it when the data is dropped. The drop target must register itself with the system by calling RegisterDragDrop. This function provides the system with the handle to a target window and a pointer to the target application's IDropTarget interface. Note For drag-and-drop operations, your application must initialize COM with OleInitialize, not CoInitialize. The following procedure outlines the essential steps that are typically used to transfer Shell data with drag-and-drop: The target calls RegisterDragDrop to give the system a pointer to its IDropTarget interface and register a window as a drop target. When the user starts a drag-and-drop operation, the source creates a data object and initiates a drag loop by calling DoDragDrop. When the cursor is over the target window, the system notifies the target by calling one of the target's IDropTarget methods. The system calls IDropTarget::DragEnter when the cursor enters the target window, and IDropTarget::DragOver as the cursor passes over the target window. Both methods provide the drop target with the current cursor position and the state of keyboard modifier keys such as CTRL or ALT. When the cursor leaves the target window, the system notifies the target by calling IDropTarget::DragLeave. When any of these methods return, the system calls the IDropSource interface to pass the return value to the source. When the user releases the mouse button to drop the data, the system calls the target's IDropTarget::Drop method. Among the method's parameters is a pointer to the data object's IDataObject interface. The target calls the data object's IDataObject::GetData method to extract the data. With some Shell data transfers, the target might also need to call the data object's IDataObject::SetData method to provide feedback to the source on the outcome of the data transfer. When the target is finished with the data object, it returns from IDropTarget::Drop. The system returns the source's DoDragDrop call to notify the source that the data transfer is complete. Depending on the particular data transfer scenario, the source might need to take additional action based on the value returned by DoDragDrop and the values that are passed to the data object by the target. For instance, when a file is moved, the source must check these values to determine whether it must delete the original file. The source releases the data object. While the procedures outlined above provide a good general model for Shell data transfer, there are many different types of data that can be contained in a Shell data object. There are also a number of different data transfer scenarios that your application might need to handle. Each data type and scenario requires a somewhat different approach to three key steps in the procedure: How a source constructs a data object to contain the Shell data. How a target extracts Shell data from the data object. How the source completes the data transfer operation. The Shell Data Object provides a general discussion of how a source constructs a Shell data object, and how that data object can be handled by the target. Handling Shell Data Transfer Scenarios discusses in detail how to handle a number of common Shell data transfer scenarios. **Debugging with the Shell This overview explains how to debug Shell and namespace extension dynamic-link libraries (DLLs). Running the Shell Under a Debugger Running and Testing Shell Extensions on Windows NT Unloading the DLL Running the Shell Under a Debugger To debug your extension, you need to execute the Shell from the debugger. Follow these steps: Load the extension's project into the debugger, but do not run it. From the Start menu on the Microsoft Windows taskbar, choose Shut Down. Press CTRL+ALT+SHIFT, and click No in the Shut Down Windows dialog box. On Windows 2000, click Cancel instead of No. The Shell is now shut down, but all other applications are still running, including the debugger. Set the debugger to run the extension DLL with Explorer.exe from the Windows directory. Run the project from the debugger. The Shell will start up as usual, but the debugger will be attached to the Shell's process. Running and Testing Shell Extensions on Windows NT You can run and test your Microsoft Windows NT extensions in a separate Windows Explorer process to avoid stopping and restarting the desktop and taskbar. Your desktop and taskbar can still be used while you run and test the extensions. To enable this feature, add the following value to the registry. HKEY_CURRENT_USER Software Microsoft Windows CurrentVersion Explorer DesktopProcess (REG_DWORD)= 1 For this value to take effect, you must log off and log on again. This setting causes the desktop and taskbar windows to be created in one Explorer.exe process, and all other Explorer and folder windows to be opened in a different Explorer.exe process. In addition to making running and testing your extensions more convenient, this setting also makes the desktop more robust as it relates to Shell extensions. Many such extensions (shortcut menu extensions, for example) will be loaded into the nondesktop Explorer.exe process. If this process terminates, the desktop and taskbar will be unaffected, and the next Explorer or folder window will re-create the terminated process. Unloading the DLL The Shell automatically unloads a DLL when its usage count is zero, but only after the DLL has not been used for a period of time. This inactive period might be unacceptably long at times, especially when a Shell extension DLL is being debugged. For operating systems prior to Windows 2000, you can shorten the inactive period by adding the following information to the registry. HKEY_LOCAL_MACHINE Software Microsoft Windows CurrentVersion Explorer AlwaysUnloadDll **Scriptable Shell Objects The Microsoft Windows Shell provides a powerful set of automation objects that enable you to program the Shell with Microsoft Visual Basic and scripting languages such as Microsoft JScript (compatible with ECMA 262 language specification) and Visual Basic Scripting Edition (VBScript). You can use these objects to access many of the Shell's features and dialog boxes. For example, you can access the file system, launch programs, and change system settings. This section introduces the scriptable Shell objects. Shell Versions Instantiating Shell Objects Shell Object Folder Objects Shell Versions Many of the Shell objects became available in version 4.71 of the Shell. Others are available in version 5.00 and later. This means that on computers running Windows 95 or Microsoft Windows NT 4.0, the Shell objects are available only if the integrated desktop is installed. Version 4.71 of the Shell is on all Windows 98 computers, and version 5.00 is on all Windows 2000 computers. The following table lists each Shell object under the version of the Shell in which the object became available. Table with 2 columns and 12 rows Version 4.71 Version 5.00 Folder DIDiskQuotaUser FolderItemVerb DiskQuotaControl FolderItemVerbs Folder2 Shell FolderItem ShellFolderView FolderItems ShellUIHelper FolderItems2 ShellWindows IShellDispatch2 WebViewFolderContents IShellLinkDual2 ShellFolderItem ShellFolderViewOC ShellLinkObject table end Instantiating Shell Objects To instantiate the Shell objects in Visual Basic applications with early binding, add references to the following libraries in your project: Microsoft Internet Controls (SHDocVw) Microsoft Shell Controls and Automation (Shell32) Late Binding You can also instantiate many of the Shell objects with late binding. This approach works in Visual Basic applications and in script. The following example shows how to instantiate the Shell object in JScript. The following example shows how to instantiate the Folder object in VBScript. Show Example In the preceding example, sDir is the path to the Folder object. Note that the ShellSpecialFolderConstants enumeration values are not available in script. The ProgID for each of the Shell objects is shown in the following table. Table with 2 columns and 20 rows Object ProgID DIDiskQuotaUser Microsoft.DiskQuota.1 DiskQuotaControl Cannot late bind Folder Shell.Application.NameSpace("...") Folder2 Shell.Application.NameSpace("...") FolderItem Shell.Application.NameSpace("...").Self or Folder.Items.Item or Folder.ParseName FolderItems Folder.Items FolderItems2 Folder.Items FolderItemVerb Shell.NameSpace("...").Self.Verbs.Item() FolderItemVerbs FolderItem.Verbs or Shell.NameSpace("...").Self.Verbs IShellDispatch2 Shell.Application IShellLinkDual2 Shell.NameSpace("...").Self.GetLink or Shell.NameSpace("...").Items().GetLink Shell Shell.Application ShellFolderItem Shell.NameSpace("...").Self or Shell.NameSpace("...").Items() ShellFolderView Cannot late bind ShellFolderViewOC Cannot late bind ShellLinkObject Shell.NameSpace("...").Self.GetLink or Shell.NameSpace("...").Items().GetLink ShellUIHelper Cannot late bind ShellWindows Shell.Windows or ShellWindows._NewEnum WebViewFolderContents Cannot late bind table end HTML OBJECT Element You can also use the OBJECT element to instantiate Shell objects on an HTML page. To do this, set the OBJECT element's ID attribute to the variable name you will use in your scripts, and identify the object using its registered number (CLASSID). The following HTML creates an instance of the ShellFolderItem object using the OBJECT element. The following table lists each Shell object and its respective CLASSID. Table with 2 columns and 19 rows DIDiskQuotaUser 7988B571-EC89-11cf-9C00-00AA00A14F56 DiskQuotaControl 7988B571-EC89-11cf-9C00-00AA00A14F56 Folder BBCBDE60-C3FF-11CE-8350-444553540000 Folder2 f0d2d8ef-3890-11d2-bf8b-00c04fb93661 FolderItem 744129E0-CBE5-11CE-8350-444553540000 FolderItems 744129E0-CBE5-11CE-8350-444553540000 FolderItems2 C94F0AD0-F363-11d2-A327-00C04F8EEC7F FolderItemVerb 08EC3E00-50B0-11CF-960C-0080C7F4EE85 FolderItemVerbs 1F8352C0-50B0-11CF-960C-0080C7F4EE85 IShellDispatch2 A4C6892C-3BA9-11d2-9DEA-00C04FB16162 IShellLinkDual2 317EE249-F12E-11d2-B1E4-00C04F8EEB3E Shell 13709620-C279-11CE-A49E-444553540000 ShellFolderItem 2fe352ea-fd1f-11d2-b1f4-00c04f8eeb3e ShellFolderView 62112AA1-EBE4-11cf-A5FB-0020AFE7292D ShellFolderViewOC 4a3df050-23bd-11d2-939f-00a0c91eedba ShellLinkObject 11219420-1768-11d1-95BE-00609797EA4F ShellUIHelper 64AB4BB7-111E-11D1-8F79-00C04FC2FBE1 ShellWindows 9BA05972-F6A8-11CF-A442-00A0C90A8F39 WebViewFolderContents 1820FED0-473E-11D0-A96C-00C04FD705A2 table end Shell Object The Shell object represents the objects in the Windows Shell. You can use the methods exposed by the Shell object to: Open, explore, and browse for folders. Minimize, restore, cascade, or tile open windows. Launch Control Panel applications. Display system dialog boxes. Users are perhaps most familiar with the commands they access from the Start menu and the taskbar's shortcut menu. The taskbar's shortcut menu appears when users right-click the taskbar. The following HTML Application (HTA) produces a start page with buttons that implement many of the Shell object's methods. Some of these methods implement features on the Start menu and the taskbar's shortcut menu. Show Example Start Page

Start...









Security As an application, an HTA runs under a different security model than a Web page. To interact with a Web page that implements the functionality of the Shell objects, users must enable the Initialize and script ActiveX Controls not marked as safe option for the security zone in which they are viewing the page. Folder Objects The Folder object represents a Shell folder. You can use the methods exposed by the Folder object to: Get information about a folder. Create subfolders. Copy and move file objects into the folder. The FolderItem object represents an item in a Shell folder. Its properties enable you to retrieve information about the item. You can use the methods exposed by this object to execute an item's verbs, or to retrieve information about an item's FolderItemVerbs object. The FolderItems object represents a collection of items in a Shell folder. Its methods and properties enable you to retrieve information about the collection. The following Visual Basic example shows the relationship between several of the folder objects and how they can be used together. When the user clicks the command button called cmdGetPath, the program displays a dialog box that enables the user to select a folder from My Computer, where ssfDRIVES is the ShellSpecialFolderConstants enumeration value for My Computer. When the user chooses a folder, the folder's path is displayed in the text box called txtPath. Private Sub cmdGetPath_Click() Dim oShell As New Shell Dim oFolder As Folder Dim oFolderItem As FolderItem Set oFolder = oShell.BrowseForFolder(Me.hWnd, "Select a Folder", 0, ssfDrives) Set oFolderItem = oFolderItems.Item txtPath.Text = oFolderItem.Path End Sub In VBScript, this function is slightly different because the ShellSpecialFolderConstants enumeration values are not available in script. The following example shows the VBScript equivalent of the previous example. Show Example In the following JScript example, which is a direct translation of the preceding VBScript example, note how the empty parentheses '()' are used to invoke the Items and Item methods. Show Example **Shell Basics: Extending the Shell By integrating your application with the Shell, you can extend the Shell's functionality and customize certain aspects of its behavior. In order of increasing complexity, you can extend the Shell by: Putting information in the registry or in special files. Implementing a Shell extension handler. Implementing a namespace extension. The first approach, which is used by many applications, is discussed in the following documentation. Creating a File Association Customizing Icons Extending Shortcut Menus Customizing Folders with Desktop.ini Creating an AutoRun-enabled CD-ROM Application Using Hardware AutoPlay For a discussion of how to write extension handlers, see Creating Shell Extension Handlers. For a discussion of how to write namespace extensions, see Creating a Shell Namespace Extension. Note To improve the readability of the sample code in the Shell Basics documentation, most of the normal error-correction code has been removed. You should add error code, as appropriate, to your own applications. To make registry samples more readable, key names are in a bold font and values are in a normal font. **Creating a File Association Files that contain a particular type of data commonly have the same file name extension. It is appended to the file name and typically consists of a period followed by three alphanumeric characters. For example, ANSI text files commonly have a .txt file name extension. Although it is customary, file name extensions are not restricted to three letters on systems that support long file names. On Microsoft Windows 95 and later systems, you can use any number of characters you like as long as the file name doesn't exceed 255 characters. Note You can use multiple periods in a file name, but only those characters following the final period are recognized as a file name extension. Any other periods are treated as part of the file name. Although file names can contain spaces, do not use spaces in file name extensions. Any time you create or change a file association, it is important to notify the system that you have made a change with SHChangeNotify, specifying the SHCNE_ASSOCCHANGED event. If you do not call SHChangeNotify, the change might not be recognized until the system is rebooted. Defining a File Class Defining Attributes for a File Class Registering an Application to Handle Arbitrary File Classes Excluding an Application from the Open With Dialog Box Defining a File Class Files with a common file name extension can be defined as members of a file class. Defining a file class allows you to extend the Shell by customizing the behavior of all files in the class. The Shell Basics: Extending the Shell section discusses those behaviors that can be customized by adding registry entries or special files, including: Specifying the application used to open the file when it is double-clicked. Adding commands to the shortcut menu. Specifying a custom icon. For a greater degree of control over the behavior of a file class, you can write one or more Creating Shell Extension Handlers. To define a file class, first create a registry key for the extension, including the period, under HKEY_CLASSES_ROOT . Set the key's value to the ProgID for the associated application. Next, create a second key under HKEY_CLASSES_ROOT for the application's ProgID. Set it to a REG_SZ value that describes the application. For example, to create a file class with an .myp extension and an associated application, MyProgram.exe with a ProgID of MyProgram.1, the registry entries would be as follows. HKEY_CLASSES_ROOT .myp (Default) = MyProgram.1 MyProgram.1 (Default) = MyProgram Application A user can act on a member of the file class in a variety of ways, such as double-clicking or right-clicking the file in Windows Explorer. Once these two keys are in place, you can add subkeys to them to customize the behavior of the file class and its associated application. When a user acts on a member of the class, the Shell's response includes the information contained in these keys. Defining Attributes for a File Class Assigning attributes to a file class allows you to control some aspects of its behavior. It also allows you to limit the extent to which the user can modify various aspects of the class, such as its icon or verbs, with the Folder Options property sheet. The attributes are defined as binary flags. To assign attributes to a file class, combine the selected attributes with a logical OR to form a single attribute value. Add an EditFlags REG_BINARY value to the class's ProgID key and set it to the attribute value. The following table lists the file class attributes and their numerical values. Table with 3 columns and 20 rows Flag Value Description FTA_Exclude 0x00000001 Exclude the file class. FTA_Show 0x00000002 Show file classes, such as folders, that aren't associated with a file name extension. FTA_HasExtension 0x00000004 The file class has a file name extension. FTA_NoEdit 0x00000008 The registry entries associated with this file class cannot be edited. New entries cannot be added and existing entries cannot be modified or deleted. FTA_NoRemove 0x00000010 The registry entries associated with this file class cannot be deleted. FTA_NoNewVerb 0x00000020 No new verbs can be added to the file class. FTA_NoEditVerb 0x00000040 Canonical verbs such as open and print cannot be modified or deleted. FTA_NoRemoveVerb 0x00000080 Canonical verbs such as open and print cannot be deleted. FTA_NoEditDesc 0x00000100 The description of the file class cannot be modified or deleted. FTA_NoEditIcon 0x00000200 The icon assigned to the file class cannot be modified or deleted. FTA_NoEditDflt 0x00000400 The default verb cannot be modified. FTA_NoEditVerbCmd 0x00000800 The commands associated with verbs cannot be modified. FTA_NoEditVerbExe 0x00001000 Verbs cannot be modified or deleted. FTA_NoDDE 0x00002000 The Dynamic Data Exchange (DDE)-related entries cannot be modified or deleted. FTA_NoEditMIME 0x00008000 The content-type and default-extension entries cannot be modified or deleted. FTA_OpenIsSafe 0x00010000 The file class's open verb can be safely invoked for downloaded files. Note that this flag may create a security risk, because downloaded files could contain malicious content. To reduce this risk, consider methods to scan downloaded files before opening. FTA_AlwaysUnsafe 0x00020000 Do not allow the Never ask me check box to be enabled. The user can override this attribute through the File Type dialog box. This flag also affects ShellExecute, download dialogs, and any application making use of the AssocIsDangerous function. FTA_AlwaysShowExt 0x00040000 Always show the file class's file name extension, even if the user has selected the Hide Extensions option. FTA_NoRecentDocs 0x00100000 Don't add members of this file class to the Recent Documents folder. table end The following example assigns the FTA_NoRemove (0x00000010) and FTA_NoNewVerb (0x00000020) attributes to the .myp file class. HKEY_CLASSES_ROOT .myp (Default) = MyProgram.1 MyProgram.1 (Default) = MyProgram Application EditFlags= 30 00 00 00 Registering an Application to Handle Arbitrary File Classes The most common use of file classes is to associate a file name extension with the application that should be used to open members of the class. The user can then open a file by double-clicking the file icon or by selecting a command such as Open or Edit from the file's shortcut menu. Some applications can be associated with a single file class; other applications can be associated with many file classes. For a detailed discussion of how to implement this behavior, see Extending Shortcut Menus. In some cases, however, the user might attempt to open a member of a file class with an application that is not associated with the class. For example, if the user double-clicks a file that is not associated with an application, an Open With dialog box appears that allows him or her to specify which application should open the file. The user can also use this dialog box to specify which application is associated with a particular file name extension. The following illustration shows a typical Open With dialog box. Open With dialog box In most cases, the application is asked to open a file that it is capable of handling. For example, many applications can handle .txt files. In other cases, the file might be completely incomprehensible. The ways that applications open arbitrary files can be divided into three general classes: Class 1. Open only those file classes that have a registered association with the application. If the user attempts to have the application open any other file class, return an error. Applications of this type are typically designed to work only with certain proprietary file formats. Class 2. Use the same procedure to open any file. Examine the contents of the file and display the file, if possible. Only return errors for those files that the application cannot handle. Applications of this sort are typically designed to work with a common file format, such as ANSI text, that can be the underlying format of many file classes. Class 3. Have one set of procedures for opening files that have a registered association with the application. Provide a default procedure to open all other files. Applications of this sort are usually a hybrid of the first two classes. They have one or more proprietary formats that need special handling, but they are also capable of handling some standard formats. Assume, for instance, that the MyProgram application discussed in the preceding sections of this document can also handle .txt files. If a user attempts to use the Open With dialog box to open a .txt file with MyProgram, or associate .txt files with MyProgram, the Shell attempts to open the file as if it were an .myp file. What happens next depends on how the application opens files. If MyProgram falls into either of the first two classes, there is no need for special handling by the Shell. For class 1, MyProgram would simply examine the file name, see that it lacked an .myp extension, and return an error. For class 2, MyProgram would use its standard procedure for opening all files. However, with Windows 2000, the Shell can be extended to make class 3 applications easier to implement as well as provide two important new features for users. What makes the third class of applications more difficult is that, if MyProgram is expecting a proprietary .myp file, it might have problems handling a .txt file. On the other hand, writing a general-purpose routine to open all files the same way can be inefficient. Instead, the Shell allows you to register normal file associations for your proprietary formats, plus a default procedure to be used for arbitrary file types. When a user attempts to open one of your proprietary files, the file is opened as specified by the file association. If a user attempts to open an arbitrary file type, the file is opened as specified by the default procedure. The ability to define a default file opening procedure also supports two new features that are helpful to users: If the user uses the Open With dialog box to associate a file name extension with an application, that choice is always respected. Applications that are subsequently installed are not permitted to take over the file association. File associations can roam with the user. For example, assume that the user has associated MyProgram with .htm files on his or her primary computer. When that user attempts to open an .htm file on a different computer, MyProgram is used, if available. The procedure for registering an application to accept arbitrary file classes is similar to that used to define shortcut menus for a file class. For a detailed discussion, see Extending Shortcut Menus. Excluding an Application from the Open With Dialog Box The applications that are listed in the Open With dialog box are registered as subkeys of HKEY_CLASSES_ROOT\Applications . However, many applications should not be used to open files that are not members of their associated file class. To exclude an application from the Open With dialog box, add a NoOpenWith REG_SZ value name to the application's subkey. For example, the following sample registry entry excludes MyProgram.exe from the Open With dialog box. HKEY_CLASSES_ROOT Applications MyProgram.exe NoOpenWith It is also possible to exclude an application from the Open With dialog box by appending the application's file name to the Windows Explorer kill list. This option is not recommended and is discussed here only for completeness. The kill list is a REG_SZ value of the following key. HKEY_LOCAL_MACHINE Software Microsoft Windows CurrentVersion Explorer FileAssociation The kill list is a string consisting of the file names of the applications, separated by semicolons (;). **Customizing Icons Microsoft Windows supplies default icons for every item displayed on the desktop and in Windows Explorer. Mass storage devices, such as disk drives, are also assigned default icons. However, these icons often provide little insight to the user as to the contents of the file or what program is associated with it. You can assign a custom icon to a file system folder by creating a Desktop.ini file. This document discusses how to use the registry to associate custom icons with file classes and drive letters. Assigning a Custom Icon to a File Class Assigning a Custom Icon and Label to a Drive Letter Assigning a Custom Icon to a File Class By default, all files are displayed on the desktop and in Windows Explorer with default icons. For example, the following illustration shows this icon used with MyDocs4.xyz. Default icon All the files displayed in this screen shot contain ANSI text. The reason that the files with the .txt extension do not display the default icon is that .txt has been registered as a file class and assigned a custom icon. Assigning a custom icon to a file class is a simple matter. Create a subkey, under the key for the application's ProgID, and name it DefaultIcon . Assign it a REG_SZ value containing the fully qualified path for the file with the icon. Any file containing an icon is acceptable, including .ico, .exe, and .dll files. If there is more than one icon in the file, the path should be followed by a comma, and then the index of the icon. The following illustration shows a custom icon that has been assigned to the .myp file class, which was also used in the example in Creating a File Class. The My Documents directory now looks like this: Custom icon for .myp files In this example, the icon is in the c:\MyDir\MyProgram.exe file, with an index of two. The registry entry that assigns the custom icon to all .myp files is as shown here. HKEY_CLASSES_ROOT .myp (Default) = MyProgram.1 MyProgram.1 (Default) = MyProgram Application DefaultIcon (Default) = C:\MyDir\MyProgram.exe,2 Finally, call SHChangeNotify to notify the Shell to update its cache. Assigning a Custom Icon and Label to a Drive Letter For Shell versions 4.71 and later, you can use the registry to replace the standard drive icon with a custom icon. With versions 5.0 and later, you can also add a custom label. Custom drive icons and labels are normally used for removable mass storage devices, such as tape drives, to allow users to easily distinguish them from their system's hard and floppy drives. To replace the standard drive icon with a custom icon in Windows 2000, add a subkey named for the drive letter to the following key. HKEY_CLASSES_ROOT Applications Explorer.exe Drives To replace the standard drive icon with a custom icon in all versions of Windows other than Windows 2000, add a subkey named for the drive letter to the following key. HKEY_LOCAL_MACHINE Software Microsoft Windows CurrentVersion Explorer DriveIcons The drive letter should not be followed by a colon (:). Add a DefaultIcon subkey to the drive letter subkey and set its default value to a string containing the location of the icon. The first part of the string contains the fully-qualified path of the icon's file. If there is more than one icon in the file, the path is followed by a comma, and then by the zero-based index of the icon. If you are using Windows Millennium Edition (Windows Me) or later, add a custom label by adding a DefaultLabel subkey to the drive letter subkey, and setting its default value to a string containing the label. The following example specifies a custom icon and label for the E: drive. The icon is in the C:\MyDir\MyDrive.exe file with a zero-based index of three. For Windows 2000: HKEY_CLASSES_ROOT Applications Explorer.exe Drives E DefaultIcon (Default) = C:\MyDir\MyDrive.exe,3 DefaultLabel (Default) = MyDrive For all other versions of Windows: HKEY_LOCAL_MACHINE Software Microsoft Windows CurrentVersion Explorer DriveIcons E DefaultIcon (Default) = C:\MyDir\MyDrive.exe,3 DefaultLabel (Default) = MyDrive Note The DefaultLabel key was introduced in Windows Me and Windows 2000. It should not be used with earlier versions of Windows. In all versions of Windows, if you change a file class or drive icon you must also call SHUpdateImage to notify the Shell to update any icons currently displayed. **Extending Shortcut Menus Right-clicking an object on Microsoft Windows 95 and later systems usually pops up a shortcut menu. This menu contains a list of commands that the user can select to perform various actions on the object. This section is an introduction to shortcut menus for file system objects. Shortcut Menus for File System Objects Shortcut Menu Verbs Extending the Shortcut Menu for a File Class Extending the Shortcut Menu for Predefined Shell Objects Registering an Application to Handle Arbitrary File Classes Extending the New Submenu Shortcut Menus for File System Objects When a user right-clicks an object, such as a file, that is displayed in Windows Explorer or on the desktop, a shortcut menu appears with a list of commands. The user can then perform an action on the file, such as opening or deleting it, by selecting the appropriate command. Because shortcut menus are often used for file management, the Shell provides a set of default commands, such as Cut and Copy, that appear on the shortcut menu for any file. Note that although Open With is a default command, it is not displayed for some standard file classes, such as .wav. The following illustration of the sample My Documents directory, which was also used as an example in Customizing Icons, shows a default shortcut menu that was displayed by right-clicking MyDocs4.xyz. Default shortcut menu for file system objects The reason that MyDocs4.xyz shows a default shortcut menu is that it is not a member of a registered file class. On the other hand, .txt is a registered file class. If you right-click one of the .txt files, you will instead see a shortcut menu with two additional commands in its upper section: Open and Print. Customized shortcut menu for file system objects Once a file class is registered, you can extend its context with additional commands. They are displayed above the default commands when any member of the class is right-clicked. Although most of the commands added in this way are common ones, such as Print or Open, you are free to add any command that a user might find helpful. All that is required to extend the shortcut menu for a file class is to create a registry entry for each command. A more sophisticated approach is to implement a shortcut menu handler, which allows you to extend the shortcut menu for a file class on a file-by-file basis. For more information, see Creating Context Menu Handlers. Shortcut Menu Verbs Each command on the shortcut menu is identified in the registry by its verb. These verbs are the same as those used by ShellExecuteEx when launching applications programmatically. For further information about the use of ShellExecuteEx, see the discussion in Launching Applications. A verb is a simple text string that is used by the Shell to identify the associated command. Each verb corresponds to the command string used to launch the command in a console window or batch (.bat) file. For example, the open verb normally launches a program to open a file. Its command string typically looks something like this: "My Program.exe" "%1" Note If any element of the command string contains or might contain spaces, it must be enclosed in quotation marks. Otherwise, if the element contains a space, it will not parse correctly. For instance, "My Program.exe" will launch the application properly. If you use My Program.exe, the system will attempt to launch "My" with "Program.exe" as its first command line argument. You should always use quotation marks with arguments such as "%1" that are expanded to strings by the Shell, because you cannot be certain that the string will not contain a space. Verbs can also have a display string associated with them, which is displayed on the shortcut menu instead of the verb string itself. For example, the display string for openas is Open With. Like normal menu strings, including an ampersand (&) in the display string allows keyboard selection of the command. Canonical Verbs In general, applications are responsible for providing localized display strings for the verbs they define. However, to provide a degree of language independence, the system defines a standard set of commonly used verbs called canonical verbs. A canonical verb can be used with any language, and the system automatically generates a properly localized display string. For instance, the open verb's display string will be set to Open on an English system, and to Öffnen on a German system. The canonical verbs include: Table with 2 columns and 8 rows Value Description open Opens the file or folder, possibly in an existing window. opennew Opens the file or folder in a new window. print Prints the file. explore Opens Windows Explorer with the folder selected. find Opens the Windows Search dialog box with the folder set as the default search location. openas Opens the Open With dialog box. properties Opens the object's property sheet. table end The printto verb is also canonical but is never displayed. It allows the user to print a file by dragging it to a printer object. Extended Verbs When the user right-clicks an object, the shortcut menu contains all the normal verbs. However, there could be commands that you want to support but not have displayed on every shortcut menu. For example, you could have commands that are not commonly used or that are intended for experienced users. For this reason, you can also define one or more extended verbs. These verbs are also character strings and are similar to normal verbs. They are distinguished from normal verbs by the way they are registered. To have access to the commands associated with extended verbs, the user must right-click an object while pressing the SHIFT key. The extended verbs will then be displayed along with the normal verbs. Extending the Shortcut Menu for a File Class The simplest way to extend the shortcut menu for a file class is with the registry. To do this, add a Shell subkey below the key for the ProgID of the application associated with the file class. Optionally, you can define a default verb for the file class by making it the default value of the Shell subkey. The default verb is displayed first on the shortcut menu. Its purpose is to provide the Shell with a verb it can use when ShellExecuteEx is called but no verb is specified. The Shell does not necessarily select the default verb when ShellExecuteEx is used in this fashion. For Shell versions 5.0 and later, found on Windows 2000 and later systems, the Shell uses the first available verb from the following list. If none are available, the operation fails. The open verb The default verb The first verb in the registry The openwith verb For Shell versions prior to version 5.0, omit the third item. Below the Shell subkey, create one subkey for each verb you want to add. Each of these subkeys will have a REG_SZ value set to the verb's display string. You can omit the display string for canonical verbs because the system will automatically display a properly localized string. If you omit the display string for noncanonical verbs, the verb string will be displayed. For each verb subkey, create a command subkey with the default value set to the command string. The following illustration shows a shortcut menu for the .myp file class used in Creating a File Association and Customizing Icons. It now has open, doit, print, and printto verbs on its shortcut menu, with doit as the default verb. The shortcut menu looks like this. Customized shortcut menu The registry entries used to extend the shortcut menu shown in the preceding illustration are: HKEY_CLASSES_ROOT .myp (Default) = MyProgram.1 MyProgram.1 (Default) = MyProgram Application Shell (Default) = doit open command (Default) = C:\MyDir\MyProgram.exe "%1" doit (Default) = &Do It command (Default) = C:\MyDir\MyProgram.exe /d "%1" print command (Default) = C:\MyDir\MyProgram.exe /p "%1" printto command (Default) = C:\MyDir\MyProgram.exe /p "%1" "%2" %3 %4 Although the Open With command is above the first separator, it is automatically created by the system and doesn't require a registry entry. The system automatically creates display names for the canonical verbs open and print. Because doit is not a canonical verb, it is assigned a display name, "&Do It", which can be selected by pressing the D key. The printto verb does not appear on the shortcut menu, but including it allows the user to print files by dropping them on a printer icon. In this example, %1 represents the file name and %2 the printer name. You can ignore %3 and %4 for Windows 95 and later systems. For Windows 3.1 systems, %3 represents the driver name and %4 the port name. Unlike most similar arguments, the %3 and %4 arguments of printto should not be enclosed in quotation marks. Verbs can be suppressed through policy settings by adding a SuppressionPolicy value to the verb's key. Set the value of SuppressionPolicy to the policy ID. If the policy is turned on, the verb and its associated shortcut menu entry are suppressed. For possible policy ID values, see the RESTRICTIONS enumeration. Defining Extended Verbs You can also use the registry to define one or more extended verbs. The associated commands will be displayed only when the user right-clicks an object while also pressing the SHIFT key. To define a verb as extended, simply add an "extended" REG_SZ value to the verb's subkey. The value should not have any data associated with it. The following sample registry entry shows the example from the previous section, with doit defined as an extended verb. HKEY_CLASSES_ROOT .myp (Default) = MyProgram.1 MyProgram.1 (Default) = MyProgram Application Shell (Default) = doit open command (Default) = C:\MyDir\MyProgram.exe "%1" doit (Default) = &Do It extended command (Default) = C:\MyDir\MyProgram.exe /d "%1" print command (Default) = C:\MyDir\MyProgram.exe /p "%1" printto command (Default) = C:\MyDir\MyProgram.exe /p "%1" "%2" %3 %4 Associating Verbs with DDE Commands Invoking a verb normally launches the application specified by the verb's command subkey. However, if your application supports DDE, you can instead have the Shell initiate a Dynamic Data Exchange (DDE) conversation. To specify that invoking a verb should initiate a DDE conversation, add a ddeexec subkey to the verb's key. Set the default value of ddeexec to the DDE command string. The ddeexec key has three optional subkeys that provide some control over the DDE process: application . Set the default value of this subkey to the application name to be used to establish the DDE conversation. If there is no application subkey, the default value of the verb's command subkey is used as the application name. topic . Set the default value of this subkey to the topic name of the DDE conversation. If there is no topic subkey, System is used as the topic name. ifexec . Set the default value of this subkey to the DDE command to be used if DDE conversation cannot be initiated. When initiation fails, the application specified by the default value of the verb's command subkey is launched. If an ifexec key exists, its default value will then be used as the DDE command. If there is no ifexec subkey, the default value of the ddeexec key will be used again as the DDE command. The following example specifies that invoking the open verb for MyProgram.1 initiates a DDE conversation with a DDE command of Open (%1") and an application name of MyProgram. HKEY_CLASSES_ROOT MyProgram.1 (Default) = MyProgram Application Shell (Default) = doit open command (Default) = C:\MyDir\MyProgram.exe "%1" ddeexec (Default) = Open("%1") application (Default) = MyProgram Extending the Shortcut Menu for Predefined Shell Objects Many predefined Shell objects have shortcut menus that can be extended. Register the command in much the same way that you register typical file classes, but use the name of the predefined object as the file class name. A list of predefined objects can be found at Predefined Shell Objects. Those predefined Shell objects whose shortcut menus can be extended by adding verbs in the registry are marked in the table with the word "Verb." Registering an Application to Handle Arbitrary File Classes The preceding sections of this document have discussed how to define shortcut menu items for a particular file class. Among other things, defining the shortcut menu allows you to specify how the associated application opens a member of the file class. However, as discussed in Creating a File Association, applications can also register a separate default procedure to be used when a user attempts to use your application to open a file class that you have not associated with the application. This topic is discussed here because you register the default procedure in much the same way you register shortcut menu items. The default procedure serves two basic purposes. One is to specify how your application should be invoked to open an arbitrary file class. You could, for instance, use a command-line flag to indicate that an unknown file class is being opened. The other purpose is to define the various characteristics of a file class, such as the shortcut menu items and the icon. If a user associates your application with an additional file class, that class will have these characteristics. If the additional file class was previously associated with another application, these characteristics will replace the originals. To register the default procedure, place the same registry keys you created for your application's ProgID under the application's subkey of HKEY_CLASSES_ROOT\Applications . You can also include a FriendlyAppName value to provide the system with a friendly name for your application. The application's friendly name may also be extracted from its executable file, but only if the FriendlyAppName value is absent. The following registry fragment shows a sample default procedure for MyProgram.exe that defines a friendly name and several shortcut menu items. The command strings include the /a flag to notify the application that it is opening an arbitrary file class. If you include a DefaultIcon subkey, you should use a generic icon. HKEY_CLASSES_ROOT Applications MyProgram.exe shell open FriendlyAppName= Friendly Name command (Default) = C:\MyDir\MyProgram.exe /a "%1" print command (Default) = C:\MyDir\MyProgram.exe /a /p "%1" printto command (Default) = C:\MyDir\MyProgram.exe /a /p "%1" "%2" %3 %4 Extending the New Submenu When a user opens the File menu in Windows Explorer, the first command is New. Selecting this command displays a submenu. By default, it contains two commands, Folder and Shortcut, that allow users to create subfolders and shortcuts. This submenu can be extended to include file creation commands for any file class. To add a file-creation command to the New submenu, your application's files must have a file class associated with them. Include a ShellNew subkey under the file extension key. When the File menu's New command is selected, the Shell will add it to the New submenu. The command's display string will be the descriptive string that is assigned to the program's ProgID. Assign one or more data values to the ShellNew subkey to specify the file creation method. The available values follow. Table with 2 columns and 5 rows Value Description Command Executes an application. This is a REG_SZ value specifying the path of the application to be executed. For example, you could set it to launch a wizard. Data Creates a file containing specified data. Data is a REG_BINARY value with the file's data. Data is ignored if either NullFile or FileName is specified. FileName Creates a file that is a copy of a specified file. FileName is a REG_SZ value, set to the fully qualified path of the file to be copied. NullFile Creates an empty file. NullFile is not assigned a value. If NullFile is specified, the Data and FileName values are ignored. table end The following illustration shows the New submenu for the .myp file class used as an example in Creating a File Association and Customizing Icons. It now has a command, MyProgram Application. When a user selects MyProgram Application from the New submenu, the Shell creates a file named "New MyProgram Application.myp" and passes it to MyProgram.exe. Custom New menu The registry entry is now as follows: HKEY_CLASSES_ROOT .myp (Default) = MyProgram.1 MyProgram.1 ShellNew NullFile MyProgram.1 (Default) = MyProgram Application DefaultIcon (Default) = C:\MyDir\MyProgram.exe,2 Shell (Default) = doit open command (Default) = C:\MyDir\MyProgram.exe "%1" doit (Default) = &Do It command (Default) = C:\MyDir\MyProgram.exe /d "%1" print command (Default) = C:\MyDir\MyProgram.exe /p "%1" printto command (Default) = C:\MyDir\MyProgram.exe /p "%1" "%2" %3 %4 **Customizing Folders with Desktop.ini File system folders are commonly displayed with a standard icon and set of properties, which specify, for instance, whether or not the folder is shared. You can customize the appearance and behavior of an individual folder in two ways: Create a Desktop.ini file for the folder Create a Folder.htt template for the folder Folders can be displayed in either Classic or Web style. For a detailed discussion of these styles, see Web View. The Desktop.ini file, discussed here, applies to both styles. It allows you to assign a custom icon to a folder and control its behavior in a limited way. To customize the folder's style beyond what is possible with the Desktop.ini file, you must create a custom Folder.htt template for the folder. This file will only affect the appearance of the folder when the Web style is selected. If this template is not present in the folder, the Shell uses a default template. For further discussion of .htt templates, see The Web View Template. Using Desktop.ini Files Creating a Desktop.ini File Using Desktop.ini Files Folders are normally displayed with the standard folder icon. The most common use of the Desktop.ini file is to assign a custom icon to a folder. This icon will be displayed in Classic style as well as Web style, and it will appear next to the folder's name anywhere the name appears. You can also use Desktop.ini to create an infotip that displays information about the folder and controls some aspects of the folder's behavior, such as whether it can be shared. Use the following procedure to customize a folder's style with Desktop.ini: Use PathMakeSystemFolder to make the folder a system folder. You can also make a folder a system folder from the command line by using attrib +s FolderName. Create a Desktop.ini file for the folder. You should mark it as hidden and read-only to protect it from being modified. Creating a Desktop.ini File The Desktop.ini file is a text file that allows you to specify how a file system folder will be viewed. There are three sections in the file. The first two, [ExtShellFolderViews] and [{5984FFE0-28D4-11CF-AE66-08002B2E1262}] are necessary only if you want to use a custom Folder.htt template. If you omit them, the system will use the default template. To use a custom Folder.htt template, you must include these two sections into the Desktop.ini file exactly as they are shown: [ExtShellFolderViews] Default={5984FFE0-28D4-11CF-AE66-08002B2E1262} {5984FFE0-28D4-11CF-AE66-08002B2E1262}={5984FFE0-28D4-11CF-AE66-08002B2E1262} [{5984FFE0-28D4-11CF-AE66-08002B2E1262}] PersistMoniker=file://Folder.htt The third section, [.ShellClassInfo], allows you to customize the folder's view by assigning values to several entries: Table with 2 columns and 6 rows Entry Value ConfirmFileOp Set this entry to 0 to avoid a "You Are Deleting a System Folder" warning when deleting or moving the folder. NoSharing Set this entry to 1 to prevent the folder from being shared. IconFile If you want to specify a custom icon for the folder, set this entry to the icon's file name. The .ico file extension is preferred, but it is also possible to specify .bmp files, or .exe and .dll files that contain icons. If you use a relative path, the icon will be available to people who view the folder over the network. You must also set the IconIndex entry. IconIndex Set this entry to specify the index for a custom icon. If the file assigned to IconFile only contains a single icon, set IconIndex to 0. InfoTip Set this entry to an informational text string. It will be displayed as an infotip when the cursor hovers over the folder. If the user clicks the folder in a Web view, the information text will be displayed in the folder's information block, below the standard information. table end The following illustrations are of the Music folder with a custom Desktop.ini file. The folder now: Has a custom icon. Does not display a "You Are Deleting a System Folder" warning if the folder is moved or deleted. Cannot be shared. Displays informational text when the cursor hovers over the folder. The folder options in the following illustrations have been set to show hidden files, so that Desktop.ini is visible. A folder only needs its own Folder.htt template if it does not use the default template. The Web style view of the folder looks like this: A view of a folder with a custom icon. When the cursor hovers over the folder, the infotip is displayed. Web view of a folder with an infotip. The Classic style of this folder is similar, with the custom icon replacing the folder icon everywhere the folder name appears. Custom icon replaces the folder icon. The following desktop.ini file was used to customize the Music folder, as seen in the preceding illustrations. For instructional purposes, it includes the optional sections that are needed if you want to use a custom Folder.htt template. Show Example [ExtShellFolderViews] Default={5984FFE0-28D4-11CF-AE66-08002B2E1262} {5984FFE0-28D4-11CF-AE66-08002B2E1262}={5984FFE0-28D4-11CF-AE66-08002B2E1262} [{5984FFE0-28D4-11CF-AE66-08002B2E1262}] PersistMoniker=file://Folder.htt [.ShellClassInfo] ConfirmFileOp=0 NoSharing=1 IconFile=Folder.ico IconIndex=0 InfoTip=Some sensible information. **Creating an AutoRun-enabled CD-ROM Application AutoRun is a feature of the Microsoft Windows operating system. It automates the procedures for installing and configuring products designed for Windows-based platforms that are distributed on CD-ROMs. When users insert an AutoRun-enabled compact disc into their CD-ROM drive, AutoRun automatically runs an application on the CD-ROM that installs, configures, or runs the selected product. If you want your CD-ROM product to display the Windows 95 logo, it must be enabled for AutoRun. AutoRun can be used to install and run CD-ROM applications written for Microsoft MS-DOS, Windows 3.0 and Windows 3.1, and all 32-bit versions of Windows. Although AutoRun is most commonly used for Windows applications, it can also be used to install, configure, or run MS-DOS-based applications in a WindowsMS-DOS session. You can configure each MS-DOS-based application with its own unique icon, Config.sys file, and Autoexec.bat file. Windows creates the correct configuration files for the MS-DOS-based application. The startup application then starts the MS-DOS-based application in a window. There are two essential requirements that a system must meet in order for AutoRun to work. The system must be running Windows 95, Microsoft Windows NT 4.0, or later versions. MS-DOS, Windows versions 3.1 and earlier, and Windows NT versions 3.51 and earlier do not support AutoRun. You can use AutoRun-enabled CD-ROMs in such systems. However, the AutoRun features will be ignored, and the CD-ROMs will behave as ordinary CD-ROMs. The CD-ROM drive must have 32-bit device drivers that detect when a user inserts a compact disc and notify the system. Device drivers for MS-DOS or 16-bit versions of Windows do not have this feature. The following sections discuss how to implement an AutoRun-enabled CD-ROM application. Creating an AutoRun-Enabled Application Autorun.inf Commands Enabling and Disabling AutoRun **Using Hardware AutoPlay AutoPlay is a new feature introducted in Microsoft Windows XP that detects content such as pictures, music, or video files on removable media and removable devices. AutoPlay then automatically launches applications to play or display that content. This simplifies the use of specialized peripheral devices such as MPEG-Layer 3 (MP3) players and digital photo readers. It also makes it easier for users who are unfamiliar with the software needed to access various content types. An expanded selection of icons, including branded icons for major manufacturers, is included to offer improved visual differentiation of drives and other attached devices in My Computer. Icons for devices with removable media, with the exception of floppy drives, are provided in both ready and not ready versions to indicate the current state of the device. This confirms that a device hot-plugged into the system is ready for use, and it helps avoid "device not ready" messages from devices without media inserted. Note AutoPlay should not be confused with AutoRun. AutoRun, introduced in Windows 95, enables a compact disc to automatically launch a function, such as an installer or game play, when placed in the CD-ROM drive. This is accomplished through the use of an Autorun.inf file in the root directory of the compact disc. For more details, see Creating an AutoRun-enabled CD-ROM Application. This documentation is organized in the following sections. Using and Configuring AutoPlay Preparing Hardware and Software for Use with AutoPlay **Creating Shell Extension Handlers The Shell Basics section discusses how to extend the capabilities of the Shell with registry entries and .ini files. While this approach to extending the Shell is simple, and adequate for many purposes, it is limited.