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

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

[复制链接]
发表于 2005-8-11 11:42:04 | 显示全部楼层 |阅读模式
  1. #include <WinIOCtl.h>" I! C2 C# t3 A6 K, ^
  2. #include <stdio.h>% G8 \% g6 R+ Z; v/ m* W! p1 n7 F
  3. ! W( q% Q; {/ a
  4. #pragma inline0 q2 I' Q$ A+ Q8 ^& P
  5. //---------------------------------------------------------------------------
    ' [6 f8 r6 A) b) i( K
  6. // IDE NT/2000/XP专用变量
    # o4 e6 M* E% H' m9 \% A  W1 c7 X
  7. #define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS8 h: L# q( k& x1 F, k
  8. #define DFP_GET_VERSION         SMART_GET_VERSION6 W7 b5 z1 ~) V+ h- j7 u
  9. #define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
    8 o. F2 J. P3 x+ J, A
  10. #define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
    ) b, X; b! F; }, ~: R9 a! l( s8 n. ]" i, `

  11. 0 a8 H8 c$ p5 ^
  12. const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令( t$ W; S! I6 u8 B! l+ z; K2 L
  13. const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
    , Z2 G5 b. ]- W( U
  14. + U$ H/ G  _9 B5 D& k! u1 W
  15. const int MAX_IDE_DRIVES = 4;2 c% ]8 F5 r0 ?' _' @, I- ]+ s

  16. ; u$ M; @8 {. H) u0 i! Z
  17. // SCSI专用变量+ u6 m4 b/ T! ]- ?
  18. const DWORD FILE_DEVICE_SCSI             = 0x0000001B;) x$ K1 R0 f9 X+ o
  19. const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);, n3 o" w) L$ H( [- ?# X
  20. const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition5 B- a, ~9 ^% A  _; V" Z
  21. const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;/ W' I/ T2 p2 r3 E% W

  22. $ d" ^1 T7 Q+ [4 L5 j; |
  23. typedef struct _SRB_IO_CONTROL4 Q0 N2 t& T- L; _7 n9 r& Z% k& x2 t
  24. {7 G0 Z% d% h8 C  e7 }6 J( e/ F
  25.    ULONG HeaderLength;: K- K2 i6 z) X/ G! m( t5 u$ L; J/ K
  26.    UCHAR Signature[8];3 |0 s0 C% h# B% M# Y& g
  27.    ULONG Timeout;7 F  s7 _8 \' r# \
  28.    ULONG ControlCode;
    / |6 h* i8 L5 c" z( B; ~3 U
  29.    ULONG ReturnCode;2 [5 m5 m" r! Z0 N3 e0 l
  30.    ULONG Length;
    7 _/ X3 v  ~$ x; l4 U& D
  31. }SRB_IO_CONTROL, *PSRB_IO_CONTROL;! ~  k/ v/ i; v% G6 R; u$ S. R4 _* J! q2 Z

  32. 2 }% W9 y; p) q4 d2 F  N1 `( W' Y% }
  33. // 读取的主函数% W. H/ S! L! o8 Q/ j
  34. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);/ p5 x* h/ Z; X2 j6 m- R1 R
  35. ( }( p4 y) F5 X6 d/ u
  36. // 辅助函数
    * Q  I) N  V: R: [
  37. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
    " [' `" j) k/ U, k
  38. // NT/2000/XP函数- q0 n9 d0 }; W+ i
  39. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
      L2 ~) E* l4 B7 j- w3 n
  40. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,9 s  |$ V; Q4 h. {3 F+ O% [+ M
  41.        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
    8 l: H; g2 l# {  N$ Q! j$ Z
  42.        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);  T5 i5 N. R2 w+ d) b8 ]
  43. // Windows 9X函数4 R1 R2 w4 m9 ~$ S! l5 `
  44. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);
    0 L& a( v- P# N2 W1 j
  45. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
    ) S. C: j1 ]5 s% L  v1 \. I' p9 `
  46.        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);- X% `0 n) u1 E; x; _5 V

  47. , V  ~( ?% c: ~1 G1 |
  48. // SCSI读取函数(for NT/2000/XP)
    7 `( [$ N9 N. A% c( b7 G
  49. String __fastcall ReadIDEDriveAsScsiDriveOnNT();: _1 z( g: S* U4 O( W
  50. //---------------------------------------------------------------------------
    4 a- d/ C7 |* }
  51. // ReadPhysicalDrive
    % F) ^8 Q5 ]0 @2 |! I! z9 k
  52. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
    9 F4 ~) o& N2 l& j
  53. {; h8 n. f1 _  N* q
  54.    switch(Win32Platform)
    ; L  ^/ o' ?# @; U& D- o& D2 c
  55.    {# n# h  x: V, I, ~: n& z- l
  56.        case VER_PLATFORM_WIN32_WINDOWS:' F: ?/ i0 N3 W7 {
  57.            ReadPhysicalDriveOnW9X(pSerList, pModeList);
    : l) q" n# U- [6 h: p5 w
  58.            break;* b4 G' {3 ?7 f( a4 ]5 n
  59.        case VER_PLATFORM_WIN32_NT:
      z2 E  y0 |( z2 D+ V: w7 v0 l
  60.            ReadPhysicalDriveOnNT(pSerList, pModeList);  b5 r6 |* l9 n: r2 ]/ k: e. @
  61.            break;. O% V! j7 B- `$ Q- U
  62.        default:  [2 E; I4 y- ?
  63.            break;
    % F, J# m* u5 o* m3 n
  64.    }
      p- X2 r0 X" G* x4 K
  65. }
    . b1 ?: m6 V, [* F* _$ U- Z
  66. //---------------------------------------------------------------------------
    & o* t0 Z9 V. m* I( n- G# l/ {
  67. // ConvertToString9 E" I  G" L' y9 {; L
  68. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)2 ^' r" _6 a1 i1 d% D1 U( {2 k
  69. {
    ( `% x; y# V9 e
  70.    static char szResBuf[1024];" A: d" ?6 f  O& ~3 h( h
  71.    int nIndex = 0;
    7 u' p" d( x! ^# J9 M5 e, C- F
  72.    int nPosition = 0;3 t# V2 b2 f, L+ u: M4 N

  73. $ \  a5 y2 O3 [' @
  74.    // Each integer has two characters stored in it backwards0 k' B" I9 I9 g' ~$ m6 i8 p
  75.    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
    3 A8 E9 \! D/ P0 s
  76.    {) ]0 [3 Y4 E- t8 _9 N! e; p3 _7 Q
  77.        // Get high BYTE for 1st character
    0 g2 \$ H- b' L! t9 V* z9 ?, F
  78.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
    6 [; ~  X- i5 F
  79.        nPosition++;1 Z/ [6 @+ T0 D7 |" p3 c5 s& a

  80. ! i0 @+ l7 `0 n) u/ ]* `5 x
  81.        // Get low BYTE for 2nd character5 y: A3 H& Q: U0 P
  82.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
    # Y# g2 k  ~% l7 ]: S6 G9 G, l
  83.        nPosition++;
      `4 H  j2 U, d) z7 t
  84.    }7 ]: [6 E/ x3 G( w$ v2 K# \

  85. / h$ D+ {+ |/ k5 j( T6 G
  86.    // End the string
    ' A; c& t0 h& h1 V" k
  87.    szResBuf[nPosition] = '\0';
    4 c% o+ u7 F, x$ s' I4 y; E! [

  88. 8 |5 I6 _: G" W- @$ \: L+ l
  89.    // Cut off the trailing blanks
    % I) P3 x) Z1 J' R( e
  90.    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)0 @3 t* t4 w0 k( J# m" ]* D2 ?
  91.        szResBuf[nIndex] = '\0';4 A: Q& t- F" _0 w4 U

  92. 3 I& t3 \' X: H3 Y! O
  93.    return szResBuf;. u# ?! B/ v. h# ~4 m8 i
  94. }$ T1 \7 E) _, K8 V* `; |
  95. //---------------------------------------------------------------------------8 {- R$ a( [1 Z9 D3 |1 ~; ]% l: |. E
  96. // Winndows NT4/2000/XP 代码
    1 D. M5 O3 e& C3 s
  97. //---------------------------------------------------------------------------
    ; Y! `, C: T2 g
  98. // ReadPhysicalDriveOnNT
    . d- o7 \0 j; Z" f
  99. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
    " B) m1 h5 f# q2 x0 d* U# u$ n7 D1 h
  100. {
    & z: |. p% }8 |! n1 G7 I
  101.    // 输出参数+ A0 D  a- s5 `) L* |( j+ X) y
  102.    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
    ( n6 I( J$ p) H
  103. 5 r: c! ~9 x: j' T4 H% u( u- _
  104.    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)1 p# ]' I& u  ^8 F: O% g
  105.    {7 \" w% ]5 i) f. a- a
  106.        HANDLE hPhysicalDriveIOCTL;
    5 T) S3 A; \& t
  107.        char szDriveName[32];7 {8 Y/ ?& F  d: d+ r

  108. ( J8 q) f/ g; O- F9 F: x/ i
  109.        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);4 U4 M# h7 q8 }+ m7 a/ L5 x
  110.        hPhysicalDriveIOCTL = CreateFile(szDriveName,4 S2 s6 \0 A2 S0 J8 U
  111.                        GENERIC_READ | GENERIC_WRITE,
    # H1 X4 F' H2 L3 A. d. f1 ^
  112.                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,7 C" T. q6 {  _% g/ T2 N
  113.                        OPEN_EXISTING, 0, NULL);6 o7 s# N8 @, H: U' u% Y
  114. 6 _+ u1 R* }) Y# x- x' ?& q* P
  115.        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
    + z$ H+ ?) {$ d/ U0 D# _% u
  116.        {
    7 U* T- ^) E. n9 ~
  117.            DWORD dwBytesReturned = 0;
    ' }+ c- Q8 w0 d6 y7 g5 f9 U
  118.            GETVERSIONOUTPARAMS gvopVersionParams;4 b# J9 z( }8 F6 E6 \8 P2 I3 v

  119. 6 j3 N! }' [- F; C6 v
  120.            // Get the version, etc of PhysicalDrive IOCTL$ k$ i0 `& y! ^# ]! a- [6 [1 `
  121.            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));! m8 H) Z9 S/ _$ z" v* b

  122. 2 D  B; }+ b- p( p& |! _
  123.            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,. R' M, n$ j. R( r7 C3 u' \
  124.                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),5 c4 L' H6 m& J2 L: j+ r- w
  125.                    &dwBytesReturned, NULL))
    + G/ z$ k/ z4 b& i6 W
  126.            {3 q- q/ ^) \$ b+ j: F' O8 d7 v3 \2 u
  127.                continue;7 M1 j( Y: Z3 g/ Q3 p
  128.            }
    # Q& E) Z; \2 W* {9 H7 v

  129. . C# T) M- y4 `2 [3 K& j$ d
  130.            if(gvopVersionParams.bIDEDeviceMap > 0)9 {3 D) S1 ]' V3 s* s3 u
  131.            {4 l7 E' U9 }& Z5 O5 H
  132.                // IDE or ATAPI IDENTIFY cmd- C. u! q2 ^# `; y1 n0 j# w
  133.                BYTE btIDCmd = 0;
      g- J' k7 u3 V
  134.                SENDCMDINPARAMS InParams;! \; V( K) {" x/ S5 S! j
  135.                // Now, get the ID sector for all IDE devices in the system.' {+ i  x# w0 _5 E
  136.                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
    0 p' z; Y9 ]$ A" U+ k& o
  137.                // otherwise use the IDE_ATA_IDENTIFY command' X# v/ |% i" w" e* K5 z
  138.                // 具体所得结果请参考头文件中的说明" @+ k4 Y; Z6 m/ z  m5 g
  139.                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?1 [/ m% X% W9 q! R
  140.                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;. e1 W) @0 [+ Y
  141.                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));7 y) l- j4 T& P( T: N, E
  142.                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
    9 B0 D: p/ G" H' b, {$ O
  143. " D: r) q( h& k* N# C
  144.                if(DoIdentify(hPhysicalDriveIOCTL,# G# k" R  Z2 O" d# R( p
  145.                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,3 T! h/ }  m7 N7 e. E. P* j
  146.                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))7 f& y8 D1 L1 J2 _+ k# @' y
  147.                {
    * Z. p4 T. x3 l( K! K  x. d9 N
  148.                    DWORD dwDiskData[256];
    ! G! u' Q& X9 G; X$ W8 |( A1 |
  149.                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
    2 u/ ?  ]# i! x/ g+ r
  150.                    char szSerialNumber[21];
    9 g; R; E  ]9 J
  151.                    char szModelNumber[41];$ T/ J- T" `7 K0 e3 G: d- p
  152. $ }7 X/ x6 J' ~3 B
  153.                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
    5 u8 o  K" V+ g5 r6 u3 W, a1 [% y
  154.                    for(int i=0; i < 256; i++)
    9 o) p, c8 S$ L" n, ^) Q
  155.                        dwDiskData = pIDSector;
    3 F( s6 |6 K  n, ?) N: F; U
  156.                    // 取系列号
    8 Z# y* T/ r0 m" U& i, C
  157.                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));2 |' r' U8 C. _' S6 s
  158.                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
    ( N  [* E8 Y  K! ?- d" t
  159.   o9 [4 S# x. ?% B. o4 j
  160.                    // 取模型号' b3 \4 Q1 |4 s! o) R  M7 }
  161.                    ZeroMemory(szModelNumber, sizeof(szModelNumber));  }$ R  [" F4 L# R6 Y
  162.                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));  o. C7 ~, y. f: H8 E% D, M  q

  163. # X  M; G2 i8 G- D; _8 C; ]# z
  164.                    pSerList->Add(szSerialNumber);
    : {$ k4 U- J8 m$ H$ X
  165.                    pModeList->Add(szModelNumber);
    6 [1 N+ J+ F9 I
  166.                }
    * q6 E; m  c' F7 n
  167.            }
    ! ~$ q2 F/ J6 _7 K& D! q
  168.            CloseHandle (hPhysicalDriveIOCTL);2 |' n) P, E+ e% l2 D' g
  169.        }
    2 y! @& s/ n4 Z8 _4 B
  170.    }
    5 D4 |+ d9 f1 I
  171. }
    7 u' o; X2 B0 |  w8 W4 ~" N
  172. //---------------------------------------------------------------------------$ h. I! h( n/ r
  173. // DoIdentify
    5 ?) ]% Z) [2 K8 v. `1 t. A
  174. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
    ! a1 E* X+ }* m5 s2 }  _' p
  175.              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
    3 }% W5 b7 X6 I* R! B( e
  176.              PDWORD pdwBytesReturned)
    ; E/ G+ S7 S  Z' e* b. K$ v
  177. {3 b( S! @2 t$ v9 m. o
  178.    // Set up data structures for IDENTIFY command.6 c! W- ]# }7 o$ \/ v& G
  179.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;5 Y" H) W) _' y; Y8 r0 N
  180.    pSCIP->irDriveRegs.bFeaturesReg = 0;
    % a( }7 j2 R7 A- G0 x) |
  181.    pSCIP->irDriveRegs.bSectorCountReg  = 1;
    0 G$ H. ^$ t7 D) K
  182.    pSCIP->irDriveRegs.bSectorNumberReg = 1;- h8 d7 I! H' e. `5 j) [9 h2 v
  183.    pSCIP->irDriveRegs.bCylLowReg  = 0;
    - }- M/ p; J" _  K6 _2 @2 c
  184.    pSCIP->irDriveRegs.bCylHighReg = 0;
    . v! O9 @9 Y4 y
  185. 9 \/ S1 ~: u; }& d" e3 N  Q4 Z
  186.    // Compute the drive number.(主盘和从盘所对应的值是不一样的)1 \/ R: x3 o) O' I
  187.    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
    . o) m9 z7 C/ j& I- U) R) U
  188. ' u# q5 A% Q: R2 I. I. s
  189.    // The command can either be IDE identify or ATAPI identify.
    ' {1 ?9 e# L3 S; ?
  190.    pSCIP->irDriveRegs.bCommandReg = btIDCmd;
      }4 ^" Y( f6 a* q# A" a" v# [# e
  191.    pSCIP->bDriveNumber = btDriveNum;: m4 _, W! L( y5 }: M8 W
  192.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;  L) Z# P& l  C
  193. / i/ n# l" D8 I+ ?! Y
  194.    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
    ' e3 k' D/ Q1 |! k* l; g
  195.           (LPVOID)pSCIP,
    ! r6 H2 j( _+ x9 f1 n3 B
  196.           sizeof(SENDCMDINPARAMS) - 1,
    * `4 a8 Z& E5 r1 B6 R
  197.           (LPVOID)pSCOP,
    " \/ X6 \' w$ u  J8 G6 ~6 S
  198.           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,$ Q, Y: {8 T, G2 F
  199.           pdwBytesReturned, NULL);2 J6 U  x( w( [
  200. }
    ( G1 Q& ]/ z; J2 n! u* v
  201. //---------------------------------------------------------------------------
    3 d7 b' T1 Z' ^
  202. // Windows 95/98/ME 代码  W9 s* R% P* T5 V7 H: k( w+ w# V
  203. //---------------------------------------------------------------------------  w/ i4 x& W* T; [/ H) m' I* ~: V: Q
  204. // ReadPhysicalDriveOnW9X; j* i' n  ^5 `
  205. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList), X; S& r! a- C( Q
  206. {0 t6 f- n; A/ Q' a. K
  207.    WORD wOutData[256];5 }4 _1 V1 ^# N$ G2 u* g) R6 J
  208.    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
    & m! m2 E- T) F. ?  I9 _" _
  209. & Y5 \, C, x# e6 w3 X; u
  210.    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
    ! \# A1 \, x, P
  211.    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以, \1 V& n1 e! [: L% j7 }
  212.    // 避免蓝屏的出现。(期待高人能指出原因)# \1 u4 L- ]! f; m, l& a5 y
  213.    for(int nDrive = 0; nDrive < 8; nDrive++): B: S  B' L* R% z  B
  214.    {
    % N9 o" R8 V. e. B! j$ H
  215.        WORD dwBaseAddress;
    & Z: d0 @3 K: `* s) W( j: G! D1 s
  216.        BYTE btMasterSlave;         // Master Or Slave
    + C. r# }/ W+ P% I3 p5 Y, q) |
  217.        bool bIsIDEExist;
    6 k9 a4 Q$ p6 m4 _7 |/ p  K7 Y- F
  218.        bool IsDiskExist;
    7 D& Q; j1 A" R' v! G) \! ]4 ?6 |/ e
  219. " @0 ^: _( G8 ?, D# w7 z2 p9 Z
  220.        switch(nDrive / 2)
    4 G7 q; _" d# |* f
  221.        {' |  K0 x8 \" P+ T
  222.            case 0: dwBaseAddress = 0x01F0; break;
    9 ^6 t- a: `- Q# t5 K+ V6 u$ y
  223.            case 1: dwBaseAddress = 0x0170; break;  Z' y9 Z( v, M- q3 w# e' T$ H
  224.            case 2: dwBaseAddress = 0x01E8; break;
    , E9 o1 P+ h, y4 s
  225.            case 3: dwBaseAddress = 0x0168; break;
    9 @/ ?3 u3 O; b& n) \* N
  226.        }5 l& `, W; V$ s9 O( N6 q1 d6 F& ?" z

  227. 8 f- x. P# L4 a! i3 w% b& y
  228.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
    # l* [8 {& e/ Y4 T  t$ ], y
  229. 4 J5 k& T$ n8 X( [) F
  230.        // 进入Ring0
    2 f, z, C) q; O3 V
  231.        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,' K/ _! `# Y8 d" }9 B3 Y: m
  232.                bIsIDEExist, IsDiskExist, wOutData);
    & N) y, f+ r& i9 I1 R1 T
  233.    }
    5 S7 H5 }) d5 l/ `9 F/ A

  234. ) p& t4 f/ ?1 r" W" y3 [
  235.    // 开始读取5 n& R$ ]2 A  ~; w( C, b% h% M. B
  236.    for(int nDrive = 0; nDrive < 8; nDrive++)
    + ~2 a; H. ?: U0 t
  237.    {
    $ v: E/ U: g! {0 p! ^6 `
  238.        WORD dwBaseAddress;
    $ c/ T  E8 H5 k
  239.        BYTE btMasterSlave;         // Master Or Slave
      S: L: ~( Z$ J. r! G! j
  240.        bool bIsIDEExist;+ `6 L& g: X9 a- i
  241.        bool bIsDiskExist;9 ?3 V) N7 D: }
  242.        switch(nDrive / 2)
    3 Y" c: z+ }: @! S
  243.        {
    5 J! ^- S/ S% E% {
  244.            case 0: dwBaseAddress = 0x01F0; break;( G+ Q8 ]; P9 a5 a) g
  245.            case 1: dwBaseAddress = 0x0170; break;
    - l% H) {$ U' o) V  K/ I
  246.            case 2: dwBaseAddress = 0x01E8; break;
    ( T1 f: g0 }7 b, A. s
  247.            case 3: dwBaseAddress = 0x0168; break;
    . C' c  K6 H0 K; j0 J* [
  248.        }: I+ s) t/ D) h- S4 \* ~8 q
  249. - m$ Z4 W( P% a% v" E' N1 s
  250.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);' g* l. {1 y3 y0 D8 {

  251.   i0 f- l/ B& j. {3 K* N$ _
  252.        // 进入Ring0- d/ W2 W& h8 b3 o, h. }- _
  253.        bIsIDEExist  = false;  l# U& q" }* f
  254.        bIsDiskExist = false;- x! y; t$ K! t2 f% I7 i4 |2 E
  255.        ZeroMemory(wOutData, sizeof(wOutData));3 Y+ _8 \8 ^- v: a: L  c$ L
  256. + |) E& G. H* B' h% ]# U' x$ g
  257.        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
    6 D8 o0 ^  a6 X. w& _
  258.                bIsIDEExist, bIsDiskExist, wOutData);
    " Y* W3 `  G# \, k. |

  259. * R5 \5 ?( w' |
  260.        if(bIsIDEExist && bIsDiskExist)
    & O8 _3 u9 v4 Q
  261.        {
    # i* q' Q: N! T: V% u1 ]* u
  262.            DWORD dwDiskData[256];
    & z1 e* S) ?1 b7 x  [1 F) Q
  263.            char  szSerialNumber[21];2 O- _8 z6 f' N
  264.            char  szModelNumber[41];( u6 n& p# ^0 B; f+ B/ x* w/ `' D

  265. % g- T: ?% u* H* V5 Y" m
  266.            for(int k=0; k < 256; k++)
    ) P+ [8 I5 q( S6 |3 B6 n$ q% [
  267.                dwDiskData[k] = wOutData[k];  p( z, ]# y8 o# w/ ~8 b; W6 p

  268. 1 o# J, v0 u- L2 q2 s
  269.            // 取系列号
    ) w( z9 k- i% y. U8 F* [) C
  270.            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));9 v) G5 N2 o+ y/ ~
  271.            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));6 s- H3 I2 [9 v1 h/ W5 i

  272. : Y" Z1 h7 @, d; @5 g7 z* d
  273.            // 取模型号
    ; z( j. T, |: X: X3 G
  274.            ZeroMemory(szModelNumber, sizeof(szModelNumber));
    9 g0 A3 u& i% F; z1 R5 k
  275.            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));7 R. Q3 j4 A' U6 J" j6 Y6 H/ a; u4 y
  276. * w9 z; K% M. I
  277.            pSerList->Add(szSerialNumber);# O- z$ t" O: j
  278.            pModeList->Add(szModelNumber);" t0 U* i0 G. X' t. N5 t' s$ z
  279.        }
    ! f# b" q* y8 C: l! Q$ ]
  280.    }
    - l7 \% v$ T. y8 U) t
  281.    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
    1 A  D2 R7 |8 A2 G+ ^
  282. }
    9 @9 h3 @1 p% |. t- Q' K
  283. //---------------------------------------------------------------------------- d0 L; u) H) k8 Z0 b6 ]  E
  284. // ReadPhysicalDriveOnW9X_Ring0()8 ]9 `2 \2 W2 {# Q7 r: u! F
  285. //
    " ?, `, L& ^3 Q& p4 j  F1 q
  286. // dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h5 K1 \. ~" D0 B8 X  Y- I
  287. // btMasterSlave = Master(0xA0) Or Slave(0xB0)
    " A* q7 W8 K9 A2 r3 y8 ~
  288. //---------------------------------------------------------------------------( L  Y" x  H. S. Z% ~
  289. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
    ! X/ O$ x& s- g' F( e) X
  290.        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)# H' S8 C$ v( o$ B1 W
  291. {0 R# I6 D5 k! M
  292.    BYTE  btIDTR1[6];
    . i9 m+ [6 t; N7 H& [1 y, G
  293.    DWORD dwOldExceptionHook;3 {* L! M" L; v: Z7 |( Z$ d
  294.    const int nHookExceptionNo = 5;# Y: ]% h, ~2 l- C4 ^. A
  295. . p, }4 W; Q# k: C4 X# B1 f
  296.    BYTE  btIsIDEExist = 0;! a9 B  o' J1 {/ L9 P1 ]
  297.    BYTE  btIsDiskExist = 0;
    5 [7 t- L' P$ \# T1 ]8 I8 e3 O
  298.    WORD  wOutDataBuf[256];! o  l' A1 c4 K5 m) q
  299. 1 C6 H$ c# y  c1 r6 @7 y# ~% b
  300.    BYTE  btIsFirst = (BYTE)bIsFirst;% G, _* @( X" [6 C( s& P3 C

  301. 4 F/ J( E. @' m
  302.    const BYTE btBit00 = 0x01;) J1 V  m* \% a' x
  303.    // const BYTE btBit02 = 0x04;
      ?% D# V+ e0 t. i4 G, F% A# C5 I, k
  304.    const BYTE btBit06 = 0x40;) W& U# I8 H" [/ [2 Z
  305.    const BYTE btBit07 = 0x80;& P9 {6 N' P8 M3 W8 @! }
  306.    // const BYTE btERR  = btBit00;. [4 Y% I, a6 A
  307.    const BYTE btBusy = btBit07;
    7 {- D1 H3 [, u7 I
  308.    const BYTE btAtaCmd   = 0xEC;- H% `, D0 K9 G- T! w
  309.    const BYTE btAtapiCmd = 0xA1;
    . Z5 {1 P! k/ u# b: `2 m5 D4 v

  310. & i2 F$ a) \& a2 M* ^  [
  311.    __asm  ^' K7 x& W0 c  U' W
  312.    {4 q) c0 b" ~& @9 ?3 V% z" S# J1 x; p
  313.        // 必须先执行这条语句0 f. d# F5 i# {- x4 e9 P
  314.        JMP EnterRing0
    6 Q' l: J. s2 |: W2 i

  315. & l% x. g/ J+ |
  316.        // 定义过程
    1 j2 h# l$ j) l1 M* \. |: l& W
  317.        // 等待IDE设备直到其不为忙为止, z4 `" `) t! [- x! U- z& Z
  318.        WaitWhileBusy proc
    * u) k" n7 V4 S

  319. & ~: |$ c' J  b! e
  320.        MOV  EBX, 100000  M/ }. B4 b; ~
  321.        MOV  DX, dwBaseAddress8 K. h, z% ^; N$ J! x1 J+ z: e
  322.        ADD  DX, 74 n$ D3 s1 A3 H  x" X

  323. % {, W7 m1 ]* S6 M
  324.        LoopWhileBusy:
    0 W# B4 s. ^) X

  325. 9 G$ c4 m( G0 Q9 C+ J
  326.        DEC  EBX9 B* `5 B( V: ]& J. B$ T
  327.        CMP  EBX, 00 h; z% a- S  |" T2 Y
  328.        JZ   Timeout
    , `/ D6 `* X  q* Q/ c  n& i
  329.        in   AL, DX" {; G" I; P  f1 s' W$ S& @% f. T
  330.        TEST AL, btBusy$ h& z; `" T! i6 R" x" Q: \
  331.        JNZ  LoopWhileBusy" G0 z; z) l. m: }9 D; X
  332.        JMP  DriveReady
    9 H1 S  h2 k4 o) M% K
  333. , p* s1 H( Q. ]2 F4 M
  334.        // 超时,直接退出
    4 w% u' R' @2 f3 I. m
  335.        Timeout:
    1 ^, H3 G- a# ^$ k1 D" `
  336.        JMP  LeaveRing0
    # _4 \4 @& K+ Q$ y; w2 M  \- |
  337.        DriveReady:" C" S! U3 q4 p2 ~
  338.        RET
    + k! i, H. o) A+ G2 ~0 k
  339.        ENDP   // End of WaitWhileBusy Procedure
    : U9 q. i& s# v4 B% T; W. a

  340. * V7 Y3 b1 v9 n. Y- f, _; t) j
  341.        // 设置主盘和从盘标志6 l8 A  u! D4 v) P4 u% x
  342.        SelectDevice proc3 ~( h' u/ q$ |
  343. / N; c, O+ T. N3 G, L  a
  344.        MOV  DX, dwBaseAddress
    : D5 \1 [" q5 R0 B
  345.        ADD  DX, 6
    / F' `2 y' E( a
  346.        MOV  AL, btMasterSlave
    & c3 [! A3 x* `6 t+ a. ?( _- E

  347. : O. j- o( X. E; R% F
  348.        out  DX, AL
    1 z. _# D/ }! C: v$ V! K
  349.        RET
    % z' N6 F) ^0 y8 R1 t
  350. & K, P' x, y8 F( g. _% w
  351.        ENDP  // End of SelectDevice Procedure
    ) X, |9 r* V$ T4 n0 I, u/ n
  352. & A* c5 ^7 l4 s; N8 d( X1 c
  353.        // 向IDE设备发送存取指令
    2 N7 V* o, ~0 t, ?
  354.        SendCmd proc
    7 D: P- b7 @1 i/ o3 n/ K+ P

  355. ' [% Z$ r* E$ b1 J: }1 y
  356.        MOV DX, dwBaseAddress
    / v! u5 r4 M6 Y3 q
  357.        ADD DX, 72 }! t$ s3 S, u4 @: k# v' Q
  358.        MOV AL, BL // BL是主从盘标识,在过程外设置
    9 Z! U0 s/ g6 I1 g& N1 m
  359.        out DX, AL  H! x, s5 g* _8 f: ]/ g- `6 E
  360.        RET0 E( n% k( V( y% n, L+ N8 d5 `# R6 b8 S
  361.        ENDP  // End of SendCmd Procedure
    ; r) N6 G9 B  P+ N
  362. * T1 L& l; |& @( B8 G( h2 r
  363.        // Ring0代码
    2 |# n* a' L. ~% p1 b3 T
  364.        Ring0Proc:6 H( i8 v/ Y! W: ^
  365.        PUSHAD! }) \9 B& L9 F4 s8 H+ s' X+ h
  366.        // 查询IDE设备是否存在7 Q# I) x, |" p5 F' @3 I5 w
  367.        MOV DX, dwBaseAddress
    7 k9 U( s8 ?( C( ?2 L
  368.        ADD DX, 7
    6 R! p) E: q6 d: R$ g( L; Q' g3 k
  369.        in  AL,DX
    ' \' g) N% [, \9 g3 d

  370. 7 ~. {$ u8 I# \3 l% o5 e3 `8 C
  371.        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回* S4 H7 l  G6 f, G
  372.        CMP AL,0xFF; _  @' D# ~8 g1 w0 [
  373.        JZ  LeaveRing0% b. u$ D7 i* q
  374.        CMP AL, 0x7F0 f1 [( x1 m. r2 z# |- r8 g
  375.        JZ  LeaveRing0" I/ P& v4 d6 Z: }

  376. " f) V# b0 w- N
  377.        // 设置IDE设备存在标志# h/ h- d' S# i/ C# w* D
  378.        MOV btIsIDEExist, 19 v; J4 u8 n- e
  379. 5 ~- |# g$ b, N* B) }2 I' T
  380.        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
    & s7 s# D/ j" z( I9 V3 `
  381.        CALL WaitWhileBusy
    0 ~, z, G+ c, e# P/ g
  382.        CALL SelectDevice
    3 K, p5 r* {0 @! i) a

  383. 4 R+ s; H+ S. q2 X
  384.        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
    2 J* A) Z6 M% R5 G5 J1 T9 E! n. k
  385.        CMP  btIsFirst, 1
    0 G8 _0 r: e7 o5 D4 @, F2 X
  386.        JZ   LeaveRing0
    8 [* g4 C$ [! A1 d
  387. . A9 U) L# [$ M/ V4 J% X' I
  388.        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
    6 Y+ t1 u, c) U% {* G9 L( T
  389.        CALL WaitWhileBusy
    4 }! y2 k0 W" R6 S$ R
  390. 1 u+ M2 ?* ~# M+ ~; n
  391.        // AL的值等于cBit06时,不存在驱动器,直接返回! E7 |5 [% `* I" ~6 e  C
  392.        TEST AL, btBit06
    - f6 X  u( A' E; F% E, |; H
  393.        JZ   LeaveRing0  \9 Q5 w5 s; U/ p
  394. 5 ^2 D  h" v0 ?/ h( ~1 r6 t5 m
  395.        // 设置驱动器存在标志
    $ ~; U, s, e: t* h1 w( B4 f
  396.        MOV  btIsDiskExist, 1
    1 J& O- Q) c$ H- O5 q( _2 V* x* X* L
  397. / D. B; S4 j# q' M+ i
  398.        // 发送存取端口命令6 [8 v0 M$ E" e6 a
  399.        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,7 \2 D, h9 x. k# c
  400.        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
    4 n# D' i5 M. y5 L( ^" ~/ W2 W+ j
  401.        CALL WaitWhileBusy
    " g2 n6 T# |3 q
  402.        CALL SelectDevice    // 设置主从盘标识+ y0 i3 o* K+ a% c3 Y4 l
  403.        MOV  BL, btAtaCmd      // 发送读取命令
    , X8 t% z2 e) V! t% W8 {" A
  404.        CALL SendCmd
    - u8 E# V# R0 q
  405.        CALL WaitWhileBusy6 k# |# Q8 _: c+ |: n
  406. ' G4 V! z; g; y' u
  407.        // 检查是否出错
    0 g) e, [7 M$ {( o2 {6 z6 g0 f
  408.        MOV  DX, dwBaseAddress
    9 q8 k& k( n& Q/ t3 [
  409.        ADD  DX, 7
    , T/ M4 G/ a/ V# ]1 i3 Q! i
  410. 3 b: x# @6 X+ E" X' g. x
  411.        in   AL, DX! u, g1 f3 q. c: x9 v
  412. / `, `7 W- ?6 b8 B( ?. `1 z
  413.        TEST AL, btBit00
    / s3 S0 z: P4 r" u5 {7 E& r
  414.        JZ   RetrieveInfo   // 没有错误时则读数据  F7 n3 X% x. G8 j1 D; P- t7 }
  415. 0 g3 s. Z& P# F3 z+ b
  416.        // 如果出错,则进一步尝试使用ATAPI设备命令' M% Y2 x5 V3 V3 Y8 e3 `- ~
  417.        CALL WaitWhileBusy) ^0 a7 l8 X, n3 I( g# S
  418.        CALL SelectDevice
    & m, Q; g/ v' A/ }& a
  419.        MOV  BL, btAtapiCmd# |$ }& E! M8 A, Z
  420.        CALL SendCmd
    6 k/ F7 R4 d5 l: F& M
  421.        CALL WaitWhileBusy4 P1 y0 ?: [. g& d& @& B1 |: \5 _
  422. * K( c% S" L/ N1 e1 b8 R
  423.        // 检查是否还出错1 e* H2 D7 v9 n: Y! I3 D
  424.        MOV  DX, dwBaseAddress
    4 N/ ]' M, J5 o
  425.        ADD  DX, 7
    - W( {% N* d, ^1 p" b) |; N* I
  426.        in   AL, DX
    ; U2 l* Y3 ~) {& H3 ?$ |( h
  427.        TEST AL, btBit00
    ; b# S& n; x, k; h4 u
  428.        JZ   RetrieveInfo   // 没有错误时则读数据
    # k( F( X6 l1 ~. y0 B2 c- F; Z2 e
  429.        JMP  LeaveRing0     // 如果还是出错,直接返回6 `/ z$ y5 T6 `

  430. " k% {3 m+ K% {% d
  431.        // 读取数据
      R4 V% n: a- G0 s! Q
  432.        RetrieveInfo:
    7 P4 g2 }  `0 P9 x) Q8 k

  433. ) a/ i9 w4 D5 }! Q! s# R
  434.        LEA  EDI, wOutDataBuf3 y1 a2 M& @/ R
  435.        MOV  ECX, 256! j, m# w: m1 m( x& w3 Z& x
  436.        MOV  DX, dwBaseAddress
    1 d  a! m8 T' I/ |& _: f# t
  437.        CLD' R$ j1 H$ e5 L& g; {, d# F5 `+ A

  438. 7 T7 q2 a, G& C% G& `
  439.        REP  INSW4 e6 g. W+ H8 C$ d6 S8 a
  440. + C, o2 Y% t( z/ I3 z6 |* i  q, `
  441.        // 退出Ring0代码4 d9 {( Z/ R0 |  l; F) g
  442.        LeaveRing0:
    " a! i! ?, S- F- L( n" z
  443. ; n" C2 i- M4 a8 I
  444.        POPAD  j8 {4 Q$ O( {+ ~9 m9 x
  445.        IRETD3 F3 E+ E1 r! W% o+ F9 n

  446. 3 I% D* S5 E# o) N+ z3 {9 ]6 I9 w
  447.        // 激活Ring0代码9 x/ T! J# W( |, o2 S' Z6 _  S
  448.        EnterRing0:
    7 o+ d7 P6 Q0 D% q' ^' N1 ^2 q: o" L

  449. , S( q/ f6 X7 l
  450.        // 修改中断门9 L5 N  ?- m. k, S8 \( T
  451.        SIDT FWORD PTR btIDTR11 p8 `& B0 o7 e& n
  452.        MOV EAX, DWORD PTR btIDTR1 + 02h/ f5 ~$ P% @& |8 D
  453.        ADD EAX, nHookExceptionNo * 08h + 04h
    9 _, e: |$ ^/ J" x6 {4 c  N' _
  454.        CLI% F8 T. o% @7 ^0 C7 S

  455. ! B, T3 q0 ~: Q5 @6 E0 [
  456.        // 保存原异常处理例程入口5 K0 _& y2 r9 N3 D& ~
  457.        MOV ECX, DWORD PTR [EAX]
    ! [" \" l, Z# x6 N) p9 b
  458.        MOV CX, WORD PTR [EAX-04h]
    9 G  Z+ S: _* [( y- z
  459.        MOV dwOldExceptionHook, ECX
    1 z* \6 \, m4 i, L9 G9 e5 C! F9 ~
  460. ! b' `" B4 r( M
  461.        // 指定新入口
    ' l. e! e  G0 n$ k/ P, }
  462.        LEA EBX, Ring0Proc) m9 V, N  [7 q' a
  463.        MOV WORD PTR [EAX-04h],BX
    : \$ {6 |' R' z5 h, r
  464.        SHR EBX, 10h
    ; P8 L0 w" W3 L+ I2 H- n
  465.        MOV WORD PTR[EAX+02h], BX8 W  d6 F1 ]; G- p* ?
  466. 7 R3 L; j- k6 Q: _/ P
  467.        // 激活Ring0代码
      V6 {& C! d  D
  468.        INT nHookExceptionNo
    , H- Z% N: T) W! |6 u, E
  469. 2 j2 y9 x( r+ B/ X, J2 D
  470.        // 复原入口
    $ n1 n- o- S4 X6 H. i, E3 \% L% H% \
  471.        MOV ECX,dwOldExceptionHook
    , j, R- c6 R  d, l
  472.        MOV WORD PTR[EAX-04h], CX9 L% V3 P$ U$ {5 q1 i' y+ t  _0 y
  473.        SHR ECX,10h
    & w/ A8 |5 g4 m* H" d# x% O& h
  474.        MOV WORD PTR[EAX+02h], CX
    " {, Z% \$ q- b- r( ]  a$ ]9 F
  475.        STI# p: ?: @) E) }2 L) Z
  476.    }& Z% y9 \8 Z8 |) @& N/ T
  477.    if(!bIsFirst)$ M' n! O) W4 E  `! K4 w" O
  478.    {, ~/ g3 S( o9 y5 O: f1 P
  479.        bIsIDEExist  = (bool)btIsIDEExist;
    ' Y8 ~) ^* q) O# R: ~/ R
  480.        bIsDiskExist = (bool)btIsDiskExist;0 O7 x# I1 W- M7 ?8 l* c
  481.        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));$ Z0 e- n) K' W, A
  482.    }6 q3 h9 i% ?! C4 w7 g# ]' I
  483. }0 I, `( ]+ M' C% x! X# P. [
  484. //---------------------------------------------------------------------------
      X0 W: r: x1 k  V2 q4 J- e4 W
  485. // 调用方法:
    # l. p" l7 M% }; X3 {/ [; u
  486. void __fastcall TForm1::Button1Click(TObject *Sender)
    % r0 \- K3 E+ w, |! W4 W
  487. {7 _5 C& H7 V$ b6 x  l, H
  488.    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
    . ]+ x+ c) \% ^  p' x0 j
  489. }
复制代码
发表于 2005-8-15 01:00:45 | 显示全部楼层
晕乎乎。。。怎么看8 洞阿
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-9-30 11:17 , Processed in 0.037689 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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