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

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

[复制链接]
发表于 2005-8-11 11:42:04 | 显示全部楼层 |阅读模式
  1. #include <WinIOCtl.h>1 R( U; W. ?1 E  C' V3 q$ m6 k+ r6 R
  2. #include <stdio.h>
    5 j1 i; e# q" i5 E7 J
  3. ' t2 t5 z7 ]: ^( J  k1 F! g9 L
  4. #pragma inline
    # I! q2 q5 ~  u$ w+ L1 M, c- i5 q
  5. //---------------------------------------------------------------------------8 t3 S) Z3 Y" G$ m/ G" v/ G
  6. // IDE NT/2000/XP专用变量
    " M+ L9 l6 y) c2 a1 w# G
  7. #define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS% M. H" t% Q4 s# ?$ F
  8. #define DFP_GET_VERSION         SMART_GET_VERSION
    & P' e- t$ ?: N: m2 m
  9. #define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND7 n) X) m& v9 x' T% x) W* L
  10. #define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA; Z/ C+ |+ i$ g" X$ X5 M
  11. " K- M: T& A+ x  f; M# P
  12. const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令+ O8 n( x2 h% \- }' a! [1 e$ l
  13. const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令! j1 f" k7 k2 x4 q+ {, h
  14. : S' d9 h$ U3 \
  15. const int MAX_IDE_DRIVES = 4;
    ) R) {* f7 [( N4 e" m
  16. : v' M- p: r4 o! w4 h+ ~4 J
  17. // SCSI专用变量- l1 X+ x3 O. [3 A
  18. const DWORD FILE_DEVICE_SCSI             = 0x0000001B;. w5 |# p, J. H# M8 R1 k
  19. const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
    ! C/ V2 J* P5 q$ D
  20. const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
    ( B. x7 \/ F# Y/ r: H( V( v
  21. const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
    5 `$ x) U! e$ L$ X6 t
  22. # e! ?8 l; K% e8 L( u! r0 t
  23. typedef struct _SRB_IO_CONTROL
    4 \" L/ S, s  H# y$ M
  24. {
    ( g5 S+ ?) ~2 B# T" ?
  25.    ULONG HeaderLength;) n7 H+ {) n0 }9 P$ B
  26.    UCHAR Signature[8];
    8 g# f8 f$ r9 n, t; s
  27.    ULONG Timeout;! R; o! a) o8 p4 a+ x  e
  28.    ULONG ControlCode;
    . [/ P4 L8 E4 a( E$ Q- w( D
  29.    ULONG ReturnCode;& N/ i  l1 a, P8 M6 A+ _4 p
  30.    ULONG Length;
    2 ]  p9 ^' ]$ [
  31. }SRB_IO_CONTROL, *PSRB_IO_CONTROL;
    2 ^4 N1 \4 E9 Z4 H

  32. ) Z# {3 `4 S' ~  Y
  33. // 读取的主函数& V9 f* F* E3 L6 L: g
  34. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
    " }4 o: T0 X4 P$ B% i: j3 D! S

  35. + F3 P8 s+ Y3 P  r8 k, D
  36. // 辅助函数2 P6 D- G& V# E" m- m- A
  37. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
    3 S7 Z2 @) C' V* v
  38. // NT/2000/XP函数& C/ \- P3 ?  m- p8 c; E
  39. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
    * K3 g0 I* q- y7 [
  40. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
    . U) D& d" d1 i+ X4 p
  41.        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
    , E1 \. s$ Q- V" s  w
  42.        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);2 Z5 t9 W) u* R4 P+ r
  43. // Windows 9X函数
      q  ^9 G: z. J# D  m
  44. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);
    9 |2 ]/ b1 d' I" q; }
  45. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
    : K* c% H5 x2 F* l
  46.        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);* p/ f: U) E) ^  C+ X

  47.   r. F) q6 ^3 l( O/ t
  48. // SCSI读取函数(for NT/2000/XP)  @7 T! q: U6 ?0 B- T7 P  A2 U
  49. String __fastcall ReadIDEDriveAsScsiDriveOnNT();
    & Y- d+ j5 V& |3 C9 U
  50. //---------------------------------------------------------------------------
    ; q1 k  i+ P1 X% U
  51. // ReadPhysicalDrive
    , e  m5 W" _8 c; u
  52. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
    % G8 G! W5 Y. q- h$ m: K
  53. {
    / B- ]% R' J) u+ U: q- c6 ~2 |0 ]
  54.    switch(Win32Platform)' l  [- p( ?: B. D7 j5 C3 e
  55.    {
    1 _+ ]( {/ z8 `6 {$ W2 Z
  56.        case VER_PLATFORM_WIN32_WINDOWS:* w- [" _# @: Z5 K3 q
  57.            ReadPhysicalDriveOnW9X(pSerList, pModeList);2 h; {) D  Y# q8 V6 s( v* F, p
  58.            break;- O# ~- _+ j6 V9 Q& `
  59.        case VER_PLATFORM_WIN32_NT:* x  W8 i* b- M9 U- s3 Z7 M
  60.            ReadPhysicalDriveOnNT(pSerList, pModeList);- Y6 s' ?" B! {9 X
  61.            break;1 m+ M& `' w! u
  62.        default:
    ; ]2 L; |6 }& v8 f4 r
  63.            break;7 P1 Y% i0 {* t4 [1 e
  64.    }% s1 P8 q  j$ f: t' ~8 |
  65. }* w3 E8 J( ^+ I( M
  66. //---------------------------------------------------------------------------
    5 d& k0 r: s3 C9 H2 ]2 C
  67. // ConvertToString
    # `) F5 ?5 F) u; T% ^' N+ K
  68. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
    $ q8 d3 i0 D. w% p
  69. {( S+ i  R4 I( }0 m! b9 a
  70.    static char szResBuf[1024];
    ) \- A9 b0 O: L3 j7 C
  71.    int nIndex = 0;
    + j# L  O1 S# ~% |: c% U
  72.    int nPosition = 0;9 |& {! c4 ^. e  [6 `8 a

  73.   u0 Z4 u0 H3 [* F
  74.    // Each integer has two characters stored in it backwards
    5 p* M0 O9 `8 K( w
  75.    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
    & h* h& r5 j( M/ I6 o& n
  76.    {5 U- j& P7 M; a& Z+ w
  77.        // Get high BYTE for 1st character3 z, _- e' U6 r/ R% m
  78.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
    ! W7 Q4 s# k% Z( a; Q1 F0 O
  79.        nPosition++;  Y2 `8 r- B* L2 n
  80. + I: {! n* l0 g$ v3 w
  81.        // Get low BYTE for 2nd character
    1 y( g7 T5 V3 w
  82.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);8 Z& O; c1 \) f8 \9 l
  83.        nPosition++;
    % ^* P) a! u  W- o2 G$ j
  84.    }, c: d/ d9 B% a/ R% F

  85. 1 y7 _! H% a( C. J# D7 g
  86.    // End the string
    1 O+ x( g& h0 s5 y- Y
  87.    szResBuf[nPosition] = '\0';( y9 `& j0 l1 f) i

  88. # R# `( l7 F8 U9 ]  E2 g. ~# u8 p
  89.    // Cut off the trailing blanks5 A9 p2 H* _& ^1 \9 W
  90.    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)' R* ~/ ~0 ]  X: p
  91.        szResBuf[nIndex] = '\0';9 z6 Y+ g& `6 }

  92. ' @2 ]7 F" r7 f' |1 e
  93.    return szResBuf;
    8 _8 U7 O2 ?" Q
  94. }5 A( e, H" R; R# g0 t" u2 y) k$ ?
  95. //---------------------------------------------------------------------------
    7 B2 Z. f8 Y# }  _+ o1 o
  96. // Winndows NT4/2000/XP 代码( {/ Z: r7 w6 a, X: j& g4 s
  97. //---------------------------------------------------------------------------
    5 W* V: C$ h* K2 ]+ r
  98. // ReadPhysicalDriveOnNT
    / z" G2 u2 G" t/ I
  99. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)  `& B, O1 U' |3 U; l: e
  100. {
    6 \# o% n* W2 x& r8 E; b; o
  101.    // 输出参数8 s) K  q  _2 H
  102.    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
    / [3 ^" }; ^/ R4 v# t5 ^5 G) \4 \/ V

  103. % [0 s" q/ \' N9 |) Y3 b
  104.    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)8 S' |  B* Q0 J  W3 v6 R
  105.    {
    7 l. T- K- R/ X
  106.        HANDLE hPhysicalDriveIOCTL;
    ) m+ \. v3 b9 s9 x8 v
  107.        char szDriveName[32];
    : k$ v* @' }, T- R0 Z6 s: F
  108. ! S. V$ D, J" q/ I- m/ x
  109.        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
    ' l) G5 L0 @% @& c0 q  n
  110.        hPhysicalDriveIOCTL = CreateFile(szDriveName,! _# O/ m& d1 d, g& o: a0 s; h
  111.                        GENERIC_READ | GENERIC_WRITE,% n$ Q0 a) f4 C9 Q
  112.                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
      E' B: X3 S! G& F* v0 s' w6 h% F2 `
  113.                        OPEN_EXISTING, 0, NULL);  d" {% P' j9 W- a) u5 r
  114. 7 o& p) c6 h+ R. f& t
  115.        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)- ]3 v( [. y4 ~: c; h
  116.        {
    % l; J" q4 l; @0 W1 E9 N
  117.            DWORD dwBytesReturned = 0;
    + l7 n+ I% H; j& u2 b
  118.            GETVERSIONOUTPARAMS gvopVersionParams;
    ; n9 x% A8 y/ k3 K/ E* Z
  119. # x7 J9 R) f6 |( s# [
  120.            // Get the version, etc of PhysicalDrive IOCTL
    ) y! t' N+ U3 Z4 c" E
  121.            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));3 G6 M( u8 i/ `6 g: G( L

  122. 3 T/ T1 o9 m! q( g2 A% O3 `( n& i2 M
  123.            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,' Y. t4 v( h$ L! s0 t( S; \
  124.                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),! b- o8 D$ y( e
  125.                    &dwBytesReturned, NULL))- A) v0 V( u7 y1 B
  126.            {4 `% ?. I( Q+ F
  127.                continue;
    / f$ Y* _+ ?  O# ~, o2 ]
  128.            }
    0 }3 F3 H) Q& K

  129. 8 f& X. [7 Q6 S. H5 h
  130.            if(gvopVersionParams.bIDEDeviceMap > 0). l( |) x& \% z! s1 e4 h% `
  131.            {7 A9 T% J& _3 ]" A# s" X
  132.                // IDE or ATAPI IDENTIFY cmd
    7 t/ Y% A7 S8 T" h! n
  133.                BYTE btIDCmd = 0;
    ; f- g  Z. O; u2 |. m" u
  134.                SENDCMDINPARAMS InParams;  _7 S# s7 c( ^% y. ?3 e5 o2 m
  135.                // Now, get the ID sector for all IDE devices in the system.. x3 o! u$ N2 |
  136.                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
    ! M# \# |, I, K/ }' O6 d4 A
  137.                // otherwise use the IDE_ATA_IDENTIFY command
    ' B7 `5 Y8 }; G& C: \+ O0 ^
  138.                // 具体所得结果请参考头文件中的说明: @- J  c, A: q7 e' `
  139.                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
    7 i9 \  q- T; e, L
  140.                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;  ^) S! E6 \+ L1 V7 X2 o  r
  141.                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));. p& I( f' u4 W2 h0 Y8 m5 M/ `6 M8 Q
  142.                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
    * o  H9 [8 }5 }* W

  143. % B' o5 ]7 Z7 C: h' G
  144.                if(DoIdentify(hPhysicalDriveIOCTL,
    8 Y3 k9 `) ?7 X5 V% a
  145.                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,% n" M: y; i, x! y9 q$ q5 t
  146.                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))# X4 g$ \8 G) N8 d7 I
  147.                {
    5 R6 F3 N; t2 \! I7 N, j
  148.                    DWORD dwDiskData[256];
    ; a! F0 f. f% n5 p' G, Z
  149.                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
    ! d4 B1 T0 r) U" j( y- ~
  150.                    char szSerialNumber[21];* D* t% k: n* a- Y" R4 r
  151.                    char szModelNumber[41];
    . ~4 {! P- ]/ r- q+ s  O

  152. . @2 k, {$ }' f( {9 j, p) W7 T
  153.                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;4 d" ^! v  E& d) V/ w  q
  154.                    for(int i=0; i < 256; i++)
    1 p0 i9 h% m0 Y! q8 o+ h! Y
  155.                        dwDiskData = pIDSector;1 u8 @& {5 K; X/ Z0 H
  156.                    // 取系列号
    ) w) j  X3 \- `, z3 G+ p7 q: p
  157.                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));4 \: j. ~& z0 U5 H- o+ m+ E$ J
  158.                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
    , m: o7 C4 Q2 j( E5 C/ N6 j
  159. # r+ K3 y7 A7 x
  160.                    // 取模型号( B- F4 m  e1 M4 n# J! X
  161.                    ZeroMemory(szModelNumber, sizeof(szModelNumber));5 G5 J# G" v1 h' [7 P
  162.                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));5 Y, {+ ]; \: a8 v% ~7 u

  163. 8 c- O' \1 [8 J9 C
  164.                    pSerList->Add(szSerialNumber);
    1 H0 g  k+ n" i* O5 F
  165.                    pModeList->Add(szModelNumber);  v) l; k+ f. z
  166.                }
    8 I% v2 l9 V* g6 o, d
  167.            }
    2 ~. a' g& |& i" l( u/ G
  168.            CloseHandle (hPhysicalDriveIOCTL);
    7 e3 i4 L( N) l* n: k1 m
  169.        }5 ^8 L9 P- P2 M: K1 s" L
  170.    }: ~7 k, T2 u* w; T0 W
  171. }
    , S6 ^( W/ \" z$ r& `
  172. //---------------------------------------------------------------------------% M5 L) n/ C: b. j6 C  o* M
  173. // DoIdentify2 E4 @, r6 C% d3 Q
  174. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
    ; O( c1 C3 \! e# p6 a7 @  ]7 g
  175.              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,5 h: p7 W- \0 T
  176.              PDWORD pdwBytesReturned); y: f# G6 m% T3 g  x# Y: @
  177. {
    . \3 k5 y8 P& ]$ y1 B
  178.    // Set up data structures for IDENTIFY command.
    + ?4 u; g, Y& R4 ]2 e5 I) L8 M
  179.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
    " `! U* X( Q; E' @/ A9 [  S
  180.    pSCIP->irDriveRegs.bFeaturesReg = 0;4 p( y8 s5 Y' ?% E# K5 f7 M
  181.    pSCIP->irDriveRegs.bSectorCountReg  = 1;
    ) G+ G" e0 t( `( F; g% w* Q3 ]! K
  182.    pSCIP->irDriveRegs.bSectorNumberReg = 1;
    # a. f+ s. R  L( b  n
  183.    pSCIP->irDriveRegs.bCylLowReg  = 0;
    # b* [% d$ Y- Q4 `1 N9 B6 K) f
  184.    pSCIP->irDriveRegs.bCylHighReg = 0;( I6 A/ [2 E# i, P$ D3 v
  185. 9 W) ]' o+ e3 N8 N0 i
  186.    // Compute the drive number.(主盘和从盘所对应的值是不一样的)- ~; ?$ S2 D# [+ F  P
  187.    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;; g) h/ a: ~/ m8 F+ J* o4 G' _9 i

  188. 8 q. S5 w2 e$ N$ E" Q
  189.    // The command can either be IDE identify or ATAPI identify.
    $ Z0 Q5 I/ L, m9 D$ V  H
  190.    pSCIP->irDriveRegs.bCommandReg = btIDCmd;
    ( _7 g! W: a8 W, M) \& M& q
  191.    pSCIP->bDriveNumber = btDriveNum;
    ) B  W  U& S( U2 m: T; X
  192.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;, E1 }- |+ i9 ?: f
  193. 2 F0 K& `- m/ X
  194.    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
    9 G' B! E; X+ F$ I
  195.           (LPVOID)pSCIP,
    5 c4 j+ u! u# s8 P: ]! Z
  196.           sizeof(SENDCMDINPARAMS) - 1,
    ' U  K# r/ Q; J& U
  197.           (LPVOID)pSCOP,
    7 n( B: w, v) H' |- F$ U
  198.           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,: d3 f- I" `0 p8 a. p
  199.           pdwBytesReturned, NULL);- v- h1 f8 H% M( u. N
  200. }
    & [8 y0 |, K/ o6 i- y
  201. //---------------------------------------------------------------------------
    $ C; S5 ]$ ^9 w5 G: j3 \
  202. // Windows 95/98/ME 代码! T% _& ?# P1 ]+ B& Z3 N
  203. //---------------------------------------------------------------------------
    ! J- i3 D0 _: _; x# E$ z9 x. M& A* H
  204. // ReadPhysicalDriveOnW9X3 K, \: a% `* y' u3 o1 ?
  205. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)! b& L0 v' y- D+ \
  206. {
    2 i4 B+ l' C7 d" e7 p
  207.    WORD wOutData[256];% Q$ I8 W1 v  j( n7 P- b5 j/ U
  208.    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);, y4 @+ T; H/ V7 ~: ~1 P

  209. 3 e$ i& Y% C" F3 U  R  ?
  210.    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。, r0 f  q* U( w
  211.    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以6 n+ E9 \: y0 H3 Q
  212.    // 避免蓝屏的出现。(期待高人能指出原因)
    9 b7 u# H8 `" m% @2 ~9 g
  213.    for(int nDrive = 0; nDrive < 8; nDrive++)
    1 n' ?1 \2 ?! q3 f
  214.    {# b  D) k* s1 y& J# I$ \
  215.        WORD dwBaseAddress;3 q; l  `7 ?+ Y7 x
  216.        BYTE btMasterSlave;         // Master Or Slave
    & `0 r7 |& I' c" l; k' z
  217.        bool bIsIDEExist;
    " }) X/ j! f' @' ~- r& s" c
  218.        bool IsDiskExist;
    / L' p2 n0 W" G, k9 P" O
  219.   n; X, W) T( [# l5 G4 G
  220.        switch(nDrive / 2)7 s/ D  `, ]  @* F9 q/ D
  221.        {
    3 ^' ?. y; W! r$ |
  222.            case 0: dwBaseAddress = 0x01F0; break;* p7 `2 C$ x+ }5 L3 t
  223.            case 1: dwBaseAddress = 0x0170; break;5 K, c% R- A, P& f6 n& `. l9 C
  224.            case 2: dwBaseAddress = 0x01E8; break;
    1 m; m1 Z, N# e7 Q5 y+ y
  225.            case 3: dwBaseAddress = 0x0168; break;7 |, ]' j& Q. I/ W! I$ g! C
  226.        }
    $ T8 N' D% Q; X
  227. 9 V9 C! f" N/ X: Y& ]! i' Y" u
  228.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);9 ]9 o- c' G% ?  v4 ^

  229. : Q4 Z! {- Y5 B8 g) G+ f
  230.        // 进入Ring0, |+ T6 S. t5 X* H# ?
  231.        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,: ]" z! Y# ^8 p) {" Z! l) i2 }
  232.                bIsIDEExist, IsDiskExist, wOutData);5 L* a* W% Q2 I; m$ |3 n
  233.    }
    9 g$ y+ Y0 M; m* c& ~/ K: [+ H
  234.   q% _7 q7 f# C# A
  235.    // 开始读取# @  c: {- l! e
  236.    for(int nDrive = 0; nDrive < 8; nDrive++)
    - A. Z/ c. w! T5 F
  237.    {5 b2 o% I, T8 @6 {) G& U* }" y
  238.        WORD dwBaseAddress;0 _% m8 {7 r6 H
  239.        BYTE btMasterSlave;         // Master Or Slave
    & u5 h+ h2 D7 \; |' [7 b. x! Y
  240.        bool bIsIDEExist;
    5 W4 T. r6 _  z$ s1 F
  241.        bool bIsDiskExist;
    8 b( h9 G3 c- z6 p8 t6 \' t
  242.        switch(nDrive / 2)
    4 v' H% t4 R6 P' y* F/ {
  243.        {, c) J8 \0 M, E& l) D# G. C8 P5 n$ u
  244.            case 0: dwBaseAddress = 0x01F0; break;! t# j! \$ L& w4 j0 Z
  245.            case 1: dwBaseAddress = 0x0170; break;
    # H3 ?  ]. A( b0 U# E1 {3 q
  246.            case 2: dwBaseAddress = 0x01E8; break;' R: A) {# J$ [) @. d4 S0 d1 V
  247.            case 3: dwBaseAddress = 0x0168; break;* O  z3 m+ A6 O( L5 c3 Q* F
  248.        }
    7 |8 x9 p2 V$ R2 W4 p  X6 [1 o
  249. ' P' l/ P- d9 _; c' I% v7 M4 N
  250.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
    ' u, w6 ^9 ]2 f7 Z
  251. ' z" l& {" C3 v' `
  252.        // 进入Ring0
    ' f7 ?4 L" H' K; j
  253.        bIsIDEExist  = false;, M% @" e, m# i: i) Y% r: j$ x# C
  254.        bIsDiskExist = false;+ M/ S8 @( A0 G
  255.        ZeroMemory(wOutData, sizeof(wOutData));
    6 A! i! }/ _- s
  256. ; ?% @: [' N5 u  ?  V
  257.        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,. Z3 A0 D) o1 v! Y
  258.                bIsIDEExist, bIsDiskExist, wOutData);
    2 j2 |' E, Q4 ?  a  a% Q

  259. 1 W7 A2 D5 J( ?2 M+ |. {' \  j
  260.        if(bIsIDEExist && bIsDiskExist)
    ; b4 S& A( m: b4 N: e6 [8 F
  261.        {
    # N" D( a4 ~" C6 g
  262.            DWORD dwDiskData[256];; E( d; C' Y* W, t: w/ Y
  263.            char  szSerialNumber[21];( @9 A$ p$ _" u; i$ W
  264.            char  szModelNumber[41];
    ) [% t6 M0 G/ U! k! M

  265. + L5 c5 `; Z' A! A3 P" }
  266.            for(int k=0; k < 256; k++)
    4 C( O) [3 G  n+ c* C
  267.                dwDiskData[k] = wOutData[k];" v& g' P2 a- d- @" w; g3 S! k) I

  268. * U8 r* k. i+ V1 s9 n, |. \" @
  269.            // 取系列号
    ! I/ H( |# C! {9 n
  270.            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
    9 K; z5 `3 C: ~5 s8 O" m" o
  271.            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));: c1 L1 n, ~& H; }2 t

  272. $ D) [% }% W& N* l! I
  273.            // 取模型号5 \; a, a- G( u- A% u
  274.            ZeroMemory(szModelNumber, sizeof(szModelNumber));2 P" K1 K5 ~- `
  275.            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
    1 f9 t5 l, j: j; P4 A

  276. 6 G3 b9 k, p# P, B4 B
  277.            pSerList->Add(szSerialNumber);
    % p5 h+ a9 Q7 a& m, {) F! `
  278.            pModeList->Add(szModelNumber);" A1 R% w! T) ^( b* ]5 w+ ~1 h  `
  279.        }
    4 R7 n6 c. J" p5 \0 O; K: r# A- q
  280.    }2 I  l; m  K9 O; j& t/ g
  281.    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
    / S. z; C9 k% A- ]  Z
  282. }" V; c+ x/ C8 U) j0 y9 W
  283. //---------------------------------------------------------------------------# b7 R, _3 \( q( `& ?! Z) m3 s5 s
  284. // ReadPhysicalDriveOnW9X_Ring0()
    & `0 Y6 B0 ]% e% j
  285. //% I3 B6 r! [, k, E
  286. // dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h1 A1 Z4 b! J/ E
  287. // btMasterSlave = Master(0xA0) Or Slave(0xB0): g3 M5 k8 c/ E  L
  288. //---------------------------------------------------------------------------: m: w- h% A- l9 w) x- e4 i
  289. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,7 C2 a8 L$ w- |/ e  E1 }
  290.        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
      D" f% k& [# O
  291. {
    ; J1 a2 G' Y) X  h" G; ^' S0 Y' h+ j5 v
  292.    BYTE  btIDTR1[6];& I4 t. Z7 {3 U7 W2 Z
  293.    DWORD dwOldExceptionHook;
    6 ~* x! m7 T# S" y, |6 u
  294.    const int nHookExceptionNo = 5;8 R, f+ B* t6 B5 T: V- ]

  295. ; B, w+ F' i1 n0 W% j0 ?% D0 H
  296.    BYTE  btIsIDEExist = 0;% |% h' [  f9 \" @7 P2 a- A
  297.    BYTE  btIsDiskExist = 0;
    - C% W4 {2 C# }. a0 K! ]6 U
  298.    WORD  wOutDataBuf[256];- d( U$ z' z. ~9 r/ ^
  299. * J7 v& w8 `, G# t. Y
  300.    BYTE  btIsFirst = (BYTE)bIsFirst;! M6 B& ^' o3 K# C( x
  301. ) K: ?& E9 Z+ t# }1 e" K
  302.    const BYTE btBit00 = 0x01;) a  V& `% `% M  T4 |( r8 L' ?
  303.    // const BYTE btBit02 = 0x04;
    3 [" l" e5 O6 m5 k. l
  304.    const BYTE btBit06 = 0x40;: Y/ _% g- z1 F( L
  305.    const BYTE btBit07 = 0x80;. E' Z3 \5 K1 f# N# V" L1 j
  306.    // const BYTE btERR  = btBit00;
    1 S+ n# r# W: j  O
  307.    const BYTE btBusy = btBit07;4 b+ U- @  R  ]
  308.    const BYTE btAtaCmd   = 0xEC;
    ! u5 u: ^' d4 x) s3 C9 i# w
  309.    const BYTE btAtapiCmd = 0xA1;
    - X$ L3 x$ ]/ C! x8 B3 t0 x

  310. ' a) _7 e% L: P
  311.    __asm5 O  l4 ~' z( w% g0 z6 ?
  312.    {$ D6 I; x, m+ d5 I% X
  313.        // 必须先执行这条语句
    * Y* n1 S; s2 `8 T( F) R
  314.        JMP EnterRing0$ O. Z  F% d3 x/ i
  315. 3 X0 b+ Y: |( D2 F# m' z
  316.        // 定义过程- @% U- {4 q, d- E  u
  317.        // 等待IDE设备直到其不为忙为止' B. i7 l! `% c2 f) A
  318.        WaitWhileBusy proc
    5 j; B/ h. O+ F! w! m1 H
  319. 6 w0 e% c; H$ c) `' ?
  320.        MOV  EBX, 100000- i+ {$ A( m! N- O% \
  321.        MOV  DX, dwBaseAddress
    $ y: u8 F% O8 `( u
  322.        ADD  DX, 7
    # e2 g' C, X4 w% r
  323. , p, d0 V* q* n  H6 H1 d7 e
  324.        LoopWhileBusy:
    : f( E7 J; H8 i# a
  325. & `) U2 m0 x  w4 ~$ f9 v3 T
  326.        DEC  EBX
    0 ^; P# r2 O! U! k1 f* P4 X5 H2 I
  327.        CMP  EBX, 0
    ) A, r, P" g! M( ]0 O
  328.        JZ   Timeout
    $ j1 s) I' }! p6 O8 ~. c
  329.        in   AL, DX
    6 \& P+ r2 E$ O/ f& X0 @- [
  330.        TEST AL, btBusy' H' J# K0 ~, U
  331.        JNZ  LoopWhileBusy+ F9 {' T( d& p4 P4 S( H
  332.        JMP  DriveReady
    9 f& T0 d* I8 R+ m' }- ^/ ]; o6 ^

  333.   F2 T9 ^6 H* e  c
  334.        // 超时,直接退出1 l7 m& L, d8 W1 z4 B- h. m
  335.        Timeout:
    1 q% L% k1 r; o+ ~5 m9 z
  336.        JMP  LeaveRing0' _) j5 l1 x1 q$ _6 d$ o7 p1 ^
  337.        DriveReady:- o8 n( L3 W) w1 X
  338.        RET7 b+ J2 W# ?4 \0 m
  339.        ENDP   // End of WaitWhileBusy Procedure! S; A$ C! L2 \- l+ q
  340. $ t; d+ h) Q% @1 R. p- A6 R
  341.        // 设置主盘和从盘标志# u7 J3 T' u; g2 F
  342.        SelectDevice proc# `! b3 p: L/ c& z$ T! h$ v

  343.   t1 M% k7 W- B) A, O
  344.        MOV  DX, dwBaseAddress  W1 e) C$ |& V, v7 _
  345.        ADD  DX, 6' z, Q- |( L- V$ s- V
  346.        MOV  AL, btMasterSlave
    ( @! V+ y) N$ [: j; x! ]+ A* @

  347. / X2 s( `# i# {8 b( F
  348.        out  DX, AL
    , v8 B. o) W! [$ w' Y" B' j0 t
  349.        RET, n* n( S5 k3 T. W5 n

  350. # _* R  W7 u  y7 R3 \
  351.        ENDP  // End of SelectDevice Procedure$ l2 p2 R) z$ u. U8 @
  352. . ]7 e% u3 ]  C9 y5 N- E7 g8 g% m
  353.        // 向IDE设备发送存取指令
    " a2 y$ @. D  l
  354.        SendCmd proc  h* o. I" K4 x( Q6 V3 Z) B

  355. . V7 g, _( ?* F- q
  356.        MOV DX, dwBaseAddress
    2 [2 ~. M4 O" O
  357.        ADD DX, 7! u+ x* A9 B2 t0 ?/ J
  358.        MOV AL, BL // BL是主从盘标识,在过程外设置, ?2 m1 x& n0 \  C' ^2 G) A$ `
  359.        out DX, AL( G) ?6 D! L$ |9 Q6 R& M# Q
  360.        RET; i+ P* m3 x7 z, G
  361.        ENDP  // End of SendCmd Procedure
    - O* N1 n5 ]/ I2 I( E2 G+ S

  362. 6 h( ?% o% o# ?& L/ n6 h
  363.        // Ring0代码* ^. e/ V- U: U4 E! d
  364.        Ring0Proc:. A* F1 G9 T! i6 `. ~
  365.        PUSHAD
    % c$ j! a% }# I, w$ h
  366.        // 查询IDE设备是否存在
    0 n/ v. P4 ]! n# x9 J7 l
  367.        MOV DX, dwBaseAddress
    ; A4 O% q& i( |
  368.        ADD DX, 7
    - R9 I$ P3 C0 p3 E) Q2 e( P* \
  369.        in  AL,DX: i6 m' U4 E. ]) Z( F
  370. " H' \) n7 J5 o( I# G
  371.        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
    2 u2 i. M6 l2 g# f! y" i( z
  372.        CMP AL,0xFF
    3 H9 K% }0 E# R0 p
  373.        JZ  LeaveRing0
    $ U8 D5 x0 @7 j0 t8 E: i1 [0 P, H  ^
  374.        CMP AL, 0x7F
    2 i6 y- ^6 \, x* W9 F$ f
  375.        JZ  LeaveRing02 y/ v7 Z( h- c) X: u) \3 v
  376. 1 V  ?2 }! K# F# `
  377.        // 设置IDE设备存在标志
    1 U7 W/ E  }8 C$ W. p! i6 \
  378.        MOV btIsIDEExist, 1
    6 k( [: l. z, a8 V% U8 E% w; A8 y

  379. & R, k! j& q) ^% A9 e9 Q; f
  380.        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)+ J; W3 K  L9 a! y2 V8 \% O
  381.        CALL WaitWhileBusy
    # G( R8 ?( d: ?
  382.        CALL SelectDevice3 a" c, w  M) Q% Z/ H3 Q

  383. ! R" B1 h' q7 Z
  384.        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏3 Z6 D  m6 Y- N( O! M! L, H$ p
  385.        CMP  btIsFirst, 13 N0 @5 C9 @% a' l. N' Y. _
  386.        JZ   LeaveRing0
    # s# k2 c/ t1 z' u

  387. 7 R- @" U" f/ }' w* |( C- N) ~
  388.        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???: M7 g2 g$ ?# `" q3 D; m
  389.        CALL WaitWhileBusy
    " ?) X3 a( d: k

  390. / g2 B1 O: y' i, ?, A7 b5 h& {
  391.        // AL的值等于cBit06时,不存在驱动器,直接返回
    ; I: T' p7 W& J7 T/ @  l( u6 ~
  392.        TEST AL, btBit06' n0 d, B0 h) _# @8 E
  393.        JZ   LeaveRing0
    , g( q* D+ D) P
  394. + i( A! g9 b+ ]/ T9 u( z
  395.        // 设置驱动器存在标志4 b# Z- e- o: [' D2 `
  396.        MOV  btIsDiskExist, 19 e  p  }* q/ `5 ], w

  397. " q# m5 `5 I' s9 t6 R" j+ B! a
  398.        // 发送存取端口命令
    / Z3 @% H) |/ \$ d: e5 l
  399.        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
    9 R% c# A8 {7 @! k3 O- n1 ~* [% _
  400.        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
    ; ?$ f/ q% \' r, |5 d/ v% `4 \
  401.        CALL WaitWhileBusy1 j3 K) n, P8 J; b: \8 I3 b
  402.        CALL SelectDevice    // 设置主从盘标识
    ; z8 b# @5 R. U7 \+ _8 f5 Q
  403.        MOV  BL, btAtaCmd      // 发送读取命令
    : @  x1 S3 T- W+ v6 ~! S
  404.        CALL SendCmd0 e; Y$ w* k2 z
  405.        CALL WaitWhileBusy7 U6 v" G3 Q3 w! Q4 Y
  406. ' l  d: d* a/ ?6 d2 U0 a+ a# q
  407.        // 检查是否出错
    9 P8 s# U# @* B. N
  408.        MOV  DX, dwBaseAddress3 ~# R4 h% o( s+ N
  409.        ADD  DX, 7
    # T+ K; q' R$ x! ]* w* \1 M

  410. * X  u- \: c. i8 N% U' o/ _+ b
  411.        in   AL, DX3 Y/ u# B- L: Q/ ?

  412. , A  G: [: l5 E
  413.        TEST AL, btBit00, i  m% p# `1 V, B( }0 B7 R
  414.        JZ   RetrieveInfo   // 没有错误时则读数据
    % I3 l( O3 s2 R' d. @* g& I& E* t' H
  415. * R& r. z) e0 c; c$ M( f1 e- W# x
  416.        // 如果出错,则进一步尝试使用ATAPI设备命令. ~' |1 q$ d- W2 @' {; _5 u: }
  417.        CALL WaitWhileBusy
      _3 K' y. y' x* g. \
  418.        CALL SelectDevice
    : ~7 c( [& N. M9 M( _8 i; P
  419.        MOV  BL, btAtapiCmd, Z" u8 [' S: Q# e+ j
  420.        CALL SendCmd
    5 T' \/ s8 @- H
  421.        CALL WaitWhileBusy
    ) w; e1 N! I+ m, c' K
  422. - [8 _- K6 g9 k+ k4 n! |( L4 n
  423.        // 检查是否还出错
    0 h8 n7 C( |6 U
  424.        MOV  DX, dwBaseAddress3 m4 Z/ Z2 V# `' n8 l1 F7 y' |8 N
  425.        ADD  DX, 7
    - Q4 C7 [( X8 j' ~% Z. H) F
  426.        in   AL, DX
    . U! z# z, @$ F& i8 ^
  427.        TEST AL, btBit00/ c3 W6 w1 f6 R2 V4 J4 B: y
  428.        JZ   RetrieveInfo   // 没有错误时则读数据' f7 W% K" F9 c/ Y
  429.        JMP  LeaveRing0     // 如果还是出错,直接返回
    & x* X# e. g# n, p$ J

  430. + W9 N% j1 O8 B% B6 h  G; `% ]
  431.        // 读取数据
    0 `7 G$ |7 n1 U' p( z1 B
  432.        RetrieveInfo:6 M, w# ]0 r+ z2 m4 R  O  ^

  433. . d  ?0 y4 H4 u0 I- [+ U
  434.        LEA  EDI, wOutDataBuf  A* E$ n# w& H5 q! Y
  435.        MOV  ECX, 256
    4 b6 Z4 v) [+ v' b
  436.        MOV  DX, dwBaseAddress) U9 l" C. G1 H: Z1 @9 b
  437.        CLD8 B. X( O7 {! C- k
  438.   b9 j0 M! q+ v. J5 R- H
  439.        REP  INSW2 k% z8 ^. a/ @. C% h1 |
  440. ! `0 h* r  x9 F
  441.        // 退出Ring0代码* z8 z7 M6 Z/ m6 _* E" a
  442.        LeaveRing0:
    9 f+ x' \6 F$ i2 @

  443. 1 O* a1 [1 J/ L. @
  444.        POPAD! p+ I" _0 O, K# l+ d+ K$ P
  445.        IRETD) Z4 G3 b) m3 Q9 S( h! `* z" O& F

  446. , k  }8 _) x7 N  x, H: H
  447.        // 激活Ring0代码
    / P( L9 }7 _/ k: g, A( d
  448.        EnterRing0:8 j, m$ Q% r0 N6 w
  449. 6 J% m: O+ m' x6 R
  450.        // 修改中断门
    ) Y& Z3 k' l0 a9 x# B+ e; v1 l
  451.        SIDT FWORD PTR btIDTR1
    4 h' _  ]6 U* {6 p% `9 `
  452.        MOV EAX, DWORD PTR btIDTR1 + 02h. _( T* u+ B5 V2 j
  453.        ADD EAX, nHookExceptionNo * 08h + 04h- M9 @1 l. O* J& m% |
  454.        CLI; o& L* X6 y2 [7 @, W

  455. ' G7 S9 i1 u: f' [3 G1 ]
  456.        // 保存原异常处理例程入口
    5 y- I- Y/ u8 k# y; V- a
  457.        MOV ECX, DWORD PTR [EAX]& u, J% c! v+ d
  458.        MOV CX, WORD PTR [EAX-04h]
    7 n: f: ]% k; c" F: |$ g- [0 ^  r
  459.        MOV dwOldExceptionHook, ECX
    " R! ~. V, y9 P" l

  460. , x1 Z& Q7 M! S" W/ z/ F" @
  461.        // 指定新入口' l2 d* x1 j* p9 I3 W
  462.        LEA EBX, Ring0Proc, E+ x$ |! T, m& q$ T0 k# u& t
  463.        MOV WORD PTR [EAX-04h],BX) W$ ~* V7 R3 w8 @0 B/ c+ |: ~
  464.        SHR EBX, 10h
    / K. a" R: i+ P3 P$ c
  465.        MOV WORD PTR[EAX+02h], BX
    3 B& q0 O4 b% @+ F* V

  466. " S5 j# B' o( S  l3 v
  467.        // 激活Ring0代码
    $ s" _9 Q, C6 \  ^9 A' T) F3 {$ A( h$ n
  468.        INT nHookExceptionNo
    + C2 [2 v! s, v+ r9 F& P
  469.   K$ y( c1 T- e5 L8 J
  470.        // 复原入口
    + Q! f- O+ E4 k+ K. c- a! O2 {0 C
  471.        MOV ECX,dwOldExceptionHook
    & B5 G0 c! j' U5 F$ ^( {1 p
  472.        MOV WORD PTR[EAX-04h], CX
      o4 U4 Z# ]# C$ ^1 @
  473.        SHR ECX,10h6 t3 W# A6 u+ e, ]/ {7 P- c% l
  474.        MOV WORD PTR[EAX+02h], CX. N" S- w8 G# N  G
  475.        STI9 N' p2 o3 O0 i  b7 W% G' I
  476.    }8 ~* C* V( U1 i0 ^$ q+ d; T- M! c
  477.    if(!bIsFirst)
    / @0 }, B2 G7 H8 l# W: l
  478.    {+ }, ^* z: c- ~$ [* Y* n  N3 n8 [& |
  479.        bIsIDEExist  = (bool)btIsIDEExist;
      T* {: k+ Y5 Z: A0 N; {- y4 D0 `
  480.        bIsDiskExist = (bool)btIsDiskExist;
    , r* D) `( j. C/ U
  481.        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));7 [+ w8 C% W7 o0 m% r* u" ]0 J
  482.    }
    ! p' N0 C* q" B  ]4 k
  483. }/ ]; o% Y' o5 w, a7 b
  484. //---------------------------------------------------------------------------
    - U! x& R9 l  G4 U! k- d
  485. // 调用方法:
    * ^: F( ^9 K7 |3 \* Y- o) S
  486. void __fastcall TForm1::Button1Click(TObject *Sender)
    1 r" x. x) X9 p4 h: Y; Z" }
  487. {# @+ _- `7 g5 U. [( X+ k
  488.    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);( t4 H( S* V9 f. o8 T+ h
  489. }
复制代码
发表于 2005-8-15 01:00:45 | 显示全部楼层
晕乎乎。。。怎么看8 洞阿
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-6-20 00:52 , Processed in 0.037167 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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