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