Battle DeviceIocontrol five: Enumerally enumerated storage equipment installed

zhaozj2021-02-16  51

Q The first few times we discussed the device name, with the device name (path), you can directly call CreateFile to open the device, and make it supported I / O operation. If you don't know how to know the device name in advance, how do you access your device?

A Access device must use the device handle, and get the device handle must know the device path, this routine is not changed. Each device has a GUID it belongs, we can get the device path along this GUID.

GUID is the world's unique identification code of the same or the same equipment. It is a 128 bit (16-byte) plastic surgery, true face

TypedEf struct _guid

{

Unsigned long data1;

UNSIGNED SHORT DATA2;

UNSIGNED SHORT DATA3;

Unsigned char data4 [8];

} GUID, * Pguid;

For example, the GUID of the DISK class is "53F56307-B6BF-11D0-94F2-00A0C91EFB8B", which can be defined as in our program.

Const Guid DiskClassGuid = {0x53F56307L, 0xB6BF, 0x11D0, {0x94, 0xF2, 0x00, 0xA0, 0xc9, 0x1e, 0xfb, 0x8b)};

Or use a macro to define

Define_guid (DiskClassGuid, 0x53F56307L, 0xB6BF, 0x11D0, 0x94, 0xF2, 0x00, 0xA0, 0xc9, 0x1e, 0xfb, 0x8b);

Find the device path through GUID, you need to use a set of device-managed API functions

SetupdiGetClassDevs, SetupdienumDeviceInterfaces, SetupdiGetInterfaceDeetail, SetupdideStroyDeviceInfolist,

And structure sp_device_interface_data, sp_device_interface_detail_data.

For information, please check the MSDN, here is not described in detail.

The code for realizing the GUID to the device path is as follows:

// setUpdiGetInterFaceDeviceDetail requires the output length, defined enough

#define interface_detail_size (1024)

/ / Get the device path according to GUID

// LPGUID: GUID pointer

// pszdevicepath: Pointer for device path pointer

// Return: Successfully obtained device path number, there may be more than 1

INT getDevicePath (LPGUID LPGUID, LPTSTSTST * PSZDEVICEPATH)

{

HDevinfo hdevinfoseet;

Sp_device_interface_data ifdata;

PSP_DEVICE_INTERFACE_DETAIL_DATA PDETAIL;

Int ncount;

Bool Bresult;

/ / Get a GUID related device information set sector

HDevinfoset = :: setupdigetclassdevs (lpguid, // class gUID

NULL, / / ​​NS

NULL, / / ​​Do not specify a parent window handle

Digcf_present | Digcf_DeviceInterface); // Currently existing equipment

// Failure ...

IF (hdevinfoseet == invalid_handle_value)

{

Return 0;

}

// Apply for equipment interface data space

PDETAIL = (psp_device_interface_detail_data) :: GlobalAlloc (LMEM_ZEROINIT, Interface_Detail_size); pdetail-> cbsize = sizeof (sp_device_interface_detail_data);

Ncount = 0;

BRESULT = True;

// Equipment number = 0, 1, 2 ... take one by one test equipment interface, until failure

While (BRESULT)

{

IFData.cbsize = sizeof (ifdata);

// Enumerate the device interface that meets the GUID

BRESULT = :: setUpdienumDeviceInterfaces

HDEVINFOSET, // device information set sector

NULL, / / ​​No additional equipment description

LPGUID, // GUID

(Ulong) NCOUNT, / / ​​Equipment sequence number in the device information set

& ifdata); / / Device Interface Information

IF (BRESULT)

{

// Take the details of the device interface (device path)

BRESULT = SetupdiGetInterfaceDeviceDetail

HDEVINFOSET, // device information set sector

& ifdata, // Device Interface Information

PDETAIL, // Device Interface Details (Device Path)

Interface_detail_size, // Output Buffer Size

NULL, // Do not calculate the output buffer size (direct set value)

NULL); // No additional equipment description

IF (BRESULT)

{

// Copy the device path to the output buffer

:: Strcpy (pszdevicepath [ncount], pdetail-> devicepath);

// Adjust the count value

NCOUNT ;

}

}

}

/ / Release device interface data space

:: GlobalFree (pdetail);

// Close the device information set sector

:: setupdideStroyDeviceInfolist (HDEVINFOSET);

Return ncount;

}

When calling your getDevicePath function, pay attention to the pszdevicePath is a pointer to the string pointer, for example

INT I;

Char * szdevicepath [max_device]; // device path

// Assign space required

