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