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

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

[复制链接]
发表于 2005-8-11 11:42:04 | 显示全部楼层 |阅读模式
  1. #include <WinIOCtl.h>
    0 n: F. h+ l% B
  2. #include <stdio.h>
    / s- }7 F6 ]% O. Z" }; y
  3. & |  V+ o  i! I, H; o( u% C& p
  4. #pragma inline
    - N) E8 P9 j4 j( ?9 ?9 ?8 ?
  5. //---------------------------------------------------------------------------. r5 d) U) \( x
  6. // IDE NT/2000/XP专用变量
      x( B% R6 _7 ~% S" s8 p
  7. #define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
    4 ^0 V* y- K9 D# \1 V3 V( k! C
  8. #define DFP_GET_VERSION         SMART_GET_VERSION
    2 s( i5 b' \- G3 J3 m) W! p/ Q! B2 i
  9. #define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND- h: C" M7 a) M8 }& h! N* q4 h
  10. #define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
    " K# A+ Q1 {7 u6 O' n, W

  11. * Y7 y2 _' l( m1 [) ~: R& a/ b" t
  12. const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令
    ! B( c) Y. _) }, I; U
  13. const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令% }# W( Y1 V- `- ]$ X" B/ o( K1 K' j) U

  14. : n: }3 q: S9 l
  15. const int MAX_IDE_DRIVES = 4;( I# m9 q. n& X1 L4 F
  16. 7 l9 J8 l/ n3 L3 [! |
  17. // SCSI专用变量
    ( i3 _2 T% x9 s2 P: v6 E
  18. const DWORD FILE_DEVICE_SCSI             = 0x0000001B;; M/ Q3 ]$ b3 p+ V7 ?
  19. const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);! M; V/ X# Q: e
  20. const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition( z5 {6 G5 x$ b7 \
  21. const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
    4 c1 i/ B" d; ^& p; e

  22. ! X9 n$ J9 r$ v# S) X4 ]
  23. typedef struct _SRB_IO_CONTROL
    4 @- Z9 ?8 q4 D+ @( K6 G. F
  24. {
    + ^$ s6 ]; I5 R* f: `8 W8 S
  25.    ULONG HeaderLength;$ Y* Y) y, p" t" j1 F+ S3 U* j
  26.    UCHAR Signature[8];; L3 E/ W/ z% Z/ X
  27.    ULONG Timeout;( p0 K9 w3 M4 \. K( S
  28.    ULONG ControlCode;
    1 u9 y' ?# B9 @3 ]
  29.    ULONG ReturnCode;
    + _2 U- J! T" G; q
  30.    ULONG Length;; W0 C0 M- \, L, T  F7 C
  31. }SRB_IO_CONTROL, *PSRB_IO_CONTROL;
    3 b8 O% U; Z, x1 q+ q* G' R3 w
  32. # l0 z; E5 T: K
  33. // 读取的主函数5 P1 q4 _' [. |2 ^& n2 S  ~
  34. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
    5 [1 }: v9 k3 M

  35. , b! a- x- t+ p5 Y, b
  36. // 辅助函数; u) K8 p5 Q; A; Z0 t, f! f
  37. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);( Q+ a, p0 r. n7 R+ D- O
  38. // NT/2000/XP函数/ l# K2 k6 {. y
  39. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
    - c" K/ g$ k5 _% r
  40. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
    9 o. `% V) a9 v2 r& f. c
  41.        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,' p# T8 L- A1 S, u( ]* G2 S& R" U
  42.        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
    % S& P0 U$ _& f
  43. // Windows 9X函数
    3 K- x  \4 v7 t8 U" L0 Q
  44. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);6 f+ t9 _" _5 a8 g% Z  t' b
  45. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,) S$ t# C  q, m  i
  46.        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);& W: L: L7 Q$ G9 M4 y0 W+ @6 G: `' X
  47. 2 P9 Z# o5 J7 E1 x9 c8 X
  48. // SCSI读取函数(for NT/2000/XP)
    3 F* [2 Y% m% e! |
  49. String __fastcall ReadIDEDriveAsScsiDriveOnNT();9 @' ^3 h/ S5 N. t' |; j
  50. //---------------------------------------------------------------------------( i) c/ ~2 }' r/ \* ?
  51. // ReadPhysicalDrive
    & _) N5 I9 a4 n4 h1 F6 M
  52. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList): }5 i* q' Q) Z  ?3 e& u/ Y% J1 v
  53. {1 h! t( Q5 ^7 }8 Q
  54.    switch(Win32Platform)# V6 W9 r& J/ e& @& d
  55.    {
    3 p7 Y3 D' V+ ]) K
  56.        case VER_PLATFORM_WIN32_WINDOWS:) w0 q6 K" D( N" _
  57.            ReadPhysicalDriveOnW9X(pSerList, pModeList);
    9 V1 o' _% B& c! G9 l
  58.            break;
    - ^: Y0 L  l4 O5 Y5 E
  59.        case VER_PLATFORM_WIN32_NT:
    - V: v' }9 A6 |- i, y' j) }0 @2 h
  60.            ReadPhysicalDriveOnNT(pSerList, pModeList);8 B6 I) k( B& ^( @/ S" i
  61.            break;
    / v7 F% H& k3 ]$ y; P) _
  62.        default:, B& u! ^& J# t' ]+ b
  63.            break;
    . W9 C4 F3 z9 [* G. ]5 b+ n
  64.    }* |! _2 d/ T: @. i4 ~* ]9 `5 A
  65. }  l( C! i1 E) g1 X& o
  66. //---------------------------------------------------------------------------
    % o* P2 z- a  h9 O: ?
  67. // ConvertToString
    8 l) n% G, m& g  r1 ^; Q
  68. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)/ B4 c! H6 N, I
  69. {
      I; E3 Z; A, l% V" i
  70.    static char szResBuf[1024];& G0 k9 f; U6 w' K! m  f
  71.    int nIndex = 0;) J- t; l% M& Z1 Y$ {9 E' J
  72.    int nPosition = 0;
    % G( h! @+ y' d9 U/ H$ z5 z
  73. $ }6 a) C& Y) p0 ?
  74.    // Each integer has two characters stored in it backwards
    ' k3 s! g# C- u
  75.    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)' q. Q9 ^: [0 n* p, I
  76.    {
    2 }2 Y3 d% A0 p
  77.        // Get high BYTE for 1st character/ t* s, s8 b3 E' q; a6 Z% g
  78.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
    4 p! ?, |" r- }  {! s. T
  79.        nPosition++;
    - _+ w# |5 z+ m" e

  80. 0 Q0 q) Q* ]7 n- s
  81.        // Get low BYTE for 2nd character9 B' i/ n# [( E4 p) L( }
  82.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);" T' I- \! J& ~1 _1 t" _
  83.        nPosition++;+ g2 ]# \+ r' |" H8 u4 L3 q1 S8 J
  84.    }
    ' `( a$ A! h8 e
  85. 6 k0 y5 Y+ I. S$ _" \4 a0 R
  86.    // End the string
    / M( c: L$ N- i6 G% Z7 C
  87.    szResBuf[nPosition] = '\0';
    & j; Q- z' l  `* M' s- J2 g( O

  88. 6 Y* V9 a5 e& T4 u
  89.    // Cut off the trailing blanks
    # {3 b1 ]& l1 o) H" R6 `8 Q, E
  90.    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
    : B/ V6 P  C# K" s% l
  91.        szResBuf[nIndex] = '\0';
    . d/ i& `0 ^  W: j8 G; E; _
  92. . ~5 L0 k7 q! z/ B7 a% }% \
  93.    return szResBuf;" c7 _. j3 P2 }7 O
  94. }
    3 U' R0 n, |; Q, e
  95. //---------------------------------------------------------------------------
    6 {) F5 `# D) S& o2 Z( g" H% C
  96. // Winndows NT4/2000/XP 代码
    ( j7 S0 Q, f% f* o4 K9 l
  97. //---------------------------------------------------------------------------
    * p! S  c4 u8 e" {. C
  98. // ReadPhysicalDriveOnNT5 [: \" [; X1 A# V
  99. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
      c. i& P& m/ f8 \& G' h6 t
  100. {
    1 N. p5 Q# @# Z* U
  101.    // 输出参数
    + z' P2 n  q0 j% X% d5 \: I% ]
  102.    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
    8 R7 w5 ?" B) [# E

  103. , q, x0 j( r* S
  104.    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
    # T* n+ W( S* f- g' Z6 p: k
  105.    {' M* `; ^2 ^8 c* L) [& x
  106.        HANDLE hPhysicalDriveIOCTL;' {0 [* z- \1 i4 S7 I
  107.        char szDriveName[32];
    7 G6 \2 r7 }6 i7 Z2 a9 P
  108. 7 U  r1 ^7 o3 D2 f
  109.        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
    1 ]4 a% ]" y' B5 W1 N5 Y2 S* @7 d
  110.        hPhysicalDriveIOCTL = CreateFile(szDriveName,
    + g' I% h  D: f) w, X( W
  111.                        GENERIC_READ | GENERIC_WRITE,
    2 s7 u8 I3 y& F& ?$ x4 t
  112.                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,+ P: `: S% B$ ~
  113.                        OPEN_EXISTING, 0, NULL);* G4 e1 ?, q. N3 L
  114. : ]) A% y/ M1 q+ h9 l9 ~7 Y3 j) C
  115.        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
    $ m- y9 z' b# U; w' V
  116.        {
    / C# M# |( Z6 X! [2 h' ^5 P
  117.            DWORD dwBytesReturned = 0;
    ; F2 y* L* n5 P7 j  o8 h
  118.            GETVERSIONOUTPARAMS gvopVersionParams;# y% d/ @0 p, _8 m  M3 U
  119. 6 E- S& ^9 A# O- e4 U
  120.            // Get the version, etc of PhysicalDrive IOCTL& y8 D! {4 ~3 u- L& t
  121.            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
    ( ^- t, t& }) \6 B

  122. 8 W7 {* Y- Q2 ^) H$ p
  123.            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,, p" ]1 X$ R0 E( r) Y5 m
  124.                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),. _: ?* @! b0 F/ I
  125.                    &dwBytesReturned, NULL))
    / X4 z8 [8 w- N/ y6 t
  126.            {' ~) S$ B7 ^2 B) y' l
  127.                continue;
    2 b! P2 Q& s, o8 y" }) {; E
  128.            }( C. ?; ^$ `* w' I

  129. 5 R" w3 E: H* [; P
  130.            if(gvopVersionParams.bIDEDeviceMap > 0)' V: x4 b$ W3 r9 t) z
  131.            {
    ! K6 V3 n) j/ o( V
  132.                // IDE or ATAPI IDENTIFY cmd& }& x9 j' p5 o4 r- I" S- o
  133.                BYTE btIDCmd = 0;
    6 y! T: N* V- R1 }8 w) {' U# `
  134.                SENDCMDINPARAMS InParams;
    " x% B# D& y9 c5 a5 h
  135.                // Now, get the ID sector for all IDE devices in the system.
    - h2 l7 T. |9 Y. @0 Y0 G
  136.                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command," s- I8 K8 ?0 {" Q
  137.                // otherwise use the IDE_ATA_IDENTIFY command
    6 O3 L1 I6 Y4 c5 G) W8 a
  138.                // 具体所得结果请参考头文件中的说明3 o$ _4 j4 U0 J
  139.                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?/ j4 l# n5 W8 u7 l; _; }, Z% R
  140.                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;7 q1 Y4 S0 }4 i" b, j
  141.                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));) u9 P2 f: }8 w; d* P3 R
  142.                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));5 q% P* V4 u2 l# a% f
  143. 7 Z8 _  k# o- {
  144.                if(DoIdentify(hPhysicalDriveIOCTL,
    - F0 e" C! d+ k0 S
  145.                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
    ! }6 P( o7 p' b; v! C- i# F  J
  146.                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))# t* _1 T+ `2 N' G/ x
  147.                {
    7 f4 J* d9 {: r1 h9 ?$ ?5 R4 e
  148.                    DWORD dwDiskData[256];
    & S$ y" h. [3 d" G: |
  149.                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件. n5 v, X1 {3 b: L+ `
  150.                    char szSerialNumber[21];
    4 `1 N3 ^8 {$ |
  151.                    char szModelNumber[41];
    3 t, s" A( c1 @: G6 S
  152. + h9 }% @) e- h+ E. _
  153.                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
    ! b" x; O$ v0 d6 U# J! Y  [
  154.                    for(int i=0; i < 256; i++)* S# [: |, C* `' h
  155.                        dwDiskData = pIDSector;
    - C0 u! C3 S3 @0 e" m
  156.                    // 取系列号
    , p1 k0 B0 j0 _; B; `2 O; S- L4 R) I# h
  157.                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
    1 S# v* ~# d5 t5 Y
  158.                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));3 s( O5 D8 b) ~$ ~& }0 I
  159. 8 n5 R7 |4 S! J- k
  160.                    // 取模型号' j' @; {+ p. s) m$ |
  161.                    ZeroMemory(szModelNumber, sizeof(szModelNumber));0 r8 L$ P- {( l2 }
  162.                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));. l* Z1 n& L' Z. N  @) k9 w2 c
  163. 6 u8 g7 E3 @$ D6 ?; l4 b* O( }* u
  164.                    pSerList->Add(szSerialNumber);$ F/ {5 |: W) q4 X  t: ?% {
  165.                    pModeList->Add(szModelNumber);
    8 x3 t" @0 U0 B$ a3 q- Q  i, d) B
  166.                }
    % ?+ s0 ]/ S+ w3 a9 o5 u
  167.            }
    % U; s8 Z% r5 f& F
  168.            CloseHandle (hPhysicalDriveIOCTL);
      z; S1 u- s5 |3 c
  169.        }2 b; @3 f  E9 i3 y! `% H3 Y
  170.    }' \4 m3 D$ a9 g0 \0 o5 Y3 [7 q
  171. }
    ; T! P% C! F$ R2 x& x  R! S9 {, z" j: V
  172. //---------------------------------------------------------------------------: t2 T$ Y, H/ e1 Y: H+ D* A
  173. // DoIdentify
    $ D; n- P3 x3 W  V8 K9 C
  174. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,: `6 _' o) C) Z7 p- c8 a* B
  175.              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
    $ P/ _; j1 r- l! ^
  176.              PDWORD pdwBytesReturned)
    , N/ y6 B" _9 d
  177. {  ?- q" P7 i' S2 @
  178.    // Set up data structures for IDENTIFY command.' f1 j- d( v4 Y% ~$ u. _( V: z& ?* A
  179.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
    " u/ M- K( m* p1 r$ Q* H2 e0 t
  180.    pSCIP->irDriveRegs.bFeaturesReg = 0;2 R4 Y& B2 w; U( o2 p* E  d# |" o
  181.    pSCIP->irDriveRegs.bSectorCountReg  = 1;
    " r: X7 C+ t; ?$ Z6 V8 l/ S% c
  182.    pSCIP->irDriveRegs.bSectorNumberReg = 1;8 f$ E; H+ y. S+ {% }' K. Z% F
  183.    pSCIP->irDriveRegs.bCylLowReg  = 0;' ~, Q* y$ g  u
  184.    pSCIP->irDriveRegs.bCylHighReg = 0;3 Q% T0 o/ q) d1 }0 n0 y

  185. 9 R3 v/ T5 b0 C
  186.    // Compute the drive number.(主盘和从盘所对应的值是不一样的)
    . o7 M5 t2 C  }, a: n
  187.    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;8 Y% m% D. e+ {+ ~8 X2 _: Q
  188. # S; I1 ]+ t: E1 s0 ]! ^
  189.    // The command can either be IDE identify or ATAPI identify.! s% E, R8 r# w: U7 ^) z0 X6 S
  190.    pSCIP->irDriveRegs.bCommandReg = btIDCmd;
    ) h8 o$ X. E3 y
  191.    pSCIP->bDriveNumber = btDriveNum;2 @" X) t, Z5 f% {8 F- B/ E% ~
  192.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
    ; D- C& }9 x' v
  193. : ^8 E$ B: m2 ]- L
  194.    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
    5 X' Y' M  w. L! h9 X1 G% ~
  195.           (LPVOID)pSCIP,/ J+ m& |: Z# L3 B. v) D
  196.           sizeof(SENDCMDINPARAMS) - 1,
    " Z8 a% V! |  G+ h- f
  197.           (LPVOID)pSCOP,
    * g: ]2 _/ B$ ^% j% K: h6 x0 X: I
  198.           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
    5 X- y+ Q1 I1 Z1 q
  199.           pdwBytesReturned, NULL);5 g3 H) M- P& ?6 r) I9 }
  200. }% L5 r& _4 D! i- F; S
  201. //---------------------------------------------------------------------------9 V9 U+ a. \+ A9 k8 H9 {
  202. // Windows 95/98/ME 代码* a* M/ p" _7 m5 c; [
  203. //---------------------------------------------------------------------------4 a  I% O6 p7 _( n; q
  204. // ReadPhysicalDriveOnW9X3 }' }9 a7 y7 |8 w! X' }
  205. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)7 `' D) B, x1 }7 x# O1 d- D+ Z
  206. {
    % s/ j0 j* S- s" l3 V6 m% _3 a
  207.    WORD wOutData[256];
    8 X4 @# f5 s, S; D1 |  w
  208.    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);) \9 `6 f& X. r/ q9 m
  209. : ^4 F7 z* X$ q, \: {
  210.    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。+ `/ z6 W' b' G; U3 U: t8 ^2 G. S
  211.    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
    7 w/ @- `) z' z, n! c# @
  212.    // 避免蓝屏的出现。(期待高人能指出原因)1 B( L6 j: z8 R" K- @; \+ D/ D/ p
  213.    for(int nDrive = 0; nDrive < 8; nDrive++)8 h% J* b9 z7 H; o2 _: |
  214.    {
    - W" E& O5 H! B5 T# A: a- r' u. r
  215.        WORD dwBaseAddress;; ?+ q! U9 O! y" Z/ ^( |
  216.        BYTE btMasterSlave;         // Master Or Slave  S6 b+ y# h* Y4 ?, q) X2 z+ |* f
  217.        bool bIsIDEExist;* @2 [$ S0 U5 U
  218.        bool IsDiskExist;. G: s5 G  g! R6 \  F
  219. ) m3 v5 |+ j) w3 U9 O4 o# f) B  ]
  220.        switch(nDrive / 2)( S5 |& z4 {8 h5 K; C
  221.        {" @8 V, K/ H7 M; |
  222.            case 0: dwBaseAddress = 0x01F0; break;
    : k3 G- B7 A7 L; b3 W8 e: }+ {* P
  223.            case 1: dwBaseAddress = 0x0170; break;
      m6 q& o0 w7 `
  224.            case 2: dwBaseAddress = 0x01E8; break;
    1 H' D( b) j# ]5 S
  225.            case 3: dwBaseAddress = 0x0168; break;
    - R$ G) h4 {* C6 Y, ]7 a6 K- w. K
  226.        }5 \- a% s$ v& a/ \8 b! {
  227. ! B' p7 l6 ]9 N4 T  a$ n: a* f
  228.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
    2 x% D( O+ N! J+ @" U4 c

  229. ! K# ~4 z1 J& v
  230.        // 进入Ring0
    % q) n+ Y: {7 q9 Y. i
  231.        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,2 m3 x3 |0 ^% f0 A, ]. _) k: P
  232.                bIsIDEExist, IsDiskExist, wOutData);" [1 e- ^6 V- p
  233.    }- a. \! m: j2 L0 e; O  S5 n
  234. " V- V0 @0 {, d8 Y
  235.    // 开始读取
    ( |/ N; N3 T3 @+ K2 t
  236.    for(int nDrive = 0; nDrive < 8; nDrive++), Q; G, c. i3 M- z
  237.    {. J7 h3 T( a8 @
  238.        WORD dwBaseAddress;
    6 q0 D2 @9 M* ?" W- }
  239.        BYTE btMasterSlave;         // Master Or Slave+ ]( r3 t, q" T* U
  240.        bool bIsIDEExist;
    " y1 x, H$ m/ n2 w% s; @4 l( t
  241.        bool bIsDiskExist;0 S' B6 x$ ]9 P5 c' Q; k7 D% T
  242.        switch(nDrive / 2)
    9 R6 X' O  ~2 n' _
  243.        {; k8 g7 F9 L! k: Q: F$ t7 \% q
  244.            case 0: dwBaseAddress = 0x01F0; break;
    ; C6 j/ A0 t) N: `* a
  245.            case 1: dwBaseAddress = 0x0170; break;8 W6 S& b3 m3 z% [& l9 [
  246.            case 2: dwBaseAddress = 0x01E8; break;# x2 ~( l9 |9 v9 h; M
  247.            case 3: dwBaseAddress = 0x0168; break;! D3 M% P$ e3 o! f
  248.        }9 x- Q% O5 \2 V4 I3 R9 Y3 {) h7 X

  249. 4 j$ E4 |$ S2 [. ?0 O6 ]* u" \2 w5 n
  250.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);. s1 x( P. V2 Q. |; s
  251. 4 w! l" e" r2 g3 ?
  252.        // 进入Ring0
    . R# E2 e, w; Z8 M2 g6 y. L
  253.        bIsIDEExist  = false;
    ( R( J5 t8 Z3 D; ]* D4 U
  254.        bIsDiskExist = false;8 h' ~2 z# I3 O6 j$ j0 |7 t
  255.        ZeroMemory(wOutData, sizeof(wOutData));
    / z6 I4 x: B, h6 D# t* s6 C3 R0 ?

  256. % \8 t: t4 B: T, p' w: O. G2 R, z
  257.        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,% p1 H$ R: ]4 |! f: Z
  258.                bIsIDEExist, bIsDiskExist, wOutData);& h1 B  Z/ w! h$ P$ Z

  259. 7 d/ _- g% M: E+ U
  260.        if(bIsIDEExist && bIsDiskExist)% V- J. c) G1 k0 A
  261.        {
      x5 e/ n* y+ s4 {( M' a- }7 N8 u
  262.            DWORD dwDiskData[256];
    3 a+ S9 \5 E. V" q
  263.            char  szSerialNumber[21];' ~4 [3 s; z4 B  U- Y& K7 l+ r' q2 W
  264.            char  szModelNumber[41];
    + x0 j( U+ {& e/ z% H" H$ D8 z

  265. ' U8 S* {( i- G) b' [; D) d0 i1 m
  266.            for(int k=0; k < 256; k++)/ a( k# ^" M1 J+ y* M$ F, M
  267.                dwDiskData[k] = wOutData[k];
    ! J( Y3 B3 y! A4 {

  268. 9 s" H6 \. _# w
  269.            // 取系列号
    5 c$ x% v. D0 N
  270.            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));! H6 h! l0 y0 M# @- a( _: o
  271.            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
    9 f# J( {" a( l1 M! D
  272. & t1 E& d& m$ Y* M1 j
  273.            // 取模型号6 O7 t7 b  W# S/ `+ [; E# r) n
  274.            ZeroMemory(szModelNumber, sizeof(szModelNumber));
    8 G7 h/ e8 V/ P+ w8 D, Y7 d& s
  275.            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));. m9 y, S( A# B2 L8 Q
  276. * w. e% O4 J0 Y' P/ u7 r2 r
  277.            pSerList->Add(szSerialNumber);4 n+ H9 m5 a/ W
  278.            pModeList->Add(szModelNumber);
    ) k& t) k' F0 h  H: v: Y
  279.        }
    " O( U' x& Q4 s0 l: ~  K
  280.    }, x( a* v9 q, w0 `( P1 [9 d
  281.    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);- i2 g7 Z0 o  O, {: B! p
  282. }
    $ I2 R6 P9 u  A/ P! G4 t
  283. //---------------------------------------------------------------------------8 d- |) `4 F; e' c
  284. // ReadPhysicalDriveOnW9X_Ring0()
    4 `. d+ v! h+ ^; p
  285. //
    1 e' o# M8 {3 X/ d' b8 l) R
  286. // dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
    + |3 b5 k% [+ K8 q
  287. // btMasterSlave = Master(0xA0) Or Slave(0xB0): g# S) L( s! j1 C% u
  288. //---------------------------------------------------------------------------
    0 y7 T/ ?- Z1 B6 i8 O- Q
  289. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
    . i& v' V9 ^2 i0 l! F2 @+ O
  290.        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
    & b; P0 T* v0 L0 l
  291. {
    7 k! Y1 E8 W, ?4 c: ^
  292.    BYTE  btIDTR1[6];% v3 A9 C' ^5 A* T: I1 Z) u
  293.    DWORD dwOldExceptionHook;# V0 c  I) r2 }9 z
  294.    const int nHookExceptionNo = 5;
    # |9 J" o4 K5 n( \( S

  295. $ y! z# R( ^2 R  x: N9 D
  296.    BYTE  btIsIDEExist = 0;
    4 j9 v1 {3 `. T1 O# N
  297.    BYTE  btIsDiskExist = 0;. x6 @3 _0 ]1 M) d4 f
  298.    WORD  wOutDataBuf[256];
    0 b/ k$ E6 v  u

  299. & \* [/ N$ V8 m, B
  300.    BYTE  btIsFirst = (BYTE)bIsFirst;* y9 I" t4 B5 U
  301. 9 s; K, c& P" d4 u5 O: o
  302.    const BYTE btBit00 = 0x01;* n) c! Q+ ~% M- @* d; m
  303.    // const BYTE btBit02 = 0x04;
    : v/ B! C+ S  o
  304.    const BYTE btBit06 = 0x40;
    - b& |# A9 [& p' ?% H8 z' `
  305.    const BYTE btBit07 = 0x80;$ o" g# K, }/ `) h; Y6 Q  \( ^
  306.    // const BYTE btERR  = btBit00;
    $ u. f; [% o8 t% b! B% a
  307.    const BYTE btBusy = btBit07;
    $ V) }, H. z9 J" W8 ^3 W! \
  308.    const BYTE btAtaCmd   = 0xEC;7 l% m) `+ P1 K4 r& S
  309.    const BYTE btAtapiCmd = 0xA1;+ }: r, t4 {* ^3 A
  310. 0 w$ f$ z4 {6 I2 ~
  311.    __asm
    % U3 Y, Z0 d: h
  312.    {
    & e6 m" |4 r& J; n
  313.        // 必须先执行这条语句* W( t5 }" U6 q# w- E
  314.        JMP EnterRing0  Z' x0 Q! B: y) q: B( e

  315. 2 E$ b' s! ?1 @5 U
  316.        // 定义过程" H% X& q' d  X6 K: O2 s# o1 G
  317.        // 等待IDE设备直到其不为忙为止
    * l- M6 N( l3 u$ \
  318.        WaitWhileBusy proc
    ; D8 L6 o! {  J0 u. _

  319. 6 Y- m! v8 v/ X+ V. l; Y; A) y
  320.        MOV  EBX, 100000
    ! Q) h( H- T3 E# }+ Y. \# |
  321.        MOV  DX, dwBaseAddress! @. g& S- @2 Y( o
  322.        ADD  DX, 7
    5 T( O% u8 y! M, V3 \: ]$ ]

  323. 5 }& V+ w- Z5 L- S6 [% f
  324.        LoopWhileBusy:( C2 X) V! P6 r/ u6 z
  325. : h0 ?, r( Y$ U" U/ ^
  326.        DEC  EBX- p  N- T8 ^7 ]& D# W; t
  327.        CMP  EBX, 0
    2 u8 d* O1 W% i$ l
  328.        JZ   Timeout6 T2 _, |4 T/ g, z" R- X$ ^8 u. a
  329.        in   AL, DX
    $ r7 h% ]6 _$ q: h4 k6 `) o9 E5 o
  330.        TEST AL, btBusy. {  Z: N0 G/ H" F- M: ~  E
  331.        JNZ  LoopWhileBusy+ |5 c; S  l! S. g0 |
  332.        JMP  DriveReady( y! V- X6 m" S8 [) W

  333. . L* g0 u$ |7 \
  334.        // 超时,直接退出
    1 h. k( V" ^, [9 `$ E4 `. |8 l. l
  335.        Timeout:
    , E' E5 o0 Q  O6 O
  336.        JMP  LeaveRing0
    ! h" l. }2 j. y
  337.        DriveReady:
      i& m, ^6 z% q$ T' `
  338.        RET* J* Z8 ~7 Z7 M0 ]
  339.        ENDP   // End of WaitWhileBusy Procedure! x0 |' m1 s. D+ z! i

  340. " T( n# J6 U' x2 `$ @7 r
  341.        // 设置主盘和从盘标志
    - Z8 E: C. [5 J  I) s: ]
  342.        SelectDevice proc
    2 v8 I3 ?8 S2 H* s7 R; c- o0 J

  343. % l! x6 `9 b8 h/ F* q) q
  344.        MOV  DX, dwBaseAddress
    ! m6 E2 L! w2 Q( R0 i
  345.        ADD  DX, 6/ I$ M2 B5 u! D0 O* A, v$ m2 X0 q
  346.        MOV  AL, btMasterSlave
    , H) z2 @. B, N1 F
  347. ' k1 }/ `. u9 g- y- y
  348.        out  DX, AL1 f0 s" k7 `; g- \) F2 S& r
  349.        RET9 p" k4 [% K9 X3 d" J) O6 i
  350. / G; @9 y+ A( q1 e; j
  351.        ENDP  // End of SelectDevice Procedure. C& g0 |- A! Y. _
  352. 3 ]) ]/ h- v6 z5 [
  353.        // 向IDE设备发送存取指令! N8 O2 x2 O, s8 M0 w) H- U
  354.        SendCmd proc" p0 m* U$ B. p& h0 n; [
  355. 3 k, `& h0 Y$ i; @! R
  356.        MOV DX, dwBaseAddress
    7 F+ Q+ Z. ^, C! ?4 v8 {! O" l
  357.        ADD DX, 7
    % e# g) F8 C. q! A4 ]8 B
  358.        MOV AL, BL // BL是主从盘标识,在过程外设置' Q  y) m$ g% y8 o2 M
  359.        out DX, AL4 r6 q, b$ ?8 g, r% K& G$ u" F0 [
  360.        RET, r: y- F2 m1 {' A, K5 Y/ T5 N
  361.        ENDP  // End of SendCmd Procedure
    : [- w& z6 j% P( h( }
  362. 4 U- H6 @) Y( R4 A+ q1 u8 e8 [2 g
  363.        // Ring0代码
    , C; w! o9 Q9 c( X
  364.        Ring0Proc:( r* y0 z/ ^* [. r3 f
  365.        PUSHAD
    - ]& k' J7 H3 E9 G( c
  366.        // 查询IDE设备是否存在
    ; K* X  u( x- a$ U5 a; [
  367.        MOV DX, dwBaseAddress
    0 e- p1 T' c3 X7 g9 x; Y7 E
  368.        ADD DX, 7
    1 c9 p6 _& O* K8 c
  369.        in  AL,DX. V4 M1 L3 u  Z& g

  370. / E3 I6 W% O+ t0 y9 U
  371.        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
    : F# {8 ]8 a9 P! c% S# T% }) X
  372.        CMP AL,0xFF
    6 I/ v5 l. z, ]
  373.        JZ  LeaveRing0
    . P; t8 x; e4 _. b3 G5 a
  374.        CMP AL, 0x7F4 \1 n1 p; a- Q: ~4 Q; B/ Y1 X; V: ]
  375.        JZ  LeaveRing0; T( ~2 w) ^+ u* Q: U
  376. 0 q+ Y' Q7 H) S
  377.        // 设置IDE设备存在标志) i: {- X. {- `5 r$ w3 y+ M
  378.        MOV btIsIDEExist, 19 v/ x& c% K9 h& w

  379. 9 o, }7 c* C1 S1 M4 d0 {
  380.        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
    6 M9 V( `# o5 H& h9 o
  381.        CALL WaitWhileBusy% K8 t, o4 I. o6 o$ |, ^, X
  382.        CALL SelectDevice
    1 N: M  o) `" W; k# c

  383. 4 ]% {( W% ]  N8 t! Y8 b
  384.        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
    ) U: p) U* {6 Z" i) Q8 q4 K( l
  385.        CMP  btIsFirst, 1
    ) Q4 z7 r, y: T
  386.        JZ   LeaveRing0
    " w) j+ n; p0 i' J* w6 o

  387. 3 J! x1 V% l' q3 _
  388.        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
      v6 G0 A* X0 y9 {( b0 j
  389.        CALL WaitWhileBusy
    " M1 v, R/ E( P2 V2 L& N

  390. 7 w3 U5 R. q. `8 c9 |3 P' s
  391.        // AL的值等于cBit06时,不存在驱动器,直接返回
    * \3 X- l6 _! w3 h( M0 z" R
  392.        TEST AL, btBit063 O5 `5 M1 M8 S" X8 P
  393.        JZ   LeaveRing0
    * S' V/ b, B6 j5 r4 V

  394. 5 t- c& r3 Q9 p6 t, {0 |" v( [4 p
  395.        // 设置驱动器存在标志
    * T8 H0 D# H  W, X# @
  396.        MOV  btIsDiskExist, 1  p8 w4 f! d2 |8 |  w4 e$ E4 {% \
  397. 0 `  ~$ D6 N5 G
  398.        // 发送存取端口命令8 `6 P! L8 j- \, g) g  T( t  [( q! I
  399.        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,9 M3 n! d5 Y% _5 d4 Q
  400.        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
    / ^+ M" T8 E8 l2 z3 J
  401.        CALL WaitWhileBusy0 G. V6 c( L& ~" l; q- j6 s
  402.        CALL SelectDevice    // 设置主从盘标识3 P! `: J* I6 T; Q9 ~3 ]
  403.        MOV  BL, btAtaCmd      // 发送读取命令. I8 w0 N' \4 S9 w
  404.        CALL SendCmd
    $ _5 I% Y- E! E3 F0 v2 q
  405.        CALL WaitWhileBusy! a7 `( F' z" C# p8 i$ h
  406. . g, o3 l/ k$ V' Q: N
  407.        // 检查是否出错
    * f5 |: l" v/ f. N0 j0 F. |
  408.        MOV  DX, dwBaseAddress7 v$ ?1 F3 w. h
  409.        ADD  DX, 76 [' ?5 g$ C2 X# s5 C6 D1 S

  410. " \) O9 A2 j) J; V
  411.        in   AL, DX8 N0 _& o: W. ^! ]: k

  412. # ]1 u/ I) ?4 O8 Z5 t/ c2 M" L# \
  413.        TEST AL, btBit00! u6 E. B8 L. x) N, f+ z0 P
  414.        JZ   RetrieveInfo   // 没有错误时则读数据$ D, I6 S: G' [  [& y5 A" }" p0 z
  415. 9 x" T0 B( t, _# a1 D& I8 y6 V
  416.        // 如果出错,则进一步尝试使用ATAPI设备命令
    ; h# t& H0 J$ o/ [; x! h1 c" }
  417.        CALL WaitWhileBusy' I6 z8 g9 A( _4 }/ z- t" g, i: m
  418.        CALL SelectDevice
    : ^& h: Z1 o" {5 c4 t) [& d! I
  419.        MOV  BL, btAtapiCmd
    % f9 k3 Y" W# [" b+ a; h9 L7 K
  420.        CALL SendCmd
    4 f* w1 n- \. K0 u  {" c$ s
  421.        CALL WaitWhileBusy/ W; T( y" _, B4 B
  422. 1 e! i: R0 i. \
  423.        // 检查是否还出错
      D- s0 c* t. [" G- q
  424.        MOV  DX, dwBaseAddress
    0 R, ?( n! A9 p$ |5 j# I3 \% D4 P
  425.        ADD  DX, 7: o7 ~) N( x. Q1 C; c- E" L% J
  426.        in   AL, DX
    * N1 V; `% D1 e5 ~+ \1 M
  427.        TEST AL, btBit008 p/ N; @* a5 r! p4 T
  428.        JZ   RetrieveInfo   // 没有错误时则读数据
    $ \0 h* D9 Y3 L! J" t
  429.        JMP  LeaveRing0     // 如果还是出错,直接返回
    ; z. ?' N1 {& p  M! |
  430. % i7 g9 l4 w( R5 j* p4 _4 ~
  431.        // 读取数据
    3 ^" s( r7 D( }- Q- m* l- P9 y; t
  432.        RetrieveInfo:9 @2 M2 s! A  p& }" a

  433. 3 s4 b% R. i8 j* i5 h$ o5 q1 p& u
  434.        LEA  EDI, wOutDataBuf
    0 d, S  J- ^9 l; f
  435.        MOV  ECX, 256" v7 O* O7 Y1 G* H8 T7 I
  436.        MOV  DX, dwBaseAddress
    ; t- `  T* X* T1 ?& R+ l  m+ h9 G
  437.        CLD* a9 i/ s" {- X& ?

  438. 5 r$ b+ y) _" _# [
  439.        REP  INSW( A) q/ W9 |' y( A$ p

  440. % m$ q' K* B7 \8 o3 I! Q
  441.        // 退出Ring0代码
    3 `- t, \$ M! }
  442.        LeaveRing0:
    6 p2 `/ G1 \1 ^  B) T

  443. ) [& j* v, W. C5 n
  444.        POPAD
    ) H' s& S" R6 R0 X+ [$ y7 b: i
  445.        IRETD
    * ?+ M6 m, U" A6 E% L

  446. + A0 j6 O' }  t1 v
  447.        // 激活Ring0代码
    " C; w5 x8 R: g0 G4 l
  448.        EnterRing0:
    0 I( L$ |6 E  _/ i( i
  449. 1 C* w8 q& g  a
  450.        // 修改中断门3 V" ~* [, ]! i
  451.        SIDT FWORD PTR btIDTR17 y$ u/ h6 x+ [
  452.        MOV EAX, DWORD PTR btIDTR1 + 02h2 F% l% s; e% V: @
  453.        ADD EAX, nHookExceptionNo * 08h + 04h
    8 |) _) S0 _; {# C+ O0 t; x
  454.        CLI
    / P2 n2 y' i8 I* I9 A; g
  455. - N- V( N; p# S: F4 _/ ]1 ^- L9 b
  456.        // 保存原异常处理例程入口
    * P& I  o# h2 X! H0 L& G
  457.        MOV ECX, DWORD PTR [EAX]& L9 F4 L) Z' J5 N) u; J8 C
  458.        MOV CX, WORD PTR [EAX-04h], G+ X1 b+ ]9 J4 V( S( x% V; w
  459.        MOV dwOldExceptionHook, ECX' n7 v" g7 t9 F) b; I# r) J
  460. 2 G' ]4 c. U; i+ P5 r5 N
  461.        // 指定新入口
    2 x, Y2 @; w% T
  462.        LEA EBX, Ring0Proc( `8 U7 L; z3 A/ ~; B. R4 q
  463.        MOV WORD PTR [EAX-04h],BX
      [! ~! W9 I/ K2 a- J9 G9 _  t
  464.        SHR EBX, 10h
    7 u& X0 j6 w. r2 _' G0 K
  465.        MOV WORD PTR[EAX+02h], BX( Z* K" L3 f: k) N  ^, V
  466. 0 A7 A8 z" v+ e" X5 ]" I
  467.        // 激活Ring0代码
    * s: A% L1 h* i7 R' P
  468.        INT nHookExceptionNo
    4 B% X% c1 Z4 [. D! e+ K& D+ q
  469. / D) M/ j$ P! \, u! {" N
  470.        // 复原入口
    4 N* s, j6 p" e1 f7 T
  471.        MOV ECX,dwOldExceptionHook( I1 D: N$ A: Y: V" h- A6 A& R: S
  472.        MOV WORD PTR[EAX-04h], CX
    ! r1 Y2 u" {: v4 Y; j
  473.        SHR ECX,10h
    0 T" w9 N5 [, G! |
  474.        MOV WORD PTR[EAX+02h], CX
    7 W, h. {" j* ~+ [2 P3 i0 e2 G* z
  475.        STI& Q1 a9 H" d3 h5 ~
  476.    }  e& b6 V1 k4 Y' A1 s1 S' z
  477.    if(!bIsFirst)
    - M# \1 {; Y" A* j- {6 z
  478.    {4 Y2 P0 ?/ S8 @7 t
  479.        bIsIDEExist  = (bool)btIsIDEExist;
    7 ]7 T7 I% [' @+ U
  480.        bIsDiskExist = (bool)btIsDiskExist;
    % w/ q4 k4 b: F) v3 P' k: K
  481.        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));. C: R: v' c& S1 D% o- V! i) b
  482.    }' A5 h8 q1 t) ]3 X6 i, y6 c6 O8 a& O
  483. }
    ; k$ F2 E+ ]4 J3 I* t
  484. //---------------------------------------------------------------------------; {7 J! w" @3 u9 P, s* @
  485. // 调用方法:
    + W8 A/ ?& i, {! [3 P  B' o, O6 ~
  486. void __fastcall TForm1::Button1Click(TObject *Sender)7 X" {0 e0 X+ s
  487. {
    1 Q* u! _* R/ i: d  N3 a
  488.    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
      q, F' Y2 t8 q8 V& t! C
  489. }
复制代码
发表于 2005-8-15 01:00:45 | 显示全部楼层
晕乎乎。。。怎么看8 洞阿
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-5-5 10:28 , Processed in 0.015808 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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