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

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

[复制链接]
发表于 2005-5-30 19:22:36 | 显示全部楼层 |阅读模式
  #include <WinIOCtl.h># K: e2 Q  G% y* X) H
#include <stdio.h>) c( s' A6 n2 N: ?0 \- O; n+ t

( B, y& I. H- b" Q/ `#pragma inline2 W  M6 E9 e" i/ I1 P' B" j
//---------------------------------------------------------------------------
6 B* Y2 H) R$ W) }% Z7 I: H6 Z// IDE NT/2000/XP专用变量
8 X5 Y" l# n2 V( o: Q  @- g#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS' q$ G4 c* H/ L0 c: M" l, S% j
#define DFP_GET_VERSION         SMART_GET_VERSION
6 d8 u/ V4 W9 x5 M& k% e#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND- l3 K  P# x- z  p7 ~3 B
#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA5 s. w& J* Q- f+ ^& A! K7 X
* m# G$ X3 q: `. m5 z
const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令% [; n; S3 v/ M$ K- U2 E! a8 m
const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
. X3 A) D" X: d7 Q3 h( t: \! C+ B
const int MAX_IDE_DRIVES = 4;
3 Q% h! b$ I! E1 w* F
( D3 U$ U1 Y! d" K% N/ y1 c// SCSI专用变量6 L& p0 e& G" e' h: D
const DWORD FILE_DEVICE_SCSI             = 0x0000001B;
3 A+ B  X6 K1 Q+ i  T% y8 y9 E4 cconst DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
) Q1 n! i+ O, P$ Mconst DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition. ^3 K3 e& k/ g# G4 x
const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;1 B- }8 U5 J3 G: a1 V: z/ h" l7 v9 Q
! S0 O* K/ H  o) r' S( ^1 G
typedef struct _SRB_IO_CONTROL% H1 |" q$ j5 _* b. K
{
# l1 I! o# Q  g1 L( d    ULONG HeaderLength;' V- Z2 h% @. K4 I, ^
   UCHAR Signature[8];( a% x* x7 |' b; V5 D) m
   ULONG Timeout;0 x# o1 z* r4 R0 Y. ?
   ULONG ControlCode;# t+ x1 h; [) I% N8 R; [
   ULONG ReturnCode;. y+ |! S% I' t! P* f  c7 d# E
   ULONG Length;3 A. i- y3 `( K& j; }1 q0 L
}SRB_IO_CONTROL, *PSRB_IO_CONTROL;3 u: |5 ?; o# r8 H. P

1 c3 R7 r; m1 _# c( r( Z7 F5 u// 读取的主函数- a" {4 ]* k5 C& V
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
, \5 c- p$ a$ }# D, R
, F0 E: J3 {4 s* r1 _% t4 z" [// 辅助函数6 S# g. U$ }9 I9 `, M$ ^
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);% _. s, V* l' l- t5 [; H
// NT/2000/XP函数2 h: ], n& W: Y" d( x7 E8 K1 _
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
  J# [2 z6 \  A9 S# K4 Xbool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
& \+ k8 i7 a/ Y" N+ s. E        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
+ @) ~( [/ }( Z" I6 W        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
6 \2 C2 {0 P1 ^8 g" Y0 w// Windows 9X函数
4 I2 I3 j0 U4 h( `7 j: Bvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);
% P; c, O' q; I# |. |void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,' F9 b0 c' F& v: s& x% Z# f  i
       BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);$ l4 @1 `3 |% A% Z& l

3 K0 ~( I. _. b3 u6 g// SCSI读取函数(for NT/2000/XP)
8 x9 b4 X0 H  iString __fastcall ReadIDEDriveAsScsiDriveOnNT();3 L, S; v9 R  @5 ]- H: p
//---------------------------------------------------------------------------
! c5 l9 R2 {: a% f2 u// ReadPhysicalDrive
# G' }- t. x9 g% e" |; Ovoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
/ k, {  `& m1 n1 F6 P0 M{& U! X' h; D! h5 s' D0 G, _
   switch(Win32Platform)
. d& ], b% Y0 ?. U/ @5 `/ j    {
! h/ |: _7 [* @! P        case VER_PLATFORM_WIN32_WINDOWS:% a1 K4 |9 G& P
           ReadPhysicalDriveOnW9X(pSerList, pModeList);
$ @) P. T3 x4 J4 ^- J& A4 k            break;
, g, V) M2 b' T+ u. h        case VER_PLATFORM_WIN32_NT:
9 J0 f0 g# [/ `  h; _- t# T            ReadPhysicalDriveOnNT(pSerList, pModeList);' I, l" p% R& S
           break;
  s" Z! p; A( w% K8 d$ K( M        default:% E- c* d4 F+ K' m* p
           break;
! ^/ S! B: l) O# U- H    }
0 z& f' Z. C$ i: E3 F8 h}7 ?2 `* {3 i' Y2 N/ Y
//---------------------------------------------------------------------------
1 ]1 \6 g+ e  q' N) H1 w// ConvertToString
1 l! s$ ~: r& ?2 B- S: l1 Schar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)9 J# |. Z) p; Q4 u7 [
{
# J& x$ G) w; h    static char szResBuf[1024];2 U. ]- U5 K7 C, h7 b! q
   int nIndex = 0;
( J  B; o* R- D  ~8 i% S3 c: A    int nPosition = 0;
5 ^; N7 @/ [- `2 W
# J7 q) o7 T; I    // Each integer has two characters stored in it backwards
8 h- [! q0 K- O' W" E" c5 J/ d7 O: l    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)8 v7 r# @) K3 I8 i
   {2 F5 I3 N. [2 M. s: @1 K- r
       // Get high BYTE for 1st character
4 f3 m" Y9 _% i        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
' l$ X4 Y" f$ Z8 s9 a( N2 M$ ?        nPosition++;7 m0 ?* L4 A: A  |
6 l( u, ~; O* t/ ]
       // Get low BYTE for 2nd character) I" P  v/ v; V  c, J
       szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
/ k; [3 ^1 M. b' ]) k        nPosition++;: X; @0 `; m' A4 k& x- ^0 m9 g
   }7 R7 [: o9 q! b+ M& Q

7 \& g( {( n' ^6 B5 X( n: U    // End the string' l/ x; d! ]" Y4 c* d
   szResBuf[nPosition] = '\0';
$ C. y9 m7 ~3 j! u7 l3 Q; ?. ?
2 ]0 [6 \" F9 c5 ]    // Cut off the trailing blanks# v  A7 I3 E; }
   for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)+ i, f$ R$ o: q# c* w
       szResBuf[nIndex] = '\0';
' h" U( y+ `$ o& u, d' @1 y
2 H7 J# G1 _5 H0 B& m    return szResBuf;* C' @& r% X4 v. T; l- D0 B( c& T
}
4 ^  d; Q9 c; o0 U' }3 k6 U# R4 t//---------------------------------------------------------------------------
+ r6 v6 T8 X& N9 v2 n" z( [// Winndows NT4/2000/XP 代码7 r! y: o- @2 L+ i, @$ a
//---------------------------------------------------------------------------- c8 F- D* V4 J' m2 V
// ReadPhysicalDriveOnNT
5 n7 |8 l1 m( W$ H5 xvoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)) u: Z8 d' |" U" F
{
2 o9 G1 D7 [$ C+ c    // 输出参数9 D* |: Z6 i3 E- o0 ~% O
   BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
- Q) D& S5 r0 f5 [) Y1 O7 Q/ }6 K0 c
   for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)  w: R0 \% o# `6 F: V
   {2 J7 J' A6 Z( K- O& e4 k
       HANDLE hPhysicalDriveIOCTL;
: K- q, n+ y$ T" p; N        char szDriveName[32];$ D/ P& Z) a) C% m, V6 v6 |2 t
% `  j' s7 X/ f6 t
       sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);% l3 c  v7 p. G2 I# j5 @% C
       hPhysicalDriveIOCTL = CreateFile(szDriveName,/ h) [$ \1 ~" l( {+ f' |
                       GENERIC_READ | GENERIC_WRITE,* H, M) m  }; a% v% X! {
                       FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
' O5 M6 m2 W+ r4 R3 S) Y$ R                        OPEN_EXISTING, 0, NULL);
" m$ b$ K5 M0 C2 C# U  E; N1 _& J6 p- C1 _( D8 }
       if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE). v$ u& F6 c" Z: ~  I% ]6 n
       {2 F/ D5 `" ~2 q
           DWORD dwBytesReturned = 0;/ k/ ^% t! F- @6 r8 X' w
           GETVERSIONOUTPARAMS gvopVersionParams;% Q0 E) r: C) ?) }% i& ?

0 M+ {" J# n- s1 [" \' x0 G6 J! U            // Get the version, etc of PhysicalDrive IOCTL: u/ v# ?* z" k# s" Y3 d
           ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));+ J/ H# g% P9 ~! I8 |+ b3 e' W
