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