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