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