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