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