|
|
#include <WinIOCtl.h>
3 M5 x' V2 s3 J6 d1 T9 B" K#include <stdio.h>) q3 t2 g5 X. a8 [4 Y& w! h& [
- D7 N8 u# ?& ^1 ~, X/ h0 o8 s#pragma inline% B) P! d" z6 i- B
//---------------------------------------------------------------------------
, }7 E# _( e5 {( n' S// IDE NT/2000/XP专用变量3 w2 }, r3 A! f: `5 \
#define GETVERSIONOUTPARAMS GETVERSIONINPARAMS
0 g5 t3 i. a3 i* M' S! M% I#define DFP_GET_VERSION SMART_GET_VERSION1 Q F& s7 ^: r. o/ X0 X) u
#define DFP_SEND_DRIVE_COMMAND SMART_SEND_DRIVE_COMMAND, ^" G7 o) [ w
#define DFP_RCV_DRIVE_DATA SMART_RCV_DRIVE_DATA& C8 g; d$ |3 v9 U: d1 m0 e
& w. T1 t9 E7 c2 z/ U0 zconst WORD IDE_ATAPI_IDENTIFY = 0xA1; // 读取ATAPI设备的命令
1 f! ]6 k5 b* G/ I# _$ L4 H0 }const WORD IDE_ATA_IDENTIFY = 0xEC; // 读取ATA设备的命令 X) R. _) y. K2 S( r/ B0 I& |
1 F' N: K! _0 o6 c2 U7 i* ^
const int MAX_IDE_DRIVES = 4;/ y g3 V) L; Y3 }% m
2 C0 i) O. U/ B+ p; p7 ` k7 u$ A
// SCSI专用变量
8 W0 M% m- Z y3 O9 h5 v/ Vconst DWORD FILE_DEVICE_SCSI = 0x0000001B;$ L7 g6 N+ m. L/ D, `7 d
const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
! |, g `& |5 J! gconst DWORD IOCTL_SCSI_MINIPORT = 0x0004D008; // see NTDDSCSI.H for definition% h* T' ?* M# C, i" \
const DWORD SENDIDLENGTH = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;6 o' F, r) y6 Z/ y% {1 d: T
2 q1 T9 `0 y' i# w2 e# }typedef struct _SRB_IO_CONTROL' ]& [1 S8 s0 m; B n# T
{
; i4 r- \( e& M7 C ULONG HeaderLength;
+ K. Z4 F( W% y. _: [" w: t. A UCHAR Signature[8];# d3 z7 i" a8 [7 B" L
ULONG Timeout;0 V/ Y& |4 Q* R I, \; Z! Y
ULONG ControlCode;
- L ^0 p; ?0 p0 a ULONG ReturnCode;
$ n, d. f0 l' ]1 z; W9 k/ k ULONG Length;. N' n# Q; P9 a- ]$ }3 V8 Q+ a3 ]- ?
}SRB_IO_CONTROL, *PSRB_IO_CONTROL;0 d* D+ d3 g) }3 o) r1 p
4 L0 _4 l( `$ g/ X% T6 {3 V// 读取的主函数
3 ^" U) k8 ^6 F1 Fvoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
' f9 R H: H- ]! w4 K! i: Z/ m
3 }: s, B |1 i/ ]0 E; A- J// 辅助函数
% Q2 r; C& w' c1 H" V: Ichar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
7 ]$ A3 o( j- {9 Y2 F6 q// NT/2000/XP函数
: l" b) T P; h2 O% Y$ Mvoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);0 V1 \1 E' n, Q" N4 |2 V2 G+ L
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
* B; t$ Y. K4 k* }! l PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,3 ~4 M" n2 P! _4 y& u
BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
# r! U( A( j8 A// Windows 9X函数
8 l3 p3 F* Y y% c) avoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);( Z4 t8 {! o; b: v
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
2 T% y2 \$ K2 U N. }* ]3 k6 y BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);' z9 J9 v E* e7 Z$ j
8 i$ z* c2 l8 A
// SCSI读取函数(for NT/2000/XP)
6 x+ j3 X) G4 ^% T- C8 [String __fastcall ReadIDEDriveAsScsiDriveOnNT();
. K, G, a2 X3 o, B$ D//---------------------------------------------------------------------------: N( G, X- J' h# T
// ReadPhysicalDrive
0 Y+ f, j1 c- ]9 S& [: N2 W5 Y( ivoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
5 \1 M% t; M! n. S' m! m1 [( |7 k{* {9 r+ \, p2 N: ^! V6 j i3 v- Z
switch(Win32Platform)
% W8 b6 T$ _; O: J {
{; }1 D& F E, x0 S6 l" q* m case VER_PLATFORM_WIN32_WINDOWS:: W7 O9 O! x7 I4 i8 X2 y
ReadPhysicalDriveOnW9X(pSerList, pModeList);) p0 [2 o. X! Z% J' e6 L$ G
break;
4 R& N7 i( Q e& S' {$ ]' D case VER_PLATFORM_WIN32_NT:' X+ P8 Z+ A, o8 [
ReadPhysicalDriveOnNT(pSerList, pModeList);2 t* e- Y7 b1 H( R; @% g
break;
0 I( |4 m* ^7 Z# a7 j/ [ default:
3 I, Y9 |. e# f4 ?8 W$ { break;
3 z( g4 }) J! D4 b7 B! q }
v( ^2 y/ h+ K4 D2 J}
4 x) y: N# A4 Z: E1 v% O5 R//---------------------------------------------------------------------------, ]4 m- p6 X" I
// ConvertToString0 ?" P F) E: c3 J4 {! q& W
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
' g0 m8 x% T% J; C8 C" I; n{
j2 y! O& b8 H" q, O& Y static char szResBuf[1024];7 N( B" {$ l4 U* l, V6 R' t
int nIndex = 0;2 n: D( g% z5 d& ~, J; d6 G
int nPosition = 0;
3 W* a2 E6 N9 S& g x2 k0 M! K
0 L7 ]" ~7 X9 T) V" r) X // Each integer has two characters stored in it backwards
3 S. |$ r3 f- Y2 w' L$ p for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
) a, g/ x8 q% b, [0 d* D& r; |3 V {
j" L4 r* V1 J+ x" v3 R // Get high BYTE for 1st character
% F5 {$ X: r- s, ~- k0 y szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);* u1 o9 H! t9 B+ v& u: t4 R
nPosition++;
/ {% |. i) M+ {3 v" r; T6 G, ]/ n3 M7 ^/ e" i
// Get low BYTE for 2nd character" f) V; H/ m" P& U2 p: p! h
szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
' g2 V6 O. r+ [0 B- T nPosition++;
. y5 j, b) @3 ]' l7 h }
% C2 `2 _8 V6 g6 m) c+ [7 z
2 {6 x- I: D# m/ [6 v6 } // End the string
' w0 I. S* f1 q% h. |( i szResBuf[nPosition] = '\0';+ M3 D4 y+ F4 _0 g
6 E0 P1 D& @$ @0 l: }2 T // Cut off the trailing blanks( H" O- Y) N% B) n1 S
for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
, y6 ~5 a! |5 v; a+ L' m szResBuf[nIndex] = '\0';2 V% T' @! c- y* ?
3 e2 _- G# V9 d- V return szResBuf;6 H& S- {* o1 L, {. s% z1 Z
}6 j: C' Y% L6 w7 J6 N
//---------------------------------------------------------------------------
+ s5 W; d) |: Q/ u. p// Winndows NT4/2000/XP 代码& f& D8 T: s. s$ M! |' j4 w! }2 p, |
//---------------------------------------------------------------------------
* p4 ?4 R6 j$ |// ReadPhysicalDriveOnNT0 v4 M9 x+ K0 q6 ]9 s9 n4 s w
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
4 k l1 j M/ ~* C{6 @- _9 a$ Z4 S5 _- u
// 输出参数* m- z& ?: }5 @3 _
BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
% |2 k% z9 v& K- M: t/ M, c+ G# ]5 N" M6 w9 z+ T
for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++) E" [5 b$ l4 s$ C
{" L' @* R" Q+ u# ^# M" }0 X* X
HANDLE hPhysicalDriveIOCTL;
5 t6 M/ `) D2 ^4 i char szDriveName[32];, ^- z- y% ]2 Q+ } o5 }" Q
& r/ s+ M w/ M, h
sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);0 K g& K6 ^5 l( I( Q
hPhysicalDriveIOCTL = CreateFile(szDriveName,
& {; |6 F9 K' B5 _/ y# l& P/ ] GENERIC_READ | GENERIC_WRITE,
) z2 f( G3 b: _) c FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
) p7 E j3 N1 {/ P8 D+ Q OPEN_EXISTING, 0, NULL);1 H" M, `( P0 U( s
3 d0 H$ U7 q5 ^# z3 O+ x if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
# u/ D* \/ ?- |0 d( P8 s0 j5 \ {. T7 o5 ^3 j' U
DWORD dwBytesReturned = 0;* W$ p1 l9 `$ R0 h
GETVERSIONOUTPARAMS gvopVersionParams;
7 n! i* R4 ?2 j& |' t" e6 g% z
3 r- E8 ]: R8 v2 \2 W9 k% M // Get the version, etc of PhysicalDrive IOCTL9 ^2 o5 _' }( E# J0 {7 s1 l
ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));6 u7 f( C. {( T8 y( f1 W
7 v' _3 r2 @, K- w
if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,! p" G B6 Y8 F& u# x( Z3 F+ }
NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
5 W- r* g$ B: t* o2 K' w& m &dwBytesReturned, NULL))% Q& N! {+ S3 E3 p' w2 b4 }9 u
{
/ U4 I6 s0 _7 b continue;+ n% q" Q. A: j* L9 ]
}& z# c4 f- i$ S: _7 a$ q9 j/ J
2 O$ h2 _; q( _" J if(gvopVersionParams.bIDEDeviceMap > 0)
# k! L* P, J: _6 ^" w: Q S0 ^ {5 H; s$ i9 n! ?4 S x
// IDE or ATAPI IDENTIFY cmd8 T; c4 U b7 f8 c3 D5 D4 i1 k
BYTE btIDCmd = 0;
+ O$ g4 a5 k } F ] SENDCMDINPARAMS InParams;1 m& D( [- V6 x: b! M
// Now, get the ID sector for all IDE devices in the system.
. r" n9 r( Q. w: c9 }. F // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
7 D4 |# \6 B5 P3 i! s0 {1 K& j // otherwise use the IDE_ATA_IDENTIFY command
- {+ X7 t/ O! `2 [( i // 具体所得结果请参考头文件中的说明
& o- {% Y- F! D, b; B9 U btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
# \9 b' L- O4 E+ M- h" s) D) Z ^" ^ IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
: e/ _: D& K# a% {* |# r/ ` ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));3 p6 T r+ |) X
ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));; p# K% X5 `& g7 O- F
+ M6 [% z4 `! S4 I
if(DoIdentify(hPhysicalDriveIOCTL,
; ]! I8 A( m/ N0 d' _ &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,) p) D3 t- [8 r% q) a
(BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))0 x: B5 v. ~" ~/ y! Y
{
* n W+ l# r& U+ Y8 N0 f: } DWORD dwDiskData[256];
# J% O) {% G- L# [ USHORT *pIDSector; // 对应结构IDSECTOR,见头文件8 M. P' s2 t9 v( T" B, g
char szSerialNumber[21];* D$ T8 K# O- `; ~+ a" t
char szModelNumber[41];
% G9 G% A! a- i7 n4 U% j
9 L( L, n% O9 j! P7 X2 C pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;: c7 |; Z: v9 g6 Z" y2 _# |
for(int i=0; i < 256; i++)) u$ r. {4 m9 c
dwDiskData = pIDSector;
" n1 w) r, M; o, [ // 取系列号
9 O1 A# }+ s9 S# d# B0 j7 G. @2 y ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
3 q7 r$ y: C3 F: S strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));# F$ k5 r, I6 `, z5 R
. T$ t% P+ N4 a% Z& S3 [) _7 _; H // 取模型号
" M5 t M$ p: B2 E. Y ZeroMemory(szModelNumber, sizeof(szModelNumber));% m/ ~5 J& k; F+ K. M# q( l q0 r+ a
strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
; `; j; M' K" S7 h( x9 \ m/ S% m; h1 C
pSerList->Add(szSerialNumber);
) J4 Q5 _/ z! ~ pModeList->Add(szModelNumber);
" n( Z% q5 B- R0 f }
# |7 A0 H- d/ y& J, Z( f& ?5 i7 T }
* |% N1 e$ B7 c/ s9 F3 B; U CloseHandle (hPhysicalDriveIOCTL);
3 U: n1 `7 q# _, x1 u2 C }
2 e( R8 q, _8 m4 w; c2 s4 ^ }
7 E8 n$ Q$ D* s}
) g0 S3 W" `* a* F N//---------------------------------------------------------------------------) M8 r# K5 D% i) l
// DoIdentify
$ q. j" P. h ?/ l6 T, \ Tbool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
) d' u, y9 m' E9 E- v+ ]7 X PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
; _/ {* C. U4 z PDWORD pdwBytesReturned)* |; f3 ^( o; a% J- W
{
3 b6 w) q& Y# l3 k) S; H // Set up data structures for IDENTIFY command.8 U5 g3 U5 w8 i9 W
pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;9 z; |& D7 p# h8 V/ ^7 V+ `+ S: c
pSCIP->irDriveRegs.bFeaturesReg = 0;; j# ~8 k* k' h5 ^! I* A9 C/ w8 P
pSCIP->irDriveRegs.bSectorCountReg = 1;
' F- p+ t; ]+ n2 M9 r& Y5 n pSCIP->irDriveRegs.bSectorNumberReg = 1;9 x- i2 O; d9 K- w0 C- J5 _/ |
pSCIP->irDriveRegs.bCylLowReg = 0;
7 B, U1 u( K) L3 x. J pSCIP->irDriveRegs.bCylHighReg = 0;1 m8 m3 `8 H# C5 D% v7 V9 {
, C0 p: U2 L: W/ l% K // Compute the drive number.(主盘和从盘所对应的值是不一样的)
: S4 t* b v# \/ r) ?, N, x7 p pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
( V4 G8 ~0 Y0 l+ M& L1 A6 N) G4 S
// The command can either be IDE identify or ATAPI identify.
( ?$ b) a& a! A2 }0 o) [ pSCIP->irDriveRegs.bCommandReg = btIDCmd; C3 h; u" W# b$ \$ L0 F; @5 F. j
pSCIP->bDriveNumber = btDriveNum;% t. a9 T/ e7 M m# \+ l
pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;3 E' M( K% P6 Q* Q6 W
7 J" q* n n3 V- f: K' @% l, E
return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
, Y5 N% m" P, U+ u (LPVOID)pSCIP,/ n) B2 U" u: o- \3 R) [
sizeof(SENDCMDINPARAMS) - 1,4 j/ I: M9 @4 y) K' T3 s* H
(LPVOID)pSCOP,
; Y7 N1 [( `: u6 I, Y sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
$ E( h4 h- U# {% D* h( o pdwBytesReturned, NULL);
5 N/ I. v6 a. Q: u1 v4 @}6 {, ~2 q$ r* C% P
//---------------------------------------------------------------------------
3 e# M' Z. \# O( M5 t// Windows 95/98/ME 代码9 Q* Y6 J# N. A2 Q
//---------------------------------------------------------------------------
) a) F- n7 G( S# Q) g' c7 S! ?1 }// ReadPhysicalDriveOnW9X
4 L2 Q6 c2 O- \4 _void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList). O [+ ]- Z: L3 p9 x. m- f# }
{/ D) |3 X+ L1 K6 @: c/ g7 `: @& Z
WORD wOutData[256];" G0 s/ L+ V& L3 g
SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);5 W$ z7 g G" t" \2 M, r! z+ K9 z/ A
3 b% z8 l' F" _, b {' B
// 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
- H% g% d9 s; t" _. @& `6 ~ // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
+ H6 p1 i/ w" t7 ~0 X* C) H // 避免蓝屏的出现。(期待高人能指出原因)
% `/ \ l0 A- _0 N* j for(int nDrive = 0; nDrive < 8; nDrive++)% O% d% d0 V5 g' w1 U
{1 p7 b4 y4 C. ?) k0 A6 n
WORD dwBaseAddress;
8 o+ q/ i" F4 ~ ^" S1 O' X* y BYTE btMasterSlave; // Master Or Slave
+ B; _+ u& f# u0 O! t' e bool bIsIDEExist;+ Q) M" w+ x4 G# |1 v: c5 p
bool IsDiskExist;/ I2 j! n3 M9 A3 ^. G: Y
$ `( M3 U ]) W7 x+ l& w e, m9 K" u
switch(nDrive / 2)
; \& \' S" c( n* M6 h! a) L {
% ?# J, t9 k6 T0 d( w+ r; Q; P case 0: dwBaseAddress = 0x01F0; break;5 \0 m. |5 u1 Z
case 1: dwBaseAddress = 0x0170; break;
) k# E7 f9 o. R8 H$ h2 `% A. F: h case 2: dwBaseAddress = 0x01E8; break;
' E+ X U" V- |' F' X case 3: dwBaseAddress = 0x0168; break;- \4 g" Q# ?0 r! E) g: `
}- g9 ^. Q: b7 |2 E+ l
- S! H& A" h# c+ K6 d! x1 ?0 F; } btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
! j# X. w5 G. v9 o
5 I: B( S8 T" y7 ~7 f // 进入Ring0
- D0 l2 X5 B: m, \. z: W" x ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
# F# t0 J2 e: Y1 G7 o bIsIDEExist, IsDiskExist, wOutData);
9 O2 X; N% X7 p6 ~; t) ?8 ~) R, M! P }; @9 Y' x$ E$ S
% |9 c- L7 ^( [( j$ i // 开始读取" }- V7 g) Q# ~# d
for(int nDrive = 0; nDrive < 8; nDrive++)
. g( c8 W+ }1 [* I/ o# k/ j i4 Z P {" W s) S% r- v7 F+ A h4 J
WORD dwBaseAddress;7 E2 P+ x9 f/ n. F& J* E+ f
BYTE btMasterSlave; // Master Or Slave
K+ M. T( r2 F4 m! { bool bIsIDEExist;
9 f0 I6 ?( u# J: M* ~* w: \" z bool bIsDiskExist;
9 a9 x' S+ O- J3 I2 d# f switch(nDrive / 2)
K) n8 V4 D6 d0 U; i H! y$ ~7 O {; Z4 T. b! b" O1 i* K! ?# U, k
case 0: dwBaseAddress = 0x01F0; break;* k+ T! V% H5 H, e: v$ i/ T# T: N, T
case 1: dwBaseAddress = 0x0170; break;
/ D) d! n, d0 \2 ^9 N. p7 ~/ T+ @ case 2: dwBaseAddress = 0x01E8; break;
, L7 c3 h8 G2 q- Y7 O) k# W W case 3: dwBaseAddress = 0x0168; break;* l w' i. j* E+ d$ Z3 q) b
}
+ N4 y- C& I, s8 T( d3 J$ ~2 B5 r/ `. f$ J( o% D! f
btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
9 F) V# N5 ~2 B! `/ x7 K. G6 f" b+ |9 ^0 h6 M
// 进入Ring0
- w' F9 m, ]& C; e( |6 l bIsIDEExist = false;8 w5 Y) T5 k& M6 A# F5 N( Z
bIsDiskExist = false;
- j1 d% n9 W, t1 d+ @5 X( o ZeroMemory(wOutData, sizeof(wOutData));
& b& H4 {) C+ I8 f4 c8 t' D) \1 t9 u/ I" U u' Y- c
ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
U$ o# E1 x1 P+ H: K+ o8 | bIsIDEExist, bIsDiskExist, wOutData);
5 P$ D, {4 s o" x0 H# h) x
6 b4 Y3 r, U3 C7 l) k5 C/ D$ Q if(bIsIDEExist && bIsDiskExist)# P- {8 `3 o- e/ Q
{
& V- k% B Q! w DWORD dwDiskData[256];" n6 p8 G& U! s, Q n3 G0 b' P
char szSerialNumber[21];
1 r) Y7 s1 Q, }6 C char szModelNumber[41];) P( R( C5 J, |2 p2 f# K h
+ o J i" m' K t t+ N
for(int k=0; k < 256; k++)/ E4 f# G5 a f% [$ O
dwDiskData[k] = wOutData[k];
2 d6 d+ Q8 Y+ M Z6 x# T
- t, n+ v5 i5 C" h# C8 T // 取系列号
% u# a A" G. M. m) j* U ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
! e0 c" a4 P% B' {6 [ strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
7 ~2 N O8 B% `
, X2 U% p/ W* h3 p- Q) T& ` // 取模型号
j$ ~8 t. K: \# _! a$ _ ZeroMemory(szModelNumber, sizeof(szModelNumber));0 L/ s% x2 _ d# J7 A, r
strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));: O* c: S2 d# Z! V8 V1 i( O
5 k1 H* q" q3 R9 t( \7 N) J pSerList->Add(szSerialNumber);
3 m+ L* p, J# V4 Y0 i pModeList->Add(szModelNumber);3 ?; i) G1 }2 G3 @+ f
}
6 X# _( i8 ~8 O+ K) O$ s }
; u" _5 _# F/ y7 Q2 }* H+ g SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);! m# z# r1 p5 z- y- E! s
}
3 A8 k, w# o0 y }7 g4 P# Z) }4 y" P//---------------------------------------------------------------------------
3 L; i! W q% b, _ h// ReadPhysicalDriveOnW9X_Ring0()
7 |/ @9 R* Z; \) ]/ h9 N" r/ l+ `//5 K7 \' E; b3 L Q
// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
- |; k8 R2 {1 Z8 b3 L// btMasterSlave = Master(0xA0) Or Slave(0xB0)/ Z% F/ I/ z% [
//---------------------------------------------------------------------------- a+ i) Q2 Y$ h
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
+ w5 H @3 _' y8 y BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
; K# b" t! U6 G% f) }4 Q, D2 U1 N{
+ ?* w0 m8 C1 y9 F! `* W6 b BYTE btIDTR1[6];
7 |$ D9 q6 v: B# {8 ?& T% m DWORD dwOldExceptionHook;9 \. H) Z/ a# n% {
const int nHookExceptionNo = 5;8 l. v/ m* Y+ e/ Y$ A
+ D' M# O/ Y, P: o9 y8 p" T
BYTE btIsIDEExist = 0;
; G, ^) ^; f# n# k BYTE btIsDiskExist = 0;
2 C% Z O0 ^3 c1 Y! Q: o% ~ R WORD wOutDataBuf[256];
' \3 A0 {: k8 N! o9 a0 I N: z
- y2 c2 G) F# ?( |7 i+ P BYTE btIsFirst = (BYTE)bIsFirst; o* h6 J) u$ V' n( \: a
0 k2 I+ P2 s) N6 n K; [1 e
const BYTE btBit00 = 0x01;- S' [3 H! B8 s4 F% t9 f
// const BYTE btBit02 = 0x04;% Q- R% ~0 h1 }* Q7 {; ?# L
const BYTE btBit06 = 0x40;
" \! n) O5 E# U5 x5 D4 a( i const BYTE btBit07 = 0x80;
( ~) T1 Z2 y, p2 a // const BYTE btERR = btBit00;4 B! w2 W; q* L
const BYTE btBusy = btBit07;
# _9 h7 F6 ]4 F, n9 c ] const BYTE btAtaCmd = 0xEC;9 P9 l9 g2 L1 E
const BYTE btAtapiCmd = 0xA1;% c. z4 U! S6 G3 W- S6 F: z
- y" q; ~. g: e: D __asm! w8 E* G5 b7 J
{
; t. b1 q& O9 f* S // 必须先执行这条语句
- ?" J2 R* S; I3 Q$ j JMP EnterRing0
7 e+ S! o! ^& V. u$ j$ `8 d
# [; `0 d5 c1 } // 定义过程
1 K2 A: m P1 z // 等待IDE设备直到其不为忙为止# l0 _2 ~3 u# s
WaitWhileBusy proc
. j7 v* Z" M3 x, n
( e4 R* @/ X$ Q. X$ \) D MOV EBX, 100000
5 V# d/ H9 C* v+ l" g7 l- Z MOV DX, dwBaseAddress
- j6 ] m* @2 C8 u: I6 J ADD DX, 7
! q& ?: u" [4 O4 m3 j% f8 [
/ b0 [/ p( t0 R2 a LoopWhileBusy:
8 I, O% y3 M! _ f+ o+ ?# R( r
" e( [5 @# L w( |+ \ DEC EBX" c. _4 c; n0 \( J3 F6 D. G
CMP EBX, 0; K' F4 o) G( b! Z' W
JZ Timeout
. ~4 z: ?0 [; D5 s in AL, DX& z: m' r7 K5 `. i) O$ R( D
TEST AL, btBusy
$ w, f! B3 P) W- A2 d b JNZ LoopWhileBusy
: V& s' `% @6 ?0 H# V JMP DriveReady
; b' n% ]- N. A' j2 r
! E C# q0 e) Y: A5 U4 p; g // 超时,直接退出
& K! y9 X$ ^4 _ Timeout:
( {1 S1 g1 k5 W3 W+ O5 S) H JMP LeaveRing0
* n- J, z+ [1 t9 _* D$ ] DriveReady:7 Q. O: ?5 X1 U
RET
8 l& V7 q" f# q; F/ B0 g ENDP // End of WaitWhileBusy Procedure
* c9 y6 b+ J$ n% {
! M$ m! N% ]- ?) o% n& F' R // 设置主盘和从盘标志
E8 z4 K* F7 u5 I9 d; P" O) v; F+ }/ U SelectDevice proc
' k! K# A5 P2 m
$ u. G- n( h( k: t MOV DX, dwBaseAddress
: A( {8 F6 n0 ^( e7 p9 v' z2 p ADD DX, 6 P/ ?3 k( b1 d) I+ m5 y
MOV AL, btMasterSlave
1 {( b6 Z: J6 }, d& S4 P& t t* G. G) e4 [) ]" a1 ]! o4 d: ?
out DX, AL
/ T' S8 a3 G2 l8 I6 N6 G RET# a7 [0 }! J9 S) @0 j% D" Z4 q
" A: P5 S% p6 K ENDP // End of SelectDevice Procedure
# t, |# U5 U5 A6 L7 ^) O6 V2 {: I0 W/ K5 ?! B2 G* y
// 向IDE设备发送存取指令
* h! O/ Y F0 j( L, ~) y) u& M SendCmd proc" H( n2 T, _9 B: r( U9 R: b
) D( p1 h% O5 |- g7 _
MOV DX, dwBaseAddress
' y5 Y1 t. G2 X; m: `& _ ADD DX, 7
4 Y7 }+ E( a% `; n MOV AL, BL // BL是主从盘标识,在过程外设置
0 l' B$ J9 j# r' `0 z# J& O3 r& Y+ _ out DX, AL! t% o$ d8 V9 s7 L0 c( J
RET
& X! L2 q/ u. x) W! t ENDP // End of SendCmd Procedure3 }7 U2 T! I! w n' }+ m- P
4 Q* ^# q; q ?+ q+ K8 X // Ring0代码; W: e! U2 {* H0 J* h# G# o
Ring0Proc:
7 }: ?* x8 ^. T. O+ t% P3 o: ~ PUSHAD& X8 R8 h8 d! ^/ r' d# t! c
// 查询IDE设备是否存在. v# b# z# k; E9 x: j
MOV DX, dwBaseAddress1 c& O3 N j1 Z8 Z2 P" T
ADD DX, 7# n. |0 q/ H) j- \' W' H/ r
in AL,DX
* c- c3 e$ ^! X1 a& ~. \# ^9 t+ X% i+ r
// 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回% h t& c9 x6 m- g2 ^- k
CMP AL,0xFF. I! j1 Q( \/ h( P( j K) S
JZ LeaveRing0) r& E! B. }5 T6 b, Y: d
CMP AL, 0x7F
( _, i# e: {( G' W JZ LeaveRing0
% ]; T, H" i4 a8 l7 N8 c% S" ^
" |) b1 C8 V# u# d3 }8 n // 设置IDE设备存在标志
; `0 L/ M% h' i8 r/ \ MOV btIsIDEExist, 19 E) r7 w7 \( G$ ?( U5 T
; I; m/ Q5 | y/ M) w
// 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
2 k6 Q+ s2 {: Y( K CALL WaitWhileBusy
3 T; s' P: B, B' c/ d3 O8 _ CALL SelectDevice$ W/ ^; k W3 I2 W: b
2 Q6 L7 \1 I2 h5 @, D u // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏* |3 C/ [' F6 Q7 o3 |: s
CMP btIsFirst, 13 o8 x8 X! G$ Z' p5 C
JZ LeaveRing0
; L; P: F% c& b+ k( c( @7 z' [4 O4 ?3 x, v& U4 n" J3 m2 u
// 第一次调用时,如果执行这行语句会导致蓝屏,Why???
9 O% K5 A9 z/ z. K! C* d CALL WaitWhileBusy _4 s$ O9 f+ R1 ]4 L$ n, X, T
' }8 R k- ?; Y: [7 F/ c // AL的值等于cBit06时,不存在驱动器,直接返回
/ ]+ W1 t7 Z# W4 ?8 [ TEST AL, btBit06# B# K2 r' ?; Q/ T
JZ LeaveRing0
6 H( L# B3 s7 c/ d$ ]
. f' q6 W' X, U Q" _( P- S // 设置驱动器存在标志6 Q3 y- E2 i5 H; ~8 ?
MOV btIsDiskExist, 1
. o& `# M2 n- M0 W. s1 V( K4 G" X M9 e2 g9 P [1 l
// 发送存取端口命令
1 X9 ]. E$ z- d+ k) Q- ^! F // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
p' d2 O4 G8 O7 d+ v // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
2 w( q; f0 }$ Y. U) m+ [ CALL WaitWhileBusy
0 O; o3 G2 s i; e4 Z/ z CALL SelectDevice // 设置主从盘标识
/ V2 E1 R! u5 c2 H) B MOV BL, btAtaCmd // 发送读取命令# U5 j$ x j6 ]4 A8 L
CALL SendCmd
6 p- y3 q1 |$ s CALL WaitWhileBusy
% h& g) o" Y: u: g6 S% I* {/ u; f0 g# x8 V9 `
// 检查是否出错( F1 O, V4 E. f5 V6 y9 z
MOV DX, dwBaseAddress
6 H/ W9 v% v' e+ L O& z ADD DX, 7
9 p6 s7 L7 \- C8 E K5 E6 W0 S; p7 @9 }1 _! ?5 m0 o
in AL, DX
2 z4 Y4 y" Q$ _5 A1 B6 r H+ ^; x- u% b% W, [ [! V
TEST AL, btBit000 F2 p2 W3 |. U7 j( ^+ D
JZ RetrieveInfo // 没有错误时则读数据/ y# q, ? j& {9 g4 {' R J2 p
& n. E5 O2 ~4 s" u // 如果出错,则进一步尝试使用ATAPI设备命令( F! ^; { ?' L% @' J
CALL WaitWhileBusy
' A) D8 X) ?0 D% m' ` CALL SelectDevice
* z5 v, l& n" b3 y1 {1 Z MOV BL, btAtapiCmd
+ S5 e: L, N4 z, W CALL SendCmd0 t) _( f# _5 L# \3 f
CALL WaitWhileBusy- {: H" F% K: D6 A$ I* j
. K/ b! Y7 ^' H U$ F, i, |5 s // 检查是否还出错
* u2 y7 j2 x7 V5 w MOV DX, dwBaseAddress
# q$ k6 t7 M* A+ s ADD DX, 71 m; T( p: n4 G8 F1 }* N
in AL, DX9 @" h: U& Q2 s
TEST AL, btBit00& c! M7 B4 `9 n$ }$ o' a
JZ RetrieveInfo // 没有错误时则读数据
: b3 F/ E) q6 ~# {" [! c( V" b JMP LeaveRing0 // 如果还是出错,直接返回
* M" |! [) W4 e
5 F, n' S* k* A3 l4 ?' t$ a5 x+ V // 读取数据
9 u7 J# }* |3 n* t7 ]8 G9 w3 @5 f) P, L RetrieveInfo:* Q, s. e8 E3 K
# x/ g7 I, F& g* \# m) p( n LEA EDI, wOutDataBuf
) k: f+ l5 p7 T9 h MOV ECX, 2567 ~- k9 D3 U# `3 |' K
MOV DX, dwBaseAddress* i- z/ K" \3 F! g1 M
CLD$ }% R/ x' }# O) Y/ K# ^6 T
5 P7 k0 q- j$ D/ l
REP INSW& y2 i. l$ j8 I0 k/ @9 `0 X
7 l6 O( b% _. }2 W Q; L // 退出Ring0代码; |0 T8 J% b5 L
LeaveRing0:
& n+ u6 }4 K0 D1 {7 j4 F" W( |6 n( J( g) G, D& r$ J: [5 [' \ ]+ l5 O6 J
POPAD
. O0 b1 K0 T* Q IRETD5 H7 m( Z9 g5 X
- E: X6 z3 |: l+ T' {
// 激活Ring0代码
6 H7 [1 q$ v' p* J: s EnterRing0:2 j) @& k* a+ R6 I" N0 q3 m( {
$ r8 J9 x5 }3 I1 ]+ ?
// 修改中断门, N- W: q" F+ c$ w5 b1 W
SIDT FWORD PTR btIDTR19 ~% p& ~9 T: S h# k
MOV EAX, DWORD PTR btIDTR1 + 02h; H- M2 Q, f1 @3 [' k |% l
ADD EAX, nHookExceptionNo * 08h + 04h
! \ P' y( `/ B( U& j CLI0 L& Y1 J8 U) |* Q# `
8 x$ O2 T6 i {1 b
// 保存原异常处理例程入口
6 N; L# `- m1 l1 P+ c. a( H MOV ECX, DWORD PTR [EAX]
" B" o. V) A5 Z8 K- E( ] MOV CX, WORD PTR [EAX-04h]' U. w! }" l% d6 X
MOV dwOldExceptionHook, ECX
! N, S# y- F+ O) q
9 V7 d* _* i" J1 z- a // 指定新入口* v T% J$ h$ G1 ?" N
LEA EBX, Ring0Proc
2 E7 o' r" q; n! [ MOV WORD PTR [EAX-04h],BX! [1 |! O4 d% K
SHR EBX, 10h3 T9 Z' U! N. w) N) ^; [, f( t
MOV WORD PTR[EAX+02h], BX
" Q- w( n) f5 P( m3 n' ^, a8 N9 ]' w9 x& G' h" M/ S
// 激活Ring0代码2 Y, x9 ^1 }1 F. K! b7 Y2 ?
INT nHookExceptionNo& v4 M, P- p; x
4 d6 b K# `/ @, a // 复原入口: R# B [( |5 Z9 r. V
MOV ECX,dwOldExceptionHook; b# Z4 R$ n/ t2 Z9 `8 u
MOV WORD PTR[EAX-04h], CX/ {" t5 d5 Q1 ]( z2 K
SHR ECX,10h
- r+ H: y4 Z9 h& k MOV WORD PTR[EAX+02h], CX
% N) f( c) v/ I, b# o( B5 t STI
% f; D3 j' ^3 r2 h+ c& y. ~ }, T! m' b/ f g e) ?9 `
if(!bIsFirst)
F3 k0 O# U3 \ {5 U( h9 e# h( U1 t* F. h! O8 r1 \+ ~
bIsIDEExist = (bool)btIsIDEExist;
' _, z* H' x) p# V" [9 d( E0 p7 \! P bIsDiskExist = (bool)btIsDiskExist;3 F3 a2 ~4 V* C6 G* m. O: ~
CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
9 j, u( `! J$ [) M9 `9 d# m/ b- c }
8 l) c' u4 [7 u# p4 b$ g( B y}
4 U8 m2 M8 \, R//---------------------------------------------------------------------------7 x! D! D. r# ?8 j, W
// 调用方法:
5 f1 I' h7 m' P. ?, P: [void __fastcall TForm1::Button1Click(TObject *Sender)
5 W, ?: O* y2 P2 c{
1 Q4 c4 `9 B% E' w ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
9 V1 C; w: x, B A} |
|