#include
#include
#pragma inline
/ / -------------------------------------------------------------------------------------------- ---------------------------
// IDE NT / 2000 / XP special variable
#define getversionoutparams getVersioninparams
#define DFP_GET_VERSION SMART_GET_VERSION
#define DFP_SEND_DRIVE_COMMAND Smart_send_drive_command
#DEFINE DFP_RCV_DRIVE_DATA Smart_rcv_drive_data
Const Word IDE_ATAPI_IDENTIFY = 0xA1; // Read the command of the ATAPI device
Const Word IDE_ATA_IDENTIFY = 0xec; // Read ATA Device Command
Const int max_IDE_Drives = 4;
// SCSI special variable
Const dword file_device_scsi = 0x0000001B;
Const DWORD ioctl_scsi_miniport_identify = ((file_device_scsi << 16) 0x0501);
Const dword ioctl_scsi_miniport = 0x0004d008; // See ntddscsi.h for definition
Const dword sendidens = sizeof (sendcmdoutparams) Identify_buffer_size;
Typedef struct _srb_io_control
{
Ulong headerlength;
Uchar Signature [8];
Ulong timeout;
Ulong controlcode;
Ulong Returncode;
Ulong Length;
} SRB_IO_CONTROL, * PSRB_IO_CONTROL;
// Read the main function
Void __fastcall readphysicaldrive (tstrings * pserlist, tstrings * pmodelist);
// Auxiliary function
Char * __ fastcall convertostnow (dword dwdiskdata [256], int nfirstindex, int nlastindex);
// NT / 2000 / XP function
Void __fastcall readphysicalDriveonNT (Tstrings * pserlist, tstrings * pmodelist);
Bool __fastcall doidentify (Handle HphysicalDriveioctl, Psendcmdinparams PSCIP,
Psendcmdoutparams Pscop, Byte Btidcmd,
Byte Btdrivenum, PDWORD LPCBBYTESRETURNED;
// windows 9x function
Void __fastcall readphysicaldriveonw9x (tstrings * pserlist, tstrings * pmodelist);
Void __fastcall readphysicalDriveonw9x_ring0 (Bool IsFirst, Word Baseaddress,
Byte Mos, Bool & IsideExist, Bool & Isdiskexist, Word * Outdata; // SCSI Reading Function (for NT / 2000 / XP)
String __fastcall readidedriveasscsidriveonnt ();
/ / -------------------------------------------------------------------------------------------- ---------------------------
// readphysicalDrive
Void __fastcall readphysicaldrive (tstrings * pserlist, tstrings * pmodelist)
{
Switch (Win32Platform)
{
Case Ver_Platform_Win32_Windows:
ReadphysicalDriveonW9X (Pserlist, Pmodelist);
Break;
Case Ver_Platform_WIN32_NT:
ReadphysicalDriveonNT (Pserlist, Pmodelist);
Break;
DEFAULT:
Break;
}
}
/ / -------------------------------------------------------------------------------------------- ---------------------------
// ConvertToString
Char * __ fastcall convertostring (DWord DwdiskData [256], INT NFIRSDEX, INT NLASTINDEX)
{
Static Char Szresbuf [1024];
INT NINDEX = 0;
INT nPosition = 0;
// Each Integer Has Two Characters Stored In It Backwards
For (nindex = nfirstindex; nindex <= nlastindex; NINDEX )
{
// Get High byte for 1st Character
Szresbuf [nposition] = (char) (DWDiskData [NINDEX] / 256);
NPOSITION ;
// Get Low byte for 2nd Character
SzResbuf [nposition] = (char) (DWDiskData [NINDEX]% 256);
NPOSITION ;
}
// end the string
SzResbuf [nposition] = '/ 0';
// Cut Off The Trailing Blanks
For (Nindex = nPosition - 1; NINDEX> 0 && '' == SzResbuf [NINDEX]; NINDEX -)
SzResbuf [NINDEX] = '/ 0';
Return SzResbuf;
}
/ / -------------------------------------------------------------------------------------------- ---------------------------
// WinNDOWS NT4 / 2000 / XP code
/ / -------------------------------------------------------------------------------------------- ---------------------------
// readphysicalDriveonNT
Void __fastcall readphysicalDriveonNT (Tstrings * pserlist, tstrings * pmodelist)
{
// Output parameters
BYTE BTIDOUTCMD [SIZEOF (Sendcmdoutparams) Identify_buffer_size - 1];
For (int NDRIVE = 0; ndrive { Handle HphysicalDriveiocTl; Char szdrivename [32]; Sprintf (szdrivename, ".//physicaldrive%D", ndrive); HphysicalDriveiocTl = CREATEFILE (SzdriveName, Generic_read | generic_write, File_share_read | file_share_write, null, Open_EXISTING, 0, NULL IF (hphysicaldriveioctl! = invalid_handle_value) { DWORD DWBYTESRETURNED = 0; GetversionOutparams gvopVersionparams; // Get The Version, ETC of PhysicalDrive ioctl ZeromeMory (& gvopVersionParams, Sizeof (GetVersionOutparams); IF (! DeviceioControl (HphysicalDriveiOctl, DFP_GET_VERSION, NULL, 0, & GVOPVERSIONPARAMS, SIZEOF (GVOPVersionParams), & dwbytesreturned, NULL)) { CONTINUE; } IF (gvopVersionparams.bidedEDeviceMap> 0) { // IDE or atapi identify cmd BYTE BTIDCMD = 0; Sendcmdinparams INPARAMS; // now, get the id sector for all my devices in the system. // if the device is atapi us ie_atapi_identify command, // OtherWise Use the IDE_ATA_IDENTIFY COMMAND / / Please refer to the description of the header file for the result of the specific result. BTIDCMD = (gvopVersionParams.BidedEDeviceMap >> NDrive & 0x10)? IDE_ATAPI_IDENTIFY: IDE_ATA_IDENTIFY; ZeromeMory (& INPARAMS, SIZEOF (Sendcmdinparams); ZeromeMory (BTIDOUTCMD, SIZEOF (BTIDOUTCMD)); IF (HphysicalDriveiocTl, & INPARAMS, (psendcmdoutparams) BTIDOUTCMD, (Byte) BTIDCMD, (Byte) NDrive, & DWBYTESRETURNED)) { DWORD DWDiskData [256]; Ushort * pidsector; // correspondence structure idsector, see head file Char szserialnumber [21]; Char szmodelnumber [41]; Pidsector = (usHort *) (Sendcmdoutparams *) btidoutcmd) -> bbuffer; For (int i = 0; i <256; i ) DWDiskData [i] = pidsector [i]; // Take a series ZeromeMory (SizserialNumber, Sizeof (SZSerialNumber); STRCPY (SZSerialnumber, ConvertToString (DWDiskData, 10, 19); // Timing model ZeromeMory (Szmodelnumber, Sizeof (Szmodelnumber); STRCPY (Szmodelnumber, ConvertToString (DWDiskData, 27, 46)); PSerlist-> Add (SZSerialnumber); Pmodelist-> add (szmodelnumber); } } CloseHandle (HPHYSICALDRIVEIOCTL); } } } / / -------------------------------------------------------------------------------------------- --------------------------- // doidentify Bool __fastcall doidentify (Handle HphysicalDriveioctl, Psendcmdinparams PSCIP, Psendcmdoutparams Pscop, Byte Btidcmd, Byte Btdrivenum, PDWORD PDWBYTESRETURNED) { // SET UP DATA STRUCTURES for Identify Command. PSCIP-> CBuffersize = Identify_buffer_size; Pscip-> IrDriveRegs.BfeaturesReg = 0; Pscip-> IrDriveRegs.bsectorcountreg = 1; Pscip-> IrDriveRegs.bsectorNumberReg = 1; Pscip-> IrDriveRegs.bcyllowreg = 0; Pscip-> IrDriveRegs.bcylhighReg = 0; // compute the drive number. (The value corresponding to the main disc and slave "is not the same) Pscip-> irdriveRegs.bdriveheadreg = (BTDrivenum & 1)? 0xB0: 0xA0; // The Command CAN Either Be Ide Identify or atapi Identify. Pscip-> IrDriveRegs.bcommandreg = btidcmd; Pscip-> bdrivenumber = btdrivenu; PSCIP-> CBuffersize = Identify_buffer_size; Return DeviceioControl (HphysicalDriveiocTl, DFP_RCV_DRIVE_DATA, (LPVOID) PSCIP, Sizeof (Sendcmdinparams) - 1, (LPVOID) PSCOP, Sizeof (Sendcmdoutparams) Identify_buffer_size - 1, PDWBYTESRETURNED, NULL); } / / -------------------------------------------------------------------------------------------- --------------------------- // Windows 95/98 / ME code / / -------------------------------------------------------------------------------------------- --------------------------- // readphysicalDriveonw9xvoid __fastcall readphysicalDriveonw9x (tstrings * pserlist, tstrings * pmodelist) { Word woutdata [256]; SetPriorityClass (GetCurrentProcess (), realtime_priority_class; // After testing, it is found that the first call and DRIVE> = 2 will occur in the RING0 code, resulting in a blue screen. // After the N (n> 15), it still can't find the reason after the blue screen: (, there is no additional useless code here. // Avoid the appearance of the blue screen. (I look forward to a high person to point out the reason) For (int NDRIVE = 0; NDRIVE <8; NDRIVE ) { Word dwbaseaddress; Byte btmasterslave; // master or slave Bool bisideexist; Bool isdiskexist; Switch (ndrive / 2) { Case 0: dwbaseaddress = 0x01f0; Break; Case 1: dwbaseaddress = 0x0170; Break; Case 2: dwbaseaddress = 0x01e8; Break; Case 3: DWBaseAddress = 0x0168; Break; } BTMASTERSLAVE = (Byte) ((nDrive% 2) == 0)? 0xA0: 0xB0); // Enter RING0 ReadphysicalDriveonW9x_ring0 (True, Dwbaseaddress, Btmasterslave, Bisideexist, ISDISKEXIST, WOUTDATA } // Start reading For (int NDRIVE = 0; NDRIVE <8; NDRIVE ) { Word dwbaseaddress; Byte btmasterslave; // master or slave Bool bisideexist; Bool bisdiskexist; Switch (ndrive / 2) { Case 0: dwbaseaddress = 0x01f0; Break; Case 1: dwbaseaddress = 0x0170; Break; Case 2: dwbaseaddress = 0x01e8; Break; Case 3: DWBaseAddress = 0x0168; Break; } BTMASTERSLAVE = (Byte) ((nDrive% 2) == 0)? 0xA0: 0xB0); // Enter RING0 Bisideexist = FALSE; Bisdiskexist = false; ZeromeMory (Woutdata); ReadphysicalDriveonW9x_ring0 (False, Dwbaseaddress, BtmasterSlave, Bisideexist, Bisdiskexist, Woutdata; IF (bisideexist && bisdiskexist) { DWORD DWDiskData [256]; Char szserialnumber [21]; Char szmodelnumber [41]; For (int K = 0; k <256; k ) dwdiskdata [k] = woutdata [k]; // Take a series ZeromeMory (SizserialNumber, Sizeof (SZSerialNumber); STRCPY (SZSerialnumber, ConvertToString (DWDiskData, 10, 19); // Timing model ZeromeMory (Szmodelnumber, Sizeof (Szmodelnumber); STRCPY (Szmodelnumber, ConvertToString (DWDiskData, 27, 46)); PSerlist-> Add (SZSerialnumber); Pmodelist-> add (szmodelnumber); } } SetPriorityClass (GetCurrentProcess (), Normal_Priority_Class; } / / -------------------------------------------------------------------------------------------- --------------------------- // readphysicalDriveonw9x_ring0 () // // dwbaseaddress = IDE (0, 1, 2, 3): 1F0H, 170H, 1E8H, 168H // btmasterslave = master (0xA0) OR slave (0xB0) / / -------------------------------------------------------------------------------------------- --------------------------- Void __fastcall readphysicalDriveonw9x_ring0 (Bool Bisfirst, Word Dwbaseaddress, BYTE BTMASTERSLAVE, BOOL & Bisideexist, Bool & Bisdiskexist, Word * Poutdata) { Byte btidtr1 [6]; DWORD DWOLDEXCEPTIONHOK; Const int nhookedXceptionNO = 5; Byte btisideexist = 0; BYTE BTISDISKEXIST = 0; Word woutdatabuf [256]; Byte btisfirst = (byte) bisfirst; Const byte btbit00 = 0x01; // const byte btbit02 = 0x04; Const byte btbit06 = 0x40; Const byte btbit07 = 0x80; // const byte bterr = btbit00; Const byte btbusy = btbit07; Const byte btatacmd = 0xec; Const byte btatapicmd = 0xa1; __ASM { // must implement this statement first JMP Enterring0 // Define the process // Waiting for the IDE device until it is not busy Waitwhilebusy Proc MOV EBX, 100000 MOV DX, DWBaseAddress Add dx, 7 LoopWhilebusy: Dec EBX CMP EBX, 0 JZ Timeout IN Al, DX Test Al, BTBUSY Jnz loopwhilebusy JMP DriveReady // Timeout, directly exit TIMEOUT: JMP Leavering0 DriveReady: RET Endp // end of waitwhilebusy procedure // Set the primary disc and slave SelectDevice Proc MOV DX, DWBaseAddress Add dx, 6 Mov Al, BtMasterslave Out dx, al RET Endp // end of selectdevice procedure / / Send an access command to the IDE device Sendcmd Proc MOV DX, DWBaseAddress Add dx, 7 MOV Al, BL // BL is the main slave dish identifier, outside the process Out dx, al RET Endp // end of sendcmd procedure // Ring0 code Ring0Proc: Pushhad // Query if the IDE device exists MOV DX, DWBaseAddress Add dx, 7 IN Al, DX // When the value of Al is 0xff or 0x7f, the IDE device does not exist, and then it is directly returned. CMP Al, 0xFF JZ Leavering0 CMP Al, 0x7f JZ Leavering0 / / Set an IDE device exists Mov btisideexist, 1 / / Query if the drive on the IDE device exists (with the IDE slot on the motherboard, but not necessarily a hard disk inserted above) Call Waitwhilebusy Call SelectDevice // If it is called, then it is returned directly, otherwise it will appear blue screen when performing a downlist. CMP BTISFIRST, 1 JZ Leavering0 // When calling, if you do this, you can cause Blue Screen, why? ? ? Call Waitwhilebusy // Al is equal to CBIT06, there is no drive, directly return Test al, btbit06 JZ Leavering0 / / Set the drive existence flag Mov btisdiskexist, 1 // Send an access port command // Cannot be like NT / 2000 / XP can be used to get the value of the Version to get the type of drive, // So I can only test one step by step. If it is not an ATA device, try using the ATAPI device command. Call Waitwhilebusy Call selectDevice // Set the primary slam sign MOV BL, BTATACMD / / Send Read Command Call sendcmd Call Waitwhilebusy / / Check if an error MOV DX, DWBaseAddress Add dx, 7 IN Al, DX Test al, btbit00 JZ RETRIEVEINFO / / read data when there is no error // If an error, further try to use the ATAPI device command Call Waitwhilebusy Call SelectDevice MOV BL, BTATAPICMD Call sendcmd Call Waitwhilebusy / / Check if it is still wrong MOV DX, DWBaseAddress Add dx, 7 IN Al, DX Test al, btbit00 JZ RETRIEVEINFO / / read data when there is no error JMP Leavering0 // If it is still an error, return directly // read data RetrieveInfo: Lea Edi, WoutdataBuf Mov ECX, 256 MOV DX, DWBaseAddress CLD Rep Insw // Exit Ring0 code Leavering0: PopadiRetd // activate Ring0 code ENTERRING0: / / Modify the interrupt gate SIDT FWORD PTR BTIDTR1 MOV EAX, DWORD PTR BTIDTR1 02H Add Eax, NHOOKEXCENO * 08H 04H CLI / / Preserve the original exception handling routine entry MOV ECX, DWORD PTR [EAX] MOV CX, Word PTR [EAX-04H] Mov DwoldExceptionHook, ECX / / Specify new entry Lea EBX, RING0PROC MOV Word PTR [EAX-04H], BX SHR EBX, 10H MOV Word PTR [EAX 02H], BX // activate Ring0 code Int nhokexceptionno // Restore the entrance MOV ECX, DwoldExceptionHOK Mov Word PTR [EAX-04H], CX SHR ECX, 10H MOV Word PTR [EAX 02H], CX STI } IF (! bisfirst) { Bisideexist = (BOOL) btisideexist; BiSDISKEXIST = (BOOL) btisdiskexist; CopyMemory (poutdata, woutdatabuf, sizeof (woutdatabuf); } } / / -------------------------------------------------------------------------------------------- --------------------------- // Call method: Void __fastcall tform1 :: button1click (Tobject * Sender) { ReadphysicalDrive (Memo1-> Lines, Memo2-> lines); }