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