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

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

[复制链接]
发表于 2005-8-11 11:42:04 | 显示全部楼层 |阅读模式
  1. #include <WinIOCtl.h>. q6 ?( x# e: Q3 E" R; P
  2. #include <stdio.h>% X& h% F0 N, G" @

  3. . t. Z7 C  \9 m  Z# b& K
  4. #pragma inline
    8 |2 `2 D& b- V, S" J
  5. //---------------------------------------------------------------------------
    - W! U( Q- C% }% D, M) h; ]
  6. // IDE NT/2000/XP专用变量
    ! c; `; i8 U4 d+ h5 A  \, [. c- a
  7. #define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
    + m7 q: s; ?6 c8 i0 F- I
  8. #define DFP_GET_VERSION         SMART_GET_VERSION
    5 P3 s$ O: |$ K8 t
  9. #define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND  n' K( l9 V! W5 x% B1 i+ m% K" Z
  10. #define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
    ( L. j, y& e. v( ]) M. y
  11. $ ~# _6 o& D1 }
  12. const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令
    ! c7 t2 H2 j! c5 \1 w
  13. const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令5 g, @# z4 H$ x; C3 x8 t: f

  14. & q' \  c" p: X" T) O9 A3 }
  15. const int MAX_IDE_DRIVES = 4;
    0 A3 b+ n! S( m$ g

  16. 7 \0 c: c) _, T+ C, @
  17. // SCSI专用变量8 d4 u! R3 n5 e' s( j" p
  18. const DWORD FILE_DEVICE_SCSI             = 0x0000001B;: E! D% t6 f6 M% S' ^
  19. const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);7 \8 [$ _# W2 t' h) L" m$ F5 e
  20. const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
    0 ]" [; O9 O# V2 u3 m/ G9 n0 r! m7 y
  21. const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
      u7 N; T  Q2 u! I

  22. & {0 A% b8 `% @
  23. typedef struct _SRB_IO_CONTROL& v$ C6 f3 ?! Z- x! G
  24. {" P# Y+ R- _, a; \
  25.    ULONG HeaderLength;& }9 w+ y. I5 I* L/ [: x6 _- [: d
  26.    UCHAR Signature[8];, N1 a6 h' {& J! ]* }( s
  27.    ULONG Timeout;
      Y- {. W8 z  p6 W3 {* g. h
  28.    ULONG ControlCode;
    + z/ h% j. z: K6 M, ^5 b
  29.    ULONG ReturnCode;
    ) p4 `4 \% i/ q$ J6 C
  30.    ULONG Length;- z1 f: M  u5 v# \
  31. }SRB_IO_CONTROL, *PSRB_IO_CONTROL;# T: T; C, L' G# f. ?" M2 H

  32. * S! b$ ?- c& ?! h
  33. // 读取的主函数, F" O* k) e2 Y- ^' C
  34. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
    1 R. m' S% D, U4 ~8 `* x* U7 R
  35. 6 T  k- s, C. Y% z9 s1 V
  36. // 辅助函数
    0 z7 v2 L; p- S% @) M
  37. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
    " ~& z7 O. w  d' @
  38. // NT/2000/XP函数
    . q+ C' G+ h9 K' k) {0 A, t8 o
  39. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);7 b# x& x' E" P
  40. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,- }2 |" ~0 ?6 j, T+ t3 M
  41.        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,3 i4 z, T2 A% A" e, F
  42.        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);! I2 C( A" H/ i* |$ X. g, u; s
  43. // Windows 9X函数7 _1 y5 x$ G6 M& ]
  44. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);
    4 W9 Q+ K( |- @3 n, e. `7 ^
  45. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,: y1 z/ z+ V- ^' H
  46.        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
    ' c/ m3 U% ~1 B3 A( d
  47.   L  C/ @0 A- ~
  48. // SCSI读取函数(for NT/2000/XP)
    $ c+ ]) `  N# ^
  49. String __fastcall ReadIDEDriveAsScsiDriveOnNT();
      ^) Z# i) P  A4 l5 L
  50. //---------------------------------------------------------------------------
    4 V& L$ D; s; q6 ]5 e
  51. // ReadPhysicalDrive
    6 Z2 C$ g8 e" M; C" Y
  52. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)3 F' A, c' ~0 F/ |! b: O
  53. {
    + {- m. C* x  q  }
  54.    switch(Win32Platform)
      s, w8 `, Z5 [# h
  55.    {& P- j$ a9 O5 w8 Z9 I
  56.        case VER_PLATFORM_WIN32_WINDOWS:
    3 p4 x0 }5 X5 k4 m
  57.            ReadPhysicalDriveOnW9X(pSerList, pModeList);" y0 I: `7 M/ N. e  `3 [
  58.            break;6 n6 N7 W9 V0 Q0 F: O& l0 d
  59.        case VER_PLATFORM_WIN32_NT:# x* L9 R0 x' Q2 b+ e
  60.            ReadPhysicalDriveOnNT(pSerList, pModeList);& p: p% m5 `1 X! Q6 N8 X
  61.            break;
    & ~# s0 c& e9 n, q/ F* I
  62.        default:
    / i0 t* t0 \4 o, H6 a
  63.            break;
    + F" q/ R1 S% p2 b& E
  64.    }% `& r0 O8 q& e, l! V
  65. }
    ) H. v; L; H& x0 `- I; b1 u
  66. //---------------------------------------------------------------------------1 B: E* ~# C# C; r, Z$ a! n' r
  67. // ConvertToString' d- {+ X& W/ e* Q, Q. K
  68. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
    $ H; f6 z* ?* E7 G8 t6 ~+ F
  69. {- [0 S1 l3 l' c# p
  70.    static char szResBuf[1024];8 k# U! ]4 c7 ?9 w7 F! R4 e
  71.    int nIndex = 0;2 `) ^$ T! ?+ `6 ]5 J
  72.    int nPosition = 0;0 I9 `6 v/ F. y3 O/ E* B* G/ W
  73. 8 d( B  H0 J% A  T# \$ I2 g5 c
  74.    // Each integer has two characters stored in it backwards- k/ l& f! Z$ d; ]! a
  75.    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)& I( D& H5 f  t, Y: w1 h1 o6 S
  76.    {
    1 U0 ?) W0 q0 b9 K: q
  77.        // Get high BYTE for 1st character
    6 j8 `  j2 h+ D4 w3 L9 H0 g2 U& B
  78.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);3 w* _/ C( Z' y; s; y1 I
  79.        nPosition++;
    3 |  n0 z! d7 L4 L8 k# U" }

  80. , a- g# k1 }6 ^+ g9 M  I& B
  81.        // Get low BYTE for 2nd character
    / h( r$ c$ a. x0 |0 g
  82.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);& T0 G6 f6 T0 b+ D* A  ?: W
  83.        nPosition++;4 G/ w6 y6 u* q- \
  84.    }! J9 j2 N6 M# Z

  85. 1 I9 a4 Z. x- {, H
  86.    // End the string
    % P$ E# F0 g6 H
  87.    szResBuf[nPosition] = '\0';1 r& Y/ U3 n% b7 R. x
  88. ; _( ]8 j, f+ k& t
  89.    // Cut off the trailing blanks
    * s! @; [% @! W! Q  Q. x
  90.    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
    # M" D: r# ?+ z
  91.        szResBuf[nIndex] = '\0';! L& S$ D' o! m9 x& J

  92. ) k' H  |- h8 D" M( U
  93.    return szResBuf;
    ' F9 K; W: R5 r6 O6 A
  94. }/ ~( D/ v, X2 `' @% |
  95. //---------------------------------------------------------------------------7 p- b& c& }" F: p6 ~  @
  96. // Winndows NT4/2000/XP 代码* Z+ C( h9 G, S8 [
  97. //---------------------------------------------------------------------------7 @4 }( W: t4 ~$ K' [2 n. P
  98. // ReadPhysicalDriveOnNT; u& p& T, A3 Z) i* l, i
  99. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
    4 L' _. h/ G% Z' S
  100. {+ ?: V! C2 F+ j" C' N9 Z, z
  101.    // 输出参数
    1 O  u" i6 N9 D
  102.    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];, ]! _9 y# y6 K
  103. 2 O$ k" R4 a3 W1 Z
  104.    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)4 }3 n* y' ~, B; g5 B3 G+ m0 g$ \
  105.    {, w: t) f& F; ^( E
  106.        HANDLE hPhysicalDriveIOCTL;
    $ d1 m# ?9 [3 D( D5 o. V! i( ~
  107.        char szDriveName[32];/ B* \% ~& i9 S$ y8 ^( r6 Y
  108. ) g9 p3 Y; [/ K  X( w
  109.        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
    ; K) {  r* O' x* `
  110.        hPhysicalDriveIOCTL = CreateFile(szDriveName,9 e/ X- [+ Q& C5 L5 j8 F' n7 D( U
  111.                        GENERIC_READ | GENERIC_WRITE,
    3 V( C9 ?+ i; y3 |( U# E) v) Z$ x
  112.                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
      |9 N2 W% V% E" [' i
  113.                        OPEN_EXISTING, 0, NULL);
    * y" C8 h# Z& p# X3 R3 t) u& q

  114. + B; Q& K" a* f  j* w2 F4 C
  115.        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)) y  B$ t; V; m, z. H6 i7 W
  116.        {
    9 }, e9 N9 f) Y" y* A7 \
  117.            DWORD dwBytesReturned = 0;
    8 H0 ^# |; s& `1 L& Q
  118.            GETVERSIONOUTPARAMS gvopVersionParams;2 ]. c* _3 r$ D- {1 w* f
  119. : }6 f0 }9 n0 D2 n5 O: z. y
  120.            // Get the version, etc of PhysicalDrive IOCTL4 N) ?' \$ d( w
  121.            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));" O1 e" M7 ?; k4 `' U6 \3 v
  122. ! ~& @2 C& f- p$ J2 X! Y  I
  123.            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,) d4 \: K! H6 ?4 j9 Q4 W
  124.                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),/ |) [: H; [+ @4 e6 I1 d- L
  125.                    &dwBytesReturned, NULL))
    ! Q" B  _' W4 a6 W' |' I
  126.            {
    1 t) l! Q# M2 H! i8 K
  127.                continue;5 I/ k8 T4 k: M& I
  128.            }. `$ P; _% l0 P! C) K8 g
  129. 3 L, e& M% A' e- W
  130.            if(gvopVersionParams.bIDEDeviceMap > 0)
    # ~" C( t, u3 x  Q7 q; N$ Q2 p
  131.            {5 n0 O0 |5 Y7 |$ C, _( F7 T1 Q
  132.                // IDE or ATAPI IDENTIFY cmd
    / G* `# y) t) s' P$ }
  133.                BYTE btIDCmd = 0;
    , A$ n- P- [4 X; W
  134.                SENDCMDINPARAMS InParams;
      N8 G, w* ^. ?# b; P6 C# V
  135.                // Now, get the ID sector for all IDE devices in the system.
    , r( T: d+ a$ \, V) m
  136.                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
    * f9 K+ q+ o! q) c; P
  137.                // otherwise use the IDE_ATA_IDENTIFY command# s9 m- m& g( r! s+ G2 T1 w
  138.                // 具体所得结果请参考头文件中的说明
    - b) u, \  {) A/ j
  139.                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?* A; s$ l3 q& ~; H. l
  140.                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;" m0 H  m5 h- D! G
  141.                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
    ' e7 _4 @! L+ l& G3 Y- O* C% c
  142.                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));3 s  ^% o5 U5 ^5 F. a- S( w
  143. * T% d# m# k' x' K+ c
  144.                if(DoIdentify(hPhysicalDriveIOCTL,
    $ z" D- I( p: O) x1 D+ u
  145.                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
    8 X; r4 P9 O# g7 ?& q" L+ G
  146.                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
    8 J( m* G8 o2 K) E
  147.                {
    5 U7 b. f% d7 M# q, C
  148.                    DWORD dwDiskData[256];& y! A% P/ ?* L1 r9 T
  149.                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
    2 b( v; c' x8 S2 ^6 K
  150.                    char szSerialNumber[21];/ y7 X/ R0 ?( @/ \4 z5 @
  151.                    char szModelNumber[41];$ O) u( s# ?. F3 O# @3 X$ c
  152. 4 m! ]* P4 Q5 N. J
  153.                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;+ j' v1 c/ O3 b+ R; z* N
  154.                    for(int i=0; i < 256; i++)# c. w2 ]0 ?1 Z: p* W  K
  155.                        dwDiskData = pIDSector;4 K1 x  f# b$ Y( O' [& z
  156.                    // 取系列号
    3 a% P0 [# R; {* Y
  157.                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
    9 z5 s, h* I' R, V. f) H' K
  158.                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
    . X. p# E5 ]. B& m. q$ O" x, A

  159. $ k0 n2 H2 ]+ H& \+ J2 j
  160.                    // 取模型号  n8 q/ s+ V: x4 K, L7 t
  161.                    ZeroMemory(szModelNumber, sizeof(szModelNumber));( e0 \4 |; J( a
  162.                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));+ @8 n5 z1 r6 s' |

  163. 4 ~0 K, g8 I4 o) \, J: ?; n2 [* v
  164.                    pSerList->Add(szSerialNumber);
    8 y. P" [6 t* z$ `9 a& ?9 S5 s
  165.                    pModeList->Add(szModelNumber);
    ; r4 ~) p) U) z
  166.                }1 D1 `& ^( r& I/ C
  167.            }
    ( _; O1 h2 v2 w2 s! ?4 f+ g% u
  168.            CloseHandle (hPhysicalDriveIOCTL);- v, w6 P' N% e' N8 g7 A% q. q: V
  169.        }: Z- j& A  `4 E6 Y9 [9 t" D
  170.    }
    7 R; C& B3 v* F
  171. }  d; [  o5 g! d. P- m3 Q0 B8 l8 Y
  172. //---------------------------------------------------------------------------
    * n5 d) ^, i# p& o, [
  173. // DoIdentify' I4 a; S8 b" n3 ]
  174. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
    & R  b$ |! F) ]9 x  {
  175.              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,  D; E% @' i# y/ i7 `
  176.              PDWORD pdwBytesReturned)
    $ i2 |- ~' N& j2 k4 K. a, ?& r
  177. {" J/ [4 A: p+ O: T' x: s! O/ I
  178.    // Set up data structures for IDENTIFY command.* Q( R" j/ [- H. h6 ]* d
  179.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
    # C' r$ [% |2 ~
  180.    pSCIP->irDriveRegs.bFeaturesReg = 0;' I# H! ?" E2 ?) ], ~+ z
  181.    pSCIP->irDriveRegs.bSectorCountReg  = 1;# I* x; d+ l  `1 Q* r# E3 ]
  182.    pSCIP->irDriveRegs.bSectorNumberReg = 1;
    # U4 F3 x) D2 k: L: M- \, ^
  183.    pSCIP->irDriveRegs.bCylLowReg  = 0;8 C3 F3 R. i2 q
  184.    pSCIP->irDriveRegs.bCylHighReg = 0;
    ' ?% F$ L7 M' d# K8 |. [
  185. 7 |& Z7 r" A$ f* I4 B0 m) [
  186.    // Compute the drive number.(主盘和从盘所对应的值是不一样的)
    * W! {8 s6 I4 \) b# v% U8 ?
  187.    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
    6 ^( @! A6 {" |( W! v& ~5 k
  188. . }* T% k5 z5 b( o+ V# D
  189.    // The command can either be IDE identify or ATAPI identify.
    , q+ j+ U; W) y4 O, S& D( p6 }
  190.    pSCIP->irDriveRegs.bCommandReg = btIDCmd;: P% A1 a( H8 Q2 ]* P
  191.    pSCIP->bDriveNumber = btDriveNum;
    0 z4 ~6 p7 e  S, ^' ^7 X4 `: t1 x
  192.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
    ; H- k* e4 r& z7 r
  193. & P' ?3 C5 e' x% g
  194.    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
    " h3 V. k2 m$ p% P6 k
  195.           (LPVOID)pSCIP,
    % r  X8 N" C5 N8 H& N
  196.           sizeof(SENDCMDINPARAMS) - 1,8 D, j8 B: E! L1 S5 k% f7 y4 y9 I
  197.           (LPVOID)pSCOP,
    ' V! w! r( D$ ?, l* ^5 n
  198.           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
    3 P* \- _: q# Y, }- O" ?. N% [
  199.           pdwBytesReturned, NULL);  x7 [% s4 ~+ C# s9 t
  200. }/ o- {4 H; H3 Q# l  H/ P
  201. //---------------------------------------------------------------------------
    & S8 J9 I9 P/ t: K
  202. // Windows 95/98/ME 代码
    % c9 d  D3 u6 r6 x/ x
  203. //---------------------------------------------------------------------------
    / ]5 c5 P* f7 F8 q5 i  ^
  204. // ReadPhysicalDriveOnW9X0 V# [- X5 R# c
  205. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)/ a7 U. u2 ~! f6 p
  206. {
    0 [8 g! B* {6 z1 Y6 q' R4 I* L/ }
  207.    WORD wOutData[256];
    3 E' \9 C0 `" r" D2 C. D
  208.    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
    5 B: e4 o& @8 C

  209. ) U& X- E0 @- q+ C+ s) K& e
  210.    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。( j2 s) a7 K/ |
  211.    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
    % b9 s/ d( _9 r# o2 l( m* ]
  212.    // 避免蓝屏的出现。(期待高人能指出原因), y& s3 r  D7 ?8 q$ H
  213.    for(int nDrive = 0; nDrive < 8; nDrive++)5 R% {0 \1 |) G0 g7 E
  214.    {
    + G) S0 k7 Y4 e% Q" a
  215.        WORD dwBaseAddress;* A5 y# g5 S- r. R
  216.        BYTE btMasterSlave;         // Master Or Slave
    ( D. k' g" a( |$ Z
  217.        bool bIsIDEExist;
    0 G7 r  }3 Y, K
  218.        bool IsDiskExist;
      C. T7 _! k2 P% K
  219. $ K! g' G+ u* z5 R
  220.        switch(nDrive / 2)
    - T7 T/ W) n: S  p3 D
  221.        {+ Y7 L8 `' Y& u  s* ?* H/ t3 H
  222.            case 0: dwBaseAddress = 0x01F0; break;
    * o* |5 h; }. H6 Q5 ?' S1 Y, y
  223.            case 1: dwBaseAddress = 0x0170; break;! p/ ]+ e+ q1 _- K1 \3 N  j& ~
  224.            case 2: dwBaseAddress = 0x01E8; break;9 S! @! b! D, m  P* d% L
  225.            case 3: dwBaseAddress = 0x0168; break;
    : [! ~1 D9 a/ K' R* S; D
  226.        }
    ; b  X$ S# O  }7 H* ?
  227. ' A. i# L) t, ]" M$ B; C; Y
  228.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
    5 P2 X$ g; D* _
  229. # a! E- N, z# j9 i9 k- p; B
  230.        // 进入Ring0# L# U$ U. n+ ~% ^" v
  231.        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,5 {. F4 l3 c6 t6 Q9 A: A4 n! d$ A
  232.                bIsIDEExist, IsDiskExist, wOutData);
    . Z6 p6 P" I4 x7 x/ H. h
  233.    }2 |) _7 ^% h" N) p+ r

  234. / Z6 G8 N% g+ `5 n
  235.    // 开始读取3 ]- S4 _3 \1 u' g* |& c5 a) {  Q
  236.    for(int nDrive = 0; nDrive < 8; nDrive++)- ^! @, F% l( Z1 E
  237.    {" k% J! f5 B/ D% A6 C& w3 |
  238.        WORD dwBaseAddress;& S. P+ r/ m! L( r7 g6 ?: I
  239.        BYTE btMasterSlave;         // Master Or Slave; N# V# _2 z3 A6 x, X2 i& M
  240.        bool bIsIDEExist;
    . ?0 {4 H6 M0 C( D& e* i) Z
  241.        bool bIsDiskExist;. d2 O; Y( q; c+ v8 Q& ~; b2 }
  242.        switch(nDrive / 2)
    # `7 Z' Q' ?- ?* f
  243.        {- |+ X) C  B2 g2 d  T( W0 k
  244.            case 0: dwBaseAddress = 0x01F0; break;
    3 O! S$ O( `/ f# N2 o
  245.            case 1: dwBaseAddress = 0x0170; break;  u: O' H  G% i9 @$ `- Q  v6 Z7 \
  246.            case 2: dwBaseAddress = 0x01E8; break;
    : R; W; ?, A4 X" E' l8 b; A* D) {, o
  247.            case 3: dwBaseAddress = 0x0168; break;8 e. S. s4 ~) p
  248.        }: x& W1 Z) P: @8 z% P7 q( L9 D1 B
  249. " x1 Q9 S7 Z' K
  250.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
    * s/ U1 _7 ?% a8 E" X- m  i2 n2 P
  251. 0 J. L& h4 \: ^7 b' L
  252.        // 进入Ring0, i. U7 l9 G! u: z5 t! [' j. X% _8 v
  253.        bIsIDEExist  = false;
    2 B' t" e/ a6 t$ ^& J
  254.        bIsDiskExist = false;
    7 p, Z' C& B+ j" y( X) R
  255.        ZeroMemory(wOutData, sizeof(wOutData));0 r& C8 q: S% y. v. q
  256. 1 t2 H! _1 X& H  x2 d& c6 y6 z. _/ |/ R
  257.        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
    : S0 s" J  e! P8 k
  258.                bIsIDEExist, bIsDiskExist, wOutData);
    5 N; u3 L5 ]: d7 U+ N# `
  259. 0 b- v$ i( {' o+ X
  260.        if(bIsIDEExist && bIsDiskExist)8 p7 T# y& N5 \& f
  261.        {
    1 `/ h3 q" Z% p
  262.            DWORD dwDiskData[256];9 s+ [5 `! s! e
  263.            char  szSerialNumber[21];
    % h# Y1 @8 w1 c  u5 I) ]8 a3 ^
  264.            char  szModelNumber[41];
    $ y' ^2 O! a2 a) M/ g; \$ v
  265. 2 ]% t. u. ~9 ~, E- h
  266.            for(int k=0; k < 256; k++)+ W6 A5 K/ T7 g4 f0 `" L
  267.                dwDiskData[k] = wOutData[k];
    , x8 e, V9 E3 w' v0 E9 g3 v
  268. : o  c) x4 v5 @
  269.            // 取系列号' f# ]3 }& O( V; X2 F- K4 e, x
  270.            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
    : A; @- h& |3 n; W: m! i
  271.            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));+ O' M" f) N, `; Y# {6 R$ D8 f
  272. 4 _4 a/ ?% n' A3 r7 z3 u$ p
  273.            // 取模型号
    9 B/ t5 {0 P# C$ M& |
  274.            ZeroMemory(szModelNumber, sizeof(szModelNumber));) u. M) L1 e  Z# M2 K, Z
  275.            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));+ w$ B+ f' z9 Z/ v: E7 a1 n

  276. + z- s: i9 {; A2 Q$ u8 f1 ^4 |
  277.            pSerList->Add(szSerialNumber);# {/ v4 W' N& p" r% I/ o
  278.            pModeList->Add(szModelNumber);3 h' t- A" ?" r7 G3 E6 t% P
  279.        }  }$ y8 k* z0 O' c" w9 U  L
  280.    }* i3 I) g7 s1 c# G
  281.    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);& C) @8 [' {& p0 c; I* Z" K
  282. }' R' W6 I8 @! ^- B  E! P
  283. //---------------------------------------------------------------------------
    4 k$ A2 M( U# @" Z' ^/ b9 {
  284. // ReadPhysicalDriveOnW9X_Ring0()
      t1 E7 R* r% G0 X- o) I& O7 w2 c. P
  285. //5 @6 u0 t/ C. z5 W
  286. // dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h. g+ V6 h8 X, ?! _
  287. // btMasterSlave = Master(0xA0) Or Slave(0xB0)  z4 r# V  _7 @1 S
  288. //---------------------------------------------------------------------------
    $ a) |/ u) q9 Y. L# d; q+ u# N
  289. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
    + {% X& y8 X2 Y* I" W/ X$ I5 _  @
  290.        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
    ) _0 s% }3 `: o2 `( \  F8 G1 H
  291. {* G* s! W+ `. B/ v$ P
  292.    BYTE  btIDTR1[6];
      ?7 t% G8 d/ e, ^; F
  293.    DWORD dwOldExceptionHook;1 l$ N8 I, U, f' i( y) z
  294.    const int nHookExceptionNo = 5;
    & t2 t( P- O+ K% D

  295. ' M- x2 O# A+ O0 g7 L* y
  296.    BYTE  btIsIDEExist = 0;
    ' h8 ~: @, D' v* ]
  297.    BYTE  btIsDiskExist = 0;0 \6 D) m4 v2 X3 h0 g
  298.    WORD  wOutDataBuf[256];3 q! Z+ Z6 e9 H6 w( X
  299. 2 T( H: o0 }' E' y0 I" |9 C
  300.    BYTE  btIsFirst = (BYTE)bIsFirst;# f3 k; m: I! U1 {3 _' B/ y6 N4 R0 y

  301. & w) e2 b$ l. ~2 ^
  302.    const BYTE btBit00 = 0x01;- n% x, S$ u4 J! A6 p) N
  303.    // const BYTE btBit02 = 0x04;
    9 @' h( M! o& E. `. t2 L& I5 p
  304.    const BYTE btBit06 = 0x40;% C0 g4 t2 S$ M) p- b1 d  Y6 N
  305.    const BYTE btBit07 = 0x80;
    0 I: A, O9 E) p7 Y; B/ X+ \4 v9 [9 V
  306.    // const BYTE btERR  = btBit00;" {; ?  x2 n9 x, ]# }" e( u
  307.    const BYTE btBusy = btBit07;* N5 `' m+ x/ L7 f
  308.    const BYTE btAtaCmd   = 0xEC;: C4 `  [' x; {* e* X, ^; c
  309.    const BYTE btAtapiCmd = 0xA1;
    " E, j1 j6 @4 o& m! G! Q3 j

  310. 7 r6 E  l% d( }7 @& }0 n
  311.    __asm, U! V3 p5 @  @# O
  312.    {' R2 F6 M9 C8 z
  313.        // 必须先执行这条语句
    4 D# _- m) d5 n: e9 a
  314.        JMP EnterRing0
    1 z; K$ D; Y8 C5 B3 X8 y

  315. 6 b: s; W+ T" O. e" J  `
  316.        // 定义过程+ C/ p. E4 F) \2 s; Q5 f- J
  317.        // 等待IDE设备直到其不为忙为止) x3 j! \$ O3 G+ t
  318.        WaitWhileBusy proc
    & G2 F' j! K! l7 T& d

  319. / x- U: g  {9 X! g* V
  320.        MOV  EBX, 100000
    ( ]0 s; Q5 A/ T* @1 J2 H
  321.        MOV  DX, dwBaseAddress' H8 ~4 ^, l5 ?# u8 N+ ?5 R) A' U
  322.        ADD  DX, 7
    6 [1 S2 C  V: ?! b5 C" T5 F

  323. + X, b8 `9 e2 l
  324.        LoopWhileBusy:% J2 [/ V/ T* N" B
  325. ) [; a1 [7 n9 @( N- F- o
  326.        DEC  EBX
    " k4 _: v1 ?2 }4 t
  327.        CMP  EBX, 0
    2 j  [) ~1 x; S" @
  328.        JZ   Timeout
    3 E7 Z0 F5 S9 t, b- o
  329.        in   AL, DX$ U" y$ t; _2 N) Q
  330.        TEST AL, btBusy) S+ t3 G7 ]* k/ r9 j- b  L
  331.        JNZ  LoopWhileBusy
    ) ^8 M) P  ^6 k+ C
  332.        JMP  DriveReady8 U6 I. q" O4 g7 |8 Y. G
  333. 2 W/ [9 }2 e) G( U
  334.        // 超时,直接退出
      _+ X9 H1 n4 N+ i% B6 R4 j8 H4 i
  335.        Timeout:
    & A( F3 F) P7 S
  336.        JMP  LeaveRing0
    " e$ v% _" X0 E
  337.        DriveReady:
    2 }. k( t" C4 e$ s' c
  338.        RET" ?! j9 q3 |8 z; e
  339.        ENDP   // End of WaitWhileBusy Procedure+ i) W- O8 @* C6 Y& K& Z: j1 ^

  340. . J: g" Q4 M0 w+ e8 a9 h2 X
  341.        // 设置主盘和从盘标志' T6 d+ D+ ^" u6 y8 k
  342.        SelectDevice proc1 F* c# ]' P' V1 h" `3 ]
  343. ! n+ ^4 A* n/ V6 h# g3 z- ]5 r% d
  344.        MOV  DX, dwBaseAddress% a% s6 e! u  [1 P; N% `& n( o5 k
  345.        ADD  DX, 6, s5 ?& J( L1 I0 D  p6 F9 m
  346.        MOV  AL, btMasterSlave
    # R) d- s3 E0 m: G
  347. 6 V8 q9 m5 R! G7 u$ C  l
  348.        out  DX, AL& p9 @" p" e1 ~
  349.        RET
    ( V; p( k3 L4 j9 B; w) q& ]
  350. $ P% \, X$ d. Z6 O# A( @! Y
  351.        ENDP  // End of SelectDevice Procedure
    1 V6 `$ S6 ?& z) G0 @# v  u

  352. ) k/ Y$ R8 r% |4 K, W
  353.        // 向IDE设备发送存取指令8 g1 a9 U/ M! s
  354.        SendCmd proc
    0 m( Y; ?6 n5 C* `' F: N* r
  355. ! L% H& \' L; D$ U& g) o
  356.        MOV DX, dwBaseAddress
    # H- C" z4 P/ w* R9 ^* t
  357.        ADD DX, 7
    0 x* d/ v1 k- o& Z- ~
  358.        MOV AL, BL // BL是主从盘标识,在过程外设置
    1 d  q) I# U0 \& i8 z  V9 C0 o
  359.        out DX, AL/ o9 J2 j  a1 j( D* G" Y6 F
  360.        RET
    , E# c9 A3 `0 y( }, b7 n1 w3 }+ g
  361.        ENDP  // End of SendCmd Procedure
    ; C# @1 S% W3 @2 U& ?
  362. + ^( M0 J! X! a+ C* P/ u  C
  363.        // Ring0代码" Y; S7 k2 E- A! `
  364.        Ring0Proc:0 u% ]' D$ z  q7 f* h% v# f
  365.        PUSHAD
    , M0 g, O, R- z2 y
  366.        // 查询IDE设备是否存在
    ( J& e+ ^; T5 s! D0 a) n3 z
  367.        MOV DX, dwBaseAddress
    ; `1 S5 I4 K  m) a
  368.        ADD DX, 7  h5 l( L% W, r5 h6 y' g+ `
  369.        in  AL,DX8 E; ^" t9 m" M: I  h. c. }
  370. # Y. p; B) H3 I9 }' m0 ]7 f, F
  371.        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回$ S1 y# G, m9 c7 [
  372.        CMP AL,0xFF
    0 _- V3 L0 p4 n9 M
  373.        JZ  LeaveRing0
    2 b2 A2 \* S# X9 J- Y! J
  374.        CMP AL, 0x7F
    % j8 e* K/ Z' \) B
  375.        JZ  LeaveRing02 l/ ~5 n3 x- O0 g

  376. ( u3 _7 x- S. j  Y- a7 }& `
  377.        // 设置IDE设备存在标志# d& I6 k$ w( J( G/ Z- R
  378.        MOV btIsIDEExist, 1
    + D4 n9 e3 \1 z0 @8 N" `

  379. 5 p1 D2 Y$ ?' K# O8 g, }
  380.        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
    ( T$ I/ i" Z# O* w. P
  381.        CALL WaitWhileBusy
    8 ?$ p- p0 {& l; {+ W( i+ G
  382.        CALL SelectDevice/ |! m: \) e) F( ~

  383. + S2 p- O9 X# o3 \
  384.        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
    $ }% L% a$ c# B- B) d$ `/ f
  385.        CMP  btIsFirst, 1
    , _' K+ \0 F. U- _8 p5 }
  386.        JZ   LeaveRing0
    8 r6 N4 _9 `- h

  387. ) o4 F1 |3 D7 O/ j" C
  388.        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???5 d. c* C, J5 S% {* }
  389.        CALL WaitWhileBusy
    " H! P- j' Q- E- Q  ?
  390. 2 B. s; b5 g; E5 _4 y/ a" r
  391.        // AL的值等于cBit06时,不存在驱动器,直接返回
    $ M. b# D8 @' v
  392.        TEST AL, btBit060 L& c! ^, f5 P- ?' [2 [9 J- x
  393.        JZ   LeaveRing0" C( E7 c4 U9 S5 Z, [  [) u" E2 m
  394. ; N" ~' Y( ]( N: X4 v/ B+ y
  395.        // 设置驱动器存在标志
    , ~7 _, y% m' k6 o! H. ~
  396.        MOV  btIsDiskExist, 1
    " C0 X, I+ u! k8 P3 g; J2 t
  397. 9 f7 U# l7 |# n2 @3 J
  398.        // 发送存取端口命令9 c& H4 q! t; m
  399.        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
    3 A1 {% Q" f& @& y' W! d
  400.        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令5 X$ H( n7 a4 k0 b
  401.        CALL WaitWhileBusy
    ( [/ w6 @# W4 u! c) {& l
  402.        CALL SelectDevice    // 设置主从盘标识6 N# z3 k$ i/ }' c  |/ T
  403.        MOV  BL, btAtaCmd      // 发送读取命令% `3 a( b0 m7 H
  404.        CALL SendCmd: ]+ g! z" L1 y
  405.        CALL WaitWhileBusy8 M. j# o* ~, z0 ?8 D; l4 b: P

  406. $ r. W. V# R) z5 Z; f" ]6 W6 s
  407.        // 检查是否出错( W4 |: D  W0 L( @, B% H/ i
  408.        MOV  DX, dwBaseAddress
    - X5 w0 x5 }: R# D! s
  409.        ADD  DX, 7
    2 s, R7 Z" q* g: |

  410. 4 J' j, T8 n# P% T, j: k
  411.        in   AL, DX9 G& x3 q2 I! q: K6 ?

  412. , Z, C! W8 ~; V
  413.        TEST AL, btBit00' ?4 C# w* @* @3 z8 \7 h% ^
  414.        JZ   RetrieveInfo   // 没有错误时则读数据2 d1 r2 i* A( G3 w# c

  415. , t4 b$ o( v- g1 Z, D9 q$ [7 N/ p" u
  416.        // 如果出错,则进一步尝试使用ATAPI设备命令; q$ z( L8 Z* h& v# ?* t
  417.        CALL WaitWhileBusy, O8 R$ E$ K1 ?' F* h# Y6 z
  418.        CALL SelectDevice
    1 Y- x! p5 C# j9 t  s
  419.        MOV  BL, btAtapiCmd
    3 Q7 n/ V9 p* D  n. v* U
  420.        CALL SendCmd  |, A9 R( E7 A5 f( K
  421.        CALL WaitWhileBusy
    - k2 f2 a) p( p' X
  422. 6 o- |+ B( Q0 {: X" U
  423.        // 检查是否还出错, W% W( E( G: ?: y
  424.        MOV  DX, dwBaseAddress
    ' N) z$ b& m) n/ I$ v- Y
  425.        ADD  DX, 7
    1 l3 t0 U* X! Y8 F9 v- A5 G
  426.        in   AL, DX
    # n; p1 K& k5 Z8 g
  427.        TEST AL, btBit002 m0 e, Y! j) g0 h* Q
  428.        JZ   RetrieveInfo   // 没有错误时则读数据
    % p8 f* f5 H/ r8 F2 L5 V! p, V( c' t
  429.        JMP  LeaveRing0     // 如果还是出错,直接返回
    # u& |' ^# a$ B) i6 r) K
  430. ) L! S4 q: P- r) s
  431.        // 读取数据
    7 M; p! N* w3 F7 Q' E
  432.        RetrieveInfo:- v. y# w5 F5 d1 z& i, Q, G! M3 z- z

  433. 5 m$ |8 ~. [8 ]& ^( m3 P
  434.        LEA  EDI, wOutDataBuf
    ( Y$ l2 r0 C! V# P! _
  435.        MOV  ECX, 2568 w1 T0 l1 S* p, k" P
  436.        MOV  DX, dwBaseAddress
    % o0 i$ h2 y2 J, k6 P
  437.        CLD2 i* u. j( W. s( {. C! h* _) a7 h4 L* k
  438. 0 m. D& T0 l- p1 H
  439.        REP  INSW5 o0 N* z, G4 L% M$ D
  440. & I* r( \$ J- x6 ^9 W
  441.        // 退出Ring0代码# O) p9 \9 \) k) ^/ y/ D; m
  442.        LeaveRing0:5 D. c2 W8 S, f+ G& t2 ~

  443. 2 K* I4 J& {# ~7 M/ \5 Q
  444.        POPAD/ ~/ m3 x- I  _. E0 }$ V
  445.        IRETD
    ! v0 S1 _( m! `7 W4 ?. `( H

  446. , x' F3 Y" @  d; `2 g( \
  447.        // 激活Ring0代码
    & E( b* e' T- s4 S6 F3 m7 x
  448.        EnterRing0:
    % R9 |) ^5 u) v  U
  449. * ?( ~! F6 o) @% J
  450.        // 修改中断门
    ) B* T% d8 j1 k
  451.        SIDT FWORD PTR btIDTR1
    * N2 P6 S( M- Q3 j4 [  Y0 Q( b. ^
  452.        MOV EAX, DWORD PTR btIDTR1 + 02h0 ~# k7 x& |. i5 g2 p* L7 q
  453.        ADD EAX, nHookExceptionNo * 08h + 04h
    : ?" a  N  g5 m) f2 T2 o, d. M
  454.        CLI& \2 v6 u. J. ^( j
  455. # I& F9 x4 L: ~- l6 M5 X
  456.        // 保存原异常处理例程入口- ?& m1 z5 ~+ }3 \6 x5 n1 [6 X8 V4 ]
  457.        MOV ECX, DWORD PTR [EAX]; E. ], `% O5 V% _
  458.        MOV CX, WORD PTR [EAX-04h]
    : }6 ]* v9 g/ v* }2 O* ^+ ~5 Z
  459.        MOV dwOldExceptionHook, ECX. D) ?" X3 f$ ^6 f$ X

  460. & r- W0 h9 I  N4 e3 U% w
  461.        // 指定新入口) y+ ?3 v& b; G5 U' u
  462.        LEA EBX, Ring0Proc
    " s( _0 R- p! K
  463.        MOV WORD PTR [EAX-04h],BX
    8 L' M: w6 G( m
  464.        SHR EBX, 10h2 f: a0 q$ ], O' j% t, M
  465.        MOV WORD PTR[EAX+02h], BX3 |8 Q/ s/ A& q- B
  466. ! {" H" U3 F8 I! T
  467.        // 激活Ring0代码
    - b! T6 `% u7 j+ G
  468.        INT nHookExceptionNo
    : p, f, ]7 j1 m% ^* v9 m
  469. $ B2 {. c0 G" {% Z0 J& ~  P
  470.        // 复原入口- X/ [3 z  Z* c0 l) N- a
  471.        MOV ECX,dwOldExceptionHook
    / g0 {! Y+ W/ t, y  y
  472.        MOV WORD PTR[EAX-04h], CX
    1 V' q9 L' Y& S$ y; J
  473.        SHR ECX,10h
    5 }* H, \* J3 n) R, c! |
  474.        MOV WORD PTR[EAX+02h], CX
    & n- O4 x* ]5 W! @+ [
  475.        STI, }) Q# w/ Q  X+ r* I
  476.    }( S3 R3 A+ }+ U
  477.    if(!bIsFirst)) W! N- d/ B8 L3 z- O4 i; {
  478.    {& L! b& V+ Y2 @9 `0 n' T2 e) |
  479.        bIsIDEExist  = (bool)btIsIDEExist;" I+ J( ^- Y6 Q5 M" Y7 ?' X. f/ t
  480.        bIsDiskExist = (bool)btIsDiskExist;
    # y* r! E2 L9 n$ i
  481.        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));+ t$ F- g8 T( o& A, N
  482.    }7 A0 `) _5 |( M; s* |  o$ s2 U3 t
  483. }
    ( L* d6 c3 |/ L& G6 b1 `; x
  484. //---------------------------------------------------------------------------) _/ C5 W" u) b& {, Y9 ^
  485. // 调用方法:5 q: ]* M0 H4 I9 j3 A: ~- z
  486. void __fastcall TForm1::Button1Click(TObject *Sender)  X+ N- h1 @$ s, Q- G' b
  487. {
    & M" }, H9 E" i# f) p
  488.    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
      V$ M6 B# @& ~/ ?
  489. }
复制代码
发表于 2005-8-15 01:00:45 | 显示全部楼层
晕乎乎。。。怎么看8 洞阿
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-8-14 01:04 , Processed in 0.021134 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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