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