November 17th, 2014

How do I enumerate drives the same way that the NET USE command does?

If you use the Remote Desktop Connection client to connect to another computer, you have the option of making your local drives available to the remote computer.

A customer wanted to know how to enumerate all the drives on the local machine. The were able to get the volumes mapped to drive letters, but they also wanted to get the redirected drives injected by Terminal Services. (Mind you, these aren’t volumes that are assigned drive letters, so it’s not clear why they are interested in them, but whatever.)

With the NET USE command, they see the Terminal Services volumes in Explorer, and they can be browsed via \\tsclient\d:

Status       Local     Remote                    Network
-------------------------------------------------------------------------------
                       \\TSCLIENT\D              Microsoft Terminal Services
The command completed successfully.

The customer wanted to enumerate these Terminal Services client volumes. “How does the NET USE command enumerate these volumes?”

Let’s write that program. Remember, Little Programs do little to no error checking.

#define UNICODE
#define _UNICODE
#include <windows.h>
#include <winnetwk.h>
#include <stdio.h>
void report(PCWSTR pszLabel, PCWSTR pszValue)
{
 printf("%ls = %ls\n", pszLabel, pszValue ? pszValue : L"(null)");
}
int __cdecl main(int, char **)
{
 HANDLE hEnum;
 WNetOpenEnum(RESOURCE_CONNECTED,
              RESOURCETYPE_DISK,
              0,
              NULL,
              &hEnum);
 DWORD cbBuffer = 65536;
 void *buffer = LocalAlloc(LMEM_FIXED, cbBuffer);
 LPNETRESOURCE pnr = (LPNETRESOURCE)buffer;
 DWORD err;
 do {
  DWORD cEntries = INFINITE;
  DWORD cb = cbBuffer;
  err = WNetEnumResource(hEnum, &cEntries, buffer, &cb);
  if (err == NO_ERROR || err == ERROR_MORE_DATA) {
   for (DWORD i = 0; i < cEntries; i++) {
    report(L"localName", pnr[i].lpLocalName);
    report(L"remoteName", pnr[i].lpRemoteName);
    report(L"provider", pnr[i].lpProvider);
    printf("\n");
   }
  }
 } while (err == ERROR_MORE_DATA);
 LocalFree(buffer);
 WNetCloseEnum(hEnum);
 return 0;
}

We open an enumeration for connected disks and then start enumerating out of it. The usage pattern for WNet­Enum­Resources is kind of messy, with a bunch of in/out parameters that need to get reset each time. Each time, we say “Enumerate as much as you can into this 64KB buffer” and then print what we got. If we were told, “There’s still more,” then we go back and ask for more.

That’s all. Nothing particularly fancy.

Topics
Code

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

0 comments

Discussion are closed.