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