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