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