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 “远程连接桌面”,每次连接候,我都选择了“本地资源”下面的“磁盘驱动器”,都会在远程电脑 ...
随机推荐
- day10作业
1.Java中,用{}括起来的代码称为代码块. 代码块分为局部代码块,构造代码块,静态代码块,同步代码块 局部代码块:在方法中出现,限定生命周期,及早释放,提高内存利用率 构造代码块:在类中方法外出现 ...
- 如何查看页面是否开启了gzip压缩
1.谷歌浏览器 F12 2.在表头单击鼠标右键 3.如果开启了gzip则显示gzip,没有则是空
- python基础学习之路No.3 控制流if,while,for
在学习编程语言的过程中,有一个很重要的东西,它就是判断,也可以称为控制流. 一般有if.while.for三种 ⭐if语句 if语句可以有一个通俗的解释,如果.假如 如果条件1满足,则…… 如果条件2 ...
- ASP.NET:插件化机制
概述 nopCommerce的插件机制的核心是使用BuildManager.AddReferencedAssembly将使用Assembly.Load加载的插件程序集添加到应用程序域的引用中.具体实现 ...
- Python面向对象中super用法与MRO机制
1. 引言 最近在研究django rest_framework的源码,老是遇到super,搞得一团蒙,多番查看各路大神博客,总算明白了一点,今天做一点总结. 2. 为什么要用super 1)让代码维 ...
- [转载] 你所不知道的TIME_WAIT和CLOSE_WAIT
前言 本文转载自 https://mp.weixin.qq.com/s/FrEfx_Yvv0fkLG97dMSTqw.很久前看到Vincent Bernat在博客中写了一遍关于TCP time-wai ...
- [代码审计]XiaoCms(后台任意文件上传至getshell,任意目录删除,会话固定漏洞)
0x00 前言 这段时间就一直在搞代码审计了.针对自己的审计方法做一下总结,记录一下步骤. 审计没他,基础要牢,思路要清晰,姿势要多且正. 下面是自己审计的步骤,正在逐步调整,寻求效率最高. 0x01 ...
- NetCore+Dapper WebApi架构搭建(三):添加实体和仓储
上一节讲了类库添加一些底层的基本封装,下面来添加实体和仓储 1.Entities文件夹添加一个实体类Users,继承BaseModel,即拥有BaseModel的主键 using System; na ...
- iOS 11开发教程(六)iOS11Main.storyboard文件编辑界面
iOS 11开发教程(六)iOS11Main.storyboard文件编辑界面 在1.2.2小节中提到过编辑界面(Interface builder),编辑界面是用来设计用户界面的,单击打开Main. ...
- python opencv3 背景分割 mog2 knn
git:https://github.com/linyi0604/Computer-Vision 使用mog2算法进行背景分割 # coding:utf-8 import cv2 # 获取摄像头对象 ...