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