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

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

[复制链接]
发表于 2005-8-11 11:42:04 | 显示全部楼层 |阅读模式
  1. #include <WinIOCtl.h>; O* q7 b9 P2 e6 U7 K1 t$ s
  2. #include <stdio.h>: k/ W$ R. }  j: D# k2 A; p% ^1 T, ^. t

  3. 9 c) e4 _2 ~; A
  4. #pragma inline
    $ `/ j/ U% H4 e
  5. //---------------------------------------------------------------------------" f* w& ?3 x0 j
  6. // IDE NT/2000/XP专用变量1 \5 S' u# K) D' z! q
  7. #define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS4 U. ~  x0 N8 {
  8. #define DFP_GET_VERSION         SMART_GET_VERSION6 F! P' _# A) b4 F+ x2 a( g* _2 y
  9. #define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
    " u$ A# [; L0 Z8 R, x. N( A$ f
  10. #define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
    1 Q0 Q0 q1 d& W; z; C& `# _- L

  11. 8 Q2 P# {* K, v! N
  12. const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令& a5 r5 ]7 X1 B$ \; \% n& b: j& e
  13. const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令! A3 Y7 f2 v# Z% P6 s+ r  Y( G
  14. " f" ^4 u1 k- q
  15. const int MAX_IDE_DRIVES = 4;7 y* e4 h, }3 ^' G* @* P! l
  16. 6 ]0 N# D$ H; J9 @+ w& V. \) _' T
  17. // SCSI专用变量
    4 k, z5 [9 `' d# @2 N3 i# ?
  18. const DWORD FILE_DEVICE_SCSI             = 0x0000001B;
    5 W% m' U* @- Y* u" E' x2 Y" y
  19. const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
    ( P8 j- e7 x* i2 A' f
  20. const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition# m, c/ A3 P! V# G7 P$ X, u7 F
  21. const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;# V: {/ b; O6 q2 ]

  22. : V0 ~8 r* m4 g& B) q% b
  23. typedef struct _SRB_IO_CONTROL
    1 x8 I2 V  g( ^" ~* v
  24. {' o2 i! A: d4 V$ a7 i
  25.    ULONG HeaderLength;
    2 w+ z, l+ }6 Y0 u/ m) \
  26.    UCHAR Signature[8];2 R+ ]2 v( [7 j1 b1 I& c* u/ ]9 X
  27.    ULONG Timeout;
    * v- \* y$ E. \
  28.    ULONG ControlCode;
    " F- e% U4 s0 `, e! m1 ]
  29.    ULONG ReturnCode;
      d% i% @' [: Q* {1 H) d( A
  30.    ULONG Length;' Q: Y/ b% V4 B# T3 ]3 S* d) V
  31. }SRB_IO_CONTROL, *PSRB_IO_CONTROL;3 e2 |$ b0 k; K' |0 ~

  32. & {" J4 s6 O; a! I* Z
  33. // 读取的主函数
    0 z6 n0 z, w( m
  34. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);; n! X' x- t! E! }- w
  35. ) T  `- x! E8 q5 ~. r5 @
  36. // 辅助函数
    - s- c9 ~* S% N
  37. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
    3 c6 `4 s( a7 x
  38. // NT/2000/XP函数- V+ m# F" P' m# p) k
  39. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);2 U4 `4 O( v9 w1 Z; d  ^
  40. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,/ A& [! Q0 x) R4 K
  41.        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,  I+ G2 ^, s6 ?6 H$ b+ O$ ?; Y& ~
  42.        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
    ! B6 m6 g$ v. h% j/ [5 I
  43. // Windows 9X函数
    . r, S6 N( v- F8 y) d1 F- I
  44. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);
    2 Y2 F6 }0 G9 q
  45. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
    1 Y2 a" k! R3 V' k5 E
  46.        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);0 H  Y# D4 L: h+ v$ U

  47. ) h4 w3 O$ R" E
  48. // SCSI读取函数(for NT/2000/XP)
    ; F- f2 f4 ?" R  |
  49. String __fastcall ReadIDEDriveAsScsiDriveOnNT();6 [7 i9 M( q* e3 q/ t$ `' G
  50. //---------------------------------------------------------------------------
    : w% ]7 r* l9 k; {" [/ u
  51. // ReadPhysicalDrive
    , {7 Y/ C/ @7 q/ J! B- A$ |
  52. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)5 h( o" `0 U* G( x
  53. {
    4 {( M& q8 j: e( y8 |) h. q& I
  54.    switch(Win32Platform)
    $ I/ @9 g. ]3 \* j" s' B  S# M
  55.    {8 W7 ]8 `5 B: W" a! `! j# k- q
  56.        case VER_PLATFORM_WIN32_WINDOWS:
    1 y  M/ x5 Z+ s2 y
  57.            ReadPhysicalDriveOnW9X(pSerList, pModeList);
    : E* S2 {- Z1 E. m) X/ ^9 u- L
  58.            break;2 B1 |2 M1 @+ f) R1 J
  59.        case VER_PLATFORM_WIN32_NT:+ w& _: [0 U2 K- d4 p; a4 n6 e
  60.            ReadPhysicalDriveOnNT(pSerList, pModeList);
    4 I7 ^( K3 x4 \& b  |8 S; \( _/ x
  61.            break;
    * h1 s6 s7 I$ G* ]9 h& l
  62.        default:+ X) c1 ?6 Z. B- h! s( i4 j- P- }" @* p
  63.            break;* M  C& v. {; c8 E+ c
  64.    }
    6 Z( y1 R6 {* M/ R7 k- f0 W
  65. }: S6 v) Q. ~# ~, c
  66. //---------------------------------------------------------------------------, l* I; n- V$ u3 q+ P0 |
  67. // ConvertToString8 @9 Z. j" y9 ^! i/ X: X
  68. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
    # f$ s- q* M0 E, Q& F
  69. {/ j, u$ j; Y& W( ~
  70.    static char szResBuf[1024];9 Y$ f6 F) k" N- V1 @( W  h
  71.    int nIndex = 0;& T: X  m$ ~+ Q" I- R& J
  72.    int nPosition = 0;  ^. Z1 l* n) P' m6 N9 c, q

  73. + M, p; x( l/ m# S/ \
  74.    // Each integer has two characters stored in it backwards
    # C3 w" f2 i+ X: T8 O. X+ L. \
  75.    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
    * Q. }; `  }3 Q& |# z) Y8 _
  76.    {
    , S* v# ?2 c7 ~0 H( z$ A3 X! }
  77.        // Get high BYTE for 1st character
    # i7 I8 G: ?) I4 q5 `
  78.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
    $ V! J  f. A5 [- U
  79.        nPosition++;
    # L0 V2 W# T) T3 D9 t/ ~
  80. 0 Q0 ^6 \" t& I% l# ]
  81.        // Get low BYTE for 2nd character
    5 v/ r7 F, @! k/ \$ B$ ^
  82.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);1 F4 b, {$ e! R. Y
  83.        nPosition++;
      _3 v  G+ h3 ?; M* j  k. S0 e' W
  84.    }
    + s) n5 A$ s. E1 X' _
  85. ( d* w& U* C! y0 j/ Z: I. m
  86.    // End the string
    % u" |! Q# K3 z
  87.    szResBuf[nPosition] = '\0';2 `/ \" V9 o" ~; `$ Y

  88. 4 R2 Z% P) L% Q5 b9 E
  89.    // Cut off the trailing blanks$ |- {( @4 ~  N9 K+ ~
  90.    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
    0 D6 n6 x4 x1 I" O% h" c: A" @3 `
  91.        szResBuf[nIndex] = '\0';
    - c0 \* W) J: M7 k

  92. / H* M, \6 a. S+ `4 ~  X
  93.    return szResBuf;
    2 V6 I' K- L& N/ h! ~1 ?) n
  94. }
    7 Z+ v, j7 C( i/ E+ ~
  95. //---------------------------------------------------------------------------
    6 C, A2 k; H+ z3 }
  96. // Winndows NT4/2000/XP 代码; I+ W; O' o' `: ?2 i; }6 b( l
  97. //---------------------------------------------------------------------------" I! k# w# X. @8 `: ?; Q9 q9 \2 S
  98. // ReadPhysicalDriveOnNT
    7 Z* h: W7 G: _  @
  99. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)! a3 j1 a" q! \
  100. {
    0 N2 h% Q+ f4 B# y9 y+ m$ G$ l
  101.    // 输出参数: F2 d6 L, Q& a( z# E
  102.    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];8 y  S2 r+ @! {2 d5 |6 r) b

  103. 7 {  a* f# [( n7 e+ j2 w1 n
  104.    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)4 [4 w1 Q* A' @1 J7 d
  105.    {
    # U3 e( B$ b9 R& @8 o/ C1 G9 b% F
  106.        HANDLE hPhysicalDriveIOCTL;  P' k) Y+ M% B
  107.        char szDriveName[32];) \- r4 i' k6 X! B! H  A& l
  108. 2 T: [5 H# g; U; d! U& ~( n7 _) ]/ _
  109.        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);6 K) Y7 e  i; U
  110.        hPhysicalDriveIOCTL = CreateFile(szDriveName,
    $ ^2 d7 V/ c* C% H2 c- v1 I/ S3 t6 U
  111.                        GENERIC_READ | GENERIC_WRITE,
    5 Y' B8 u! e; q6 T& X" r. f
  112.                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
    7 }9 W( [+ i9 K8 `+ m
  113.                        OPEN_EXISTING, 0, NULL);
    ! `, s: T) Y4 m* {; ^

  114. ' P- g7 v6 L& a5 A" [
  115.        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)) p: |7 C0 m( g0 ]; l
  116.        {/ e& e( n7 D! _+ K0 q/ b& D# x' [
  117.            DWORD dwBytesReturned = 0;
    $ @! S  c9 H5 K7 d5 a1 i/ H% V
  118.            GETVERSIONOUTPARAMS gvopVersionParams;+ L% j' n( `: r  l4 E% c, ]- C3 k& b

  119. * V4 J2 |  j! c& f
  120.            // Get the version, etc of PhysicalDrive IOCTL9 a# M+ J; b! \7 J* r' |' W
  121.            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));5 D+ S4 C3 G* H/ E- I" i+ Y6 k. f0 Q
  122. ' u* b( }; O) C. H
  123.            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,; i( J. C8 u7 i5 }
  124.                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
    * \/ w- H* z% U9 |
  125.                    &dwBytesReturned, NULL))
    7 l3 I7 ?7 Q% a! [: @
  126.            {/ K- L6 c% s5 g  ]4 }1 e
  127.                continue;1 E8 [# s0 v/ N; g
  128.            }. d, X" c% a1 n' S! w8 X

  129. & m+ L' |6 j+ W8 {
  130.            if(gvopVersionParams.bIDEDeviceMap > 0)1 ^& {, p& Q* O8 r* }6 ^3 S) Y0 S- K
  131.            {
    * q0 X$ ?: ?0 m, L$ y+ z. L: L
  132.                // IDE or ATAPI IDENTIFY cmd7 Z$ B2 H, G, u% Q+ I
  133.                BYTE btIDCmd = 0;  p* J5 m% X% _; S. G' s. @
  134.                SENDCMDINPARAMS InParams;3 a, D) g- \7 _2 [2 I' |
  135.                // Now, get the ID sector for all IDE devices in the system.
    * M1 _1 L! m) e4 T' j
  136.                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
    & [( g8 r* Q2 s9 U9 n7 }3 h! H+ f
  137.                // otherwise use the IDE_ATA_IDENTIFY command
    % {! n5 ]) V8 Q# O
  138.                // 具体所得结果请参考头文件中的说明+ f4 f4 c( }* ?6 \* N
  139.                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?# m8 c' a9 x" q( F6 K) \
  140.                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
    $ B/ A$ u3 N/ N* o+ n7 R. R
  141.                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
    % ?* L# o- q1 v
  142.                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));  X2 L8 j/ o. W
  143.   {( A3 j: Z" W6 f$ w
  144.                if(DoIdentify(hPhysicalDriveIOCTL,2 P& |" U5 K% q
  145.                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
    4 w1 z+ y! L- Y- c8 Q
  146.                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))7 @  u+ a) ?% y3 e7 \' v  }
  147.                {1 }% {4 N5 O( y7 h" e" [' z" o, A
  148.                    DWORD dwDiskData[256];4 q' X4 J3 T6 T
  149.                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件4 g3 ^8 p9 ]. i( ^( j
  150.                    char szSerialNumber[21];
    6 `+ _( S; W8 C% C
  151.                    char szModelNumber[41];; j3 o4 _8 {1 m( Z4 \

  152. : t' t% d2 S% M* A
  153.                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
    # ~: {( c; J% {  i- `+ t5 M% g# n
  154.                    for(int i=0; i < 256; i++)
    + _1 L6 _% R/ A3 f% z/ h8 v
  155.                        dwDiskData = pIDSector;9 F1 z" B, q' C! R, Y' p( O, p: D5 ~
  156.                    // 取系列号
    ) j) U; j0 F5 ^: o6 i( o
  157.                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
    + A$ `% U2 T/ i- \
  158.                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));% b: @/ j4 |- h
  159. 6 y: k' _* y; C2 U" i  a
  160.                    // 取模型号5 F- O7 U( D1 B0 @* Z
  161.                    ZeroMemory(szModelNumber, sizeof(szModelNumber));( Y* B" y$ U8 D$ f; J" |
  162.                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));8 M4 @% B) K% |' ], {) @# d
  163. . [' v" N- Q7 R3 d0 Z
  164.                    pSerList->Add(szSerialNumber);
    / Y0 p) N7 D$ m8 m/ B
  165.                    pModeList->Add(szModelNumber);
    3 l- t' B# D- f, u7 E1 i2 y% ~
  166.                }( z+ X: {/ `3 l6 U. |+ `
  167.            }$ A8 \, n& n# K: g1 f
  168.            CloseHandle (hPhysicalDriveIOCTL);4 l- \, G' k6 Y9 w* C9 H3 c
  169.        }5 T8 \8 _# w/ a; y
  170.    }" v; C. J- i, Z7 k9 d
  171. }
    ; k( |! o) O2 ^: l/ d
  172. //---------------------------------------------------------------------------& I2 L! Z: m$ e: j: d/ V$ d$ n3 }; G5 _
  173. // DoIdentify' K* T" \$ y4 {. g4 g7 m6 u
  174. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,8 Z& N2 Y7 o8 c: p& E
  175.              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,6 f/ b/ Q! ?: f
  176.              PDWORD pdwBytesReturned)6 H( M8 \! w. }- u2 ]! Y
  177. {, O! z& R2 e3 j; o; J1 f. E* E2 c6 ^
  178.    // Set up data structures for IDENTIFY command.0 F+ N3 O8 o/ _" ]4 M
  179.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;* Y/ v: @) {0 O9 x
  180.    pSCIP->irDriveRegs.bFeaturesReg = 0;6 w6 v5 h. Q9 U& X5 w/ z2 j
  181.    pSCIP->irDriveRegs.bSectorCountReg  = 1;
    " f% i& ~+ w/ O* l5 Z/ l, R
  182.    pSCIP->irDriveRegs.bSectorNumberReg = 1;
    0 j; n) L% s1 m' u+ ^) c
  183.    pSCIP->irDriveRegs.bCylLowReg  = 0;1 G! W8 a2 _6 F( o; ?! g
  184.    pSCIP->irDriveRegs.bCylHighReg = 0;1 A$ b! b; O3 F0 k7 }8 }/ b1 D

  185. 7 F; y' w. K* T& b* [/ d8 y% q
  186.    // Compute the drive number.(主盘和从盘所对应的值是不一样的)" P7 A8 P3 K% j* d
  187.    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
    " N2 b. ~& A- E8 s' c: Q5 U
  188. ' Q1 T; ]' b4 s3 a0 `
  189.    // The command can either be IDE identify or ATAPI identify.
    % M% d5 V' l3 ^5 ^
  190.    pSCIP->irDriveRegs.bCommandReg = btIDCmd;! f$ z1 W1 f) C* d4 c& A4 H
  191.    pSCIP->bDriveNumber = btDriveNum;" _$ y: ]! f; g! Q1 ?" b
  192.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
    " O5 k. K6 E7 F) K2 D9 ~5 S

  193. 7 r+ ~; t( E: f
  194.    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,9 L# ^8 S& r7 a& k
  195.           (LPVOID)pSCIP,: P. i" c; z( C8 q9 R4 r
  196.           sizeof(SENDCMDINPARAMS) - 1," t% j( J& U9 L: }( `1 r
  197.           (LPVOID)pSCOP,. b% ^, V4 G- _1 }3 o: I! ~- G
  198.           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,6 f6 H3 W, Q' }
  199.           pdwBytesReturned, NULL);/ G) `2 J3 p) q; w0 P# d+ e# `
  200. }9 b" ^7 v  G# `- \
  201. //---------------------------------------------------------------------------3 V( p$ p) b5 R7 I+ g) A
  202. // Windows 95/98/ME 代码
    1 ^# ?6 k- e8 Z
  203. //---------------------------------------------------------------------------
    7 H; A1 i+ R% M. H7 n7 z8 S
  204. // ReadPhysicalDriveOnW9X
    8 }8 T; N- R; p( R3 M# Q
  205. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)+ h& C/ s; D/ E2 h
  206. {1 z  I/ @1 @3 `% M+ P  {
  207.    WORD wOutData[256];' w6 V# j+ u/ U$ z) z% Y
  208.    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
    . b3 o; g7 C* C% b$ Z

  209.   \0 O+ n, J: `. T
  210.    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
    : A* T! Z% e1 f! X8 [
  211.    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
    ; F% p3 q4 ?5 X
  212.    // 避免蓝屏的出现。(期待高人能指出原因)
    ! @7 M! n2 Z$ A; j7 o; ]9 {9 S
  213.    for(int nDrive = 0; nDrive < 8; nDrive++)
    % @% W- |- E$ r  ~2 c2 n' b" T1 k/ ?
  214.    {3 c, O" k5 \- J* ~: p, R) |
  215.        WORD dwBaseAddress;9 M3 t% A' O$ ~2 v
  216.        BYTE btMasterSlave;         // Master Or Slave) w: @1 A) P! V+ H, R; f
  217.        bool bIsIDEExist;
    * A# H- i! f# U' ~
  218.        bool IsDiskExist;6 B8 f8 X% |* F+ ^% I. x! ~2 S( R
  219. . F, E! q! B3 q1 Q
  220.        switch(nDrive / 2)
    8 [4 d1 P* V# g
  221.        {
    ' }/ |* m8 O9 O
  222.            case 0: dwBaseAddress = 0x01F0; break;! z/ m1 o) \$ q) z
  223.            case 1: dwBaseAddress = 0x0170; break;
      s( x# Q2 N3 W
  224.            case 2: dwBaseAddress = 0x01E8; break;
    ) Y- v& ?* ?5 c) U% H# k
  225.            case 3: dwBaseAddress = 0x0168; break;
    * |; a1 I$ Z. ]9 \2 s  Z; j
  226.        }/ i' b! U) V. t+ S
  227. " Z& ^2 \. j( F+ q& x% A/ X6 j( J) g; x+ c
  228.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);$ }  _' P) ?1 v6 r

  229. 6 B  v. m7 V7 P6 \) G" t3 z3 C- Y8 [
  230.        // 进入Ring00 z* d% `! K; P0 z+ s( A+ q& a3 c
  231.        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,! [" G# N& ?* G& K4 O1 [
  232.                bIsIDEExist, IsDiskExist, wOutData);
    . Z! U5 n3 Z6 |+ V; M6 O. e) M
  233.    }2 t* E: |1 f# r
  234. 8 u% l7 z6 q1 }% s- `: I& O
  235.    // 开始读取
    6 }6 o0 ^4 F2 R( U% p
  236.    for(int nDrive = 0; nDrive < 8; nDrive++)
    4 b, b0 \4 [+ }! y! K
  237.    {4 _2 Y4 s; o4 D4 K1 Y* M
  238.        WORD dwBaseAddress;
    : f+ l; Z) a" e# z: r
  239.        BYTE btMasterSlave;         // Master Or Slave" N9 O5 C" K8 l( Q1 L0 z
  240.        bool bIsIDEExist;
    1 g, L* [3 p* h+ U+ U
  241.        bool bIsDiskExist;
    # w/ D+ `# M# e# D+ D. b
  242.        switch(nDrive / 2)
    ( l# ]: M" C. K, f% q3 M
  243.        {% H' w4 j+ q8 a% u. `1 y
  244.            case 0: dwBaseAddress = 0x01F0; break;
    ; w/ [2 S7 `$ ]# }! O1 \* Z8 B
  245.            case 1: dwBaseAddress = 0x0170; break;
    ) A/ q" n6 @+ ^9 h5 \" j6 ^1 p
  246.            case 2: dwBaseAddress = 0x01E8; break;
    ' R, m7 X; G, m
  247.            case 3: dwBaseAddress = 0x0168; break;
    ; H' V% {8 c6 u& L7 B
  248.        }2 M0 d# e* ]! g/ t

  249. * e; H4 O  ~; u: S+ G
  250.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
    / L" {! s3 M# z" Y

  251. * m# e" u% |6 V; U8 n4 c! _
  252.        // 进入Ring0
    : f4 S8 p: o4 V
  253.        bIsIDEExist  = false;
    6 S! ]3 X! l; `  ]6 \: ~
  254.        bIsDiskExist = false;& o5 h6 h  t% Y' m9 B
  255.        ZeroMemory(wOutData, sizeof(wOutData));$ g! O2 _- u2 E9 G: \

  256. 3 K6 t$ w3 n  E1 c5 Z$ I% k
  257.        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,3 J2 s) K* P2 w& o' o
  258.                bIsIDEExist, bIsDiskExist, wOutData);
    ' v+ o7 j; [3 P- I0 M* M2 R9 ~& q# `
  259. . G! ~# r3 q: E( }6 Y" j' g
  260.        if(bIsIDEExist && bIsDiskExist)
    " e: x. \# W& Y, G: v# Z, ^9 u8 V! I
  261.        {! w" u& p  V9 m; ^: R4 Z; H' ~
  262.            DWORD dwDiskData[256];
    9 m) S1 K/ P1 V' R) I9 D! _: y
  263.            char  szSerialNumber[21];& w3 D) o0 Y9 G2 m* n
  264.            char  szModelNumber[41];5 y/ s" w8 V4 U" X: W
  265. 8 W+ b' T; `* V
  266.            for(int k=0; k < 256; k++)
    6 x0 W3 B# M! w7 g/ R6 H8 u
  267.                dwDiskData[k] = wOutData[k];9 T8 S5 w- J- I3 L! `
  268. 2 L" S7 |+ v9 T* ]$ x1 _9 r
  269.            // 取系列号
    ' L) u" i( p0 ]( L/ A/ K
  270.            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));2 O2 i4 U4 \& Z3 D
  271.            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
    / S* N* B0 U4 |! H% B8 O
  272. 8 C6 h' g4 S- Y
  273.            // 取模型号! e: S/ E- @6 K! F1 v2 C% }
  274.            ZeroMemory(szModelNumber, sizeof(szModelNumber));
    , \/ u# v* n1 ]
  275.            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
    / F' {. N5 i: k- @# x" u

  276. , E# {4 e% {5 G0 J" j0 b% q
  277.            pSerList->Add(szSerialNumber);
    . X8 l7 L& e1 p. o0 D2 e: y7 a! R
  278.            pModeList->Add(szModelNumber);" i* ?0 L8 g+ n! \. X
  279.        }( l- Z/ u1 m7 |" u
  280.    }
    2 ?8 V- e, K* K+ h" R4 o. E% M  C3 R
  281.    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);0 u( t2 G) u& v! u, f2 ~* u3 q$ O
  282. }% Y7 |4 J! W% h: k: x" K, w! P
  283. //---------------------------------------------------------------------------
    * K/ I" c; h; b/ E5 c! J% \
  284. // ReadPhysicalDriveOnW9X_Ring0()
    - h. O0 K2 Z9 x' c2 l6 |
  285. //
    ' L+ I' p1 J1 c* r/ F) E- O
  286. // dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
    , s2 c) Z0 V& U: f7 T" p
  287. // btMasterSlave = Master(0xA0) Or Slave(0xB0)
    % o% n. W  U$ Z' N) n% @4 L5 y
  288. //---------------------------------------------------------------------------
    " Y1 a8 c5 `" X5 k
  289. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,7 k7 n. F4 b' N
  290.        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)) z. I3 G2 {  r; L
  291. {& E/ o( b; x. t
  292.    BYTE  btIDTR1[6];
    ( r* H$ |9 p# H! U: |6 \& ^
  293.    DWORD dwOldExceptionHook;
      V4 Q. l+ p2 r! t+ B/ R
  294.    const int nHookExceptionNo = 5;
    0 @( z9 t, G2 c1 E1 |
  295. 3 j% I8 t2 j0 ]# {+ q7 G
  296.    BYTE  btIsIDEExist = 0;
    % o  M0 N" y! B, e4 s4 {
  297.    BYTE  btIsDiskExist = 0;6 K7 m, A+ t9 I% h. R1 c  @. [
  298.    WORD  wOutDataBuf[256];
    0 C) Y9 ~  v. u! Z

  299. 6 H  |1 a7 K5 c; Q  X. P  \9 G
  300.    BYTE  btIsFirst = (BYTE)bIsFirst;* q9 }2 i3 _# E) P' B

  301. & h: ]' C2 g2 a; K1 G: ^2 c/ M( \
  302.    const BYTE btBit00 = 0x01;
    $ H1 J( g# W& ]' X" u- i
  303.    // const BYTE btBit02 = 0x04;- r" u, ^  Z( G& a1 C" O( V' H" P
  304.    const BYTE btBit06 = 0x40;/ B6 P3 W6 W  c2 v& K; ?% v. \! t
  305.    const BYTE btBit07 = 0x80;
    . I# t. w1 I( Y" U/ t
  306.    // const BYTE btERR  = btBit00;1 X  E2 u& v$ H  u! s3 N
  307.    const BYTE btBusy = btBit07;
    % A8 ~" J4 w8 w+ P
  308.    const BYTE btAtaCmd   = 0xEC;$ `1 x4 a! `" L; S$ {" {; p5 G
  309.    const BYTE btAtapiCmd = 0xA1;/ {7 s: ~- N' F+ z$ `6 T' s

  310. 6 I4 u- o- P# N: x
  311.    __asm+ z( Y$ D: a) w" E
  312.    {
      Z3 ?2 e, r8 k- g, n
  313.        // 必须先执行这条语句  t# x- N# M; D/ o
  314.        JMP EnterRing0
    7 [2 x, Y4 [, c; n6 A- q

  315. ; s$ c7 w( }# o1 R
  316.        // 定义过程
    & X( X' o& q0 N" Z) N
  317.        // 等待IDE设备直到其不为忙为止/ S6 q' `  [! j! G% \0 w% n
  318.        WaitWhileBusy proc1 F" o: W. k6 \9 U3 z, O4 v
  319. ( m1 H9 B0 j# w2 S$ `7 E
  320.        MOV  EBX, 100000
    ' c9 W' N& ^& f9 [$ b+ w
  321.        MOV  DX, dwBaseAddress# a4 C, B* k( j' c8 r. F& |
  322.        ADD  DX, 7& t0 b. x; E3 i3 T* ]
  323. 8 v" Z6 H2 B" p; @
  324.        LoopWhileBusy:& T! q2 m$ Y  d& [
  325. 7 ~8 M' U; f( V, {# k2 |2 p8 b
  326.        DEC  EBX* x  z0 D6 s/ d6 e2 E0 v: \
  327.        CMP  EBX, 0
    4 n3 v9 A$ @) a5 P
  328.        JZ   Timeout
    3 F5 K  F/ s- J+ [
  329.        in   AL, DX4 q4 g. X% M$ E6 w" m# M
  330.        TEST AL, btBusy  K  ^9 a+ D$ G; R4 {9 f6 Y1 g$ i
  331.        JNZ  LoopWhileBusy
    ' g$ i- ^: ]( L5 i. U0 S
  332.        JMP  DriveReady
    0 b& X  p% t: ~, \

  333. , _# {9 E1 ]  B
  334.        // 超时,直接退出) p6 Z. \1 P* a' m5 U0 }: t
  335.        Timeout:
    $ B: ~+ r  g( {4 {* |0 t  }
  336.        JMP  LeaveRing0. J6 [! W" O! c' d9 T3 L) E$ Z
  337.        DriveReady:
    , [7 q! a: q5 |" T* D3 A
  338.        RET2 t5 ]+ r3 o+ s! U1 e# ^( ~
  339.        ENDP   // End of WaitWhileBusy Procedure# G* n- I& A, b, G1 y8 y

  340. 5 ?. a2 Z0 s, _. K- l1 j( I! X
  341.        // 设置主盘和从盘标志
    ! N5 A8 ?, U/ h( \8 c7 d# {2 I, ?, b* x
  342.        SelectDevice proc
    5 ]$ }6 X4 T6 w* ]5 J. V* u- m

  343. + B. Y# `- W. M! p# H* V! q
  344.        MOV  DX, dwBaseAddress7 Y2 g' f$ V/ H
  345.        ADD  DX, 6. y: \/ U2 u6 P; c$ V
  346.        MOV  AL, btMasterSlave
    0 v4 V( O* Y! {
  347. ( Z8 M" Z% n& ~8 o( i
  348.        out  DX, AL- D! S. B  {' u! X4 c6 a
  349.        RET* p+ q  a8 W& ~8 k( G% i+ b
  350. 7 ?( r2 f' y2 S1 I1 g5 r+ n
  351.        ENDP  // End of SelectDevice Procedure1 }4 c* p& s1 m4 s. M. `( _

  352. & r& O6 D1 W8 b! j1 `
  353.        // 向IDE设备发送存取指令* x+ W) c% P  [$ C1 l  b5 G
  354.        SendCmd proc5 D& K0 o' n+ x; S9 |5 V  X, i

  355. 1 ?0 O/ \2 v* P5 C9 ?  @
  356.        MOV DX, dwBaseAddress+ w6 \4 j8 ?; P$ F
  357.        ADD DX, 7
    * X4 O+ l' S/ h$ @. ?& s  _
  358.        MOV AL, BL // BL是主从盘标识,在过程外设置& V1 I: I/ D0 B8 e
  359.        out DX, AL
      g( L3 X( Z3 a  M+ D
  360.        RET
    # \! N! i+ a2 \: P2 f( @% `0 C  Q
  361.        ENDP  // End of SendCmd Procedure1 Y+ D/ R% U; D; Q3 I6 n
  362. " Z3 Y# k( n, J! L" G
  363.        // Ring0代码
    + D9 t4 f3 J# _9 x6 F; A
  364.        Ring0Proc:& ]8 @) {7 Z6 u9 j& Q; J" L, o
  365.        PUSHAD
    2 y9 ]5 J6 {0 M- ~! i7 B, r
  366.        // 查询IDE设备是否存在- `. M/ D  O" \: U$ \, \  U7 m4 u  \
  367.        MOV DX, dwBaseAddress2 C- T+ B3 u3 b; s) i1 E+ E9 ]
  368.        ADD DX, 7
    6 y- C! u/ @- F6 k& O5 s
  369.        in  AL,DX. C/ M) F: Z$ v0 n5 ^& D, \

  370. ) T1 z' |+ v  u. {4 d) Y
  371.        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
    3 |1 N! V% y( l
  372.        CMP AL,0xFF4 W, B2 X) ?( R" D$ N
  373.        JZ  LeaveRing0
      j& |1 _- e( L& G2 O/ i9 l
  374.        CMP AL, 0x7F
    0 F' ~- C& n" [% ^( n  d: i* D
  375.        JZ  LeaveRing05 }' J- t2 h3 J( J

  376. : X7 g9 H( t1 S, Y2 X
  377.        // 设置IDE设备存在标志! m# v# F; h3 Q5 M0 n
  378.        MOV btIsIDEExist, 1% r+ i4 V5 w0 @2 w1 E. {5 Z( e# `
  379. - o! w* a% k% x" w: ~* B
  380.        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)* o. V* H" y* Z
  381.        CALL WaitWhileBusy7 E2 w# R9 b, d, K4 O" j) E
  382.        CALL SelectDevice" j& O/ U  b& l
  383. 1 i3 n2 o6 d2 f( @% ?
  384.        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏' o4 C, {4 z3 z) @0 Y
  385.        CMP  btIsFirst, 1
    ' h8 e5 m8 F! B" ]( H
  386.        JZ   LeaveRing0
    ) N. d. B- Y! B8 d) e

  387. ; a, Q2 s; Z" F# k9 V. v5 ]+ l
  388.        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
    ; X  S  N+ @# [  c3 G
  389.        CALL WaitWhileBusy$ B$ R6 D' I6 s- Y9 [# q2 [% s
  390. & w% K- r9 I; X! d+ n
  391.        // AL的值等于cBit06时,不存在驱动器,直接返回
    ' l# o* m# |  }2 n+ }" m
  392.        TEST AL, btBit06" C, G& Y" u$ {/ ]6 I
  393.        JZ   LeaveRing0$ A0 {3 X$ [, C2 X- O
  394. $ P  P0 L- ]# {1 ~0 ^' `% T
  395.        // 设置驱动器存在标志
    , F8 k) z0 F  m8 v: |: h0 y
  396.        MOV  btIsDiskExist, 18 ^; g+ H! p4 ~5 _( G7 `$ b4 Z

  397. % [4 D, a& j4 e$ T( B
  398.        // 发送存取端口命令: n$ q. I3 k) W* I$ L
  399.        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型," J8 r. b6 X9 P: n3 G& W% Y
  400.        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
    - M. Q( R4 c% r# R
  401.        CALL WaitWhileBusy
    % ?0 e  M: T! j% Q% [) S8 H! M% ~' Q" Y
  402.        CALL SelectDevice    // 设置主从盘标识
    " M. ^  B* g  j* b, x" k( b- l
  403.        MOV  BL, btAtaCmd      // 发送读取命令) P) o8 ^' N- E7 P4 [: o
  404.        CALL SendCmd* X7 ]1 P  }7 \, i; ]5 V
  405.        CALL WaitWhileBusy. Y! c9 u/ u" G7 r0 m

  406. $ y$ o$ \$ q! X" S4 n: J% A
  407.        // 检查是否出错
    ( W# h$ o8 f* ]
  408.        MOV  DX, dwBaseAddress
    ( h1 H1 Y' s( K+ v4 y7 K" k- f
  409.        ADD  DX, 7
    9 K7 B; K, \" }8 ~) r2 @- L$ H
  410. % A( V" J7 \9 y$ Q, d
  411.        in   AL, DX
    . Q, `$ s5 O5 z1 f

  412. * I* @7 W8 S) Y- _
  413.        TEST AL, btBit00
    " R. \7 V' `  x7 S" I
  414.        JZ   RetrieveInfo   // 没有错误时则读数据
    4 o& f4 _) J6 B* @( @5 m

  415. 1 L" y1 Q( H' O9 C5 Y8 u5 |
  416.        // 如果出错,则进一步尝试使用ATAPI设备命令
    - A# H# r& ~; l2 p& O2 G* X0 N
  417.        CALL WaitWhileBusy
    - g1 `- T8 w# u" c7 m6 K4 j% i. {  h
  418.        CALL SelectDevice
    : o, p$ E" N' {+ G8 \2 R+ H
  419.        MOV  BL, btAtapiCmd
    0 y5 u9 V9 w0 h2 W5 z
  420.        CALL SendCmd+ ~' v* i' N/ i* b3 q
  421.        CALL WaitWhileBusy
    , P2 Z. d- s) ?" Z. D; @

  422. " z3 n. x1 v9 C
  423.        // 检查是否还出错( r8 U5 v3 h& ]' A  w
  424.        MOV  DX, dwBaseAddress6 d# _" ~, X$ {
  425.        ADD  DX, 7# N5 c$ [5 E# u6 j! v$ H0 K
  426.        in   AL, DX
    3 {! v+ I0 b- m
  427.        TEST AL, btBit00! J2 D0 i: d2 y" t. {
  428.        JZ   RetrieveInfo   // 没有错误时则读数据
    & K( z- t; G  F+ F7 o6 W
  429.        JMP  LeaveRing0     // 如果还是出错,直接返回3 ]; m+ x  R0 D/ N5 H/ F( a

  430. 7 r3 W: f# X9 u. D5 f  t% S$ I0 h
  431.        // 读取数据
    - U! S# ?9 u! k" D" _
  432.        RetrieveInfo:# E  P& j, B- C9 \$ i

  433. 4 i2 f+ p% p  @- B3 x2 r- m
  434.        LEA  EDI, wOutDataBuf3 j! b0 L: L7 G, @- K/ ]2 F0 d
  435.        MOV  ECX, 256
    6 k3 w7 i) [& M8 |) l8 L
  436.        MOV  DX, dwBaseAddress) H  Z$ ~" K$ X- |
  437.        CLD
    5 [7 B. P. D6 x

  438. 2 Q& L( M( t4 q2 V/ I; [2 @$ K
  439.        REP  INSW
    ) H# N& D5 _" W* g: E( U7 z
  440.   y7 k& ~- O+ E- P
  441.        // 退出Ring0代码: P: k& g- S3 G! @
  442.        LeaveRing0:
    $ |# s$ C( ^+ w
  443. 3 Y- b0 u2 y) r. d7 S+ N
  444.        POPAD' D' P$ K; {6 t$ p. `& a. M
  445.        IRETD
    0 `* `" b: z8 p

  446. ! @+ ]; |6 B6 r
  447.        // 激活Ring0代码+ D  K( p1 y' H1 i3 C* D# L( S1 A
  448.        EnterRing0:
    7 ?7 I( A3 g- ^4 s: F
  449. 3 S, M. @- n& E3 W. a# x! u
  450.        // 修改中断门
    & V5 |( O# k" [+ w$ I3 \. L; x% n
  451.        SIDT FWORD PTR btIDTR1! H- ?  G' u- ^- l) {
  452.        MOV EAX, DWORD PTR btIDTR1 + 02h
    ( L6 G. l+ l, Z+ E* P' \! {5 y2 v" Z
  453.        ADD EAX, nHookExceptionNo * 08h + 04h
    % ]+ g" b6 V8 r% l; ^3 C
  454.        CLI
    7 j$ S/ q. |$ b9 Q) Z

  455. 6 }' F) Q9 [, W7 w# t: k  p
  456.        // 保存原异常处理例程入口
    & a8 h7 w' n$ p/ j& j9 I
  457.        MOV ECX, DWORD PTR [EAX]
    , H0 Z* F* u5 n6 [, S0 x
  458.        MOV CX, WORD PTR [EAX-04h]
    2 d: w0 n1 P5 K" v% E' M
  459.        MOV dwOldExceptionHook, ECX$ ]* e& F9 h" O+ m- `" X: w6 F
  460. " |! H' K# B& _, s/ v( }8 w
  461.        // 指定新入口1 ?% I/ J- N. E
  462.        LEA EBX, Ring0Proc; y; H, T' T0 g4 K) d0 C. w1 H
  463.        MOV WORD PTR [EAX-04h],BX
    1 w( T5 n% x8 Y- W3 q$ t
  464.        SHR EBX, 10h' v7 k8 w( @" Q$ Q
  465.        MOV WORD PTR[EAX+02h], BX+ \# X- j6 O) h, w
  466. 4 E' [- E! u3 J$ m. v
  467.        // 激活Ring0代码  |+ ?6 ?" ?2 |& U5 c; u& P  w
  468.        INT nHookExceptionNo9 Q# N3 U) E$ t

  469. % _. u; B7 j* x: z: w* Y
  470.        // 复原入口8 _! H1 {  F- F$ o9 B7 S! H+ o
  471.        MOV ECX,dwOldExceptionHook, R. O0 R& b7 T3 M  f( Y3 B0 T
  472.        MOV WORD PTR[EAX-04h], CX% ~" X& ?, v( f( ?+ K9 \' o! s
  473.        SHR ECX,10h
    # \( \& f- p- n; K8 @: V
  474.        MOV WORD PTR[EAX+02h], CX" p6 r6 ?$ a4 a$ k: j) N
  475.        STI* O( c1 c  U" Z  X4 Z" i' ?
  476.    }" I/ s/ S' R) `, n
  477.    if(!bIsFirst)
    2 F) Q: Y# Z6 m& Q
  478.    {9 X8 `% }4 e( @, a
  479.        bIsIDEExist  = (bool)btIsIDEExist;3 w4 B& ~7 F6 {: J+ h* [0 o/ Y
  480.        bIsDiskExist = (bool)btIsDiskExist;
    1 n; V$ ^8 Y  s5 Q2 `( K! Q
  481.        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
    " h" w* o; a% ?0 l7 a
  482.    }
    $ B  x5 x& N; g1 T  l
  483. }3 {! M8 j* Q& m
  484. //---------------------------------------------------------------------------4 g. `( }. P' k- F9 V! r7 s
  485. // 调用方法:3 p' n. c% F5 c* Z: `
  486. void __fastcall TForm1::Button1Click(TObject *Sender)
    5 g1 g* n. d: Z
  487. {- q3 n8 L# y9 y9 b
  488.    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
    - I. ?) e* M8 s8 L3 o5 @$ v& |! h
  489. }
复制代码
发表于 2005-8-15 01:00:45 | 显示全部楼层
晕乎乎。。。怎么看8 洞阿
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-5-5 06:13 , Processed in 0.016666 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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