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