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