// disk_drive_test.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <windows.h>
#include <Winioctl.h>
#include <stdlib.h>
typedef struct PartitionInfo {
char chDrive;
PARTITION_INFORMATION info;
} PartitionInfo, *LPPartitionInfo;
typedef struct DiskInfo {
int iPartitionSize;
PPARTITION_INFORMATION pPartitions;
} DiskInfo, *LPDiskInfo;
void PrintDiskDrives();
int GetAllDiskPartitionInfo (LPDiskInfo* lpDisks);
int GetAllLogicalDriveInfo (LPPartitionInfo* lpPartions);
int main(int argc, char* argv[])
{
PrintDiskDrives ();
getchar ();
return 0;
}
bool IsPartitionEqual( PPARTITION_INFORMATION pPart1, PPARTITION_INFORMATION pPart2 )
{
if (pPart1->BootIndicator == pPart2->BootIndicator &&
pPart1->HiddenSectors == pPart2->HiddenSectors &&
pPart1->PartitionLength.QuadPart == pPart2->PartitionLength.QuadPart &&
pPart1->PartitionNumber == pPart2->PartitionNumber &&
pPart1->PartitionType == pPart2->PartitionType &&
pPart1->RecognizedPartition == pPart2->RecognizedPartition &&
pPart1->RewritePartition == pPart2->RewritePartition &&
pPart1->StartingOffset.QuadPart == pPart2->StartingOffset.QuadPart)
{
return true;
}
return false;
}
void PrintDiskDrives()
{
LPDiskInfo lpDisks = NULL;
LPPartitionInfo lpPartitions = NULL;
int iDisks = GetAllDiskPartitionInfo (&lpDisks);
int iDrives = GetAllLogicalDriveInfo (&lpPartitions);
for (int i = 0; i < iDisks; ++i) {
printf("Disk%d:", i);
for (int k = 0; k < lpDisks [i].iPartitionSize; ++k) {
for (int j = 0; j < iDrives; ++j) {
if (IsPartitionEqual (&lpDisks [i].pPartitions[k], &lpPartitions [j].info)) {
printf ("%c, ", lpPartitions [j].chDrive);
break;
}
}
}
printf("\n");
}
// free memory
for (int j = 0; j < iDisks; ++j) {
free (lpDisks [j].pPartitions);
}
free (lpDisks);
free (lpPartitions);
}
int GetAllDiskPartitionInfo( LPDiskInfo* lpDisks )
{
HKEY hKEY;
long lRet;
lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
"SYSTEM\\CurrentControlSet\\Services\\Disk\\Enum",
0,
KEY_READ,
&hKEY);
if (lRet != ERROR_SUCCESS) {
return 0;
}
int iSize = 0;
DWORD dwType;
DWORD dwValue;
DWORD dwBufLen = sizeof(DWORD);
__try {
lRet = ::RegQueryValueEx (hKEY, "Count", NULL, &dwType, (BYTE*)&dwValue, &dwBufLen);
if(lRet != ERROR_SUCCESS)
{
__leave;//失败
}
*lpDisks = (LPDiskInfo) malloc (dwValue * sizeof (DiskInfo));
for (UINT i = 0; i < dwValue; i++)
{
char szDiskPos [128] = {0};
sprintf(szDiskPos, "\\\\.\\PHYSICALDRIVE%u", i);
HANDLE hDevice = NULL;
DWORD nDiskBytesRead = 0;//预设为0,当缓冲区的长度不够时,该值为所需的缓冲区的长度
DWORD nDiskBufferSize = sizeof(DRIVE_LAYOUT_INFORMATION) + sizeof(PARTITION_INFORMATION) * 104;//26*4
PDRIVE_LAYOUT_INFORMATION lpDiskPartInfo = (PDRIVE_LAYOUT_INFORMATION)malloc(nDiskBufferSize);
if(lpDiskPartInfo == NULL)
{
free (lpDiskPartInfo);
continue;
}
//将缓冲区lpDiskPartInfo的内容设为nDiskBufferSize个NULL
memset(lpDiskPartInfo, 0, nDiskBufferSize);
//////////////////////获得所有分区的信息///////////////////////////////////////
hDevice = CreateFile(szDiskPos,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);
if(hDevice == NULL) {
free (lpDiskPartInfo);
continue;
}
/////////////获得某磁盘上的所有分区信息/////////////////////////
BOOL fRet = DeviceIoControl(
hDevice,
IOCTL_DISK_GET_DRIVE_LAYOUT,
NULL,
0,
(LPVOID) lpDiskPartInfo,
(DWORD) nDiskBufferSize,
(LPDWORD) &nDiskBytesRead,
NULL
);
if (!fRet)
{
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0,
NULL
);
LocalFree( lpMsgBuf );
free (lpDiskPartInfo);
CloseHandle(hDevice);
continue;
}
//////////////////////////////导出分区信息///////////////////////////////////////
DWORD dwPartitionCount = lpDiskPartInfo->PartitionCount;
int iPartitions = dwPartitionCount / 4;
(*lpDisks)[iSize].pPartitions = (PPARTITION_INFORMATION)malloc (iPartitions * sizeof (PARTITION_INFORMATION));
(*lpDisks)[iSize].iPartitionSize = 0;
//永远是实际的分区数的4倍,不能用的分区将会显示类型PARTITION_ENTRY_UNUSED,即分区类型为0
///////////////////依次获取导出某分区信息,并与目的驱动器进行比较///////////////////////////////////
for (UINT j = 0;j < dwPartitionCount; j += 4)//+4是因为只有下标为4的整数倍的值才是正确的引用
{
memcpy (&((*lpDisks)[iSize].pPartitions [(*lpDisks)[iSize].iPartitionSize++]), &lpDiskPartInfo->PartitionEntry [j], sizeof (PARTITION_INFORMATION));
}
free(lpDiskPartInfo);
CloseHandle(hDevice);
++iSize;
}
} __finally {
if (hKEY != NULL) {
RegCloseKey(hKEY);
}
}
return iSize;
}
int GetAllLogicalDriveInfo( LPPartitionInfo* lpPartions )
{
int iSize = 0;
char szBuf [1024];
GetLogicalDriveStrings (1024, szBuf);
*lpPartions = (LPPartitionInfo) malloc (sizeof (PartitionInfo) * 26); // 26 个英文字母
char szDrive [64] = {0};
for (char* pszDrive = (char*)szBuf; pszDrive != NULL && *pszDrive != 0; pszDrive += strlen (pszDrive) + 1) {
(*lpPartions)[iSize].chDrive = *pszDrive;
wsprintf(szDrive, "\\\\.\\%c:", *pszDrive);
HANDLE hDevice = CreateFile(szDrive,
GENERIC_READ,
FILE_SHARE_WRITE | FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
0,
NULL);
if (hDevice == INVALID_HANDLE_VALUE)
continue;
DWORD dwNum;
DeviceIoControl(hDevice,
IOCTL_DISK_GET_PARTITION_INFO,
NULL,
0,
&(*lpPartions)[iSize++].info,
sizeof(PARTITION_INFORMATION),
&dwNum,
NULL);
CloseHandle(hDevice);
}
return iSize;
}