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