How to find the Boot Volume GUID using Windows APIs?

Prem Jha 70 Reputation points
2024-12-19T10:35:33.3266667+00:00

I am quite new to Win32 programming. Pardon me for any mistakes in the question.

I am trying to get the GUID of the Boot Volume of the system of which I have device path which I found by querying the BCD device path through registry function.

I tried to list all the Volume GUIDs using FindFirstVolumeW and FindNextVolumeW Windows functions and then used the QueryDosDeviceW Windows function to get the device path for its corresponding GUID of the Volume and then return the Volume GUID of that device path that matches with the BCD device path which I already found.

All the Volume GUID gets its device path except the boot volume's GUID which did not found any device path for that volume GUID which is actually the boot volume GUID, and its reason could be the fact that the boot volume does not always have an associated DOS drive letter. Some system volumes, like the boot or EFI partitions, may not have any mount points or drive letters accessible via GetVolumePathNamesForVolumeNameW.Windows function.

Could anyone please help me with the best possible approach to get the Boot Volume GUID using Win32 API functions call.

Windows API - Win32
Windows API - Win32
A core set of Windows application programming interfaces (APIs) for desktop and server applications. Previously known as Win32 API.
2,699 questions
0 comments No comments
{count} votes

2 answers

Sort by: Most helpful
  1. Castorix31 86,396 Reputation points
    2024-12-19T17:33:09+00:00

    To get the Volume Guid from Device name read from registry, I did this test on my PC, but it is about the same thing as enumerating volumes :

    HKEY hKey = NULL;
    DWORD nSize;
    TCHAR* wsDeviceName = NULL;
    HANDLE hMountPtMgr = INVALID_HANDLE_VALUE;
    TCHAR wsText[255];
    DWORD nError = (DWORD)RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SYSTEM\\Setup", 0, KEY_QUERY_VALUE, &hKey);
    if (nError == ERROR_SUCCESS)
    {
    				nError = (DWORD)RegQueryValueEx(hKey, L"SystemPartition", NULL, NULL, NULL, &nSize);
    				if (nError == ERROR_SUCCESS)
    				{							
    					wsDeviceName = (TCHAR*)CoTaskMemAlloc(nSize);
    					nError = (DWORD)RegQueryValueEx(hKey, L"SystemPartition", NULL, NULL, (LPBYTE)wsDeviceName, &nSize);
    					//\Device\HarddiskVolume1
    					wsprintf(wsText, TEXT("Device name : %s\r\n"), wsDeviceName);
    					OutputDebugString(wsText);
    					if (nError == ERROR_SUCCESS)
    					{
    						hMountPtMgr = CreateFile(L"\\\\.\\MountPointManager"/* MOUNTMGR_DOS_DEVICE_NAME*/, 0,
    							FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL);
    						if (hMountPtMgr != INVALID_HANDLE_VALUE)
    						{
    							DWORD nInBufferSize, nOutBufferSize;									
    							PMOUNTMGR_MOUNT_POINT pMountPoint = NULL;
    							PMOUNTMGR_MOUNT_POINTS pMountPoints = NULL;
    							nInBufferSize = sizeof(MOUNTMGR_MOUNT_POINT) + wcslen(wsDeviceName) * sizeof(TCHAR);
    							pMountPoint = (PMOUNTMGR_MOUNT_POINT)CoTaskMemAlloc(nInBufferSize);
    							ZeroMemory(pMountPoint, nInBufferSize);
    							pMountPoint->DeviceNameOffset = sizeof(MOUNTMGR_MOUNT_POINT);
    							pMountPoint->DeviceNameLength = wcslen(wsDeviceName) * sizeof(TCHAR);
    							CopyMemory(((PBYTE)pMountPoint) + pMountPoint->DeviceNameOffset, wsDeviceName, pMountPoint->DeviceNameLength);
    							nOutBufferSize = sizeof(MOUNTMGR_MOUNT_POINTS);									
    							DWORD nBytesReturned = 0;
    							while (TRUE)
    							{
    								if (pMountPoints)
    								{
    									CoTaskMemFree(pMountPoints);
    									pMountPoints = NULL;
    								}
    								pMountPoints = (PMOUNTMGR_MOUNT_POINTS)CoTaskMemAlloc(nOutBufferSize);
    								if (pMountPoints)
    								{											
    									ZeroMemory(pMountPoints, nOutBufferSize);
    									if (DeviceIoControl(hMountPtMgr, IOCTL_MOUNTMGR_QUERY_POINTS, pMountPoint, nInBufferSize, pMountPoints, nOutBufferSize, &nBytesReturned, NULL))
    										break;
    									nError = GetLastError();
    									if (nError != ERROR_MORE_DATA)
    										break;
    									nOutBufferSize = pMountPoints->Size;
    								}
    							}									
    							DWORD nNbMountPoints = (nBytesReturned - FIELD_OFFSET(MOUNTMGR_MOUNT_POINTS, MountPoints)) / sizeof(MOUNTMGR_MOUNT_POINT);
    							TCHAR* wsMountPoint = NULL;
    							PMOUNTMGR_MOUNT_POINT pCurrentMountPoint;
    							GUID guid = GUID_NULL;
    							for (int i = 0; i < nNbMountPoints && i < pMountPoints->NumberOfMountPoints; i++)
    							{
    								pCurrentMountPoint = &pMountPoints->MountPoints[i];
    								nSize = pCurrentMountPoint->SymbolicLinkNameLength + 2 * sizeof(TCHAR);
    								if (wsMountPoint)
    								{
    									CoTaskMemFree(wsMountPoint);
    									wsMountPoint = NULL;
    								}
    								wsMountPoint = (TCHAR*)CoTaskMemAlloc(nSize);
    								if (wsMountPoint)
    								{
    									CopyMemory(wsMountPoint, ((PBYTE)pMountPoints) + pCurrentMountPoint->SymbolicLinkNameOffset, pCurrentMountPoint->SymbolicLinkNameLength);
    									int nLenght = pCurrentMountPoint->SymbolicLinkNameLength / sizeof(TCHAR);
    									wsMountPoint[1] = L'\\';
    									wsMountPoint[nLenght] = L'\\';
    									wsMountPoint[nLenght + 1] = 0;
    									// \\?\Volume{78e26ddb-0000-0000-0000-100000000000}\
    
    									TCHAR wsPrefix[] = L"\\\\?\\Volume{";
    									TCHAR* ws;
    									ws = wsMountPoint;
    									ws += wcslen(wsPrefix);
    									ws[36] = 0;
    									UuidFromString((unsigned short*)ws, &guid);
    									wsprintf(wsText, TEXT("Guid : %s\r\n"), ws);
    									OutputDebugString(wsText);
    									CoTaskMemFree(wsMountPoint);
    									if (guid != GUID_NULL)
    										break;
    								}
    							}
    							CloseHandle(hMountPtMgr);
    							if (pMountPoints)
    								CoTaskMemFree(pMountPoints);
    							if (pMountPoint)
    								CoTaskMemFree(pMountPoint);
    						}
    						if (wsDeviceName)
    							CoTaskMemFree(wsDeviceName);
    					}
    				}					
    				RegCloseKey(hKey);
    }
    
    

    with :

    #pragma comment (lib, "Rpcrt4")
    
    //#include <mountmgr.h>
    typedef struct _MOUNTMGR_MOUNT_POINT {
    	ULONG  SymbolicLinkNameOffset;
    	USHORT SymbolicLinkNameLength;
    	USHORT Reserved1;
    	ULONG  UniqueIdOffset;
    	USHORT UniqueIdLength;
    	USHORT Reserved2;
    	ULONG  DeviceNameOffset;
    	USHORT DeviceNameLength;
    	USHORT Reserved3;
    } MOUNTMGR_MOUNT_POINT, * PMOUNTMGR_MOUNT_POINT;
    
    typedef struct _MOUNTMGR_MOUNT_POINTS {
    	ULONG                Size;
    	ULONG                NumberOfMountPoints;
    	MOUNTMGR_MOUNT_POINT MountPoints[1];
    } MOUNTMGR_MOUNT_POINTS, * PMOUNTMGR_MOUNT_POINTS;
    
    
    #define MOUNTMGR_DEVICE_NAME L"\\Device\\MountPointManager"
    #define MOUNTMGRCONTROLTYPE 0x0000006D // 'm'
    #define MOUNTDEVCONTROLTYPE 0x0000004D // 'M'
    #define IOCTL_MOUNTMGR_QUERY_POINTS                 CTL_CODE(MOUNTMGRCONTROLTYPE, 2, METHOD_BUFFERED, FILE_ANY_ACCESS)
    
    

  2. RLWA32 46,271 Reputation points
    2024-12-24T03:17:23.5866667+00:00

    Another way to find the boot volume guid is to use a file name that you know exists in the boot partition. Following example uses bootmgr file.

    #define WIN32_LEAN_AND_MEAN
    #include <Windows.h>
    
    #include <stdio.h>
    #include <tchar.h>
    
    int main()
    {
        TCHAR szBoot[MAX_PATH]{}, szFile[]{_T("bootmgr")};
        _stprintf_s(szBoot, _T("\\\\?\\Global\\SystemPartition\\%s"), szFile);
        auto hFile = CreateFile(szBoot, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
        if (hFile != INVALID_HANDLE_VALUE)
        {
            TCHAR szPath[MAX_PATH]{};
            if (GetFinalPathNameByHandle(hFile, szPath, ARRAYSIZE(szPath), VOLUME_NAME_GUID))
            {
                LPTCH p = _tcsrchr(szPath, _T('\\'));
                *p = _T('\0');
                _tprintf_s(_T("Volume guid is %s\n"), szPath);
            }
            else
                _tprintf_s(_T("GetFinalPathNameByHandle failed with error %d\n"), GetLastError());
    
            CloseHandle(hFile);
        }
        else
            _tprintf_s(_T("CreateFile failed with %d\n"), GetLastError());
    
        return 0;
    }
    

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.