For (i = 0; i

{

SzdevicePath [i] = new char [256];

}

// Take the device path

NDEvice = :: getDevicePath ((LPGUID) & diskclassguid, szdevicepath;

// acquire device information one by one

For (i = 0; i

{

// Open the device

HDevice = :: OpenDevice (szdevicePath [i]);

IF (HDevice! = INVALID_HANDLE_VALUE)

{

... // I / O operation

:: CloseHandle (HDevice);

}

}

// Release space

For (i = 0; I & lt; max_device; i )

{

Delete [] szdevicepath [i];

}

In addition to the Project of this example, in addition to the WiniocTl.h, INITGUID.H, SetupAPI.H, and connection setupapi.lib. Q After you get the device path, you can go to the next step, open the device with CreateFile, then read and write with DeviceioControl?

A Yes. Although the device path is not the same as those we have in contact. This is "//./physicaldrive0", now the bird gun is changed, and it has become a pair like this:

"//? / IDE # diskmaxtor_2f040j0 __________________________m51j0 # 3146563447534558202020202020202020 # {53F56307-B6BF-11D0-94F2-00A0C91EFB8B}".

In fact, this device name can be found somewhere in the registry, for example, in Win2000, this name can be located

HKEY_LOCAL_MACHINE / SYSTEM / CURRENTCONTROLSET / SERVICES / DISK / ENUM / 0,

But "#" is replaced with "/". Analyze such a device path, you will find a very interesting thing, which is combined by the interface type, product model, firmware version, serial number, computer name, GUID and other information. Of course, it is not specified, can't expect from this to get what you want to know.

After using CreateFile to open the device, use the I / O control code such as storage device, ioctl_disk_get_drive_geometry, ioctl_storage_get_media_types_ex.

Today we discuss a new control code: IOCTL_STORAGE_QUERY_PROPERTY, get the device attribute information, you want to get the various fixed and removable hard drives installed in the system, the interface type, serial number, serial number, serial number , Product ID and other information.

// ioctl control code

#define ioctl_Storage_Query_Property CTL_CODE (ioctl_storage_base, 0x0500, method_buffered, file_any_access)

// Storage device bus type

Typedef enum _Storage_bus_type {

Bustypeunknown = 0x00,

Bustypescsi,

Bustypeatapi,

Bustypeata,

Bustype1394,

Bustypessa,

Bustypefibre,

Bustypeusb,

Bustyperaid,

BustypeMaxReServed = 0x7f

} Storage_bus_type, * pstorage_bus_type;

// Query the type of storage device properties

TypedEf Enum _Storage_Query_Type {

PropertyStandardQuery = 0, // Read Description

PropertyExistsQuery, // Do not support

PropertyMaskQuery, // Read the specified description

PropertyQueryMaxDefined // Verify data

} Storage_Query_Type, * PStorage_Query_Type;

// Query storage device or adapter properties

TYPEDEF ENUM _STORAGE_PROPERTY_ID {

StorageDeviceProperty = 0, // Query device properties

StorageAdapterProperty // Query Adapter Properties} Storage_Property_ID, * PStorage_Property_ID;

// Query the data structure entered by the property

TypedEf struct _Storage_Property_Query {

Storage_Property_ID PropertyID; // Device / Adapter

Storage_query_type querytype; // query type

Uchar additionalParameters [1]; // Extra data (only 1 byte of symbolic)

} Storage_Property_Query, * pstorage_property_query;

// Query the data structure output by the property

Typedef struct _Storage_Device_descriptor {

Ulong version; // version

Ulong size; // structure size

Uchar deviceType; // device type

Uchar DeviceTypeModifier; // SCSI-2 Additional device type

Boolean RemovableMedia; / / Can be moved

Boolean commandQueueing; / / Do you support command queue?

Ulong vendoridoffset; // Manufacturer sets the offset

Ulong productIdoffset; // Product ID offset

Ulong productRevisionOffset; // Product version offset

Ulong serialnumberoffset; // serial number offset

Storage_bus_type busType; // Bus Type

Ulong RawpropertiesLength; // Extra property data length

Uchar RawdeviceProperties [1]; // Extra attribute data (only 1 byte of symbolic)

} Storage_Device_descriptor, * pstorage_device_descriptor;

// Take the device attribute information

// HDevice - device handle

// PDEVDESC - Output device description and attribute information buffer pointer (including two parts connected together)

Bool getDriveProperty (Handle HDevice, PStorage_Device_Descriptor PDEVDESC)

{

Storage_property_query query; // Query input parameters

DWORD dwoutBytes; // ioctl output data length

BOOL BRESULT; // ioctl return value

/ / Specify the method of query

Query.propertyId = storageDeviceproperty;

Query.QueryType = propertyStandardQuery;

// Take device properties information with ioctl_storage_query_property

BRESULT = :: Deviceiocontrol (HDevice, // Equipment handle

IOCTL_STORAGE_QUERY_PROPERTY, // Take device properties information

& Query, SIZEOF (Storage_Property_Query), // Enter data buffer

PDEVDESC, PDEVDESC-> SIZE, / / ​​OV output Data buffer

& dwoutbytes, // Output Data Length (LPOVERLAPPED) NULL); // Synchronous I / O

Return BRESULT;

}

Q I use this method from the data returned from IOCTL_STORAGE_QUERY_PROPERTY, the serial number, product ID and other information of the external hard disk of the CDROM and USB interfaces are not available. However, from the device path, it is clear that there is this information, why didn't it fill it into the storage_device_descriptor? Then why the hard disk serial number is "D22P7khe", why is it filled with "314656344753455820202020202020202020"?

A for these two questions, I am also confused, but I don't dare to guess, I am pondering to ask Microsoft.

[related resources]

This article Demo Source: StorageEnum.zip (23KB) BHW98 column: http://www.9cbs.net/develop/author/netauthor/bhw98/

First release: 2003-02-28 Last revision: 2003-05-20

转载请注明原文地址:https://www.9cbs.com/read-23675.html

New Post(0)