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