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