The only thing you can do with display names is display them

Raymond Chen

Raymond

There are many functions that return strings called “display names”. And the only thing you can do with display names is display them. Don’t assume that the string actually means anything, because it doesn’t. Theoretically, a function like SHGetFileInfo could be implemented as

...
 if (uFlags & SHGFI_DISPLAYNAME) {
  StringCchCopy(psfi->szDisplayName, MAX_PATH, TEXT("Booga!"));
 }
...

and your program should still work.

(Of course, this is merely a ground rule. Specific functions may have exceptions. For example, the IShellFolder::GetDisplayNameOf has a special flag SHGDN_FORPARSING flag which explicitly indicates that the string returned is designed to be parsed.)

The purpose of a “display name” is to be a string suitable for displaying to the user. The display name for a file, for example, might be the file name, or it might have the extension removed, or the name might even be translated into the user’s preferred language! For example, on an English system with the German multilanguage pack installed and active, asking for the display name of C:\Documents and Settings\Raymond\My Documents will return Eigene Dateien because that’s the name for My Documents in German.

If your program assumed that the display name of C:\Documents and Settings\Raymond\My Documents would be something like “My Documents”, your program is in for a big surprise when I run it.

One of my colleagues was investigating a bug reported against a program that wouldn’t run. It claimed that the CD-ROM was not in the drive, even though it was. Why can’t the program find its CD-ROM?

After a few days’ investigation, my colleague found the reason. The program wanted to find its CD-ROM, so it walked through all 26 drive letters and called SHGetFileInfo passing the SHGFI_DISPLAYNAME flag. Something like this:

// The actual code was much, much more convoluted than this.
char LookForCD(LPCTSTR pszVolumeLabel)
{
 for (TCHAR chDrive = TEXT('A'); chDrive <= TEXT('Z'); chDrive++) {
  TCHAR szRoot[4];
  wsprintf(szRoot, TEXT("%c:\\"), chDrive);
  SHFILEINFO sfi;
  if (SHGetFileInfo(szRoot, 0, &sfi, sizeof(sfi), SHGFI_DISPLAYNAME)) {
   TCHAR szExpected[MAX_PATH];
   wsprintf(szExpected, TEXT("%s (%c:)"), pszVolumeLabel, chDrive);
   if (strcmp(szExpected, sfi.szDisplayName) == 0) {
    return chDrive; // Found it!
   }
  }
 }
 return 0; // not found
}

The program asked for the display name of each drive and looked for one whose display name was of the form LABEL (D:), where LABEL is the volume label they’re looking for and D: is the drive letter.

In othe words, they were trying to interpret the display name.

Don’t do that. There is no guarantee that the display name for a CD-ROM will be of any particular form. The default in Windows XP happens to be LABEL (D:), but there are a variety of system policies that can be used to change this, and if any of those policies is in effect, the program can’t find its CD-ROM and refuses to run.

(For the record, the correct way of doing this would be to pass each drive letter to the GetDriveType function to see if it is a DRIVE_CDROM; for each such drive, call GetVolumeInformation to get the CD-ROM’s volume label.)

So remember, display names are just for display purposes.†

Nitpicker’s corner

†See parenthetical remark at the top of this entry for clarification. The sentence intentionally overlooked the exceptions in order to provide a punchier ending to the story. It’s called writing style and is a valid literary technique.

0 comments

Comments are closed. Login to edit/delete your existing comments