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