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