• windows的磁盘操作之四——根据逻辑分区号获得物理磁盘号


    第一节中我们谈到了磁盘设备名称的两种形式:

    对于物理驱动器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 ", 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 ", GetLastError());
            (void)CloseHandle(hDevice);
            return (DWORD)-1;
        }
        //printf("%d %d %d ", 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

  • 相关阅读:
    C#中发送邮件,包含Html代码 CDO.Message
    CodeSmith生成SQL Server视图的实体类脚本/对应的生成模板
    分享到微信朋友圈
    获取验证码效果和后台代码(js+html+cs)
    弹出遮罩层
    WebAPI上传文件
    zoj1665 dij变形
    hdu1535 SPFA
    hdu1217 floyd
    poj1703 并查集
  • 原文地址:https://www.cnblogs.com/chaikefusibushiji/p/6775774.html
Copyright © 2020-2023  润新知