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