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