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