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