# w6 G4 `: w& j
           if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
% G3 T+ J. E/ ^9 [7 N) q7 O                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),! l$ q  y% j0 h! \5 r# `) e
                   &dwBytesReturned, NULL))
3 W; p% [3 k8 t1 v! {: i3 d            {
8 ~0 r; w8 q$ z9 c                continue;, j. F; \3 @+ d) |1 Q3 v$ p
           }
* m' b1 }; N( [5 l* ~& ?+ O' S) i3 J0 y; f
           if(gvopVersionParams.bIDEDeviceMap > 0)
, l+ {; c* y; s7 t. R1 [) E, u8 \, F            {, d9 }% {- r9 o- ]# r/ g8 p
               // IDE or ATAPI IDENTIFY cmd
! W4 a5 ]- ?/ N/ E2 W, k                BYTE btIDCmd = 0;% ?$ z3 o+ I0 u! F9 M! }6 [6 B! J. i
               SENDCMDINPARAMS InParams;5 }, _* t! A6 [/ {) Q
               // Now, get the ID sector for all IDE devices in the system., p; K1 L3 e+ ]0 l9 c
               // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,( Z, z9 t6 d' k/ K- N' s3 _8 ~
               // otherwise use the IDE_ATA_IDENTIFY command( o( s. }& w% W, ~. d5 ^! P* V
               // 具体所得结果请参考头文件中的说明) F1 q% Q- @- J1 s, {& h: g& A
               btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?& H# ?1 ~, R/ o* p7 c- g: b) W, U
                       IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;1 D, q) _+ z8 b$ H  |0 S" z
               ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));" v* F+ g0 d+ u  V' @
               ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
