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