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