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

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

[复制链接]
发表于 2005-8-11 11:42:04 | 显示全部楼层 |阅读模式
  1. #include <WinIOCtl.h>- a0 ]3 l4 z. r& R# v' A
  2. #include <stdio.h>7 s/ a* D- L  l' S
  3. 5 J* P+ ]; F+ j4 Y6 Y2 L0 ~
  4. #pragma inline. ^4 Q! d& Q# x$ N/ |& ~, `' k) _( v
  5. //---------------------------------------------------------------------------2 e' L6 B2 i9 Y- @' t- I9 G
  6. // IDE NT/2000/XP专用变量
    ( A( ], R* x( j4 k2 j) U
  7. #define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
    3 e8 @; ?5 Z" m- w/ _7 B
  8. #define DFP_GET_VERSION         SMART_GET_VERSION
    * o( a- ^: }9 X6 h/ P
  9. #define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND; v* d4 A5 Q, b2 `2 ~& Q; ]
  10. #define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
    4 S: Q$ n, y- R7 w+ V; g1 h- X
  11. ; M+ e; T' u7 [1 h) [
  12. const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令
    $ `: V1 |, p; h' g  _/ T4 P
  13. const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
    . u4 Y7 Z9 z, I; b
  14. : N9 s0 ]( D/ u7 T- P$ |
  15. const int MAX_IDE_DRIVES = 4;* H8 c5 ^: ^: c( x
  16. : I& \# @( a5 L% ^9 S4 r
  17. // SCSI专用变量, Z" X/ x% S1 I5 Y9 R1 x, E
  18. const DWORD FILE_DEVICE_SCSI             = 0x0000001B;1 V* `4 N3 ]: q* ]( D
  19. const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);/ ^0 M) o5 F% Z
  20. const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
    7 _' Y/ [% V5 ?
  21. const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;  s' e& d7 D6 k: Z% K, z/ I

  22. 6 n  S, H4 S1 `
  23. typedef struct _SRB_IO_CONTROL8 F6 K" }5 _" o/ ^* o4 r
  24. {
    6 t0 }' a; G9 U5 m2 S
  25.    ULONG HeaderLength;
    & n: E7 k/ S7 S
  26.    UCHAR Signature[8];
    : h% H3 Z" _# P. ^: E) F8 E
  27.    ULONG Timeout;
    , A8 i/ @7 B: U
  28.    ULONG ControlCode;9 Q" I& @2 y5 t; R9 l3 ^
  29.    ULONG ReturnCode;1 c) p+ V) ?$ T2 K+ t4 N
  30.    ULONG Length;
    - V2 L/ p" w* \5 k4 q% U
  31. }SRB_IO_CONTROL, *PSRB_IO_CONTROL;6 }. N+ k# R9 r" ]

  32. 4 o3 n$ U2 @! S( j& d
  33. // 读取的主函数+ w3 c2 v+ x" w  o' b
  34. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
    $ V$ }& E. J: U! a
  35. ) n1 n! H. d" K7 a" N" S  @3 H
  36. // 辅助函数
    9 W- b2 q( R8 _* g7 J1 m% ]
  37. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);! B1 V9 c& V% ?7 H6 h& z
  38. // NT/2000/XP函数
    ( M( a* t+ q3 j: q8 H/ q" k
  39. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);( b+ A+ G$ L/ r! J  C
  40. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
    + c( R2 |. C& _# L
  41.        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,2 C2 M0 [4 C4 q0 @* l5 g- @7 _
  42.        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
    + ]" P. e4 @' \/ ]* G5 Z$ O; k
  43. // Windows 9X函数- h; s9 a# q% a% Z% d7 Z0 e& Q' A! g
  44. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);
    " k1 m6 s- ^+ E) R" x7 R
  45. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,* M% @* }7 G" {/ L  v/ U2 [1 W9 f
  46.        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
    8 G! h/ }' [; H2 n$ K) f
  47. 8 j9 k( S2 ^' U* S
  48. // SCSI读取函数(for NT/2000/XP)$ H! q% M1 V) B
  49. String __fastcall ReadIDEDriveAsScsiDriveOnNT();8 v1 @, y2 s2 c. E
  50. //---------------------------------------------------------------------------
    7 }$ W' j7 d- |
  51. // ReadPhysicalDrive# Y0 L! ?! T  F2 d) H, ^
  52. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
    3 c# g$ Q$ ?$ k# I6 O* S+ [: X, ~1 n
  53. {0 ?7 U0 x2 Y! i5 |# Z/ L9 v
  54.    switch(Win32Platform)8 d! F' q! h# k
  55.    {9 p, _# j5 l2 _1 @
  56.        case VER_PLATFORM_WIN32_WINDOWS:
    - c. Z$ a! z8 S4 ~3 B
  57.            ReadPhysicalDriveOnW9X(pSerList, pModeList);% t8 U! f. [" N7 v% k
  58.            break;/ ?# n3 s: j( v; `
  59.        case VER_PLATFORM_WIN32_NT:
    6 _' E! G$ C3 H
  60.            ReadPhysicalDriveOnNT(pSerList, pModeList);
    % n; h2 ]2 B3 s- K. r
  61.            break;1 y: U- U0 H0 v, d; t2 w
  62.        default:
    7 v' V( U2 K0 @: @3 d
  63.            break;, V& w$ K) X2 [2 A
  64.    }
    + z  ?6 P, D8 D* c7 V
  65. }
    $ r  j/ I; k, A2 O6 _9 s( B
  66. //---------------------------------------------------------------------------
    8 L$ ^$ a& ?" Q' i$ g, I( `/ _3 A2 @
  67. // ConvertToString
    1 z7 u2 J/ @5 o$ u: ~
  68. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
      w% N0 i1 A$ l6 ^0 V4 j5 C+ C- o
  69. {
    " w& t& ?/ Z! e
  70.    static char szResBuf[1024];' ?) N+ f0 V7 k% i, M
  71.    int nIndex = 0;
    5 _+ [& E$ m, h# o" N2 v$ H# r" A
  72.    int nPosition = 0;* r& ^- \4 b. y6 [7 J

  73. ' J5 W$ O, |0 q6 c# @- `
  74.    // Each integer has two characters stored in it backwards0 r$ D  [/ [5 j* F
  75.    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)  m9 s1 R: l7 o
  76.    {  N: ?0 E' q7 o! K% q
  77.        // Get high BYTE for 1st character
    ) C6 ]4 S; x: w0 M2 f- d
  78.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);7 p1 `6 T, a+ j
  79.        nPosition++;& m4 D/ `- \2 k) S

  80. 7 g& ^) u- @# `" e9 k7 g; {7 A
  81.        // Get low BYTE for 2nd character
    ( E! ?# d9 w, ~% ^# k
  82.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
    6 ]( e6 C' t5 }+ S0 f4 s" c
  83.        nPosition++;! u/ L! G3 y, Q/ j
  84.    }- T+ W  H, N" \8 x6 Q1 H

  85. * W" @5 v8 l# d) ]6 b8 `6 ?5 L& u
  86.    // End the string6 ?: y' n7 i: a# w
  87.    szResBuf[nPosition] = '\0';
    9 @" }* p* k4 S( [( s

  88. . v5 U3 n5 ^4 B$ z
  89.    // Cut off the trailing blanks
    ! i, p& h, q2 X7 [  ?& W: v0 y
  90.    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
    9 l; c: \8 ?1 ~$ y3 }. m0 J4 Q5 _
  91.        szResBuf[nIndex] = '\0';  n7 Q  g1 g2 h: @2 L- K
  92. 9 r4 S9 I/ `# @7 @9 f
  93.    return szResBuf;
    ; {* y  `2 g, A. I7 t& h1 D) h
  94. }
    ' v$ s0 l. O1 {
  95. //---------------------------------------------------------------------------" ~9 h8 b, i! f0 |) c! D. d
  96. // Winndows NT4/2000/XP 代码
    * r& d* U4 m2 H! E) ?2 ?; r- L
  97. //---------------------------------------------------------------------------
    + \, R' d2 F- D# c- u( \
  98. // ReadPhysicalDriveOnNT7 z0 b- @; _" T
  99. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
    0 s/ J6 ], T+ q- _5 b
  100. {
    ( F. T- p2 `! ~  z, r% b: d
  101.    // 输出参数! D& n( @1 b  O8 q# k. h) J
  102.    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
    1 ?$ f% E3 Q3 \
  103. 9 ~4 s4 B* n4 r5 |
  104.    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++): X7 @; b) N% b9 n
  105.    {
    # @1 V0 G. i% D5 z) _. L
  106.        HANDLE hPhysicalDriveIOCTL;6 H& c+ f* c0 P  h5 n
  107.        char szDriveName[32];
    * P8 N0 O1 k5 `/ R4 f8 e, I- B

  108. ! T5 G, {' O1 E! o; F
  109.        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);# d  E$ z* _6 n# [9 D" n+ O  Y- U
  110.        hPhysicalDriveIOCTL = CreateFile(szDriveName,
    ' W; f# d$ N7 ~' O, t
  111.                        GENERIC_READ | GENERIC_WRITE,
      ]9 a7 S' t5 ^+ \* N( V
  112.                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
    0 O- q6 N6 |4 X  z0 I. `0 u
  113.                        OPEN_EXISTING, 0, NULL);
    $ J8 b2 F# \5 h3 O- k

  114. ' R9 u0 J) ?$ I. G" F
  115.        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)7 s: B! [# ^0 I1 Y7 x/ o
  116.        {
    * S5 w: \9 M" Q, u" m0 B
  117.            DWORD dwBytesReturned = 0;
    6 U0 Z" P6 H7 D2 d
  118.            GETVERSIONOUTPARAMS gvopVersionParams;5 \3 T1 I4 a# {$ q! U1 G  U2 [( `

  119. 5 c/ i# I: \4 ?
  120.            // Get the version, etc of PhysicalDrive IOCTL
    ( r0 l6 c1 R. ^+ q$ D9 d$ V4 J
  121.            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));" H0 ~+ Q- E% v+ L* I/ u  c
  122. 2 G' w( G3 ]/ z7 U5 s2 x
  123.            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,/ U2 G4 B. M0 k8 i4 ]$ J  v, d4 G* q
  124.                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),7 [% h- O) E9 ^) |2 g$ _+ }
  125.                    &dwBytesReturned, NULL))
    2 k7 [1 Z5 z4 l
  126.            {+ D4 }: S; r7 o& V
  127.                continue;
    7 G  l, F8 k3 O8 }, I% Z# V
  128.            }
    8 t+ X0 J) K+ X" I- t. a2 ]
  129. * v- ?" p& e, Z# X+ s# W
  130.            if(gvopVersionParams.bIDEDeviceMap > 0)  T% c% N9 ~7 I9 ^
  131.            {
    , z  s. N# M1 Y2 L
  132.                // IDE or ATAPI IDENTIFY cmd
    5 h7 o/ L  C' D" r5 j, _/ u
  133.                BYTE btIDCmd = 0;
    8 W! V, a: b! Q( i
  134.                SENDCMDINPARAMS InParams;9 n; G/ k, a; N% s. F) s1 n) S( T: F! M
  135.                // Now, get the ID sector for all IDE devices in the system.8 w2 V- p0 ]4 `6 N; \
  136.                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,/ N: [  `6 D7 S# l
  137.                // otherwise use the IDE_ATA_IDENTIFY command
    $ A- Z* c9 E/ a
  138.                // 具体所得结果请参考头文件中的说明
    9 C: m( G' c1 m3 X% ?
  139.                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
    ; O) Y! {' R8 t* b/ p: ^$ A
  140.                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;0 n  L1 ~/ ?& E4 w& X7 ~! m
  141.                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));' u9 E1 h8 ~" G0 p( Z4 }- j- C8 _
  142.                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));3 g8 b  P6 Q* h8 a; S

  143. 6 H& c5 k( j1 w7 F
  144.                if(DoIdentify(hPhysicalDriveIOCTL,
    ( }4 z) q( t1 u5 x/ M/ ~
  145.                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
    # |) F  ?. c, }1 G& w8 O$ ^
  146.                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
    6 ^4 K) _" y' z
  147.                {1 z4 f, j5 Y5 \) t4 C+ a% }2 w3 k
  148.                    DWORD dwDiskData[256];
      A# T& ?! v8 c/ A* U4 P7 W
  149.                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件2 e3 t6 r" O: v
  150.                    char szSerialNumber[21];
    % @' t& e. y! N: z# \
  151.                    char szModelNumber[41];4 @& k$ F. E0 _) m' k  |

  152. ) J' _( V  B6 m+ y! m- R% G' U' |+ q
  153.                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
    0 z/ D4 `# d+ g
  154.                    for(int i=0; i < 256; i++)9 @& k2 K' Y% u& a1 V
  155.                        dwDiskData = pIDSector;
    + m  r8 d% F2 p" V# T
  156.                    // 取系列号  |; h2 c' N$ s+ L
  157.                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
    + ?5 _& a2 j* Y
  158.                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));" a4 _2 t/ X& {# C2 f

  159. 1 X6 W+ X  P9 T/ \, U
  160.                    // 取模型号
    & f* d1 o% e7 ~( {* }1 t
  161.                    ZeroMemory(szModelNumber, sizeof(szModelNumber));
    # n) |1 w* `9 A4 f' A! i
  162.                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
    ; Q8 N: u& C" I* z% [$ J

  163. 9 a; j, S- ~8 M2 m8 `
  164.                    pSerList->Add(szSerialNumber);, d5 J( ?$ ^8 `& `
  165.                    pModeList->Add(szModelNumber);! r0 j4 x4 V% B& F" Y5 ]1 @& t
  166.                }% b* x$ ?9 [" ^, t( j% p
  167.            }& X" o, l. z, L9 J0 ~
  168.            CloseHandle (hPhysicalDriveIOCTL);$ Q/ J, S$ D) @! D  y2 h$ M6 J9 b% Z
  169.        }
    0 H4 _7 R4 J" x3 v" h
  170.    }  T$ n1 n7 i$ d* k
  171. }' h0 _+ v. ~# a% T8 @! U
  172. //---------------------------------------------------------------------------( [% p6 o: Z" V' S. G& x
  173. // DoIdentify9 D6 d# O2 ^+ A7 o/ A
  174. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,( t/ s, U; _9 M( i! ~8 P' w- k
  175.              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
    - b* J3 _+ C7 c8 j' V! m3 b- T
  176.              PDWORD pdwBytesReturned). A$ d) q9 Y" C! q5 b' M
  177. {
    ( V0 \  u; m7 z" V
  178.    // Set up data structures for IDENTIFY command.$ \* C! Z2 M2 s( C0 E" F
  179.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;) |) l/ W9 u/ s1 k! Q2 |2 p! G
  180.    pSCIP->irDriveRegs.bFeaturesReg = 0;
    # F( p3 _( m0 c& E  w1 ~
  181.    pSCIP->irDriveRegs.bSectorCountReg  = 1;
    4 I* A6 X7 ~1 |* r# j& R( M
  182.    pSCIP->irDriveRegs.bSectorNumberReg = 1;
    8 }- L0 ]1 i/ @% f( t
  183.    pSCIP->irDriveRegs.bCylLowReg  = 0;
    / a" D$ R3 x9 L0 }/ v3 J5 s) T" k
  184.    pSCIP->irDriveRegs.bCylHighReg = 0;- }$ v3 z: E, B$ @0 K+ M0 E- r
  185. 1 p2 k7 W2 S( T. d9 O7 X
  186.    // Compute the drive number.(主盘和从盘所对应的值是不一样的). ?5 v) k/ R( r9 [, h
  187.    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;# a; i1 {: r3 E( e
  188. ; ]+ B, S2 i& p3 l9 z( ?' s
  189.    // The command can either be IDE identify or ATAPI identify.
    ) ]9 G) ], N( h: ]6 b
  190.    pSCIP->irDriveRegs.bCommandReg = btIDCmd;# m6 t0 U( c8 I3 N# K$ h/ |& e% h
  191.    pSCIP->bDriveNumber = btDriveNum;) L" k6 `' D( |& q) Z, ^! d6 p
  192.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;3 x  q# b$ L! O, {% ?0 f3 @

  193. 4 d/ X$ x5 D3 k0 @5 @8 M
  194.    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
    9 q8 N1 a& ~; l7 S' M
  195.           (LPVOID)pSCIP,: O1 o9 \4 w( ?  l, I  I# B& b
  196.           sizeof(SENDCMDINPARAMS) - 1,0 @- f& t# c$ k4 ]
  197.           (LPVOID)pSCOP,
    6 x- I# \7 h) F; b) V* I+ |
  198.           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,5 U6 N0 C; R1 w) t
  199.           pdwBytesReturned, NULL);
    $ n; P9 _7 T1 e' n8 i+ e
  200. }
    7 v/ e  [! f, h7 v' z; \
  201. //---------------------------------------------------------------------------
    5 ]/ ]# o& k' P# w
  202. // Windows 95/98/ME 代码
    " n/ d/ C/ y1 x! ]" b. R, y7 s
  203. //---------------------------------------------------------------------------# t4 A2 ^, K2 ^. {, c4 d* s
  204. // ReadPhysicalDriveOnW9X
    4 e2 a$ a& S6 o. M' y5 g
  205. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)9 p: ]2 U3 o5 s- {3 K
  206. {
    , h0 }5 c5 z6 T. ?9 H/ M$ L; y
  207.    WORD wOutData[256];
    " |, a* Y. t3 d! M( c5 L( \
  208.    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);# ~7 l5 ^" x$ x0 y2 e
  209. % N8 g8 ~9 V2 O
  210.    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。  l3 e. d/ t0 B& K4 ~6 F
  211.    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以8 w) X* j$ R; T4 d; |7 |
  212.    // 避免蓝屏的出现。(期待高人能指出原因)
    + d0 B9 H8 b3 x$ h7 [' z0 s6 O
  213.    for(int nDrive = 0; nDrive < 8; nDrive++)
      h" M$ r8 s  D! Q: {
  214.    {
    % }, z1 W- L% \+ n- r$ B
  215.        WORD dwBaseAddress;
    ( Z) S' y0 ^) P) U- s! T
  216.        BYTE btMasterSlave;         // Master Or Slave
    * a9 b' S  y( e, Z
  217.        bool bIsIDEExist;$ o% z  X0 N5 z4 ^$ C
  218.        bool IsDiskExist;
    2 w: s1 C" w+ U: t
  219. 9 E* f- O  e7 y- {) b3 W
  220.        switch(nDrive / 2)* b) P5 i" k# ^: \0 [2 X
  221.        {2 s- v1 m  \5 W9 v# ^! P6 d
  222.            case 0: dwBaseAddress = 0x01F0; break;
    8 i: v+ P  n3 b7 i& F; B: b* _
  223.            case 1: dwBaseAddress = 0x0170; break;1 \  Z. S. W9 t' k, w$ `
  224.            case 2: dwBaseAddress = 0x01E8; break;
    9 T: X. {7 Y; `+ y+ o- V+ _
  225.            case 3: dwBaseAddress = 0x0168; break;
    " x4 H  D) v+ J6 b2 j
  226.        }
      f0 A; C( n% M2 V8 Z* k- Z% H0 q

  227. ' V$ D; F$ o0 M! C
  228.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
    & w" F6 Z: f/ b5 P4 I- M

  229. " i8 s" b2 z. Y6 J  ?( O6 M
  230.        // 进入Ring03 @8 E3 J0 c5 o1 H
  231.        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
    & z- c% M% S  V0 D% ^
  232.                bIsIDEExist, IsDiskExist, wOutData);
    $ @* `. b- y3 [2 ^
  233.    }7 Y/ n/ _( m7 c( m
  234. ' c2 `- u8 s9 c- E6 o( Z1 ~
  235.    // 开始读取" D: c3 U% ~6 _3 K+ R
  236.    for(int nDrive = 0; nDrive < 8; nDrive++)! T* Y- M4 X/ d6 {. E
  237.    {
    ; G- y/ @& N( k) T: l
  238.        WORD dwBaseAddress;# u1 i! c+ ]" m' e# y
  239.        BYTE btMasterSlave;         // Master Or Slave6 o( p5 L' o: f+ t$ _! }' h& T
  240.        bool bIsIDEExist;2 s  f( B7 Y/ R  y
  241.        bool bIsDiskExist;
    7 x1 X. ]$ z, b8 K8 `( o9 z5 J
  242.        switch(nDrive / 2)
    , U# t- G: u8 j  d9 x( |5 e6 b
  243.        {* ^) S( Q6 u; ]
  244.            case 0: dwBaseAddress = 0x01F0; break;
    7 W. ~4 q; c" v& p2 Z+ J, u
  245.            case 1: dwBaseAddress = 0x0170; break;
    1 R- ~' s5 j4 r
  246.            case 2: dwBaseAddress = 0x01E8; break;8 B4 R: \  {# Y: S9 `
  247.            case 3: dwBaseAddress = 0x0168; break;& P3 s. Q; A5 q: g: g; n) Z
  248.        }$ w  a8 C1 J; l  n/ `; D( Y* |

  249. ; j' O8 L! k" S0 q
  250.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
    ) P* C" w" ^! H# ]
  251. 0 t- w3 s7 l. Z5 ]! J
  252.        // 进入Ring0
    ' O/ k) d2 x: G9 b' ?7 V+ _
  253.        bIsIDEExist  = false;
    - A4 c8 _7 s" r. z# c1 A# g7 t# z2 R
  254.        bIsDiskExist = false;
    , ?4 A8 m$ T- u. A, d' Y: K
  255.        ZeroMemory(wOutData, sizeof(wOutData));# f' f' o3 A7 h; s

  256. ' g! p( Z# i7 r5 ?+ a) M' m; x% b
  257.        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
    ' P& S  j0 d* C
  258.                bIsIDEExist, bIsDiskExist, wOutData);
    * @* [, |; J. c" t9 n( C! H* g) C5 ^
  259. , f4 d8 _- o- |3 k+ `" d
  260.        if(bIsIDEExist && bIsDiskExist)
    / a- u% q+ S$ ^) g* a( j! m
  261.        {/ n4 J* h' P% z6 U! q9 f) H/ C+ K! d
  262.            DWORD dwDiskData[256];
    & C, d$ y/ U6 n/ `
  263.            char  szSerialNumber[21];! L" H+ Q; C  n
  264.            char  szModelNumber[41];2 O2 m& D* U9 t# ~' A. l

  265. 1 f( ^/ Y( m# Q% E2 U9 P
  266.            for(int k=0; k < 256; k++)' B1 e% ]: c) a+ x( h5 @& `
  267.                dwDiskData[k] = wOutData[k];* H. {! Z3 r8 X8 n) j/ E* I
  268. / V3 W. T2 }4 J4 Y2 B9 M
  269.            // 取系列号, N4 i5 Q  V/ _$ X( |
  270.            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));4 r3 O! a5 p$ r- z
  271.            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
    3 o8 R9 x- ~9 [6 i2 }
  272. ' [! O& ^. J/ }- r, Y/ c
  273.            // 取模型号# b1 E6 _  t, e6 W- J: q* ?
  274.            ZeroMemory(szModelNumber, sizeof(szModelNumber));
    ! |* h+ Z( ]- l; w: |' G: C
  275.            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));4 }+ J7 \! r5 k. v6 }

  276. . c3 ^4 X3 q) Z1 Q6 x
  277.            pSerList->Add(szSerialNumber);
    % J& ?: i3 ^2 G6 ~# x6 [* }
  278.            pModeList->Add(szModelNumber);- o' v( g$ M9 l4 q
  279.        }
    7 m& `: r+ ^+ J
  280.    }
    5 ~1 C. ~; N2 }9 H+ _. C
  281.    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
    ( x) V& q1 Y6 S  r+ s( y
  282. }5 j& ^, @5 e' A, c* n4 y
  283. //---------------------------------------------------------------------------
    0 r3 g$ B! i6 K9 s% `$ d; z
  284. // ReadPhysicalDriveOnW9X_Ring0()1 F5 X2 [( \) y! ^6 e7 {+ S$ Y
  285. //
    & a: ]& o0 y$ g7 h8 M0 D. J; M) h- u
  286. // dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h; c7 @5 c0 \2 M, Q) m" H2 c: f3 {7 [& v
  287. // btMasterSlave = Master(0xA0) Or Slave(0xB0)& R+ ~5 K2 D7 o/ E
  288. //---------------------------------------------------------------------------, i! e7 B. |1 B9 ?) }8 Z$ f, \" @
  289. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,6 A7 Z6 `7 V' P
  290.        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
    $ _* X. T/ z& d. R
  291. {3 H, j. O. F" d1 o
  292.    BYTE  btIDTR1[6];5 D6 T: _2 [' p& F+ q+ s  U
  293.    DWORD dwOldExceptionHook;
    * h9 j# p+ ^; _# `, J
  294.    const int nHookExceptionNo = 5;- a! i5 @. ~: k7 i  V% ?
  295. * Q0 N) ~% s. w) `# ~, v: }0 X  }
  296.    BYTE  btIsIDEExist = 0;
    7 f7 S( X( H0 r" r& H
  297.    BYTE  btIsDiskExist = 0;% i/ K9 v, q( V8 Z7 y
  298.    WORD  wOutDataBuf[256];
    1 Q* y1 x% t1 z: [, F

  299.   R1 N' w4 F: o/ t1 G  ]8 ?5 S9 X4 B
  300.    BYTE  btIsFirst = (BYTE)bIsFirst;- E1 r8 N$ v$ |

  301. " t! R( {8 l) n! b
  302.    const BYTE btBit00 = 0x01;, p) ]) H$ `9 A# D' K$ C
  303.    // const BYTE btBit02 = 0x04;; l" f* t- g! R# N  l3 ]( u. E
  304.    const BYTE btBit06 = 0x40;9 J# b8 D9 H7 `
  305.    const BYTE btBit07 = 0x80;) X6 U! V+ B0 F/ D
  306.    // const BYTE btERR  = btBit00;
    . c- Y- Y" v0 c4 e; c( t
  307.    const BYTE btBusy = btBit07;
    " `5 k4 ~5 W# N" t( L1 Z( s) z
  308.    const BYTE btAtaCmd   = 0xEC;1 x' }( `! u8 t0 z) b
  309.    const BYTE btAtapiCmd = 0xA1;: G# V- q4 O5 I

  310. 7 i4 N  q: t/ ?& S3 D! ^' L* p
  311.    __asm
    , g* c& G- r  D' K$ K
  312.    {. ]8 i. H- u1 {1 l- N+ c7 }
  313.        // 必须先执行这条语句
    ) k6 J2 j- r5 M! W! X/ {) p  E0 S
  314.        JMP EnterRing01 i* w* }4 X2 a+ c0 L7 P
  315. 2 R; i$ p- M( F1 u$ V& E* i% Y* H6 K
  316.        // 定义过程
    - R# F- K, ^8 n# K( [8 I" B# T! I! `
  317.        // 等待IDE设备直到其不为忙为止
    ; r( \/ w" v& A3 Z2 L- ]: o
  318.        WaitWhileBusy proc
    9 ]; `3 |# _" A0 R  M1 j% D; m

  319. 4 Q1 y! k6 {, |+ k8 u0 [" i/ u5 H
  320.        MOV  EBX, 100000) n" N8 H2 {0 d) \- ]
  321.        MOV  DX, dwBaseAddress
    . V" q: A: X: F# T0 v! v
  322.        ADD  DX, 7
    ; t- G8 O) `/ q; K( D, l

  323. , v( O6 }9 ^; ]3 ]$ p
  324.        LoopWhileBusy:
    + D$ A% e* b3 k( P  K4 J% }- k% j
  325. 3 d% u- h0 D0 Q' k3 Q
  326.        DEC  EBX/ N3 i  b9 }: L) \; T# k- f
  327.        CMP  EBX, 0
    $ l4 v+ h7 Y1 q6 m2 L
  328.        JZ   Timeout
    / }! ^: D; H5 P
  329.        in   AL, DX" d4 K" m: r  B% t' g4 \8 i
  330.        TEST AL, btBusy& s3 Y) \6 b5 C
  331.        JNZ  LoopWhileBusy+ S8 p; y# e5 |6 G. ~; n& l
  332.        JMP  DriveReady/ k/ V+ n" F5 T  g( ]
  333. ; d; n/ V9 w; A( l! O) @% H
  334.        // 超时,直接退出
    7 L8 ~) {& s( G0 b7 A4 L# `
  335.        Timeout:, c# O3 q2 Y$ w' P1 ?; f
  336.        JMP  LeaveRing0
    ; E1 }) F) x4 q( Y% i+ S( z
  337.        DriveReady:
    # ^- B* a7 j5 I& o. k7 X2 d
  338.        RET* Y; l3 H$ q8 |! ~! i! h
  339.        ENDP   // End of WaitWhileBusy Procedure% J$ G5 d! E: ~4 ]# F# O' ~3 ^2 a- M

  340. 8 D) @+ {. A1 u
  341.        // 设置主盘和从盘标志/ _8 [+ e, a  i" U1 C$ |
  342.        SelectDevice proc) y7 s: y' b+ k! I
  343. + k+ H& Q/ _+ G! T
  344.        MOV  DX, dwBaseAddress
    , Q0 o  ~" C" q
  345.        ADD  DX, 6& Q5 ^$ J: T" I
  346.        MOV  AL, btMasterSlave
    ( a8 a% B5 F4 t8 {$ X( u/ S7 e: `5 x
  347. & R( C- e! H1 _8 D7 P
  348.        out  DX, AL
    7 k4 g  o% t" @8 Y0 c
  349.        RET
    : Y2 N/ k, q& |

  350. 1 o  F' A$ o, j, K9 @8 v" J
  351.        ENDP  // End of SelectDevice Procedure
    3 o2 ^6 B9 ]3 Q  Y' Z2 i6 S

  352. # q4 i" Z3 Q" K7 G/ r, v3 v/ A
  353.        // 向IDE设备发送存取指令
    $ ]2 U" Q+ Q+ ]$ j# |4 _
  354.        SendCmd proc
    . W+ H8 v& \. z) x* N: S4 V0 J
  355. 3 L, ^8 B2 m4 G& X% h& K- s, Q1 u7 d
  356.        MOV DX, dwBaseAddress9 {/ L, ~9 k1 B& d3 k6 |+ c
  357.        ADD DX, 70 j" U5 I6 c- k9 l2 v
  358.        MOV AL, BL // BL是主从盘标识,在过程外设置0 z# r5 v1 j3 \/ ?! E; K
  359.        out DX, AL
    ' @$ f6 z$ N6 u8 E
  360.        RET1 F* H) f# |, O
  361.        ENDP  // End of SendCmd Procedure
    ) {6 ~. l+ V8 M$ {* H1 g. p1 w/ r3 e0 h

  362. - U; ^- B2 e  X1 J% j1 ]. ~2 W
  363.        // Ring0代码3 l* Z- z' L, z3 `3 u
  364.        Ring0Proc:& r% \5 ~; f4 }. A! p: b
  365.        PUSHAD
    8 B' y# |1 Y  D0 V/ T! W9 I
  366.        // 查询IDE设备是否存在& m  Q9 ?- ?& O! u; U2 d$ S+ m
  367.        MOV DX, dwBaseAddress
    8 M: I2 ?+ P5 B7 }
  368.        ADD DX, 7
    # t. t$ U/ f2 k# s$ t0 C% z
  369.        in  AL,DX  Q9 _% J7 v4 p- c( _
  370. 1 d% k4 b* a0 {: K
  371.        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
    3 r0 _( Q4 n; h6 F: c. m7 h) N: ]
  372.        CMP AL,0xFF/ z7 C) z* I- P" k6 e  j
  373.        JZ  LeaveRing0
    # O% f9 x8 e- Z9 t9 R
  374.        CMP AL, 0x7F5 f1 b0 u: }9 }5 k, n
  375.        JZ  LeaveRing0
      w6 h' E% v* d+ s
  376. 6 [( V6 j6 H; b9 Q/ s& h+ O
  377.        // 设置IDE设备存在标志" \, R2 J! x; a, u8 q3 o/ }
  378.        MOV btIsIDEExist, 1
    : }0 ~: f+ w- \0 g
  379. 7 f4 A/ e# q7 Q0 a' y! U
  380.        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
    , W4 c5 E5 g1 w# T6 E
  381.        CALL WaitWhileBusy3 e4 ~* M; G" @9 H& b4 o$ o
  382.        CALL SelectDevice7 x$ o' C* }" v, X

  383. ; [1 E( S! z; F$ s5 I, o$ D& I5 D: p
  384.        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏; u2 E. B$ W& F* ^" ]% u, ?
  385.        CMP  btIsFirst, 1
    6 `& g/ r7 X5 ~3 S  J- b; i% a
  386.        JZ   LeaveRing0' D; c+ K! _, V- r8 x

  387. 7 D* K* u9 f3 U3 w: q
  388.        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
    ; {: q8 t7 N9 n9 I0 M# Z, w- g/ ~: H
  389.        CALL WaitWhileBusy
    ! q$ T1 ?- h* z! X2 e0 Z
  390. ; ]* l3 J$ W3 a% x
  391.        // AL的值等于cBit06时,不存在驱动器,直接返回- l$ ~5 o5 }7 N
  392.        TEST AL, btBit06' h0 a7 R' A) U0 I, _9 u
  393.        JZ   LeaveRing0' k$ n, q$ A4 U
  394. 5 V- S5 E% S9 L. E8 I0 l: E: f. K
  395.        // 设置驱动器存在标志. v$ r& l5 h: `1 B  }# e
  396.        MOV  btIsDiskExist, 1
    0 e+ z! y7 c* p0 ^$ N  f6 R% [$ _
  397. " X1 c8 u# c4 a
  398.        // 发送存取端口命令% O" m$ f. L  |4 w: f- j8 C
  399.        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,, N: I& R: T1 x
  400.        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
    - Z7 m/ N* p7 F* P% E/ Q$ x
  401.        CALL WaitWhileBusy; z3 M! |# v$ x0 o
  402.        CALL SelectDevice    // 设置主从盘标识1 r4 ?0 g/ @# ^* N: u8 k
  403.        MOV  BL, btAtaCmd      // 发送读取命令
    2 |1 N$ _/ A  N8 t* V) _+ N
  404.        CALL SendCmd: ~( G4 m) A$ H% w2 }
  405.        CALL WaitWhileBusy
    . Z1 F7 ?3 o! {. G
  406. : P: ?* s; v# z5 ~3 E: J: _4 v# P) k9 e
  407.        // 检查是否出错
    ( C+ I& W! A  L6 p
  408.        MOV  DX, dwBaseAddress
    $ z! Y) S$ q1 S: T. J
  409.        ADD  DX, 7
      u/ V; s! C/ Z8 R" ]) b

  410. 3 q# v- Z2 L* ~  s) ~
  411.        in   AL, DX
      k" K7 ]+ m. r* a3 i' Q2 c
  412.   D! u: W. m: @, `2 i% ]) O
  413.        TEST AL, btBit00' o2 |' p0 K% U4 X( O* a2 W
  414.        JZ   RetrieveInfo   // 没有错误时则读数据
    4 S" p# X& h! F3 z5 F3 x0 P! e
  415. 5 D2 }) |6 `1 W+ B2 ^  b
  416.        // 如果出错,则进一步尝试使用ATAPI设备命令
    / F, z+ d! U/ g, {
  417.        CALL WaitWhileBusy
    % w, Q* `% M9 C8 s2 \$ v
  418.        CALL SelectDevice
    ! J9 v! c2 ~8 g, \
  419.        MOV  BL, btAtapiCmd
    / ^/ q  s( l5 G7 r" R# J+ L  H
  420.        CALL SendCmd8 o* J) t/ ]& }! w$ X/ S
  421.        CALL WaitWhileBusy: n  }8 x5 L5 v0 J! f

  422. : `" a0 {' J$ p- H* c* C: s
  423.        // 检查是否还出错, K* ]& \4 \' e* a9 l- B9 h0 @
  424.        MOV  DX, dwBaseAddress5 X/ t. v$ H4 `
  425.        ADD  DX, 78 ^' K3 I: x. t" e
  426.        in   AL, DX& }4 m( i% |0 q5 K( g
  427.        TEST AL, btBit00  {3 i# B0 U6 n0 Y, P
  428.        JZ   RetrieveInfo   // 没有错误时则读数据
    2 p: D- H. M& k7 t1 }2 u& D
  429.        JMP  LeaveRing0     // 如果还是出错,直接返回) U6 z  Y6 r# N4 y" \8 p5 H
  430. 3 R9 t& a- G% w- ?& |0 t; G. I
  431.        // 读取数据* V5 \5 ]; Q9 w5 w/ \" y( b
  432.        RetrieveInfo:
    # Q% B* @) X+ a6 B0 c

  433. # Y1 Z* N; z) h1 d  [7 B
  434.        LEA  EDI, wOutDataBuf
    . n- t9 o: F) j8 r6 z/ f
  435.        MOV  ECX, 256
    1 X9 K: ~" H& y+ K2 F
  436.        MOV  DX, dwBaseAddress  U6 n, y( g$ b1 j
  437.        CLD6 M/ g0 B- n5 V4 q7 H

  438. # H: O$ S4 N' ~* @6 J
  439.        REP  INSW( w/ z* D# h+ W3 Q) Z
  440. 3 t& d7 y8 G0 F& g; s
  441.        // 退出Ring0代码
    * A. b3 @) d: ?( w; c
  442.        LeaveRing0:. Y& ~6 l4 V, Y! W
  443. * W3 a. ]6 j1 w8 G* `6 A
  444.        POPAD# J2 [. J" y: r6 P; x% I
  445.        IRETD
    # U8 c! \3 I2 ?: I/ {& I
  446. % K- {  N! l5 M3 t
  447.        // 激活Ring0代码( {% A8 I; p6 \: |' `8 U; D
  448.        EnterRing0:
    + e" g6 }( N  v- _) M8 W% s

  449. 4 Q  W, k/ X: p: [% l' p: Q
  450.        // 修改中断门6 l& G0 l8 u) J/ c
  451.        SIDT FWORD PTR btIDTR1
    8 \/ c% V9 a& F/ S9 k* M4 g
  452.        MOV EAX, DWORD PTR btIDTR1 + 02h
    + p; t% I# }: V5 l5 c6 H- r
  453.        ADD EAX, nHookExceptionNo * 08h + 04h
    # S, K! g# y# z4 M& o0 n
  454.        CLI
    ; h. \9 c7 x, {0 c9 T7 b9 D) o
  455. 3 Y. z: x) p1 @
  456.        // 保存原异常处理例程入口# T, g( ?  t+ f5 i* B$ t  a' T
  457.        MOV ECX, DWORD PTR [EAX]
      Q% x  j, W. G2 D8 p# Q
  458.        MOV CX, WORD PTR [EAX-04h]7 ?+ ~! j* G8 M0 b, n- x# I9 G
  459.        MOV dwOldExceptionHook, ECX
    : v& r, e0 C& L2 Y1 H  {1 S& u
  460. 8 _. u/ _, E, D8 K3 Q
  461.        // 指定新入口/ S3 {6 H- A' i) C
  462.        LEA EBX, Ring0Proc
    / {$ y3 ]( A3 v0 O$ N7 _) G
  463.        MOV WORD PTR [EAX-04h],BX' A1 z( b: R) c5 O
  464.        SHR EBX, 10h* d  h; l$ E. W
  465.        MOV WORD PTR[EAX+02h], BX
    % A* d7 b0 z- q: G

  466. 9 k4 d) O8 V. U1 x
  467.        // 激活Ring0代码* Z4 n2 o4 B! O' \+ b, F- J( @
  468.        INT nHookExceptionNo
    ! Q6 k/ b% p4 t3 A; m

  469. 4 C9 k' h9 T- ~
  470.        // 复原入口
    2 o# {" E+ t1 D
  471.        MOV ECX,dwOldExceptionHook; g' A# T0 M. L2 ]5 M
  472.        MOV WORD PTR[EAX-04h], CX' F' l9 @! D0 `( a4 n2 d
  473.        SHR ECX,10h6 W+ n' z/ X7 a0 R4 |& s5 e
  474.        MOV WORD PTR[EAX+02h], CX
    5 ?, O6 N, ?) a6 J/ Q
  475.        STI; \; p: W% `+ B% v9 R5 o
  476.    }
    8 H; B$ ~$ G0 H! D! H9 N4 e
  477.    if(!bIsFirst)
    . V" s: Y6 H" a3 B4 p+ f: W3 R' `9 k
  478.    {5 x6 W$ B& Y/ I, T
  479.        bIsIDEExist  = (bool)btIsIDEExist;( @3 Y: l" l7 N( z) B! T# E2 X1 M4 S5 a
  480.        bIsDiskExist = (bool)btIsDiskExist;
    1 W: R8 e- c7 N
  481.        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));# M9 Z5 [; K6 p  Q) J- b
  482.    }- Y. E! e  ]9 ?7 [
  483. }% ?; J& e4 \: m7 T0 ]
  484. //---------------------------------------------------------------------------# a- @7 r3 b7 x. A/ f; Q
  485. // 调用方法:
    + N: Y& @. f3 k* L
  486. void __fastcall TForm1::Button1Click(TObject *Sender)
    % ^0 o- U+ y% F: k! ]1 B) d: T* t; Z
  487. {
    # S5 y" q/ {# D" r5 a1 N$ x' E
  488.    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
    8 N$ S) P8 U+ J) ?8 W4 l6 m
  489. }
复制代码
发表于 2005-8-15 01:00:45 | 显示全部楼层
晕乎乎。。。怎么看8 洞阿
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-11-15 01:43 , Processed in 0.020525 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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