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