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