Q:
Use ioctl_disk_get_drive_geometryioctl_storage_get_media_types_ex to obtain only a few disk parameters.
I want to obtain more detailed information, including the hard disk serial number. How can this problem be solved?
A:
Indeed, with the I/O control code you mentioned, you can only get the most basic disk parameters. Obtain the I/O control code for the disk factory information. Microsoft is not open in the VC/mfc environment, and some
Clues. Previously, Lynn McGuire wrote a well-known program named diskid32, which obtains detailed information about the IDE hard disk. The following example is based on the program added, deleted, and improved.
In this example, we need to use the ATA/apapi identify.
Device command. ATA/apapi is an IDE/Eide/udma hard disk and other removable storage devices and host interface standard drafted and released by t13.
ATA/APAPI-7 version. This API standard specifies ATA/atapi
The input/output registers and instruction sets of the device. For more detailed ATA/atapi technical information, visit the t13 site.
Constants and data structures used include the following:
//
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
Ctrochelle 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 command
# Define ide_ata_identify
0xec // id command of ATA (identify device)
// Ide command register
Typedef struct
_ Ideregs
{
Byte bfeaturesreg; // feature register (for smart commands) byte
Bsectorcounregulatory; // register the number of sectors
Byte bsectornumberreg; // start sector register
Byte bcyllowreg; // The Low-byte register of the Start cylindrical disk.
Byte bcylhighreg ;//
Start cylindrical high byte register
Byte bdriveheadreg; // driver/head register
Byte
Bcommandreg; // command register
Byte breserved; // Reserved
} Ideregs,
* Pideregs, * lpideregs;
// Status 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; // Number of buffer bytes
Ideregs irdriveregs; // ide register group
Byte bdrivenumber; // drive letter
Byte breserved [3]; // Reserved
DWORD dwreserved [4]; // Reserved
Byte
Bbuffer [1]; // input buffer (1 byte in symbolic form)
} Sendcmdinparams,
* Psendcmdinparams, * lpsendcmdinparams;
// Structure of IOCTL output data of the IDE Device
Typedef
Struct _ sendcmdoutparams
{
DWORD cbuffersize; // Number of buffer bytes
Driverstatus; // The status returned by the driver.
Byte bbuffer [1];
// Input buffer (1 byte symbolic here)
} Sendcmdoutparams, * psendcmdoutparams,
* Lpsendcmdoutparams;
// Data returned by the IDE id command
//
A total of 512 bytes (256 words), where only items of interest are defined (basically based on ATA/ATAPI-4)
Typedef struct
_ Idinfo
{
Ushort wgenconfig; // word 0: Basic Information word
Ushort
Wnumcyls; // word 1: Number of cylinders
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 sectors per track
Ushort wvendorunique [3]; // word 7-9: factory Value
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 verification size
Char sfirmwarerev [8]; // word
23-26: firmware version
Char smodelnumber [40]; // word 27-46: Internal Model
Ushort
Wmorevendorunique; // word 47: factory Value
Ushort wreserved48; // word
48: Reserved
Struct {
Ushort reserved1: 8;
Ushort DMA: 1 ;//
1 = Support for DMA
Ushort LBA: 1; // 1 = Support LBA
Ushort disiordy: 1 ;//
1 = do not use iordy
Ushort iordy: 1; // 1 = iordy supported
Ushort softreset: 1;
// 1 = ATA soft start required
Ushort overlap: 1; // 1 = Support for overlapping operations
Ushort
Queue: 1; // 1 = command queue supported
Ushort inldma: 1; // 1 = support for cross-access DMA
}
Wcapabilities; // word 49: general capability
Ushort wreserved1; // word 50:
Retained
Ushort wpiotiming; // word 51: Pio Time Series
Ushort wdmatiming;
// Word 52: DMA timing
Struct {
Ushort chsnumber: 1; // 1 = word
Valid from 54-58
Ushort cyclenumber: 1; // 1 = word 64-70 valid
Ushort
Unltradma: 1; // 1 = word 88 valid
Ushort Reserved: 13;
}
Wfieldvalidity; // word 53: indicates the validity of subsequent fields.
Ushort wnumcurcyls; // word
54: Number of CHS addressable Cylinders
Ushort wnumcurheads; // word 55: Number of splices addressable by CHS
Ushort
Wnumcursectorspertrack; // word 56: CHS addressable number of sectors per track
Ushort
Wcursectorslow; // word 57: number of segments that the CHS can address.
Ushort wcursectorshigh;
// Word 58: the number of segments that the CHS can address is high.
Struct {
Ushort curnumber: 8 ;//
Current number of read/write sectors at a time
Ushort multi: 1; // 1 = multiple read/write sectors selected
Ushort reserved1: 7;
}
Wmultsectorstuff; // word 59: multi-sector read/write settings
Ulong dwtotalsectors ;//
Word 60-61: Number of LBA addressable sectors
Ushort wsingleworddma; // word 62:
Single-byte DMA support capacity struct {
Ushort mode0: 1; // 1 = supported Mode 0 (4.17 Mb/s)
Ushort mode1: 1; // 1 = supported Mode 1 (13.3 Mb/s)
Ushort mode2: 1; // 1 = supported Mode 2
(16.7 Mb/s)
Ushort reserved1: 5;
Ushort mode0sel: 1 ;//
1 = selected mode 0
Ushort mode1sel: 1; // 1 = mode 1 Selected
Ushort
Mode2sel: 1; // 1 = selected mode 2
Ushort reserved2: 5;
} Wmultiworddma;
// Word 63: Multi-byte DMA support
Struct {
Ushort advpoimodes: 8 ;//
Number of advanced poi modes supported
Ushort Reserved: 8;
} Wpiocapacity; // word 64:
Advanced Pio support
Ushort wminmultiworddmacycle; // word 65: minimum value of the Multi-byte DMA transmission cycle
Ushort
Wrecmultiworddmacycle; // word 66: Recommended Value for multi-byte DMA transmission period
Ushort
Wminpionoflowcycle; // word 67: Minimum Pio transmission cycle when no traffic control is available
Ushort
Wminpoiflowcycle; // word 68: Minimum Pio transmission cycle when traffic control exists
Ushort
Wreserved69 [11]; // word 69-79: Reserved
Struct {
Ushort reserved1: 1;
Ushort ATA1: 1; // 1 = ATA-1 supported
Ushort ATA2: 1; // 1 = ATA-2 supported
Ushort ata3: 1; // 1 = ATA-3 supported
Ushort ata4: 1; // 1 = ATA/ATAPI-4 supported
Ushort ata5: 1; // 1 = ATA/ATAPI-5 supported
Ushort ata6: 1 ;//
1 = Support ATA/ATAPI-6
Ushort ata7: 1; // 1 = ATA/ATAPI-7 supported
Ushort
Ata8: 1; // 1 = ATA/ATAPI-8 supported
Ushort ata9: 1; // 1 = ATA/ATAPI-9 supported
Ushort ata10: 1; // 1 = ATA/ATAPI-10 supported
Ushort ata11: 1 ;//
1 = Support ATA/ATAPI-11
Ushort ata12: 1; // 1 = ATA/ATAPI-12 supported
Ushort
Ata13: 1; // 1 = ATA/ATAPI-13 supported
Ushort ata14: 1; // 1 = ATA/ATAPI-14 supported
Ushort reserved2: 1;
} Wmajorversion; // word 80: Master version
Ushort
Wminorversion; // word 81: Sub-version
Ushort wreserved82 [6]; // word
82-87: Reserved
Struct {
Ushort mode0: 1; // 1 = supported Mode 0 (16.7 Mb/s)
Ushort mode1: 1; // 1 = supported Mode 1 (25 Mb/s)
Ushort mode2: 1; // 1 = supported Mode 2
(33 Mb/s)
Ushort mode3: 1; // 1 = supported Mode 3 (44 Mb/s) ushort mode4: 1 ;//
1 = supported Mode 4 (66 Mb/s)
Ushort mode5: 1; // 1 = mode 5 (100 Mb/s)
Ushort
Mode6: 1; // 1 = supported mode 6 (133 Mb/s)
Ushort mode7: 1; // 1 = supported mode 7
(166 Mb/s )???
Ushort mode0sel: 1; // 1 = selected mode 0
Ushort
Mode1sel: 1; // 1 = mode 1 Selected
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 = mode 6 Selected
Ushort mode7sel: 1; // 1 = mode selected 7
} Wultradma; // word 88: Ultra
DMA support
Ushort wreserved89[ 167]; // word 89-255
} Idinfo,
* Pidinfo;
// Input/output shared structure required by the SCSI driver
Typedef struct _ srb_io_control
{
Ulong headerlength; // Header Length
Uchar signature [8]; // feature name
Ulong
Timeout; // timeout
Ulong controlcode; // control code
Ulong
Returncode; // return code
Ulong length; // The buffer length.
} Srb_io_control,
* Psrb_io_control;
Note that idinfo 57th-58 word (number of chs' addressable sectors) cannot be defined as a ulong field because it does not meet 32-bit alignment requirements.
Lynn McGuire is defined as a ulong field, which makes the structure unavailable.
The following is the core code:
//
Enable the device
// Filename: "file name" of the device"
Handle opendevice (lpctstr filename)
{
Handle
Hdevice;
// Open the device
Hdevice =: createfile (filename, // file name
Generic_read | generic_write, // read/write Method
File_pai_read |
File_pai_write, // Sharing Method
Null, // Default Security Descriptor
Open_existing ,//
Creation Method 0, // file attributes do not need to be set
Null); // you do not need to refer to the template file.
Return hdevice;
}
//
Send the "identify device" command to the driver to obtain the device information.
// Hdevice: Device handle
//
Pidinfo: device information structure pointer
Bool identifydevice (handle hdevice, pidinfo
Pidinfo)
{
Psendcmdinparams pscip; // input data structure pointer
Psendcmdoutparams
Pscop; // output data structure pointer
DWORD dwoutbytes; // IOCTL Output Data Length
Bool
Bresult; // return value of IOCTL
// Apply for input/output data structure 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. bsectorcounreg = 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 buffer size of input/output data
Pscip-> cbuffersize = 0;
Pscop-> cbuffersize
= Sizeof (idinfo );
// Identify Device
Bresult =
: Deviceiocontrol (hdevice, // device handle
Dfp_receive_drive_data ,//
Specify IOCTL
Pscip, sizeof (sendcmdinparams)-1, // input data buffer
Pscop,
Sizeof (sendcmdoutparams) + sizeof (idinfo)-1, // output data buffer
& Dwoutbytes, // Output Data Length
(Lpoverlapped) null); // use synchronous I/O
//
Copy device parameter structure
: Memcpy (pidinfo, pscop-> bbuffer, sizeof (idinfo ));//
Release input/output data space
: Globalfree (pscop );
: Globalfree (pscip );
Return
Bresult;
}
// Send the "identify device" command to the SCSI mini-port driver to obtain the device information.
//
Hdevice: Device handle
// Pidinfo: device information structure pointer
Bool
Identifydeviceasscsi (handle hdevice, int ndrive, pidinfo)
{
Psendcmdinparams
Pscip; // input 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; // return value of IOCTL
// Apply for input/output data structure 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 ));
//
Fill in 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. bsectorcounreg = 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, // device handle
Ioctl_scsi_miniport, // specify IOCTL
Psrbio, sizeof (srb_io_control)
+ Sizeof (sendcmdinparams)-1, // input data buffer psrbio, sizeof (srb_io_control)
+ Sizeof (sendcmdoutparams) + sizeof (idinfo)-1, // output
Data Buffer Zone
& Dwoutbytes, // Output Data Length
(Lpoverlapped) null); // use synchronous I/O
//
Copy device parameter structure
: Memcpy (pidinfo, pscop-> bbuffer, sizeof (idinfo ));
//
Release input/output data space
: Globalfree (psrbio );
Return bresult;
}
//
Invert the characters in the string
// The reason is that the word in ATA/atapi is in the opposite byte order in windows.
//
In the driver, all the received data has been reversed. Let's make a negative profit.
Void adjuststring (char * STR, int Len)
{
Char
Ch;
Int I;
// Reversing
For (I = 0; I <Len; I + = 2)
{
Ch =
STR [I];
STR [I] = STR [I + 1];
STR [I + 1] = CH;
}
//
If it is right-aligned, adjust it to left-aligned (remove spaces on the left)
I = 0;
While (I <Len & STR [I] ='
') I ++;
: Memmove (STR, & STR [I], len-I );
// Remove the right space
I = len-
1;
While (I> = 0 & STR [I] = '')
{
STR [I] = '';
I --;
}
} // Read the device information of the IDE hard disk. You must have sufficient permissions.
// Ndrive:
Drive letter (0 = first hard disk, 1 = 0 = second hard disk ,......)
// Pidinfo: device information structure pointer
Bool
Getphysicaldriveinfoinnt (INT ndrive, pidinfo)
{
Handle
Hdevice; // device 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 the string
: Adjuststring (pidinfo-> sserialnumber, 20 );
: Adjuststring (pidinfo-> smodelnumber, 40 );
: Adjuststring (pidinfo-> sfirmwarerev, 8 );
}
: Closehandle
(Hdevice );
Return bresult;
}
// Use the SCSI driver to read the device information of the IDE hard disk, without permission Control
//
Ndrive: drive letter (0 = primary master, 1 = promary slave, 2 = secondary master,
3 = secondary slave)
// Pidinfo: device information structure pointer
Bool
Getidedriveasscsiinfoinnt (INT ndrive, pidinfo)
{
Handle
Hdevice; // device 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 whether the string is empty
If (pidinfo-> smodelnumber [0] = '')
{
Bresult = false;
}
If (bresult)
{
// Adjust the string
: Adjuststring (pidinfo-> sserialnumber, 20 );
: Adjuststring (pidinfo-> smodelnumber, 40 );
: Adjuststring (pidinfo-> sfirmwarerev, 8 );
}
Return bresult;
}
Q: I noticed that in ATA/atapi and diskid32, there is a "identify packet"
What is the difference between the device command and the identifydevice command?
A:
Identify
Device is used for Fixed hard disks, while identify packet device is used for removable storage devices such as CDROM, CF, Mo, zip,
Tape. Because of the driver, we actually use the method in this example, whether it is identify device or identify packet.
It is generally impossible to obtain detailed information about a removable storage device. In addition to the IDE hard disk, it does not work for hard disks with SCSI, USB, and other interfaces. Unless the driver provided by the vendor
This function is supported.
Q: ATA/atapi has many commands, such as read sectors, write sectors,
Security, sleep, standby, and so on. Can operations be performed using the above methods?
A:
It should be okay. But remember, be careful and proceed with caution!
Q: Can I explain the permission issues?
A:
In NT/2000/XP, the administrator can manage devices. The above two methods can be used to access the driver. However, if you are a user or have logged on to the domain, you cannot access
Physicaldrive driver core layer, but SCSI mini-Port
Driver. Currently, yes. I do not know if windows and later versions are supported. This is definitely a security risk.
In addition, we will focus on NT/2000
For the deviceiocontrol application in/XP, if you need to obtain more detailed information including the hard disk serial number in 98/Me, refer to diskid32.