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