本節討論與上一節相反的操作,根據物理驅動器號獲取該磁盤上的所有分區號。DeviceIoControl函數並沒有提供操作碼來直接完成此操作,所以需要稍微繞個圈子來實現這項功能。
大體思路爲,先通過GetLogicalDrives函數獲得系統中所有分區號,然後過濾掉非硬盤分區(例如軟驅、光驅),再過濾掉不屬於指定物理磁盤的分區,最後剩下的就是我們所需要的分區號了。
代碼如下
/******************************************************************************
* Function: get disk's drive letters from physical number
* e.g. 0-->{C, D, E} (disk0 has 3 drives, C:, D: and E:)
* input: phyDriveNumber, disk's physical number
* output: letters, letters array
* return: Succeed, the amount of letters
* Fail, -1
******************************************************************************/
DWORD GetPartitionLetterFromPhysicalDrive(DWORD phyDriveNumber, CHAR **letters)
{
DWORD mask;
DWORD driveType;
DWORD bmLetters;
DWORD diskNumber;
CHAR path[DISK_PATH_LEN];
CHAR letter;
DWORD letterNum;
WORD i;
CHAR *p;
bmLetters = GetLogicalDrives();
if (0 == bmLetters)
{
return (DWORD)-1;
}
letterNum = 0;
for (i = 0; i < sizeof(DWORD) * 8; i++)
{
mask = 0x1u << i;
if ((mask & bmLetters) == 0) //get one letter
{
continue;
}
letter = (CHAR)(0x41 + i); //ASCII change
sprintf(path, "%c:\\", letter);
driveType = GetDriveType(path);
if (driveType != DRIVE_FIXED)
{
bmLetters &= ~mask; //clear this bit
continue;
}
diskNumber = GetPhysicalDriveFromPartitionLetter(letter);
if (diskNumber != phyDriveNumber)
{
bmLetters &= ~mask; //clear this bit
continue;
}
letterNum++;
}
//build the result
*letters = (CHAR *)malloc(letterNum);
if (NULL == *letters)
{
return (DWORD)-1;
}
p = *letters;
for (i = 0; i < sizeof(DWORD) * 8; i++)
{
mask = 0x1u << i;
if ((mask & bmLetters) == 0)
{
continue;
}
letter = (CHAR)(0x41 + i); //ASCII change
*p = letter;
p++;
}
return letterNum;
}
代碼分析
函數輸入參數DWORD phyDriveNumber爲物理磁盤號,例如0,1,2……。
函數輸出參數CHAR **letters爲獲得的邏輯分區號數組指針。由於一塊物理盤上可能有多個分區,所以用數組存放求得的多個分區號。
函數返回值爲分區數量。
1. 調用函數GetLogicalDrives獲得所有分區號。注意函數GetLogicalDrives返回值爲位圖形時,例如第0位代表A:,第2位代表C: 等等。
2. 對獲得的邏輯分區逐個檢測。
調用函數GetDriveType獲得分區類型,如果類型不爲硬盤(driveType != DRIVE_FIXED),將此位清0。
調用函數GetPhysicalDriveFromPartitionLetter(詳見第四節http://cutebunny.blog.51cto.com/301216/624379)查詢該邏輯分區所屬的物理分區號,如果不爲phyDriveNumber,將此位清0。
經過上兩項條件過濾後的位圖存儲了我們所需的邏輯分區號。
3. 爲*letters分配空間,並將位圖轉換爲盤符字母存儲在數組中。