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