Search code examples
c++cvisual-c++visual-studio-2013ntfs

Getting NTFS volume GUID from drive letter


I thought I had this working, but apparently not. I discovered that, using the mountvol.exe command, the mountpoint for my C:\ drive is:

\\?\Volume{f993747a-5d7a-4de1-a97a-c20c1af1ba02}\

This volume ID contradicts the output this code is giving me:

#include "stdafx.h"
#include <stdio.h>
#include <tchar.h>
#include <ole2.h>

int _tmain(int argc, _TCHAR* argv[])
{
    HANDLE h = CreateFile(L"C:", 0,
        FILE_SHARE_READ, NULL,
        OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);

    FILE_OBJECTID_BUFFER buf;
    DWORD cbOut;
    DeviceIoControl(h, FSCTL_CREATE_OR_GET_OBJECT_ID, NULL, 0, &buf, sizeof(buf), &cbOut, NULL);
    GUID guid;
    CopyMemory(&guid, &buf.ObjectId, sizeof(GUID));
    WCHAR szGuid[39];
    StringFromGUID2(guid, szGuid, 39);
    _tprintf(_T("GUID is %ws\n"), szGuid);

    CloseHandle(h);
    getchar();
}

Which is similar to some code I found online. It is printing "GUID is {5FC6F114-D10D-11E4-8278-E8B1FC697FA2}" which appears to be incorrect.

Any ideas?


Solution

  • In your case, FSCTL_CREATE_OR_GET_OBJECT_ID returns the object ID for the root directory of the C: mountpoint, which is not what you appear to be after.

    The correct way to obtain the GUID path for a volume is via the GetVolumeNameForVolumeMountPoint() function.

    Sample code from MSDN that prints the volume GUID paths for drive c-z:

    #include <windows.h>
    #include <stdio.h>
    #include <tchar.h>
    
    #define BUFSIZE MAX_PATH 
    
    void main(void)
     {
      BOOL bFlag;
      TCHAR Buf[BUFSIZE];           // temporary buffer for volume name
      TCHAR Drive[] = TEXT("c:\\"); // template drive specifier
      TCHAR I;                      // generic loop counter
    
      // Walk through legal drive letters, skipping floppies.
      for (I = TEXT('c'); I < TEXT('z');  I++ ) 
       {
        // Stamp the drive for the appropriate letter.
        Drive[0] = I;
    
        bFlag = GetVolumeNameForVolumeMountPoint(
                    Drive,     // input volume mount point or directory
                    Buf,       // output volume name buffer
                    BUFSIZE ); // size of volume name buffer
    
        if (bFlag) 
         {
          _tprintf (TEXT("The ID of drive \"%s\" is \"%s\"\n"), Drive, Buf);
         }
       }
     }