windows的磁盘操作之九——区分本地磁盘与移动硬盘
http://cutebunny.blog.51cto.com/301216/674443
最近碰到了个新问题,记录下来作为windows的磁盘操作那个系列的续篇吧。
|
Return code
|
Description
|
|
DRIVE_REMOVABLE
|
The drive has removable media; for example, a floppy drive, thumb drive, or flash card reader.
|
|
DRIVE_FIXED
|
The drive has fixed media; for example, a hard drive or flash drive.
|
http://cutebunny.blog.51cto.com/301216/624027中介绍的GetDriveGeometry()函数,其输出参数DISK_GEOMETRY *pdg中的MediaType字段代表设备类型。
typedef enum _MEDIA_TYPE
{
RemovableMedia,
FixedMedia
} MEDIA_TYPE;
这两个方法看似能方便快捷的解决我们的需求,但事实上当你使用GetDriveType()去获取一块移动硬盘的类型时,
程序会坑爹的告诉你这块移动硬盘的类型是DRIVE_FIXED,根本无法与本地磁盘区分开来。
GetDriveGeometry()函数的结果也是如此。
而对移动硬盘甚至是一块稍大容量的U盘(比如我有一块格式化为FAT32格式的4G U盘),就无能为力了。
当然,其基础还是我们那万能的DeviceIoControl,不过这次的控制码为IOCTL_STORAGE_QUERY_PROPERTY。
同时对应的输入参数为STORAGE_PROPERTY_QUERY结构,输出参数为STORAGE_DEVICE_DESCRIPTOR结构体。
typedef struct _STORAGE_PROPERTY_QUERY {
STORAGE_PROPERTY_ID PropertyId;
STORAGE_QUERY_TYPE QueryType;
UCHAR AdditionalParameters[];
} STORAGE_PROPERTY_QUERY, *PSTORAGE_PROPERTY_QUERY;
调用时需设置输入参数中的字段
输出参数才会得到STORAGE_DEVICE_DESCRIPTOR类型数据。
typedef struct _STORAGE_DEVICE_DESCRIPTOR {
ULONG Version;
ULONG Size;
UCHAR DeviceType;
UCHAR DeviceTypeModifier;
BOOLEAN RemovableMedia;
BOOLEAN CommandQueueing;
ULONG VendorIdOffset;
ULONG ProductIdOffset;
ULONG ProductRevisionOffset;
ULONG SerialNumberOffset;
STORAGE_BUS_TYPE BusType;
ULONG RawPropertiesLength;
UCHAR RawDeviceProperties[];
} STORAGE_DEVICE_DESCRIPTOR, *PSTORAGE_DEVICE_DESCRIPTOR;
typedef enum _STORAGE_BUS_TYPE {
BusTypeUnknown = 0x00,
BusTypeScsi,
BusTypeAtapi,
BusTypeAta,
BusType1394,
BusTypeSsa,
BusTypeFibre,
BusTypeUsb,
BusTypeRAID,
BusTypeiScsi,
BusTypeSas,
BusTypeSata,
BusTypeSd,
BusTypeMmc,
BusTypeMax,
BusTypeMaxReserved = 0x7F
} STORAGE_BUS_TYPE, *PSTORAGE_BUS_TYPE;
明白了吧,如果总线类型为BusTypeUsb,就是找到了我们的USB移动硬盘了。
最后一个字段RawDeviceProperties[1]是可以动态扩展的(windows API经常有这种情况),
那么函数DeviceIoControl()中的参数nOutBufferSize应该填多少呢?
这时我们需要借助另一个数据结构STORAGE_DESCRIPTOR_HEADER,
在我们不知道device descriptor实际需要多大的缓冲区时,
可以先把STORAGE_DESCRIPTOR_HEADER作为输出参数以获得device descriptor的缓冲区大小,
其大小被存入header的size字段中。
typedef struct _STORAGE_DESCRIPTOR_HEADER {
ULONG Version;
ULONG Size;
} STORAGE_DESCRIPTOR_HEADER, *PSTORAGE_DESCRIPTOR_HEADER;
/******************************************************************************
* Function: get the bus type of an disk
* input: drive name (c:)
* output: bus type
* return: Succeed, 0
* Fail, -1
******************************************************************************/
DWORD GetDriveTypeByBus( const CHAR *drive, WORD *type )
{
HANDLE hDevice; // handle to the drive to be examined
BOOL result; // results flag
DWORD readed; // discard results STORAGE_DESCRIPTOR_HEADER *pDevDescHeader;
STORAGE_DEVICE_DESCRIPTOR *pDevDesc;
DWORD devDescLength;
STORAGE_PROPERTY_QUERY query; hDevice = CreateFile( drive, // 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
, // 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( - );
} query.PropertyId = StorageDeviceProperty;
query.QueryType = PropertyStandardQuery; pDevDescHeader = (STORAGE_DESCRIPTOR_HEADER *) malloc(
sizeof(STORAGE_DESCRIPTOR_HEADER) );
if ( NULL == pDevDescHeader )
{
return (DWORD) -;
} result = DeviceIoControl( hDevice, // device to be queried
IOCTL_STORAGE_QUERY_PROPERTY, // operation to perform
&query, sizeof query, // no input buffer
pDevDescHeader, sizeof(STORAGE_DESCRIPTOR_HEADER), // output buffer
&readed, // # bytes returned
NULL ); // synchronous I/O
if ( !result ) //fail
{
fprintf( stderr, "IOCTL_STORAGE_QUERY_PROPERTY Error: %ld\n",
GetLastError( ) );
free( pDevDescHeader );
(void) CloseHandle( hDevice );
return DWORD( - );
} devDescLength = pDevDescHeader->Size;
pDevDesc = (STORAGE_DEVICE_DESCRIPTOR *) malloc( devDescLength );
if ( NULL == pDevDesc )
{
free( pDevDescHeader );
return (DWORD) -;
} result = DeviceIoControl( hDevice, // device to be queried
IOCTL_STORAGE_QUERY_PROPERTY, // operation to perform
&query, sizeof query, // no input buffer
pDevDesc, devDescLength, // output buffer
&readed, // # bytes returned
NULL ); // synchronous I/O
if ( !result ) //fail
{
fprintf( stderr, "IOCTL_STORAGE_QUERY_PROPERTY Error: %ld\n",
GetLastError( ) );
free( pDevDescHeader );
free( pDevDesc );
(void) CloseHandle( hDevice );
return DWORD( - );
} //printf("%d\n", pDevDesc->BusType);
*type = (WORD) pDevDesc->BusType;
free( pDevDescHeader );
free( pDevDesc ); (void) CloseHandle( hDevice );
return ;
}
代码说明:
调用操作码为IOCTL_STORAGE_QUERY_PROPERTY的DeviceIoControl函数获得输出缓冲区大小。
以pDevDesc为输出参数,调用操作码为IOCTL_STORAGE_QUERY_PROPERTY的
DeviceIoControl函数获得device descriptor。
BOOL
WINAPI
DeviceIoControl(
_In_ (HANDLE) hDevice, // handle to a partition
_In_ (DWORD) IOCTL_STORAGE_QUERY_PROPERTY, // dwIoControlCode
_In_ (LPVOID) lpInBuffer, // input buffer - STORAGE_PROPERTY_QUERY structure
_In_ (DWORD) nInBufferSize, // size of input buffer
_Out_opt_ (LPVOID) lpOutBuffer, // output buffer - see Remarks
_In_ (DWORD) nOutBufferSize, // size of output buffer
_Out_opt_ (LPDWORD) lpBytesReturned, // number of bytes returned
_Inout_opt_ (LPOVERLAPPED) lpOverlapped ); // OVERLAPPED structure
Parameters
- hDevice
-
A handle to the disk device from which partition information is retrieved. To retrieve a device handle, call the CreateFile function.
- dwIoControlCode
-
The control code for the operation. Use IOCTL_STORAGE_QUERY_PROPERTY for this operation.
- lpInBuffer
-
A pointer to a buffer that contains a STORAGE_PROPERTY_QUERY data structure that specifies the details about the query. Device properties must be retrieved only from a device; attempting to retrieve device properties from an adapter will cause an error.
- nInBufferSize
-
The size of the input buffer, in bytes. It must be large enough to contain aSTORAGE_PROPERTY_QUERY data structure.
- lpOutBuffer
-
An optional pointer to a buffer that receives a structure that starts with the same fields as a STORAGE_DESCRIPTOR_HEADER data structure. For more information on the specific structures returned see the Remarks section.
- nOutBufferSize
-
The size of the output buffer, in bytes. It can be zero to determine whether a property exists without retrieving its data. To do that, set this parameter to zero (0) and the QueryType member of the STORAGE_PROPERTY_QUERY input structure to PropertyExistsQuery (1). If the call to DeviceIoControl returns a nonzero value then the property exists.
- lpBytesReturned
-
A pointer to a variable that receives the size of the data stored in the output buffer, in bytes.
If the output buffer is too small, the call fails, GetLastError returnsERROR_INSUFFICIENT_BUFFER, and lpBytesReturned is zero.
If lpOverlapped is NULL, lpBytesReturned cannot be NULL. Even when an operation returns no output data and lpOutBuffer is NULL, DeviceIoControl makes use oflpBytesReturned. After such an operation, the value of lpBytesReturned is meaningless.
If lpOverlapped is not NULL, lpBytesReturned can be NULL. If this parameter is not NULL and the operation returns data, lpBytesReturned is meaningless until the overlapped operation has completed. To retrieve the number of bytes returned, call GetOverlappedResult. If hDevice is associated with an I/O completion port, you can retrieve the number of bytes returned by callingGetQueuedCompletionStatus.
- lpOverlapped
-
A pointer to an OVERLAPPED structure.
If hDevice was opened without specifying FILE_FLAG_OVERLAPPED, lpOverlapped is ignored.
If hDevice was opened with the FILE_FLAG_OVERLAPPED flag, the operation is performed as an overlapped (asynchronous) operation. In this case, lpOverlappedmust point to a valid OVERLAPPED structure that contains a handle to an event object. Otherwise, the function fails in unpredictable ways.
For overlapped operations, DeviceIoControl returns immediately, and the event object is signaled when the operation is complete. Otherwise, the function does not return until the operation is complete or an error occurs.
Return value
If the operation completes successfully, DeviceIoControl returns a nonzero value.
If the operation fails or is pending, DeviceIoControl returns zero. To get extended error information, call GetLastError.
Remarks
The optional output buffer returned through the lpOutBuffer parameter can be one of several structures depending on the value of the PropertyId member of theSTORAGE_PROPERTY_QUERY structure pointed to by the lpInBuffer parameter. These values are enumerated by the STORAGE_PROPERTY_ID enumeration. If the QueryTypemember of the STORAGE_PROPERTY_QUERY is set to PropertyExistsQuery then no structure is returned.
| Value | lpOutBuffer structure |
|---|---|
| StorageDeviceProperty (0) | STORAGE_DEVICE_DESCRIPTOR |
| StorageAdapterProperty (1) | STORAGE_ADAPTER_DESCRIPTOR |
| StorageDeviceIdProperty (2) | STORAGE_DEVICE_ID_DESCRIPTOR |
| StorageDeviceUniqueIdProperty (3) | STORAGE_DEVICE_UNIQUE_IDENTIFIER |
| StorageDeviceWriteCacheProperty (4) | STORAGE_WRITE_CACHE_PROPERTY |
| StorageMiniportProperty (5) | STORAGE_MINIPORT_DESCRIPTOR |
| StorageAccessAlignmentProperty (6) | STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR |
| StorageDeviceSeekPenaltyProperty (7) | DEVICE_SEEK_PENALTY_DESCRIPTOR |
| StorageDeviceTrimProperty (8) | DEVICE_TRIM_DESCRIPTOR |
| StorageDeviceWriteAggregationProperty(9) | DEVICE_WRITE_AGGREGATION_DESCRIPTOR |
| StorageDeviceLBProvisioningProperty (11) | DEVICE_LB_PROVISIONING_DESCRIPTOR |
| StorageDevicePowerProperty (12) | DEVICE_POWER_DESCRIPTOR |
| StorageDeviceCopyOffloadProperty (13) | DEVICE_COPY_OFFLOAD_DESCRIPTOR |
| StorageDeviceResiliencyProperty (14) | STORAGE_DEVICE_RESILIENCY_DESCRIPTOR |
windows的磁盘操作之九——区分本地磁盘与移动硬盘的更多相关文章
- windows 10 超级优化,同时解决本地磁盘100%的问题
windows 10 超级优化,同时解决本地磁盘100%的问题 我的系统是笔记本I7处理器,配置了web服务器IIS 和一个数据库(mysql7),同时启用了虚拟机(表中已禁用),以及安装了offic ...
- servlet中获取各种相对地址(服务器、服务器所在本地磁盘、src等)。
[本文简介] 本文将提供javaWeb中经常使用到的相对路径的获取方法,分别有: url基本地址 带目录的url地址 服务器的根路径 服务器所在的 本地磁盘路径 服务器所在的本地磁盘路径,带文件夹 S ...
- windows 挂载windows 共享盘为本地磁盘
我们在设置数据库自动备份时,为了数据的安全往往需要直接将数据备份到远程服务器上.在Linux可以通过NFS挂载来实现,在Windows平台可以直接通过net use+subst来实现将远程服务器的目录 ...
- Windows平台将远程服务器的目录挂载为本地磁盘
我们在设置数据库自动备份时,为了数据的安全往往需要直接将数据备份到远程服务器上.在Linux可以通过NFS挂载来实现,在Windows平台可以直接通过net use+subst来实现将远程服务器的目录 ...
- windows的磁盘操作之七——获取当前所有的物理磁盘号 加备注
windows的磁盘操作之七--获取当前所有的物理磁盘号 2011-07-28 17:47:56 标签:windows API DeviceIoControl 物理磁盘 驱动器号 原创作品,允许转载 ...
- Ubuntu SSH 客户端的应用 | sshfs映射远程文件系统为本地磁盘
SSH是指Secure Shell,是一种安全的传输协议. Ubuntu客户端通过SSH访问远程服务器 ,以下步骤是客户端 的配置方法: 1. sudo apt-get install ssh 2. ...
- 实验六:通过grub程序引导本地磁盘内核启动系统(busybox)
实验名称: 通过grub程序引导本地磁盘内核启动系统(busybox) 实验环境: 理论上,该实验只需要配置好xen环境即可,但是,我们的xen环境安装在centOS7上,但是我们又是使用的kerne ...
- VMware虚拟机磁盘操作占用过高问题
使用虚拟机运行Linux图形桌面时,经常因为一个网页或者编译某个程序就导致虚拟机卡死,甚至影响主机使用.明明主机内存有8G,分配给虚拟机的内存也不少,为什么就这么卡顿.打开主机上的任务管理器查看发现磁 ...
- 服务器--远程桌面选择"本地资源"下不显示"本地磁盘"的解决办法(转)
转自:http://blog.sina.com.cn/s/blog_4cd978f90102wsvc.html “远程连接桌面”,每次连接候,我都选择了“本地资源”下面的“磁盘驱动器”,都会在远程电脑 ...
随机推荐
- 移动端Touch事件
案例1: <!doctype html> <html lang="en"> <head> <meta charset="UTF- ...
- JS动态创建元素(两种方法)
前言 创建元素有两种方法 1)将需要创建的元素,以字符串的形式拼接:找到父级元素,直接对父级元素的innnerHTML进行赋值. 2)使用Document.Element对象自带的一些函数,来实现动态 ...
- OKR.2019
转眼又一年过去了,回顾审视一年的得失,规划下一年的奋斗目标.Review And Planning,让全新的2019迎来全新的自己. O1 学习软件开发技术知识 KR1.1 阅读<CLR via ...
- UE简单配置
1 头上显示文件位置和名称,视图->视图列表——>打开文件标签,在右面点放大 2 函数列表,视图->视图列表——>打开文件标签
- new[] 到底做了什么?
#include<iostream> #include<cstdlib> using std::cout; using std::endl; using std::hex; c ...
- pycharm、webstorm和idea激活码
pycharm ---> http://blog.csdn.net/kevinelstri/article/details/57413791 idea ---> http://idea.l ...
- Rookey.Frame之实体表单验证
昨天给大家介绍了实体FluentValidation验证,今天继续给大家介绍表单验证,在Rookey.Frame框架中,表单验证有PrimaryKeyFields字段验证.唯一验证.必填验证.常用验证 ...
- Codeforces Round #213 (Div. 1) B - Free Market 思维+背包 好题
B - Free Market 思路:这个题怎么说呢,迷惑性很大,题目里说了交换了两个集合的时候如果有相同元素不能交换,感觉如果没 这句话能很快写出来, 其实当交换的两个集合有重复元素的时候只要交换那 ...
- linux用户下的.profile文件丢失
登录用户时出现以下问题: #su - wqq-bash-4.1$ -bash-4.1$ 查看时发现环境变量文件丢失造成的 解决方法: # ls -la /etc/skel/ total 36drwx ...
- 7-13 Power Calculus 快速幂计算 uva1374
想到快速幂 但是这题用不上 用迭代加深搜索 注意启发函数为 当前最大数<<(maxx-d) 如果大于n则剪枝 注意跳出语句的两种写法 一种170ms 一种390ms !!! d ...