找回密码
 注册
搜索
查看: 3990|回复: 0

[收藏]在Win9x/NT下获取硬盘物理序列号

[复制链接]
发表于 2005-5-30 19:22:36 | 显示全部楼层 |阅读模式
  #include <WinIOCtl.h>" y1 i( X; r  b! v, a6 w
#include <stdio.h>
5 e. v: v* h: m3 _* U  {1 P, @) ?- ?7 H2 ]% T9 u
#pragma inline
) z& i3 w* M. `+ n, o2 \  j//---------------------------------------------------------------------------% ?; k) O' A5 K/ ^; |, r- C
// IDE NT/2000/XP专用变量- s; [4 U9 O: h/ t" F
#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS& g) N& T4 I& D$ X0 D2 @9 u7 n
#define DFP_GET_VERSION         SMART_GET_VERSION7 t0 `& o: O9 I( t5 q% W* A4 C5 s
#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND( ~* b: `& F; g# V
#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA, h8 O# C; D% w- S( A2 M
) y5 K# ^. x* r- W
const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令8 q6 }! U$ \$ r, j& A
const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
' j% G! r5 @' M8 @/ \9 D
" R" o6 L. X2 j2 @3 ?+ Q7 E& oconst int MAX_IDE_DRIVES = 4;2 v/ [6 l% _8 [8 f4 r4 I" H% P
: K5 j6 K! u8 N& b! I: j+ _
// SCSI专用变量
" N8 d9 v, S; R- Fconst DWORD FILE_DEVICE_SCSI             = 0x0000001B;
9 x$ b& b* h0 [7 }const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);7 M- V- x/ C3 M& b9 ]8 p
const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition( p+ ]8 i" d$ P
const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
' y! f% ]5 Z. J: r9 n' G0 J5 B+ U6 @/ m* Z9 E3 X: M$ `6 i; H
typedef struct _SRB_IO_CONTROL
1 j: `; \- \$ w1 d/ N{0 U: H& t5 u2 a
   ULONG HeaderLength;6 R2 u- O8 p  @
   UCHAR Signature[8];
* Z) \4 K0 H% F! [    ULONG Timeout;
2 d* q0 V- G0 i% _$ [* K    ULONG ControlCode;
  n. A. Y( v3 m    ULONG ReturnCode;- H/ O: [  n/ k1 P, d0 K
   ULONG Length;" A* w4 G  R* V2 _& o
}SRB_IO_CONTROL, *PSRB_IO_CONTROL;! u& n: x' O& @- [* L( P% z
9 i* V5 Y/ ~! z9 [4 Z
// 读取的主函数: d8 m" }) |7 V1 u! S: {
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
7 r8 x* z1 v3 N9 k: I9 o& K
$ A$ {4 m4 ]; F1 m/ `' p2 J, l# b// 辅助函数
2 p6 V% Z; p# {. n; d% g$ Z6 mchar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
5 d6 _3 P& ~" H8 W( z" x8 u3 _// NT/2000/XP函数" [' l1 \2 }+ {9 _. K9 u
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);/ J# v' W' E% l% m' i) O. Y% g
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
1 R  W* F' q7 \        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
: E1 K0 _1 d( X        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);! N) j8 f4 i8 u5 p
// Windows 9X函数
$ E% \5 k& c! n) b" d7 ^, B% j. u6 ?" ~void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);0 Y2 I/ B; s+ }7 f6 h- U; u
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,3 f: [. n3 `, I0 k' a7 H
       BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);- w9 b) T/ V! p

- m( n, d! R; g: D// SCSI读取函数(for NT/2000/XP)& Q0 ~. e/ V/ g
String __fastcall ReadIDEDriveAsScsiDriveOnNT();' h7 w  ?/ T3 e% t) ?0 b% b0 s
//---------------------------------------------------------------------------
) K" D" S+ u6 F) ]* F// ReadPhysicalDrive7 N3 D) [! V. A) q/ v( ~
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
  o, m( Q& O# l, @{' W3 q& X) q4 p8 f! n5 E$ s
   switch(Win32Platform)
' M6 u/ U/ a  U( Q    {5 ]' _4 ]6 J  l( W% i( @
       case VER_PLATFORM_WIN32_WINDOWS:, N1 {: f; j' M2 ~4 S
           ReadPhysicalDriveOnW9X(pSerList, pModeList);
: `6 T- d, Y; w3 T1 q) a( x  O; U            break;7 O8 @/ v: q1 h& y2 c
       case VER_PLATFORM_WIN32_NT:. x- ?! u8 r2 \4 F' o' s& p
           ReadPhysicalDriveOnNT(pSerList, pModeList);
. E% d3 R" Z( m. D" N6 M6 |            break;
8 h4 O2 `+ P, i4 V        default:
# w& A: @6 d0 @: F3 T( v            break;
! o% Y: ?/ W, J2 F- d  I' ^    }
. n/ O$ \$ \3 H& Z}
% x, v- N. B4 m) J  h6 g& p//---------------------------------------------------------------------------6 b4 X8 A7 n; k
// ConvertToString
4 G2 [& @- ^( a# T6 P- Z+ l7 B: Vchar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)0 e8 K, J! I0 ?
{, P3 s. M$ @5 x2 L" B, X
   static char szResBuf[1024];9 a  j: }4 A$ \% E- g: o6 T' J
   int nIndex = 0;
  N; |6 E" D; X2 C' b    int nPosition = 0;2 t) F# s" S8 a" j) Z
% Z$ c( Z# j5 Z' V: \& a8 I0 a1 s
   // Each integer has two characters stored in it backwards  P! I7 {, B/ d3 E
   for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
, Y2 F  E& L0 m    {" u2 X* L& f. [7 D6 k* L
       // Get high BYTE for 1st character
) Q0 l# ?  J) O2 D: M        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);3 a; ^- Z% s# r7 b$ s' Q
       nPosition++;1 J* i  S1 x; L. m1 i

# N( G& @8 M% Q        // Get low BYTE for 2nd character
8 x+ o" p  A$ X0 J- T: |        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
; D" l# O/ t8 A: ]7 c        nPosition++;
5 S. u5 J/ T% H+ p    }1 g/ S! S/ |9 p

- l- r" k: _( X' e. d    // End the string) F' `. t% s+ Y" ^' w( W
   szResBuf[nPosition] = '\0';
% `2 S; k7 h" O+ Y) `4 N* `8 c6 \9 P+ _
   // Cut off the trailing blanks3 Z& o4 Y; h4 q( X. }
   for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--). X" T5 a7 L6 \& w  z/ e
       szResBuf[nIndex] = '\0';% n" m+ r" w" X2 i" d" p8 A
% u8 p+ x) c9 d4 s: P  ^  Y( ~9 I
   return szResBuf;
8 O  h  N# c! |: A/ H) f4 H* Z/ R  q}
% R$ }9 |3 a+ l6 m//---------------------------------------------------------------------------
, b5 J: i8 l6 M: R) t, |// Winndows NT4/2000/XP 代码$ b0 [/ P3 }# L* ^& g8 K
//---------------------------------------------------------------------------! ^; ]  I9 B2 Y0 L8 C* b; j
// ReadPhysicalDriveOnNT: {+ q4 t; o: r- S6 U
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)% c1 W: a9 G6 T- y
{- A, f1 D8 P0 a3 E7 n" s' W
   // 输出参数9 `1 \+ v# k9 a
   BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];; {2 z2 P1 J2 b- w/ R" i) i  A

6 h% d( D. K. v3 m  {    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
' M  E/ [8 r; c% b! Y/ a0 F- P' P    {
1 z+ t+ b8 s1 ]8 Q. B        HANDLE hPhysicalDriveIOCTL;
. K9 E4 y1 m8 ~* A; E        char szDriveName[32];* L. `8 u0 ~7 o% B) L2 T! T; _
; k3 b/ K0 H( Z  g6 X, l/ u
       sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);* a; h6 A7 Y) [5 Y# W( X- K: n
       hPhysicalDriveIOCTL = CreateFile(szDriveName,
6 B+ o; d4 E9 z# }& K# N                        GENERIC_READ | GENERIC_WRITE,
/ Y1 U/ O9 {. Z! {4 h0 N) L+ K                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
* y2 C# N4 g( L" c" x5 t                        OPEN_EXISTING, 0, NULL);3 R- O6 _3 l% p/ h7 e7 D
4 H& Z! t0 L9 l% e( A) ]4 i0 @
       if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)$ V, L- F# |0 g6 ^! g
       {& O3 b" K  o+ F* K
           DWORD dwBytesReturned = 0;' R! z' W- h1 p$ o' H
           GETVERSIONOUTPARAMS gvopVersionParams;0 H/ U. x5 o' v& |" u5 j
3 \' g: x. R  q0 t* s1 m
           // Get the version, etc of PhysicalDrive IOCTL$ n7 x) c) v: x; N  p: I( i5 J, A
           ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
! g6 O) U9 U* m' v4 H" Y/ h! D% ]( f6 G. {: H2 |6 _
           if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
4 t/ ~; a6 k! w1 t) O! v6 _( X                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
# y+ @$ o" |5 @( M7 g! H$ ?                    &dwBytesReturned, NULL))6 `8 S% q6 _% ~' A0 {
           {
/ W( \7 U0 B+ U                continue;
$ N7 N, a( \5 I: }0 c            }# F# }1 T2 |& P( S4 A' E

0 E$ |/ G1 A/ A0 U. Z            if(gvopVersionParams.bIDEDeviceMap > 0)4 Y* r; P3 j# o
           {/ N5 H! W$ `( M  i3 o6 t! [* z/ ?
               // IDE or ATAPI IDENTIFY cmd
- s! z! y  q9 o: h1 O; s7 y9 U                BYTE btIDCmd = 0;$ s' `( R- V* X( S+ G
               SENDCMDINPARAMS InParams;
, C. k$ q' n  Z8 y                // Now, get the ID sector for all IDE devices in the system.& b# }9 k! p$ r% @
               // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,2 U* z1 ~3 F; M+ S  E% m5 ^, d+ q
               // otherwise use the IDE_ATA_IDENTIFY command% m4 D9 A4 k# f2 [2 ?% D4 t
               // 具体所得结果请参考头文件中的说明2 h5 U# s% Z% s$ h
               btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?1 R) x+ t1 y6 R
                       IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;! q6 z! p) b+ _$ _$ G9 i
               ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));+ i7 T: n* }) ^6 o  y; L
               ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));( b: N4 {! m4 b) T+ x

2 ^( R7 Z1 ]4 \                if(DoIdentify(hPhysicalDriveIOCTL,' a5 `* ~5 L1 y; B0 o# h/ R1 a0 B$ E3 |
                    &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
% ]9 Z. g6 |9 h1 u8 h0 i                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
6 r' d! q& m$ I1 x+ r1 Z                {4 n' G% K* R* R2 K/ H7 x
                   DWORD dwDiskData[256];9 v( T; L4 N9 q
                   USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
, G0 }& ~9 g7 U+ z; t8 M                    char szSerialNumber[21];
' S2 Q- U9 l6 }1 V! P                    char szModelNumber[41];, E) D/ F6 h* ?$ c' O8 t: C( i7 z  L

$ ]4 A3 P- ^% u                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
3 }# V: U, H6 B) j( ^* J                    for(int i=0; i < 256; i++)
1 i- u; T" i; f& r, \( p, c& J                        dwDiskData = pIDSector;
8 v6 T% ^* J4 q( T1 m. Q1 n, D2 Z' w                    // 取系列号- P+ J( ?2 q7 a& B# h' i1 B
                   ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
) s6 n8 X" Z6 @                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));6 ~3 V0 T7 h, U7 i2 v9 i& Y6 D

1 D2 m2 D2 m, T2 w: i. v                    // 取模型号7 C% Y2 B% g- a
                   ZeroMemory(szModelNumber, sizeof(szModelNumber));
2 K0 c' ~7 y& S                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));1 k3 e9 N, v5 ~& S+ U* ?
- M( M. T( n8 d
                   pSerList->Add(szSerialNumber);
" L0 D1 o) C' w$ W0 W1 v                    pModeList->Add(szModelNumber);
2 O, o. e+ n3 m# I& s" j4 n, E, t) _                }
( x# i: R; W) \            }) A* k0 R+ E$ c1 Q+ W# a: Q; f
           CloseHandle (hPhysicalDriveIOCTL);2 o% j! y: \! R2 a
       }$ [! ?7 C( s% `* @
   }* {# Q6 e) l! T" j7 M# O
}* m' Y4 ?( M' \# v- w
//---------------------------------------------------------------------------
9 h: ^% N& X$ R, A/ {4 {// DoIdentify6 L/ s) F* F+ P" {+ N
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
! J6 A7 P1 q4 o# Z* A$ T5 q              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,1 e* t  R2 `5 z- d, D% _9 `7 h
             PDWORD pdwBytesReturned)
" T1 e1 Y9 g1 `  U; E: o{
" S% j% u: H4 Y  ^# u' T; v    // Set up data structures for IDENTIFY command.
' v6 S$ n# d! ~( R8 F# n4 h    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;* W+ S) A) K( X  D
   pSCIP->irDriveRegs.bFeaturesReg = 0;
" Z; R; S: a& i9 \$ A( ~    pSCIP->irDriveRegs.bSectorCountReg  = 1;3 e; r8 o& X7 u0 y3 n; x* M) y
   pSCIP->irDriveRegs.bSectorNumberReg = 1;3 B7 S4 Z" m4 w4 Q0 M3 v; r
   pSCIP->irDriveRegs.bCylLowReg  = 0;' z2 Z+ v7 R+ Z/ ?$ O2 _" q
   pSCIP->irDriveRegs.bCylHighReg = 0;
* v9 A3 t: ]& Y$ \) m  P* S+ F& q' u# C/ ]( [2 P4 W$ ~3 V
   // Compute the drive number.(主盘和从盘所对应的值是不一样的)
$ c9 ?9 f8 [! x' @5 t2 p    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;8 K% X, O3 T2 H! ^; _7 J

1 J5 S* \: ~7 x    // The command can either be IDE identify or ATAPI identify.
7 J, Y7 B3 @' X    pSCIP->irDriveRegs.bCommandReg = btIDCmd;) s# p, @6 H( W! Y1 d# v
   pSCIP->bDriveNumber = btDriveNum;4 B) N% Q: _1 j/ Y9 j: C
   pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
# {" W' \. `1 ]8 ^) ^
* z/ ^1 D  k! n1 Z+ x( T    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,& U# w1 E& q6 @8 S+ J- _6 G! W
          (LPVOID)pSCIP,8 m9 J3 y8 A: P7 |$ I, K, V
          sizeof(SENDCMDINPARAMS) - 1,( [2 Q9 `: R: r% ?
          (LPVOID)pSCOP,  {( c5 ~8 |5 A7 a9 [
          sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
; c- e' G7 z) Q( ^& R+ h           pdwBytesReturned, NULL);8 [& s9 Q* m# r; ~2 ]
}
! D6 ?9 R8 `, n0 h  t8 Z//---------------------------------------------------------------------------4 _* K1 S) j; \. S6 f, W
// Windows 95/98/ME 代码
4 F6 U  [4 ?" v" J: A//---------------------------------------------------------------------------
, C. Z6 [3 x+ ]1 L9 Q2 n7 w4 {// ReadPhysicalDriveOnW9X! u& j/ o7 t% _# A2 Y$ L) [+ W' B
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)) N  D8 b+ T5 C. S
{
5 z- h' q0 X! N  {& \! A8 T9 w    WORD wOutData[256];
: V' F; j) H6 ]; N    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);2 E9 U* U. \9 q8 H' X- d$ P
2 W) F0 y: ~1 _9 ?' g& d' v
   // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
- O# W& S. p% o    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以) Z  F9 c4 @7 G  l% E3 m
   // 避免蓝屏的出现。(期待高人能指出原因)
4 Y# T: O1 R! K) @2 l% P    for(int nDrive = 0; nDrive < 8; nDrive++)
+ M5 k3 u% k* S( }% e2 W( c* A    {& t9 K7 c1 s1 G# s, [
       WORD dwBaseAddress;
6 G* N' ^$ v+ g) r# q' H        BYTE btMasterSlave;         // Master Or Slave
4 O2 l5 c. R5 w7 p, f        bool bIsIDEExist;
- x9 ^  b+ ^7 `+ P9 v9 Z        bool IsDiskExist;
' J# e9 @5 [  C- l5 _* Y  M3 r/ _$ [
       switch(nDrive / 2)
) o1 W# i9 e1 g        {5 s1 s1 Y4 z* d5 A( c% d8 y
           case 0: dwBaseAddress = 0x01F0; break;
# @8 L, R% G7 t7 P7 b+ ^" o5 }            case 1: dwBaseAddress = 0x0170; break;
2 ?( ?4 \1 i2 Q' a            case 2: dwBaseAddress = 0x01E8; break;3 H' Z- H" o" M( o2 q& w
           case 3: dwBaseAddress = 0x0168; break;
  X# C5 g* S, J5 M        }
. H/ c: q* K: Q$ ^+ J1 R! L+ O7 @' g, k- C8 ~
       btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);1 E- T9 l8 t8 v) m: f0 ?
; A; ^! Z, ]6 ~7 V) q: b7 e" i( C
       // 进入Ring0* p3 y3 E; C" M' A
       ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
* L3 N" ], }5 i                bIsIDEExist, IsDiskExist, wOutData);
; A4 `1 C& m+ C" B    }5 z3 M- T/ s5 h3 L$ T/ G  W; i
/ u' p9 B- C. l9 Z  j0 D! x8 F
   // 开始读取
* |2 {. k; o9 |    for(int nDrive = 0; nDrive < 8; nDrive++)
: m2 w: h* J1 g8 r  f$ Q- ]    {
; |2 W4 g. u1 i) x4 D        WORD dwBaseAddress;
6 U6 w9 F2 J5 [: Q, ~# j4 ?4 q6 y( z        BYTE btMasterSlave;         // Master Or Slave7 o. i/ z3 q/ _5 K6 H% r  O
       bool bIsIDEExist;$ b- {$ V( t& r* T7 w& V
       bool bIsDiskExist;
2 b+ ?. K% L' Y7 o* J* b! \        switch(nDrive / 2)
  r- d% B5 ~& d0 v/ f, [, c7 a" b5 n5 `        {
; i& h3 ^" f2 ?9 l6 Q            case 0: dwBaseAddress = 0x01F0; break;# l( E" J* s9 G+ Q3 s7 K" F
           case 1: dwBaseAddress = 0x0170; break;
( m( |( c5 i, P! e- S0 W& `2 `            case 2: dwBaseAddress = 0x01E8; break;
/ L! j6 ]1 ^* N: R# }            case 3: dwBaseAddress = 0x0168; break;
7 W. C8 D. Y2 G  K5 d        }. c0 S2 k" r3 P' w: J1 U* |) t

" Z1 O9 ^+ m* y/ |4 K/ G9 Z        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
$ X$ n# U. Q! X' P5 @6 \; W
  ^9 K& Z; h- y6 v- g& w        // 进入Ring0& _" V( |; ~- S5 }( u
       bIsIDEExist  = false;8 {, a2 A4 l( i: f: i; l
       bIsDiskExist = false;
& i: {3 r9 z3 L        ZeroMemory(wOutData, sizeof(wOutData));
# w" Z4 Y& S' K7 ]: X8 k/ ^$ }7 t3 o( _" q
       ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,+ X6 J; N; C$ |6 ?9 y
               bIsIDEExist, bIsDiskExist, wOutData);
5 J* b" b- L3 U' g& b: f0 A
9 o: v- @& j: a# Y' C        if(bIsIDEExist && bIsDiskExist)
6 L* O5 x1 _1 Y        {; u/ z& A  h& C; L4 ?9 C& t( a
           DWORD dwDiskData[256];
  [8 q! p" N) e% f3 X4 `! E            char  szSerialNumber[21];9 X9 @- Z9 B( I, ]/ a; c3 }5 ~1 h
           char  szModelNumber[41];
/ j$ B8 B' g# ?8 E% t6 F$ g- V( N
           for(int k=0; k < 256; k++)7 w8 |/ y, L1 D; o
               dwDiskData[k] = wOutData[k];
4 A  ?# E, Z9 \
: D" S+ _( Y. P- g, R, w            // 取系列号  D; v, A& N" R9 J" H/ K
           ZeroMemory(szSerialNumber, sizeof(szSerialNumber));. N  g( P& l! \: l7 e9 i9 H
           strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));/ O7 ]0 A- ]# H/ v( U7 m  Y
7 m3 E, G4 R; P
           // 取模型号8 j3 e+ J- X% |4 Q1 T8 R
           ZeroMemory(szModelNumber, sizeof(szModelNumber));. ?) I+ p# x+ v6 {; x* g: I
           strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));, G, C* L" s8 Z# N0 G/ b9 H

' @9 B4 X: p- ?  ^: X8 N& J" ]3 E            pSerList->Add(szSerialNumber);
: Y/ e% z1 _' {            pModeList->Add(szModelNumber);
1 O. |; F- z" A; P3 d        }
9 h& U. m+ C! L6 x! C# v" t4 g# z    }
1 {& T5 z! |8 D( j% E" V7 L3 L    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);& S' ?- Y9 g1 y; S4 {
}
. L6 \9 i1 G: }0 F& l, t//---------------------------------------------------------------------------
3 e6 d2 i+ v8 R; J( t1 X// ReadPhysicalDriveOnW9X_Ring0()" b" y" b+ w3 n- i: v/ D+ Q+ @1 e
//
4 a! q1 I4 C. Q1 `6 a8 W// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
! K, o; S3 N' Z5 `5 S0 D// btMasterSlave = Master(0xA0) Or Slave(0xB0)
: l; o4 B) w" i5 v. w//---------------------------------------------------------------------------
0 `; Z; c8 f7 k7 g* cvoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,# k7 ]6 h8 y( n
       BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
4 t" L- [1 L; C" G5 H: l; W' j{
' J9 _* V! U. o- q    BYTE  btIDTR1[6];+ P+ @# y3 B, [
   DWORD dwOldExceptionHook;
3 K% E/ s7 G- L8 p3 w. _$ G    const int nHookExceptionNo = 5;% X/ a! }) I! ?! b0 _

  y! W3 @  v7 I' v$ f4 ]    BYTE  btIsIDEExist = 0;  d" g; e0 Q' N; b7 l+ c
   BYTE  btIsDiskExist = 0;4 W- O0 p. ^# ]. o& f$ ?
   WORD  wOutDataBuf[256];0 @$ e% {4 U7 m! S+ a
( \) R, V0 |+ `" S, `1 z/ H5 O
   BYTE  btIsFirst = (BYTE)bIsFirst;: p' A8 s9 h" v5 S9 q8 w( ~# R
1 q$ z/ h) M# f: N9 q6 ]; ?1 q
   const BYTE btBit00 = 0x01;
8 T0 [: v1 m) S0 V6 Y: e+ `    // const BYTE btBit02 = 0x04;/ K/ @* Y/ A/ |# p" O$ Z, \) y+ g
   const BYTE btBit06 = 0x40;9 r& j" Q6 e7 c& Y" G. N
   const BYTE btBit07 = 0x80;
& v7 |8 o  o. H3 _    // const BYTE btERR  = btBit00;
' e& U& b# d- q. L1 T$ J2 H    const BYTE btBusy = btBit07;9 Z0 Y; g: d2 Z& z4 ~
   const BYTE btAtaCmd   = 0xEC;
* `. {0 f! K! J: N    const BYTE btAtapiCmd = 0xA1;
+ v6 U9 z4 Q; U8 x0 O" o9 Y% W( g) G4 s" c1 Z1 Q
   __asm1 t( ~: ]# G9 b. S( ~9 X$ T9 c
   {
- x, }5 z) \% \8 G/ j        // 必须先执行这条语句% `# ]6 |6 ]+ O4 H& A2 a  `
       JMP EnterRing0& a5 j# o# {5 D! r8 U! p
4 ]8 L1 K! z( I5 ^# \; Z
       // 定义过程: c. f% G) \2 ]# h) {3 M
       // 等待IDE设备直到其不为忙为止# P& I7 M+ k* M- F
       WaitWhileBusy proc1 l* C/ Z/ ^9 X% q* Y! O
$ t; k: o9 z, I- _! S9 [
       MOV  EBX, 100000
* O. @* d  Z3 W% l# U9 r% x        MOV  DX, dwBaseAddress
, p4 z' ~& J' F- j3 J0 l6 U- c        ADD  DX, 7- S# @2 Q' X% u  O4 m

+ b: z. ~# @8 V6 V2 }% n; G        LoopWhileBusy:
  R4 ^) m! P  c: Q9 m7 h5 j  i( w1 V
1 ~  t' A; |% [: x* H  T        DEC  EBX
* L8 D2 P. k: K( n7 d5 ~% H        CMP  EBX, 0
+ R: T7 A9 ?2 P- e$ Q" v        JZ   Timeout; n0 e+ C+ d, F3 P
       in   AL, DX3 z* X+ ^. P9 ~0 ]( Q+ _
       TEST AL, btBusy2 Z" Q8 y' l  R+ `% L* I  v, e( I
       JNZ  LoopWhileBusy5 V* u0 _* b& r9 H. ?- f0 W
       JMP  DriveReady6 k) q& n* i' Y$ `) G3 d" [
& V( m" u* o2 X, s- e/ k$ `0 q" b& A5 k4 x; T
       // 超时,直接退出
8 j6 ?2 Y* }7 q5 `( j* Y3 b        Timeout:! h4 E5 t, B. N
       JMP  LeaveRing0
( T" O6 _+ e( `, F6 j2 R        DriveReady:3 L& `: R' `9 ]$ C' ?
       RET  z0 H, q" M' Z6 x
       ENDP   // End of WaitWhileBusy Procedure
7 j* u% N8 J3 W* x! u: ?; F" ]3 h; |% s! \
       // 设置主盘和从盘标志
1 X  P7 I/ d6 C- r        SelectDevice proc
; |! q7 `- P& x' S2 T" R: v
2 X! J+ t8 @( L        MOV  DX, dwBaseAddress$ U! R6 W! n9 g) U
       ADD  DX, 6# w5 w- K0 Y) n3 M: D. b
       MOV  AL, btMasterSlave
6 |9 v* R3 \3 P' D; V3 P. P+ z* z
       out  DX, AL
/ k5 k  k$ u. `8 S' v2 T! l5 y        RET3 ?) Z4 O$ P, D: K6 [5 n

$ q$ Y( `+ H4 a        ENDP  // End of SelectDevice Procedure
  G% P, Z0 f! ]* r2 R4 a+ `
) Q3 `! |' |) M6 y( @        // 向IDE设备发送存取指令
! M% O6 p2 w: y' D        SendCmd proc8 R8 H# d9 b; x& m

4 x  V9 I- Q) R. b        MOV DX, dwBaseAddress0 s, m9 m6 _# r; Y5 x& q7 u, V# N( c" U
       ADD DX, 7
0 j" [1 p# W+ E. u. w9 ~        MOV AL, BL // BL是主从盘标识,在过程外设置
/ {& t+ W$ [3 `        out DX, AL
4 `$ Q6 U# o" I) o/ e8 }$ u! v1 _        RET
& K! ]" E& m' s- D( r  E3 }        ENDP  // End of SendCmd Procedure) j; Q% [3 `3 n& x  F

5 p4 T/ w! r1 K* ]1 E; @. U* A        // Ring0代码
. }+ r9 m3 e* B# |+ [        Ring0Proc:
0 F4 B. q' o2 X3 V        PUSHAD
. p2 C. c, B4 G. K8 ^        // 查询IDE设备是否存在
$ M- j  J; a2 l        MOV DX, dwBaseAddress" ~- Z/ I/ r  w- N
       ADD DX, 7+ C% u0 v# a' M
       in  AL,DX
$ ?! B# x' N; u  z& }4 m
" P; J" E( W' _. h' r9 t0 u        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回7 M: H" H! H, Q
       CMP AL,0xFF* c+ B, L6 g) G
       JZ  LeaveRing0
9 S/ O# ?- z, ], E        CMP AL, 0x7F
# i' H, l4 S- X( \0 R, ?: X        JZ  LeaveRing0) b/ y1 J! P1 }' p  _- \
9 ^( z, o; b0 \# B9 E
       // 设置IDE设备存在标志
: i) @# _3 t+ t        MOV btIsIDEExist, 1' A2 [) B3 K9 p, s9 D; Y/ r) D

3 [; l6 T/ k7 |0 H        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
; y" p; x) Y8 T/ c3 D' _        CALL WaitWhileBusy
1 t% c* o" H" Z, I1 n        CALL SelectDevice# c3 Y: }2 m' x

  X( n1 Y; P, z$ X; z( l3 P        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
/ ^5 f+ l8 h9 b+ ^        CMP  btIsFirst, 1
" U4 K( L7 T* W* r        JZ   LeaveRing0* g7 m/ R; r: T" M

: C, T3 C3 Q( O& M  p5 s) n        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
; f9 M0 L! j/ d3 y        CALL WaitWhileBusy
# \* U# ]) A2 W
7 S  i- x+ d' E! d! X* E        // AL的值等于cBit06时,不存在驱动器,直接返回
' a6 `% z$ g" }+ `1 J( P        TEST AL, btBit067 T* m( N( @3 F; @* n
       JZ   LeaveRing00 J* j0 Q! F  ]4 X3 W8 J8 }- [; H

1 M4 S8 O7 `7 M  s        // 设置驱动器存在标志
, g3 f+ Q& z; A7 z0 f        MOV  btIsDiskExist, 1
6 |! Q+ g/ T, Q/ e9 Z/ i3 L) a& m! [1 R" [4 A5 E
       // 发送存取端口命令1 S) W) ^5 E  x5 ~) f3 ]6 c
       // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,- n5 B3 d1 U4 U6 ]
       // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令% u. V$ a: o7 ~2 D1 v, N
       CALL WaitWhileBusy/ @* o0 J: [( m4 i, V
       CALL SelectDevice    // 设置主从盘标识
" @4 c9 G+ q, S6 [        MOV  BL, btAtaCmd      // 发送读取命令
% Z! Z: e5 ~( E& Q9 t, u        CALL SendCmd
1 F0 W7 y* |/ O. l: y/ L        CALL WaitWhileBusy
0 ~5 p( H* [6 \* A/ t+ s% B# Y4 e. C! c7 |' j
       // 检查是否出错- M3 i! T' A6 D5 k: E% S
       MOV  DX, dwBaseAddress
  _* {' S( K5 a        ADD  DX, 79 A- ~% Q( K/ I# {% m3 |
# r+ h- J: V" Z7 X2 @0 A, I' [/ k
       in   AL, DX6 J. n" |" w. s6 V1 l- N/ n9 d: d
9 L3 T7 s( k  H( n% u' ]9 P+ m
       TEST AL, btBit00
& u  T6 ]: _. A+ Q! K, V6 s        JZ   RetrieveInfo   // 没有错误时则读数据, L4 x1 r# f/ B& V4 s7 o

& s1 z0 q) G* P( e" G0 W3 G        // 如果出错,则进一步尝试使用ATAPI设备命令
1 e& o% ~! A6 i' R  q        CALL WaitWhileBusy
9 T* \( t) T3 {8 \  {  |) u        CALL SelectDevice4 U8 j4 U9 {/ }7 E3 ?
       MOV  BL, btAtapiCmd
  {7 X1 T1 Z( `$ U5 k1 F        CALL SendCmd
$ F3 l( R; u* X. [        CALL WaitWhileBusy- J3 {& u$ C3 q' J
8 G- K0 d) N; c4 P1 Z" {( s
       // 检查是否还出错: V6 G- }6 `; `" K" b% i0 _: S
       MOV  DX, dwBaseAddress
# A  o( E. M, N( Q        ADD  DX, 7
1 W1 K9 S( Q$ q$ e" Q        in   AL, DX
& E% n' x" W6 T6 [: z        TEST AL, btBit00
4 E5 i* B, i& X        JZ   RetrieveInfo   // 没有错误时则读数据
+ \3 T# W& Q! f" f/ Q/ U  w" P        JMP  LeaveRing0     // 如果还是出错,直接返回$ ^7 a5 z0 K& Y
4 a4 G( t/ ]( C+ G* P; i2 Y) m
       // 读取数据
1 f  C: w4 e# {. h4 \7 a1 V        RetrieveInfo:; R/ Q" o5 C3 P7 D9 X& B5 H( l

# ~* B5 A* P/ i2 E4 ]        LEA  EDI, wOutDataBuf
2 v2 f; F4 y" }& t6 {+ S. G# `        MOV  ECX, 256& K9 [# e' K0 X2 y' h
       MOV  DX, dwBaseAddress
& _/ U/ ]6 b: x4 G7 E0 z        CLD
' E! K0 }0 c- }) A! U8 E; T  K' _! S- L7 I
       REP  INSW( B7 Y/ V2 c6 e- \5 [& j
4 p9 V% g: G% @: P, A! c% N
       // 退出Ring0代码
  d3 y: w$ A: N7 m; J! n+ B        LeaveRing0:
+ O( D, x- w, v0 L; q& O; X6 V5 P% @6 A8 K3 ^+ J
       POPAD% C9 r, F  W; E0 T# l* J) X
       IRETD
9 @7 M0 j/ s+ l, _2 q/ F
& ?/ }6 V2 B* A6 D' k        // 激活Ring0代码
: e+ U' Y8 t2 t        EnterRing0:9 o' ~. }, D- S$ r: ?
( l- d. l9 v( `  V. j$ e& G
       // 修改中断门
: g, T# S' q: p0 O' C( B1 |  C        SIDT FWORD PTR btIDTR14 P8 {8 {+ f! }/ t: T# ]& q
       MOV EAX, DWORD PTR btIDTR1 + 02h# P; F7 |  M7 Q9 I: E
       ADD EAX, nHookExceptionNo * 08h + 04h' c" I3 R6 j% d3 L! r3 t- Y
       CLI
. V/ a( x  T5 N% f; @2 i7 }4 h
, O( M' e8 W1 R  ]6 n2 u        // 保存原异常处理例程入口5 ?4 L, \$ ~. F+ A
       MOV ECX, DWORD PTR [EAX]8 a. V  j  C$ F9 H# f/ n3 f: ^
       MOV CX, WORD PTR [EAX-04h]5 @$ w3 z$ k& A' h7 t
       MOV dwOldExceptionHook, ECX
5 `6 d8 ~. c4 _6 Q& R
. T( e5 ]* b9 ?( K  Y8 }* H% t        // 指定新入口
5 v& [7 s. ^) f2 o8 ]        LEA EBX, Ring0Proc
% C5 J! s: s' {8 ~        MOV WORD PTR [EAX-04h],BX' ]% n9 U  |, G6 T, H0 c9 S
       SHR EBX, 10h/ i1 q% d! z% Z7 o; R+ I( z; k9 b! X
       MOV WORD PTR[EAX+02h], BX( p  G: x& L4 d. e/ s
" ?9 H, Q+ z, ], O2 T
       // 激活Ring0代码
- f( `0 R2 E: a; m4 j! u/ H4 \        INT nHookExceptionNo5 w6 }2 W9 z  B6 ?2 x/ r+ E# o  |

2 M* z2 a5 r$ n) k+ M        // 复原入口
  V9 h; J5 o9 X1 ?" D        MOV ECX,dwOldExceptionHook
2 J1 G6 C  b' [( U/ b( l* L        MOV WORD PTR[EAX-04h], CX' e; i2 ]- a8 C6 Q% x& S, U; n
       SHR ECX,10h
6 S, O2 Q5 n) b7 K* H; V7 r        MOV WORD PTR[EAX+02h], CX) G( {" Y7 U9 i8 w' E  v
       STI, f* W; _3 G& w# w, O3 T
   }
' g1 B) A1 B& H- f    if(!bIsFirst)0 M+ l4 H+ K7 F- W
   {. p$ t( o, u( @0 g& F+ I
       bIsIDEExist  = (bool)btIsIDEExist;
3 G. N3 o5 h" j; a' {/ W8 u; `) b        bIsDiskExist = (bool)btIsDiskExist;
! p* ]$ v! r/ t0 @: @; H5 L: i$ T$ W        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));) f4 ]! J# c6 k3 ?1 f
   }7 p  G+ |" g  _6 T0 d0 ~
}  p% _3 l; p6 ]  w5 |1 h
//---------------------------------------------------------------------------" f1 w" [. Z; g* n! F" B# L
// 调用方法:% F7 U8 s3 _7 l3 K2 L: n; D
void __fastcall TForm1::Button1Click(TObject *Sender)/ r. Q; n8 C- \
{9 F9 }2 G0 R: V. L4 f
   ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);( F( S% x# b) B0 u/ V1 _  Y
}
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|宁德市腾云网络科技有限公司 ( 闽ICP备2022007940号-5|闽公网安备 35092202000206号 )

GMT+8, 2025-6-19 22:35 , Processed in 0.037404 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表