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