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

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

[复制链接]
发表于 2005-8-11 11:42:04 | 显示全部楼层 |阅读模式
  1. #include <WinIOCtl.h>& Q2 y( D4 l: B1 N% X
  2. #include <stdio.h>
    ! l. |3 |  u; S+ S& m+ b9 n

  3. ' S# W2 b& f) Y
  4. #pragma inline* Y4 e6 V. _3 e
  5. //---------------------------------------------------------------------------, L! _* m' k4 j7 _
  6. // IDE NT/2000/XP专用变量
    ( f; C" F( o  @0 u9 C+ R7 |
  7. #define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS" k3 r1 V& e+ H0 C6 J% J
  8. #define DFP_GET_VERSION         SMART_GET_VERSION: S8 ~& j" j' M4 T( Q3 Q; f
  9. #define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
    " {+ {5 I. ?; z# T/ r3 s- H/ {
  10. #define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA8 b% r# ~0 H) ^" d) {6 [. E, `; l

  11. 6 `( ?# M% E0 e' {+ ?
  12. const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令  t$ P+ v7 ^( t6 q" u  j7 z
  13. const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
    + A; r: b1 c" X6 ?
  14. " a# h$ X" F" J
  15. const int MAX_IDE_DRIVES = 4;
    $ X, ~! b$ ~) _) `2 z, J7 W

  16. 4 C+ `) Y7 u$ ~. N
  17. // SCSI专用变量
    5 U- ]7 r9 }# e& I/ z
  18. const DWORD FILE_DEVICE_SCSI             = 0x0000001B;
    4 C8 w" M% ^8 w: O5 T9 U
  19. const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);5 L1 a) U$ o6 c. ~
  20. const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition" X: q1 p! |$ ?8 x. F1 M. v! ^! ]
  21. const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;; m# o0 L! g2 }: d
  22. ; `6 C5 ?$ }& J, m9 I1 [& l
  23. typedef struct _SRB_IO_CONTROL
    6 |$ H  g! r& H: G
  24. {% T5 ^0 G# P+ s( R, ?1 p
  25.    ULONG HeaderLength;
    . l8 h- G! G, O" D+ l
  26.    UCHAR Signature[8];
    1 a- z7 u8 U# C7 y. \5 \
  27.    ULONG Timeout;
    ( O- n  i, u* G9 n! ~/ n+ x
  28.    ULONG ControlCode;
    : ~. z( Z5 C# v% m7 ?$ [- p) p
  29.    ULONG ReturnCode;( S/ P: c( ~4 |
  30.    ULONG Length;
    ( {6 _( \" y2 `
  31. }SRB_IO_CONTROL, *PSRB_IO_CONTROL;1 a( f' ^- b7 {  I. w2 n/ [
  32. % I1 y0 M: M6 E8 z" t- |
  33. // 读取的主函数
    8 K( U6 D8 @# U5 F7 U
  34. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
    , h) v% Z7 O4 @
  35. - L9 r; ^9 H2 W
  36. // 辅助函数
    3 \0 p/ C, x9 |3 T( L7 o
  37. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
    # k' p5 g0 x  V7 i7 C
  38. // NT/2000/XP函数# j$ W* J! ?* w8 m
  39. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
    # G, g9 ^( l  U4 a! M
  40. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,5 N+ E7 t2 ?7 }; U' O! D
  41.        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,/ K5 i/ h9 M! Q& [$ k# S0 B
  42.        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
    7 i* g* t; x5 u- H! y
  43. // Windows 9X函数
    3 L4 x' G1 s. s1 m$ I# _
  44. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);
    " {9 H' a1 J% I
  45. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,! ?2 z  F4 ?- ^6 y6 C
  46.        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
    7 y$ |% w/ F+ w
  47. & C6 D+ `2 p4 G, U6 M  B
  48. // SCSI读取函数(for NT/2000/XP)
    7 Z6 D; X. d1 i0 j. \4 u, J
  49. String __fastcall ReadIDEDriveAsScsiDriveOnNT();
    ' L8 \, `( j, I
  50. //---------------------------------------------------------------------------
    5 l! t4 k; `9 }! c' ^+ d! b1 a/ G
  51. // ReadPhysicalDrive/ U) }& i6 J* H1 |
  52. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)) i* R0 R7 q; `8 h5 A7 s3 e1 M
  53. {/ F$ c6 {$ t% Z& E$ V
  54.    switch(Win32Platform)2 i% G4 R, v/ ~# f- L6 F- y
  55.    {2 r6 E. M3 L& _& V2 n
  56.        case VER_PLATFORM_WIN32_WINDOWS:
    ( ^& w4 W2 Q  b6 k6 E  ~
  57.            ReadPhysicalDriveOnW9X(pSerList, pModeList);
    9 B  |0 @6 N% V
  58.            break;& o- n( G7 k, n" P
  59.        case VER_PLATFORM_WIN32_NT:5 M. l9 L/ C4 Z: H( F' @; d" G
  60.            ReadPhysicalDriveOnNT(pSerList, pModeList);
    9 }/ m" ~' w+ {. @8 h" \( M
  61.            break;
    . ^( ?, E3 |; z! B; ^# S1 B
  62.        default:
    ( s/ x; F/ P/ {7 Z3 F" L8 x/ H
  63.            break;6 A/ \# {9 a! O$ r3 E
  64.    }1 W% z+ B* T: t3 ?) M
  65. }) i( J9 M! B7 I, U( m( q1 Y
  66. //---------------------------------------------------------------------------1 K/ v* Q1 A3 d* v6 S5 Q
  67. // ConvertToString- u- k" @. p3 ?; M$ H' e
  68. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)1 c8 ~3 \4 o  d. r
  69. {4 E6 J  i4 V8 `5 W3 W5 ^
  70.    static char szResBuf[1024];* K2 |6 b& w' [
  71.    int nIndex = 0;
    4 F/ @& E/ e' Y) o4 m
  72.    int nPosition = 0;
      I4 M  _) S0 F$ H6 o; N$ x# o4 l" x
  73. . P6 h( x/ a; x
  74.    // Each integer has two characters stored in it backwards3 ~1 I5 d0 c1 ~+ j6 q9 `
  75.    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
    7 `7 c$ R' y% ]5 w/ X
  76.    {
      }6 f+ W  |0 B8 j- U$ x
  77.        // Get high BYTE for 1st character- I# O  o- H! R  S
  78.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);# Y' T6 o4 C  w4 S
  79.        nPosition++;# u6 x. S& I1 t2 z, K

  80. 0 L( c7 _8 A( h
  81.        // Get low BYTE for 2nd character* G2 h/ a1 w. b! m/ F! j7 e: V
  82.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
    9 y9 {" r9 L: b! S2 ^( ]
  83.        nPosition++;
    : }5 k8 e% ^+ |) @) c
  84.    }
    2 ~. Y+ ~1 q- z
  85. 4 a$ W$ e; w5 [7 Y) X- J
  86.    // End the string: Q- s% r+ g0 q6 _! K" g
  87.    szResBuf[nPosition] = '\0';6 {5 g, U4 L, f. H$ D9 x  V

  88. * n4 z. C! w' _+ J' a: T
  89.    // Cut off the trailing blanks: c1 G1 W1 N, |6 ^5 k2 z  }8 A* R
  90.    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)- e# z0 @4 B% Q2 Y8 j' L! Z
  91.        szResBuf[nIndex] = '\0';/ c. w4 x$ f: F; F1 q/ @+ B( N
  92. - ]. s" g* z9 H" P) E) `* _+ S
  93.    return szResBuf;
    0 _7 }4 Y0 D/ m2 r# R7 L
  94. }
    $ I1 S# X% J9 a  x+ h
  95. //---------------------------------------------------------------------------
    * z: Q. b. b- z
  96. // Winndows NT4/2000/XP 代码
    1 R8 {2 |) N" H# h
  97. //---------------------------------------------------------------------------
      @/ c. q  C+ a  ]; r7 K
  98. // ReadPhysicalDriveOnNT
    ! C* O* I- n5 R3 C  P
  99. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
    " {/ e* z' c% o8 s2 ]2 F" f) q
  100. {9 g' L9 N% n1 L
  101.    // 输出参数0 ?1 |$ k. T$ S7 ]/ ]
  102.    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
    2 c6 @  o7 Y; u

  103. 9 j% B- u  s6 A5 A: m" ]
  104.    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)2 H$ P( P0 v. {- O
  105.    {
    9 F. @* s! i8 ^: P
  106.        HANDLE hPhysicalDriveIOCTL;
    / N" r! O2 Z6 d, M3 e/ s( @3 u
  107.        char szDriveName[32];7 g& S/ B) w0 q7 W% L9 z/ A
  108. 5 U1 z' @% x6 D  g- L6 L) n
  109.        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);: m* I( {2 g/ U
  110.        hPhysicalDriveIOCTL = CreateFile(szDriveName,
    " @/ C3 l% |& @3 ^0 F* S
  111.                        GENERIC_READ | GENERIC_WRITE,
    % I( h9 p" n: C
  112.                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,; o; C$ ?+ }& q9 U9 T5 J, V
  113.                        OPEN_EXISTING, 0, NULL);3 G# J* M7 h( W2 }

  114. ; ~( S9 `8 e" D! {3 J
  115.        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE): z. j! ~; i% v9 y( U/ B  B1 @
  116.        {& U3 u& P7 Q) L7 A. i
  117.            DWORD dwBytesReturned = 0;7 y5 J' y/ [5 P- h
  118.            GETVERSIONOUTPARAMS gvopVersionParams;
    0 O6 v2 T4 X! s

  119. & W. P' R' B4 ~* {+ }0 I: `
  120.            // Get the version, etc of PhysicalDrive IOCTL
    ! M, i* {& u# g4 e4 g6 U
  121.            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
    9 d" W& n, h/ T4 ]

  122. : y2 L3 p) D# K1 ^1 U
  123.            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,5 Z9 F3 g( g6 }* ?0 ?$ Z
  124.                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),. e4 O2 B2 {6 [4 y
  125.                    &dwBytesReturned, NULL))( p5 H; q6 l, u* w0 U
  126.            {! `4 _: R# L. X$ \8 d3 L/ o
  127.                continue;
    % h; }' r" c2 o. m4 }/ {
  128.            }$ s1 O8 y5 q3 Y/ C9 N% |' p
  129. / T; q" D& h, x% x9 n
  130.            if(gvopVersionParams.bIDEDeviceMap > 0)
    : ]  o; K$ t! [5 `- b1 ]7 {4 Y
  131.            {
    7 l! \/ a, p6 v5 Y6 Y# `3 B- D
  132.                // IDE or ATAPI IDENTIFY cmd
    & ^4 N+ G6 z& y1 z- `- \
  133.                BYTE btIDCmd = 0;- G1 u5 m  \3 |) y+ d8 X" K
  134.                SENDCMDINPARAMS InParams;
      A+ t. |- Q( r( X
  135.                // Now, get the ID sector for all IDE devices in the system.
    5 y: N% \) K% `  U
  136.                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,; v8 X( L! R$ Q: q( N
  137.                // otherwise use the IDE_ATA_IDENTIFY command
    * a  U0 r6 `/ @2 z4 n
  138.                // 具体所得结果请参考头文件中的说明8 g- ?, V& R5 Y& {5 e& i3 m, [7 _
  139.                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?& ]3 a. V3 G- }  t7 E: W% ]% b4 X- q
  140.                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;$ H/ t) P  t2 d+ @4 L6 W0 J, Y# r: g( G
  141.                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
    & {- c1 @" k' m
  142.                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));7 H$ p, _1 o# C5 c/ ]
  143. * G- ]: U6 W  W( d; M; U, p$ k+ x
  144.                if(DoIdentify(hPhysicalDriveIOCTL,% J8 @! w  Q# F  O+ W( C5 U1 h
  145.                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
    6 P8 ~8 B( X2 @  Z3 B
  146.                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
      H/ S# }, U% f
  147.                {0 i$ {( g+ {2 r& C8 x3 o3 h
  148.                    DWORD dwDiskData[256];3 `  A6 w$ D$ _! I1 w$ Y! o
  149.                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
    : V, ?4 {& j6 F+ j6 R' m/ n/ \% k
  150.                    char szSerialNumber[21];
    6 ?6 ?* N3 V0 {2 ^: h3 X
  151.                    char szModelNumber[41];
      i9 r1 L, K! W6 q  o+ d: O

  152. 6 P$ B7 ^2 G3 r; ?- w
  153.                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
    / `& Q: O( |3 K: a+ C
  154.                    for(int i=0; i < 256; i++)
    & |; P% H0 N) r0 a2 V
  155.                        dwDiskData = pIDSector;# m2 i, q# H# X9 h7 n
  156.                    // 取系列号
    8 p. {/ K$ q! h0 |
  157.                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));4 U# f6 n" A. |  ]5 L
  158.                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
    6 D! J& v% ?) }& y# F7 g, O/ l

  159. * ?* {) U6 d4 R3 z
  160.                    // 取模型号3 B2 s4 C+ P- F! v7 |7 M; [" u
  161.                    ZeroMemory(szModelNumber, sizeof(szModelNumber));
    ! Z$ s; a' z0 }' q" {2 N
  162.                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
    + C2 _) q3 R( m) n, U

  163. . a* _9 J% z6 b/ i
  164.                    pSerList->Add(szSerialNumber);7 t8 _" q/ u0 U
  165.                    pModeList->Add(szModelNumber);# m0 _3 G# [& O% }/ ^+ c
  166.                }0 L& J9 J8 y& r: E$ g) K
  167.            }
    6 \& y+ @/ e  I& O
  168.            CloseHandle (hPhysicalDriveIOCTL);
    + D+ _/ q* L- z
  169.        }
    6 {  ^2 F% t3 ~
  170.    }. K0 t6 k: s8 u1 \
  171. }
    & J3 R6 P/ B3 g+ @
  172. //---------------------------------------------------------------------------" q5 v3 w5 ?8 d5 Y' a/ x( B
  173. // DoIdentify
    ) Z( U( d0 n9 X& B% V
  174. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,8 Z2 k' E, P) m. }; i3 j
  175.              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
    ; q5 }' s  w. b7 j6 O; r
  176.              PDWORD pdwBytesReturned)
    ' z9 y' L+ U' U
  177. {& _. h/ u) Z- [- E! [' _. f# p1 g' B
  178.    // Set up data structures for IDENTIFY command.
    . `. H, H$ f$ a9 L
  179.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
    # c) }0 t- \$ z, u2 P
  180.    pSCIP->irDriveRegs.bFeaturesReg = 0;
    ) w. C! Q5 m- {+ ?, t/ X
  181.    pSCIP->irDriveRegs.bSectorCountReg  = 1;( j* Q) C% c5 A0 ~
  182.    pSCIP->irDriveRegs.bSectorNumberReg = 1;
    1 Q$ i& R5 C6 |, R9 x
  183.    pSCIP->irDriveRegs.bCylLowReg  = 0;
    7 e+ z; Y! t& s2 j+ l5 |* l  O
  184.    pSCIP->irDriveRegs.bCylHighReg = 0;
    * H9 @2 ]8 y% U6 _

  185. 1 `' O+ {# h/ J2 Z
  186.    // Compute the drive number.(主盘和从盘所对应的值是不一样的)
    6 ^0 c" P5 m$ C. u, k* f5 K1 k5 x
  187.    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
    ; j  P7 H! Z0 ]' j
  188. ; u8 Z0 G7 ]3 y" S' T' [1 v
  189.    // The command can either be IDE identify or ATAPI identify.9 v5 e6 i: a" m  `
  190.    pSCIP->irDriveRegs.bCommandReg = btIDCmd;# n; c/ G; T: ^3 T5 W7 H
  191.    pSCIP->bDriveNumber = btDriveNum;  g, {! }; x9 m: K1 h
  192.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;" e6 S: ^1 M& Y. f  ]

  193. 4 i& W0 D2 Y8 u( S# s
  194.    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,) y3 }, \, g# C8 D+ l
  195.           (LPVOID)pSCIP,
    - y$ |8 _9 H9 F  e3 c$ y
  196.           sizeof(SENDCMDINPARAMS) - 1,2 Z8 Z5 q8 f; v3 C/ W2 m- V2 [& R
  197.           (LPVOID)pSCOP,
    * z7 M, L/ e. V2 X2 H
  198.           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
    6 C9 a' b. ^" N. A1 @
  199.           pdwBytesReturned, NULL);6 T2 v( P2 L( [$ d
  200. }5 D2 o' k7 _, `2 l. L6 z) m
  201. //---------------------------------------------------------------------------
      X6 P) Q3 C2 W$ b4 L
  202. // Windows 95/98/ME 代码
    . N/ w  A. e/ q3 s- S
  203. //---------------------------------------------------------------------------
    * F0 N9 `, O; E0 R) n+ p
  204. // ReadPhysicalDriveOnW9X4 L) Z0 l0 ~* K# C) _0 a
  205. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)
    # j0 D; q9 ]7 W# J+ R9 {
  206. {1 M& e; c/ b) W5 x, K
  207.    WORD wOutData[256];
    - t% }4 t  n5 j: j: Z
  208.    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);# o2 U( b  D7 ^2 q) y7 c4 g$ b5 z# D
  209. $ h! M! P& h* B9 B( h
  210.    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
    5 H4 b# N/ y7 m$ p1 H. F
  211.    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
    " i7 {8 X9 Y( E0 q! G
  212.    // 避免蓝屏的出现。(期待高人能指出原因)/ w: }" {( I( W' n+ t
  213.    for(int nDrive = 0; nDrive < 8; nDrive++)
    $ W- f3 {7 ^0 U
  214.    {
    7 l, i6 b' ?' k; i% b3 s
  215.        WORD dwBaseAddress;2 l3 t3 I3 \' K& {1 S3 N
  216.        BYTE btMasterSlave;         // Master Or Slave
    1 s3 Q8 H9 C& x, O8 H8 z4 b  O
  217.        bool bIsIDEExist;3 e" }) Q; e# f1 w7 s
  218.        bool IsDiskExist;( k- K  q  L- m# A" ^
  219. 3 T+ i1 A3 j/ p; C, s/ r- g
  220.        switch(nDrive / 2)
    # g. ^9 Y3 Q$ p' L( Y. U/ e) \, u
  221.        {( q6 x  J  L. ?* m0 b1 u
  222.            case 0: dwBaseAddress = 0x01F0; break;
    ( e9 K5 N  R4 a0 J5 ?& [- t' g. k- r3 F
  223.            case 1: dwBaseAddress = 0x0170; break;
    1 O/ s6 W* ?& e1 B; E5 c" o
  224.            case 2: dwBaseAddress = 0x01E8; break;
    7 Y* m8 w$ F, F* I) g; g9 I6 {
  225.            case 3: dwBaseAddress = 0x0168; break;
    ! i' ~. k  Y( b( P
  226.        }
    & ]; L; k4 n) K; B6 C1 Q: [
  227. 6 k1 g1 d1 g1 T" ~
  228.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);, a$ q5 T% h& ?6 ^
  229. $ L: _% ]& V" c5 o( @
  230.        // 进入Ring0
    + Q9 `7 v+ P! H9 S0 d
  231.        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,! k) t7 w; Z: A! s
  232.                bIsIDEExist, IsDiskExist, wOutData);8 w: X, E: C2 S3 }/ O
  233.    }
    0 H0 f! K, H$ c, u$ D% L3 n6 ^) b6 L

  234. 4 g% n; h# V9 Q4 r: M
  235.    // 开始读取) J8 X/ _$ M! T8 i& ?% v
  236.    for(int nDrive = 0; nDrive < 8; nDrive++)5 r3 W- [0 F4 E: z  g
  237.    {
    0 M- `/ O1 e  H9 Q  g# L* U! |1 `
  238.        WORD dwBaseAddress;6 m# N$ F$ Y3 P" W
  239.        BYTE btMasterSlave;         // Master Or Slave. v& z( B4 o9 F( @+ }3 Y8 k7 ?
  240.        bool bIsIDEExist;. C4 \9 @  _; w, f. Z$ g
  241.        bool bIsDiskExist;
    4 J$ U2 C) P9 q8 m! u7 S
  242.        switch(nDrive / 2)" z" A" t+ t; x& [: Q% f
  243.        {% A2 r$ ?$ X9 Y6 h* A9 }
  244.            case 0: dwBaseAddress = 0x01F0; break;8 H6 g/ e! ^' p7 Q
  245.            case 1: dwBaseAddress = 0x0170; break;- F( U8 j# c: J+ H/ o+ y$ F
  246.            case 2: dwBaseAddress = 0x01E8; break;& Q: c% l! K4 s! c
  247.            case 3: dwBaseAddress = 0x0168; break;
    " t0 E9 Q- o* @: w
  248.        }! f4 E2 {  z# Y! n
  249. 8 P# q2 N8 G2 d3 F  Y0 V& \
  250.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
    0 E3 _. G( M& ?) g, C* m
  251.   _9 Y' ~  _( m: t: M3 E' N
  252.        // 进入Ring0# [8 r' X4 U+ @
  253.        bIsIDEExist  = false;9 C0 q& }3 \5 O* t2 }) [
  254.        bIsDiskExist = false;9 _- a3 o+ t. o( X- F& b, M
  255.        ZeroMemory(wOutData, sizeof(wOutData));  l% j! g! i% Z7 p
  256. 3 p, V6 \1 L8 m8 W
  257.        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
    . @" y6 D& K# a
  258.                bIsIDEExist, bIsDiskExist, wOutData);9 A  x9 H# y; U  G0 J4 z

  259. 7 I7 j/ ~! |& E. w- l1 U3 `
  260.        if(bIsIDEExist && bIsDiskExist)9 M! t( s! m$ y& f0 a
  261.        {! G! D, ^8 _0 F1 N: Y1 w( f8 R
  262.            DWORD dwDiskData[256];3 Q9 B5 B. B0 U
  263.            char  szSerialNumber[21];
    " n& a+ d1 ], n8 h- c" x' r: e
  264.            char  szModelNumber[41];" k/ @9 e' A6 f# r

  265. . j  Y3 z- M5 e4 \+ @; q5 S
  266.            for(int k=0; k < 256; k++)& F8 O1 O$ {+ u3 Q7 C
  267.                dwDiskData[k] = wOutData[k];
    ' ^& q- ]9 `+ I1 h8 b5 K
  268. 3 k2 N+ i6 N6 J9 ^4 h
  269.            // 取系列号
    : r% d$ d4 ^! G1 t% e+ [, [% s
  270.            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
    + I; @+ a8 A3 Z; w
  271.            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
    ; ?" I5 S6 c) L! n7 [9 S! X4 h

  272. ! j+ I! d4 A* J9 f
  273.            // 取模型号8 G# V4 c% y8 f+ v( c0 r0 ~" A3 ?
  274.            ZeroMemory(szModelNumber, sizeof(szModelNumber));3 p4 q7 |4 y6 X5 w
  275.            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));7 L2 w2 X" d- L' }" _/ y1 ]" y
  276. 8 A1 x% F# U  {. B' p
  277.            pSerList->Add(szSerialNumber);; I* u$ M6 e1 R
  278.            pModeList->Add(szModelNumber);5 _( |* z. e4 S) H
  279.        }
    2 J7 W  d% ~" Y9 L9 D3 a5 \
  280.    }
      [* }% c  f, R+ ?! b
  281.    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);1 L9 o% f' Y- P( e+ Y
  282. }
    ( g9 ~- w- {7 g$ @# }
  283. //---------------------------------------------------------------------------) J! D$ D+ S' @
  284. // ReadPhysicalDriveOnW9X_Ring0(); C  z: E% i' v! w
  285. //4 P. D0 r& B7 v" \- W0 r
  286. // dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h: G) C! j* p1 ~  o! v4 n3 f
  287. // btMasterSlave = Master(0xA0) Or Slave(0xB0)3 U8 o6 e3 x2 x+ q1 ]( I9 C* j
  288. //---------------------------------------------------------------------------- @' U6 o% x1 l. v. t
  289. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,( }* z4 k0 E( U: E2 p
  290.        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData), Y. J7 }" J- V6 P! W
  291. {; a6 @: m3 D7 ^2 S
  292.    BYTE  btIDTR1[6];; }" _; ]  _1 O2 q& u1 r2 Y
  293.    DWORD dwOldExceptionHook;
    4 \) E- V2 F5 e5 }# P2 c  }
  294.    const int nHookExceptionNo = 5;0 k/ w  X# y) Z

  295. # j, r$ b$ c6 b+ c+ O
  296.    BYTE  btIsIDEExist = 0;
    + k( f# i: k+ v- n- P  ]& R. J
  297.    BYTE  btIsDiskExist = 0;9 ]) X3 j0 g! e# n/ N/ _* F8 ~/ D
  298.    WORD  wOutDataBuf[256];: _# P8 [" W0 q

  299. * c9 l% \0 i  X0 E& F5 s( ~
  300.    BYTE  btIsFirst = (BYTE)bIsFirst;
    # y" Q" `1 ]) p( C$ |

  301. + N- A* b/ m9 E- c, w7 L
  302.    const BYTE btBit00 = 0x01;
    # p1 A+ x  N! [- y% c. v! j  g
  303.    // const BYTE btBit02 = 0x04;3 l5 N1 y! X* ?
  304.    const BYTE btBit06 = 0x40;6 k4 K$ r: m" K6 v
  305.    const BYTE btBit07 = 0x80;
    & ]/ s6 c. N* K- ~: z  d' y% m
  306.    // const BYTE btERR  = btBit00;) K. ]1 l" ?* n7 W
  307.    const BYTE btBusy = btBit07;: c# o+ z5 b! i
  308.    const BYTE btAtaCmd   = 0xEC;
    ! O. J+ ?0 y& v9 t0 @% F1 @
  309.    const BYTE btAtapiCmd = 0xA1;9 C- p3 L1 h; S4 P

  310.   M" T2 w0 t3 U; v" B6 }$ s* ^
  311.    __asm* X+ Y8 d/ j/ I3 T$ r4 l
  312.    {1 W$ }* w7 C% j
  313.        // 必须先执行这条语句
    8 ?4 b8 |2 D7 p; F" n
  314.        JMP EnterRing0) P' m' V7 ^  u6 @8 \- d
  315. 9 T6 ~+ |3 ]6 ^- m9 l2 ]& u, X# {2 s
  316.        // 定义过程+ w/ `) q8 ?/ e' M$ y9 a" }) W
  317.        // 等待IDE设备直到其不为忙为止
    1 y' p. K5 T! h2 a7 t, E5 x
  318.        WaitWhileBusy proc
    ( K9 a* U- q+ y: |% M* Z$ L! m

  319. ; Y* g$ I* F) H0 b) u: z# v
  320.        MOV  EBX, 1000000 G' h2 N4 h, `7 ~1 I6 w( [9 S
  321.        MOV  DX, dwBaseAddress
    ) h0 l) Z  W% G4 U: D8 b
  322.        ADD  DX, 7
    9 k3 J. O. T. Q

  323. : e( z# n; w# k8 x' z% c- |% G
  324.        LoopWhileBusy:
      j1 l8 w  d! P4 }9 {  m$ j

  325. 9 l( B6 q: w% b! X, L' n) F
  326.        DEC  EBX
    $ W" h  d+ K7 {0 e; c' c3 W
  327.        CMP  EBX, 0
    + y3 x( H' y& W( @
  328.        JZ   Timeout
    ) f6 a) t) F* G$ P) D8 S* ~
  329.        in   AL, DX6 ^( Z5 ^  D, c( d  ^, a
  330.        TEST AL, btBusy7 b& f. P0 r3 j- }/ n  @# ~
  331.        JNZ  LoopWhileBusy
    + D1 b% h7 s7 A  _/ x0 ^) ]5 `
  332.        JMP  DriveReady
    % e* |0 O) d8 J: A2 v+ p. N

  333. & E. }. y( @+ ~
  334.        // 超时,直接退出  s/ R; N' G8 ]2 C4 N+ l1 C2 x- O" U1 h
  335.        Timeout:4 P) s3 @1 N1 r; O& O3 t
  336.        JMP  LeaveRing0% p  p* w( M: i2 e8 ?7 a
  337.        DriveReady:
    # J8 R' U3 q" V% O4 K
  338.        RET  i8 [& z) \- J6 F. N
  339.        ENDP   // End of WaitWhileBusy Procedure6 N) n+ u$ Y/ L' C) v
  340. ( Q# f; c) Y; g; G. X$ ]0 f7 H
  341.        // 设置主盘和从盘标志& P9 D- B; P# C4 w4 j! r
  342.        SelectDevice proc
      |+ F3 }* _$ m: o( ~; b7 ?% A: Z

  343. 3 E9 N9 \7 b9 G6 R/ X) F* ~
  344.        MOV  DX, dwBaseAddress/ A% p4 q, _, T' l) F* ~* ?
  345.        ADD  DX, 6  ]- O3 U! i9 q0 l! Z
  346.        MOV  AL, btMasterSlave
    ; V! P9 C, h: I# L& x: i4 N

  347. $ C9 ], j& a, N* b; ^
  348.        out  DX, AL. k8 T, _* I2 H* l3 ^8 j6 M
  349.        RET
    8 K# ?. P( p& y8 y3 M
  350. ' k, r* o* }; |2 ?
  351.        ENDP  // End of SelectDevice Procedure
    ( w" @" {! ~$ v5 a' z1 S

  352. . ^4 }* y% h+ Y+ R9 V
  353.        // 向IDE设备发送存取指令+ n* [! }! G0 i; @0 _8 ^" t
  354.        SendCmd proc
    ' h8 [6 Z7 Q9 N# m
  355. * M0 q! |, i! H7 G, @- K1 t
  356.        MOV DX, dwBaseAddress
    % C# E8 E3 [6 f' D* n! h
  357.        ADD DX, 7; c- v% o4 e5 R5 K
  358.        MOV AL, BL // BL是主从盘标识,在过程外设置9 a$ z5 s/ q3 a) Q2 L
  359.        out DX, AL; H* ?# D9 a. A6 i& ]8 N$ d
  360.        RET
    ) `7 p3 ~% X4 X/ }
  361.        ENDP  // End of SendCmd Procedure. f# {2 q- P  [
  362. ' v  u' R5 s3 l& ]& g
  363.        // Ring0代码2 O4 F! t) {: ~; C* q
  364.        Ring0Proc:
    . \/ \. Y' s# z0 m! w
  365.        PUSHAD
    7 F( {: `, U0 n" D, c$ K
  366.        // 查询IDE设备是否存在
    7 q5 }0 {: Y% [+ u: I! R1 i
  367.        MOV DX, dwBaseAddress
    / m$ m7 g' L: P0 o' m' e; B
  368.        ADD DX, 7
    8 d9 {3 x9 U- F5 W) i% ]
  369.        in  AL,DX+ c( ]: N  s( m8 y" B# D% h" G

  370. 5 V9 v7 V: F6 o5 B$ J9 b
  371.        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
    ( y8 ~: J  M/ C& U0 L: L/ [( m2 w
  372.        CMP AL,0xFF0 p  ?; T% ]3 {1 b0 t8 D0 B. O
  373.        JZ  LeaveRing0
    - y6 _4 v+ G, L
  374.        CMP AL, 0x7F
    0 \: w% }: I8 K" L8 G" D/ F) A
  375.        JZ  LeaveRing0
    - j4 r' B7 m; r( J$ K- n4 m

  376. & v- f6 D0 Z% P( m
  377.        // 设置IDE设备存在标志
    4 {% M4 X7 `( z; }
  378.        MOV btIsIDEExist, 16 k+ c# p9 ^) T

  379. % i8 [# j" n' d' L* ~' F
  380.        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)7 A: S2 ?4 m7 F  F1 n5 _
  381.        CALL WaitWhileBusy
    ; K& g: v9 J1 F2 @
  382.        CALL SelectDevice
    6 n* W$ J, h2 {1 b

  383. . O- Q& F" k3 M1 c: r
  384.        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
    9 r& J  A. Q- H! n0 ?
  385.        CMP  btIsFirst, 1
    ' S+ {3 t" l2 j/ y
  386.        JZ   LeaveRing03 [3 D" p' E, M+ k& I
  387. 2 g3 H! J- g% J  C& F
  388.        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
    ! n  U% C6 I5 }; S7 V: t6 |( Q
  389.        CALL WaitWhileBusy
    ; c: J; e/ X2 V" w) c! k) a: _' T, h

  390. + u, B2 _3 f/ H+ S1 ^7 X' M' b; z
  391.        // AL的值等于cBit06时,不存在驱动器,直接返回% O/ \. o) J! p* g
  392.        TEST AL, btBit06
    . I: c' V8 c" Z" d  Q
  393.        JZ   LeaveRing0
    3 \5 e  |5 P9 v2 @* q
  394. 1 B# X2 k- O- Z/ m! q9 ?* \2 ?+ L
  395.        // 设置驱动器存在标志6 r, {9 j( P2 C/ n9 r% K
  396.        MOV  btIsDiskExist, 1
    4 Y7 P9 ]* I: u

  397. 9 P' `, [/ V! z- ?" H
  398.        // 发送存取端口命令
    0 l+ O. n; c( Q6 ^
  399.        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
    ' h( G' O& h* `% P
  400.        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
    $ G+ D: g/ A- R% k  Q" q* n
  401.        CALL WaitWhileBusy1 |0 r, v% p+ ^
  402.        CALL SelectDevice    // 设置主从盘标识
    " @" w# z9 A; F, p; Q+ P% n* w
  403.        MOV  BL, btAtaCmd      // 发送读取命令
    ' p5 h6 k3 }3 f
  404.        CALL SendCmd' Y; @0 j7 V8 I; [: `: ]* N
  405.        CALL WaitWhileBusy5 f3 M+ _  k9 W6 m& ~2 E

  406. 8 b- |4 d( G; H2 A8 K2 i
  407.        // 检查是否出错$ G* q5 b( f! a/ M5 q
  408.        MOV  DX, dwBaseAddress
    , |& u8 d4 w1 \- {3 i& F
  409.        ADD  DX, 7
    * e9 c2 `: G" B+ B0 [" ~# S
  410. ( e1 u2 y$ v4 m1 S, j$ H
  411.        in   AL, DX0 N# H2 x0 I7 ]# @; t$ Q" v$ f

  412. 4 p+ Z- _0 }' P& B* o7 P
  413.        TEST AL, btBit00
    ' f4 B/ E9 F$ `0 M) f
  414.        JZ   RetrieveInfo   // 没有错误时则读数据) r$ L7 Z& V, y. g/ `. Z
  415. ( S6 F5 b! i/ p! R1 _4 B
  416.        // 如果出错,则进一步尝试使用ATAPI设备命令) V7 X- o* |% U1 S0 I, l7 G
  417.        CALL WaitWhileBusy
    7 U6 p) S1 x8 d: }. c
  418.        CALL SelectDevice# ]$ r6 i& N' B  l1 E% R2 ^1 B
  419.        MOV  BL, btAtapiCmd
    : s2 F; H  x; v0 D( c" h, I* K
  420.        CALL SendCmd5 i. j$ v0 p0 Q+ V% v+ w( m: y8 x
  421.        CALL WaitWhileBusy& N1 S# _/ B! d/ n
  422. 2 g) k3 M  s% D
  423.        // 检查是否还出错
    : x  y& m( L- t! U# x+ o7 w% ]
  424.        MOV  DX, dwBaseAddress
    * |& g2 |( b# x" u1 [
  425.        ADD  DX, 7+ @" Z& @/ I2 S
  426.        in   AL, DX
    2 u! q7 v5 v0 r0 o5 y# P/ f
  427.        TEST AL, btBit001 o) c- i/ k$ `/ Y
  428.        JZ   RetrieveInfo   // 没有错误时则读数据# B0 N" a7 k' n2 v* j
  429.        JMP  LeaveRing0     // 如果还是出错,直接返回
      B8 C8 s9 k' W7 \/ `- I
  430. ! U; j- d$ W# Z% u
  431.        // 读取数据
    0 r% N) U" z( h8 W$ W9 I2 _9 l
  432.        RetrieveInfo:
      U) t+ D8 L" k. q3 i/ |+ }1 z* j
  433. 0 ?6 @  D. K- f$ @
  434.        LEA  EDI, wOutDataBuf
    & h; S5 q# V8 F
  435.        MOV  ECX, 2565 p2 s" ~+ P# e/ R% d0 X
  436.        MOV  DX, dwBaseAddress; J9 P3 B8 H6 k
  437.        CLD) N. n9 D6 J+ ^

  438. * W, s3 P7 g5 d" ]' \" p4 q1 s
  439.        REP  INSW5 w8 ^4 M* z8 E' e) A3 p9 L2 N! o
  440.   _4 I% Q+ n$ g/ O
  441.        // 退出Ring0代码- P" |& w. Y( w' n2 ^2 D2 I
  442.        LeaveRing0:' i! k% x$ L8 v5 M# `9 A
  443. * Q  H( e/ z! j5 [
  444.        POPAD% G$ Y: i3 m# i. c/ ?
  445.        IRETD
    ) `, l( f7 A7 H) G9 A; B( a; p3 P3 V
  446. ) E( a7 q0 }% v
  447.        // 激活Ring0代码
    ) m9 O$ p9 \% P. p6 [. T
  448.        EnterRing0:* k- U' x& V! R; s' [2 F9 g

  449. + M3 T0 u; s& S* @. |( y" g3 h2 s
  450.        // 修改中断门$ ?, v# G3 X$ e3 Y; I. n5 u  z: j
  451.        SIDT FWORD PTR btIDTR1
    ) T0 L+ o" d4 K0 P
  452.        MOV EAX, DWORD PTR btIDTR1 + 02h) {* u0 x  R2 a6 w; M; u+ X
  453.        ADD EAX, nHookExceptionNo * 08h + 04h$ O: K# q1 m" w2 b3 R8 K8 X7 e, K
  454.        CLI; U" S: v3 P- M& L: c
  455.   a; F7 x; ~3 W* i) _3 X7 A$ V/ @: _
  456.        // 保存原异常处理例程入口/ R) S# |9 q. N) g: H
  457.        MOV ECX, DWORD PTR [EAX]( w) `: e. X4 G' Z) i
  458.        MOV CX, WORD PTR [EAX-04h]: c5 r& z( t, d
  459.        MOV dwOldExceptionHook, ECX
    % [# c$ P1 b+ \8 D- h, k% E

  460. 5 F, h7 J) h, L, A# a
  461.        // 指定新入口
    . s4 A% @1 H! \3 J2 \) R
  462.        LEA EBX, Ring0Proc
    ! E. B( ?9 u1 |" K/ x# D
  463.        MOV WORD PTR [EAX-04h],BX. Q7 o* d6 x6 Z
  464.        SHR EBX, 10h
    6 _8 V/ W* l# t/ w1 d
  465.        MOV WORD PTR[EAX+02h], BX5 H- m: i* ~3 s! K& B8 d
  466. 1 H) X+ Y( _, t' [" l0 O
  467.        // 激活Ring0代码
    0 K+ m, P" @2 Y; V0 [7 Q! |
  468.        INT nHookExceptionNo
    2 U3 E' E- o2 d6 T+ a9 V' W
  469. 7 j3 e0 ?4 G4 s
  470.        // 复原入口3 D3 `! I' i4 g) {- Q, R8 {$ U
  471.        MOV ECX,dwOldExceptionHook
    $ B7 y4 R4 q3 I4 ?4 M  o9 Z0 g- F
  472.        MOV WORD PTR[EAX-04h], CX2 G: z1 J5 J! y: _
  473.        SHR ECX,10h
    4 v4 `: \5 G7 j8 A/ y( ?
  474.        MOV WORD PTR[EAX+02h], CX# o: m  `' f2 f# _! Q1 w% ^
  475.        STI
    ! v* @5 e5 ]. b% g& p4 [
  476.    }
      F6 w# Y, O: H- ]6 h( p% r- Q( i
  477.    if(!bIsFirst)
    & s% ^( x1 y+ w( v! e; m
  478.    {
    ; F" q% T$ y" x# L8 m
  479.        bIsIDEExist  = (bool)btIsIDEExist;
      ^6 q4 P, k; F+ |+ R0 a
  480.        bIsDiskExist = (bool)btIsDiskExist;% a; ]5 T3 l7 E/ T9 L9 x6 B( @
  481.        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
    : ^4 @% l' z. A( x! L% ]; B* Z9 g! h
  482.    }! F; r1 L0 h# A* d6 f3 w
  483. }
    " H2 W5 x: q9 v& s+ z, p
  484. //---------------------------------------------------------------------------3 e0 m' X$ |) L) n# q1 M8 M
  485. // 调用方法:/ T5 K, q2 B* q7 w
  486. void __fastcall TForm1::Button1Click(TObject *Sender)
    ! q$ Y7 _; l$ s0 F
  487. {3 @3 {/ {/ U- N% A
  488.    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
    7 G8 {) Q0 ?1 l2 i* F& f1 ~3 W
  489. }
复制代码
发表于 2005-8-15 01:00:45 | 显示全部楼层
晕乎乎。。。怎么看8 洞阿
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-6-19 17:40 , Processed in 0.039270 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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