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