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