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