How do I get the user-customized name of a mapped network drive?


Last time, we displayed the names of This PC and Recycle Bin. This time, we'll look at mapped volumes, because they are a little tricky.

When you map a network drive, the name in Explorer defaults to something like sharename (\\server) (Z:). But you can right-click the label, select Rename, and change it to Awesome if you like.

Let's try to retrieve the name Awesome. Take the program from last time and make these changes:

int __cdecl wmain(int argc, wchar_t **argv)
{
  CoInitialize(0);
  IShellItem* item;
  SHCreateItemFromParsingName(argv[1], nullptr,
                              IID_PPV_ARGS(&item));
  PrintDisplayName(item, SIGDN_NORMALDISPLAY, L"name");
  item->Release();
  CoUninitialize();
  return 0;
}

This prints the display name of whatever you pass on the command line. Let's say that drive Z: is mapped to \\server\sharename.

Run the program with the command line parameter Z:,

name = sharename (\\server) (Z:)

Now go to Explorer and rename the drive to Awesome. Then run the program again with Z: on the command line.

name = Awesome (Z:)

Close. We got the Awesome part, but the non-awesome drive letter is still there. That sort of makes sense, since Explorer also shows the non-awesome drive letter.

But what if you really want it without the drive letter? Well, you can ask for a different kind of display name.

int __cdecl wmain(int argc, wchar_t **argv)
{
  CoInitialize(0);
  IShellItem* item;
  SHCreateItemFromParsingName(argv[1], nullptr,
                              IID_PPV_ARGS(&item));
  PrintDisplayName(item, SIGDN_PARENTRELATIVEEDITING, L"name");
  item->Release();
  CoUninitialize();
  return 0;
}

This time, we ask for the parent-relative editing name. This is the name used by the Rename command when you rename an item that is displayed relative to its parent.

Run the program with Z: on the command line, and see what happens:

name = Awesome

Awesome.

For those who want to do things the classic way, you can use the SHGDN_IN­FOLDER | SHGDN_FOR­EDITING flags.

Take the second program (the one that uses the classic style) and make these changes:

int __cdecl wmain(int argc, wchar_t **argv)
{
  CoInitialize(0);
  PIDLIST_ABSOLUTE absolute;
  SHParseDisplayName(argv[1], nullptr, &absolute, 0, nullptr);
  PrintDisplayName(absolute, SHGDN_INFOLDER | SHGDN_FOREDITING, L"name");
  CoTaskMemFree(absolute);
  CoUninitialize();
  return 0;
}
Comments (6)
  1. sense says:

    A link to the previous article would be awesome.

    Generally, a better way of navigating this awesome blog's archive (by series or what) would've been awesome.

  2. Azarien says:

    What happened to CCoInitialize? Withdrawn for security issues? :-)

    [It lost the dice roll. -Raymond]
  3. acq says:

    @sense

    This blog is awesome even as is. You can easily search this site for all the articles that contain PrintDisplayName, as an example, from the search box on the right.

  4. Kyle S. says:

    It seems inappropriate to advocate using a constant specifically intended for _editing_ to generate a name for _display_.

    Kind of like the many innocuous-at-the-time misuses of API that eventually wind up being the topic for other articles on this blog.

    [True, but in this case, we don't want the display name. We want the thing the user customized, via editing. -Raymond]
  5. Joshua says:

    Analysis of returning boolean in flags vs register:

    If it's in flags and we want it in register, we do:

      mov al, 0

      adc al, 0

    If it's in register and we want it in flags, we do:

     test al, al

    So it turns out flags is a better choice unless moving the boolean to memory happens more than half as often as branching immediately on the return. Looking at the code I write, I'd say it's weighted about one to one.

    [You forgot to count the cost of setting the flag in the function being called. This can get tricky when destructors execute between the "return" statement and the final "ret". -Raymond]
  6. ch says:

    @Joshua: Or sbb ax,ax if non-zero vs zero is all you need. Though I think your comment was intended for another article!

Comments are closed.

Skip to main content