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