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

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

[复制链接]
发表于 2005-8-11 11:42:04 | 显示全部楼层 |阅读模式
  1. #include <WinIOCtl.h>8 ^+ Y: k5 c0 Q# E
  2. #include <stdio.h>) h4 L/ k) ]8 n, f, F' d; C
  3. / o# I& a9 _  [9 q0 z, @
  4. #pragma inline) \' G$ u! G0 l
  5. //---------------------------------------------------------------------------
    * D8 K. `3 o! W; Y3 ?. l0 K
  6. // IDE NT/2000/XP专用变量
    # C# _$ r8 G7 A
  7. #define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
    ! }2 x! @$ y+ K/ ^+ D2 e
  8. #define DFP_GET_VERSION         SMART_GET_VERSION/ B+ L/ S! O2 @4 A" P
  9. #define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
    6 n! X3 j1 v3 C0 K. [
  10. #define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
      r0 ~. i  N: \1 k

  11. ' T8 y( V- l7 n- M9 C# p
  12. const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令% F# `( F# {! W, ~7 T# y
  13. const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令. D) J$ N; e( U& E6 u3 ~
  14. 7 S: d- N  ?3 k& d
  15. const int MAX_IDE_DRIVES = 4;
    * M# }  W  }6 W+ K/ u
  16. % S1 Z' `* z7 N* z3 ~% W* _
  17. // SCSI专用变量
    4 h" ~0 n; `# \: q) m/ [. ~+ u
  18. const DWORD FILE_DEVICE_SCSI             = 0x0000001B;
    " r1 K7 i! c9 o4 |% j  Q9 K2 q
  19. const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
    2 ]* h. Y# q0 U! `% R
  20. const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
    4 J  S+ h2 g  z' P8 ?8 _
  21. const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
    5 x9 E8 W* U+ A( f) v! H/ v& |) W

  22. " Q$ M9 H9 b$ j, `9 a! ?; O
  23. typedef struct _SRB_IO_CONTROL5 T, Z% t0 U1 P8 T0 U, j
  24. {
    0 T. _  g; M, w, `
  25.    ULONG HeaderLength;
    ' y% B8 A# f/ f1 h9 f
  26.    UCHAR Signature[8];, o# o% \, f7 R1 }: o) D  O, Q$ c2 \/ a
  27.    ULONG Timeout;7 Q$ k4 [3 U2 O% P
  28.    ULONG ControlCode;; x" |, H' h( P. w2 O8 W4 g
  29.    ULONG ReturnCode;
    % B5 ?, X6 z$ d* r# g! d, s# B
  30.    ULONG Length;) c+ e# y& ?1 [% d2 J# d: S
  31. }SRB_IO_CONTROL, *PSRB_IO_CONTROL;
    8 m# T% s  s# e2 u# N

  32. ; [" M  A8 \4 a" B' L
  33. // 读取的主函数8 I- H+ l; z" S, ]: z" F# P/ S, E
  34. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
    ! V* \3 _2 G! V

  35. 9 E1 Q$ W0 V& n5 H6 G
  36. // 辅助函数1 F) K  Z' {0 h- j- f3 ^1 c6 B
  37. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);4 @1 u5 d, u- k2 W+ j. ]
  38. // NT/2000/XP函数, |, h& n& Q  l, F$ k$ d% K
  39. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
    " k' Q, Y% h! F% l. E( L: r
  40. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
    ) Z+ W; f  B) V# M
  41.        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd," B8 u; Y& f' I5 }+ C! u, s, i6 {2 `+ v
  42.        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);3 `8 y& J4 Z& B2 S+ \# s! M6 t1 G7 ~
  43. // Windows 9X函数
    3 h/ d5 R, g6 y
  44. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);7 ^/ a2 Y3 W* v5 Y% _* X
  45. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
    5 W! @/ q4 B* K" c
  46.        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
    5 ~! i$ m, T8 P8 d5 x
  47. # ]' X7 `9 n( E# H/ M$ p
  48. // SCSI读取函数(for NT/2000/XP). |6 K( ?% A; I( N
  49. String __fastcall ReadIDEDriveAsScsiDriveOnNT();( O, ]( Z  N/ q" g0 V
  50. //---------------------------------------------------------------------------6 O2 {3 V: H3 r( U+ P
  51. // ReadPhysicalDrive
    . u  A1 `# j* r- g; ~# ~
  52. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)! F$ G. u6 {5 L, f5 ?2 L
  53. {' Y" ?* ^3 I7 i0 J: A1 \
  54.    switch(Win32Platform)' H- j! }; I& M5 A8 X& c
  55.    {
    + F- Y) p' Z5 d  t/ R
  56.        case VER_PLATFORM_WIN32_WINDOWS:
    ! n1 w: H8 \- H3 G8 T6 d
  57.            ReadPhysicalDriveOnW9X(pSerList, pModeList);
    - W( b3 p+ _% d
  58.            break;
    : H5 @" D8 n- M/ ~3 p+ P7 V6 z0 L
  59.        case VER_PLATFORM_WIN32_NT:
    % K9 E, v0 p& E; T) ~  ~1 d
  60.            ReadPhysicalDriveOnNT(pSerList, pModeList);
    # z' z3 {, \- C
  61.            break;
    . y% f3 U" l6 ?# V% i
  62.        default:$ C# u# a" D" Q9 Z( N
  63.            break;  S; q" s4 K6 a. p
  64.    }
    0 Y: H3 R# G4 g7 ]* @/ q
  65. }
    6 {- e  u+ k5 ?% T7 U7 \
  66. //---------------------------------------------------------------------------
    4 p3 E4 n& s2 a8 k# x. l% q# ^7 `
  67. // ConvertToString
    % o% u2 U" |0 n: d
  68. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
    1 e; s4 t' M3 I! V6 B1 ^0 k
  69. {7 r* T2 c0 K8 ?% q5 j
  70.    static char szResBuf[1024];
    % q6 W; W6 q/ O( z3 K
  71.    int nIndex = 0;
    3 t. u# `+ M+ Z1 {$ l
  72.    int nPosition = 0;/ ]5 ?3 b8 {" `1 ?" M9 E& S
  73. / j' w3 W! S% v) g8 Q1 n' [- ^
  74.    // Each integer has two characters stored in it backwards
    , I& F) M  l$ r- x5 s
  75.    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)5 G/ n% R+ o0 [  P& i# x8 F
  76.    {2 m, z8 n3 ~- t2 s2 O5 C; l
  77.        // Get high BYTE for 1st character
    8 [) Z8 w5 p) d6 ^/ [" O$ z
  78.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
    % j2 B! X: N: e' B
  79.        nPosition++;
    4 e, R/ W' D, s4 C( z+ U

  80. . r4 y0 d  u! P8 S$ R: G( u
  81.        // Get low BYTE for 2nd character
    . V/ @2 N5 p% S  J, S/ q
  82.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
    5 B' ?$ O. I( L
  83.        nPosition++;
    / }7 R+ _" }- m* V( V* o
  84.    }
    % T; b8 m1 @4 ]) l6 z* q) s2 P
  85. 7 ^: V( g$ P% \/ E- h7 \
  86.    // End the string/ `+ ], \3 g; u# N9 d' M
  87.    szResBuf[nPosition] = '\0';
    & [/ p$ |1 |1 [3 u/ B

  88. / {7 m4 e2 V6 b" T. |  n
  89.    // Cut off the trailing blanks
    , o( U; J/ ]& v$ s) z
  90.    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--); q$ v, ^1 J6 l! L% P& P' m1 |- v
  91.        szResBuf[nIndex] = '\0';
    # w% t9 G, V+ m4 k: D; x0 S# u* t* M
  92. " a0 j. l; v& e; I5 K1 r
  93.    return szResBuf;' }3 \4 ?) v- }* Y$ l
  94. }: [9 }4 a1 j, c% g* _
  95. //---------------------------------------------------------------------------) W! Y6 z6 v# @; V) \: ?
  96. // Winndows NT4/2000/XP 代码
    ( y# q' C! E& T6 L2 y
  97. //---------------------------------------------------------------------------
    : a. X& Q3 U0 M
  98. // ReadPhysicalDriveOnNT
    ) l% Q( ]3 k7 }; B) n! A
  99. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)& X# w* o% R1 a6 V/ A
  100. {
    3 J) m* z- P6 R2 g0 _8 v& D  J2 ^
  101.    // 输出参数
    * w2 I" ?& G% x- i/ v# H3 O2 P  k
  102.    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
    7 d/ S: c  x6 ^7 l3 _1 F) a0 w
  103. 7 |5 z/ B2 c, {# q! x( {0 m
  104.    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
    % N# o3 |( U' P" s5 R9 F
  105.    {
    & z! s! p. e) h% P3 q1 L7 o" x6 d* M
  106.        HANDLE hPhysicalDriveIOCTL;* I5 |: |' }  ~) o
  107.        char szDriveName[32];
    1 Q* {: E3 m$ ?" b1 _* }3 w
  108. / g. y% K9 r% V9 @
  109.        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
    * K( n/ S+ Z: L: y! V' A* X( T+ m
  110.        hPhysicalDriveIOCTL = CreateFile(szDriveName,
    ; f8 n1 g/ D: [; u; R. x+ N! z
  111.                        GENERIC_READ | GENERIC_WRITE,) m& Y0 v( N1 U, E
  112.                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
    1 r+ _- [+ _* U3 t+ n4 x: R
  113.                        OPEN_EXISTING, 0, NULL);
    5 X& d1 l! p% _
  114. ! l7 @0 {+ u- @& S$ @3 a) h; s' U
  115.        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
    2 [; {$ g2 l; q$ `$ S
  116.        {0 G% f! ?# \) q4 z
  117.            DWORD dwBytesReturned = 0;
    ; M! f, D3 r- x+ f1 u5 |; c% C* }
  118.            GETVERSIONOUTPARAMS gvopVersionParams;9 m6 `# T! n, x9 |+ K9 z1 C' ^
  119. % j. m6 b7 t, g, M( k+ Z4 E
  120.            // Get the version, etc of PhysicalDrive IOCTL3 t4 \) O- _  `8 g  K4 F- @& d/ x& z
  121.            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
    ' M3 x7 s$ M( Z  l- g8 n

  122. 0 y* c& r  F# P
  123.            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
    5 L0 D# a6 e6 o4 V7 o" I
  124.                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
    # W8 y  K/ T1 a* ?& y  W5 h
  125.                    &dwBytesReturned, NULL))3 E3 ^* M1 g1 \8 r, Y
  126.            {
    & l- t5 H4 v2 D& ?: k+ P0 Q0 h
  127.                continue;
    " ~3 m- Y% N; K1 c2 J1 ?; f
  128.            }
    : F5 e! M( Q; l1 ]$ b
  129. 4 _+ [0 C7 h5 }% s- [9 f
  130.            if(gvopVersionParams.bIDEDeviceMap > 0)
    9 H) x! ~4 f, h! }
  131.            {
    . |; @6 E6 @7 }
  132.                // IDE or ATAPI IDENTIFY cmd, L7 C- g( ^9 C2 @/ s" [" q
  133.                BYTE btIDCmd = 0;2 I& s! j" j& ]$ l( D
  134.                SENDCMDINPARAMS InParams;
    ) Y$ Z5 W: y9 p' I- Y4 Q: A2 @2 ]
  135.                // Now, get the ID sector for all IDE devices in the system.  `7 `8 u6 {" h1 l) O; W
  136.                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,7 ~' B! |+ z3 l8 q3 i4 l" k0 w
  137.                // otherwise use the IDE_ATA_IDENTIFY command
    % `( Y1 e7 D3 G2 t6 s, n: S
  138.                // 具体所得结果请参考头文件中的说明9 R, D; b5 K7 O" k; k
  139.                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?; D' \! F, T; m3 o" n1 p7 X
  140.                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
    - a/ Y8 c) t1 G5 m2 U
  141.                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
    : {( X! V: Y* a: P6 u+ P. J
  142.                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
    . k' k( B7 }+ V& n' j: \: F) x4 O

  143. " ~7 }& d* o* I; P3 ?% s8 @
  144.                if(DoIdentify(hPhysicalDriveIOCTL,$ n3 _7 a- p3 c% v) N0 D) a1 n' ]  G
  145.                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
    ) I+ Q9 h$ l% Q- W
  146.                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))8 ^0 ]" e$ ?) D" K! v' o1 c
  147.                {. ?% F' `+ c5 f7 X7 \" |+ }) D' E
  148.                    DWORD dwDiskData[256];
    8 m6 l8 y, i1 D( B( h) u
  149.                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
    9 x3 B. f' T( E& p5 \+ v1 u
  150.                    char szSerialNumber[21];
    6 X% A, k: h2 Z; z4 y+ @
  151.                    char szModelNumber[41];4 X( C2 g4 W3 Y# t

  152. 3 M0 J$ S; L7 Q" d
  153.                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;! D8 a4 i# e3 e( p4 v
  154.                    for(int i=0; i < 256; i++)
    * v: S2 o4 W6 p% j3 D
  155.                        dwDiskData = pIDSector;
    1 P" e$ s: [' |* i9 Q
  156.                    // 取系列号
    : F, y, |9 q( ~) W9 E) L
  157.                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
    8 K; N' J( U9 _: W
  158.                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
    6 a7 a- n! a  ?8 Q  {! T. S$ A3 b6 l
  159. ! @- k* X! a  ~8 U3 V) t/ J
  160.                    // 取模型号1 J9 ^" k1 b( J% O; Z- u3 a: @6 X
  161.                    ZeroMemory(szModelNumber, sizeof(szModelNumber));- Y) q9 Y, o. ~) ?, i
  162.                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));/ `5 d1 a% O: `9 _% {# o7 p
  163. + }) A* D! s+ p
  164.                    pSerList->Add(szSerialNumber);
    1 Q3 i2 I: g# {/ X4 k" e( r4 W
  165.                    pModeList->Add(szModelNumber);) c  Q6 B0 v1 P9 w: B
  166.                }" ~, G5 X8 q$ X
  167.            }
    + g' r( C& ^' T5 [( i+ ]$ c
  168.            CloseHandle (hPhysicalDriveIOCTL);
    . K+ l% ~. R4 |- b  L9 ~( [$ _
  169.        }5 j9 S) C7 [, r5 l% Q6 p
  170.    }) ~6 l" w1 l7 @0 \! H; A
  171. }
    4 c; I& r5 {5 Q: A- c0 Q
  172. //---------------------------------------------------------------------------
    * ~1 o3 n$ I# @6 @
  173. // DoIdentify, U" q/ W6 t' l1 X/ n4 O
  174. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
    , b, a- X6 K' R5 h% o( n" Y
  175.              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
    ; ~( x. G* E0 x) f/ Y) l1 Z
  176.              PDWORD pdwBytesReturned)
    ) g3 t7 H% h, v; _8 X8 T; I/ g
  177. {' O- M& m4 Z9 V1 n* m3 T5 Z  T
  178.    // Set up data structures for IDENTIFY command.
    0 a* @/ K) A3 M
  179.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;3 l$ k2 _+ s! g7 i" \2 M  x5 Z
  180.    pSCIP->irDriveRegs.bFeaturesReg = 0;: H+ K/ J, p6 Z  R
  181.    pSCIP->irDriveRegs.bSectorCountReg  = 1;3 u8 o, T6 C5 B( W
  182.    pSCIP->irDriveRegs.bSectorNumberReg = 1;, u, f& R" b$ h
  183.    pSCIP->irDriveRegs.bCylLowReg  = 0;1 n7 a, Q0 I- ?5 ~, {2 x' T
  184.    pSCIP->irDriveRegs.bCylHighReg = 0;
    2 _# q( J! }* M6 S

  185. 1 K8 W$ ~2 X5 R
  186.    // Compute the drive number.(主盘和从盘所对应的值是不一样的)
    ' f6 f) X( ^9 {# R7 O
  187.    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
    6 J; r2 H' \: s6 L6 k) {* _, h

  188. 6 p$ W4 C( D% h! w
  189.    // The command can either be IDE identify or ATAPI identify.3 b0 b! i& n, s& D5 z0 U
  190.    pSCIP->irDriveRegs.bCommandReg = btIDCmd;. i: T9 l& R. \1 j: h
  191.    pSCIP->bDriveNumber = btDriveNum;
    / A4 s4 v! t! h, F5 b& N
  192.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
    : K' c4 q) s/ d" J8 b
  193. * {+ o$ y* E. g  z' K' A- ^4 @" C) h
  194.    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
    4 Z5 j) t! l9 A4 ?
  195.           (LPVOID)pSCIP,
    " |! i$ }( J% t+ q8 d+ C
  196.           sizeof(SENDCMDINPARAMS) - 1,) H( q) U5 C! r
  197.           (LPVOID)pSCOP,
    ! T8 J/ K  B% |/ ]5 ]- ~6 F
  198.           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,1 [1 A1 o4 m& H6 L0 [
  199.           pdwBytesReturned, NULL);
    & x4 j: s- h& _  t4 V0 L7 g& n
  200. }$ f5 s  A' O. G: t
  201. //---------------------------------------------------------------------------
    3 C3 J) N' ?. Q$ z; j
  202. // Windows 95/98/ME 代码
    ) v5 E' \" U; g4 R- b) w- U
  203. //---------------------------------------------------------------------------: \2 n- d2 p# f) [$ k* z
  204. // ReadPhysicalDriveOnW9X
    # ~+ b4 `" c8 c. T* G! E
  205. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)! d3 `4 I% v- O' `# t+ n
  206. {7 r" i/ x0 [5 X$ o7 n- T
  207.    WORD wOutData[256];
    5 `' q1 K! N/ \: Z. A
  208.    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);, r7 L2 M0 a* y! m9 K- X

  209. - A; |6 \! [  R. g- [
  210.    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。. k* _% V: m: l# T% i) y8 i
  211.    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以2 o! z0 D. s  y( {
  212.    // 避免蓝屏的出现。(期待高人能指出原因)
    ; G: |3 }. p& |+ e9 u! v& W: O4 m
  213.    for(int nDrive = 0; nDrive < 8; nDrive++)
    , h2 {$ G% B7 `
  214.    {
    ; v- [' [$ x; U$ i- e
  215.        WORD dwBaseAddress;
    - \! P1 D7 d- s- L& H0 I; Q
  216.        BYTE btMasterSlave;         // Master Or Slave+ ^8 T! F: d6 C9 u5 t
  217.        bool bIsIDEExist;! O: P# ]( Z8 F- Q
  218.        bool IsDiskExist;! [- u( G) q" K# h% V  `

  219. 8 ^) W# l, a  O7 w# z# x2 O
  220.        switch(nDrive / 2)
    , d  o8 r$ `3 M0 S3 Z9 N
  221.        {
    + q, U& K& e: V8 Z# j
  222.            case 0: dwBaseAddress = 0x01F0; break;
    5 P! Y7 U8 |4 D* p
  223.            case 1: dwBaseAddress = 0x0170; break;
    % A0 L5 S( k. p- i; {& E: p
  224.            case 2: dwBaseAddress = 0x01E8; break;
    . L4 `2 S; \* i2 i* v/ \. C4 c9 e
  225.            case 3: dwBaseAddress = 0x0168; break;/ f) F1 E, o" x: P
  226.        }
    1 F3 D6 w: J! w7 a3 F- Q

  227. - \1 _" N, h7 m
  228.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);7 P2 a4 m7 {/ o8 R$ G
  229. + F' E( G/ q: _( c
  230.        // 进入Ring0
      {% m+ S; @% t4 F- c! \( s( l' [
  231.        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,6 V( ~% S: b, N
  232.                bIsIDEExist, IsDiskExist, wOutData);
    $ u% A% r8 \6 `" b1 ?
  233.    }! U+ v# ]  ]' f5 L- M1 y
  234. 4 D0 a* [2 U8 a. B! s) D
  235.    // 开始读取
    8 V+ \0 m8 V: s7 v
  236.    for(int nDrive = 0; nDrive < 8; nDrive++): j& O2 a# S& h/ e" \& \% `& H$ a9 z$ u+ i
  237.    {
    0 ^( f) G# y+ \+ j- A( T
  238.        WORD dwBaseAddress;
    3 O& w; Z3 D% {; v
  239.        BYTE btMasterSlave;         // Master Or Slave7 j6 d& U& r$ W+ N, [
  240.        bool bIsIDEExist;  m- T9 N+ U) t9 r9 J  [3 H! S
  241.        bool bIsDiskExist;9 w" j' ~$ ?! f: @5 `6 U
  242.        switch(nDrive / 2)
    # f  \7 Z* m% `' f& j" {% M) q
  243.        {
    3 e3 T" F& g( m
  244.            case 0: dwBaseAddress = 0x01F0; break;
    9 C; e: G! s# x% m+ l
  245.            case 1: dwBaseAddress = 0x0170; break;
    9 G* j/ j& I" D9 r7 i3 l; x8 _
  246.            case 2: dwBaseAddress = 0x01E8; break;
    4 K' v% O4 r& ^* g3 `
  247.            case 3: dwBaseAddress = 0x0168; break;
    , `. g, R/ p) y6 ?) i+ c$ F
  248.        }
    - C  W( K$ |; S9 K. \3 S0 I% K% E
  249. 2 j4 o. O) \6 J- f; k
  250.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);, ~8 x4 a- E- g7 u* I
  251. 5 D( K6 P$ ?( z/ B3 b
  252.        // 进入Ring0
    3 G7 }5 ]5 W$ f+ K8 Q$ }
  253.        bIsIDEExist  = false;
    - }; M! U+ ]. y5 K# t
  254.        bIsDiskExist = false;
      B: z% t* d0 ?( \% I+ A- \$ I+ m
  255.        ZeroMemory(wOutData, sizeof(wOutData));
    ) p. q+ e  y+ k& }6 j1 E1 c

  256. ' v  {( d& U2 n$ D0 h7 F, w' S
  257.        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
    : K- Z# P2 K; U& V! }) p
  258.                bIsIDEExist, bIsDiskExist, wOutData);
    " @: A$ L8 J, H: C+ }; u1 L

  259. . d0 L1 \4 z& J2 y5 [
  260.        if(bIsIDEExist && bIsDiskExist)
    * }4 I4 f+ L/ _
  261.        {, j  e; U0 v; y' l% S
  262.            DWORD dwDiskData[256];6 `1 g' t$ b1 c( b* O! S
  263.            char  szSerialNumber[21];
    & M- O7 v" P2 j! i" w, s, y
  264.            char  szModelNumber[41];
    0 t( ?7 k" Z* ?0 j/ o6 {; [1 j

  265. ; ?3 b5 N. P0 |& s! M
  266.            for(int k=0; k < 256; k++)
    4 i( I% H( x2 y# A, v  |0 h0 w. n2 _
  267.                dwDiskData[k] = wOutData[k];+ Q1 N2 `# }& p* u  c; h% g8 z
  268. ! u1 O# G& T5 p, B+ E3 @
  269.            // 取系列号/ N2 N7 t, @. c* W
  270.            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));0 Y* `9 E' {  |' @8 ]( o" {) ?- l6 k
  271.            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));3 _2 {% {4 f) v2 Z7 d7 _
  272. 9 Y/ l/ I3 L/ U6 G6 h& o
  273.            // 取模型号
    ( ]3 ~3 O9 A  Z* j: p0 R4 o
  274.            ZeroMemory(szModelNumber, sizeof(szModelNumber));' `' h5 i6 g9 g
  275.            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));7 S& W) B; ?" T+ b
  276. 2 n. G  ?& s6 i# W0 v- a
  277.            pSerList->Add(szSerialNumber);: ]5 }4 a0 Q/ s- A: c  i
  278.            pModeList->Add(szModelNumber);$ E! @# r& j  H5 u2 V6 ?
  279.        }
    3 y! _* E+ c3 g+ I) P
  280.    }
    * x) N8 B3 W5 O+ F# c
  281.    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
    * i1 D8 R: E+ t
  282. }
    " _2 g, x0 r" r' `9 L  Q
  283. //---------------------------------------------------------------------------7 O6 o+ A1 w1 l% g
  284. // ReadPhysicalDriveOnW9X_Ring0()
    1 h, T9 P3 d+ h. h# ?% M
  285. //( p& \+ X  |7 W/ V! w
  286. // dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
    " C: Q) Z' Y, ?: o  Q$ y
  287. // btMasterSlave = Master(0xA0) Or Slave(0xB0)
    2 n4 q8 ]4 l& p" K1 p5 V/ \& J
  288. //---------------------------------------------------------------------------
    ' {$ V. q& k( L2 E
  289. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,. X/ \! B8 s9 Z9 c3 U- R" \$ G- @* g
  290.        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)( U& g+ g" H9 w; G2 Z
  291. {, v+ e1 y$ h) }: ]7 M* [6 i7 H
  292.    BYTE  btIDTR1[6];
    4 F( M% M4 o3 k- }$ k
  293.    DWORD dwOldExceptionHook;9 h5 o8 T- P( E: `% C. _
  294.    const int nHookExceptionNo = 5;2 K. R1 r. E9 k/ C; ~: a$ [

  295. $ K& r6 b! i/ I8 w: n$ y6 u
  296.    BYTE  btIsIDEExist = 0;2 P( q1 p( T7 p  o. d' i' ^/ L0 f; n
  297.    BYTE  btIsDiskExist = 0;! W, w2 c+ k/ F
  298.    WORD  wOutDataBuf[256];0 y# ?3 r; B! v6 _7 l* a! N- _
  299. ; m! J: P4 Z: p: x  w4 i- a+ C
  300.    BYTE  btIsFirst = (BYTE)bIsFirst;) Z+ V' p2 i0 R4 a/ x2 u" q* ]/ V
  301. 5 ^# |; b5 r0 C  V
  302.    const BYTE btBit00 = 0x01;8 j  }2 n; q4 c. e; m0 K6 H% G
  303.    // const BYTE btBit02 = 0x04;+ o' x( t0 s" V1 G: ]. J
  304.    const BYTE btBit06 = 0x40;) N2 q0 `+ J) j  |' U" R2 \
  305.    const BYTE btBit07 = 0x80;$ y9 h. i3 u  t: J" C+ O8 X1 \
  306.    // const BYTE btERR  = btBit00;  y/ T  y$ ]+ F( M
  307.    const BYTE btBusy = btBit07;* K5 n) z; [( J4 f5 y
  308.    const BYTE btAtaCmd   = 0xEC;6 k6 h( f; G/ V/ E5 s. O1 a
  309.    const BYTE btAtapiCmd = 0xA1;2 }0 |- j! x/ V
  310. - q3 u0 E) p3 x8 P: \
  311.    __asm
    6 I" w0 t: z  s8 ^6 N' e- Q& _0 s
  312.    {
    9 M6 Z* ^" L! h8 ?; |) S1 O# [$ H% a
  313.        // 必须先执行这条语句
    2 X% u$ \* W6 @! ^& F
  314.        JMP EnterRing0
    " X* r, n. A: y6 q% S# Q
  315. # }& r$ H# Y% g, h2 o
  316.        // 定义过程; i. M- S  j( u
  317.        // 等待IDE设备直到其不为忙为止
    - K& h2 E& ?) s
  318.        WaitWhileBusy proc. g. t! Z4 I1 w! L2 a
  319. ; H: R# c, f7 m- M
  320.        MOV  EBX, 100000* k, Y% x7 ]3 O# ^
  321.        MOV  DX, dwBaseAddress) E" Z6 o6 A/ I3 f0 I2 w. {/ I
  322.        ADD  DX, 79 W, C; X. C4 V# j) t5 b9 _4 s

  323. % C) r. X& j* ?5 a2 W3 R
  324.        LoopWhileBusy:8 G" r* \- b9 H) X
  325. 4 ^) ^: X6 n+ u6 F" ?: d( [
  326.        DEC  EBX. o5 U/ c  Y$ d4 G9 V+ F- {
  327.        CMP  EBX, 0
    - C; G& N7 U% J& B9 `$ N. b
  328.        JZ   Timeout
    + X9 I: t* R- M" G  n
  329.        in   AL, DX
    % E& Z) Y+ t/ t$ o1 ^
  330.        TEST AL, btBusy
    2 f4 ~( l1 M+ H* s
  331.        JNZ  LoopWhileBusy
    . Q) ^1 S7 ^( y- e9 E
  332.        JMP  DriveReady
    % G! i% M$ Z+ ^

  333. 0 b+ T. `+ a9 J6 \; \( A
  334.        // 超时,直接退出# U; e% Z7 N( i* s9 F! J3 `
  335.        Timeout:. h. E8 D4 M6 v% M$ {
  336.        JMP  LeaveRing0" h) ~: w  s+ K! U- O) t5 k# j
  337.        DriveReady:
    $ O$ X% s. \  C
  338.        RET  @2 ]  K4 `( {# D8 u& f9 l9 b
  339.        ENDP   // End of WaitWhileBusy Procedure4 c! ]$ Z% o" X8 F8 d& B
  340. ( W( G+ H; o1 U+ x8 M, J% J
  341.        // 设置主盘和从盘标志
    # q% I0 D4 t4 [# ~! }) X" b
  342.        SelectDevice proc
    ' c3 K+ p! n5 j) Q5 j

  343. $ |3 ?$ {- A0 q* w' I4 i
  344.        MOV  DX, dwBaseAddress
    9 M& }3 J5 c; {; c8 @$ ~9 m7 L
  345.        ADD  DX, 6
    5 [( I" g& Z. W: i: ?: x
  346.        MOV  AL, btMasterSlave# b4 c4 Q( d! W7 a) S" P0 B
  347. / l7 H3 y! g$ ?
  348.        out  DX, AL8 ]" C. g4 @  F5 O
  349.        RET; e( G' z) N2 b( U3 z- g4 K6 ]+ R4 n
  350. / w# d0 r4 q& j  Y, i
  351.        ENDP  // End of SelectDevice Procedure
    & P& l  R6 f6 y  c' F

  352. - s+ C3 ~$ y! |  g% L+ V
  353.        // 向IDE设备发送存取指令, e# d9 O1 v* }" L! L
  354.        SendCmd proc5 T& B1 j, X) F: V0 z
  355. # L) W5 Z) J6 m  z6 s  O% K( U: P; F7 l
  356.        MOV DX, dwBaseAddress
    5 \; ?) n+ d( e* o
  357.        ADD DX, 7
    1 x* d3 `  ?( \8 d
  358.        MOV AL, BL // BL是主从盘标识,在过程外设置7 R  m, G2 `1 S5 l( C
  359.        out DX, AL' I2 ]2 I: L: Q$ t
  360.        RET
    7 j* T6 S7 ~, K! w% q/ j  G7 K' S
  361.        ENDP  // End of SendCmd Procedure
    ( u8 m# |+ u9 f+ ^/ _' k
  362. 9 q* a' v9 d% I: I9 ^$ V
  363.        // Ring0代码/ e5 k: |. A0 z  d5 t" g" |
  364.        Ring0Proc:9 ?2 X4 r6 b* ]! V
  365.        PUSHAD
    8 k, V% ~" w/ o: w
  366.        // 查询IDE设备是否存在& _. Q2 Y  w9 x  A$ N. q0 G9 n' m
  367.        MOV DX, dwBaseAddress# w0 b9 ~0 P/ l5 f+ }* V# z1 k
  368.        ADD DX, 79 s2 D. C) t! I4 y1 k
  369.        in  AL,DX) W& J/ J; ?; I$ f/ _7 }1 Q
  370. 8 Q5 I: s( I% [8 G" }( M) ]
  371.        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
    ; L: Q& F/ E' U1 r' c2 A( n
  372.        CMP AL,0xFF
    9 _+ k' L$ i$ G, {: G6 ?( H: ^
  373.        JZ  LeaveRing0
    4 |# q' D8 r: _0 [/ D: T, }/ G
  374.        CMP AL, 0x7F
    ) n! E, \+ o$ H) B
  375.        JZ  LeaveRing0
    3 [5 p7 U8 ~& D' ?
  376. 0 E" I2 W9 c3 k# g
  377.        // 设置IDE设备存在标志
    8 T3 ^# E! A9 c. ]$ k* I# m: I0 e
  378.        MOV btIsIDEExist, 1: `, P% M* Y7 y  P( j1 a

  379. * {  a4 X( ]9 `7 u- ~" p/ ]
  380.        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)) |# B, p6 X( @9 G- A0 W  B" a* k
  381.        CALL WaitWhileBusy% K7 z0 V/ J4 m' C6 A
  382.        CALL SelectDevice2 z3 n( s8 z1 K; Q' q! o
  383. - K: \- E$ O1 B1 Q( V5 G! W
  384.        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
    : r4 p; x2 n) s, Y7 {2 ~; B0 x
  385.        CMP  btIsFirst, 1$ a) d0 W% t* A; ]6 I6 O
  386.        JZ   LeaveRing0% [2 c. v( C9 g$ |$ b5 G' ~
  387.   q$ \; ?' k9 k4 s: }' r
  388.        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
    $ R) J2 d7 R; H6 f0 Q& _4 \
  389.        CALL WaitWhileBusy
    ! [5 E4 V3 \( z

  390. 8 k' H* r$ j8 T! x
  391.        // AL的值等于cBit06时,不存在驱动器,直接返回0 K2 T! Q( a5 t; _
  392.        TEST AL, btBit06; O: g8 [! r- @) z6 \  |# H
  393.        JZ   LeaveRing0
    9 s' ?0 l) e* M& V

  394. . ^% x4 \  K, ~: ?; u
  395.        // 设置驱动器存在标志/ c, D& N! M0 H; `  P
  396.        MOV  btIsDiskExist, 1
    2 s, N2 E) p: p; x/ {# F
  397. 0 c- A  e- P: L  X
  398.        // 发送存取端口命令) G! W: I2 s# a
  399.        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
    2 z2 F5 Y% _% `; |
  400.        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
    & B7 D9 k' m2 {6 G
  401.        CALL WaitWhileBusy" S! z6 U- g) \7 \/ Z# H
  402.        CALL SelectDevice    // 设置主从盘标识
    9 A5 A  K& Z, I2 ^  f& ~$ D
  403.        MOV  BL, btAtaCmd      // 发送读取命令% {5 e  @2 c% B5 q9 w6 Z8 o$ T
  404.        CALL SendCmd3 r$ ]* u, K" f( O8 w- H7 S& y: P
  405.        CALL WaitWhileBusy
    " ]6 q$ w, `3 {; c( c

  406. ) j3 t( i4 V  e; _" u
  407.        // 检查是否出错& T" r$ R9 ?% H2 m( e. m  R
  408.        MOV  DX, dwBaseAddress
    % v) ]  P# R! _9 }+ g2 Z
  409.        ADD  DX, 7
    , e$ J" B/ H$ e1 A* D+ z

  410. ( B6 e# L3 G6 Z7 I1 A2 ~
  411.        in   AL, DX
    ! s2 {, g! N  y& w4 l

  412. 5 q: x; C$ p- y6 b" w% O/ V
  413.        TEST AL, btBit00
    , H* A8 n, j& C" t8 m+ _
  414.        JZ   RetrieveInfo   // 没有错误时则读数据
    2 m1 M  o/ [* z: b! v4 r, T
  415. . i2 U# u* H2 H" r6 Q7 q9 f
  416.        // 如果出错,则进一步尝试使用ATAPI设备命令/ B# O: i! |6 f1 Q# l! ]% @( |. k
  417.        CALL WaitWhileBusy3 o; r9 z! [3 V+ x% N  o
  418.        CALL SelectDevice
    : k( D# |; v& y! V1 ]
  419.        MOV  BL, btAtapiCmd
      j) ~4 c# C2 X4 A! {
  420.        CALL SendCmd
    $ d; ?. v9 f+ k% ^
  421.        CALL WaitWhileBusy
    8 \8 b, u: L) d
  422. ( o$ \: B6 |8 r+ H6 Q; b5 d
  423.        // 检查是否还出错
    ) c% d  G4 n  }+ J1 [
  424.        MOV  DX, dwBaseAddress
    - x' q- u- x: P8 c; o
  425.        ADD  DX, 7
    ' y" u+ {- f( U# h& S7 ^
  426.        in   AL, DX
    + ~! r- x/ t+ |4 O3 S
  427.        TEST AL, btBit00. D+ K: b- {+ S9 N) x( S0 z
  428.        JZ   RetrieveInfo   // 没有错误时则读数据
    . F6 Y1 S1 T* f9 L
  429.        JMP  LeaveRing0     // 如果还是出错,直接返回
    . W# S4 c1 |- R0 }$ C
  430. . V6 `- o! \! U" u! ]9 Q6 f
  431.        // 读取数据# K( j# p% |2 z* {% L6 {- e8 y
  432.        RetrieveInfo:  Y7 b- f0 s3 N- P7 z* U
  433. * F; f- z! z' X* C0 j( ~
  434.        LEA  EDI, wOutDataBuf& r0 V* x& {( I8 r
  435.        MOV  ECX, 256* E7 X6 v/ G3 E5 E' t! l
  436.        MOV  DX, dwBaseAddress- p3 ]  ^9 x! O- l' e4 c& [8 D
  437.        CLD
    3 V" P9 q8 {& u9 M$ Q
  438.   ?7 x% x6 w" R1 v
  439.        REP  INSW- s" \! J& @1 i6 ^8 F% p9 d  ~9 x" h
  440. 3 K$ i6 p6 Z2 e5 v. c/ @% U# q
  441.        // 退出Ring0代码
    * v1 f8 m! j: D
  442.        LeaveRing0:, S; m; M6 F1 H* S5 e8 t# t

  443. 3 H3 Z1 C! N) L7 S# |) ^
  444.        POPAD  u9 R2 V. V7 e5 _. K
  445.        IRETD
    + K1 h  N- S# Y8 ?/ V' A

  446. % L  p' f* ~  s8 c0 A" p# J
  447.        // 激活Ring0代码
    6 B9 R" N6 E+ N/ c. s- ~& l
  448.        EnterRing0:
    " n" Y5 s) _! z* r1 I; G; M. E. M5 b
  449. 3 K7 m0 M% n4 G# C! I
  450.        // 修改中断门7 k( |( N( r0 [5 i# y2 p' f
  451.        SIDT FWORD PTR btIDTR1& Y/ M# z, l1 `- Z. |
  452.        MOV EAX, DWORD PTR btIDTR1 + 02h
    8 }# R& Z2 J3 ]1 ^- s5 v  _# G
  453.        ADD EAX, nHookExceptionNo * 08h + 04h
    & Y! i. [' O) z. D" W- x4 _6 y
  454.        CLI0 {4 h: ~8 s5 }5 w/ h$ @# P! w2 {

  455. / M: M! x7 x* O
  456.        // 保存原异常处理例程入口
    % b/ l) l0 ^! C! w% R& g
  457.        MOV ECX, DWORD PTR [EAX]4 m, \- x+ ?8 [. z
  458.        MOV CX, WORD PTR [EAX-04h]
    ! C% U$ O. k9 }
  459.        MOV dwOldExceptionHook, ECX
    9 Z: L; K& \: S  h

  460. 1 s' p/ k3 N+ v) e1 I
  461.        // 指定新入口
    0 n& G! N3 A$ t6 U8 Y0 i8 N3 i# O
  462.        LEA EBX, Ring0Proc
    6 @: g6 X2 S5 N- T3 A7 O# o
  463.        MOV WORD PTR [EAX-04h],BX
    ! Q2 h- |; ]3 n0 P* W1 x, v: h
  464.        SHR EBX, 10h2 b1 W( d4 G! t/ m! _
  465.        MOV WORD PTR[EAX+02h], BX
    0 a3 t4 S% ^' K

  466. 0 z' V- A: @5 ^4 Y3 c- A( l
  467.        // 激活Ring0代码5 p& f: I' u' c. i
  468.        INT nHookExceptionNo
    / U4 o3 r2 o! M/ v- Z1 S1 N; u

  469. ) S0 |- q6 f+ y
  470.        // 复原入口$ O% }2 u( w- c- f& ^* g4 S+ A# T2 S
  471.        MOV ECX,dwOldExceptionHook
    % ], T# k8 o  V' Y
  472.        MOV WORD PTR[EAX-04h], CX" h$ @0 }2 s5 ~; q
  473.        SHR ECX,10h
    1 e( B6 p; u: ~  C4 P, E
  474.        MOV WORD PTR[EAX+02h], CX
    * L) t  d6 l5 T. ^; e$ K
  475.        STI
    7 k7 V8 I/ C) s
  476.    }
    # @  Y  ~: o1 ^0 P0 ?
  477.    if(!bIsFirst)
    ! i0 `; U5 g8 @5 t! }* A
  478.    {' y" w6 k8 B, D9 v" I& {8 v
  479.        bIsIDEExist  = (bool)btIsIDEExist;6 v9 F. e- _3 D7 U: p. v& P# P) x
  480.        bIsDiskExist = (bool)btIsDiskExist;; u( A& v- t5 m/ ^' ?
  481.        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
    : ?1 G% e, j% G
  482.    }
    / z6 _! R: O# M2 y( h
  483. }
    - `1 x1 U3 B" l6 O; O3 `' o9 v- s
  484. //---------------------------------------------------------------------------
    # e+ e4 u3 b9 T' n
  485. // 调用方法:! g+ E$ K; j& E' E& C# O
  486. void __fastcall TForm1::Button1Click(TObject *Sender)! M. ]2 w+ n# ]2 Q8 q% ~' N
  487. {6 O1 ]  g) b) L& X+ ^  o2 [
  488.    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);' B+ R4 u! K4 s1 C& ^
  489. }
复制代码
发表于 2005-8-15 01:00:45 | 显示全部楼层
晕乎乎。。。怎么看8 洞阿
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-8-14 00:56 , Processed in 0.020322 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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