windows的磁盤操作之四——根據邏輯分區號獲得物理磁盤號

第一節中http://cutebunny.blog.51cto.com/301216/624027我們談到了磁盤設備名稱的兩種形式:

對於物理驅動器x,形式爲 \\.\PhysicalDriveX,編號從0開始,例如

名稱
含義
\\.\PhysicalDrive0
打開第一個物理驅動器
\\.\PhysicalDrive2
打開第三個物理驅動器
對於邏輯分區(卷),形式爲 \\.\X: ,例如

名稱
含義
\\.\A:
打開A盤(軟驅)
\\.\C:
打開C盤(磁盤邏輯分區)
 
那麼如何找出物理驅動器號 012…… 和邏輯分區號 C, D, E……之間的關係呢?本節討論通過邏輯分區號獲取所在物理驅動器號的方法,下一節討論通過物理驅動器號找出其所包含的邏輯分區號的方法。當然,必定會存在其他思路實現同樣的功能,歡迎大家補充。
首先我們要明確,物理驅動器號和邏輯分區號應該是一對多的關係。例如disk0可能包含C, D, E三個分區。所以下面討論的函數GetPhysicalDriveFromPartitionLetter返回一個單獨的整型數。DeviceIoControl提供操作碼IOCTL_STORAGE_GET_DEVICE_NUMBER,可以非常方便的獲得打開設備的設備類型和設備號。
代碼如下
/******************************************************************************
* Function: get disk's physical number from its drive letter
*           e.g. C-->0 (C: is on disk0)
* input: letter, drive letter
* output: N/A
* return: Succeed, disk number
*         Fail, -1
******************************************************************************/
DWORD GetPhysicalDriveFromPartitionLetter(CHAR letter)
{
    HANDLE hDevice;               // handle to the drive to be examined
    BOOL result;                 // results flag
    DWORD readed;                   // discard results
    STORAGE_DEVICE_NUMBER number;   //use this to get disk numbers
 
    CHAR path[DISK_PATH_LEN];
    sprintf(path, "\\\\.\\%c:", letter);
    hDevice = CreateFile(path, // drive to open
                         GENERIC_READ | GENERIC_WRITE,    // 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 attribute
    if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
    {
        fprintf(stderr, "CreateFile() Error: %ld\n", GetLastError());
        return DWORD(-1);
    }
 
    result = DeviceIoControl(
                hDevice,                // handle to device
                IOCTL_STORAGE_GET_DEVICE_NUMBER, // dwIoControlCode
                NULL,                            // lpInBuffer
                0,                               // nInBufferSize
                &number,           // output buffer
                sizeof(number),         // size of output buffer
                &readed,       // number of bytes returned
                NULL      // OVERLAPPED structure
            );
    if (!result) // fail
    {
        fprintf(stderr, "IOCTL_STORAGE_GET_DEVICE_NUMBER Error: %ld\n", GetLastError());
        (void)CloseHandle(hDevice);
        return (DWORD)-1;
    }
    //printf("%d %d %d\n\n", number.DeviceType, number.DeviceNumber, number.PartitionNumber);
 
    (void)CloseHandle(hDevice);
    return number.DeviceNumber;
}
 
代碼分析:
1. 根據分區號生成設備名稱。
2. 調用CreateFile打開設備並獲得設備句柄。
3. 調用操作碼爲IOCTL_STORAGE_GET_DEVICE_NUMBERDeviceIoControl函數,輸出爲結構體變量STORAGE_DEVICE_NUMBER number
結構體STORAGE_DEVICE_NUMBER定義爲
typedef struct _STORAGE_DEVICE_NUMBER {
DEVICE_TYPE  DeviceType;
ULONG  DeviceNumber;
ULONG  PartitionNumber;
} STORAGE_DEVICE_NUMBER, *PSTORAGE_DEVICE_NUMBER;
       其中DeviceNumber就是我們需要的物理磁盤號。
4. 返回DeviceNumber
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章