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

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

[复制链接]
发表于 2005-8-11 11:42:04 | 显示全部楼层 |阅读模式
  1. #include <WinIOCtl.h>; S7 I- W6 P4 U  }0 O' [
  2. #include <stdio.h>
    6 U1 q' }9 J1 y) |
  3. . J& [: E0 O& z9 M5 _) M
  4. #pragma inline
    : F0 Q9 E/ e& j$ x
  5. //---------------------------------------------------------------------------
    8 Y* J+ r7 f. F  n: Q4 r
  6. // IDE NT/2000/XP专用变量- }1 N- h) r' g; q: }2 M/ i+ l9 `
  7. #define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
    : Q9 ?" t7 B: K7 X) E
  8. #define DFP_GET_VERSION         SMART_GET_VERSION
    - R7 k3 [" X+ Q5 c% p2 H, Q+ b
  9. #define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
    : ]/ G. M; e, G( m/ P
  10. #define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
    ' [! E2 m7 w* B  m! U4 p9 O' `
  11. , l: Z' j9 ^9 i4 c
  12. const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令" k* q7 P4 q6 H  O1 B5 k0 ^
  13. const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令& I5 W8 {4 p* s7 g5 d' R7 n

  14. ; V# K3 }1 V+ z" m& E" y
  15. const int MAX_IDE_DRIVES = 4;! e; \$ n1 C& W, Y" A: l
  16. 7 I/ V) B8 v' q) N# w& z
  17. // SCSI专用变量7 ?, x5 k! }( [
  18. const DWORD FILE_DEVICE_SCSI             = 0x0000001B;
    5 T! R+ ]# ]0 w3 W1 R
  19. const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
    0 J, `+ v7 P# n# F) X
  20. const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition! V" j0 b2 `+ [$ X3 |* ~
  21. const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;% K( p+ j. j$ O
  22. 7 Y0 B+ {1 Q# q
  23. typedef struct _SRB_IO_CONTROL* z9 ^* v4 ^& D7 J  n
  24. {8 K- N) S1 I. D( [
  25.    ULONG HeaderLength;7 b- y( \& ]$ ]  x7 t
  26.    UCHAR Signature[8];* Z2 I: X- U$ B1 ~8 @
  27.    ULONG Timeout;
    " J% l+ G/ ]' A
  28.    ULONG ControlCode;8 L! k0 I/ @' j$ k& w
  29.    ULONG ReturnCode;0 h% I' N& x3 D
  30.    ULONG Length;+ G/ e6 u0 x* V2 v
  31. }SRB_IO_CONTROL, *PSRB_IO_CONTROL;
    8 @, X8 z3 k# C, e$ Q2 q2 i

  32. 4 ?3 }( W. F* Y$ `9 E
  33. // 读取的主函数
    % a4 v( B. q/ ~1 d+ e4 K* k
  34. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
    1 y: Y7 F9 y% @+ I; J: p
  35. 5 a2 \+ h, i9 d; U
  36. // 辅助函数
    1 e' d3 i$ `: Z' x; O0 x  }# b
  37. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
    ' r5 H$ }: p, {  ?( Z
  38. // NT/2000/XP函数1 Y: b+ X3 M2 H' U
  39. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);- s0 G" A) `7 b* f  O) |% ~1 N
  40. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
    4 m8 b; o5 o! c1 K# Z+ q, M
  41.        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
    - N  C. N5 M. F
  42.        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
    0 x; N# ^! i1 c. B9 e
  43. // Windows 9X函数
    ' Y! i  |% D: B: ?$ L* d; I
  44. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);. X. S5 Q# H# P( ]8 k$ z
  45. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,9 s" R$ ]8 n4 ?( M
  46.        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
    , \$ l$ L& _" f6 {3 N* x

  47. 2 ^* @# X" g- _+ O
  48. // SCSI读取函数(for NT/2000/XP); c. e* |2 o( f! }/ d
  49. String __fastcall ReadIDEDriveAsScsiDriveOnNT();% E5 Q4 e. ?4 G0 y5 K2 k
  50. //---------------------------------------------------------------------------+ D) S1 }1 ~! y) J4 R
  51. // ReadPhysicalDrive8 q4 X7 R/ A+ w+ x! a6 r- x
  52. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)) {! }0 X1 {# t0 B0 Y; M
  53. {
    3 Q2 m. C6 k! K& j
  54.    switch(Win32Platform)
    3 o/ g6 J" Z+ Y3 _0 N2 \, Y6 Y
  55.    {
    ( h0 d0 R& H5 k$ ~7 g
  56.        case VER_PLATFORM_WIN32_WINDOWS:& N2 }) s" s7 k  ^; x# S& W
  57.            ReadPhysicalDriveOnW9X(pSerList, pModeList);
    ( G9 m5 J6 y+ ^
  58.            break;
    ( y  X7 m1 q& ?$ G& R1 D
  59.        case VER_PLATFORM_WIN32_NT:
    , f& r+ n9 n3 K# \9 e: K7 I/ u% z0 W
  60.            ReadPhysicalDriveOnNT(pSerList, pModeList);, b& b" C9 I6 ^( p* D6 J! l
  61.            break;
    # d$ }% D: n- R  D% }3 _
  62.        default:4 @' {; x" ?5 |; J+ @
  63.            break;
    7 U% q9 r5 a5 @3 w
  64.    }* M, n2 z4 \( s4 n# K3 ]
  65. }
    + s# v: d( m: i/ p# U
  66. //---------------------------------------------------------------------------
    ! O+ X+ U# l  a; K' V
  67. // ConvertToString
    0 `6 r0 @. k  B: y+ i) v( L- N& [
  68. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)5 c- Y, _2 ^0 c
  69. {
    " I! f: V$ Q* X- Q- u" E
  70.    static char szResBuf[1024];
      m+ t: S. Y7 G, C" c
  71.    int nIndex = 0;
    : |8 M  s' X/ u( A- a6 T- {9 |# c
  72.    int nPosition = 0;
    4 v! Z( i4 {0 J( q6 ]

  73. 8 y7 k$ S; \9 `; }$ G9 c
  74.    // Each integer has two characters stored in it backwards! \* q: L; h1 v/ K
  75.    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)! n) e+ |: j$ e3 o3 B5 x
  76.    {$ D5 F5 X. R* q# i; X
  77.        // Get high BYTE for 1st character9 k- c  Q' g" T6 C
  78.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
    ( s, m) y3 g  T( O
  79.        nPosition++;
    , n+ t8 h  ^" `  j

  80. % w& E/ |4 ~8 b8 X# t( A0 c0 c
  81.        // Get low BYTE for 2nd character
    ; ]' L( P7 @) Q0 u4 b# Z; W
  82.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);5 Y/ j  M) M* E* L, t+ b
  83.        nPosition++;& K! ?  |+ V: f: O
  84.    }
    . k3 y% O' Q+ x: }8 P7 v

  85. 3 k( H% {3 R+ V6 z' ?
  86.    // End the string2 ?* f0 l: y% D9 @. D
  87.    szResBuf[nPosition] = '\0';0 F' G- x0 S( c2 q3 @( D/ k/ U( ^5 i$ D& N
  88. * ~/ q# d% V) g
  89.    // Cut off the trailing blanks; F: V' q! ~" a9 Q  Z, ?% [6 c4 s
  90.    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--), P8 Z" \9 J  W$ s7 ~) L: T: k
  91.        szResBuf[nIndex] = '\0';
    1 q+ D% S. \- l3 e. f2 f+ ?

  92. : V; l* H& {) {3 d6 m
  93.    return szResBuf;
    " y, c' {) b; H& R4 g; F
  94. }, N2 F+ V& s) V9 m6 O  C
  95. //---------------------------------------------------------------------------
      m8 X5 E0 I1 p3 W
  96. // Winndows NT4/2000/XP 代码
    / p! j( s. P6 k8 _: C* D- H
  97. //---------------------------------------------------------------------------
    : }% v# r6 ]/ `" U3 [: _5 E" g- z' A2 e
  98. // ReadPhysicalDriveOnNT
    # m& P' k* t9 j8 T/ w4 t# T7 l3 k
  99. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
    + x- k5 k5 W: v* l1 o0 P
  100. {! R1 C4 q: v2 ]8 d1 h, e
  101.    // 输出参数4 O9 z% [1 s; I' r6 k* z
  102.    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];; P& ^3 @; h6 @, w; x

  103. : z$ r9 r& o9 m3 [7 {7 I
  104.    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
    % W; I, |9 m5 A; @9 m
  105.    {
    ; u6 ]3 {3 H0 h5 W' G$ |
  106.        HANDLE hPhysicalDriveIOCTL;7 n/ V) W5 z3 d9 \) f2 z
  107.        char szDriveName[32];. S9 H" E6 k1 b1 q  M+ }# Y, @
  108. . X3 |. E% p1 g: G/ y
  109.        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
    4 i, q& y' r0 J: n6 h
  110.        hPhysicalDriveIOCTL = CreateFile(szDriveName,
    ! o( j* d/ K( Q9 a6 v  b- U4 _
  111.                        GENERIC_READ | GENERIC_WRITE,  L( ?! V" v7 R8 N7 `+ w; Y
  112.                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,' U0 j! }+ U8 L6 k
  113.                        OPEN_EXISTING, 0, NULL);6 q& _: |! p2 S
  114. 1 ^. M- Y' X1 }" f7 b0 h! w( M
  115.        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
    & U0 X) W) w+ Q
  116.        {9 R5 A/ M5 p$ N, `: O0 K
  117.            DWORD dwBytesReturned = 0;4 a1 u$ Z  K9 n. s" ]9 c9 N. |0 D
  118.            GETVERSIONOUTPARAMS gvopVersionParams;7 p0 g# [( \/ H# M

  119. * J! s3 I" A1 ]1 a6 n/ F! Z$ a
  120.            // Get the version, etc of PhysicalDrive IOCTL
    " r$ a" z2 H! a. r+ j, z% |
  121.            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
    9 K5 U! M" g5 p+ u0 a3 D
  122. 5 E9 e+ e2 s& S' P' O+ I
  123.            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
    * s' K  |' ?# f  J
  124.                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
    3 Z+ I0 Y4 B7 |& \/ B
  125.                    &dwBytesReturned, NULL))
    7 \" L' q+ t; {" W% M$ a' G+ I
  126.            {; N( k+ i  k. _3 ]7 b. k
  127.                continue;
    - R9 b8 u) `4 h$ ]+ r
  128.            }
    ' T  t( c# G( C) c( ]! y# [
  129. + T7 D  j; @9 y3 G- e1 F
  130.            if(gvopVersionParams.bIDEDeviceMap > 0)
    1 x. x( z- }& [
  131.            {8 A+ S4 v) j2 c+ U: U9 ~' e2 b  K$ m
  132.                // IDE or ATAPI IDENTIFY cmd
    # V4 J0 w8 b, C6 x: j7 P! L
  133.                BYTE btIDCmd = 0;& Q- L; O4 e6 }- P" }! L
  134.                SENDCMDINPARAMS InParams;
    % F; O7 X" Z# z2 H
  135.                // Now, get the ID sector for all IDE devices in the system.
    0 _) V' l. ^: C0 p& |! D
  136.                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,. W5 ~/ K- W2 {
  137.                // otherwise use the IDE_ATA_IDENTIFY command
    4 \; g0 W( f: r) e( @6 |1 F* @/ r& U
  138.                // 具体所得结果请参考头文件中的说明6 b8 f0 l6 k$ v
  139.                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
    1 s1 @" [! Y9 E1 \, z% t( d
  140.                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;, ~. q2 N1 ?9 U6 `7 G1 Z
  141.                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
    ; w! w: c7 e" r1 B3 f  V
  142.                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
    ( \8 }( K" S9 c1 |+ ~* p/ t

  143. 1 R1 W8 g% `5 |- X
  144.                if(DoIdentify(hPhysicalDriveIOCTL,- v6 D9 Z  h, z6 v. W8 {  R' \
  145.                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,# \  e, b  g! l- K. W* g. F
  146.                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))0 D' k) o% s! D$ Z
  147.                {7 {) [% a2 U* A1 s- p0 R( Y
  148.                    DWORD dwDiskData[256];3 x. }/ J& j" B- B( Y* A5 \8 D0 {
  149.                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件! t; K+ Y. d7 w2 b
  150.                    char szSerialNumber[21];- i* ?% d9 y# d+ F; r
  151.                    char szModelNumber[41];2 C' T5 j. v* A; }
  152. * M$ u. _$ ^) V; x# s1 b
  153.                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;9 i7 Y* X; g: \, d
  154.                    for(int i=0; i < 256; i++)
      W$ ], }1 ~( f; c% i+ U
  155.                        dwDiskData = pIDSector;
      r4 x) X; }& y! Y! M
  156.                    // 取系列号
    9 F; n9 z6 Q: i2 J/ y5 W  Q
  157.                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));8 Z& s! m' J: \% O# a9 V3 B$ \; R
  158.                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
    - W7 L9 B+ b/ q1 t) |, t: Q$ _- F2 k

  159. # i$ W$ H# u, h6 R: s' r
  160.                    // 取模型号
    ! X$ L8 s% T$ n/ ^9 f4 {( k
  161.                    ZeroMemory(szModelNumber, sizeof(szModelNumber));
    + r8 F1 s" C% j4 C
  162.                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
    " O  w( g& ^. i% o7 |
  163. * \5 H9 A; G% ]/ W
  164.                    pSerList->Add(szSerialNumber);, t! h3 F/ ^) t& m
  165.                    pModeList->Add(szModelNumber);$ ~6 y0 j3 x& _5 Z0 N+ V6 o
  166.                }, l2 o) u. m. E; y( M
  167.            }2 P3 a: y5 L  J% A
  168.            CloseHandle (hPhysicalDriveIOCTL);
    7 T$ n" b4 `& {
  169.        }
    1 k+ B! D! s$ |% m% B9 @  D9 W( [
  170.    }
    ! @: S) }1 ?" c1 {! U% ?
  171. }8 R" [0 \" v8 T" b  \8 W  h) n) B
  172. //---------------------------------------------------------------------------
    9 B  Y' _, M6 w5 N2 u- p% C
  173. // DoIdentify) w" j/ _! F! v3 j0 T4 J4 p
  174. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,+ z) X& f; H9 i0 A: M
  175.              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
    % E6 K$ J- w  _( q' o0 b7 c
  176.              PDWORD pdwBytesReturned)# A/ C$ g. }3 H. U6 C) c
  177. {4 g; L; R" I3 P
  178.    // Set up data structures for IDENTIFY command.4 D% D* j& Z! V1 ?
  179.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;* K$ ~5 v% ~# Z* P: ^& E, G% H
  180.    pSCIP->irDriveRegs.bFeaturesReg = 0;
    . @+ s2 w& b. H+ P$ ~) ^
  181.    pSCIP->irDriveRegs.bSectorCountReg  = 1;
    3 z" L6 F  {  Z) H: m
  182.    pSCIP->irDriveRegs.bSectorNumberReg = 1;5 V0 ~) D4 K7 @$ U
  183.    pSCIP->irDriveRegs.bCylLowReg  = 0;
    - d2 f7 t/ q7 R' Y4 y. O, C
  184.    pSCIP->irDriveRegs.bCylHighReg = 0;" M2 k! j0 M# G" P1 F; A! `7 O

  185. + F6 V$ b% C; Y
  186.    // Compute the drive number.(主盘和从盘所对应的值是不一样的)+ m& i) }' k1 [! |
  187.    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;$ [- T  u& |' Q: N. b# _

  188. # B  m4 ^3 H  q% r3 H; O( n
  189.    // The command can either be IDE identify or ATAPI identify.
    ' n6 N, Z2 }" n8 e9 D6 b6 D
  190.    pSCIP->irDriveRegs.bCommandReg = btIDCmd;: P$ _6 m, Y* P
  191.    pSCIP->bDriveNumber = btDriveNum;( C3 {7 p0 @+ ^* K( N
  192.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
    $ x6 v" [  u( [" }0 b

  193. 4 D! |" ]- Y/ d
  194.    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
    % T& O2 Q2 n3 K1 r
  195.           (LPVOID)pSCIP,% D0 k+ s$ h$ g0 W
  196.           sizeof(SENDCMDINPARAMS) - 1,
    - k- y6 [& t7 U
  197.           (LPVOID)pSCOP,8 z  {( Q- O1 j* _& W
  198.           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
    : Y" G& A( _$ B- h8 J+ u3 {  [
  199.           pdwBytesReturned, NULL);: E+ h5 V* @, i/ }* ]2 \# e& O
  200. }
    6 k$ r% P- z( y& q
  201. //---------------------------------------------------------------------------
    4 s6 b- e% `4 F; I& S7 w
  202. // Windows 95/98/ME 代码3 s0 u: P1 u2 z! x, x* x, _' ^
  203. //---------------------------------------------------------------------------
    . Z* W/ A1 s. y  B9 m+ i
  204. // ReadPhysicalDriveOnW9X% _6 [8 A! K3 A, Y# b9 C
  205. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)- v8 d# l! w5 k. |
  206. {1 a6 G% Z# Q3 F4 t
  207.    WORD wOutData[256];
    ; ^( ~$ `0 a+ A; O
  208.    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
    0 h# g1 d& [7 c1 Y* P$ ]
  209. ! I* c) B, p9 x4 Y" J3 Q1 X
  210.    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。0 J( l' ]; i* x2 L' |
  211.    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
    : u$ f) _3 @. `8 {
  212.    // 避免蓝屏的出现。(期待高人能指出原因)$ A2 O* l9 e" x( B. B# J
  213.    for(int nDrive = 0; nDrive < 8; nDrive++)5 L2 `  H0 ~' P& m. m
  214.    {% U2 H( K+ D! t+ V- Y
  215.        WORD dwBaseAddress;7 m% U6 ~- y; D
  216.        BYTE btMasterSlave;         // Master Or Slave
    3 w0 ~. L8 Y% W/ |& x  M
  217.        bool bIsIDEExist;
    . t% R* Y. J) {6 @- a' V5 r
  218.        bool IsDiskExist;0 D; u* U  U9 s& U( ?, W. G
  219. ) M7 O/ o' W0 h- i2 Z5 Y: c+ K
  220.        switch(nDrive / 2)! w7 Z* [5 k9 H, K
  221.        {
    " n9 a+ w: @3 a0 Z8 W
  222.            case 0: dwBaseAddress = 0x01F0; break;* G  N, L; d7 i* d2 l0 R" d
  223.            case 1: dwBaseAddress = 0x0170; break;
    / u% f* S* B" V# p4 |* S
  224.            case 2: dwBaseAddress = 0x01E8; break;
    , e! |5 |: k2 T; z. i* J$ V( {% D
  225.            case 3: dwBaseAddress = 0x0168; break;
    : v- b9 m& Z$ z! f8 e# U* ]* j
  226.        }4 w( T/ D* O' y  l: i/ z( Z
  227. + P# ?& D4 j$ J4 k% _8 N. Q6 W
  228.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
      e. n: G" N& K0 L  J
  229. ' M6 V! `9 Y( Q$ K( V  u6 U
  230.        // 进入Ring0
    ( U& g! {% F# N
  231.        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,7 A( P  p. {3 n" l) C7 v
  232.                bIsIDEExist, IsDiskExist, wOutData);
    . [# R" _0 m, @: y+ y, U4 x. A3 M
  233.    }
    $ a4 s- v  J& e( n, M5 Q$ S

  234. / ?( K& @. h7 N: a8 t
  235.    // 开始读取
    3 H$ \. C8 N1 }0 ^9 g
  236.    for(int nDrive = 0; nDrive < 8; nDrive++)7 \9 O3 p" `( J) u+ n9 `3 p
  237.    {
    / L. H! s& E; v, i6 _
  238.        WORD dwBaseAddress;5 T" v2 ?4 \3 l6 b3 B
  239.        BYTE btMasterSlave;         // Master Or Slave& e" e% X# c) _) R6 _) C
  240.        bool bIsIDEExist;
    8 Z9 S! k8 k" K$ K/ B
  241.        bool bIsDiskExist;
    3 e: ^) h( @* P: W2 j. w. U1 t( K
  242.        switch(nDrive / 2)
    1 S' x; A7 x: Z8 F
  243.        {
    : P. @& X5 _% j) v7 M
  244.            case 0: dwBaseAddress = 0x01F0; break;
      U' _1 p- H! @
  245.            case 1: dwBaseAddress = 0x0170; break;
    3 P1 I- Q; n4 T8 p9 s. F( b
  246.            case 2: dwBaseAddress = 0x01E8; break;
    9 F6 {/ H1 W2 c: d  ~( D) Q% U
  247.            case 3: dwBaseAddress = 0x0168; break;
    ) e& h- G$ l; j0 L4 q
  248.        }
    : A; W- ~( v9 k5 g  V6 f

  249. % V# D. K6 N$ r% n* k" k' p1 j
  250.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
    ( y, \5 }* c2 X2 R0 O: q+ {

  251. ( f# t* a0 [6 I3 x
  252.        // 进入Ring0
    # h; p: y  l, v1 z1 ~
  253.        bIsIDEExist  = false;
    : k$ K( h, X( }* U9 t3 I! K
  254.        bIsDiskExist = false;
    $ ^3 x# W8 E# G7 Y9 f8 s
  255.        ZeroMemory(wOutData, sizeof(wOutData));
    2 S! y  j! i, m6 y# V# \
  256. . i% d% [1 C& u. [6 z
  257.        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
    2 x- k% T# E0 z5 P& d9 T
  258.                bIsIDEExist, bIsDiskExist, wOutData);, ?( X, k# f- R: @6 x

  259. * k2 g& p. C, D2 S4 |/ I
  260.        if(bIsIDEExist && bIsDiskExist)5 A( }8 j4 x1 `/ ]( m  O3 X. M
  261.        {
    2 {  h4 n2 h& I* G$ i
  262.            DWORD dwDiskData[256];1 f  X5 b/ X  k5 N
  263.            char  szSerialNumber[21];# o. z5 p9 q0 C! ]) E. a) J& v
  264.            char  szModelNumber[41];
    8 N3 B2 t0 q6 r2 L+ j2 O- \8 ~2 ?
  265. , P4 R3 T' N* ]
  266.            for(int k=0; k < 256; k++)8 u4 G2 J! O& m% ~. J
  267.                dwDiskData[k] = wOutData[k];
    / [+ t# [- p/ o7 B9 Y7 H

  268. & }/ D( l+ d7 L2 F8 I. o
  269.            // 取系列号
    & _8 q% b2 E* h: k6 d. B
  270.            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));% |! P- {4 o) `  g! S6 o
  271.            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
    ' x. H$ k; s7 J& S$ B3 |
  272. 9 J5 G. s. D, o* r$ H( T
  273.            // 取模型号+ z% D* Q% I0 ]' _& B4 x4 i
  274.            ZeroMemory(szModelNumber, sizeof(szModelNumber));* @7 L. n2 |2 s+ Z  Q/ B- F) A
  275.            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));: F3 l5 N4 T) Z6 o6 w% q
  276. + p' V( j( |0 g/ Y
  277.            pSerList->Add(szSerialNumber);( R2 Z8 U+ E8 D, i
  278.            pModeList->Add(szModelNumber);6 e! S5 f& @3 x
  279.        }8 [) [) z2 J: r* B$ t2 D
  280.    }
    ' E% N0 c) X. c1 [( h4 i: N" C
  281.    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
    ! i. k/ t' n% M. j
  282. }
    # c, l! E* ^/ V' x5 L$ p
  283. //---------------------------------------------------------------------------0 v* V( u2 U; U. A: \
  284. // ReadPhysicalDriveOnW9X_Ring0()5 f. p' p2 z  H0 N3 S. \$ d
  285. //+ @0 z8 F) W9 H+ g; E5 q4 g5 c' `
  286. // dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
    ' m9 K0 I) b: a, ]$ [9 @& P
  287. // btMasterSlave = Master(0xA0) Or Slave(0xB0)
    ) `1 q5 u/ n5 j  c$ L
  288. //---------------------------------------------------------------------------
    $ L( J! o; ?6 P3 `
  289. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,. N; w3 ~( r* d; E: [
  290.        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)# s% v8 B! y: R
  291. {
    , b0 d8 f- i( t/ h; b5 U
  292.    BYTE  btIDTR1[6];! W9 X, L/ i  z( |8 _. k6 W
  293.    DWORD dwOldExceptionHook;9 A% b& L2 Z/ M7 g* t, B  B
  294.    const int nHookExceptionNo = 5;
    - j+ e5 h$ O% B' n, D9 @! v; l) R

  295. 2 k1 R  e/ \3 t, Z/ p9 W
  296.    BYTE  btIsIDEExist = 0;
    ) r8 ?) g& w8 _9 t2 }
  297.    BYTE  btIsDiskExist = 0;
    7 e" v" Y8 x2 v+ m- I. n
  298.    WORD  wOutDataBuf[256];# `& _, U3 e1 i9 d  y8 ^2 U

  299. 4 I- b! D' r7 f" E+ q% I
  300.    BYTE  btIsFirst = (BYTE)bIsFirst;
    5 X# }; j( ]8 J0 S

  301. 2 G, t* ~; x2 E; @( J
  302.    const BYTE btBit00 = 0x01;
    0 B4 o+ \, m" E: V1 @
  303.    // const BYTE btBit02 = 0x04;; h4 a/ u% `# v1 b4 ^
  304.    const BYTE btBit06 = 0x40;
    9 ~3 p" n* r* Y4 ~. D- c
  305.    const BYTE btBit07 = 0x80;- O( I* o/ ?, ^7 z/ r
  306.    // const BYTE btERR  = btBit00;
    : I; ~- n4 s8 C
  307.    const BYTE btBusy = btBit07;
    " R" m, h( _7 V3 I6 o: S1 j
  308.    const BYTE btAtaCmd   = 0xEC;; Q$ H% j* v3 y% h' Q( X
  309.    const BYTE btAtapiCmd = 0xA1;
    % ^) a8 \$ a: a
  310. ; E$ s- ~/ \0 `; L3 U
  311.    __asm
    ! X3 Z$ ]3 L! L$ O! ?( F7 E6 M
  312.    {
    ' l* _- p+ W* z8 S
  313.        // 必须先执行这条语句
    # |; ^6 s# W0 l: Y0 m
  314.        JMP EnterRing0$ H; d# E. s' O" \7 h2 l6 }
  315. ' ~0 w& m4 w6 Y8 u+ C
  316.        // 定义过程. z8 C( |4 i% k2 P; E
  317.        // 等待IDE设备直到其不为忙为止/ `1 W8 W+ N6 ]1 J* p
  318.        WaitWhileBusy proc
    0 a6 x2 S( X) z7 T

  319. 4 F2 r" ^7 k+ |3 E
  320.        MOV  EBX, 1000001 R- R& W/ R- G1 M6 \
  321.        MOV  DX, dwBaseAddress  ^1 ]  _( `# M& B+ N
  322.        ADD  DX, 7
    : w) [# q% ?# L( `9 x' a5 L# \
  323. / R3 U: p( ^" Y6 W, Y! Q  r
  324.        LoopWhileBusy:
    , D% l4 q* U5 ]! I1 Y+ x9 W6 W
  325. 0 z) Z4 f7 g3 O, Z
  326.        DEC  EBX. m) O& y2 [+ z' l) f
  327.        CMP  EBX, 09 J+ @7 Y2 U) P, ?5 |
  328.        JZ   Timeout& T# S6 }. Z' Q4 \+ n1 M
  329.        in   AL, DX
    ! B" c% G6 Q( `2 H) X
  330.        TEST AL, btBusy* u5 u# s. A, ^& q
  331.        JNZ  LoopWhileBusy4 y; E9 M& Z0 E$ h
  332.        JMP  DriveReady
    " g8 a8 x/ H; b( p# B

  333. " J- o, s: d6 M
  334.        // 超时,直接退出
    & o3 u4 g$ w, r- U6 ~
  335.        Timeout:  |5 C% l* V- q! Q1 d9 l  j: v& Q
  336.        JMP  LeaveRing0
    ( i% J' D* \  N
  337.        DriveReady:! a2 X5 s6 Y; H6 g
  338.        RET. f, C. s7 {' T/ U
  339.        ENDP   // End of WaitWhileBusy Procedure/ \: c' _$ f: S/ J
  340.   f* B1 c0 ^0 j' v. \
  341.        // 设置主盘和从盘标志
    ( d$ _% s  M$ l9 O% _
  342.        SelectDevice proc
    8 m3 I3 J/ O- X- b+ W% V
  343. ; t6 f( O! U8 j6 l1 _& U* W9 R
  344.        MOV  DX, dwBaseAddress' y% L+ W3 g2 w0 z, a7 y, l5 K4 F
  345.        ADD  DX, 6' ?7 i* x; i2 U& I3 h
  346.        MOV  AL, btMasterSlave& p& O$ Y/ a, @% g7 {1 d

  347. / y, Y) V5 ]# D1 g7 [
  348.        out  DX, AL
    7 s% f0 }) w) C& ?
  349.        RET
    , x/ B) U4 b6 y; K6 O, z

  350. - Q- z  o. N% H5 V
  351.        ENDP  // End of SelectDevice Procedure
    3 }( e' x) D  e, [6 s) j

  352. " G) d) k' ]8 C6 p* ?  ^& w3 A  h
  353.        // 向IDE设备发送存取指令3 U2 s/ i( U9 j; ?, [2 s* d. L
  354.        SendCmd proc
    1 W& n( S2 I2 Q9 |2 Y! X

  355. * m) o! ^8 Q/ p+ O8 y/ K
  356.        MOV DX, dwBaseAddress
    2 F; i3 c. ?% d* n- i4 j
  357.        ADD DX, 7- C+ D, M* \: v/ _
  358.        MOV AL, BL // BL是主从盘标识,在过程外设置# l0 A! x0 f' `# ~
  359.        out DX, AL
    4 I; l8 `: j  D" X) D( r
  360.        RET4 Y  \" F9 h; X# X( s0 x# ?4 l
  361.        ENDP  // End of SendCmd Procedure
    / C. a' @' [9 Z8 w* c

  362. 6 q7 e! m- C: [
  363.        // Ring0代码1 Y# j& K/ r: L$ k
  364.        Ring0Proc:
    6 h$ a! ]9 N! w7 O9 T2 N
  365.        PUSHAD
    " }6 y, |6 t, @4 W
  366.        // 查询IDE设备是否存在
    # i% z4 g) e( f1 \9 F/ [
  367.        MOV DX, dwBaseAddress& s7 l" S$ e; ]  K/ \9 }* ?4 D
  368.        ADD DX, 73 m+ T' n, a% c$ a# `) O9 ]+ D
  369.        in  AL,DX0 N. C. E' ?- ]0 z: O1 Q
  370. 9 h4 j$ B, k% r4 A7 |. \
  371.        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回- p  n/ D( `+ q4 l6 s
  372.        CMP AL,0xFF9 H" t9 v+ I& F- w8 D3 q$ \
  373.        JZ  LeaveRing0  s6 ?  q7 q  H
  374.        CMP AL, 0x7F5 f8 d8 W- c; l0 F" w" e, q
  375.        JZ  LeaveRing05 Y1 T8 u& _5 y- ^

  376. : b- {$ H' \, \9 ?' o; Q4 i* h& {
  377.        // 设置IDE设备存在标志
    ! G+ g! h& _1 C: I
  378.        MOV btIsIDEExist, 1
    7 B6 P: J3 [4 _% a# z3 z
  379. $ l! B& z" J' [9 j" F+ [
  380.        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
    3 k, N& B, ]$ R. S2 s2 E
  381.        CALL WaitWhileBusy# j9 A7 e0 O) a$ v, E6 U$ U) [. W
  382.        CALL SelectDevice
    2 ~- Y9 }& K: f2 g0 N0 |1 y+ J
  383. 0 W; `% B8 {3 U
  384.        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏4 G7 h. X' V1 F% D
  385.        CMP  btIsFirst, 12 b2 _6 o! Q" W: X, l
  386.        JZ   LeaveRing08 A) A' h5 m/ [
  387. 0 S3 D4 q4 b# @! ?
  388.        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
    % T+ u& S* C3 m" x$ ?% H) \! F' Q- P/ V
  389.        CALL WaitWhileBusy
    3 Y$ O+ D1 O' b& p; W+ ]
  390. + x* S" C1 n" a" Z, c$ A( s$ k! q
  391.        // AL的值等于cBit06时,不存在驱动器,直接返回$ D) l* v, e& e9 H5 g; p% G
  392.        TEST AL, btBit06
    : |) }; l2 y- w* T5 c$ m$ _2 M! Q
  393.        JZ   LeaveRing0! ]+ M& T# `* C6 s# t. o$ m5 F4 o
  394. : t  U9 Z( b$ u
  395.        // 设置驱动器存在标志8 k- W' X, L( `/ v: y! s$ h
  396.        MOV  btIsDiskExist, 1
    8 O4 {$ {0 |7 z

  397. 2 R* T% z. m" p- T; V) {, Y
  398.        // 发送存取端口命令# c2 Y- Z; {  v! o* U
  399.        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
    % t. y" O% E( R. C, O
  400.        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令8 R' h; t( i- p, j/ `; |
  401.        CALL WaitWhileBusy. n) {( @+ X0 J- V6 t
  402.        CALL SelectDevice    // 设置主从盘标识
    ) J+ ?' K8 u! t6 J
  403.        MOV  BL, btAtaCmd      // 发送读取命令
    9 q% _8 K# e6 D+ K8 A
  404.        CALL SendCmd
    * o- P- @6 S# d
  405.        CALL WaitWhileBusy
    7 P! {  y2 H3 W; T+ o: A/ r- _
  406. : h/ S0 w/ s2 z1 M- e9 u
  407.        // 检查是否出错
    8 ]7 T! `+ g  D# O
  408.        MOV  DX, dwBaseAddress
    8 f+ T, s4 d- d. t* ?* W
  409.        ADD  DX, 7( A5 N1 |, p- j; J- @" y  V! T2 o

  410. ! P0 v; H. k$ K* S9 }
  411.        in   AL, DX# v; I& \2 }7 U1 D

  412. 7 M6 v5 R- `, z* ^$ m8 F
  413.        TEST AL, btBit00
    / k- }* @- n( x, w
  414.        JZ   RetrieveInfo   // 没有错误时则读数据4 H2 @, K' l3 x) p! q, U- s/ y

  415. * g( x$ o6 b8 ]+ K
  416.        // 如果出错,则进一步尝试使用ATAPI设备命令% b( ^0 S6 M$ q; E( v
  417.        CALL WaitWhileBusy
    # I0 G$ A" {  w( m" w- H# n& b
  418.        CALL SelectDevice/ l# {+ h. q# k
  419.        MOV  BL, btAtapiCmd
    ) P: D/ c0 V5 V& X
  420.        CALL SendCmd  t- h3 y4 d4 l5 i1 V4 y
  421.        CALL WaitWhileBusy
    ) B* h: ~/ c, T4 I, L) ^( s
  422. 6 W2 N+ h: D$ h. q
  423.        // 检查是否还出错
    7 g7 v$ k; I3 k* J" H' |; a) K
  424.        MOV  DX, dwBaseAddress
    0 [! b) {  Q: t
  425.        ADD  DX, 7% G; t, W/ u: J3 o! i
  426.        in   AL, DX
    4 ]" O6 I/ @  e7 n; \% p0 A
  427.        TEST AL, btBit00
    . }5 Z0 u+ U- ]* N: ]  s2 l2 v
  428.        JZ   RetrieveInfo   // 没有错误时则读数据
    " ~: T# [9 m  q7 _# s  y3 V
  429.        JMP  LeaveRing0     // 如果还是出错,直接返回1 z. C9 e: g$ _9 O
  430. 8 B* Z/ [2 t# B- y! e1 H3 u$ ~
  431.        // 读取数据
    $ J4 u! b3 p% X; P) w5 L& m( M1 n
  432.        RetrieveInfo:
    9 _8 O/ B* ]) @; G3 c" Z! `
  433. : ~: h7 Y( f! ]" [; T- l2 W
  434.        LEA  EDI, wOutDataBuf$ [& T7 H$ P( }9 D: ^: ~3 b. H
  435.        MOV  ECX, 256
    5 O% h* c+ o& h* L' t2 K
  436.        MOV  DX, dwBaseAddress/ U+ @. U$ k. b( U
  437.        CLD( R  S+ G/ o7 q  I& B

  438. 4 a- Y5 ~+ d7 @$ h. F
  439.        REP  INSW& n. H" a1 f' a: ?8 _
  440. % z2 ?9 X: ]! V; s
  441.        // 退出Ring0代码& y" Y8 C, R% L2 J9 C
  442.        LeaveRing0:4 S3 o9 |/ k6 s- F) z" U
  443. 6 i" P; U6 d. r! [
  444.        POPAD
    & r# H  V0 L4 p9 A2 ?5 X: i9 d
  445.        IRETD
    " U7 x4 {" `' K! m
  446. ! d3 y0 ?7 `7 B1 p  c
  447.        // 激活Ring0代码3 y8 u) J9 }1 g# h0 i8 i5 N1 S
  448.        EnterRing0:
    / S4 Q; P4 y; `5 X5 B: @- V

  449. 4 Y5 m4 _; N6 O7 `1 A" i( O* W
  450.        // 修改中断门
    ' D, Y& ^) _; ]7 D- U7 J
  451.        SIDT FWORD PTR btIDTR1
    - c6 X& s$ H5 o* |1 S
  452.        MOV EAX, DWORD PTR btIDTR1 + 02h$ U* |( q( x3 q/ K5 ?
  453.        ADD EAX, nHookExceptionNo * 08h + 04h
    4 B. A7 e7 ]; H! Y
  454.        CLI
    ; |2 ?) l0 y) N# g" x0 A" u
  455. : X: y7 z4 k7 H4 h9 f
  456.        // 保存原异常处理例程入口
    ' C! D5 w3 n8 E. W+ J
  457.        MOV ECX, DWORD PTR [EAX]
    $ D) K* a3 {- ~- H" V
  458.        MOV CX, WORD PTR [EAX-04h]
    + R! u( J, }2 S
  459.        MOV dwOldExceptionHook, ECX
    ! z. }% n+ m* x) I0 h( I
  460. 9 }( x8 m5 |6 J! D5 l
  461.        // 指定新入口
    ; G& w, C0 G" d( y
  462.        LEA EBX, Ring0Proc2 k7 C5 `7 Z4 d' l" d' o
  463.        MOV WORD PTR [EAX-04h],BX6 ^- m1 \! ?3 Q) Z
  464.        SHR EBX, 10h8 O' g9 k" c0 O  |
  465.        MOV WORD PTR[EAX+02h], BX
    * A7 m' I2 `+ |/ P

  466. + @5 s. k, c) H+ f5 s3 J1 h
  467.        // 激活Ring0代码
    6 D9 \( ?- y; F1 M
  468.        INT nHookExceptionNo
    ! C! k# f% {; ~+ W: l% D$ V  ~
  469. 5 a! @3 u( l4 ~. J+ F
  470.        // 复原入口
    6 y3 }" R6 H; m0 u
  471.        MOV ECX,dwOldExceptionHook- Y0 m: g9 s7 _
  472.        MOV WORD PTR[EAX-04h], CX& X5 Q" ]" I3 z- H: i: l, [
  473.        SHR ECX,10h
    5 ?+ y7 d- t( i. |
  474.        MOV WORD PTR[EAX+02h], CX/ O8 X# j' d" V4 ]& I/ y7 g
  475.        STI
    9 i/ T, W8 X& [& b* A/ [
  476.    }
    3 a: G7 S5 Q+ ^( V
  477.    if(!bIsFirst)6 e- g) N% F& u4 S" O- p4 w+ s
  478.    {# v6 j$ T$ }% j6 o0 n; h
  479.        bIsIDEExist  = (bool)btIsIDEExist;
    4 e" h5 b( x, ^3 M( A# g/ [
  480.        bIsDiskExist = (bool)btIsDiskExist;
    & i/ u, z# S2 H3 A
  481.        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
    # Y4 r6 l( e4 O3 J: s$ I
  482.    }
    . G5 ?; {. F# ~1 k$ K
  483. }9 |# u0 ]* N0 D1 F
  484. //---------------------------------------------------------------------------! Y' T7 D# D/ |/ v
  485. // 调用方法:
    / U" I# W+ h# H2 R0 A3 t
  486. void __fastcall TForm1::Button1Click(TObject *Sender)" k; T. l" w  h
  487. {" H; B" Q) \/ ]
  488.    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);  t  ]- j$ l$ f6 I7 Q4 p' H1 ~
  489. }
复制代码
发表于 2005-8-15 01:00:45 | 显示全部楼层
晕乎乎。。。怎么看8 洞阿
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-9-30 09:09 , Processed in 0.039116 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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