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