本节讨论与上一节相反的操作,根据物理驱动器号获取该磁盘上的所有分区号。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 分配空间,并将位图转换为盘符字母存储在数组中。