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