Q with ioctl_disk_get_drive_geometry or ioctl_storage_get_media_types_ex can only get very few disk parameters, I want to get more detailed information including the hard disk serial number, what is the way?
A is indeed, with the I / O control code you said, only the most basic disk parameters can be obtained. Get the I / O control code of the disk factory information, Microsoft is not open in the VC / MFC environment, and some clues can be found in the DDK. Earl, Lynn McGuire wrote a very famous program DISKID32 that acquires IDE hard drive details, the following example is based on its basis, which is increasing and improved.
In this example, we want to use the ATA / APAPI Identify Device Directive. ATA / APAPI is the Ide / EIDE / UDMA hard disk and other standardable storage devices and host interfaces, which have been reached by ATA / APAPI-7 version. The interface standard specifies the input and output register and instruction set of the ATA / ATAPI device. For more detailed ATA / ATAPI technical materials, you can access T13 sites.
The constant and data structures used are below:
// ioctl control code
// #define DFP_SEND_DRIVE_COMMAND 0x0007C084
#define DFP_SEND_DRIVE_COMMAND CTL_CODE (ioctl_disk_base, 0x0021, method_buffered, file_read_access | file_write_access)
// #define DFP_RECEIVE_DRIVE_DATA 0x0007C088
#DEFINE DFP_RECEIVE_DRIVE_DATA CTL_CODE (ioctl_disk_base, 0x0022, method_buffered, file_read_access | file_write_access)
#define file_device_scsi 0x0000001B
#DEFINE IOCTL_SCSI_MINIPORT_IDENTIFY ((file_device_scsi << 16) 0x0501)
#define ioctl_scsi_miniport 0x0004d008 // See ntddscsi.h for definition
// ATA / ATAPI instruction
#define IDE_ATA_IDENTIFY 0XEC / / ATA ID instruction (Identify Device)
// IDE command register
Typedef struct_Ideregs
{
BYTE BFEATURESREG; // Feature Register (for Smart Command)
Byte bsectorcountreg; // sector number register
Byte bsectorNumberReg; // Start sector register
BYTE BCYLOWREG; / / Start Cylinder Low byte Register
Byte bcylhighreg; // Start Cylindrical High byte Register
Byte BDriveHeadReg; // Drive / Head Register
BYTE BCOMMANDREG; / / instruction register
BYTE BRESERVED; // Reserved
} Idegers, * pidegeggs, * lpideregs;
// State returned from the driver
Typedef struct_driverstatus
{
Byte bDriveRerror; // error code
BYTE BIDESTATUS; // IDE Status Register
Byte breserved [2]; // Reserved
DWORD dwreserved [2]; // Reserved
DRIVERSTATUS, * PDRIVERSTATUS, * LPDRIVERSTATUS;
// IDE device IOCTL input data structure
Typedef struct _sendcmdinparams
{
DWORD CBUFFERSIZE; / / Buffer byte
Idegegs IrDriveRegs; // IDE register group
BYTE BDRIVENUMBER; // Drive
Byte breserved [3]; // Reserved
DWORD dwreserved [4]; // Reserved
BYTE BBUFFER [1]; / / Input buffer (here consisting of 1 byte)
} Sendcmdinparams, * psendcmdinparams, * lpsendcmdinparams;
// IDE device IOCTL output data structure
Typedef struct _sendcmdoutparams
{
DWORD CBUFFERSIZE; / / Buffer byte
DriversTatus driverStatus; // Driver returns status
BYTE BBUFFER [1]; / / Input buffer (here consisting of 1 byte)
} Sendcmdoutparams, * psendcmdoutparams, * lpsendcmdoutparams;
// IDE ID command returned by the data
// Total 512 bytes (256 Word), only some of the items (substantially based on ATA / ATAPI-4)
Typedef struct _idinfo
{
Ushort wgenconfig; // Word 0: Basic information word
Ushort wnumcyls; // Word 1: Cylindrical
Ushort WRESERVED2; // Word 2: Reserved
Ushort Wnumheads; // Word 3: Number of magnetic heads
Ushort WRESERVED4; // Word 4: Reserved
Ushort WRESERVED5; // Word 5: Reserved
Ushort wnumsectorspertrack; // Word 6: Number of channels per track
Ushort Wvendorunique [3]; // Word 7-9: Manufacturer Settings
Char sserialnumber [20]; // Word 10-19: Serial number
Ushort wbuffertype; // Word 20: Buffer type
Ushort wbuffersize; // Word 21: Buffer size
Ushort Weccsize; // Word 22: ECC Check Size
Char sfirmwarerev [8]; // Word 23-26: Firmware version
Char Smodelnumber [40]; // Word 27-46: Internal Model
Ushort wmorevendorunique; // Word 47: Manufacturer setting value
Ushort Wreserved48; // Word 48: Reserved
Struct {
USHORT RESERVED1: 8;
Ushort DMA: 1; // 1 = Support DMA
Ushort LBA: 1; // 1 = Support LBAUSHORT DISIORDY: 1; // 1 = Can not use iREDY
Ushort iordy: 1; // 1 = Support IRDY
Ushort SoftReset: 1; // 1 = Need ATA soft start
Ushort overlap: 1; // 1 = Support overlapping operation
Ushort queue: 1; // 1 = support command queue
Ushort INLDMA: 1; // 1 = Support crossover DMA
} wcapabilities; // Word 49: General capabilities
Ushort WRESERVED1; // Word 50: Reserved
Ushort wpiotiming; // Word 51: PIO timing
Ushort wdmatiming; // Word 52: DMA timing
Struct {
Ushort chsnumber: 1; // 1 = Word 54-58 is effective
Ushort cyclenumber: 1; // 1 = Word 64-70 is effective
USHORT UNLTRADMA: 1; // 1 = Word 88 is valid
Ushort reserved: 13;
} wfieldvalidity; // Word 53: Subsequent field validity logo
Ushort wnumcurcyls; // Word 54: CHS addressable cylindrical number
Ushort wnumcurheads; // Word 55: CHS addressable number of magnetic heads
Ushort wnumcursectorspertrack; // Word 56: CHS addressable number of channels per track
Ushort wcursectorslow; // Word 57: CHS addressable sector number low words
Ushort wcursectorshigh; // Word 58: CHS addressable sector number high word
Struct {
USHORT CURNUMBER: 8; // Current disposable readable write sector number
Ushort Multi: 1; // 1 = Selected multi-sector reading
USHORT RESERVED1: 7;
} WMULTSECTORSTUFF; // Word 59: Multi-sector reading and writing settings
Ulong dwtotalsectors; // Word 60-61: LBA addressable sector number
Ushort WSINGLEWORDDMA; // Word 62: Single-byte DMA support capability
Struct {
Ushort mode0: 1; // 1 = support mode 0 (4.17Mb / s)
USHORT MODE1: 1; // 1 = Support mode 1 (13.3MB / s)
USHORT MODE2: 1; // 1 = Support mode 2 (16.7MB / s)
USHORT RESERVED1: 5;
USHORT MODE0SEL: 1; // 1 = Selected mode 0
USHORT MODE1SEL: 1; // 1 = Selected mode 1
USHORT MODE2SEL: 1; // 1 = Selected Mode 2USHORT Reserved2: 5;
} WMULTIWORDDMA; // Word 63: Multi-byte DMA support capabilities
Struct {
Ushort AdvPoimodes: 8; // Support advanced POI mode
USHORT RESERVED: 8;
} wpiocapacity; // Word 64: Advanced PIO support capabilities
Ushort wminmultiwordddmacycle; // Word 65: Multi-byte DMA transfer cycle minimum
Ushort WRECMULTIWORDDMACYCLE; / / WORD 66: Recommended value for multi-byte DMA transfer cycle
Ushort WMINPIONOFLOWCY; / / WORD 67: Minimum value of the PIO transfer cycle when no current control
Ushort wminpoiflowcycle; // Word 68: Minimum value of the PIO transfer cycle when streaming
Ushort Wreserved69 [11]; // Word 69-79: Reserved
Struct {
USHORT RESERVED1: 1;
Ushort ATA1: 1; // 1 = Support ATA-1
Ushort ATA2: 1; // 1 = Support ATA-2
Ushort ATA3: 1; // 1 = Support ATA-3
Ushort ATA4: 1; // 1 = Support ATA / ATAPI-4
Ushort ATA5: 1; // 1 = Support ATA / ATAPI-5
USHORT ATA6: 1; // 1 = Support ATA / ATAPI-6
Ushort ATA7: 1; // 1 = Support ATA / ATAPI-7
Ushort ATA8: 1; // 1 = Support ATA / ATAPI-8
Ushort ATA9: 1; // 1 = Support ATA / ATAPI-9
Ushort ATA10: 1; // 1 = Support ATA / ATAPI-10
Ushort ATA11: 1; // 1 = support ATA / ATAPI-11
Ushort ATA12: 1; // 1 = support ATA / ATAPI-12
Ushort ATA13: 1; // 1 = Support ATA / ATAPI-13
Ushort ATA14: 1; // 1 = Support ATA / ATAPI-14
Ushort reserved2: 1;
} wmajorversion; // Word 80: Proper version
Ushort wminorversion; // Word 81: Depth version
Ushort Wreserved82 [6]; // Word 82-87: Reserved
Struct {
Ushort mode0: 1; // 1 = support mode 0 (16.7MB / s)
Ushort Mode1: 1; // 1 = Support mode 1 (25MB / s)
USHORT MODE2: 1; // 1 = Support mode 2 (33MB / s)
Ushort Mode3: 1; // 1 = Support mode 3 (44MB / s)
USHORT MODE4: 1; // 1 = Support mode 4 (66MB / s)
Ushort mode5: 1; // 1 = support mode 5 (100MB / s)
Ushort mode6: 1; // 1 = support mode 6 (133MB / s)
Ushort Mode7: 1; // 1 = Support mode 7 (166MB / s) ???
USHORT MODE0SEL: 1; // 1 = Selected mode 0
USHORT MODE1SEL: 1; // 1 = Selected mode 1
Ushort mode2sel: 1; // 1 = Selected mode 2
USHORT MODE3SEL: 1; // 1 = Selected mode 3
Ushort mode4sel: 1; // 1 = Selected mode 4
Ushort mode5sel: 1; // 1 = Selected mode 5
Ushort mode6sel: 1; // 1 = Selected mode 6
Ushort mode7sel: 1; // 1 = Selected mode 7
} wultradma; // Word 88: Ultra DMA support capabilities
Ushort Wreserved89 [167]; // Word 89-255
} IDINFO, * PIDINFO;
// SCSI driver desired input and output shared structure
Typedef struct _srb_io_control
{
Ulong headerlength; // head length
Uchar Signature [8]; // Feature Name
Ulong timeout; // timeout time
Ulong controlcode; // control code
Ulong returncode; // return code
Ulong length; // buffer length
} SRB_IO_CONTROL, * PSRB_IO_CONTROL;
It is necessary to pay attention to the IDInfo 57-58 Word (CHS addressable sector number), because not satisfying the 32-bit demand, is not defined as a Ulong field. Lynn McGuire is exactly because it is defined as a ULONG field, which causes the structure to be unavailable.
The following is the core code:
// Open the device
// filename: "File Name" of the device (device path)
Handle OpenDevice (lpctstr filename)
{
Handle HDevice;
// Open the device
HDevice = :: createfile (filename, // file name
Generic_read | generic_write, // Read and write
File_share_read | file_share_write, // shared method
NULL, / / Default security descriptor
Open_existing, // creation method
0, // Do not set file properties
NULL); // Do not need to refer to the template file
Return HDevice;
}
/ / Get device information to the "Identify Device" command to the drive
// HDevice: Equipment handle // pidInfo: device information structure pointer
Bool IdentifyDevice (Handle Hdevice, PidInfo PidInfo)
{
Psendcmdinparams pscip; // Enter data structure pointer
Psendcmdoutparams pscop; // Output data structure pointer
DWORD dwoutBytes; // ioctl output data length
BOOL BRESULT; // ioctl return value
// Apply for input / output data structural space
PSCIP = (psendcmdinparams) :: Globalalloc (LMEM_ZEROINIT, SIZEOF (Sendcmdinparams) - 1);
PSCOP = (psendcmdoutparams) :: GlobalAlloc (LMEM_ZEROINIT, SIZEOF (SENDCMDOUTPARAMS) SIZEOF (IdInfo) - 1);
/ / Specify the register value of the ATA / ATAPI command
// pscip-> IrDriveRegs.bfeaturesReg = 0;
// pscip-> IrDriveRegs.bsectorcountreg = 0;
// pscip-> IrDriveRegs.bsectornumberreg = 0;
// pscip-> IrDriveRegs.bcyllowreg = 0;
// pscip-> IrDriveRegs.bcylhighReg = 0;
// pscip-> IrDriveRegs.BdriveHeadReg = 0;
Pscip-> IrDriveRegs.bcommandreg = IDE_ATA_IDENTIFY;
/ / Specify the input / output data buffer size
Pscip-> cbuffersize = 0;
Pscop-> cbuffersize = sizeof (iDInfo);
// Identify Device
BRESULT = :: Deviceiocontrol (HDevice, // Equipment handle
DFP_RECEIVE_DRIVE_DATA, / / Specify IOCTL
PSCIP, SIZEOF (Sendcmdinparams) - 1, // Enter data buffer
PSCOP, SIZEOF (Sendcmdoutparams) SizeOf (IDInfo) - 1, // Output Data Buffer
& dwoutBytes, // Output data length
(LPOVERLAPPED) NULL); // Synchronous I / O
/ / Copy device parameter structure
:: Memcpy (PidInfo, Pscop-> BBuffer, Sizeof (iDInfo);
// Release the input / output data space
:: GlobalFree (PSCOP);
:: GlobalFree (PSCIP);
Return BRESULT;
}
/ / Drive the "Identify Device" command to the SCSI Mini-Port to get device information
// HDevice: Equipment handle
// pidinfo: Equipment information structure pointer
Bool IdentifyDeviceAsscsi (Handle Hdevice, Int NDRIVE, PIDINFO PIDINFO)
{
Psendcmdinparams pscip; // Enter data structure pointer
Psendcmdoutparams pscop; // Output data structure pointer
PSRB_IO_CONTROL PSRBIO; / / SCSI input Output data structure pointer DWORD dwoutBytes; // ioctl output data length
BOOL BRESULT; // ioctl return value
// Apply for input / output data structural space
PSRBIO = (PSRB_IO_CONTROL) :: GlobalAlloc (LMEM_ZEROINIT,
SizeOf (SRB_IO_CONTROL) SIZEOF (Sendcmdoutparams) SizeOf (IDInfo) - 1);
Pscip = (psendcmdinparams) ((char *) PSRBIO SIZEOF (SRB_IO_CONTROL);
PSCOP = (psendcmdoutparams) ((char *) PSRBIO SIZEOF (SRB_IO_CONTROL);
// Plip the input / output data
Psrbio-> HeaderLength = SizeOf (SRB_IO_CONTROL);
PSRBIO-> Timeout = 10000;
Psrbio-> length = sizeof (sendcmdoutparams) sizeof (IDInfo) - 1;
Psrbio-> Controlcode = ioctl_scsi_miniport_identify;
:: Strncpy ((char *) Psrbio-> Signature, "SCSIDISK", 8);
/ / Specify the register value of the ATA / ATAPI command
// pscip-> IrDriveRegs.bfeaturesReg = 0;
// pscip-> IrDriveRegs.bsectorcountreg = 0;
// pscip-> IrDriveRegs.bsectornumberreg = 0;
// pscip-> IrDriveRegs.bcyllowreg = 0;
// pscip-> IrDriveRegs.bcylhighReg = 0;
// pscip-> IrDriveRegs.BdriveHeadReg = 0;
Pscip-> IrDriveRegs.bcommandreg = IDE_ATA_IDENTIFY;
Pscip-> bdrivenumber = ndrive;
// Identify Device
BRESULT = :: Deviceiocontrol (HDevice, // Equipment handle
IOCTL_SCSI_MINIPORT, / / Specify IOCTL
PSRBIO, SIZEOF (SRB_IO_CONTROL) SIZEOF (Sendcmdinparams) - 1, // Input Data Buffer
PSRBIO, SIZEOF (SRB_IO_CONTROL) SIZEOF (IdCmdoutparams) SizeOf (IDInfo) - 1, // Output Data Buffer
& dwoutBytes, // Output data length
(LPOVERLAPPED) NULL); // Synchronous I / O
/ / Copy device parameter structure
:: Memcpy (PidInfo, Pscop-> BBuffer, Sizeof (iDInfo);
// Release the input / output data space
:: GlobalFree (Psrbio);
Return BRESULT;
}
// Pour the characters in the string two
// The reason is that Word in the ATA / ATAPI is opposite to the byte sequence adopted by Windows.
// The data has been received in the driver, we have negative negative
Void AdjustString (Char * STR, INT LEN)
{
CHAR CH;
INT I;
// Two two times
For (i = 0; i { CH = STR [I]; STR [I] = STR [i 1]; STR [i 1] = CH; } // If it is right or right, adjust to left alignment (remove the left space) i = 0; While ((i :: Memmove (STR, & STR [I], LEN - I); / / Remove the space on the right I = LEN - 1; While ((i> = 0) && (STR [i] == ')))) { STR [I] = '/ 0'; I-; } } // Read the device information of the IDE hard drive, there must be sufficient permissions // NDRIVE: Drive letter (0 = first hard disk, 1 = 0 = second hard disk, ...) // pidinfo: Equipment information structure pointer Bool getPhysicalDriveInfoinNT (int NDRIVE, PIDINFO PIDINFO) { Handle HDevice; // Equipment handle BOOL BRESULT; / / Return Results Char szfilename [20]; // file name :: sprintf (szfilename, ".// PhysicalDrive% D", NDrive); HDevice = :: OpenDevice (SZFileName); IF (HDevice == Invalid_Handle_Value) { Return False; } // Identify Device BRESULT = :: IdentifyDevice (HDEvice, PIDINFO); IF (BRESULT) { // Adjust string :: AdjustString (PidInfo-> sSerialNumber, 20); :: AdjustString (PidInfo-> SmodelNumber, 40); :: AdjustString (PidInfo-> Sfirmwarerev, 8); } :: CloseHandle (HDevice); Return BRESULT; } // Drive the device information of the Ide hard disk with SCSI drive, not right to restrict // NDRIVE: Drive Number (0 = Primary Master, 1 = Promary Slave, 2 = Secondary Master, 3 = SECONDARY SLAVE) // pidinfo: Equipment information structure pointer Bool getidedriveasscsiinfoinnt (int NDRIVE, PIDINFO PIDINFO) { Handle HDevice; // Equipment handle BOOL BRESULT; / / Return Results Char szfilename [20]; // file name :: sprintf (szfilename, ".// SCSI% D:", ndrive / 2); HDevice = :: OpenDevice (SZFileName); IF (HDevice == Invalid_Handle_Value) { Return False; } // Identify Device BRESULT = :: IdentifyDeviceAsscsi (HDevice, NDrive% 2, PIDINFO); // Check is an empty string IF (pidinfo-> smodelnumber [0] == '/ 0') { BRESULT = FALSE; } IF (BRESULT) { // Adjust string :: AdjustString (PidInfo-> sSerialNumber, 20); :: AdjustString (PidInfo-> SmodelNumber, 40); :: AdjustString (PidInfo-> Sfirmwarerev, 8); } Return BRESULT; } Q I noticed in ATA / Atapi, and DISKID32, there is a "identify packet device" instruction, what is the difference with "Identify Device"? A Identify Device is designed to secure the hard disk, while Identify Packet Device is used for removable storage devices such as CDROM, CF, Mo, ZIP, TAPE, and the like. Because of the reasons of the driver, in this way, the Identify Device is also, Identify Packet Device, it is generally not possible to obtain detailed information for removable storage devices. Moreover, in addition to the IDE hard drive, hard drives such as SCSI, USB and other interfaces do not work. Unless the drive supports the drive supports such a function. Q ATA / ATAPI has many instructions, such as Read Sectors, Write Sectors, Security, Sleep, Standby, etc., can it be operated accordingly? A should have no problem. But remember, be careful and careful! Q About permission issues, please explain it? A Under NT / 2000 / XP, Administrator can manage the device, and the above two access drives are rows. But under the User identity, or after logging in to the domain, the user cannot access the PhysicalDrive driven core layer, but the SCSI Mini-Port driver can. Currently, I don't know if the version after Windows is supported. Because this is definitely a safe hidden danger. In addition, we focus on the application of DeviceIocontrol in NT / 2000 / XP. If you need to get more detailed information including the hard disk serial number in 98 / me, please refer to DISKID32. [related resources] Demo source code: IDEDiskinfo.zip (25kb) Lynn McGuire's Diskid32.zip (30KB) T13 official website: http://www.t13.org BHW98 column: http://www.9cbs.net/develop/author/ NetAuthor / BHW98 / First release: 2003-02-24 Last revision: 2003-05-20