Four of actual DeviceIocontrol: Get a hard drive details

zhaozj2021-02-16  55

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

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

New Post(0)