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