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