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