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