Author Topic: Windows SDK IShellFolder examples: Enumerating File and System Folders  (Read 6725 times)

LarsJ

  • Guest
The examples are based on the Windows SDK by ToutEnMasm so you need that. You can download it here: http://luce.yves.pagesperso-orange.fr/sdkrc7.cab.

For more information about the Windows SDK search for "windows.sdk" in the old forum and select the subject with the title "Revision of the "ready to use sdk heder's files" and of the masm32 samples".


The examples

The attached zip-file contains two source files: PrintFileFolders.asm and PrintSysFolders.asm.

PrintFileFolders.asm enumerates files and subfolders of an ordinary file folder e.g. C:\.

PrintSysFolders.asm enumerates files and subfolders of a system/special folder e.g. Desktop, My Computer, Control Panel or Recycle Bin. More precisely folders given by a CSIDL_constant.

The enumaration is done with the methods of the IShellFolder and IEnumIDList interfaces.

The methods of the IShellFolder interface works on relative PIDL's (pointers to ITEMIDLIST structures, see http://msdn.microsoft.com/en-us/library/windows/desktop/cc144090(v=vs.85).aspx).

To enumerate a folder get an IShellFolder interface pointer for the folder. Use the EnumObjects method of the interface to get an IEnumIDList interface pointer. Use the Next method of this interface to enumerate the files and subfolders. The Next method provides relative PIDLs. Finally use the IShellFolder interface with the relative PIDLs to get information for the files and subfolders.

The plan to enumerate a folder is:
   0. Get a fully qualified PIDL for the folder
   1. Get the name of the folder and print it
   2. Get the names of the files and print them
   3. Get fully qualified PIDLs for the subfolders
   4. Repeat step 1 - 4 for the subfolders

This plan is used for both file and system folders. But the implementation is slightly different and that's why there are two source files. An important difference is that to successfully enumerate a system folder you must initialize COM.

Step 0 is used to get started. It's only done once. The procedures in the source files to implement step 0 are EnumFileFolder and EnumSystemFolder. A parameter is used to define how many levels to enumerate.

The procedure to implement step 1 - 4 is EnumSubFolder in both source files. Step 4 is done by recursion.


Implementation

0. Get a fully qualified PIDL for the folder

A fully qualified PIDL corresponds to a full path. It's used to get an IShellFolder interface pointer for the parent folder.

File folder:
Code: [Select]
invoke ILCreateFromPath, FullPath
mov pPidlFQ, eax
http://msdn.microsoft.com/en-us/library/windows/desktop/dd378420(v=vs.85).aspx

System folder:
Code: [Select]
invoke SHGetFolderLocation, NULL, csidl, NULL, 0, ADDR pPidlFQhttp://msdn.microsoft.com/en-us/library/windows/desktop/bb762180(v=vs.85).aspx

pPidlFQ is the fully qualified PIDL.

1. Get the name of the folder and print it

With pPidlFQ get an IShellFolder interface pointer for the parent folder and a relative PIDL for the folder:
Code: [Select]
invoke SHBindToParent, pPidlFQ, offset IID_IShellFolder, ADDR ppvIShellFolder, ADDR pPidlRelhttp://msdn.microsoft.com/en-us/library/windows/desktop/bb762114(v=vs.85).aspx

Get the name of the folder:
Code: [Select]
IShellFolder GetDisplayNameOf, pPidlRel, SHGDN_NORMAL, ADDR strrethttp://msdn.microsoft.com/en-us/library/windows/desktop/bb775075(v=vs.85).aspx

2. Get the names of the files and print them

Get an IShellFolder interface pointer for the folder (not parent):
Code: [Select]
IShellFolder BindToObject, pPidlRel, NULL, offset IID_IShellFolder, ADDR ppvIShellFolder
Get an IEnumIDList interface pointer to enumerate the files of the folder:
Code: [Select]
IShellFolder EnumObjects1, 0, SHCONTF_NONFOLDERS+SHCONTF_INCLUDEHIDDEN, ADDR ppvIEnumIDList
Enumerate the files:
Code: [Select]
.while(1)
    IEnumIDList Next, 1, ADDR pPidl, NULL
    .break .if eax != S_OK
    IShellFolder GetDisplayNameOf, pPidl, SHGDN_NORMAL, ADDR strret
.endw
(IEnumIDList: see http://msdn.microsoft.com/en-us/library/windows/desktop/bb761982(v=vs.85).aspx)

3. Get fully qualified PIDLs for the subfolders

Get an IEnumIDList interface pointer to enumerate the subfolders of the folder:
Code: [Select]
IShellFolder EnumObjects1, 0, SHCONTF_FOLDERS+SHCONTF_INCLUDEHIDDEN, ADDR ppvIEnumIDList
Enumerate the subfolders:
Code: [Select]
.while(1)
    IEnumIDList Next, 1, ADDR pPidl, NULL      ; Enumerate the subfolders of the folder associated with pPidlFQ.
    .break .if eax != S_OK                     ; Get a fully qualified PIDL for the subfolder by combining pPidlFQ
    invoke ILCombine, pPidlFQ, pPidl           ; for the parent folder with pPidl for the subfolder. pPidl is the
    mov pPidlSub, eax                          ; PIDL for the subfolder relative to the parent folder.
    invoke EnumSubFolder, pPidlSub, nextLevel  ; Enumerate the subfolder (step 4)
.endw


Link the obj-files

Link the obj-files as CONSOLE applications.

To be able to link I had to comment out 3 lines in ShObjIdl.sdk because of "unresolved external symbol" errors:
         ;SetTextColor                  comethod2 ?
         ;PlaySound                     comethod2 ?
         ;PlaySound                     comethod2 ?

My antivirus program (Avira Free Antivirus) detects virus alarms in the exe-files.

Testet on XP SP3.

LarsJ