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