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