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