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