# G4 t3 ^' h' w4 S0 V$ ~" ~; J* b- R3 V; v$ n( ]
               if(DoIdentify(hPhysicalDriveIOCTL,
( A/ g+ l. K9 W+ \/ [; A                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,+ a& ~  w3 p5 f5 T
                    (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))2 Y0 u2 V' j0 \' F
               {
+ o! Z9 \% S3 r5 G! N+ R" j$ ~3 E                    DWORD dwDiskData[256];
" I! c! i5 s1 e# U- ^                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件# Q) j" t' \5 E- M. e
                   char szSerialNumber[21];+ E( i5 t# O& `
                   char szModelNumber[41];
3 k1 p' P) R9 r
( {2 M- R, X$ ^! _1 P$ Y1 ~                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
/ M1 \4 H* r7 {: L  z                    for(int i=0; i < 256; i++)
3 `* H, P% q# p( p' L                        dwDiskData = pIDSector;( e8 d3 c& i% q; _& K; b  w
                   // 取系列号& D; m: v+ p9 r$ J' V6 H" ~( w: M& R
                   ZeroMemory(szSerialNumber, sizeof(szSerialNumber));6 u/ A* x. j9 q5 @( N6 J
                   strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
2 g. e6 T1 @3 v& N8 b% S4 j6 w$ i$ m% b1 p1 A2 }3 R6 I
                   // 取模型号
( N! W3 Q! ~( Y" f  V                    ZeroMemory(szModelNumber, sizeof(szModelNumber));
& J6 n) a" z! @* Q- x& C                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));( g0 s1 l) a7 S5 P

: p: _; R. N- o4 }                    pSerList->Add(szSerialNumber);0 ^# W/ Y. m# z7 e3 N$ X
                   pModeList->Add(szModelNumber);
5 N. d& |' l% u1 w# b& ~* Y                }
$ h7 \; t$ Z3 T# s$ r            }
, m. R3 n6 o+ M8 [% P            CloseHandle (hPhysicalDriveIOCTL);2 w4 `: s, C/ H! |! ^; X
       }
! x+ p+ ?& e: B) {1 c    }: k- C3 C" \, Z5 H' F
}
8 r* v, R: k/ a//---------------------------------------------------------------------------0 B% ^5 a: q% z/ ?& W
// DoIdentify
7 S+ w/ Y! V; V2 Abool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,) H5 d" @! x2 J% _  p) ]' r; h7 \% i
             PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
  |' B$ T# F- ]- Y+ K1 i5 |4 `4 C              PDWORD pdwBytesReturned)1 ?* e) H6 ]& Y, x9 m7 T7 w
{; o( G6 P$ q+ g. S
   // Set up data structures for IDENTIFY command.
% T2 @- N% A  c    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
8 `( Q1 P3 ^0 h$ m( |    pSCIP->irDriveRegs.bFeaturesReg = 0;
' {7 `8 \7 T: ?- j    pSCIP->irDriveRegs.bSectorCountReg  = 1;
0 @5 U: C, }0 k5 V3 s    pSCIP->irDriveRegs.bSectorNumberReg = 1;
6 p) k0 `) b. b$ F    pSCIP->irDriveRegs.bCylLowReg  = 0;
! o9 w$ z0 ^9 [1 f% E% N    pSCIP->irDriveRegs.bCylHighReg = 0;
3 M) G; L8 k9 i. m2 u4 w0 N* _6 [0 p" b0 {% Y3 @1 o
   // Compute the drive number.(主盘和从盘所对应的值是不一样的)
8 Q- M! W8 |; `9 v: i    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;- b8 D3 |3 w) q4 t- [% ^( L

9 ?5 F) U$ V, ~* {1 D' P2 T. M; a    // The command can either be IDE identify or ATAPI identify.8 g# }" {- q* |3 N* ^1 X; e" o
   pSCIP->irDriveRegs.bCommandReg = btIDCmd;
3 ?, S2 ?* F; N  l1 h* h" P6 ]    pSCIP->bDriveNumber = btDriveNum;
  Z6 Q; s% M! o1 O  B( W, R7 p& ]    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;+ v5 S! W  t5 u7 F# z0 u( o5 ~) g
* ~8 ]4 _7 }) ^- c; x0 Z
   return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,7 Z1 y6 Q8 I# {% e* p) N
          (LPVOID)pSCIP,
4 K: S0 Y' t* G& Q           sizeof(SENDCMDINPARAMS) - 1,
+ u/ Z$ h, @" j0 x1 I           (LPVOID)pSCOP,
  i5 J( F9 h# Q! u. f# D5 K           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,8 V1 @1 |% F* l6 I6 Z
          pdwBytesReturned, NULL);
# U6 K/ H& A: N" v}/ ^4 Z8 K1 t, Q) x2 j8 W7 a1 a4 _
//---------------------------------------------------------------------------' e! \' Y) ]% Q& V' u1 m, u! T
// Windows 95/98/ME 代码
$ ~+ l9 h( X" Z//---------------------------------------------------------------------------# ^) U) T6 @' G" p, m4 s
// ReadPhysicalDriveOnW9X
! `3 y' s& ~  S; k2 O2 q3 H) B. Tvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)7 F6 @  n. t9 U/ O2 q7 a& j% h' I
{9 U! w: F5 Y& a4 G' g' T
   WORD wOutData[256];
6 R; ?$ I! A- P2 b$ }, l/ t2 S    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
* w; T  @0 e3 b# q+ L
4 W" t. l% X& k3 M0 \    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。/ P) M: ~2 ]5 R- z7 X0 b8 Q8 O8 c
   // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
& l2 O( P! ^5 R8 _+ i5 Y    // 避免蓝屏的出现。(期待高人能指出原因)
2 q6 C8 g+ e$ u  C6 ?8 H1 A  S( g    for(int nDrive = 0; nDrive < 8; nDrive++)7 D" q, b# d* ~& Q& f" M: D0 S7 s* `
   {
5 J+ }5 E' ]7 _% ~1 C        WORD dwBaseAddress;& e. a' V& P4 N: e
       BYTE btMasterSlave;         // Master Or Slave
' m0 Y. U7 T3 }' n# p+ U0 T  A( m7 Y, z        bool bIsIDEExist;
0 ]! R, r$ x. @/ a/ X0 S- o5 I  v        bool IsDiskExist;
6 E  c  _% s+ G, l- M7 J  l/ R8 Y; y1 j; A" m8 ]
       switch(nDrive / 2)
7 G, f5 c, H0 k3 Q% V( ?        {8 r) P8 ?: N/ t; X
           case 0: dwBaseAddress = 0x01F0; break;
' G+ y" J' _$ p. c            case 1: dwBaseAddress = 0x0170; break;& |9 q: i2 f- B/ \) b
           case 2: dwBaseAddress = 0x01E8; break;
2 Y. T3 y6 b6 R            case 3: dwBaseAddress = 0x0168; break;
! O4 L4 X7 t8 ^% S        }
. d* K1 V6 p9 r! ?2 ]) _! ^7 \- m0 f/ J4 r4 j9 I- `
       btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);) \6 f; x- G. b' b& k- C; X
& K6 V7 P; j0 `& b, P. k9 y. ^) T
       // 进入Ring0
