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