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