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