- q  o1 z, N  s) ~3 |        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,. ^2 Y- T$ [3 [. D- b
               bIsIDEExist, IsDiskExist, wOutData);
3 G  L( t2 n$ C$ W7 D$ @( _    }
& u# V: \$ q% Y7 N7 o( }' Q+ y; Z# I# ^' S  a- Q, k
   // 开始读取0 e7 J3 J/ T: _% L2 r
   for(int nDrive = 0; nDrive < 8; nDrive++)- ^/ M  W2 b2 e* i4 q
   {
  Y- f- F: `0 w! f4 N        WORD dwBaseAddress;6 Y8 b7 |# S$ f" S- g, u2 S
       BYTE btMasterSlave;         // Master Or Slave2 ]- v4 }5 x* l+ K4 b+ A1 ?4 G: P' Q
       bool bIsIDEExist;
, `/ C2 D' z% f: i/ l        bool bIsDiskExist;
" D0 X9 v  |* ?# W        switch(nDrive / 2)
8 L0 X9 S3 l. B' M9 B8 L        {& P$ ~: i5 }2 P6 {& ?* S
           case 0: dwBaseAddress = 0x01F0; break;( Y( k7 g' c* c- y- C
           case 1: dwBaseAddress = 0x0170; break;
5 p! W( b3 z0 _! q, B            case 2: dwBaseAddress = 0x01E8; break;
) {2 J6 H7 J. k7 e! F- Q# f            case 3: dwBaseAddress = 0x0168; break;: ^! L: b1 R. f' N- j, r  @
       }
& o; S( B: O/ P2 v1 S+ Z- n! j# x8 b
       btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
4 A% v9 M! K0 _( g! m: ?" L+ l% K# f' Y2 S% j  T3 C6 x/ p
       // 进入Ring0. `6 {/ o3 ]( @0 @( E* e
       bIsIDEExist  = false;
) u9 g6 E5 J: l7 @% O, k        bIsDiskExist = false;/ n# m  `8 V  h8 V8 u9 H9 ]. f+ V
       ZeroMemory(wOutData, sizeof(wOutData));
" V2 y% }( Z4 t% X/ m$ w" l" \; B0 Z- P! x& k
       ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,3 q% q$ n9 f# K" |
               bIsIDEExist, bIsDiskExist, wOutData);9 D8 y( m" @- D" l3 z* ]

1 o0 T$ E( Y% T2 }5 w+ R, Y& y        if(bIsIDEExist && bIsDiskExist)
# F8 m, y9 e) g, k* G4 ]2 D        {( K. j$ H4 G; ]! O
           DWORD dwDiskData[256];
, C' C2 K3 q$ `! i7 L            char  szSerialNumber[21];: `, H0 j) M# \& B3 h* S
           char  szModelNumber[41];9 A0 a4 _! N: R! u2 H7 c! @& B/ ]
7 J2 {: p3 ]0 m. Z. N
           for(int k=0; k < 256; k++): o6 t/ j, Y, S
               dwDiskData[k] = wOutData[k];2 ~$ F$ N! E5 \+ q

7 X2 Z! j! A3 j            // 取系列号# h, n# Q, B( x% t2 F" X4 [
           ZeroMemory(szSerialNumber, sizeof(szSerialNumber));* |  ]7 u5 a  X
           strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));' S/ g& a' D9 m  ?9 x* i& [  a& O
: r& _3 |" o+ I0 h8 t+ H
           // 取模型号
$ y4 s# T6 m( V, v  {& u            ZeroMemory(szModelNumber, sizeof(szModelNumber));3 H% j  X. P# \8 Z0 [3 ~+ o
           strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));( d, ~2 f: K3 }$ k) v
