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