View of Windows Shell Name Space
Jiang Weihua
Windows95 / 98 made many major improvements to DOS / Win3.x, in addition to the file system, in addition to the long file name replacing the 8.3 file name in DOS, introducing the shell name space "generation DOS file system is It is another big breakthrough. This article will briefly describe how to describe Windows 95/98 or Windows NT4.0 or later.
Overview
Introduction In DOS / WIN3.X, each logical partition constitutes a directory tree, file system, by this unified root, and each directory or file must correspond to objective existence in the file system. But after Windows introduced the concept of "Shell Name Space", it has changed. The housing namespace is the standard file system under Windows. It has greatly extended the DOS file system, which forms a single file system tree with "Desktop), the original C drive, D disk and other directory trees become The next grade sub-tree of the "My Computer", the next-stage sub-tree of the housing name space, as "control panel", "recycling station", "online neighbors" and other devices are also virtualized. The node in the housing namespace. In addition, it is different from the physical storage in DOS to be different from the file system item one by one, and an actual directory can behave different from the enclosure namespace. For example, "My Documents" and "C; / My Documents" are actually pointing to the "C; / My Documents" directory, but they are different in the enclosure namespace. If we run the "Windows Explorer" comes with the Windows Sports Manager, we can clearly see the entire enclosure namespace replace the DOS file system in its left tree view. I finally have a qualitative leap. In order to distinguish between DOS "Directory" concept, Windows introduces the concept of "Folder" (Folder). "Folder" generally refers to the non-leaf node in the housing namespace tree, which can be either DOS, or the "Control Panel", "Recycle Bin" virtual directory. However, some items in the housing name are not a folder (ie, no folder properties), but contain subfolders, such as "online neighbors". Here are convenient for lectures, we also think they are folders. During the following lecture, we will use the word "file system" to refer to the DOS file system, and use the word "shell name space" to refer to the housing name space in Windows: other use "file" The leaf node in this tree (although they are not all physical storage). In Windows, Win3.x file operation functions, such as FindFirstFile, FindNextFile, SetCurrentDirectory, etc., although they are still available, but they can only browse the file system, but they cannot browse and manipulate the entire housing name space. To browse the enclosure namespace in Windows, you must use a new, COM (Component Object Model), based on the method. New "Path" PIDL before discussing COM-based approaches, let us first introduce the "path" in the housing name space. The string of the DOS can only represent the file system, but cannot represent the entire enclosure name space, so the housing namespace provides a "path" alternative to the 乇 乇 恚 虺 虺 乇 乇 乇 乇 乇 乇?? 虺 虺 虺 虺 虺 虺? 椩. PIDL is an array of element types for the ItemIdList structure. The number of elements in arrays is unknown, but it is necessary to be a double-byte zero at the end of the array. Each array element represents a layer (ie, a folder or file) in the housing name space tree, and the previous element in the array represents the parent folder of the latter element.
It can be seen that the PIDL actually points to a pointer to a number of ItemidList structures arranged in several order, and a pointer in the last space with a double byte zero. So the type of PIDL is defined by Windows as a pointer to the ItemIdList structure. PIDL also has the concept of "absolute path" and "relative path". Represents the PIDL of the "relative path" (referred to as "relative PIDL") only an element of an itemidList structure, used to identify "path" relative to the parent folder; indicating "absolute path" PIDL (referred to as "absolute PIDL" There are elements of several itemidlist structures, and the first element represents a subfolder A under the housing namespace root folder ("desktop"), the second element represents a subfolder under the folder a. B. The rest is in this class. This absolute PIDL is the same by saving an absolute PIDL of the direct subfolder or file from "desktop", while other folders or files relative PIDL is just the last part of its absolute PIDL. But now there is a problem: "Desktop" representation. Other items in the housing name space can be represented by absolute PIDL from "Desktop", but the "desktop" PIDL array apparently does not have an element. This will only leave the last double-byte of the PIDL array. Therefore, "desktop" PIDL is a 16-bit zero. Note: "Desktop" is a double-byte zero. In addition, although "desktop" is indicated by the "C: / Windows / Desktop" folder (here the Windows system directory is "C: / Windows"), "Desktop" and "C: / Windows / Desktop" The PIDL of the folder is completely different. This is also suitable for "My Documents" and "C: / My Documents" and other folders. The path in the DOS is a string, but PIDL is a binary structure, so we can't directly find which folder or file it represents it directly, but must call the corresponding function to convert it into a representative path. String. If an absolute PIDL is part of the file system, call the SHGETPATHFROMIDLIST function; but if not, you cannot get the path string because there is no such path in DOS. But unfortunately, Windows did not provide a function to make us conveniently convert the path string of the file system into PIDL. However, we can use a function of our own implementation ParsepidLFromPath () to achieve (see the implementation of the specific functions). The creation and release of PIDL generally does not use C New and DELETE operations or C language Malloc and Free functions, but must use a special method. First call the shGeetmalloci function to get the Malloc interface (one of the COM interface, About the COM interface The pointer will be described in detail, then call the alloc method of the interface to PIDL allocation space, or call the interface of the interface to release the space occupied by a PIDL. Finally, the Release method of the interface is called to release the interface. In addition to the ISHELLFOLDER, IENUMIDLIST, etc., ISHELLFOLDER, IENUMIDLIST, etc., there are many Windows API functions that are starting with SH, but generally these functions require an absolute PIDL parameter. For example, the SHGETFILEINFO function can obtain various information of the object referred to in a PIDL, including name, icon, attribute, etc.; SHFileOperation functions can copy, move, rename, delete the items in the enclosure namespace; ShbrowseForFolder can display a Users select the browsing dialog box in a folder in the enclosure name space. Method based on COM
After discussing the concept of PIDL, we go back to discuss the method of browsing the namespace above COM. If PIDL is a "path" in the namespace of the case, then the two COM interfaces ISHELLFOLDER and IEnumIdList are similar to FindFirstFiles in Win 3.x. In Windows, each folder is implemented by the operating system interface ISHELLFOLDER that is derived from the iUnknown interface (the most basic class of the COM interface). By calling the interface of a folder, browsing of the folder can be implemented to obtain various information about child (sub-folder or file) in the folder.
We can call the SHGETDESKTOPFOLDER function to get the ISHELLFOLDER interface of the root folder (ie "Desktop") of the enclosure name. For a folder A, with the relative PIDL of its subfolder B, the BindToObject method of its ISHELLFOLDER interface can be obtained to obtain the ISHELLFOLDER interface of the subfolder B. To enumerate the child under a folder, you only need to call the EnumiPjects method of its ISHELLFOLDER interface to get an IenumIdList interface. We can enumerate all children (including folders and files such as folders and files) to obtain their relative PIDLs. Using the ISHELLFOLDER interface of the parent folder and these relative PIDLs, we can get various information about these subms, including display names, icons, properties, etc., and even get its right-click menu. For example, a getDisplayNameOF method that calls the interface can get the display name of the subkey under this folder; call the parseisplayName method to translate a child with the unicode internal code represented by the string path into a corresponding PIDL. In this way, we can traverse and manipulate the namespace of the entire housing through PIDL and these two interfaces.
In addition to the ISHELLFOLDER and IENUMIDLIST interface, Windows shell namespace also provides a lot of other COM interfaces, such as ISHELLBROWSER, ISHELLLINK, ISHELLICOM, ISHELLVIEW, and more. Through these interfaces, it can be better interact with the housing name space. Due to the limited amount of this article, these interfaces are not detailed, and interested readers can refer to relevant information.
It is worth noting that the interface in the COM is very similar to the class in the use of C (in fact, the COM interface is declared in the form of classes in C ), but maintaining its correct reference counting mechanism is very important. For each additional reference to the interface, it is necessary to call its addRef () method; and you must call its release () method after use. For details on COM and COM interface, please refer to relevant information, and details will not be described here.
It is a pity that although we can achieve the layer-by-layer deployment of the housing name space in accordance with the method given above, but the namespace of the housing is not provided with a method of freely jump to a folder, and has not provided return. To the previous folder method, because we cannot easily get the ISHELLFOLDER interface of the parent folder. If you want to return, you must get the ISHELLFOLDER interface of the parent folder by the application. One feasible method is to save the ISHELLFOLDER interface pointer of each folder when the housing namespace is expanded, which can be freely jumped relatively easily.
But in any case, the browsing and operation of the housing name space is still a huge leap than the function of DOS / Windows 3.x. As long as we understand the advantages and deficiencies of this approach, we can lead to avoid weaknesses, develop a variety of programs that use the shell name space. Related interface, function and data structure
For some of the more complex interfaces, functions, and data structures involved herein, only the authors are listed in Visual C 6.0, and they are equipped with the corresponding comments. Some simpler is omitted, no See the relevant information, please refer to the relevant information.
data structure
Typedf ishellfolder * lpshellfolder;
// ishellfolder interface pointer declaration
Typedef struct _ItemidList {// itemidlist structure definition
SHITEMID MKID;
} Itemidlist, * lpitemidlist;
TypeDef struct _shitemid {// definition of element in the itemidList structure
USHORT CB; // The length of this structure (in bytes)
Byte Abid [1]; // can grow long element identifier
} Shitmid, * lpshitemid;
Typedef struct _shfileinfo {// sffileinfo definition
Hicon Hicon; // File icon handle
INT ilcon; // icon in the serial number in the system image list
DWORD DWATITRIBUTES; // The properties of the file
Char szdisplayname [max_path]; // Display name or path
Char sztypename [80]; / / indicates a string of file type
SHFILEINFO;
2. Related interface
2.1 method of ishellfolder interface
BindtoObject format: HRESULT BINDTOOBJECT (LPBC PBCRESERVED, REFIID RIID, LPVOID * PPVOUT); Role: Get the ISHELLFOLDER interface of a single folder in this folder. Parameters: RIID should be IID_IDFOLDER, PBCReServe, should be NNUL, PIDL to represent the PIDL of the "relative path" of the subfolder, returns a pointer to the required ISHELLFOLDER interface from PPVOut. EnumObjects
Format: HRSULT ENUMOBJECTS (HWND HWNDOWNER, DWORD GRFFLAGS, LPENUMIDLIST * PPENUMIDLIST);
Role: Enumerate Members of this folder.
Parameters: hwndowmer is a parent window handle, and Grfflags determines the world-famous content, which can be combined with SHCONTF_FOLDERS, SHCONTF_NONFOLDERS, SHCONTF_INCLUDEHIDEN, and returns a pointer to the IEnumIDList interface from PPenumIdList.
(3) getDisplayNameof
Format: HRESULT GETDISPLAYNAMEOF (LPCITEMIDLIST PIDL, DWORD UFLAGS, LPSTRRRRERT LPNAME);
Role: Get the display name of an object in this folder.
Parameters: PIDL is a PIDL of the "relative path" indicating the subfolder, uflags is SHGDN_NORMAL, SHGDN_INFOLDER, SHGFI_SYSICIONDEX, SHGFI_EXETYPE, SHGFI_ATTRIBUTES, SHGFI_PIDL, SHGFI_DISPLAYNAME, SHGFI_LARGEICON, and more.
Return Value: If uflags contains the SHGFI-EXTYPE flag, the return value is the executable folder type; if uflags contains the SHGFI_SYSICIONINDEX flag, the return value is the handle of the system image list. Otherwise, if the call is successful, the non-zero value is returned, and zero is returned. Application examples
Several very useful functions
1.1parsePidLFromPath
Description: Translate the file system path into a corresponding PIDL. LpitemidList ParsepidLFromPath (LPCSTR PATH)
{
/ / Store buffer of the path string represented by Unicode internal code
OLECHAR SZOLECHAR [MAX_PATH];
// "Desktop" ISHELLFOLDER interface pointer
LPSHELLFOLDER IPSFDESKTOP;
// Returned PIDL
LPITEMIDLIST IPIFQ;
Ulong uleaten, ulattribs;
HRESULT HRES;
// Get the "desktop" ISHELLFOLDERR interface pointer
ShgetDesktopFolder (& lpsfdesktop);
// Convert the path string of the ANSI character set to Unicode string,
Szolechar
MultibyToWideChar (CP_ACP, MB_PREComposed,
PATH, -1, SZOLECHAR, SIZEOF (SZOLECHAR);
// Translate Szolechar, the path zone string into the corresponding PIDL, deposit LPIFQ
HRES = lpsfdesktop-> release ();
// Returns NULL if the translation failed
IF (Failed (HRES) RETURN NULL;
Return LPIFQ;
1.2 GetItemicon
Description: Returns the icon of the LPI of the absolute PIDL in the system image list, UFLAGS is the required icon type.
Int getLtemlcon (LPITEMIDLIST LPI, UINT UFLAGS)
{
// Structure of file information
SHFILEINFO SFI;
// Add some public marks to uflags (LPI is PIDL, require returning to system image list, require small icon)
Uflags | = SHGFI-PIDL | SHGFI_SYSICIONINDEX | SHGFI_SMALLICON;
Get icon
SHGETFILEINFO ((LPCSTR) LPI, 0, & SFI, SIZEOF (SHFILEINFO), UFLAGS;
/ / Return to the number of icons in the system image list
Return SFI, ILCON;
}
1.3 getName
Description: LPIO LPSF refers to the relative PIDL under the folder represented by the ISHELLFOLDER interface, this function gets the display name of the LPI, DWFlags indicates that the display name type of the display, LpFriendlyName is a buffer that stores the name of the display.
Bool GetName (LPSHELLFOLDER LPSF, LPITEMIDLIST LPI, DWORD DWFLAGS, LPSTR LPFRIENDLYNAME)
{
Strret STR;
// Get the display name
IF (noerror! = lpsf-> getDisplaynameof () LPI, DWFLAGS, & STR))
Return False;
/ / Conversion according to the return value
Switch (str utype)
{
// For the Unicode string, turn into a string Case Strret_WSTR of the ANSI character set.
Widechartomultibyte (CP_ACP, 0, Str.Polestr, -1, IpFriendlyName, Sizeof (lpfriendlyname), NULL, NULL
Break; // If the offset is removed, the offset is removed.
Case Strret_offset:
LSTRCPY (LPFRIENDLYNAME, (LPSTR) LPI STR.UOFFSET);
Break;
If you are an ANSI string, copy directly
Case Strret_cstr:
LSTRCPY (LPFRIENDLYNAME, (LPSTR) Str.cstr);
Break;
// illegal situation
DEFAULT:
Return False;
}
Return True;
An instance
Here we will use Visual C 6.0 to present an example to demonstrate the browsing of the housing name. Specifically, the "Desktop" folder in the enclosure namespace is expanded, enumerate all subfolders under the folder. In this project, the image list of CTreeView We use the Windows system image list instead of creating one. First, use AppWizard to create a new project, type MFC AppWizard (Exe), the project name TEST; select Single Document in the first step; change the base class of CTestView to ctreeView in the first step. Others use the default settings. Second, add a private member variable m_imagelist in CTestView, type CIMAGELIST for saving the system list. (All icons in Windows are saved in the system image list, we can get this image list in the program). In the third step, copy the two functions mentioned above and GetItemicon to CTestView.cpp to the lower position of CTestView.cpp.
In the fourth step, add the following code: / / The system image list is added: / / The system image list will himagelist hiMlsmall; / / Store the structure of the file information SHFILEINFO SFI; / / Store the information of the node in the tree control TV_INEM TVI; / / Structure TV_INSERTSTRUCT TVI_FirstSTRUCT TVI_First; // Some of the HtreeItem HParent = TV_ROT; // of the parent node of the node when inserted into the node The ISHELLFOLDER interface pointer of the folder LPSHELLFOLDER LPSF = 0; // i i i i = = l l; 一 一 一 为 为 为 为 为 为 为 为 为 为 为 为 为 为 为 为 为 为 为 为 为 为 为 为 为 为Number Ulong ulfetched; / / Store buffer char SZBUFF [MAX_PATH] of the display name; // Get the list of system images and assigns it to CTestView's CTREECTRL control HIMLSMALL = (HimageList) ShgetfileInfo ("C: /////////", 0, & sfi, sizeof (SHFIEINFO), SHGFI_SYSICONINDEX | SHGFI_SMALLICON); m_lmageList.Attach (himlsmall); GetTreeCtrl () SetlmageList (& m_imageList, TVSIL_NORMAL); // get pointer SHGetMalloc Imalloc interface (& lpMalloc); // get the "desktop" file. ISHELLFOLDER interface pointer SHGETDESKTOPFLODER (& lpsf); // Create a "desktop" absolute PIDL LPI = (LPITEMIDLIST) LPMALLOC-> Alloc (sizeof (usof (ushort *) LPI) = 0 // Setup Inserted tree node information TVi, mask = tvif_text | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN; TVI.cchtextmax = max_path; // Set the name TVi.psztext = _t ("desktop"); // Get the standard icon and the icon Tvi.ILMAGE = TETLTEMLCON (LPI, NULL) when the standard icon is expanded; tvi.iselectedLMage = getLtemlcon (LPI, SHGFI_Openicon); // Setting Insertion Position TVIS.ITEM = TVi; tvis.hlnsertAfter = tvi_first; tvis.hparent = TVi_root; // Insert root node hpparent = gettreeCtrl (). Instthtltem (& TV); // Release the space of the LPI LPMALLOC-> Free (LPI ); // Get the IENUMIDLIST interface pointer of "Desktop" folder LPE LPE LPE LPSF-> Enumjects (m_hwnd, shcontf_folders | shcontf_nonfolders, & lpe); // Enumerate "Desktop" Each subfolder while (S_OK = = LPE- > Next (1, & LPI, & ULFETCHED) {// Get the display name of the subfolder represented by the LPI GetName (LPSF, LPI, SHGDN_NORMAL, SZBUFF); TVi.psztext = SZBUFF; // Get the icon of this item / Is the direct child under "desktop",
So, its relative PIDL and absolute PIDL are consistent TVi.ilmage = getLtemlcon (LPI, NULL); TVI.ISElectedImage = getLtemlcon (LPI, SHGFI_Openicon); // Setting the insertion position tvis.Item = TVi; tvis.hinsertAfter = HPREV; Tvis.hparent = hParent; // Insert Node hprev = gettreeCtrl (). INSERTLTEM (& TV); // Release the space IPMalloc-> Free (LPI) of the LPI;} // Release IMALLOC and ISSHELLDER interface LPMALLOC-> Release (); LPSF-> Release (); // Sort GetTreeCtrl () .SortChildren (HParent); // expand GetTreeCtrl () .Selectltem (HParent); getTreeCtrl () In response to the WM_DESTROY message of CTestView, add the following code: // Due to the use of the system image list, you must release ownership // otherwise, if you exit, Windows doesn't have M_ImageList. DETACH (); the effect of this demo is as shown in the following figure:
Due to the relationship of the space, the examples of this article can only show the browsing of the housing name space, and many more complex programming methods are not expressed. Finally, I hope this paper can play a role in tiles, let more developers understand with the namespace of the shell, and develop better procedures.
references
Microsoft Windows 95 Programmer Programmer Guide, Tsinghua University Press, 1996 Stefamomaruzzi.Windows95 Developer Must Read, Electronic Industry Press, 1997