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