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


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

    对于物理驱动器x,形式为\.PhysicalDriveX,编号从0开始,例如

    名称

    含义

    \.PhysicalDrive0

    打开第一个物理驱动器

    \.PhysicalDrive2

    打开第三个物理驱动器

    对于逻辑分区(卷),形式为\.X: ,例如

    名称

    含义

    \.A:

    打开A盘(软驱)

    \.C:

    打开C盘(磁盘逻辑分区)

     

    那么如何找出物理驱动器号0,1,2…… 和逻辑分区号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_NUMBER的DeviceIoControl函数,输出为结构体变量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。

  • 相关阅读:
    java中的 equals 与 ==
    String类的内存分配
    SVN用命令行更换本地副本IP地址
    npoi 设置单元格格式
    net core 微服务框架 Viper 调用链路追踪
    打不死的小强 .net core 微服务 快速开发框架 Viper 限流
    net core 微服务 快速开发框架 Viper 初体验20201017
    Anno 框架 增加缓存、限流策略、事件总线、支持 thrift grpc 作为底层传输
    net core 微服务 快速开发框架
    Viper 微服务框架 编写一个hello world 插件02
  • 原文地址:https://www.cnblogs.com/rainbowzc/p/3387620.html
Copyright © 2020-2023  润新知