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