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