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

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

[复制链接]
发表于 2005-8-11 11:42:04 | 显示全部楼层 |阅读模式
  1. #include <WinIOCtl.h>6 i: Y# Q$ [1 ^
  2. #include <stdio.h>
    ! f5 ?( E3 o# h+ F2 i+ H
  3. : e. q8 d7 O- ?
  4. #pragma inline
    & l" h& z) w3 F* b
  5. //---------------------------------------------------------------------------
    ; s6 i3 P* F! o2 _( A  l
  6. // IDE NT/2000/XP专用变量
      {  Y+ p2 J. G6 J, K
  7. #define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS, `5 N8 C6 \- _& W2 i
  8. #define DFP_GET_VERSION         SMART_GET_VERSION
    . N, |( y% m% n+ P0 ~
  9. #define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND3 N& U. R. X+ X
  10. #define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
    2 H. n. }$ b+ s! [7 E1 {* A
  11. & b+ L4 {- S+ q$ T- |6 Y) @
  12. const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令+ m7 \, |& D) K% P9 y; l- K/ M2 r
  13. const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
    0 v! d* e/ U+ E" b
  14. 8 d7 j% ~4 A  [8 q0 B0 O* X$ h
  15. const int MAX_IDE_DRIVES = 4;$ q% M3 ^7 U; @6 @1 y3 h
  16. ' g2 j- W# ^+ W7 Q" i
  17. // SCSI专用变量- p' {; e$ {) m+ n: s
  18. const DWORD FILE_DEVICE_SCSI             = 0x0000001B;
    . B; q+ H; P* z( o$ s. G
  19. const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
    / U; G# |4 x4 U5 s
  20. const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
    # t3 m+ p5 n6 C! B4 r$ v
  21. const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;1 d9 |3 _: T7 D$ S/ g" }

  22. ! o, R. S" R9 ?3 X+ _" E3 A+ z0 W
  23. typedef struct _SRB_IO_CONTROL+ w& X: Z, C5 J$ s
  24. {
    1 |, e! H4 \6 k/ E' n
  25.    ULONG HeaderLength;
    2 ?1 L% U  x. `$ E# `3 Q+ y; u2 p' X
  26.    UCHAR Signature[8];
    $ K3 M7 N9 R. R( d- e2 ]
  27.    ULONG Timeout;% O8 d6 z- [( D4 f2 o/ f% r) ]
  28.    ULONG ControlCode;
    8 a  g2 i6 f6 ?  b
  29.    ULONG ReturnCode;3 v' p. E, Z4 W" X
  30.    ULONG Length;+ z& W4 J. _% r5 x
  31. }SRB_IO_CONTROL, *PSRB_IO_CONTROL;
    ) W0 k" m6 f" r

  32. ! _" D0 o1 G$ I- C: O6 J5 t
  33. // 读取的主函数
    ) v# j9 U9 u( R0 Z8 _
  34. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
    0 m! p$ z/ Z3 j' d4 [

  35. - ^/ q) I; M, v9 n8 A7 x$ h
  36. // 辅助函数
    : |: G# A6 Q5 j! y. j
  37. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);3 H# x/ a8 I% K4 Z
  38. // NT/2000/XP函数
    # e0 e4 I0 @# u% @& q
  39. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
    * m1 }7 r$ D4 ?+ ?
  40. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,% j: x, K/ G; p( q# ^4 V& j
  41.        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
    7 u2 K& k* N5 d, u9 T! J2 |$ c
  42.        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);* d, w5 k: T/ I* W' b8 c: {
  43. // Windows 9X函数
    . `! ^8 w, S& x, n- N& v8 [
  44. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);
    3 k  O$ x- f- Y
  45. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
    : b9 D+ z0 P! I. |
  46.        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
    : l. v$ Q0 J+ g9 u. `. j4 e, @0 y
  47. $ Q9 p' m7 T! j, d- X# i6 Q" m
  48. // SCSI读取函数(for NT/2000/XP)$ R- U, G7 e& W# F9 E6 B
  49. String __fastcall ReadIDEDriveAsScsiDriveOnNT();
    ; X3 W9 |  ^: @( ~+ B- t" S
  50. //---------------------------------------------------------------------------
    ; E8 E0 V; }% R5 G. T2 m0 [5 `
  51. // ReadPhysicalDrive
    # Z9 q3 f* L7 G. i6 p! o3 ~  Y
  52. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)9 _# J) S* W" |9 ?) A; i2 g
  53. {& n- X+ I, a$ ?: _1 }1 u( G; z+ c/ G
  54.    switch(Win32Platform)
    3 S3 m: o8 H; I1 u9 l
  55.    {
    ; r1 q$ d- U; L
  56.        case VER_PLATFORM_WIN32_WINDOWS:
    2 k8 w8 G0 [/ n* {0 C6 q4 }
  57.            ReadPhysicalDriveOnW9X(pSerList, pModeList);
    ; b1 B- ^7 p7 t7 w
  58.            break;
      T0 z7 t7 M7 `2 V6 ^, z6 j
  59.        case VER_PLATFORM_WIN32_NT:; u7 {2 U( n: D+ ], ]( ]2 f1 D6 u$ j
  60.            ReadPhysicalDriveOnNT(pSerList, pModeList);5 \$ b( W7 Z0 F0 E. n' ~
  61.            break;
      p- O" o) {' A0 d" ?- @' ]
  62.        default:5 P; k/ s  ?% B5 y+ q& h
  63.            break;3 i8 _7 a4 w7 L/ B' ?6 h: D
  64.    }8 I6 E8 K' ~$ V& T
  65. }7 ?5 Z* {( Y& D; B* L
  66. //---------------------------------------------------------------------------
    2 h* Z* j% r: n* u2 ^5 B! P4 o
  67. // ConvertToString
    & }" e8 t# d3 |8 L
  68. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex), Z1 E" c8 U' R8 x' D+ v) H
  69. {  `  _  ?+ a; @
  70.    static char szResBuf[1024];
    / B/ R1 {! n9 V  k
  71.    int nIndex = 0;
    : y6 m. f0 b6 y1 a& f. d
  72.    int nPosition = 0;+ V2 L4 T- l0 P4 @% Z+ P' T: v' B

  73. 2 |6 F! \0 Q$ C, y/ M5 F& C
  74.    // Each integer has two characters stored in it backwards
    ! w" m* M; _8 c; C. n- l& P, D& r
  75.    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)% m! |8 j, ^0 F4 N) g) E
  76.    {# T' V9 a- A$ j( Z+ J
  77.        // Get high BYTE for 1st character  }1 N# p' r5 P
  78.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
    + [! f; E6 A4 z9 {4 l' Q  }
  79.        nPosition++;3 u- I& a0 \/ P

  80. ' i$ v4 [) I/ G$ a/ P+ E/ `3 {. F+ Z
  81.        // Get low BYTE for 2nd character* G8 F2 J6 \& p9 v: g( R# @/ f) V
  82.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
    3 y0 J4 ^$ c6 O
  83.        nPosition++;
    " c( m: U) O  X: x3 p) V
  84.    }& n: j9 A7 r. J; W% }
  85. , s5 z9 C! ]- Q6 ?9 P7 m: ~7 x
  86.    // End the string
    . l- N# m; H6 f# k* n  P
  87.    szResBuf[nPosition] = '\0';( }' w- S. @6 J7 K" G7 x% e& T

  88. - T7 Q2 H& n8 `
  89.    // Cut off the trailing blanks
    - [! ]+ H# h5 j. b1 f
  90.    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)' I/ v8 o- |" r6 _5 i
  91.        szResBuf[nIndex] = '\0';
    " F( g4 k9 `' d" E3 H. s

  92. & T4 g$ f5 _0 a
  93.    return szResBuf;
    ' \$ C3 ?3 w5 }1 ~. q/ n
  94. }
    5 A3 }+ L5 Q( Z4 g; S& D0 d: \/ O! p# h
  95. //---------------------------------------------------------------------------8 d' N% W$ f: D
  96. // Winndows NT4/2000/XP 代码
    : W( `7 ]( A+ G
  97. //---------------------------------------------------------------------------5 ~8 R" [4 N, c% w" m) R& b
  98. // ReadPhysicalDriveOnNT( f: _# G3 l2 N3 H! W
  99. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
    1 n6 d8 g6 D9 W" o  e
  100. {4 `# V" s, C3 J" g: t& s" t
  101.    // 输出参数. c8 `7 R& e8 H0 K! z' d
  102.    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
    9 c6 R- l* w! R

  103. 4 n/ E( j$ {# y. \
  104.    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
    5 @  l3 U5 S5 P0 Y
  105.    {- h" C0 w; ?$ u6 _, V6 t
  106.        HANDLE hPhysicalDriveIOCTL;
    " V3 H# _6 ]* O& r4 W' s. [
  107.        char szDriveName[32];& D  V* }' [* X5 W& Y' Y* D
  108. - |& p: `5 ]5 t
  109.        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);9 w* n1 x3 [: S
  110.        hPhysicalDriveIOCTL = CreateFile(szDriveName,
    3 H8 B5 T+ A! T4 M
  111.                        GENERIC_READ | GENERIC_WRITE,
    * @( i! w9 b* G4 w
  112.                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,& u5 f6 z2 [" j, _" R3 `
  113.                        OPEN_EXISTING, 0, NULL);6 n9 o! @; ?6 B5 Z3 j" v2 Y

  114. " H% K% I5 Z3 S) O/ U! _% Z. ^
  115.        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)2 a6 S7 e4 U  M+ W7 r
  116.        {: G5 D9 Z0 ]% P2 y
  117.            DWORD dwBytesReturned = 0;) k7 v4 r" u1 B' g: Q! l
  118.            GETVERSIONOUTPARAMS gvopVersionParams;
    ! a- U/ ^" M! ]
  119. + h6 u0 A. R; T0 |
  120.            // Get the version, etc of PhysicalDrive IOCTL
    : i" m' ]; G- z% ^7 A, l
  121.            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
      Y7 w1 C( L7 \
  122. ' V4 \7 a0 z" C5 e+ z! N# K1 W
  123.            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
    2 b+ D1 z6 p. s4 a* @4 ^! n6 p) I
  124.                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),8 y! q* E) P7 n" ^2 Y: r2 I: a
  125.                    &dwBytesReturned, NULL))
    ) w3 o+ q- {; p# z4 o( I' I
  126.            {! ?( I% O! @8 |+ g
  127.                continue;- C% x# R+ B  `, o5 L; `0 [
  128.            }
    7 @2 u8 D. F/ ]* m, J

  129. 4 L$ L- L5 P( S0 F1 x0 L+ H2 l
  130.            if(gvopVersionParams.bIDEDeviceMap > 0)
    ( B3 V& k* v( w+ k2 i
  131.            {/ O. T9 G8 a; t7 L. o. {! x; A+ h5 D
  132.                // IDE or ATAPI IDENTIFY cmd
    9 o: X6 j) |% K  [- B) d# O  v/ Q
  133.                BYTE btIDCmd = 0;7 P: H8 D1 r1 }  l& U
  134.                SENDCMDINPARAMS InParams;3 a1 w$ K  U% n8 T7 _
  135.                // Now, get the ID sector for all IDE devices in the system.8 W4 x- k0 Z6 h( `3 l
  136.                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
    5 h/ K# F3 r3 u
  137.                // otherwise use the IDE_ATA_IDENTIFY command
    ! q# l: i; }# [
  138.                // 具体所得结果请参考头文件中的说明- V8 t3 K- j  v! u, Q
  139.                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?4 i6 Y6 |0 u; i' }$ D2 c
  140.                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;4 ?# i3 A6 c5 y1 J3 \. G
  141.                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));7 ?+ \+ ^9 J' a8 i, Z
  142.                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));( n" t. O# v% m* t+ U# ]4 p. c) n
  143. 7 I; F1 l# x( c, o
  144.                if(DoIdentify(hPhysicalDriveIOCTL,7 z1 w, {1 @1 D; s3 O7 K
  145.                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
    " ^& \/ U: C0 g- n6 S
  146.                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))' L) S! ]* W& Y
  147.                {
    & r4 v/ B% e8 @1 k7 f) D3 y& @
  148.                    DWORD dwDiskData[256];. z/ f% f# n: f8 J7 }& R$ p. f
  149.                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
    , h, J" J8 W: s+ \% E& C
  150.                    char szSerialNumber[21];
    * D& q" a" V  l: C& d5 V
  151.                    char szModelNumber[41];! D! }1 c0 r* H  J& g6 W  _

  152. , m$ \! p, @' F. ]
  153.                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
    ' B5 F# x6 k- k: F1 T4 X8 e
  154.                    for(int i=0; i < 256; i++)
    $ I8 B3 D# j' D" `6 W
  155.                        dwDiskData = pIDSector;) ], J, ]* a9 \
  156.                    // 取系列号5 E- c, e- u( {; t
  157.                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));/ `) W; ]% W& k9 w
  158.                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));/ F/ u$ G' d# O
  159. 0 s' C  ^* ~% A5 B' g) p2 d
  160.                    // 取模型号- s" O% p5 a  E9 V8 D7 I
  161.                    ZeroMemory(szModelNumber, sizeof(szModelNumber));! J3 s8 P; J% n2 z5 s% _+ ?
  162.                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));3 T0 Y7 \+ W# Z' o9 i, C% h% F
  163. % U7 z' C5 G. [) i9 q
  164.                    pSerList->Add(szSerialNumber);
    ) f- z5 z8 G- p; V5 X
  165.                    pModeList->Add(szModelNumber);
    & [5 [. O# A9 E0 [* F0 U. d1 @# n, x
  166.                }
    2 c$ W" B  P4 u3 b7 ]/ o- m
  167.            }" _% T7 c2 y- T) u$ ], r  _0 N8 M
  168.            CloseHandle (hPhysicalDriveIOCTL);8 E/ r4 K! S5 l7 b0 T) i
  169.        }
    + U4 D% M% w+ }! s- |
  170.    }4 ~+ |3 J; Q5 o! q' _7 i& j
  171. }3 M+ X. N& T& T5 j7 @
  172. //---------------------------------------------------------------------------
    9 N+ i* ~  Z" l5 e
  173. // DoIdentify
    0 @5 j% r" V/ ~
  174. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
    # g0 L4 S- a! Q% _7 h  ^
  175.              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
    5 ]! {+ f5 X. x/ ^% z1 L* v  z" m7 N
  176.              PDWORD pdwBytesReturned). u/ M# m- M2 D6 u0 b8 P
  177. {
    0 x* X3 n- U  y
  178.    // Set up data structures for IDENTIFY command.% n4 \8 }6 c1 V: X; k
  179.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
    7 y4 H/ r5 r; @# S$ a# d) l7 N, L
  180.    pSCIP->irDriveRegs.bFeaturesReg = 0;( X% I! \/ ?7 @# u% w
  181.    pSCIP->irDriveRegs.bSectorCountReg  = 1;
    0 p* j. u7 [/ T4 P/ _9 I( q
  182.    pSCIP->irDriveRegs.bSectorNumberReg = 1;
    ' I8 {" L% c/ v. q  N0 R% y( k! \6 \
  183.    pSCIP->irDriveRegs.bCylLowReg  = 0;4 B; W/ e  ~8 ^0 I; r( d
  184.    pSCIP->irDriveRegs.bCylHighReg = 0;
    6 e) F6 K" q2 F5 [: A
  185. ( ]" v) e# ^, j- a/ `$ {# i+ i
  186.    // Compute the drive number.(主盘和从盘所对应的值是不一样的)
    , `$ |/ n& z/ }) V
  187.    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
    6 P0 k/ c6 Y& C$ I6 e0 K5 L
  188. 5 j5 m- ]6 J& Y
  189.    // The command can either be IDE identify or ATAPI identify.
    # X" D8 n. i  `9 ^
  190.    pSCIP->irDriveRegs.bCommandReg = btIDCmd;9 o- [" I0 ]. J  a7 K
  191.    pSCIP->bDriveNumber = btDriveNum;  C" D6 F' [5 u9 ~$ |- z5 |+ J. g
  192.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
    2 ?! d6 X& O% d$ u! q, a- L

  193. 2 S3 @0 z3 H7 ^! @8 Q' l, P
  194.    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
    8 {- g) M+ c8 _' O4 R! A
  195.           (LPVOID)pSCIP,5 [1 x8 C0 K5 C, E1 F$ ~7 D
  196.           sizeof(SENDCMDINPARAMS) - 1,
    / `: f' p  [: l
  197.           (LPVOID)pSCOP,
    7 L$ A" s3 z! y$ u
  198.           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,7 r! M7 e3 d9 p5 L9 u
  199.           pdwBytesReturned, NULL);
    . r# a6 d! o) s9 [- s
  200. }
    - x0 H- @2 @+ T9 F0 c9 e. @* O
  201. //---------------------------------------------------------------------------
    % O. {$ F3 C2 S, `$ C* `
  202. // Windows 95/98/ME 代码6 [' c! B' |+ x6 ?) O
  203. //---------------------------------------------------------------------------
    1 V, z8 Z+ l' A- j" Y& K
  204. // ReadPhysicalDriveOnW9X% s! x+ `. J$ e" r( e
  205. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)
    1 X, @& p& N4 a6 s# m% L' A, Y! v* U
  206. {
    2 n" z* i* i" |, A% V
  207.    WORD wOutData[256];
    4 d0 Z; H% s( W! t- n- T
  208.    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);! ]) Q1 ?' N2 k! F" O2 V5 F

  209. ( w( o; @, `+ ^" }8 k* e
  210.    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。! R/ Y5 i  e: h0 ?
  211.    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
    ( F4 z* t( Q1 H, O8 X9 y
  212.    // 避免蓝屏的出现。(期待高人能指出原因). O' V# |3 Y% x. l
  213.    for(int nDrive = 0; nDrive < 8; nDrive++); R" B/ P6 e( i$ s# A" s
  214.    {8 F' d5 e3 n2 K5 e. D9 W
  215.        WORD dwBaseAddress;5 N- m0 Y5 Z, |5 j5 s
  216.        BYTE btMasterSlave;         // Master Or Slave
    + A. ^/ K! f7 E* Q1 I$ t* Q
  217.        bool bIsIDEExist;7 x, r5 g7 {3 X9 N! o* E& t8 |
  218.        bool IsDiskExist;
    5 M! d- r. ^& @
  219. 9 j7 L0 ~" G$ s
  220.        switch(nDrive / 2)
    6 l9 c% ^, Z! v; d, i2 _' B  w4 f
  221.        {4 `, v8 U$ F- i0 y3 Q. ~
  222.            case 0: dwBaseAddress = 0x01F0; break;% v* M) E! W. e3 d/ [4 k: a; U
  223.            case 1: dwBaseAddress = 0x0170; break;$ y* Z4 k# o3 G! F! {7 I- A, f- L
  224.            case 2: dwBaseAddress = 0x01E8; break;
    / k5 H/ l* Z( ?' ]+ I  |
  225.            case 3: dwBaseAddress = 0x0168; break;
    & {3 @) K$ U) }, J
  226.        }
    ) B9 i* Q& [6 O: T: ^

  227. / h% u0 b) S" V" n2 m/ R
  228.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);; O) u. F2 d2 \2 P

  229. 7 _- e' w- _/ Z! A! t1 H, Z3 g
  230.        // 进入Ring02 S( U: Y4 C4 t
  231.        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,6 J5 u3 L% h* ^/ _: J
  232.                bIsIDEExist, IsDiskExist, wOutData);( d& C9 X+ P# j, z! N4 ^* i" F- a
  233.    }
    ' ?' M  u! I+ H& A3 m, n

  234. 3 M/ T# |- O7 V, q$ F! [9 P
  235.    // 开始读取
    5 L* h% z+ O! _2 z
  236.    for(int nDrive = 0; nDrive < 8; nDrive++)9 |+ a& e3 @2 t
  237.    {
    - K% K- p+ u. o5 l9 c1 L5 }4 e
  238.        WORD dwBaseAddress;
    * e5 n7 }9 L' C6 O3 w0 A: W# K
  239.        BYTE btMasterSlave;         // Master Or Slave
    2 Q8 O; z& q$ P6 U6 z
  240.        bool bIsIDEExist;- A5 [; I7 m6 g( Y3 T  }, A& _& i
  241.        bool bIsDiskExist;
    # S9 E7 R* ~' h
  242.        switch(nDrive / 2)
    ' Y7 V" R( K, X% S4 m* X3 z: r  q
  243.        {- \; Z7 _/ ]9 U
  244.            case 0: dwBaseAddress = 0x01F0; break;2 \, Y* p/ ~7 x% l* k3 H& e5 B3 E
  245.            case 1: dwBaseAddress = 0x0170; break;
    6 Q1 |' }' ^; U
  246.            case 2: dwBaseAddress = 0x01E8; break;
    ) f" U7 C' S$ z  o
  247.            case 3: dwBaseAddress = 0x0168; break;) J8 E( d8 J" C! G* N
  248.        }: J. Z$ ~6 @! f7 }, Z2 z, U

  249. 5 U" x3 c* F& |- T$ l2 s3 n8 i- s
  250.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);% T5 N6 M% q- K4 i( w: _# C  `
  251. % n6 x4 U4 T4 w3 W
  252.        // 进入Ring0
    ( g9 ^+ O) d; X9 d' k) M; d& F
  253.        bIsIDEExist  = false;
    $ G0 v+ _# ]7 B. q
  254.        bIsDiskExist = false;, Y* T' n6 F+ F* _, `: r
  255.        ZeroMemory(wOutData, sizeof(wOutData));" `. E3 h9 d9 A1 b& {% P/ @

  256. 2 F! T' |% Y' B1 J! h
  257.        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
    6 w" x1 c& y. j% ~
  258.                bIsIDEExist, bIsDiskExist, wOutData);
    ) G' B9 T' H8 }# ~+ ~0 N. W0 ?
  259. 0 p, c6 |# e4 ]  u
  260.        if(bIsIDEExist && bIsDiskExist)
    . o4 L  l5 H' T- X% S
  261.        {2 D# L1 j" c  I
  262.            DWORD dwDiskData[256];- p' e+ P) T! p% t3 s! M! M7 h
  263.            char  szSerialNumber[21];; j. L* h5 G( h7 l% I2 T2 {( k
  264.            char  szModelNumber[41];0 ~, T7 ~% l. f8 S! ], ~# Q2 M

  265. + i/ E, e+ w/ w* l7 o/ f
  266.            for(int k=0; k < 256; k++)% B, d- m( N+ l; @7 M; r. `
  267.                dwDiskData[k] = wOutData[k];6 w5 A+ j* Z0 Q' f' v6 [

  268. + |: H1 S, {4 m
  269.            // 取系列号) k8 d4 W; j+ M7 e3 b# L" k. {9 G% a
  270.            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));' M5 i/ c; T9 H, z( R* a8 g
  271.            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
      H8 N* l5 o/ p! ^# \& E" [

  272. ; @5 v; T  c, V7 l
  273.            // 取模型号
    7 O& b$ a. P/ G
  274.            ZeroMemory(szModelNumber, sizeof(szModelNumber));0 [6 J9 |$ }4 ?; h
  275.            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));$ `: K7 J5 c; y3 `$ w. K
  276. ' v1 L1 V0 m$ j( n4 x+ k3 r, x/ D
  277.            pSerList->Add(szSerialNumber);/ B" Z5 R1 L' x& w4 }
  278.            pModeList->Add(szModelNumber);$ v$ f1 C8 P" o2 p4 c
  279.        }
    2 q6 ?- i3 O* A/ H
  280.    }
    , l. S% F5 [; [' K8 F
  281.    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
    # N# G  l8 c. M2 ^; U4 u
  282. }4 o9 W7 l, B2 I+ f7 O1 P
  283. //---------------------------------------------------------------------------2 s' r3 E! c5 E7 ^1 a" \- Z- @: e
  284. // ReadPhysicalDriveOnW9X_Ring0()
      z5 H' Z, a0 P: V0 W# p
  285. //8 j$ U3 z6 U6 v
  286. // dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
    2 P# u. j, O7 `
  287. // btMasterSlave = Master(0xA0) Or Slave(0xB0)
    5 v) t0 ?# F: }9 |, J
  288. //---------------------------------------------------------------------------  {" X' G% k+ N6 ^" O
  289. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
    $ m1 V5 N3 A& G  }! ?& {- L9 Y) D
  290.        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
    " \8 O$ q" F& W
  291. {8 z: w4 l7 r! C3 A  i. t
  292.    BYTE  btIDTR1[6];
    ( n" a1 C: j6 ?. X* n: p5 P
  293.    DWORD dwOldExceptionHook;
    1 l1 w5 q. ^' {! k
  294.    const int nHookExceptionNo = 5;; R' B4 @! x+ B0 v: Q6 h) ~6 Q
  295. 0 W6 Z5 }- R! P9 `
  296.    BYTE  btIsIDEExist = 0;
    . I7 w+ v- f3 _$ D- r6 {
  297.    BYTE  btIsDiskExist = 0;
    2 {+ x0 o4 p. f: E
  298.    WORD  wOutDataBuf[256];5 w* Q* D& B5 X/ X0 c% z$ V

  299. 5 F" ^% I- e* h+ N, p6 e
  300.    BYTE  btIsFirst = (BYTE)bIsFirst;8 z4 _( D+ Z1 z' n
  301. 7 L. J' x" e& V$ z
  302.    const BYTE btBit00 = 0x01;  v2 I: ]' ]: M/ l6 n
  303.    // const BYTE btBit02 = 0x04;
    1 G, k5 d! E) `# C6 G9 m+ }" f
  304.    const BYTE btBit06 = 0x40;" |% h) e- h# x: r! r
  305.    const BYTE btBit07 = 0x80;, @+ F) s, j4 f. {$ z1 G, l+ p
  306.    // const BYTE btERR  = btBit00;
    3 J7 M! A; S! {1 ~
  307.    const BYTE btBusy = btBit07;
    + X- A" C: ~+ B5 J
  308.    const BYTE btAtaCmd   = 0xEC;
    + ^6 e. L" u1 g1 e/ C" j* G
  309.    const BYTE btAtapiCmd = 0xA1;* L. ~8 n/ H- |9 c; B, Z6 [! S

  310. % m0 t  R* ]) S' l$ i) K: ^. n
  311.    __asm
      _$ v# V4 n2 j, D1 i" O# h+ g
  312.    {
    # P9 S: }. C, l# E
  313.        // 必须先执行这条语句! A5 ]/ L7 u6 s3 w  R
  314.        JMP EnterRing0
    ) ?6 {3 y; R8 Y/ C$ v& C# ~

  315. 9 b9 r" j% Z& y, m" t6 t9 |% ?
  316.        // 定义过程6 ]( Z) G6 ?& q! t0 ~
  317.        // 等待IDE设备直到其不为忙为止
    1 P! F9 x" V  X9 I8 H
  318.        WaitWhileBusy proc
    * A( F& L" R3 o' e  X/ L4 [

  319. 2 ?8 K+ M) a8 d) Q! @
  320.        MOV  EBX, 1000008 l( {/ ~! P# c  V6 L: B8 _% I+ E
  321.        MOV  DX, dwBaseAddress
    % h1 i7 Q( s2 T  k
  322.        ADD  DX, 7- O" I0 \0 G1 ~
  323. 7 ?# X5 m  {* V# O
  324.        LoopWhileBusy:: B$ [: e  g( R) Y6 b) d3 Q
  325. & C. D+ k  j9 @
  326.        DEC  EBX
    1 C$ b; D9 P. Q, X1 _
  327.        CMP  EBX, 06 @, ^- U: @" w5 e; K" N* q) n
  328.        JZ   Timeout
    : V! J; o. y* H! y
  329.        in   AL, DX
    ) {' s3 z# y( R: G7 e$ y
  330.        TEST AL, btBusy1 ?8 C7 S) N" F
  331.        JNZ  LoopWhileBusy4 R7 O8 t' \4 `* m  {
  332.        JMP  DriveReady
    4 a3 B" U" |' f# X7 Q

  333. / m( T. Z" N: z/ m$ s5 ?3 I
  334.        // 超时,直接退出! @% ~4 _; r" Q
  335.        Timeout:
    3 }. c0 t5 Q- o; Z2 I& R
  336.        JMP  LeaveRing0+ ~; ]1 W; c: z+ w' b
  337.        DriveReady:
    , q3 Z9 t: v# q5 \/ ^- C
  338.        RET
    . }# K- m! a% W) A
  339.        ENDP   // End of WaitWhileBusy Procedure
    % _0 E6 s, v( `3 Y- r
  340. # p, t+ x  x& M8 M
  341.        // 设置主盘和从盘标志
      Z9 w, n( d& ^
  342.        SelectDevice proc
    9 U6 w: b- D6 b$ K! n3 C1 E

  343. ; x$ @. {1 s2 W' J! Z! T8 D! R5 o
  344.        MOV  DX, dwBaseAddress# x5 h3 ], x, c5 m4 ]6 C
  345.        ADD  DX, 6
    , F; E% V( t6 G0 u
  346.        MOV  AL, btMasterSlave
    % r) n# Y* O$ f' e, q2 E
  347. 4 S3 a* M" ?( `1 s- q6 M6 V
  348.        out  DX, AL
      A0 @8 q& ?7 Q3 g  x$ U4 v% `
  349.        RET. \+ V' O) T. q, `) R; _6 ]

  350. 9 e& b# H0 q/ `: B1 ]! M8 `
  351.        ENDP  // End of SelectDevice Procedure
    # Y5 \" P5 a2 n2 E3 M7 u6 Q) N

  352. ; g3 ~( z" @/ e& Y, T
  353.        // 向IDE设备发送存取指令
    ! B( ]) O$ o: T: A. [
  354.        SendCmd proc, C$ F* g; K5 M* {" E
  355. ! U% {* |' [$ V. C9 b
  356.        MOV DX, dwBaseAddress1 u4 K: u* \( Z& o  q3 v
  357.        ADD DX, 79 l0 u/ E$ V/ r5 N7 o& {9 P: a! R
  358.        MOV AL, BL // BL是主从盘标识,在过程外设置( E. O: h/ l& y# j$ T0 V
  359.        out DX, AL# ?1 z' Y! y& ?; v, M5 I
  360.        RET% H- e: @3 ]5 b9 I3 k
  361.        ENDP  // End of SendCmd Procedure
    ! |/ o1 M+ [" T' q" Y: X% N

  362. ) Z3 }; l# \5 J: T) t( Z
  363.        // Ring0代码, Y1 B) I' s0 x
  364.        Ring0Proc:
    7 J. Y- S, E8 V. P- ?
  365.        PUSHAD& {; m9 K' N5 i; G
  366.        // 查询IDE设备是否存在: s/ u7 a% }, T. u, `3 y
  367.        MOV DX, dwBaseAddress
    2 A& Y0 m6 @1 P/ v% g
  368.        ADD DX, 7
    0 V% d" Z, {; l( F
  369.        in  AL,DX
    - e6 [5 Y3 J( I

  370. 4 M- s4 z0 m0 l, y7 ~
  371.        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
    ( y' M  Y7 G7 I+ F1 _
  372.        CMP AL,0xFF- x  A( b  T$ {, N* Y' L  A& M7 D
  373.        JZ  LeaveRing0
    ! Z( m$ `9 W' ~4 ?
  374.        CMP AL, 0x7F' o. D+ W3 V% Y5 ^5 N! O
  375.        JZ  LeaveRing0
    # I1 U* K( ]5 u

  376. % U+ V7 @1 T6 {  G. P- [1 M6 j1 W
  377.        // 设置IDE设备存在标志- q' m% b  Y9 j3 T; Z. i% {
  378.        MOV btIsIDEExist, 12 R& j, x8 E1 `$ I

  379. : H  z7 g. u+ ]( G
  380.        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
    & q& X) o; \* x( V! W+ T+ h! t
  381.        CALL WaitWhileBusy: y* H! Z3 d/ e9 o; l* o) f/ s
  382.        CALL SelectDevice
    3 M5 ^& m$ N8 i3 L- e- W4 L( Y: f

  383. $ b( \! r: k3 W6 P# l% N# S! e/ S
  384.        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
    $ T4 s' F6 h" M: b
  385.        CMP  btIsFirst, 17 `8 }1 ?# }( K5 F/ b* j
  386.        JZ   LeaveRing0/ ~0 J3 L7 C: P) _6 I, F
  387. + n( n* b8 p0 Y7 E
  388.        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???3 s+ ?- i* S! W1 q  I/ a
  389.        CALL WaitWhileBusy
    , R! o' S! k+ s; }* ~/ C

  390. 0 l9 U8 t9 i9 |" [
  391.        // AL的值等于cBit06时,不存在驱动器,直接返回
      ?+ a/ H) t7 ?  M3 A7 {' K
  392.        TEST AL, btBit06
    6 S* }7 f, F; p
  393.        JZ   LeaveRing0' k- s8 s. L+ |8 ^2 z1 |
  394. 2 X" L7 j* H* s+ e; `- j
  395.        // 设置驱动器存在标志
    " p1 A( y  u  S
  396.        MOV  btIsDiskExist, 1
    ! k! ]9 f5 Y# q; U

  397. " g# ~5 v3 \$ z7 g$ i. ?3 p
  398.        // 发送存取端口命令: F9 s/ P, \& g8 C3 l- X
  399.        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,; N6 k8 K/ `$ k% j0 K0 @
  400.        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令: F$ p1 Q$ c2 b" q5 C# t6 P7 W3 K
  401.        CALL WaitWhileBusy
    , G' ?2 x7 D. K, t
  402.        CALL SelectDevice    // 设置主从盘标识
    # z2 m( a+ }) Q" }
  403.        MOV  BL, btAtaCmd      // 发送读取命令7 s2 ^' V7 k, u
  404.        CALL SendCmd
    0 x6 C+ |( N9 D
  405.        CALL WaitWhileBusy
    8 B) d2 E% O( d( G& p

  406. $ R9 }" K+ L! M  |' T4 T
  407.        // 检查是否出错. r) ~2 W& g" ?
  408.        MOV  DX, dwBaseAddress
    ( O  v' d" A5 b9 A; q
  409.        ADD  DX, 7
    8 w- k2 U' _$ l3 a
  410. - _3 R4 n5 y# U
  411.        in   AL, DX
    9 V* k5 b7 ?8 n: x* |

  412. 9 Z+ `- a  `/ g% [0 s. N5 g
  413.        TEST AL, btBit00
    . h9 o) Z; A# F
  414.        JZ   RetrieveInfo   // 没有错误时则读数据
      A! J* i6 i: d( j

  415. . P& O/ M" m# ^( j
  416.        // 如果出错,则进一步尝试使用ATAPI设备命令- j+ o, ^7 Q* o
  417.        CALL WaitWhileBusy
    5 U4 A8 b) D9 B: h) N% _  C
  418.        CALL SelectDevice
    9 ^1 Z( V0 }4 x2 d6 W  p$ I. L3 j
  419.        MOV  BL, btAtapiCmd
    , E% `$ ^" B, |
  420.        CALL SendCmd5 n8 z+ Q6 Y/ s& n9 ?2 G: c/ S2 `
  421.        CALL WaitWhileBusy3 U+ f# @  O# [% r
  422. * q( ^9 {8 @' K5 ^' C/ t. \9 s
  423.        // 检查是否还出错
    0 D2 [4 x0 H; [1 k+ a1 |- |: G# m
  424.        MOV  DX, dwBaseAddress$ ^2 M' ^3 x/ W1 S4 {
  425.        ADD  DX, 7
    6 Z. u) {, W* e' s3 x) Z' J( I
  426.        in   AL, DX6 Y* a, x* o/ x( }) L0 p  C
  427.        TEST AL, btBit00
    ' Z6 D  Y' F4 p; L. ]
  428.        JZ   RetrieveInfo   // 没有错误时则读数据+ J/ G2 v, ?$ `- h) O
  429.        JMP  LeaveRing0     // 如果还是出错,直接返回7 n: `/ L! T2 n: R3 O. M+ D. E2 L% V
  430. ( J9 ?9 `9 Y9 B6 \% C! T6 q
  431.        // 读取数据
    8 _2 m1 u1 o* P5 a5 W, ]
  432.        RetrieveInfo:* m* Y6 H3 d2 h* y0 s: h+ _" q

  433. & ^3 l8 w, }  A" ]6 G. }
  434.        LEA  EDI, wOutDataBuf. S: ^* A0 Z' U- b6 y
  435.        MOV  ECX, 256
    0 l' @5 C' D4 I* P3 p
  436.        MOV  DX, dwBaseAddress
    ( P4 q8 q/ O- h5 v. }
  437.        CLD
    / f* H# ~' T, {( V! C

  438. & a  O7 T. i* L' U7 u9 y6 p5 |. x
  439.        REP  INSW6 P* C. W+ T# I# b; j" y% v) w
  440. & f: J. d7 @- f
  441.        // 退出Ring0代码
    , j" J; _( L/ ^, B/ p
  442.        LeaveRing0:/ P5 X: [" z% W* u$ P0 g' T

  443. ) `& }$ l) s3 V+ D( D- B
  444.        POPAD  `% x/ _( Y$ ^; j
  445.        IRETD9 o: Y: R0 P' C3 A

  446. ( X' d' y5 d' Z! f; Y1 L  N
  447.        // 激活Ring0代码
    ! ^4 C% [2 o& {' H# T! t  N
  448.        EnterRing0:% h; {  y) O% U; o! D  ]

  449. 9 [7 |" w7 I' }7 E# ]* c" F3 P0 O
  450.        // 修改中断门
    1 y- `- G0 t  W, A2 {3 P, R
  451.        SIDT FWORD PTR btIDTR19 y: c1 G$ I' z  V
  452.        MOV EAX, DWORD PTR btIDTR1 + 02h
    / L/ g$ L  ?. T) r$ u: u  @
  453.        ADD EAX, nHookExceptionNo * 08h + 04h
    * @* U/ ~0 V9 |
  454.        CLI
    ! l- K1 q3 L( D" g* l

  455. 7 Y1 T, E6 i8 {8 Q
  456.        // 保存原异常处理例程入口6 a. J! D* O3 f2 J# ^( k7 @) W; K
  457.        MOV ECX, DWORD PTR [EAX]
    " A/ j& ^4 c( U* ?% h  p1 w. b
  458.        MOV CX, WORD PTR [EAX-04h]; K; l% p$ V" X
  459.        MOV dwOldExceptionHook, ECX$ d" j% Y# v, j

  460. / w& W9 A  {  d( p; e
  461.        // 指定新入口
    * }5 t4 v, A8 B
  462.        LEA EBX, Ring0Proc
    8 A- h, C. c7 R6 i4 Z1 H
  463.        MOV WORD PTR [EAX-04h],BX- q0 j( c4 |+ U9 q- t/ U, z! n2 R5 `6 k! N
  464.        SHR EBX, 10h# [+ V9 Z5 X& W* c
  465.        MOV WORD PTR[EAX+02h], BX, b( i  M) ?4 H2 w9 K1 j
  466. 9 x9 T9 J* P* j
  467.        // 激活Ring0代码0 G4 o2 l. J  F# |1 S
  468.        INT nHookExceptionNo
    % S6 g) G3 q8 g( G
  469. ! J' P3 e: B/ A: F% B# k
  470.        // 复原入口1 R; T/ o. ?& ~$ `
  471.        MOV ECX,dwOldExceptionHook
    2 a3 w" U% X0 D' y% y' a) _! [
  472.        MOV WORD PTR[EAX-04h], CX
      `6 `* j6 a% Y: J( d/ E/ W7 H1 E
  473.        SHR ECX,10h2 I) f( l6 k, ?/ V
  474.        MOV WORD PTR[EAX+02h], CX3 C: i$ b: Z$ W' K$ L" k& h& A
  475.        STI; }4 F7 m( \6 O% h
  476.    }
    9 R1 F6 [% M% n& @8 G1 p( g  H
  477.    if(!bIsFirst)
    ! f; F: P- f9 r3 T, A# |  f& A
  478.    {, \* T$ U$ n  z- ~; L! Y) b
  479.        bIsIDEExist  = (bool)btIsIDEExist;# \# i/ Y+ g  u4 I. S2 A$ {5 u
  480.        bIsDiskExist = (bool)btIsDiskExist;0 L% F+ D& e* \1 w+ T& Z
  481.        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));6 X( x8 \$ F$ p, p
  482.    }
    * j- F" O4 N$ W; u
  483. }! u! u0 d' x! h' M
  484. //---------------------------------------------------------------------------
    6 N. D& N  O5 M* @! Y- W9 Q; v
  485. // 调用方法:
    & ~' h# N2 r% A1 x4 n, x
  486. void __fastcall TForm1::Button1Click(TObject *Sender)
    2 U0 B. J# o0 F# J3 J8 T5 ?
  487. {
    - j- `5 D! u& k9 i  A4 `
  488.    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);* M' m: l" H/ y" a/ ~# p! b  w, T
  489. }
复制代码
发表于 2005-8-15 01:00:45 | 显示全部楼层
晕乎乎。。。怎么看8 洞阿
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-12-29 20:04 , Processed in 0.019549 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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