#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <conio.h>
#include <windows.h>
#include "bruce.i" // Private functions, mostly string related
// Required by format()
#include "werrtxt.i" // Print error text for GetLastError()
#include "format.i" // Format numbers. 1234567 as 1,234,567
int main(int argc, char *argv[])
{
char data[256];
int i,j,k;
char Partition[26];
char Drive[26];
char DrivePart[26];
long double Starting_Offset[26];
long double Partition_Length[26];
int nparts=-1;
int maxdisk=0;
char DriveSpec[4]="?:\\";
char device[65];
char cnumber1[21];
char cnumber2[21];
HANDLE Device;
STORAGE_DEVICE_NUMBER sdn;
_PARTITION_INFORMATION_EX pi;
int piesz = sizeof(PARTITION_INFORMATION_EX);
_DRIVE_LAYOUT_INFORMATION_EX *dlie;
int dliesz = sizeof(_DRIVE_LAYOUT_INFORMATION_EX);
bool GetDSN,GetPIB;
unsigned long bytes_returned;
BOOL SizeOK;
int numparts;
void *buffer; // Used to receive drive layout info
int bufsz;
// Determine what logical drives exist (partitions)
for (i='C'; i<='Z'; i++)
{
DriveSpec[0] = i;
k = GetDriveType(DriveSpec);
if (k == DRIVE_FIXED)
{
nparts++;
Partition[nparts] = i;
}
}
printf("Partitions: %d\n",nparts+1);
for (i=0; i<=nparts; i++)
{
// -----------------------------------------------------------
// All API information retrieval will be based on Drive Letter
// -----------------------------------------------------------
sprintf(device,"\\\\.\\%c:",Partition[i]);
Device = CreateFile(device, // drive
0, // no access to the drive
FILE_SHARE_READ|FILE_SHARE_WRITE, // share mode
NULL, // default security attributes
OPEN_EXISTING, // disposition
0, // file attributes
NULL); // do not copy file attributes
if (Device == INVALID_HANDLE_VALUE)
{
i = GetLastError();
WErrTxt(i,data);
printf("Error accessing drive %c:\nRC: x'%X'\nMessage: %s\n",Partition[i],data);
return 2;
}
// -----------------------------------------------------------
// Get the physical device this partition (drive letter) is on
// -----------------------------------------------------------
GetDSN = DeviceIoControl(Device, // handle to device
IOCTL_STORAGE_GET_DEVICE_NUMBER, // dwIoControlCode
NULL, // lpInBuffer
0, // InBufferSize
&sdn, // output buffer
sizeof(STORAGE_DEVICE_NUMBER), // size of output buffer
&bytes_returned, // number of bytes returned
NULL); // OVERLAPPED structure
if (GetDSN)
Drive[i] = (int) sdn.DeviceNumber;
else
{
printf("Device number retrieval failed for %c:\n",Partition[i]);
exit(0);
}
if (Drive[i] > maxdisk)
maxdisk = Drive[i];
// -----------------------------------------------------------
// Get the partition number for the device (drive letter)
// -----------------------------------------------------------
GetPIB = DeviceIoControl(Device, // handle to device
IOCTL_DISK_GET_PARTITION_INFO_EX, // dwIoControlCode
NULL, // lpInBuffer
0, // InBufferSize
&pi, // output buffer
piesz, // size of output buffer
&bytes_returned, // number of bytes returned
NULL); // OVERLAPPED structure
if (GetPIB)
DrivePart[i] = pi.PartitionNumber;
else
{
printf("Partition number retrieval failed for %c:\n",Partition[i]);
exit(0);
}
// -----------------------------------------------------------
// Get the extents for the device partition (drive letter)
// -----------------------------------------------------------
// Number of partitions on a drive varies, so don't know
// how big a buffer we need right off the bat
SizeOK = false;
numparts = 1;
buffer = (PARTITION_INFORMATION_EX *)
malloc(sizeof(PARTITION_INFORMATION_EX)*4 *
numparts + dliesz - piesz);
// Up buffer size on each loop until success
while(!SizeOK)
{
bufsz = sizeof(PARTITION_INFORMATION_EX)*4 * numparts + dliesz - piesz;
bytes_returned = 0;
SizeOK = DeviceIoControl(
Device, // handle to device
IOCTL_DISK_GET_DRIVE_LAYOUT_EX,// dwIoControlCode
NULL, // lpInBuffer
0, // nInBufferSize
buffer, // output buffer
bufsz, // size of output buffer
&bytes_returned, // number of bytes returned
NULL); // OVERLAPPED structure
if (!SizeOK)
{
k = GetLastError();
if (k != 0x7A) // 7A is the buffer too small error code we expect
{ // This something else, we need to check it out
printf("Error retrieving disk layout data\n");
WErrTxt(k,data);
printf("RC: x'%X'\nMessage: %s\n",i,data);
exit(0);
}
free(buffer); // Release the "too small" buffer
numparts++;
// Allocate new buffer based on updated partition "estimate"
buffer = (PARTITION_INFORMATION_EX *)
malloc(sizeof(PARTITION_INFORMATION_EX)*
4 * numparts + dliesz - piesz);
bufsz = sizeof(PARTITION_INFORMATION_EX)*4*numparts+dliesz-piesz;
}
}
// Cast the void buffer to the Layout Structure
// (Need Drive layout structure to point to data)
dlie = (_DRIVE_LAYOUT_INFORMATION_EX *) buffer;
for (j=0; j<dlie->PartitionCount; j++)
{
if (dlie->PartitionEntry[j].PartitionNumber == DrivePart[i])
{
// Need to conver LARGE_INTEGER fields to long double
sprintf(data,"%I64d",dlie->PartitionEntry[j].PartitionLength);
Partition_Length[i] = atof(data);
sprintf(data,"%I64d",dlie->PartitionEntry[j].StartingOffset);
Starting_Offset[i] = atof(data);
break;
}
}
free(buffer); // Clean up allocated storage
CloseHandle(Device); // Clean up acquired handle
}
// Dump raw data to screen
for (j=0; j<=maxdisk; j++)
{
printf("\nDrive %d\n",j);
printf("Dr %17s %17s\n","Starting Offset","Partition Length");
for (i=0; i<=nparts; i++)
{
if (Drive[i] == j)
{
// You'll need an alternative to format()
printf("%c: %17s %17s\n",
Partition[i],
format(Starting_Offset[i],cnumber1),
format(Partition_Length[i],cnumber2));
}
}
}
return 0;
}
Sample output
Partitions: 12
Drive 0
Dr Starting Offset Partition Length
C: 32,256 60,003,385,344
H: 60,003,449,856 60,003,385,344
P: 120,006,867,456 190,053,287,424
Q: 310,060,187,136 190,045,062,144
Drive 1
Dr Starting Offset Partition Length
D: 32,256 205,952,753,664
O: 205,952,818,176 114,117,502,464
Drive 2
Dr Starting Offset Partition Length
E: 32,256 80,048,392,704
Drive 3
Dr Starting Offset Partition Length
F: 32,256 160,039,240,704
Drive 4
Dr Starting Offset Partition Length
G: 32,256 160,039,240,704
I: 160,039,305,216 80,015,491,584
J: 240,054,829,056 80,015,491,584
Drive 5
Dr Starting Offset Partition Length
L: 32,256 81,956,657,664