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