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 “远程连接桌面”,每次连接候,我都选择了“本地资源”下面的“磁盘驱动器”,都会在远程电脑 ...
随机推荐
- Java HashCode详解
一.为什么要有Hash算法 Java中的集合有两类,一类是List,一类是Set.List内的元素是有序的,元素可以重复.Set元素无序,但元素不可重复.要想保证元素不重复,两个元素是否重复应该依据什 ...
- plsql developer配置
一:今天plsql developer连接 出问题了 ,Oracleclient没正确安装 0.连接vpn 1.环境变量:TNS_ADMIN = D:\worksoftware\oracleClien ...
- Luogu P3384 【【模板】树链剖分】
转载请注明出处,部分内容引自banananana大神的博客 ~~别说你不知道什么是树~~╮(─▽─)╭(帮你百度一下) 先来回顾两个问题:1,将树从x到y结点最短路径上所有节点的值都加上z 这也是个模 ...
- loaded some nib but the view outlet was not set(转载)
当使用 initWithNibName 函数, 并使用 由nib文件生成的ViewController 的view属性时候,遇到这个问题. //load loc.xib UIViewControlle ...
- Effective STL 学习笔记 Item 17: Swap Trick
假设有若干对象存于一个 vector 中: class Widget; vector<Widget> vw; 后来由于某些原因,从该容器中删除了若干对象(参考erase-remove id ...
- day6作业--游戏人生
本节作业: 熟练使用类和模块,写一个交互性强.有冲突的程序. 思路: 1.各个模块之间的调用关系,如何使用类,各种方法的使用上面: 2.学了类,以为能用来解决所有问题,东西都要写在类里面: 3.下面自 ...
- JAVAEE——宜立方商城10:使用freemarker实现网页静态化、ActiveMq同步生成静态网页、Sso单点登录系统分析
1. 学习计划 1.使用freemarker实现网页静态化 2.ActiveMq同步生成静态网页 2. 网页静态化 可以使用Freemarker实现网页静态化. 2.1. 什么是freemarker ...
- Linux VXLAN
VXLAN协议 VXLAN是Virtual eXtensible Local Area Network的缩写,RFC 7348的标题“A Framework for Overlaying Virtua ...
- 1005 Spell It Right (20)(20 point(s))
problem Given a non-negative integer N, your task is to compute the sum of all the digits of N, and ...
- 1003 Emergency (25)(25 point(s))
problem 1003 Emergency (25)(25 point(s)) As an emergency rescue team leader of a city, you are given ...