利用IOCTL_STORAGE_QUERY_PROPERT获取总线类型

来源:互联网 发布:英灵召唤师 知乎 编辑:程序博客网 时间:2024/05/15 12:10

#define IOCTL_STORAGE_BASE FILE_DEVICE_MASS_STORAGE

// IOCTL控制码

#define IOCTL_STORAGE_QUERY_PROPERTY   CTL_CODE(IOCTL_STORAGE_BASE, 0x0500, METHOD_BUFFERED, FILE_ANY_ACCESS)

 

// 存储设备的总线类型

typedef enum _STORAGE_BUS_TYPE {

    BusTypeUnknown = 0x00,

                   BusTypeScsi,

                   BusTypeAtapi,

                   BusTypeAta,

                   BusType1394,

                   BusTypeSsa,

                   BusTypeFibre,

                   BusTypeUsb,

                   BusTypeRAID,

                   BusTypeMaxReserved = 0x7F

} STORAGE_BUS_TYPE, *PSTORAGE_BUS_TYPE;

 

// 查询存储设备属性的类型

typedef enum _STORAGE_QUERY_TYPE {

    PropertyStandardQuery = 0,          // 读取描述

                   PropertyExistsQuery,                // 测试是否支持

                   PropertyMaskQuery,                  // 读取指定的描述

                   PropertyQueryMaxDefined  // 验证数据

} STORAGE_QUERY_TYPE, *PSTORAGE_QUERY_TYPE;

 

// 查询存储设备还是适配器属性

typedef enum _STORAGE_PROPERTY_ID {

    StorageDeviceProperty = 0,   // 查询设备属性

                   StorageAdapterProperty   // 查询适配器属性

} STORAGE_PROPERTY_ID, *PSTORAGE_PROPERTY_ID;

 

// 查询属性输入的数据结构

typedef struct _STORAGE_PROPERTY_QUERY {

         STORAGE_PROPERTY_ID PropertyId;  // 设备/适配器

         STORAGE_QUERY_TYPE QueryType;  // 查询类型

    UCHAR AdditionalParameters[1];  // 额外的数据(仅定义了象征性的1个字节)

} STORAGE_PROPERTY_QUERY, *PSTORAGE_PROPERTY_QUERY;

 

 

 

// 查询属性输出的数据结构

typedef struct _STORAGE_DEVICE_DESCRIPTOR {

    ULONG Version;  // 版本

    ULONG Size;   // 结构大小

    UCHAR DeviceType;  // 设备类型

    UCHAR DeviceTypeModifier; // SCSI-2额外的设备类型

    BOOLEAN RemovableMedia; // 是否可移动

    BOOLEAN CommandQueueing; // 是否支持命令队列

    ULONG VendorIdOffset;  // 厂家设定值的偏移

    ULONG ProductIdOffset;  // 产品ID的偏移

    ULONG ProductRevisionOffset; // 产品版本的偏移

    ULONG SerialNumberOffset;  // 序列号的偏移

    STORAGE_BUS_TYPE BusType;  // 总线类型

    ULONG RawPropertiesLength;  // 额外的属性数据长度

    UCHAR RawDeviceProperties[1]; // 额外的属性数据(仅定义了象征性的1个字节)

} STORAGE_DEVICE_DESCRIPTOR, *PSTORAGE_DEVICE_DESCRIPTOR;

 

ULONG GetStorageDeviceBusType(IN PDEVICE_OBJECT DeviceObject)

{

   PIRP NewIrp;

   PSTORAGE_DEVICE_DESCRIPTOR Descriptor;

   STORAGE_PROPERTY_QUERY Query;

   CHAR Buffer[BUFFER_SIZE];

   KEVENT WaitEvent;

   NTSTATUS Status;

   IO_STATUS_BLOCK IoStatus;

 

   // first set the query properties

   Query.PropertyId = StorageDeviceProperty;

   Query.QueryType = PropertyStandardQuery;

 

   // initialize the waitable event

   KeInitializeEvent(&WaitEvent, NotificationEvent, FALSE);

 

   // we should build the query irp ourselves

   NewIrp = IoBuildDeviceIoControlRequest(IOCTL_STORAGE_QUERY_PROPERTY, DeviceObject,

       (PVOID)&Query, sizeof(Query), (PVOID)Buffer, NAME_BUFFER_SIZE, FALSE, &WaitEvent,

 

&IoStatus);

 

   if (NULL == NewIrp)    // can't create new irp

   {

       DbgPrint("[%s] [%u] I can't create a new irp to query the property of device (%p)!/n",

           __FILE__, __LINE__, DeviceObject);

       return BusTypeUnknown;

   }

 

   // send this irp to the storage device

   Status = IoCallDriver(DeviceObject, NewIrp);

 

   if (Status == STATUS_PENDING)

   {

       Status = KeWaitForSingleObject(&WaitEvent, Executive, KernelMode, FALSE, NULL);

       Status = IoStatus.Status;

   }

      

   if (!NT_SUCCESS(Status))

   {

       DbgPrint("[%s] [%u] Query IOCTL_STORAGE_QUERY_PROPERTY of device (%p) failed, Status=0x%

 

08X!/n",

           __FILE__, __LINE__, DeviceObject, Status);

       return BusTypeUnknown;

   }

   Descriptor = (PSTORAGE_DEVICE_DESCRIPTOR)Buffer;

   return Descriptor->BusType;

}

若本函数返回BusType3是一般硬盘,BusType7USB接口设备。