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