February 28, 2021
Hot Topics:

The Windows CE Shell

  • By Nancy Nicolaisen
  • Send Email »
  • More Articles »

Where the Files Are

CE "flattens" the standard Windows file system, and this flattening occurs in different degrees on different platforms. The practical impact of this is that the "special folders" (the Recycling Bin is an example of a special folder) that your application references may be in different locations than they were on the desktop. The path to the special folders also differs among CE platforms. Our first example program, FindDirs, shows how to use the shell functions to find the paths for the special folders. This job is accomplished differently on the palmtop devices than on the others. FindDirs.cpp is the main source file for an application that retrieves special folder locations on the palmtop CE devices. Following this example and its accompanying explanation, I'll show how to modify the FindDirs code so that it will work properly on HPC and HPC Pro class devices.

As with previous examples, we omit the support files in the interest of brevity. Full source for the FindDirs project can be found in accompanying files at developer.com.

Figure 5—The FindDirs Example Running on the Pocket PC Emulator

Click here for a larger image.

Examining the FindDirs Example

The rubber meets the road, so to speak, in the initialization sequence of the SpecialDirsDlgProc(). First, we get the handle to the list box and insert a title string.


  switch (wMsg)
      case WM_INITDIALOG:
           hWndList = GetDlgItem(hWnd,IDC_SPECIAL_DIRS );
           _stprintf( szBuff, TEXT("%s"),TEXT("Special Folders"));
           ListBox_InsertString(hWndList, -1, &szBuff);

Next, we loop to fill the list box with the paths to specific special directories. Notice that we use an array of structures, iaSpecialDirs. Here is the declaration of the structures that make up this array:

typedef struct tagSDirs
    int    csidl;

The typedef for the SPECIAL_DIRS structure includes two members. The first, csidl, contains a CE-defined constant that identifies a special folder. The second, pszCSIDL, is a literal string that contains the CE constant's defined name. The possible values for the csidl values and their meanings appear in the following table. The physical directories identified by the constants may or may not be present on a given device, so it's very important to test the return from SHGetSpecialFolderLocation().

Table 5—SHGetSpecialFolderLocation() Constants For Special Folders

Manifest Constant Identifier How This Folder Is Used
CSIDL_BITBUCKET File system directory for the user's Recycle Bin. The Recycle Bin path is not in the Registry, and is marked with the hidden and system attributes to keep users from moving or deleting it.
CSIDL_CONTROLS This is a virtual folder. Contains Control Panel applications icons.
CSIDL_DESKTOP This is a virtual folder at the root of the namespace. Contains Windows Desktop shortcuts.
CSIDL_DESKTOPDIRECTORY This is the actual physical directory used to store desktop file objects. It is not the same as the\Windows\Desktop folder.
CSIDL_DRIVES This is a virtual folder that encapsulates the contents of the desktop "My Computer" icon. It shows everything on the local computer: storage devices, printers, and Control Panel. It may also contain mapped network drives.
CSIDL_FAVORITES Physical directory that contains the user's "Favorites" items.
CSIDL_FONTS This is a virtual folder. It contains fonts.
CSIDL_NETHOOD Physical directory that contains the Network Neighborhood objects.
CSIDL_NETWORK This is a virtual folder. It represents the top level of the network hierarchy.
CSIDL_PERSONAL Physical directory that contains user documents.
CSIDL_PRINTERS This is a virtual folder. It contains installed printers.
CSIDL_PROGRAMS Physical directory that contains the user's program groups.
CSIDL_RECENT Physical directory that contains the MRU documents.
CSIDL_SENDTO Physical directory that contains Send To menu items.
CSIDL_STARTUP Physical directory. The system starts any user programs stored here when the device powers on.
CSIDL_STARTMENU Physical directory that contains Start menu items.
CSIDL_TEMPLATES This is a physical directory. It contains document templates.

We test for a specific subset of the constants in this version of FindDirs. Here's the declaration and initialization of our array of SPECIAL_DIR structures, iaSpecialDirs[]:

SPECIAL_DIRS iaSpecialDirs[] =

This subset was chosen because it is likely to be implemented on a palmtop-class device. Now we loop through the array, calling SHGetSpecialFolderLocation() for each array element:

    for ( i = 0; i < dim ( iaSpecialDirs ); i ++ )
        rc = SHGetSpecialFolderLocation(hWnd,
                  iaSpecialDirs[i].csidl, &pidl );

The parameters to SHGetSpecialFolderLocation(), in the order shown, are the handle to the window that will display any message boxes or warnings required during the processing of this call, the CE-defined constant that identifies the folder for which we want a path, and the address of a pointer to an ITEMIDLIST structure. Here's how this variable, pidl, is declared at the top of the SpecialDirsDlgProc():


This fragment of code is a bit deceptive and bears a little explanation. On the desktop, and on larger CE platforms, pidl is a pointer to a buffer that is allocated by the shell. To free this buffer, you need to get and use the shell's IMalloc COM interface. This isn't necessary on the palmtop CE devices because the value returned in pidl is a defined constant that you can pass to SHGetPathFromIDList() to retrieve a pathname. If the call to SHGetSpecialFolderLocation() is successful, we retrieve the pathname:

  if( rc == NOERROR )
      _stprintf( szBuff, TEXT("   %s "),iaSpecialDirs[i].pszCSIDL);
      ListBox_InsertString(hWndList, -1, &szBuff);

      SHGetPathFromIDList( pidl, &szBuff[0] );
      ListBox_InsertString(hWndList, -1, &szBuff);

Just one more thing. Note the declaration of szBuff:

        TCHAR szBuff[MAX_PATH];

Don't be tempted to save stack space by reducing the size of this buffer. In some cases, the SHGetPathFromIDList() function fills the buffer with null padding, using the entire MAX_PATH space, even though the actual pathname is only a few characters in length.

Source Code

Download the source code: FindDirs.zip - 3 kb.

Looking Ahead

In the next installment, we'll see how to locate special folders on HPC and H/PC Pro devices.

About the Author

Nancy Nicolaisen is a software engineer who has designed and implemented highly modular Windows CE products that include features such as full remote diagnostics, CE-side data compression, dynamically constructed user interface, automatic screen size detection, entry time data validation.

In addition to writing for Developer.com, she has written several books including Making Win 32 Applications Mobile.

# # #

Page 2 of 2

This article was originally published on June 11, 2003

Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Thanks for your registration, follow us on our social networks to keep up-to-date