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