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