windows的磁盘操作之四——根据逻辑分区号获得物理磁盘号(转)
2013-10-25 11:45
471 查看
第一节中我们谈到了磁盘设备名称的两种形式:
对于物理驱动器x,形式为\\.\PhysicalDriveX,编号从0开始,例如
对于逻辑分区(卷),形式为\\.\X: ,例如
那么如何找出物理驱动器号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\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_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。
对于物理驱动器x,形式为\\.\PhysicalDriveX,编号从0开始,例如
名称 | 含义 |
\\.\PhysicalDrive0 | 打开第一个物理驱动器 |
\\.\PhysicalDrive2 | 打开第三个物理驱动器 |
名称 | 含义 |
\\.\A: | 打开A盘(软驱) |
\\.\C: | 打开C盘(磁盘逻辑分区) |
首先我们要明确,物理驱动器号和逻辑分区号应该是一对多的关系。例如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_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。
相关文章推荐
- Implement custom foreach function in C#
- 移植intel的LAN driver source code到Linux kernel中
- ISC-dhcp server for IPv6 2011-07-26 15:34:31| 分类: linux |字号 订阅 1. 下载源码:http://www.isc.org/softw
- .h, lib和dll文件的功能和区别
- So cute are you Python 12
- 如果你是腾讯电商的产品经理,你该如何设计她?
- OCP-1Z0-052-V8.02-141题
- 关于SVN删除后的文件不能重新添加(正常途径不行)
- Linux LVM逻辑卷配置过程详解
- [互联网面试笔试汇总C/C++-24] Linux守护进程工作原理和方式-雅虎
- 新手学python 第十五篇 网络编程(二)
- hdu ——1116——Play on Words(欧拉路有向图)
- thinkpad x240 (二)
- C# datagridview 某列只能输入英文或数字
- Expression parameters.formName is undefined on line 111, column 43 in template/simple/doubleselect.
- .net常用属性
- layout_margin和 android:textColor="#FF000000" 背景变色
- APIsocket,VS2010,windows非阻塞模式异步套接字编程(看孙鑫视频有感)
- SPI,UART,I2C都有什么区别,及其各自的特点 (原作者Luckyer)
- eclipse 无法启动问题解决