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