1 F! j4 m9 j+ R# l: S+ w
           pSerList->Add(szSerialNumber);
( @- A" s! s# l- b6 S) Q2 P            pModeList->Add(szModelNumber);  V$ D! a9 E+ _/ u
       }- }! Y  n& c: ]9 |. b, ~, z4 S5 M
   }4 `2 X0 r+ \" @! D5 H3 ?" |9 C
   SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);  ^$ }$ i. Q6 |8 [& P7 f
}
3 `: V$ a2 I3 U( T6 a$ i//---------------------------------------------------------------------------! t0 g. ^% @5 r: w# j) ~
// ReadPhysicalDriveOnW9X_Ring0()3 f' o8 e* q+ g1 V: p7 h) I
//
6 U1 {2 S& e& ?7 W, z7 m// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
# _5 U( K/ V( K7 T, `( S9 B& Z' r// btMasterSlave = Master(0xA0) Or Slave(0xB0)0 @4 w% b9 |. c' ^
//---------------------------------------------------------------------------
; h+ v7 M5 Q! ^( R, a6 svoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,( b+ W' F3 [) `
       BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)( R0 O4 C( _( t% ?; M4 T# j
{2 K2 j' M/ g: c- G+ s' a. x) s
   BYTE  btIDTR1[6];
+ }! l" R# u% j3 G    DWORD dwOldExceptionHook;
7 ^* ]# f/ s) X  m: Y7 C    const int nHookExceptionNo = 5;
/ z0 }8 F( f9 B. d
0 V4 R1 q4 `* q4 C/ l6 ?0 _5 i8 `/ U    BYTE  btIsIDEExist = 0;
4 w) X9 X. P* I# A3 b9 f0 N    BYTE  btIsDiskExist = 0;& W& q  ?" }6 J$ m" ~/ ^
   WORD  wOutDataBuf[256];  ]8 p. U3 c: {$ P) `% ~

. i/ h: v, S7 f    BYTE  btIsFirst = (BYTE)bIsFirst;! r0 E  V: G1 U; H, j
# {+ S, J( ~' O' a% H, {
   const BYTE btBit00 = 0x01;" N8 H6 S+ b# \' T. P3 |
   // const BYTE btBit02 = 0x04;
/ N  k* p9 w5 v! r$ @$ x6 w    const BYTE btBit06 = 0x40;$ h8 S" \, W* t0 u. M
   const BYTE btBit07 = 0x80;
4 P* Y" t! S$ f! Y% p7 `* o* u9 N    // const BYTE btERR  = btBit00;) p$ T, ]) m3 ]3 q1 a
   const BYTE btBusy = btBit07;# W5 u$ }) a2 B3 |: v
   const BYTE btAtaCmd   = 0xEC;' r/ }5 m" [) ^2 x3 |- R9 f
   const BYTE btAtapiCmd = 0xA1;
. q8 I$ C$ |* E- e9 _, r. v7 r' s) p- \
   __asm
  ~+ n; I) E3 H- d: w% p    {; |" i/ M9 w" @1 \& o  {8 G
       // 必须先执行这条语句
/ S$ r- |1 \# {; s        JMP EnterRing0- M! u- _. Q" s: y& |# a1 d
! [3 o7 o, E2 |$ f
       // 定义过程1 }2 x4 x3 r! b( V/ V
       // 等待IDE设备直到其不为忙为止
0 e0 l& x9 v1 P8 T4 P0 q        WaitWhileBusy proc& }: C3 {0 \5 U

- K  P6 H7 S" q! h4 ]5 |        MOV  EBX, 100000
  K. C, @( |* w' V# O! W2 Z" ?& k        MOV  DX, dwBaseAddress- W" c" i2 u* ^& q5 z" I. x
       ADD  DX, 76 @5 G* Z0 T2 E* ~; o7 A: l
0 g% V. M8 z; J: d; \6 R
       LoopWhileBusy:0 K8 q) [! w3 Q. b! e2 B
& m) Q* _4 L/ D1 h5 k: N5 p
       DEC  EBX
+ Z$ s$ i/ G; x5 }        CMP  EBX, 0
) g( {5 ^' A) ~3 v2 \        JZ   Timeout
' r- a# l5 b: m; ]" }$ _        in   AL, DX
3 q& P& t; N5 s/ W4 L- c4 x        TEST AL, btBusy* S$ }+ o8 o2 [) h# X9 L. j4 n
       JNZ  LoopWhileBusy
0 {7 j& \: K8 V# V. ^8 @; }        JMP  DriveReady
4 `! r( }; N3 w: n+ F- f+ W
7 ^( _4 U! l; v        // 超时,直接退出
$ h0 o- w& O* F6 y& B$ ^        Timeout:7 l5 m0 ~! ~" L- @$ b
       JMP  LeaveRing0
, x9 a* j- Z2 s" j, ~, E        DriveReady:
0 q' o3 F2 j4 d9 |( B# K" j        RET5 N( I! q& H+ P- V3 B2 K
       ENDP   // End of WaitWhileBusy Procedure
' y$ R$ `. _- N( K  w: |% z. [+ K( e6 x
       // 设置主盘和从盘标志9 o/ n& z% \+ z1 r+ s/ j, O
       SelectDevice proc
! }5 \+ P8 A% y, r# |0 L+ P
/ I/ P( `" ~! Z! g' ]7 q- Q/ E        MOV  DX, dwBaseAddress( I0 m8 C! C( D+ P3 r8 m
       ADD  DX, 6
/ ]$ D8 n8 o/ ]/ q3 w        MOV  AL, btMasterSlave) T7 y- }; v- B1 A" x3 U- z* P
) u; P2 A! X1 q0 S6 `1 r6 E
       out  DX, AL$ E7 Q* G* R! i& H& ~( L  G
       RET  v  e* z) O! S3 {- I7 m% ?) y& v0 F$ v
& W5 a& X' c. q) p; U) Y4 n+ ]
       ENDP  // End of SelectDevice Procedure9 x9 s( o- L* M6 c- T6 z. o" m
' S# A  O6 g: m9 }0 f1 h* ?
       // 向IDE设备发送存取指令* ]7 \6 [8 c- m* Z+ R
       SendCmd proc
0 Z; f$ x0 W1 r# C* ]' G$ }
7 ?  @& y8 X2 P        MOV DX, dwBaseAddress
- [. G- e6 x( \4 a( h        ADD DX, 7
/ z) I" O7 E2 i! q$ O& i        MOV AL, BL // BL是主从盘标识,在过程外设置3 J. v  _1 Q( `$ g$ }
       out DX, AL( e# u$ t9 m( Y
       RET) K+ v$ c) j5 m+ [+ i% X3 f
       ENDP  // End of SendCmd Procedure* F( }. r3 o" s) B% Q
' N( A9 R4 R' _4 [* p6 {' v
       // Ring0代码
  |% m- d# h# S+ }8 G, _+ A        Ring0Proc:0 ^3 h; x) F9 b1 l  @8 I2 o+ t. Q
       PUSHAD
- o0 f1 s# }6 w  `2 P        // 查询IDE设备是否存在/ f$ `3 l5 T8 G; _+ Y" }  W
       MOV DX, dwBaseAddress
: B1 d0 B+ S% P1 u+ L% U/ u  a        ADD DX, 7
( z1 M( ?% O5 P- M  L* m        in  AL,DX" Y. H0 X* o; v7 W; A2 [

  b4 T$ U- ?' E( T' B- Z        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回# R* w6 M4 g% ]( g! s5 k& T
       CMP AL,0xFF6 }% F+ V2 y# E9 g. M$ ]' I
       JZ  LeaveRing04 J2 l& j: E! ~8 G, J) w
       CMP AL, 0x7F
- `" Q! _3 X9 H( [* u# F) ]+ x        JZ  LeaveRing0
/ z8 S" @' d( f  K) s% O- D7 V- }7 n/ Q$ f# V" b7 K
       // 设置IDE设备存在标志' y8 w. m/ e& l" \1 C- i
       MOV btIsIDEExist, 1
9 ~5 X$ I! B5 y4 {- I
$ ]3 G: G9 T1 k- f; i        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
& ~# l/ C1 E/ \3 K. E        CALL WaitWhileBusy3 T0 k4 k# F5 C7 \9 M  e- R% V
       CALL SelectDevice
# e8 z3 f7 O. M2 v' \4 |/ x8 C/ f. t) k
       // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
: V( `. ~' ~; b0 N        CMP  btIsFirst, 1# ]8 m) n0 W3 Y( F
       JZ   LeaveRing0$ u- _8 R7 h. A9 ]& Y! |2 O5 `% {

# Z. i) X, {* Q% d' n4 x, k) R        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
, F$ w; ]: p" e$ ]3 q. b        CALL WaitWhileBusy0 x* o. H3 T, ], m! b9 V

9 e9 j" o6 }5 t3 a, E  N$ ^4 J1 G& d        // AL的值等于cBit06时,不存在驱动器,直接返回( ]! b* d1 p+ |+ ~8 A+ K
       TEST AL, btBit06# v8 S$ t) W" R
       JZ   LeaveRing0
: A5 k% u# n2 n4 C# U
% C/ G; w: H0 l; Y9 m1 U        // 设置驱动器存在标志
; q2 v. V1 X7 l$ C# t' j/ O        MOV  btIsDiskExist, 1* D5 s7 F7 O! d; E0 W0 d
6 f8 H1 D# p  t7 A* {' U! |
       // 发送存取端口命令
# d$ }$ P3 l, `9 l        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,8 v" H3 z8 C8 \& O. q: k
       // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
$ k& i" m4 D, E- ~; L$ P" w0 Q& J4 M        CALL WaitWhileBusy. d2 P2 \) s0 x
       CALL SelectDevice    // 设置主从盘标识
3 @+ ^5 X+ V# b( m2 u        MOV  BL, btAtaCmd      // 发送读取命令
, u9 U: D, u3 Z        CALL SendCmd
; w/ J7 n* x/ ?, P5 h        CALL WaitWhileBusy
+ s7 _* J- B& B2 B( J* C
6 T/ {" @; \" a8 G8 ^' G% t) g        // 检查是否出错# G: b* g6 a" r# \0 o7 c1 B! f
       MOV  DX, dwBaseAddress
( i- V: ]! T% N. r/ h, f        ADD  DX, 7
: t: ^+ P; ?( m8 Q; i7 b/ W% h8 F3 w7 l1 M. a1 f3 ]
       in   AL, DX, H2 I5 [9 `2 n3 R( d/ \& w

6 D- Z- k* R$ `0 \1 f1 Z' U  m        TEST AL, btBit00
) H/ y: A! `+ j) P        JZ   RetrieveInfo   // 没有错误时则读数据' }* C0 {+ A8 {% ?
9 ]" c2 V% e  l" E3 j, q9 J5 r0 n
       // 如果出错,则进一步尝试使用ATAPI设备命令
+ G7 J. R6 y3 O$ z; L        CALL WaitWhileBusy
7 ]- J7 R4 N8 M5 _7 T! G        CALL SelectDevice, [* c! a  n% c; L6 p9 n0 G- R2 `# B& l
       MOV  BL, btAtapiCmd, c; ?5 Z/ r7 ^; g8 r" @8 `8 g* d
       CALL SendCmd
* ^, f: L5 c1 \        CALL WaitWhileBusy. N1 i% N  u. m# _

8 u7 q( o; r0 T- I" F4 V8 f        // 检查是否还出错
/ T' w, t1 _+ p1 L8 C        MOV  DX, dwBaseAddress% g/ @. e; n! a/ K: u- r
       ADD  DX, 75 c. o" g% @6 I) p& e
       in   AL, DX
1 N- z9 o5 U  F        TEST AL, btBit003 K! i5 _2 X# O
       JZ   RetrieveInfo   // 没有错误时则读数据% m; u, {, W1 G  R' ]5 b- Z
       JMP  LeaveRing0     // 如果还是出错,直接返回
9 w) Y2 e. s. a% h4 _# b" S# N% D- e: H- s
       // 读取数据
9 o* c- T' c+ Q7 k        RetrieveInfo:
; Y9 L$ u) Z& C! ~7 ], O0 Y4 o5 K* q
6 t2 g0 n; ?0 \        LEA  EDI, wOutDataBuf; n- G( G& f- z- z, }6 y
       MOV  ECX, 256
  Z% L# X  n7 i$ B% Z        MOV  DX, dwBaseAddress
& B" r2 @/ f( s4 K. _        CLD  K8 T" L! g% ?( k7 V5 b$ _7 e

7 g# ?$ C7 M- ]        REP  INSW
; n# m7 R( v. M! V5 M' W# Y7 d) O! A" e
       // 退出Ring0代码
1 q5 S+ m; L0 S        LeaveRing0:
9 p0 F2 i* j" M. g
) k* v& \6 h5 D! j3 @; K        POPAD3 ~) k8 {5 c3 B3 T  I' O3 k$ M
       IRETD
( i' I' J9 {" e9 R4 [+ m6 S! M: [) b: M5 Y7 F9 r% H6 V
       // 激活Ring0代码9 f4 T4 K& p% p6 R4 l
       EnterRing0:
* ]& Y. P- f: Z1 P, y0 j- E
- t. R3 v, o* G% u  w! Y; b        // 修改中断门. X  m  T$ O& ?' `* {# p4 F+ ^1 M# C
       SIDT FWORD PTR btIDTR1
( ?  Z  H7 D# p( B( Z# r3 [" W! L: o        MOV EAX, DWORD PTR btIDTR1 + 02h# F5 Y9 S  u: e0 W1 \  e! z6 o+ i
       ADD EAX, nHookExceptionNo * 08h + 04h
9 ]& A5 G9 W5 B& o, m        CLI
! s! \$ _4 N2 h% J8 t  q0 M6 z) |$ h6 P. B
       // 保存原异常处理例程入口
8 [% O7 j, v4 u, C  \; Q        MOV ECX, DWORD PTR [EAX]
+ t, N/ k/ x' r- X2 I        MOV CX, WORD PTR [EAX-04h]
3 \7 L, X7 {3 G  L        MOV dwOldExceptionHook, ECX
1 ~& |4 K0 q8 U& n/ t. S/ H/ k
1 o! E6 a* M8 K' s0 x        // 指定新入口
# k7 q5 Z6 B+ [% E        LEA EBX, Ring0Proc
. B" `1 |  Y* |% N7 v+ S! o8 C: D        MOV WORD PTR [EAX-04h],BX- D' s/ J, D7 E' ?& s/ y
       SHR EBX, 10h
3 u$ t6 ]6 U9 |0 S, {        MOV WORD PTR[EAX+02h], BX
1 }" I5 D8 \: \
% B7 ~9 i. ]# [        // 激活Ring0代码6 V6 U5 W% v" ?4 f1 j, X4 T
       INT nHookExceptionNo
. O/ z: T! b6 W8 F1 L
5 y0 M3 `. c% C5 a! m        // 复原入口) W+ l5 I  T% r- m' E( X0 |
       MOV ECX,dwOldExceptionHook9 j) K/ N' G: t0 o1 p& q
       MOV WORD PTR[EAX-04h], CX6 ^8 F) s9 l8 X0 H& G, z
       SHR ECX,10h. c4 p- s) }# _" y) F1 }
       MOV WORD PTR[EAX+02h], CX
) G- g$ _+ N3 }% i( {! L: |, O        STI7 X: K& I3 ]8 ~" t& w* m
   }
1 ?' f+ k" n3 I5 s+ c, o3 j# h' b& S    if(!bIsFirst)
* \( Q  D+ p2 l; J" R/ r  N    {
' K- a$ C4 Q; _+ `3 V7 B. K        bIsIDEExist  = (bool)btIsIDEExist;' V/ [/ t) A% Q, Q& V7 w
       bIsDiskExist = (bool)btIsDiskExist;/ }% p# {) z5 @$ ]; N
       CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
" z5 a. ]. r; ?6 _0 `7 u$ P    }
6 [: v! q3 {. J* ^, L% v5 o. a' D: U}
+ M% I) i: b" J, M5 s, u//---------------------------------------------------------------------------
' s0 w5 {9 `% G! T! @8 H* d// 调用方法:# r3 \) f' D4 ?. f. P; e" E
void __fastcall TForm1::Button1Click(TObject *Sender)
, F, `% @- j3 q5 P- ]{
9 E6 @# T) M$ c# ~, V3 i* w    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
$ H5 Q1 @, G+ Q8 @6 e}
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2025-9-30 13:13 , Processed in 0.038884 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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