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