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

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

[复制链接]
发表于 2005-8-11 11:42:04 | 显示全部楼层 |阅读模式
  1. #include <WinIOCtl.h>* E( ^8 g: p" V; F# c
  2. #include <stdio.h>
    : o% [6 k0 U& h8 e$ M% r
  3. 2 Q& R* |/ I1 L6 @! N
  4. #pragma inline
      y. C) K+ S( [" y# u* N4 q9 V
  5. //---------------------------------------------------------------------------/ ?( f4 A4 A' X
  6. // IDE NT/2000/XP专用变量* u4 n+ J' ]0 T, V5 v
  7. #define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS  R5 |* `, H1 l. z8 E# i' C
  8. #define DFP_GET_VERSION         SMART_GET_VERSION
    - D& N# b8 n  S* F$ [, Z
  9. #define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND" {$ q. E+ ^2 ?8 [# J
  10. #define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA' W! x" d+ E+ b  n
  11. 5 |' @; U9 S/ k3 e3 Z
  12. const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令
    % s9 {, [% J2 V, W7 q4 D% ?
  13. const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令; p8 ]6 C; N6 U; h: T" m
  14. : a! B1 G9 T* X. K( W
  15. const int MAX_IDE_DRIVES = 4;
    # v# i  F' \8 d9 \; l) k

  16. 4 w/ z, y, {1 o6 O  u
  17. // SCSI专用变量
    ) K6 B' n- e  Z( S# i5 F
  18. const DWORD FILE_DEVICE_SCSI             = 0x0000001B;( {3 G1 v2 e5 l& N) w
  19. const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);" \* ?7 o0 y# V, ~( l
  20. const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition! t. {& D9 S: y9 s& B' F8 @
  21. const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
    0 e! Z' S' Z2 N0 M- a
  22. 6 x( f& S7 s% `/ t' u( |3 K
  23. typedef struct _SRB_IO_CONTROL
    8 g" D: j+ ^$ ^: p& D; \
  24. {4 ]: V: R: n2 g" Y" N9 @; T7 j
  25.    ULONG HeaderLength;
    $ p6 h* u8 E9 S5 W2 B
  26.    UCHAR Signature[8];
    ; x- s2 d3 }, I0 E7 ?. b( R5 z
  27.    ULONG Timeout;( y5 N- E0 ~6 q/ L2 z7 e1 {
  28.    ULONG ControlCode;
    3 X3 t8 u- g1 B9 S
  29.    ULONG ReturnCode;5 j3 E% a. v: M2 t( Z1 H' k8 \
  30.    ULONG Length;
    & h1 k) M1 T2 {" `. b" D8 }
  31. }SRB_IO_CONTROL, *PSRB_IO_CONTROL;
    3 y' W0 Y+ J& ^+ ?% Z
  32. . D$ t' s3 f9 X/ c7 x. R
  33. // 读取的主函数" I: Y; Y1 ~1 @' x  g! d2 w! N
  34. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
    7 a$ Z8 ~. J+ ^0 H& h0 U
  35. ( |$ I1 D) H( f6 y0 n( c( A8 |
  36. // 辅助函数
    9 j- A' e, b* i4 m$ ?2 i' Y
  37. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);/ m/ Z6 R% ~1 U
  38. // NT/2000/XP函数9 [% d2 r4 k. H" ^" X2 ?) a
  39. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);% N- c2 @( x2 F! C* \6 a
  40. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
    8 P# X3 \- k; V2 s" X1 J- M. c. z  j
  41.        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
    ; u& x- t+ p' p
  42.        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
    : |: B1 v  M' {7 K: U5 H
  43. // Windows 9X函数+ j5 d& ]' I1 B/ |& n$ b
  44. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);* Z9 I2 r3 z* b
  45. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
    8 u+ F& R4 K% ]: b1 M7 x# ?2 r: u
  46.        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
    1 ~  `* {8 [$ m, A

  47. 7 D! ^6 x/ W1 i  j$ n
  48. // SCSI读取函数(for NT/2000/XP)
    % k9 b- [/ ]3 f7 h$ Q2 B, c( Q
  49. String __fastcall ReadIDEDriveAsScsiDriveOnNT();; G+ H9 i5 @/ f2 r' d
  50. //---------------------------------------------------------------------------$ S$ h. t* I: c, x! F' ~
  51. // ReadPhysicalDrive- R- T# {7 y' y% D2 d- k( s' E/ a
  52. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
    8 q0 _7 S# |/ H7 q
  53. {/ B  i, o% Z4 w3 A+ C6 f8 L
  54.    switch(Win32Platform)' T% \5 n: l, M, S9 }7 f% a4 N
  55.    {
    , o) N7 Z/ i5 y* }! L8 G
  56.        case VER_PLATFORM_WIN32_WINDOWS:8 X! N$ o. @) |( g; P+ A
  57.            ReadPhysicalDriveOnW9X(pSerList, pModeList);% H. F& u9 r# s
  58.            break;
    * X& K1 d6 ^9 a5 x' d/ B
  59.        case VER_PLATFORM_WIN32_NT:
    ) v/ n& C2 z; I' G
  60.            ReadPhysicalDriveOnNT(pSerList, pModeList);/ {; k+ \& K% [% A5 V$ q. |
  61.            break;1 {1 Q, G1 F1 d) Z- k+ H. L
  62.        default:
    8 m8 K$ O- }9 M  T7 s
  63.            break;7 K0 I* H  L3 n/ G
  64.    }
    : G0 j& C; I- l8 }' u
  65. }7 A( E# p, a7 B( E& l
  66. //---------------------------------------------------------------------------
    / ], y. j5 ?$ e+ h0 G
  67. // ConvertToString
    * w! j+ }* |: P5 ^! r
  68. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
    0 C9 ~4 R! X, y5 U
  69. {
    ! W1 S% q( E7 j& O
  70.    static char szResBuf[1024];
    7 M. n" p. h# \- m9 L# d( t
  71.    int nIndex = 0;
    0 q0 ?' V7 h' \( |/ P
  72.    int nPosition = 0;
    * [% `; n( k+ J% S' Z" u/ r

  73. ' l. Y, ?9 c" }: G
  74.    // Each integer has two characters stored in it backwards
    1 N  h' B0 p& R1 E
  75.    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
    / K3 Y1 p: T0 U9 B
  76.    {1 v" t& m: U- }5 ^; x
  77.        // Get high BYTE for 1st character; v  I: _2 F& \6 M8 X
  78.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);  X' I6 c: E; p4 W/ b
  79.        nPosition++;- c) o% H3 D) y6 v% @5 Z! s& b5 C  L

  80. 7 r0 O/ P1 A$ Z, N! v6 f
  81.        // Get low BYTE for 2nd character
    : ~" e3 k7 p+ X. T; ^6 ^
  82.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
    ! C6 g, {6 Z& g8 l. |/ S7 C. x4 v
  83.        nPosition++;
    / \; V- x" W* x9 B3 p5 F
  84.    }* j9 L  A2 B0 m9 Q

  85. ( G# q- H1 v0 W6 e9 t
  86.    // End the string
    0 K! g! R  V" L3 z% Q3 x
  87.    szResBuf[nPosition] = '\0';/ w3 m3 X, j" L- h  f

  88. 3 h4 R- j8 D; _& I; w2 j. H4 f
  89.    // Cut off the trailing blanks& d. Y2 v+ d- k- L  G' G9 }
  90.    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)9 k$ @0 P0 P! V. s8 K& L' `
  91.        szResBuf[nIndex] = '\0';
    & d5 Z3 R1 A( B3 D( t3 }  M
  92. 9 F2 W6 T/ M$ W
  93.    return szResBuf;% E  A, u2 Y8 @: E, y
  94. }
    ! D/ c2 k" G8 @3 d( O
  95. //---------------------------------------------------------------------------) [3 _- |5 q/ {! E# B: O) q
  96. // Winndows NT4/2000/XP 代码& `% G0 E: R) R7 |
  97. //---------------------------------------------------------------------------) q4 r9 `( S' V$ O! b
  98. // ReadPhysicalDriveOnNT
    - y( J- W- D3 I" b# L: s
  99. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
    ' O+ J( f- T, n+ F
  100. {1 x4 C) b5 i' a
  101.    // 输出参数' T; p7 x3 H+ d4 k( y4 X. c
  102.    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];. E( F6 M# r8 U6 q$ U$ x

  103. 2 c% Q! e! ~0 O4 m) r4 e4 y
  104.    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)/ N0 d; S( S7 d% `- {6 G
  105.    {
    3 [6 }# W! D4 s& V$ N, M* U
  106.        HANDLE hPhysicalDriveIOCTL;3 G# B) c' g) x* j; m  J' m
  107.        char szDriveName[32];
    , a: @& J7 M! |
  108. ( _$ M. I, W8 [% x& ~
  109.        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
    6 L2 N+ ]* G" i0 a" V4 O
  110.        hPhysicalDriveIOCTL = CreateFile(szDriveName,: t& o4 A* }+ w8 j' h7 i# q
  111.                        GENERIC_READ | GENERIC_WRITE,
    2 q! h4 u( l# z5 j, z4 z5 y' ~
  112.                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
    : o& ?2 G. I" l4 {5 k
  113.                        OPEN_EXISTING, 0, NULL);
    1 B9 @& c. w0 @7 Q4 u
  114. / U# u7 ~3 ?8 X3 g$ l
  115.        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)9 P% a1 `! k9 I% M; e$ j
  116.        {1 ^% _7 i! d5 S  F; X* O% Y
  117.            DWORD dwBytesReturned = 0;
    + V# K4 _6 r- J" s
  118.            GETVERSIONOUTPARAMS gvopVersionParams;
    ) ]7 ^2 z( u9 T) _8 |( o
  119. ( {, G0 R7 @& L, w2 Y! D: k9 `
  120.            // Get the version, etc of PhysicalDrive IOCTL
    / D" N# B" c/ x1 c! m3 K' H8 V# D3 c
  121.            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
    ! j' X9 K2 ]% p! j( c3 f4 G# M/ Y7 b+ {

  122. 9 u0 `# S% }* [* U( i* q
  123.            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
    $ q- T  a0 ]' I4 M
  124.                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
    8 g$ }- L8 R$ I/ {1 M; r
  125.                    &dwBytesReturned, NULL))
    / Q' d! ^5 Z# q: v- W; v' n
  126.            {: {5 C# R1 p- e
  127.                continue;
    * b- U- t) \. \8 G; x
  128.            }7 U+ H) y9 W9 E. A

  129. 6 b: ?4 n# z! y9 @6 U5 k4 M- _
  130.            if(gvopVersionParams.bIDEDeviceMap > 0)
    ( b' M. N- v0 V' m
  131.            {  b6 U# s% S$ d8 z; ^; k
  132.                // IDE or ATAPI IDENTIFY cmd9 e- Z( c+ B% u5 Y& c4 p, g  U0 X
  133.                BYTE btIDCmd = 0;
    9 p- t0 _* y5 f# [5 k
  134.                SENDCMDINPARAMS InParams;9 ?6 e/ Z. P% k6 [: X# ^
  135.                // Now, get the ID sector for all IDE devices in the system., O" Z) F# h5 L* P
  136.                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
    ( g4 C6 J; t! k- G& Y; M1 J
  137.                // otherwise use the IDE_ATA_IDENTIFY command
    2 C. ~0 X; Q7 ~7 v
  138.                // 具体所得结果请参考头文件中的说明/ |# A1 X; e  h
  139.                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
      ^3 p( m1 N& `
  140.                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
    % L8 y* _: m% e$ A7 `/ |
  141.                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
    : B) f8 G, D7 h, f& ^
  142.                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
    8 [# P* {  ^1 W) |

  143. % C1 V& u" T. B6 L5 |1 Q
  144.                if(DoIdentify(hPhysicalDriveIOCTL,5 _* F* d9 x# R5 w
  145.                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
    3 G* d0 _- b5 g- O7 m
  146.                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
      g- J; N5 @9 G) k7 U1 O' U
  147.                {- v, p4 k9 Y2 h1 t" I# p6 u
  148.                    DWORD dwDiskData[256];
    ' v! t1 F4 N! s. @9 u
  149.                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
    " c! d, U/ r3 R: C. T
  150.                    char szSerialNumber[21];
    0 e% e0 F0 r& H. S* w$ J/ Q5 \- F
  151.                    char szModelNumber[41];
    1 g9 c3 d1 w# l' }& _

  152. % M$ Q  j- f9 {6 }/ E
  153.                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;1 n, C% Q& p! r3 a- Q# p8 l$ o
  154.                    for(int i=0; i < 256; i++)
    - Y: _% P  m& V' u
  155.                        dwDiskData = pIDSector;
    . D1 Y6 x  _1 \
  156.                    // 取系列号
    ' ?4 t% }1 c% _+ M! q* w
  157.                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));5 g9 v3 F& U' j
  158.                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));& t' R1 f1 ]6 [0 C9 s

  159. # A& |' ?9 L% B  H7 H+ t
  160.                    // 取模型号
    0 b; l, C& [+ L4 B8 [% b7 u! T
  161.                    ZeroMemory(szModelNumber, sizeof(szModelNumber));8 d  Y' i% {. t6 e5 [
  162.                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));' x- w; z2 Y# p% R; V
  163. 0 V) f* L5 Q9 u: ~5 W8 B; j
  164.                    pSerList->Add(szSerialNumber);
    5 x! E0 P& U" i- n6 ^* y* n2 R
  165.                    pModeList->Add(szModelNumber);
    5 o( c; q. n$ o* \% {
  166.                }9 c4 ?# C. E/ @3 n9 i- x8 h
  167.            }+ e! h' M, t) I0 y
  168.            CloseHandle (hPhysicalDriveIOCTL);  d+ J; ^" U. g7 O! p0 v: ~
  169.        }
    ) }7 y) F8 W# t& f
  170.    }  u0 }9 `) A5 y- d7 u  q% f
  171. }
    5 J$ E" }7 n% X5 d* D5 R
  172. //---------------------------------------------------------------------------
    " ?( A7 [. X0 C; x" k
  173. // DoIdentify
    9 u; [/ t+ i' [+ D
  174. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,. U% X  z- H- W+ O
  175.              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
    8 g& {( `0 V' N1 F. [  |( d! i
  176.              PDWORD pdwBytesReturned)
      F0 H4 }1 A# c* z
  177. {
    * q. a% v; R( M0 x
  178.    // Set up data structures for IDENTIFY command.) |1 s0 L2 [- x- j# G) F; c7 O3 x+ j2 ?. H
  179.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;, m1 p, t% D8 Q  o/ K
  180.    pSCIP->irDriveRegs.bFeaturesReg = 0;
    & _  C* B) j! p
  181.    pSCIP->irDriveRegs.bSectorCountReg  = 1;
    , J' i& K2 A6 H. U; |1 X2 d. V, H
  182.    pSCIP->irDriveRegs.bSectorNumberReg = 1;
    3 e% R6 [6 G8 _0 V
  183.    pSCIP->irDriveRegs.bCylLowReg  = 0;, z+ O1 i, f* Q% W; t! V
  184.    pSCIP->irDriveRegs.bCylHighReg = 0;( u: T5 o) H4 i

  185. , b7 \5 @4 E$ ]4 E
  186.    // Compute the drive number.(主盘和从盘所对应的值是不一样的)
    3 a. j: `* T/ V  V6 b4 J
  187.    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;; @+ K- K& |$ }/ y7 e6 Q7 r5 o

  188. 7 f: T- G7 I7 }2 {
  189.    // The command can either be IDE identify or ATAPI identify.2 q- ]& |/ S; m& ^% Y  F4 b
  190.    pSCIP->irDriveRegs.bCommandReg = btIDCmd;+ |3 l. `0 L7 r# \
  191.    pSCIP->bDriveNumber = btDriveNum;
    $ |, V# M: r5 C. I1 S. q" a8 Q
  192.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
      _1 k: ]* m- J7 O

  193. . t: G: i# l* R, J. {
  194.    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,, b. H) y( P2 O& D! j! C) a: M
  195.           (LPVOID)pSCIP,1 R9 ]1 a0 L- t. C3 @" J
  196.           sizeof(SENDCMDINPARAMS) - 1,+ Y) R! e# w; U+ z, P
  197.           (LPVOID)pSCOP,' c. k- Z9 Q9 o! M: h: Q
  198.           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
      Y% z# R2 {  X  e3 ^/ B
  199.           pdwBytesReturned, NULL);7 \: r4 P+ g8 H3 K
  200. }
    . C* o' O. n5 ?5 x7 P1 I% D
  201. //---------------------------------------------------------------------------4 x8 O0 W5 Q8 y% y8 \" w
  202. // Windows 95/98/ME 代码4 m" _- t! D. A3 c) e
  203. //---------------------------------------------------------------------------& \# _& [$ w& G9 `
  204. // ReadPhysicalDriveOnW9X0 f4 W( w( O0 W% F2 C; f
  205. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)8 W( |3 k9 z( [6 ?
  206. {
      l; s* ~. Q6 `% ?3 u& w9 u
  207.    WORD wOutData[256];
    # W" U2 c+ W: B0 s$ S+ s2 _
  208.    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);$ D3 J" a7 D3 Z+ |; [* {5 C; k# P5 C
  209. ) C: I* K- }, ?# w5 J
  210.    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。$ \/ K" Z+ I! `
  211.    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
    & D1 k1 q0 m" C# [! A8 R
  212.    // 避免蓝屏的出现。(期待高人能指出原因)
    7 U) ~# v3 D2 ]7 F9 f  w: S! q+ d
  213.    for(int nDrive = 0; nDrive < 8; nDrive++)( m: N. E/ a& ]# W7 m  R/ i
  214.    {
    ( @- t/ w$ x4 R5 f% `8 I
  215.        WORD dwBaseAddress;
    ( q) C& r0 X  r, K# O) R- ~0 ?% [
  216.        BYTE btMasterSlave;         // Master Or Slave
    + ?) `7 C& l. |' P+ ?
  217.        bool bIsIDEExist;/ Q+ ]2 }+ _, N. I$ ?' d
  218.        bool IsDiskExist;* T8 D. N! f7 h' f' @4 k

  219. . \4 Z$ N& B/ E
  220.        switch(nDrive / 2)
    , ~' U3 D2 ]! C9 P2 a5 s3 e+ d
  221.        {
    9 h1 H9 }2 P, m. p2 b0 r* [
  222.            case 0: dwBaseAddress = 0x01F0; break;: l7 S; d1 P1 K) r6 T8 B
  223.            case 1: dwBaseAddress = 0x0170; break;
    ! n( |4 w1 k7 m% K
  224.            case 2: dwBaseAddress = 0x01E8; break;
    % H$ `3 @$ z! A; u9 g
  225.            case 3: dwBaseAddress = 0x0168; break;
    ( E6 c3 S7 W) Q9 b7 ]- M/ n$ c& p
  226.        }
    6 N5 v/ a! h  j2 E' Z6 A( c+ a: g
  227. ' U; ?4 |  m; Q6 H+ C
  228.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);! m; U3 X/ x* Q

  229. , |! U8 T6 Q5 U8 g8 l
  230.        // 进入Ring0- `! j: y6 t( g6 U9 M8 y
  231.        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
    0 W5 @/ V  ^2 g+ v+ I/ I9 V' {
  232.                bIsIDEExist, IsDiskExist, wOutData);
    4 n; g) @6 l& V9 x1 H
  233.    }
    $ U$ o+ T( S1 S- P' P5 @( D& s$ z+ ]

  234. , U0 o( W' T& z5 {( i
  235.    // 开始读取
    " G" `6 J7 g  {% V! S# E- \! U
  236.    for(int nDrive = 0; nDrive < 8; nDrive++)- W' ]. q. P2 ?  P/ M
  237.    {5 c" Y: X+ M" x6 u% K  V6 u
  238.        WORD dwBaseAddress;
    & r2 ?/ m, a" P7 S! f
  239.        BYTE btMasterSlave;         // Master Or Slave. {- a3 f4 w2 |3 m
  240.        bool bIsIDEExist;
    8 N  |' H5 r$ N" z5 O+ L- |/ I" ?
  241.        bool bIsDiskExist;$ N3 A0 U/ B& j0 {4 Q2 I7 Y
  242.        switch(nDrive / 2)
    & E5 A! f2 f. Y- _1 E
  243.        {1 P9 n' r( ?( @* p0 L) O9 V
  244.            case 0: dwBaseAddress = 0x01F0; break;+ m  U) p( }, P& L' j& ?
  245.            case 1: dwBaseAddress = 0x0170; break;
    8 C9 P5 ^6 ]( ^5 ]  t
  246.            case 2: dwBaseAddress = 0x01E8; break;
    8 `  {0 e8 d+ l! l+ I
  247.            case 3: dwBaseAddress = 0x0168; break;
    , W8 L4 q5 c, x$ e0 o4 v  o& a
  248.        }
    ( ?- i; C+ r4 p2 C/ O
  249. 2 z1 B; V* f& A7 e5 g
  250.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
    7 m' J- J6 P8 \. k; a. b) Q

  251. * K4 g- U- D2 s/ L
  252.        // 进入Ring0: W, j" m. y" ^; v2 r% E3 N4 _
  253.        bIsIDEExist  = false;
    , k8 a3 w$ o' v  b* `% B1 T: v
  254.        bIsDiskExist = false;  H* x: ^4 r; H  O
  255.        ZeroMemory(wOutData, sizeof(wOutData));0 R3 o- t  g! v- T  y0 j1 h

  256. 9 c$ J5 z! W; m" M# V( g' b1 _8 Q
  257.        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
    6 U5 C/ ?7 ~( B
  258.                bIsIDEExist, bIsDiskExist, wOutData);
    + K) p( b3 L/ @
  259.   g2 H2 e, Z0 C4 ^
  260.        if(bIsIDEExist && bIsDiskExist)
    * z5 l) K- T. f! c7 ]
  261.        {
    7 o3 k# K' j( s8 |
  262.            DWORD dwDiskData[256];
    0 H0 F& L, x, Z+ ^  ~* s
  263.            char  szSerialNumber[21];+ H& \; D& u) o/ Q' z
  264.            char  szModelNumber[41];
    ( @0 i2 E' s# `- k- V: E
  265. + I$ i3 l! x/ S5 p# K6 O( J
  266.            for(int k=0; k < 256; k++)
    " a* f7 d6 ^2 e- \8 |& A4 w- h/ O
  267.                dwDiskData[k] = wOutData[k];7 _4 ]2 X9 Q6 E1 @

  268. ' n9 U% W/ a& r
  269.            // 取系列号
    - m2 v# O* [6 Q, a! z4 p
  270.            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));( N* `. P, F$ l. n2 p' ?% [
  271.            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));' @# o' g' Z  u) B8 e4 W

  272. $ A0 `& O  P( ]! D; p2 r" O' g
  273.            // 取模型号
    - C& h$ w& c9 K& E- V9 Q
  274.            ZeroMemory(szModelNumber, sizeof(szModelNumber));
    * A3 D, a" w; Q. A
  275.            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
    1 j6 ?+ V# T7 N1 q
  276. . }7 y# A! y& j3 z! q& \
  277.            pSerList->Add(szSerialNumber);; v9 j# x$ R# v
  278.            pModeList->Add(szModelNumber);) x) \- o$ [  H- G5 |2 R; a& X
  279.        }; s. x! z9 P; Z7 A; \4 `' u1 E2 f) T
  280.    }
    ( b( k0 Y" z$ X* b9 P" n; k4 _
  281.    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
    ' X5 g$ t  K" ~
  282. }* A( r7 }! }8 U# U5 [/ X9 J" \5 X6 |
  283. //---------------------------------------------------------------------------5 h7 @7 \# `+ C; r2 B: `( b
  284. // ReadPhysicalDriveOnW9X_Ring0()
    ; t3 O* n( A' R
  285. //
    ! d7 ~) _+ j: J, e$ A, O
  286. // dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h1 w) H- s: y- u0 L. ?
  287. // btMasterSlave = Master(0xA0) Or Slave(0xB0)2 m0 r  q  l  k
  288. //---------------------------------------------------------------------------
      N6 Y2 r2 e' ~! K; z1 j0 e- F
  289. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
    3 ?: @* M- T# R3 z. h5 {9 k
  290.        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)4 |- @( g' T7 X  C4 a+ ~5 j
  291. {7 \$ C) P( O& b0 m7 h
  292.    BYTE  btIDTR1[6];, [/ \3 Q8 i" h: n; w
  293.    DWORD dwOldExceptionHook;3 U- t! O9 `1 ~8 L0 m
  294.    const int nHookExceptionNo = 5;" Q- E$ h& t5 `& M5 z7 \. G
  295. / x+ v- D6 D3 N& E
  296.    BYTE  btIsIDEExist = 0;
    ( z. t( O7 _- n3 t( A  g# j. F# ~, ?
  297.    BYTE  btIsDiskExist = 0;
    - ]$ W0 D4 Z5 I3 g9 O; A+ q
  298.    WORD  wOutDataBuf[256];, n/ T& m3 T) u

  299. 8 ~0 P2 z/ [  Q/ h( a( X; I8 h
  300.    BYTE  btIsFirst = (BYTE)bIsFirst;
    0 o3 x+ I, f' g5 W( x+ B5 D
  301. $ O5 M; X# d; T$ d$ I7 {( b
  302.    const BYTE btBit00 = 0x01;
    : e3 _4 G: R  v: L; w! J
  303.    // const BYTE btBit02 = 0x04;
    # V. ~& |" o" {7 M: A  t9 k
  304.    const BYTE btBit06 = 0x40;
    ' L3 A5 T, c7 m, K% D
  305.    const BYTE btBit07 = 0x80;
      Y( ?3 v8 u+ R) D0 C# r
  306.    // const BYTE btERR  = btBit00;
    , w4 a3 m5 ^; J  a9 g+ \5 H0 g# A
  307.    const BYTE btBusy = btBit07;( F- \# j8 m" ^% v: a. O
  308.    const BYTE btAtaCmd   = 0xEC;; D3 G! Z! f$ |6 c$ f
  309.    const BYTE btAtapiCmd = 0xA1;, G0 U$ |: ^! r& k% @- b4 u

  310. ; P3 n: V; {. ?0 |
  311.    __asm; p5 h+ U, f3 G" d: F7 Q! a
  312.    {
    - m# H; {3 B' c: a  I7 Z; x5 \
  313.        // 必须先执行这条语句7 b0 Z2 i/ y( a; t! h6 Y+ k+ n. X. G9 W
  314.        JMP EnterRing0- r2 D0 C9 m% u3 k

  315. , C$ H+ s9 [6 p8 v
  316.        // 定义过程
    % A' l1 a; `  ^
  317.        // 等待IDE设备直到其不为忙为止
    4 B0 H* C5 V  D( Q! a) S* ?
  318.        WaitWhileBusy proc
    & |8 R8 q8 K6 t4 ~( C
  319. * N* w0 W7 d( S( I9 P; @
  320.        MOV  EBX, 100000
    $ d% g1 o3 C5 o4 r+ w* F" W) G
  321.        MOV  DX, dwBaseAddress  j6 z: g7 l5 |
  322.        ADD  DX, 7
    1 l9 A( ~  e+ @- W1 I
  323. ' S& V5 K( p( e
  324.        LoopWhileBusy:! X2 @3 O) Y( q0 T

  325. 2 @4 S1 |) N! ^- C1 ~; k
  326.        DEC  EBX
    6 f4 K# n, g5 j$ X& P
  327.        CMP  EBX, 07 K5 ]4 i& G% M; M1 u  p. h' L
  328.        JZ   Timeout: T2 V# n$ b  F
  329.        in   AL, DX
    9 _4 ]  l  |/ u8 Q
  330.        TEST AL, btBusy0 x! X: J/ A0 E$ C
  331.        JNZ  LoopWhileBusy. ~4 c* i2 a7 R; E' K; h
  332.        JMP  DriveReady# C! K$ g- H  n" h' q# \

  333. " O) M+ L; J& v) s  x  N
  334.        // 超时,直接退出
    4 l! T0 [5 ?; _# m% u/ r: P- M
  335.        Timeout:2 [/ o1 |% K6 U6 G- y: C  ]  S
  336.        JMP  LeaveRing05 ?, v! c/ H, n3 h
  337.        DriveReady:
    . Q# R. U6 y6 B, a5 p
  338.        RET
    3 w1 o6 T! n4 u& e9 a
  339.        ENDP   // End of WaitWhileBusy Procedure
    8 M% \- z6 j0 n; H
  340. ) F9 T: w% S! m% e/ T
  341.        // 设置主盘和从盘标志
    1 K# t4 U' s8 f- i1 g7 J: R! b
  342.        SelectDevice proc
    ; Z7 V( h: G1 O  Y3 j8 l4 x
  343. 5 [  J% i! W$ t0 A  V8 y
  344.        MOV  DX, dwBaseAddress
    0 S) i/ n: N: H1 x% ^9 ?8 ]
  345.        ADD  DX, 6: y+ Z4 Z$ N8 F) D/ A& A/ N, d
  346.        MOV  AL, btMasterSlave
    9 N) ~( d3 B% C
  347. 4 s) [: O1 b8 D! m
  348.        out  DX, AL
    , j5 b1 w7 C0 ?5 n
  349.        RET1 R3 d; b" c  O; U  v5 T
  350. ; X1 Q- f1 C# o, k& `0 D7 I5 \
  351.        ENDP  // End of SelectDevice Procedure5 s+ I8 U& x" H8 {1 v
  352. 7 \$ P; G+ i% G
  353.        // 向IDE设备发送存取指令
    8 z+ Y# |) d$ F& @
  354.        SendCmd proc
    ! I! m# C% {) ~% J& O9 N. ]- r2 x' @

  355. * D- o! z1 w7 v' I# D
  356.        MOV DX, dwBaseAddress
    7 A' X: H0 I: W& [( m
  357.        ADD DX, 71 T0 r' ~/ |% E$ j
  358.        MOV AL, BL // BL是主从盘标识,在过程外设置
    ! X6 Q6 a6 S0 }+ R2 m' e
  359.        out DX, AL
    $ z& K' z2 T$ R, t
  360.        RET* I; t; B2 Y3 K2 w
  361.        ENDP  // End of SendCmd Procedure
    1 s8 S* ?1 P+ d6 H/ v
  362. 9 C  x& m. \$ n8 I
  363.        // Ring0代码* `3 h! G  `  N# J2 f
  364.        Ring0Proc:* p5 b9 v0 a8 M) @3 [
  365.        PUSHAD# t8 m' Q" H) |% Y. s# L" F: r+ Q
  366.        // 查询IDE设备是否存在
    ; c# b! [, f* [
  367.        MOV DX, dwBaseAddress! q! |6 j6 p* W9 w
  368.        ADD DX, 7
    $ b& T6 Y# I4 K/ {2 i; ^
  369.        in  AL,DX
    0 q3 W( V2 R3 D; M* c

  370. 8 f$ a# Y8 F8 t! p& M
  371.        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回3 s: a2 Z3 i( ~' j" z, }
  372.        CMP AL,0xFF5 V9 l- f' ]8 ^. |! t2 ~" i
  373.        JZ  LeaveRing0
    1 y: K, `* T% O. J  t2 s7 p  _! X
  374.        CMP AL, 0x7F
    ( N  _: e+ _- a  p) ~1 n! O
  375.        JZ  LeaveRing0' O% T7 A7 _- l7 C# V% M/ ~5 s
  376. - R: O& j7 D# f  E# n. \) f
  377.        // 设置IDE设备存在标志
    " Z# K3 d6 d% w* ^
  378.        MOV btIsIDEExist, 1! o' i$ f5 f" [  t
  379. , }/ Y5 }; J! w9 f8 O, S
  380.        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)0 m8 x! k# P( t5 f2 h! v; H
  381.        CALL WaitWhileBusy. w: n! A0 o$ B4 `. V' f  ^+ |  p
  382.        CALL SelectDevice
    3 E) w) m, @8 I# K
  383.   {7 {% Y6 s' m
  384.        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏. o# o! `  Y1 T9 ^/ W+ h5 c, ?! l; J
  385.        CMP  btIsFirst, 1
    " N1 C! y  F4 |+ }" C3 |* n
  386.        JZ   LeaveRing08 c. A9 [" \( {' W  |

  387. : S8 G9 K( P! m) w8 O. j, ^
  388.        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???1 g$ l. s7 R& `  Q# J8 X
  389.        CALL WaitWhileBusy
    9 ?7 X" \! R  c" G8 ]9 |

  390. 9 K. V  n6 ]0 k3 N! g9 m! r4 V
  391.        // AL的值等于cBit06时,不存在驱动器,直接返回
    4 h0 @8 u4 O* u. y: }
  392.        TEST AL, btBit06
    9 g' E* _; _) H2 v' t
  393.        JZ   LeaveRing0( \: [. Y2 v! v+ f# T1 D
  394. 2 u" Z) \7 c/ G0 Q& R$ [, A
  395.        // 设置驱动器存在标志
    ) r& {7 w- z& Q  i
  396.        MOV  btIsDiskExist, 1
    # t! ~# P9 \, n7 H2 y( c
  397. % P- L5 y! q4 U- R* y4 w8 |
  398.        // 发送存取端口命令
    % c: L0 Z* B0 P3 W( A  l
  399.        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,  V+ y1 e; U! z( _
  400.        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
    3 K& h/ |# r- |' Z
  401.        CALL WaitWhileBusy
    - y7 N3 m7 Q( @) J* a/ ^; i
  402.        CALL SelectDevice    // 设置主从盘标识
    7 S: g: L* p+ @$ M7 Y+ o4 T) c
  403.        MOV  BL, btAtaCmd      // 发送读取命令
    3 h2 ^& w5 p9 W; ^) K& p. Y
  404.        CALL SendCmd! E. I; N, }8 P' z; o4 z9 I
  405.        CALL WaitWhileBusy
    . Q; `# [; z% j7 N
  406. 6 B& R/ |' c- K
  407.        // 检查是否出错8 T5 x! W2 F/ d" ^0 P
  408.        MOV  DX, dwBaseAddress( [$ C' D0 t0 M% }
  409.        ADD  DX, 7, H" e6 W" [' B/ f0 t

  410. 0 u0 u, r& ?8 [
  411.        in   AL, DX4 C9 ~3 l- M6 Q8 ^3 k
  412.   M+ c" ~; {! t
  413.        TEST AL, btBit00' Y* i) k7 k' [0 E- E# X
  414.        JZ   RetrieveInfo   // 没有错误时则读数据
    ! `4 v  i+ t' R& O4 z! C
  415. * Y$ G) L' i/ O, {
  416.        // 如果出错,则进一步尝试使用ATAPI设备命令) ?5 ?- k; U5 I1 r
  417.        CALL WaitWhileBusy
    & y0 k; E1 W8 D& \+ x
  418.        CALL SelectDevice
    3 ?! R+ V8 Z( B6 y
  419.        MOV  BL, btAtapiCmd
    1 S- b6 m, K& r6 [
  420.        CALL SendCmd0 ?7 t1 O* j3 @$ G$ q, K
  421.        CALL WaitWhileBusy7 t; R5 m7 K' S2 t/ ~9 k2 ?

  422. . t! Q- B4 ]; F
  423.        // 检查是否还出错
    1 l- T" Q0 X0 k# j
  424.        MOV  DX, dwBaseAddress
    * K$ v- d, J. C7 M$ N9 x5 z
  425.        ADD  DX, 7* h4 d$ R8 A. H- F# @
  426.        in   AL, DX. o5 n  m  j. w3 E, m
  427.        TEST AL, btBit00
    + l3 a; k2 @% I4 D$ C
  428.        JZ   RetrieveInfo   // 没有错误时则读数据9 I" |  S1 E( v4 w8 [
  429.        JMP  LeaveRing0     // 如果还是出错,直接返回
    4 [1 l+ j0 N; Z
  430. 9 [3 z, o  \% }: k: U/ \6 G5 k$ ^! r
  431.        // 读取数据8 C0 l2 f8 ]& T) J% }/ T$ o
  432.        RetrieveInfo:
    - E1 V( h7 }( g5 O0 s
  433. $ W+ d+ B- J' L" q
  434.        LEA  EDI, wOutDataBuf
    & |- F6 b( y) u, h0 W
  435.        MOV  ECX, 256  O  \. Y+ U; W4 s3 t2 u
  436.        MOV  DX, dwBaseAddress5 s# X, c& {, f+ R
  437.        CLD
    ' e  q* }& E" B' ^4 F+ d
  438. / [6 g9 {0 J7 p# V9 c7 T( \
  439.        REP  INSW
    , y% f4 V% u, X9 y4 j* I* Q0 |

  440. 7 N' H+ w/ _. V/ X+ C- [' E
  441.        // 退出Ring0代码
    # @( b/ e! D& [2 l4 }8 m( @
  442.        LeaveRing0:1 X2 @8 }  G  \

  443. % S0 S% e& X+ {4 y  B, y* w
  444.        POPAD9 _! j! q  T1 H7 t
  445.        IRETD
    . K. C* L* a' ~: D
  446. 6 m5 j+ X8 H" c. @' [) Q# c; H
  447.        // 激活Ring0代码) @( b* B) r4 M8 X2 w$ U- C
  448.        EnterRing0:
    2 b8 I: `; V; @: M, N
  449. 7 C0 d$ x1 [% K1 J; ^+ r% k
  450.        // 修改中断门3 Y9 J! \! g1 \; W9 d' K
  451.        SIDT FWORD PTR btIDTR1
    8 m3 z+ G- z5 a/ T5 X
  452.        MOV EAX, DWORD PTR btIDTR1 + 02h& Q: j5 ~7 E! k9 ^& i
  453.        ADD EAX, nHookExceptionNo * 08h + 04h
    ! y: g. r) D. a2 g+ I$ q* ]
  454.        CLI
    5 N; s9 G( {1 j

  455. " Y. @1 h6 T  S: C( J
  456.        // 保存原异常处理例程入口8 P6 v2 i; g' n6 _
  457.        MOV ECX, DWORD PTR [EAX]
    7 A* H9 |) J' |8 K
  458.        MOV CX, WORD PTR [EAX-04h]
    / |$ R9 O- h) c( q, T$ K
  459.        MOV dwOldExceptionHook, ECX
    6 l: H4 J7 u  u2 V% P( B& Z

  460. 0 m+ X( g, |$ L# S9 e/ F
  461.        // 指定新入口3 k# `3 n+ S9 S
  462.        LEA EBX, Ring0Proc( r6 K0 c: L2 A, b) P
  463.        MOV WORD PTR [EAX-04h],BX
    . N# p1 b8 A6 n1 h. a0 g% n
  464.        SHR EBX, 10h
    " R% @2 W9 W+ Y8 |8 r
  465.        MOV WORD PTR[EAX+02h], BX0 P! K0 [3 }: Q. @( e' B; X
  466. 9 R2 u6 }  i( n
  467.        // 激活Ring0代码1 x9 Y1 l) g" `1 h: o" X1 h3 G
  468.        INT nHookExceptionNo. o9 R2 `2 J1 x+ w
  469. & H( A8 o2 B/ f$ o- a
  470.        // 复原入口' {! m3 p7 K. Z: o3 s: ~# e
  471.        MOV ECX,dwOldExceptionHook9 s* c* x1 A; L8 |+ u8 N; H8 ?
  472.        MOV WORD PTR[EAX-04h], CX
    : L( r( M, R- C1 t, P
  473.        SHR ECX,10h
    ' P1 K- }' P" ~( i
  474.        MOV WORD PTR[EAX+02h], CX
    9 F8 h% E  M' M( s* ]( [
  475.        STI
    9 {, x2 \, {5 [& T
  476.    }
    " K) v; E+ I4 w3 h; ^* W
  477.    if(!bIsFirst)
    6 f0 ~. [: l. R/ O) n6 l
  478.    {' |, P' x3 ?: q2 y
  479.        bIsIDEExist  = (bool)btIsIDEExist;
    9 \& n# ~2 I% ~( A3 |8 v, E
  480.        bIsDiskExist = (bool)btIsDiskExist;# n: q- n, e9 b9 M' C3 \
  481.        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));6 ]  z# i3 c" r- j% ]5 t8 l/ g
  482.    }5 f# _( [. q- s( [
  483. }
    3 V3 }# A4 B/ M: I1 Z3 F
  484. //---------------------------------------------------------------------------4 L6 m. Z" y; x4 X  A+ \
  485. // 调用方法:1 C% r5 B+ U3 x5 |, G
  486. void __fastcall TForm1::Button1Click(TObject *Sender)
    + X1 R( ^, r& h& [
  487. {
    8 v1 ^5 E/ }- r. m
  488.    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
      S- |8 P: R/ \+ y- `* T
  489. }
复制代码
发表于 2005-8-15 01:00:45 | 显示全部楼层
晕乎乎。。。怎么看8 洞阿
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-8-9 04:35 , Processed in 0.036274 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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