c++winapivisual-c++filesystems

Get total size of a hard disk in c++ windows


I am trying to get total size of a physical drive (unallocated + primary partitions + extended partitions size).

I have disk name as \\.\PhysicalDriveX

I tried using GetDiskFreeSpaceEx but it doesn't give correct result when the partition is an extended partition, in this case it returns the total size of the partition.

BOOL ret = FALSE;
ULARGE_INTEGER ulFreeSpace;
ULARGE_INTEGER ulTotalSpace;
ULARGE_INTEGER ulTotalFreeSpace;
__int64 ulTotalUsedSpace = 0;
GetDiskFreeSpaceEx(szBuffer, &ulFreeSpace, &ulTotalSpace, &ulTotalFreeSpace);
*diskSize = ulTotalSpace.QuadPart;

I can get the partition info using DeviceIoControl using IOCTL_DISK_GET_DRIVE_LAYOUT_EX but i am getting confused about extended partition size.

Is there a way that I can accurately get total size of a hard disk in C++ on windows ??


Solution

  • Since you're talking about the physical disk and not partitions, take a look at DeviceIoControl.

    Example from there, which includes the calculation of the total disk size in wmain:

    #include <windows.h>
    #include <winioctl.h>
    #include <stdio.h>
    
    BOOL GetDriveGeometry(LPWSTR wszPath, DISK_GEOMETRY *pdg)
    {
      HANDLE hDevice = INVALID_HANDLE_VALUE;  // handle to the drive to be examined 
      BOOL bResult   = FALSE;                 // results flag
      DWORD junk     = 0;                     // discard results
    
      hDevice = CreateFileW(wszPath,          // drive to open
                            0,                // no access to the drive
                            FILE_SHARE_READ | // share mode
                            FILE_SHARE_WRITE, 
                            NULL,             // default security attributes
                            OPEN_EXISTING,    // disposition
                            0,                // file attributes
                            NULL);            // do not copy file attributes
    
      if (hDevice == INVALID_HANDLE_VALUE)    // cannot open the drive
      {
        return (FALSE);
      }
    
      bResult = DeviceIoControl(hDevice,                       // device to be queried
                                IOCTL_DISK_GET_DRIVE_GEOMETRY, // operation to perform
                                NULL, 0,                       // no input buffer
                                pdg, sizeof(*pdg),            // output buffer
                                &junk,                         // # bytes returned
                                (LPOVERLAPPED) NULL);          // synchronous I/O
    
      CloseHandle(hDevice);
    
      return (bResult);
    }
    
    int wmain(int argc, wchar_t *argv[])
    {
      DISK_GEOMETRY pdg = { 0 }; // disk drive geometry structure
      BOOL bResult = FALSE;      // generic results flag
      ULONGLONG DiskSize = 0;    // size of the drive, in bytes
    
      bResult = GetDriveGeometry (wszDrive, &pdg);
    
      if (bResult) 
      {
        wprintf(L"Drive path      = %ws\n",   wszDrive);
        wprintf(L"Cylinders       = %I64d\n", pdg.Cylinders);
        wprintf(L"Tracks/cylinder = %ld\n",   (ULONG) pdg.TracksPerCylinder);
        wprintf(L"Sectors/track   = %ld\n",   (ULONG) pdg.SectorsPerTrack);
        wprintf(L"Bytes/sector    = %ld\n",   (ULONG) pdg.BytesPerSector);
    
        DiskSize = pdg.Cylinders.QuadPart * (ULONG)pdg.TracksPerCylinder *
                   (ULONG)pdg.SectorsPerTrack * (ULONG)pdg.BytesPerSector;
        wprintf(L"Disk size       = %I64d (Bytes)\n"
                L"                = %.2f (Gb)\n", 
                DiskSize, (double) DiskSize / (1024 * 1024 * 1024));
      } 
      else 
      {
        wprintf (L"GetDriveGeometry failed. Error %ld.\n", GetLastError ());
      }
    
      return ((int)bResult);
    }