找回密码
 注册
搜索
查看: 5113|回复: 1

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

[复制链接]
发表于 2005-8-11 11:42:04 | 显示全部楼层 |阅读模式
  1. #include <WinIOCtl.h>, b; _, n  O) [2 b
  2. #include <stdio.h>
    7 H' w) p3 r) I" W1 S5 o/ p

  3. 5 @  E5 A( i) }' T8 [4 V
  4. #pragma inline5 y3 {( T9 I+ H
  5. //---------------------------------------------------------------------------
    , m6 V8 F! ]7 Q; \5 b' w5 t$ Y
  6. // IDE NT/2000/XP专用变量
    7 ]( _% }  t* R4 p, s# T
  7. #define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS5 S6 g8 t% ~% ~4 x  |9 Z8 w  Y
  8. #define DFP_GET_VERSION         SMART_GET_VERSION
    0 n# I3 E# Y% d2 b) F- B
  9. #define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND6 _' o0 r" c0 M+ ]7 Z  }- k
  10. #define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
      b' ~/ U& J+ h. J
  11. ' g/ U, X: I7 B! y& [
  12. const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令
    3 n% v2 h2 `- b  A3 B7 l
  13. const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
    8 i! e9 B& L4 V4 ]6 f$ a6 N

  14. 7 w/ o' o- `# A/ q% I4 V
  15. const int MAX_IDE_DRIVES = 4;
    $ u1 {% i* ~+ m: g

  16. 9 x0 b8 Z% J! @6 d" `* I7 J
  17. // SCSI专用变量4 J3 \# s# h8 x: v6 X
  18. const DWORD FILE_DEVICE_SCSI             = 0x0000001B;. ]7 s$ {$ ]. \7 B( A6 ~
  19. const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);2 K- w$ Y, R0 A5 ]# |3 G
  20. const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
      {6 J: t3 E- ?2 X& N$ [
  21. const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
    " f: S9 ]. o- b/ T! s, x) |! b4 y

  22. 2 i3 m  F% ^! z6 x
  23. typedef struct _SRB_IO_CONTROL$ C$ t) ^( n0 n/ B7 n1 S2 r' F: p
  24. {: i8 O% y2 y: m6 d. R6 s8 K2 T& V
  25.    ULONG HeaderLength;& \5 r. s9 b1 x" c& A
  26.    UCHAR Signature[8];& v) |' w6 c& V& E* ~, R+ @
  27.    ULONG Timeout;
    # j0 T6 _! ?8 k( ^5 e- Y) u+ W9 }
  28.    ULONG ControlCode;3 m9 `% k* t/ x* g& H/ X. z
  29.    ULONG ReturnCode;0 J& `7 n) @, O' ~6 I6 S& u  {- C0 O- ^
  30.    ULONG Length;( S  ~2 J- l' L' E
  31. }SRB_IO_CONTROL, *PSRB_IO_CONTROL;/ [% T; u4 |; J7 G1 q3 A, v7 b+ k( D, Z

  32. ' W! V( E& w) T+ p  Y3 z$ V
  33. // 读取的主函数
    ) O1 t- n& C) I) \) Y3 |
  34. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);9 V7 F6 B& R# {* o+ o8 Q

  35. $ T1 B, k( [8 B. k5 j* P3 ^% [/ R
  36. // 辅助函数
    ) i  @5 V  Y1 q3 n
  37. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
    5 W5 q  G9 ^8 P( W# n
  38. // NT/2000/XP函数; _; W& T( f2 o- a
  39. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);" L  L1 l: ~$ k: S5 W
  40. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
    ) l- f; x2 D8 V% p1 Y* `% D5 o
  41.        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
    & e+ [; S2 Y3 Q1 |& D& E
  42.        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
    . m* v7 V, G7 u5 g3 J: p4 l
  43. // Windows 9X函数
    % E) a3 m( X. W5 P  I+ q2 N" w/ g# E
  44. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);3 b4 o# ^, z( ?0 F3 O+ V$ d# m
  45. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
    3 e* o. Y6 B4 H6 _' m& \
  46.        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
    % F7 u3 p4 ]! G9 d3 Y" @$ |
  47. " C& v! X1 N) ~2 P9 {4 k
  48. // SCSI读取函数(for NT/2000/XP)
    9 @* t! C2 v6 k: J- K) @# j3 T
  49. String __fastcall ReadIDEDriveAsScsiDriveOnNT();1 b" C+ P6 F& ]: x
  50. //---------------------------------------------------------------------------* R! a7 [, i! I$ n8 t
  51. // ReadPhysicalDrive" q. f* V" N. j5 C% r
  52. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)) r2 c* o( Y; R3 q* i
  53. {) t! K4 @; J& [* y% X" _5 k0 S; N
  54.    switch(Win32Platform)
    6 \( I9 S" M% C/ a# Z
  55.    {
    ' ?  {4 G8 f$ p; b' }
  56.        case VER_PLATFORM_WIN32_WINDOWS:
    # X0 @/ ?% t, B1 D/ |8 u# R  c6 r
  57.            ReadPhysicalDriveOnW9X(pSerList, pModeList);
    8 U3 z3 M/ R9 g8 F, ?0 |: ?
  58.            break;
    7 v: B0 k1 [) d6 Y' J
  59.        case VER_PLATFORM_WIN32_NT:
    ) Y6 ~0 w" n/ P3 h9 p& V, }
  60.            ReadPhysicalDriveOnNT(pSerList, pModeList);: C1 z4 Z; r* q5 N; X
  61.            break;' t# T- {5 k3 a/ \
  62.        default:2 i$ Q0 J* \, w: n1 p
  63.            break;( ~) D. i% }+ O3 h
  64.    }( H: I! c4 e6 p/ M9 c/ c  F2 }* m
  65. }( w  Z. k2 J3 M6 f$ C* D- v3 [
  66. //---------------------------------------------------------------------------
    * A; ?4 {' ]7 c
  67. // ConvertToString
    ! N8 d% ]' P7 w( l6 F* m7 `+ x
  68. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
    - F3 ~$ i5 K# l8 l1 `
  69. {
    ! |" b! l' T& Y3 j0 T- _
  70.    static char szResBuf[1024];
    8 a/ I6 u7 c8 K: `
  71.    int nIndex = 0;& x3 M  l+ P+ m- N# `  N4 F9 c6 `
  72.    int nPosition = 0;# G1 s9 }% D  q: B2 S- M
  73. % h2 \1 T- \/ {5 x7 |
  74.    // Each integer has two characters stored in it backwards. E6 _1 ~# T8 |4 q  J( p
  75.    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
    # O8 R9 E* ]" G3 D# l/ c
  76.    {4 X# o5 L2 E% }  g7 Q) ]* E
  77.        // Get high BYTE for 1st character2 x) F4 o/ \& s' N# V$ v
  78.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
    . a  y4 q! G# s8 Q( z" z
  79.        nPosition++;
    ' R6 a. `1 y0 g( x
  80. ( Y0 f& _9 K# o4 X- ?8 @/ p
  81.        // Get low BYTE for 2nd character; o3 P- q9 l8 {; y! G& Z9 j4 C
  82.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);" E% i, L% ^1 F1 X! l6 ?9 j, m
  83.        nPosition++;; X4 X/ ?" C7 C1 @& N
  84.    }: L  n& r) m9 z8 e: K3 m; w

  85. / V5 F) z8 M" [5 a% u
  86.    // End the string
    * n+ N) P; C1 D% Z2 `
  87.    szResBuf[nPosition] = '\0';% q% Z+ u% b  N+ A; S9 m

  88. 7 Z4 i. q8 Q9 Q" b
  89.    // Cut off the trailing blanks$ d, b: ?+ ?8 Q8 t+ J
  90.    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
    3 h$ o2 s% ]2 K3 J9 \0 k
  91.        szResBuf[nIndex] = '\0';& V* S* A% x/ @; j& ^: H8 _: R% |
  92. ( |7 a! l3 ?- q
  93.    return szResBuf;
    ) d- d4 U) Y' ~, C' T
  94. }
    7 g* E/ ~8 `; B
  95. //---------------------------------------------------------------------------/ V% h- ^0 I+ f, I/ p% ?
  96. // Winndows NT4/2000/XP 代码, r$ V% e8 {+ ~. ^1 V
  97. //---------------------------------------------------------------------------, v' ]' v. H; K- E) k& m) k( W8 ^
  98. // ReadPhysicalDriveOnNT
    ( ~2 v" s7 {+ h1 }9 u
  99. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
    ' |% ?( f2 u; Y! Z
  100. {$ q0 a  z' a: w! }. o
  101.    // 输出参数
    4 s9 \) _- K' O
  102.    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
    - j% T- b3 q5 S/ c& N' M% }
  103. 9 E6 r' D6 R1 G0 m
  104.    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++). w7 E3 l& l9 D5 w7 Q  I/ J3 G
  105.    {
    4 I# v* q9 |- G4 ]* @/ |
  106.        HANDLE hPhysicalDriveIOCTL;
    8 h3 a( q' I% O6 }8 L; r* B  b
  107.        char szDriveName[32];: x7 ~4 l4 \0 V# N% j' l
  108. $ U% L0 `- A/ `
  109.        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
    % n- i/ ~' T" G1 e7 u3 A  Q; J
  110.        hPhysicalDriveIOCTL = CreateFile(szDriveName,
    , S  w: w' W* v0 Y, t5 ]' e
  111.                        GENERIC_READ | GENERIC_WRITE,
    . u- \! F6 o9 P$ b- H
  112.                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,* g1 g+ d  @1 J# t7 ^
  113.                        OPEN_EXISTING, 0, NULL);) B/ L/ ~4 F7 M/ z! G
  114. 4 t1 \+ C& f8 @1 y+ ]8 q2 ^
  115.        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)! }  b9 }) |. E( M& R$ S
  116.        {
    + ]3 u9 p/ E; i& u* n1 \0 O( G
  117.            DWORD dwBytesReturned = 0;8 V0 g& T7 F/ A- _" p) z% @% m
  118.            GETVERSIONOUTPARAMS gvopVersionParams;& Q% [7 ?. B: K7 I4 n. n

  119. , b$ n# U) D4 f) L3 k
  120.            // Get the version, etc of PhysicalDrive IOCTL
    5 q) y! g$ W+ O" v' s; d$ I
  121.            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
    + k8 r4 T  E& }# c, S  a8 Q
  122. 8 F& C) D9 s) h- P9 b
  123.            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,6 b7 z2 I* R- `0 z
  124.                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
    7 K8 L* I( a6 t0 K( T  s- x' b
  125.                    &dwBytesReturned, NULL)); }4 g$ `# Z4 n! b; M
  126.            {
    # r, E) t6 T$ ]. m+ E. R4 j
  127.                continue;- d$ P$ `, H0 R. s3 `  B$ L$ t  v; i7 p
  128.            }
    4 K1 X: S8 o' f
  129. 2 {# S0 W% X# h. w0 O
  130.            if(gvopVersionParams.bIDEDeviceMap > 0)
    ( z2 [. Y/ ~, T7 h- X) S2 C
  131.            {8 `/ }/ Q! q8 X" Y6 f$ W0 d
  132.                // IDE or ATAPI IDENTIFY cmd5 `$ X( _2 h. u& e' U( ?' }
  133.                BYTE btIDCmd = 0;2 K5 E$ h0 w! V- y* o
  134.                SENDCMDINPARAMS InParams;
    . C  A6 K/ C1 N0 \  p/ B, o2 x" N
  135.                // Now, get the ID sector for all IDE devices in the system.
    ) U7 }0 Z3 B/ r2 v- ?
  136.                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,/ d# H: o, _+ D3 r/ h) f
  137.                // otherwise use the IDE_ATA_IDENTIFY command! a7 t1 T% `) n$ x7 m, \3 c$ E
  138.                // 具体所得结果请参考头文件中的说明
      e9 Q% [/ P. J' m: b$ R
  139.                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
      d! z" ^  @  Q' n
  140.                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
    3 ]4 [/ {$ x( T; K) x$ ^* j& r
  141.                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));6 _. h6 l( q; |0 `& n
  142.                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
    9 ?. N. q) n9 ~/ r
  143. 1 ^" `* v9 D1 d* e- ]. I" M' M
  144.                if(DoIdentify(hPhysicalDriveIOCTL,( Z- n% l' Q- T& g
  145.                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
    5 ~7 l% C0 f2 l! o( |4 [
  146.                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
    , B, q7 t9 H; S: R
  147.                {! x2 d; i3 l: v0 d: G$ n
  148.                    DWORD dwDiskData[256];. H( n" @1 }6 x2 u
  149.                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
    " m* W+ T+ F9 P% O6 v# k1 y
  150.                    char szSerialNumber[21];4 q. p* s( @9 L
  151.                    char szModelNumber[41];
    # Z# l7 h. k6 C, F% R: Y5 |) H- a

  152. 8 o+ ?/ a8 j5 X- z5 y; A% f- k: \
  153.                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;+ U# g' \( K5 w! X/ z1 R& d
  154.                    for(int i=0; i < 256; i++)
    " S6 ^1 W$ D8 }) l
  155.                        dwDiskData = pIDSector;
    ! z- r( t& k* H) r4 a/ g
  156.                    // 取系列号
    - K: ?# M6 |" `/ g
  157.                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
    & Q* h; P1 O7 }8 e) ?0 Y
  158.                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
    : g3 z, P6 E% i" L1 D2 \. f
  159. * b! q; K. G9 l) E- [
  160.                    // 取模型号% p$ N+ H$ Q4 n" ?+ Q2 B4 l# x1 F
  161.                    ZeroMemory(szModelNumber, sizeof(szModelNumber));8 G- r5 }" Q1 a" y$ ~
  162.                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
    % [- {* m: R" Y+ h0 {# o% d3 |* [4 _
  163. 7 D7 \4 L- ^1 M" A, n
  164.                    pSerList->Add(szSerialNumber);
    , _, H. {& G0 x! S
  165.                    pModeList->Add(szModelNumber);9 D7 m$ D& H8 r' W! ]
  166.                }% e  P4 ~6 y; Z) ?  Q
  167.            }
    % U( u) m: }% i
  168.            CloseHandle (hPhysicalDriveIOCTL);
      |7 K+ z+ f% U6 b
  169.        }6 G# J4 u0 H2 K1 p
  170.    }" w4 z7 z9 C# d6 \
  171. }
      Q( |4 u: A% @* ^
  172. //---------------------------------------------------------------------------
    ! j1 @' t" t; c# Q* G. @) M6 p" B
  173. // DoIdentify) E( s3 o0 ]5 H8 ~. q+ R
  174. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
    ( A9 Q% i2 e4 ?* r! ^; _5 V
  175.              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
      Q9 v. s5 F) C
  176.              PDWORD pdwBytesReturned)
    2 c% {, c+ E9 ?' k8 R3 E8 z) k
  177. {; o2 Q+ U4 H, E, p, ^7 \! |
  178.    // Set up data structures for IDENTIFY command.) S. h2 I. {) J, u2 x& F
  179.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;1 B+ ~2 ]/ r9 y% [
  180.    pSCIP->irDriveRegs.bFeaturesReg = 0;
    ; c4 N2 _- r2 O+ K
  181.    pSCIP->irDriveRegs.bSectorCountReg  = 1;" I# e% g' B2 O' L* D7 g5 L
  182.    pSCIP->irDriveRegs.bSectorNumberReg = 1;
    . a( b1 I# p& A7 P3 U
  183.    pSCIP->irDriveRegs.bCylLowReg  = 0;
    - ?1 |$ t0 N( G$ k' c) w
  184.    pSCIP->irDriveRegs.bCylHighReg = 0;
    9 \  i  A; f0 I& k) R
  185. # W' K9 x' D" }% }5 q# B7 \3 k- O
  186.    // Compute the drive number.(主盘和从盘所对应的值是不一样的)
    8 m2 I1 l, q! y  O* q9 S$ o
  187.    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;; l: l/ O/ j6 x4 I3 L' T# K; ]

  188. ' [2 Z- t/ R/ \; K& x. c
  189.    // The command can either be IDE identify or ATAPI identify.
      ?; p1 Q- e) F% Y* ?
  190.    pSCIP->irDriveRegs.bCommandReg = btIDCmd;8 S9 f( Z( a# y& h) [8 u# C( W
  191.    pSCIP->bDriveNumber = btDriveNum;
    : Q  l- h0 @. A5 \, U) u+ B
  192.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;. u6 I% n, K) [5 y
  193.   H8 d8 V& B# v* W6 C, c
  194.    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
    1 t! J2 F. H' Z+ r
  195.           (LPVOID)pSCIP,5 J. K: Y" o1 q& {3 @1 |; F7 [
  196.           sizeof(SENDCMDINPARAMS) - 1,0 O" g* l" O% u- Y6 c) B+ C2 o" `: B
  197.           (LPVOID)pSCOP,
    . u. C& A2 L, L! ^9 O4 N  `
  198.           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,4 x3 J1 r5 P6 @: B, e' b0 A  [! t- S
  199.           pdwBytesReturned, NULL);
      s. I% r# J. g) W
  200. }8 Z% u1 w1 \/ E6 a6 V6 q1 _
  201. //---------------------------------------------------------------------------+ j' D) g3 h4 e
  202. // Windows 95/98/ME 代码1 m9 B/ J! X, E& l
  203. //---------------------------------------------------------------------------, V) `, r5 X. H) Z1 C/ ~: @1 k
  204. // ReadPhysicalDriveOnW9X
    7 m  ]/ J& w  [/ D, v
  205. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)
    ' Y/ r/ T9 C" L# O4 z3 n0 A3 g
  206. {$ C5 b3 o- t' f! J* A, h0 ?2 O1 I
  207.    WORD wOutData[256];
    4 h% `! k3 o$ q: Y9 t+ y2 i
  208.    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
    - d+ |! q4 M* x$ t. R9 ?
  209. / l* @. s, M) n; W+ R
  210.    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
    # y( W6 [3 u+ i
  211.    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以9 [9 f$ w6 X' A( U7 O# F6 l
  212.    // 避免蓝屏的出现。(期待高人能指出原因)/ J+ O1 b& b3 {
  213.    for(int nDrive = 0; nDrive < 8; nDrive++)' p- j( ?! M& w( S+ s  ~) A
  214.    {( {) O" b+ n7 N3 R; H$ x; O( u
  215.        WORD dwBaseAddress;1 i' v) v! z; s  Y1 C7 W1 g
  216.        BYTE btMasterSlave;         // Master Or Slave" Q# [7 V# \6 v
  217.        bool bIsIDEExist;
    " U1 D1 o+ e: d- H
  218.        bool IsDiskExist;
    , |- m( B- ^; }2 h

  219. , u  u0 P6 C* g/ b6 g5 p
  220.        switch(nDrive / 2)1 T2 d, k# i% ^3 g; V
  221.        {( S1 G5 a& f$ _$ m) w& }
  222.            case 0: dwBaseAddress = 0x01F0; break;. B) ?/ ^0 V$ d0 L! Q
  223.            case 1: dwBaseAddress = 0x0170; break;+ Z/ [2 Z3 G/ g: X) |* N5 K% n6 G
  224.            case 2: dwBaseAddress = 0x01E8; break;
    9 s3 K8 z2 F$ h- i: y, f) z
  225.            case 3: dwBaseAddress = 0x0168; break;" p9 \! s  Y" {( o* T# z( b
  226.        }
    ) r# }" r/ y: ]+ o9 \$ m

  227. # C2 {! R& D: h+ \* ^
  228.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
    3 e! A  y" X! \
  229. , Y! E9 R+ o# {: L0 q* b
  230.        // 进入Ring0
    9 J6 @8 x' N0 ^$ ]  M
  231.        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
    * J7 {: S& O! T" O! [6 I
  232.                bIsIDEExist, IsDiskExist, wOutData);
    ' {/ y. X/ c( @' G/ Z# `/ z
  233.    }/ o9 h: z) a5 p4 E
  234. 6 r8 z" W6 v$ H. Z$ T3 q' a) U
  235.    // 开始读取/ U; W) {/ M; X* ?: _! ]; a
  236.    for(int nDrive = 0; nDrive < 8; nDrive++)
    . J+ z0 j) {8 N2 K2 p
  237.    {. ^( Y& z8 y" W$ V- {3 q
  238.        WORD dwBaseAddress;. f' s1 R: \. d5 ]% G4 }3 H
  239.        BYTE btMasterSlave;         // Master Or Slave
    0 P( c% c% O7 \4 p- ^
  240.        bool bIsIDEExist;# q+ g- u2 q; A0 ^
  241.        bool bIsDiskExist;; l5 _) M7 G: i$ P2 y7 m. W
  242.        switch(nDrive / 2)/ r1 i8 J. c& B: Q, V% B
  243.        {0 L5 n) B: M, q+ s6 D8 Q$ X
  244.            case 0: dwBaseAddress = 0x01F0; break;% M; ^0 ~9 ]0 ~; r0 m. b
  245.            case 1: dwBaseAddress = 0x0170; break;
    . k' U4 g6 n2 c* |( x6 q: r
  246.            case 2: dwBaseAddress = 0x01E8; break;( ]# a/ m+ r6 `! S5 v
  247.            case 3: dwBaseAddress = 0x0168; break;
    4 m- D& ^' E$ i5 E' t, z
  248.        }
    & g5 _) C. z6 T' L+ k2 W
  249. 6 a) {. c. u3 }4 B; y. }. d) Z
  250.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
    ! x- i0 `# i' ]
  251. ; \( T! Q& R! r6 r+ q
  252.        // 进入Ring0* c9 K5 t" F! B: b$ h) o( l# X
  253.        bIsIDEExist  = false;+ C% Q  ?6 _0 ^8 p8 L2 L  G3 l- |2 o
  254.        bIsDiskExist = false;' t2 C* J8 `& G
  255.        ZeroMemory(wOutData, sizeof(wOutData));8 I% s. o7 f" l, G( n
  256. 9 V6 L- U( R5 ?. N
  257.        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,$ b$ {- `; N1 h0 }  B% r
  258.                bIsIDEExist, bIsDiskExist, wOutData);( L7 u% n  f: {: j1 F+ j1 M! z
  259. 2 N" o6 Y& {, w) |7 @2 n4 e
  260.        if(bIsIDEExist && bIsDiskExist)
    ! Y) a0 ^2 Z9 E$ Z) y7 z5 z
  261.        {
    * q1 s; b+ g- I2 N; b2 F: p. f
  262.            DWORD dwDiskData[256];
    * m' i4 p, P8 }
  263.            char  szSerialNumber[21];
    2 K6 }) Z# L6 n4 ~. v, O, M
  264.            char  szModelNumber[41];
    " d# _6 \8 D3 b# p# ^7 V3 C

  265. # G! I6 E/ S! p( m, ]5 }  L  P! h
  266.            for(int k=0; k < 256; k++)* v2 V! b" r4 ]; E$ }9 ~
  267.                dwDiskData[k] = wOutData[k];
    % X: E6 |* A$ ^$ F2 c
  268. ! a) e- X3 X. T+ ]: K$ C5 R
  269.            // 取系列号6 g. n) e, Z- K9 }* a4 t" l$ ]" Q
  270.            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
    # s1 o- k9 \+ q- |
  271.            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
    / Q6 t8 `: o0 l+ M# |
  272. + ^) M) Z2 J0 l/ Y" O( W: U
  273.            // 取模型号7 q- ]- J$ r' Y0 P  ?
  274.            ZeroMemory(szModelNumber, sizeof(szModelNumber));* s) p3 `# E; l# c' Q+ a3 X/ b$ j
  275.            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
    6 A- B' L. y6 j- v! ?
  276. 2 e* D4 E8 |6 P( l0 l$ X. D' G
  277.            pSerList->Add(szSerialNumber);7 C1 x* P9 b% f+ ~# E9 t% }% ~5 @
  278.            pModeList->Add(szModelNumber);" R2 u2 p* I' W: E" Y8 |7 Q
  279.        }
    # v0 s3 i/ Q6 r
  280.    }* ]# l, N( q- y* a
  281.    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
    ! N  g5 R: Y# E/ e# {2 W; e
  282. }6 ~, }9 w: [, X6 d6 I- u5 W
  283. //---------------------------------------------------------------------------
    : I! V* X, ^' L" f) S( Y/ \; n
  284. // ReadPhysicalDriveOnW9X_Ring0()
    5 }/ j4 M6 [1 _$ B5 C) L* {. h
  285. //
    # f. `  Z5 `. A# {; g8 R; ]9 l
  286. // dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h% e! \; s) L. R/ f, @
  287. // btMasterSlave = Master(0xA0) Or Slave(0xB0)
    # ]+ U. p$ v/ {3 _
  288. //---------------------------------------------------------------------------/ G0 }, W* {: N3 }, m" V- a
  289. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
    2 `/ t% e+ G# u
  290.        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)  D; x: M- [) i/ X1 `  X
  291. {2 e# L3 l/ H8 t/ v3 N6 P+ X
  292.    BYTE  btIDTR1[6];
    ( `0 W# d1 [% @$ Y
  293.    DWORD dwOldExceptionHook;
    7 F; o- {  A" `/ r3 J5 D
  294.    const int nHookExceptionNo = 5;
    9 @  K$ w) M, i' S0 _

  295. . \" g+ w$ N' g6 X8 K
  296.    BYTE  btIsIDEExist = 0;
    ! ~. c8 M" A2 \! T# ?
  297.    BYTE  btIsDiskExist = 0;
    7 T& F0 t5 b8 H# p
  298.    WORD  wOutDataBuf[256];9 V% G+ Y! b$ F7 S, C; P* k( r

  299. ' `# w, l6 }9 N8 [3 t4 Y
  300.    BYTE  btIsFirst = (BYTE)bIsFirst;
    ! O. ^0 E6 G! j

  301. - q# w" G( G0 m: Q/ X( P
  302.    const BYTE btBit00 = 0x01;
    # p( M" a6 Q5 r8 r2 a4 }
  303.    // const BYTE btBit02 = 0x04;+ \4 M9 B- _# r3 P7 g) d2 J
  304.    const BYTE btBit06 = 0x40;6 x7 B) j" C: L* @7 {9 V
  305.    const BYTE btBit07 = 0x80;
    ( e1 k- C/ Z+ n5 |+ ]* P1 W; [
  306.    // const BYTE btERR  = btBit00;
    / E: z  B) S5 k
  307.    const BYTE btBusy = btBit07;% Z) O# \! ^  v# h
  308.    const BYTE btAtaCmd   = 0xEC;# d# @! h. q# i3 e. _7 D0 n
  309.    const BYTE btAtapiCmd = 0xA1;
    2 i1 q, U5 F- G7 B6 R5 z
  310. * x% b. u; p$ R5 y
  311.    __asm% ?" x. ^# c, Q5 c
  312.    {
    1 a$ i. k6 Z5 ~% Q2 k& L
  313.        // 必须先执行这条语句4 M4 {/ y/ ]% ~% p& }+ R
  314.        JMP EnterRing01 H, M4 M3 }' f: {
  315. $ a0 s( }3 }$ u  F( l5 h
  316.        // 定义过程
    4 L5 c% O: d; D! ]: ^
  317.        // 等待IDE设备直到其不为忙为止
    : `" j* G0 c+ Y8 O: P  m
  318.        WaitWhileBusy proc4 K1 ]8 o7 o2 f+ O' Y. O

  319. ( s4 f; I! |5 h  i8 h$ p, W7 ?
  320.        MOV  EBX, 100000, M  t1 Q& f0 Q
  321.        MOV  DX, dwBaseAddress
    8 E# t% A! D, P- J. v  @
  322.        ADD  DX, 7
    6 N& U$ \& ^! R% G4 Z7 m' u+ E

  323. 6 \. q1 i# f1 D7 e+ q
  324.        LoopWhileBusy:
    6 p% N/ o+ f) _! b9 @4 Y
  325. ( K5 T9 ?5 S$ k
  326.        DEC  EBX/ u5 [/ U; D0 M
  327.        CMP  EBX, 0
    2 |, V0 m' ~0 D( w- a/ U2 n
  328.        JZ   Timeout, y5 T0 _3 J. g: Z+ d2 r
  329.        in   AL, DX4 }6 ]. m$ ]- J& s+ X) X
  330.        TEST AL, btBusy
    6 S  Q- m, A( ~* X$ n
  331.        JNZ  LoopWhileBusy$ v! [  I0 e  ^/ Z0 I
  332.        JMP  DriveReady( t% Q9 d; l* @, }6 ?

  333. # S; o0 A; V' s6 {# N
  334.        // 超时,直接退出5 P) Y7 S* S9 T: N8 p
  335.        Timeout:) @7 H2 N# C, a1 m0 Q- W& C+ L; H
  336.        JMP  LeaveRing0
    ! e3 r2 p; {6 A' \
  337.        DriveReady:6 Y% Y9 n5 j& p8 h
  338.        RET
    + C& N" P3 n2 e4 L0 v  k
  339.        ENDP   // End of WaitWhileBusy Procedure0 P( f( S( g9 @$ t6 a
  340. 9 }( B. j- U: C9 c7 E
  341.        // 设置主盘和从盘标志
    ' I- W6 S9 A% {
  342.        SelectDevice proc
    ! J, K! }0 X6 B7 M. K4 C
  343. 4 A! F  q  u" e0 ~3 Z2 Y; t
  344.        MOV  DX, dwBaseAddress$ E5 ^, I0 p0 S1 ~, W% {1 F
  345.        ADD  DX, 67 Z  L; Y/ `( ~7 D# ?7 \
  346.        MOV  AL, btMasterSlave6 e! T4 n: k# l: f% K( I! a

  347. . c/ @& L. D5 q; B1 f+ W( }
  348.        out  DX, AL0 b: J' m' w8 D) _# S
  349.        RET
    0 L' ^( _2 [" _! I1 n, D

  350. ! i7 A0 z8 R- {6 x6 z
  351.        ENDP  // End of SelectDevice Procedure: C& g* D, `' s2 Y( A5 E
  352. " d4 h' N. n& y4 B
  353.        // 向IDE设备发送存取指令
    - Q/ A5 e+ b1 ?- w: J5 O
  354.        SendCmd proc
    ( O: a- R, U4 H) E
  355. ' l9 [4 f( h- {% w- \& H" |, m
  356.        MOV DX, dwBaseAddress& }) Z; Z2 X5 G* i& L& T: n+ c
  357.        ADD DX, 7
    2 C: _* {/ b/ \  m6 d* Q) L4 L
  358.        MOV AL, BL // BL是主从盘标识,在过程外设置
    - i$ ]. t4 \! i4 D# Q! h
  359.        out DX, AL
    / t" m2 \( j. c  ?
  360.        RET
    6 V" l9 W2 t3 t8 W# k
  361.        ENDP  // End of SendCmd Procedure
    ; Q. L8 ?9 z4 A

  362. 0 y( z+ d2 o0 U" n* I) ^0 X
  363.        // Ring0代码
    3 h; C" \( S" W  u; Q. R
  364.        Ring0Proc:) ]2 i. R2 D, M  E) m) C# S
  365.        PUSHAD" G) w8 q1 B* e% |4 d8 O
  366.        // 查询IDE设备是否存在* G3 e+ R( A, ], m. [" g7 r
  367.        MOV DX, dwBaseAddress1 W/ s, d6 N0 v, Y& j
  368.        ADD DX, 7
    $ ~. ?" i  _7 w6 [
  369.        in  AL,DX* Z7 G$ z2 w' Q, q3 {
  370. 8 R9 |$ i$ X- c$ y/ y/ `
  371.        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回2 ~" R( F! g# r4 ?; ~3 I# w7 u
  372.        CMP AL,0xFF# x$ M2 M+ M1 D/ R
  373.        JZ  LeaveRing0, L- J; }0 {( T; n: {' a
  374.        CMP AL, 0x7F
    9 u* H# b, t* r( i! H! w% ^. g
  375.        JZ  LeaveRing09 l8 i! A' Q  v( p

  376. 1 J" k! ?6 `8 T" P$ d: d
  377.        // 设置IDE设备存在标志
    # t+ Q5 p) a8 N; M, S* v
  378.        MOV btIsIDEExist, 1
    * D+ {% j; j* e, S% D. k8 v

  379. ) k& Q/ {$ G8 M7 l  o
  380.        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面), S+ z8 a/ W5 `' i0 O2 k3 n- j
  381.        CALL WaitWhileBusy
    - y6 P9 w5 ~, t! |5 A7 _+ T" O" i
  382.        CALL SelectDevice4 i+ n5 Y8 q0 ~; I$ O2 R1 v
  383. , B4 K, {% Z  u/ m" o* O& l. V
  384.        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏) z/ r" A  a4 H9 R% m2 w8 {
  385.        CMP  btIsFirst, 1
    ; v  U! ?1 m5 G* K) j: p
  386.        JZ   LeaveRing0
    : ]: n+ E2 \% o8 T1 R2 \
  387. ! }. m+ u7 H, t% U+ c, H4 e* F
  388.        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
    1 ], x4 i& o" ?9 n3 u
  389.        CALL WaitWhileBusy
    ! _7 a! X3 E- A- Z+ R
  390. : ]: o+ S3 x# Q! Z9 E2 y. Q
  391.        // AL的值等于cBit06时,不存在驱动器,直接返回: ?" M: ?; V3 [7 }4 w8 p! ~
  392.        TEST AL, btBit06
    8 r. C5 R' ~, V% [
  393.        JZ   LeaveRing0
    * x$ k$ w3 G( V" C

  394. ( j9 Y6 Q1 i: @  ]* O
  395.        // 设置驱动器存在标志7 l/ c6 k& ^2 ]; [4 X' I0 c4 M
  396.        MOV  btIsDiskExist, 1
    4 ?. Q# y: ]! d+ |1 W. T

  397. 2 [# u: J+ L3 h" @7 z; g
  398.        // 发送存取端口命令+ r) W  j  b& x' |9 e3 h
  399.        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,9 i. u  K. a& b# ?7 [" e
  400.        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令% i* P- y! }) M& d# N( h0 L  t
  401.        CALL WaitWhileBusy4 N/ F- |9 C/ L
  402.        CALL SelectDevice    // 设置主从盘标识
    ) Q3 ~- n* n" v- x) I6 T" g3 a3 ^
  403.        MOV  BL, btAtaCmd      // 发送读取命令/ e; S4 e2 V& R& @, w: b" b
  404.        CALL SendCmd$ o* m  _1 C: q
  405.        CALL WaitWhileBusy( t# M+ L7 v2 O5 Q# ]* n  c
  406. , ^# M& D: |& X
  407.        // 检查是否出错3 x8 L$ C. W' T  [7 Z% y
  408.        MOV  DX, dwBaseAddress
    # i+ t! n/ U( y
  409.        ADD  DX, 7
    ) d5 `8 T4 J" L& {; K6 x

  410. / X$ z/ h) y+ c2 `3 _& r$ j
  411.        in   AL, DX
    2 r  O, \# Y9 c9 i! p

  412. 8 K1 ^: ]% \) @
  413.        TEST AL, btBit00
    , a* Q1 B2 n$ ?& n" L" w
  414.        JZ   RetrieveInfo   // 没有错误时则读数据% Z9 D' c8 t3 i5 w3 T
  415. # w, C9 N3 k  u- S( c
  416.        // 如果出错,则进一步尝试使用ATAPI设备命令# ^' Y& i! o+ t  v
  417.        CALL WaitWhileBusy; i2 H" A: B& ?  v
  418.        CALL SelectDevice
    7 u2 {9 O  f' @' z4 J
  419.        MOV  BL, btAtapiCmd
    & o- C& d4 x& O. r; P5 x% t
  420.        CALL SendCmd
    + t1 S/ J& I; J, e
  421.        CALL WaitWhileBusy0 i5 x4 ]* y7 o  b! A/ F

  422. 6 ^. T% X$ g7 j+ w/ N, w2 C- ~0 L
  423.        // 检查是否还出错, l$ u; ~* S1 q+ i0 \: p/ V2 U
  424.        MOV  DX, dwBaseAddress2 T: @2 U* C: ]+ z
  425.        ADD  DX, 7
    , a( b/ R: W& @
  426.        in   AL, DX
    5 j, q" d8 O8 C$ k4 C
  427.        TEST AL, btBit00; G7 Y1 c2 X2 h$ I  n% a* m6 S2 w
  428.        JZ   RetrieveInfo   // 没有错误时则读数据' {' l/ H4 y# ~& E
  429.        JMP  LeaveRing0     // 如果还是出错,直接返回
    - J5 t+ f6 ~  _9 W6 Z
  430.   \" k0 f( r: b2 N
  431.        // 读取数据# p1 q& I( }1 A, A; ~$ k1 J) S
  432.        RetrieveInfo:7 j9 G2 w  y. o  ~
  433. 1 Y: _# P- v/ v1 m( v
  434.        LEA  EDI, wOutDataBuf
    2 L6 M9 ^7 c) G! C: x1 k
  435.        MOV  ECX, 256
    , o9 u- Y9 s+ e
  436.        MOV  DX, dwBaseAddress
    5 B( r/ W" L1 x% Z* ]1 `
  437.        CLD
    - C  X; g# I4 z1 @! m& R2 q& m
  438.   p' D4 T/ v& S) ?4 N: h
  439.        REP  INSW* v' N6 v& v* @; [2 B

  440. " b+ o. p( N& O0 w# T
  441.        // 退出Ring0代码
    7 X' L+ i( ]! v, v% ]
  442.        LeaveRing0:
    3 J& c% _7 f! T8 ~
  443. 5 x4 c. R3 i7 K
  444.        POPAD
    2 g/ |. E' c* r5 W
  445.        IRETD- k- z% r/ @, E  l# n

  446. ) U4 K# O2 R) n% R" s7 Y# {
  447.        // 激活Ring0代码
    # w& o# k6 q% v, \% P" l
  448.        EnterRing0:
    ! w% d7 f" l6 X# z$ ^, I
  449. " w; ~& U# w, `# H, w3 K1 f/ I
  450.        // 修改中断门
    " b  U8 H# I$ \7 I
  451.        SIDT FWORD PTR btIDTR1
    . i% |1 l$ u( I1 K1 \
  452.        MOV EAX, DWORD PTR btIDTR1 + 02h+ R+ Z3 l0 J% f  t
  453.        ADD EAX, nHookExceptionNo * 08h + 04h- ?% G' u0 G# {. }7 c
  454.        CLI2 l& `1 x: C3 e  @" b9 q( s
  455. $ y; M( k4 g  u9 U6 O6 I3 L3 ^6 y
  456.        // 保存原异常处理例程入口
    % Z: n; ?* B* Q( M3 T2 e; u
  457.        MOV ECX, DWORD PTR [EAX]$ k* m9 H- f+ z7 N
  458.        MOV CX, WORD PTR [EAX-04h]( Q' E7 E8 Q' a8 n& @6 q
  459.        MOV dwOldExceptionHook, ECX
    / m% K. N$ a5 [6 G
  460. 0 }( D. u& k  h, X9 z
  461.        // 指定新入口
    - C" Z, A' ?% `; S- e. z1 x
  462.        LEA EBX, Ring0Proc
    5 f( g: X( t* c. d4 p( s% v
  463.        MOV WORD PTR [EAX-04h],BX" v. n  d( d/ O( }9 w/ a) d
  464.        SHR EBX, 10h
    $ ]- m% K  L' k8 N3 J3 q! W, _6 `
  465.        MOV WORD PTR[EAX+02h], BX
    : A8 {9 Z* z& f* b6 S

  466. ( k4 A% d. t. O9 Z, V
  467.        // 激活Ring0代码9 F5 p" m0 j& `6 @
  468.        INT nHookExceptionNo
    ; f* x' G, c8 \; L% Z0 a
  469. & e) |5 Q. X9 y% k
  470.        // 复原入口. i' f! a7 |9 u, W( e! ?( ~
  471.        MOV ECX,dwOldExceptionHook0 r# l# u, T' P, D6 F
  472.        MOV WORD PTR[EAX-04h], CX' X! a1 H. X, H7 c' M
  473.        SHR ECX,10h
    ; E/ ^# `7 ]* J1 B4 ?
  474.        MOV WORD PTR[EAX+02h], CX2 k2 A1 W- B0 m& ?+ i5 k# W
  475.        STI
    $ z, c2 }$ o8 K8 h! J" D
  476.    }  O3 U' B- Y& r0 }0 t! x% j: \
  477.    if(!bIsFirst)
    8 l( G( T7 _% N2 v4 L
  478.    {7 i6 \* y3 ^+ s* O. v& i' Z
  479.        bIsIDEExist  = (bool)btIsIDEExist;1 r* D; m; w1 d; s& b* l! b/ f
  480.        bIsDiskExist = (bool)btIsDiskExist;
    # J% d& S" O& Y; W( T: P
  481.        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
    4 c" ~# d$ S# ?5 I) \' r: B
  482.    }
    - ^  y) H1 D) k5 ^/ B
  483. }
      Z8 }% ^3 s+ l1 A
  484. //---------------------------------------------------------------------------! q7 D+ A6 H! f2 R" @& z6 E
  485. // 调用方法:. ]7 X& ^" B" A1 j3 U. i: P, ~
  486. void __fastcall TForm1::Button1Click(TObject *Sender)
    " S) I- g6 d& ?* G3 W$ L) I; Y7 g; D
  487. {3 V1 E+ ?3 s$ A% j5 Z% r
  488.    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);( i( x  o$ y9 x+ e% f- D
  489. }
复制代码
发表于 2005-8-15 01:00:45 | 显示全部楼层
晕乎乎。。。怎么看8 洞阿
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-6-18 06:56 , Processed in 0.020336 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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