singh
singh

Reputation: 439

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 ??

Upvotes: 8

Views: 18784

Answers (1)

Rudi Visser
Rudi Visser

Reputation: 21969

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);
}

Upvotes: 11

Related Questions