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