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

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

[复制链接]
发表于 2005-8-11 11:42:04 | 显示全部楼层 |阅读模式
  1. #include <WinIOCtl.h>' C( j0 M& B4 b" Y$ [- F# ]
  2. #include <stdio.h>
    2 H. a: B, |2 c% ~+ P' o
  3. ( U& G' X7 O; ~% z! m
  4. #pragma inline  C& ]- _) y( E' d3 C4 u
  5. //---------------------------------------------------------------------------
      r+ t- N& ]. `9 N5 e" l
  6. // IDE NT/2000/XP专用变量: Z3 Z4 O% W. R+ a. E% `& Y
  7. #define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
    ' x3 N' X# w0 z. l
  8. #define DFP_GET_VERSION         SMART_GET_VERSION: Y- M) y8 `' L; p) w/ j
  9. #define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
    " F1 d: w4 {* L9 g
  10. #define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
    3 X# I# V9 d4 b

  11. * W& ^+ n* c; g, z
  12. const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令
      B* X% ?; E+ K
  13. const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
    / b# W9 X% e& y

  14. 5 @& I# }, |' A* y! }$ q- R
  15. const int MAX_IDE_DRIVES = 4;
    1 I6 G; e- c0 f, k4 y
  16. 6 S5 L8 h: n) x( R# r: a0 f
  17. // SCSI专用变量
    # a% |8 s/ b1 k  w7 c
  18. const DWORD FILE_DEVICE_SCSI             = 0x0000001B;
      K1 l2 k$ |, x8 p6 q/ p7 w$ h+ w* }
  19. const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);- q, D3 B% a: M$ ]$ g
  20. const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition5 S- _1 N" _5 w* o; X+ y
  21. const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;. W% i- s$ s* ^. k2 E: e

  22. 6 ^8 C5 E, X; }) i! Q5 q
  23. typedef struct _SRB_IO_CONTROL. a5 @3 o) r) ?* t' A
  24. {
    % g; G0 A/ {0 r/ I8 i0 G: u  K7 L
  25.    ULONG HeaderLength;, N+ l6 R3 G5 B9 [- W. {! n! k
  26.    UCHAR Signature[8];
    $ u3 R- f6 v& L0 o
  27.    ULONG Timeout;
    & {+ @1 `4 F7 K5 l- P, q+ ?1 y# b
  28.    ULONG ControlCode;
    $ v! Q; r2 T. _6 J
  29.    ULONG ReturnCode;1 u6 O5 W2 K+ o# a; S
  30.    ULONG Length;
    $ C1 D  {" ^; |! i, V* h3 V8 l) J8 d
  31. }SRB_IO_CONTROL, *PSRB_IO_CONTROL;
    " t4 i% R2 d# k4 t

  32. , [' M+ B: _. b  W7 P, a. i
  33. // 读取的主函数) p8 Y9 R& u4 j
  34. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);, U# E: L: G/ I9 [. A

  35. : T5 e9 {5 o# O- F+ J
  36. // 辅助函数" s/ E( `+ Q. h' ^0 p' k. `( l
  37. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);0 d4 C1 V. \7 @# c# ^" J9 u
  38. // NT/2000/XP函数% i6 P& W) ~  h) s" o& {% ^
  39. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
    5 F( I* V7 t0 ?8 V/ f
  40. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
    7 P9 v! ]' E" M& E
  41.        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
    / G1 v5 t% j8 \7 `- w
  42.        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
      U5 k! Z8 ?8 W
  43. // Windows 9X函数
    ; J4 e+ I; Y+ a
  44. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);1 D$ l; e8 G5 R9 ]; T: C
  45. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,; b4 T9 m" K' o8 c2 Y
  46.        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);+ A; e, j' b, o+ r6 W) _
  47. 4 |5 J, P# \. A3 U. }# `1 N
  48. // SCSI读取函数(for NT/2000/XP)
    " p7 Y. S1 O4 J. {
  49. String __fastcall ReadIDEDriveAsScsiDriveOnNT();
    ) Z8 m" O2 M/ u( q  @& ]
  50. //---------------------------------------------------------------------------
    . q1 l/ l. f( N/ [9 U
  51. // ReadPhysicalDrive0 S  `% i- r# J2 m% o+ v: B' Z
  52. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)" l- @8 i6 Q( N0 h2 J5 a3 u
  53. {# h5 I! e, p  S' {7 Z6 \& r2 Z
  54.    switch(Win32Platform)
    4 h" _* R- z% \# o) `' a% m
  55.    {
    4 E  `9 }) F5 B; F
  56.        case VER_PLATFORM_WIN32_WINDOWS:' F- k8 _- ~- B& u' \- x
  57.            ReadPhysicalDriveOnW9X(pSerList, pModeList);3 \( F. J2 J4 j. U* x& a: H
  58.            break;$ m$ E, L8 J! `; F2 V. u
  59.        case VER_PLATFORM_WIN32_NT:
    ; u) K0 ^5 p1 z& q6 t+ e
  60.            ReadPhysicalDriveOnNT(pSerList, pModeList);
    . K8 n( @2 E4 b
  61.            break;
    0 i* W  v4 E: ]0 Z8 J
  62.        default:3 A' C! u) p% ]9 _
  63.            break;* Q1 }+ A1 ^' r! J. a3 K/ V/ l
  64.    }8 C. ~' l: h5 c1 i) k, P- \& l
  65. }
    # }3 _3 p8 n( W1 T
  66. //---------------------------------------------------------------------------
    ) [2 ?  R# v4 Y/ q( Z% w$ S; S
  67. // ConvertToString% _* _3 h2 w5 p: p5 I# i4 {
  68. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
    3 @6 P  A  b2 A
  69. {' M1 S: E: x$ K: C2 N
  70.    static char szResBuf[1024];) J  I7 ~6 I6 M; }' P
  71.    int nIndex = 0;* A# V/ E! a& C6 q
  72.    int nPosition = 0;& |1 `) E! }% s- @0 |
  73. 9 D# |1 n* `. ?) U( j9 ]
  74.    // Each integer has two characters stored in it backwards
    7 x) `1 k8 f4 H
  75.    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
    2 R3 m2 q# G6 p  W( V  u, E2 a
  76.    {
    $ D8 W2 l4 {% U
  77.        // Get high BYTE for 1st character
    " @) k) Z: k3 ~
  78.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);& F! I* H1 ]: l# H$ g/ O
  79.        nPosition++;
    : z5 e8 p4 ^# h

  80. & d- W% \  w1 y
  81.        // Get low BYTE for 2nd character
    , i% j/ Q5 g& X1 K- `4 X
  82.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
    1 f1 o+ O  P5 S! X- ?
  83.        nPosition++;
    ; f0 T( \( }* Z0 o" ?4 l" y1 r
  84.    }8 d4 |- E$ P# ?
  85. * ?1 w! x) C9 o4 U9 r
  86.    // End the string
    1 @$ I' E1 Z! M- Z% T- m3 \: x+ b' Q
  87.    szResBuf[nPosition] = '\0';
    : H7 ]# f) I$ @2 _) f  S

  88. 5 A( \1 o5 {/ V9 l' k
  89.    // Cut off the trailing blanks( c5 j+ Z1 _2 ]. v9 r
  90.    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
    % f% I( c$ W( {- r# ]) p9 k8 Y
  91.        szResBuf[nIndex] = '\0';6 W7 g, ]7 O; A9 C, ~7 I$ j# G
  92. / N  Y/ O  n$ i6 S8 c( x/ y  D
  93.    return szResBuf;
    % x' l9 s( }! R2 w
  94. }& e- v' _! q) h+ ]! S
  95. //---------------------------------------------------------------------------: @/ k% f, g: m( Z* B
  96. // Winndows NT4/2000/XP 代码$ M# ]- k  K8 X* q3 T9 V
  97. //---------------------------------------------------------------------------3 r0 d  N4 [* b+ g
  98. // ReadPhysicalDriveOnNT- X' S- m/ u/ T9 J, A
  99. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
    / c7 X5 d; z( L( j& @
  100. {, M8 `% o" V: O4 I3 F0 X+ X
  101.    // 输出参数
    ' \  ]: U( }+ i. F& D5 @
  102.    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
    - H) J0 E( Z8 O" ^  O. s# E9 ]! m
  103. * r1 n0 f" v- l
  104.    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
    - o+ d, {& K) p: P: j) p% ~1 k
  105.    {
    7 E$ s2 r$ ?6 T$ R7 I, Z
  106.        HANDLE hPhysicalDriveIOCTL;7 X; \+ e% M! }3 A0 ~( J- U  t
  107.        char szDriveName[32];2 K! G# E2 s' h+ g0 r3 W
  108. 0 P) l( d' @# b5 M& o
  109.        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);5 {( o7 G3 o: W8 F, h' G4 q
  110.        hPhysicalDriveIOCTL = CreateFile(szDriveName,
      e6 q" g3 m8 j- q4 j# k
  111.                        GENERIC_READ | GENERIC_WRITE,
    : }# W' {2 L! S+ R/ E' m
  112.                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
    $ K5 U- H% Q- q* K4 Z4 k  b# O
  113.                        OPEN_EXISTING, 0, NULL);
    2 M: Y: e3 R, g; ^

  114. ) a- Q3 `" `- Y) m4 r0 s, E
  115.        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
    " |- x# \% |5 s5 j
  116.        {
    % j0 N  d* e: Z  |8 `3 n
  117.            DWORD dwBytesReturned = 0;/ `* h% y& M2 G# \
  118.            GETVERSIONOUTPARAMS gvopVersionParams;# }5 J$ F, L9 Q/ ?2 j% f. D; p8 b3 U

  119. ; K+ m: ^7 b% c1 u" L
  120.            // Get the version, etc of PhysicalDrive IOCTL" M9 [: \8 ~3 n& N# e4 U
  121.            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
    ! K& t- g( W. z  D9 u( t8 _

  122. ) a* P+ y% _; m/ t6 Q4 x1 x# Z
  123.            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
    ' u/ q. H- x6 z2 |$ Y
  124.                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
    $ i" H7 U" g% f" y; E* a: X5 B
  125.                    &dwBytesReturned, NULL))# f2 \" G1 M1 K6 D  b( N3 q
  126.            {
    # l  I# L$ z; |
  127.                continue;
    ( v5 K5 O9 V& S
  128.            }0 L. n0 p5 t2 _! T( K7 i
  129. ! W  e) R' m0 S5 p3 U+ j
  130.            if(gvopVersionParams.bIDEDeviceMap > 0)$ G- e; ]6 U" ^1 e; D/ o" b
  131.            {
    $ A8 x& U6 b3 ~. l2 j, i, D
  132.                // IDE or ATAPI IDENTIFY cmd
    8 d( P) K3 m2 E! \! G# `* @% o
  133.                BYTE btIDCmd = 0;+ R2 M; o1 M1 V- B; B3 J$ [
  134.                SENDCMDINPARAMS InParams;
    + q, V+ Y' H9 J7 l1 |# l
  135.                // Now, get the ID sector for all IDE devices in the system.
    3 x6 L) j2 F2 m3 K
  136.                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,4 X( P) P2 x1 |; {( j
  137.                // otherwise use the IDE_ATA_IDENTIFY command9 ]  G. r# ^6 b0 j/ Z. ^* |
  138.                // 具体所得结果请参考头文件中的说明6 ?9 W: d( _$ Q) W0 I
  139.                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?6 y9 b+ D$ U# T! x7 D# }
  140.                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
    . ~* G7 w2 L+ F7 Q7 n
  141.                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
    * W$ L$ A8 N4 c* |
  142.                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
    ! g# z4 g+ T+ b- B3 W+ A# [

  143. / i/ F/ [3 O6 S8 N+ _* \' {
  144.                if(DoIdentify(hPhysicalDriveIOCTL,
    " S) E6 P6 q: B1 p. R: d5 F/ d
  145.                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,+ t, ~$ C* o. Z' `
  146.                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))# O8 B5 j# d9 }( n5 |
  147.                {
    7 h* o( z) _# y  K3 W* n
  148.                    DWORD dwDiskData[256];
    % ~5 K( H3 K; i' F
  149.                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
    ) o7 _" t' x  Z
  150.                    char szSerialNumber[21];
    5 S7 T- E/ ~6 ~% P& A
  151.                    char szModelNumber[41];
    4 l' _; Z' j7 u+ m

  152. 7 P" b7 W% e6 f* j: s! L( k; s
  153.                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;" {/ E$ P  y4 v. e
  154.                    for(int i=0; i < 256; i++)
    ( J$ r( n3 h9 P& u* S! U
  155.                        dwDiskData = pIDSector;
    - Y' I0 F$ I9 c
  156.                    // 取系列号
    6 D- ]0 c2 o) [/ p* ?; x" p
  157.                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
    ! a1 [0 B" P. o  k
  158.                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
    ' W1 e! Z( u  t/ r8 m

  159. ' ^5 T7 ?3 }, d% d% L" S
  160.                    // 取模型号
    + l4 v/ n" T6 K% P; {
  161.                    ZeroMemory(szModelNumber, sizeof(szModelNumber));
    % J, m( o6 X+ G1 d. K
  162.                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));3 p8 o2 {1 D$ m: ^8 i( H

  163. 9 ~0 d7 ~) e8 H, N5 F6 v# F
  164.                    pSerList->Add(szSerialNumber);
    ) J6 R( f7 V8 m; z$ j6 p, k5 n
  165.                    pModeList->Add(szModelNumber);
    4 y& i2 b1 i5 Q# y7 _- ^/ p# Q" ]
  166.                }
    2 }8 K  z! K$ s0 L1 j* Z7 O2 y
  167.            }
    ! c% G2 Y5 ~+ S: l( w" B, ~& E) v; b! c
  168.            CloseHandle (hPhysicalDriveIOCTL);& x, a7 r' A: z% o: W4 A# _
  169.        }8 E/ k8 d' R* N1 f. \: P1 N9 c6 Y* ]
  170.    }
    ( X( |& o2 V+ ^/ n; h( I( |4 D, t
  171. }
    / T/ @/ s; Y/ h% X
  172. //---------------------------------------------------------------------------4 X, W% z" ]# Z8 Z' v8 A
  173. // DoIdentify2 z! R( H6 D' W; p
  174. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
    1 j; z' h  V' l4 Z! ~+ ]  n
  175.              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
    6 R( e7 X" H" A& c8 p
  176.              PDWORD pdwBytesReturned)& I5 m6 l1 k* W# d( M; U$ d
  177. {4 O2 b' U2 j5 _+ }
  178.    // Set up data structures for IDENTIFY command./ N! x5 ~; T% r. v
  179.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;* q( A+ {, p% ]$ _
  180.    pSCIP->irDriveRegs.bFeaturesReg = 0;  _! d7 ~; g4 u5 o) K' z7 G
  181.    pSCIP->irDriveRegs.bSectorCountReg  = 1;
    7 R1 y  M, Q9 u+ b
  182.    pSCIP->irDriveRegs.bSectorNumberReg = 1;
    - ]! U# \6 ?0 q5 b! r+ z/ X
  183.    pSCIP->irDriveRegs.bCylLowReg  = 0;+ m% p# ~# U& Q* r
  184.    pSCIP->irDriveRegs.bCylHighReg = 0;
    6 E  _* O$ Q! N$ @

  185. / ~' k8 I7 L/ k# W
  186.    // Compute the drive number.(主盘和从盘所对应的值是不一样的), k# s2 E& k. n! f9 ~. Q; X
  187.    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;/ D9 u& ?7 s+ p/ L
  188.   t7 ?# U3 d9 @9 p1 d/ a
  189.    // The command can either be IDE identify or ATAPI identify.
    * q* ]) F6 Z8 O/ `
  190.    pSCIP->irDriveRegs.bCommandReg = btIDCmd;
    * N) {& o4 L2 @) k
  191.    pSCIP->bDriveNumber = btDriveNum;3 o$ M9 F5 _8 }: @) h) F6 Q1 v0 j% F
  192.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
    9 G! j3 }+ D/ o9 ?" Q8 q
  193. 3 ^: i$ D/ b3 `6 |% u$ e8 @, w7 C
  194.    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
    # x! a6 v# h' T! M9 T  {+ k5 L  Z( y) Q
  195.           (LPVOID)pSCIP,
    3 {1 v- z: a: v( [6 q( Q
  196.           sizeof(SENDCMDINPARAMS) - 1,! g9 U; y" g% k3 x! H
  197.           (LPVOID)pSCOP,2 Q( _+ V! |8 l2 D+ e6 \9 ~6 B1 T( X
  198.           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,$ F4 U* c4 s7 N3 v) G
  199.           pdwBytesReturned, NULL);: u, j7 ~5 A" j. T* Y
  200. }
    & N/ _8 H/ E, v" m
  201. //---------------------------------------------------------------------------  A% M1 A0 ?7 m7 `$ l
  202. // Windows 95/98/ME 代码- T9 w6 C: u! W$ L
  203. //---------------------------------------------------------------------------
    & y0 f4 J5 c2 _7 C
  204. // ReadPhysicalDriveOnW9X
    $ r5 Z5 Q6 k2 i; `
  205. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)  n7 `" {; v0 x
  206. {, I4 @1 G( Q1 d
  207.    WORD wOutData[256];  E' g% X/ {) c( G
  208.    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);( F# g( T$ |% [
  209. % o- Q7 l( r. z0 G
  210.    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。6 i( ?# {1 U, C
  211.    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以: ]3 Z, C# b, Q) d$ f
  212.    // 避免蓝屏的出现。(期待高人能指出原因)
    0 {0 D' s% E3 H% ^; l+ g! O
  213.    for(int nDrive = 0; nDrive < 8; nDrive++)
    ; h, G# h, ^9 o+ x# i% u! x
  214.    {
    ' [% }  z5 {9 Z( m8 S7 F
  215.        WORD dwBaseAddress;% L$ \8 m$ @+ f: Q; x& B1 l
  216.        BYTE btMasterSlave;         // Master Or Slave
    ) p* g) u% I, }4 k+ G
  217.        bool bIsIDEExist;+ C" H! I7 S: O' a# Z
  218.        bool IsDiskExist;" v# K$ }# ^1 g' @3 }
  219. / M2 D$ E( L! ?, x8 j, n
  220.        switch(nDrive / 2)
    ' J+ P, p9 v0 Q
  221.        {' K: k' M4 u& X- c2 }- H; j& q: ^
  222.            case 0: dwBaseAddress = 0x01F0; break;+ U$ I, A* _5 q0 u9 b: q  i0 O
  223.            case 1: dwBaseAddress = 0x0170; break;9 x% X, k  w+ B) V, Z2 k5 _, O
  224.            case 2: dwBaseAddress = 0x01E8; break;
    + Y6 j/ x6 p  n
  225.            case 3: dwBaseAddress = 0x0168; break;5 g5 }- o* Y$ b& d* I! R
  226.        }: o" k- e8 P; B7 p) v* c/ ?! T
  227. : s0 h: o# j& y
  228.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);& K# z# v; e% }! e

  229. $ ^) z' s9 J/ D7 R2 S/ Q  J$ a+ g
  230.        // 进入Ring0
    0 [' y* U5 C* I' Z( g& N
  231.        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
    0 x+ Q0 c8 Q8 Z/ i% J9 m6 }1 {
  232.                bIsIDEExist, IsDiskExist, wOutData);- k, |# Q2 V- t% W3 B3 o
  233.    }
    6 Q; I2 M1 z+ Q2 @# [3 {
  234.   H' a+ @& K6 G
  235.    // 开始读取$ B0 [) N0 ]7 N- ~" l/ L/ c" Q
  236.    for(int nDrive = 0; nDrive < 8; nDrive++)- `$ N( p/ X+ k3 a7 |( W
  237.    {: [8 d4 i) `- y8 O1 j7 v& Y9 u
  238.        WORD dwBaseAddress;& R( H+ a. S, M1 l8 u
  239.        BYTE btMasterSlave;         // Master Or Slave+ n3 O" U3 V1 C! F( ]
  240.        bool bIsIDEExist;- g7 Q; N% T; w$ b" j: k; H
  241.        bool bIsDiskExist;
    3 ]# [2 {, W" C' l
  242.        switch(nDrive / 2)4 W$ i) L# k8 n2 @
  243.        {
    # v+ z+ O1 Q' z7 g1 l1 w) [0 |
  244.            case 0: dwBaseAddress = 0x01F0; break;
    ! c) l  t3 Q6 j' O
  245.            case 1: dwBaseAddress = 0x0170; break;
    3 `$ H# ]# ?& ]" U% H1 \& E9 e
  246.            case 2: dwBaseAddress = 0x01E8; break;
    % |7 A, C6 y6 u
  247.            case 3: dwBaseAddress = 0x0168; break;
    ' E9 A0 v- Q3 E2 y* `9 ?
  248.        }
    , t0 `5 }- R( M/ p

  249. 2 d* v- R$ A5 T" H8 n
  250.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
    , E; C# g6 f7 W1 j- S$ r& z" X4 i# C
  251. : ~, M- ?2 }. r$ B# S) [; A; r$ U
  252.        // 进入Ring0
    $ ^* @4 e. C! I: t: `9 `' N
  253.        bIsIDEExist  = false;8 r9 _+ P. V5 L8 N2 K
  254.        bIsDiskExist = false;: Q5 C& Q# O8 H! ?- f7 V
  255.        ZeroMemory(wOutData, sizeof(wOutData));  `1 a& u$ y4 E( ^) H
  256. 6 b4 ]1 a9 `4 j, \
  257.        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
    7 `  D% W; M7 x
  258.                bIsIDEExist, bIsDiskExist, wOutData);' q" {0 F9 J! ~2 r! I

  259. ! c# ]! y! _, k( Q
  260.        if(bIsIDEExist && bIsDiskExist)3 |# [. y: I2 K# Y
  261.        {$ {" Z1 ]: G5 N9 A# \
  262.            DWORD dwDiskData[256];* c+ \" j; D# D' f- j( y( S
  263.            char  szSerialNumber[21];4 r' E' n% _$ C- J: z3 n8 ~
  264.            char  szModelNumber[41];  f! v7 m2 b" K- R6 j
  265. * h9 J( B' `5 i+ K' m
  266.            for(int k=0; k < 256; k++)& a* x# _) Z0 ]: \- f, u  U8 i. s- r
  267.                dwDiskData[k] = wOutData[k];
    ! x) D- n) x3 k7 B1 c& s2 L# ?+ i& M
  268. " }) O5 b0 d$ X0 @# U; ?
  269.            // 取系列号0 c4 [0 G/ Y( D. T6 ^
  270.            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
    1 b# D2 T; Z0 f: t
  271.            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));) s$ c. l  ~" M8 [

  272. - i+ U1 a0 W( S" j2 Y
  273.            // 取模型号
    ; ^8 H$ N. E! J, r- z
  274.            ZeroMemory(szModelNumber, sizeof(szModelNumber));
    ' B( p# n" A. o0 z) K; s' Q
  275.            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));; `, h2 F0 l; C9 b  V
  276. 1 j+ ?$ E  j* r: D; o. P) O" n/ e
  277.            pSerList->Add(szSerialNumber);6 O  y, A' I+ F( r7 Y- i9 _2 N
  278.            pModeList->Add(szModelNumber);
    1 B8 [- ~% c8 Y4 D7 c' Z
  279.        }
    3 C, x* Z- V3 U: X9 t
  280.    }
      _# ?  N6 G! K% a2 j, u
  281.    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);3 X: _. X. [- K9 j" A
  282. }- ^' }3 {8 `; j6 y- g; V
  283. //---------------------------------------------------------------------------9 `2 w( o* f7 E. }/ I3 B2 J& R( I! ~' m
  284. // ReadPhysicalDriveOnW9X_Ring0()
    / F! C8 E( y5 H! N# x- X, w
  285. //, M( b" K2 \% f' |% l, f
  286. // dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h, |/ X8 N. D3 |7 t$ q, @% n
  287. // btMasterSlave = Master(0xA0) Or Slave(0xB0)
    $ e1 A* X, i1 N9 u
  288. //---------------------------------------------------------------------------; M9 S# J0 ~/ Y9 V8 S  X2 Q
  289. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
    1 u7 X3 k4 s$ n& M
  290.        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)1 v, H- s" E5 Y  o6 E  i- u
  291. {' b5 E! a5 r. F7 L% ?( o
  292.    BYTE  btIDTR1[6];
    + k; Q! E& a) e8 u& u+ U3 l: p
  293.    DWORD dwOldExceptionHook;
    9 K/ P, J% [  j: i$ I8 x8 s
  294.    const int nHookExceptionNo = 5;# [$ g" l0 N7 X
  295. : b$ Q7 N9 R1 K# }) S& ]
  296.    BYTE  btIsIDEExist = 0;  X# q  P+ v" U( K
  297.    BYTE  btIsDiskExist = 0;
    4 @. ~( Y' }  b4 r+ R$ ?
  298.    WORD  wOutDataBuf[256];: ]# f* ^% b6 _2 X2 @' I
  299. % z0 c. q; ?- A" y; n+ C
  300.    BYTE  btIsFirst = (BYTE)bIsFirst;
    ; T& V6 A1 s$ P2 B  m6 @8 Z
  301. 9 a9 p* I' A1 k" R1 e- O
  302.    const BYTE btBit00 = 0x01;* h/ J; |% r! f, X' k7 s& j
  303.    // const BYTE btBit02 = 0x04;
    7 y  U" L! ]$ u( D4 o
  304.    const BYTE btBit06 = 0x40;
    , \% H, @( }( M; b  c5 z
  305.    const BYTE btBit07 = 0x80;
    $ F3 E/ X+ s  z3 P7 x& A  T7 t
  306.    // const BYTE btERR  = btBit00;7 F# s% X: ^6 X* |+ e' v: l
  307.    const BYTE btBusy = btBit07;! o. j/ o" y$ w, G' n# ]2 X
  308.    const BYTE btAtaCmd   = 0xEC;/ a2 }7 O3 G( y  [( P1 N
  309.    const BYTE btAtapiCmd = 0xA1;
    8 `- z9 J# Y" }7 u! V7 ?

  310. * F$ |' S/ Z/ o! b# s& ]) f
  311.    __asm
    ) i& w) @" z( o0 i
  312.    {
    ! I- n" ?" y1 n# A0 S# C. C
  313.        // 必须先执行这条语句" U) A" X# W' Z) k
  314.        JMP EnterRing0: m3 s8 ]& H+ ~0 a8 q  [2 t
  315. 1 j6 X* _5 b1 y
  316.        // 定义过程; H! l3 r9 m/ l8 t6 V  a; G2 u
  317.        // 等待IDE设备直到其不为忙为止5 E: I- }/ W, D  `# L3 L0 M& k
  318.        WaitWhileBusy proc
    - }/ }& b* o, B1 w1 I/ x/ M

  319. 4 f. C3 J. n8 d3 {$ ?+ F
  320.        MOV  EBX, 100000% Q8 `$ i5 ^. G: z) U3 H
  321.        MOV  DX, dwBaseAddress$ ^" F4 U+ |. o8 m- _( Q7 u! I
  322.        ADD  DX, 7
    + W# ]/ z6 k& ~  ~
  323. ; h( e8 L: E3 ~/ \3 d3 f, v8 l
  324.        LoopWhileBusy:: D0 @) r5 U- u4 k: X- K* b
  325. 5 S5 R& J9 J6 ?0 H1 Q
  326.        DEC  EBX8 X* A) L7 m/ w6 }! S7 g' D
  327.        CMP  EBX, 01 G, }! `6 ]) m5 l, q9 |4 i
  328.        JZ   Timeout
    + B  L! W. O2 k. O
  329.        in   AL, DX& H& E+ }' X3 o
  330.        TEST AL, btBusy
    * a" h' n* ]  C  R
  331.        JNZ  LoopWhileBusy* Y# T" y/ p% f6 B" v7 m
  332.        JMP  DriveReady
    ' z4 c8 |1 A! |3 G

  333. , {  O! G4 \9 q! y/ x" W& j7 u
  334.        // 超时,直接退出3 d- p0 n" p# j% m
  335.        Timeout:8 H" Q) K; `( i1 y
  336.        JMP  LeaveRing0
    5 b* f0 ?5 I. ?8 H0 D6 ?
  337.        DriveReady:
    " {8 V3 @& T  |8 j. [9 R2 F
  338.        RET
    $ {1 e- V$ o* [# p! x% V; R( }
  339.        ENDP   // End of WaitWhileBusy Procedure
    ' t+ ?/ v1 W: E- W
  340. ! v" [4 G" V6 m$ e/ B: g
  341.        // 设置主盘和从盘标志
    & ]0 @. d% }0 J
  342.        SelectDevice proc: q5 e+ ?$ j3 `* s! o
  343. ) r7 H/ g5 u" w) C1 G7 Q9 L
  344.        MOV  DX, dwBaseAddress
    5 ]1 j$ G8 m8 D( v% `& R, F. i
  345.        ADD  DX, 6
    5 ~0 ]4 N. Q3 k- x
  346.        MOV  AL, btMasterSlave; d3 @' V' f5 z5 ~
  347. 2 u# O) T9 U9 W* j7 {; V, d* s
  348.        out  DX, AL9 U, w( u& I$ f) o2 A) n; S+ S
  349.        RET
    ' C1 @3 b( ]5 k- P

  350. 9 a  c* Z% [* J5 N6 ^: u
  351.        ENDP  // End of SelectDevice Procedure% j# @9 ^2 O# o0 l8 |1 z

  352. ) S* C, q' _9 W
  353.        // 向IDE设备发送存取指令
    7 T& I! |  o+ o) s5 e
  354.        SendCmd proc
    , z1 g% K3 X2 M$ j; [' c2 x2 @0 p7 D

  355. ( T" H' H: A0 O3 J
  356.        MOV DX, dwBaseAddress- r, [: P- h! \( i
  357.        ADD DX, 7% Z! O1 Z0 f: Z# L: B- l- Q) ^
  358.        MOV AL, BL // BL是主从盘标识,在过程外设置0 X% `" L- n8 ?/ z7 _8 x- u* @# x
  359.        out DX, AL7 T) C8 I. N7 z1 Q7 j/ w5 E! |
  360.        RET
    8 A5 R) Q' c" g1 v3 T3 H9 e4 b* I9 ]* x
  361.        ENDP  // End of SendCmd Procedure7 C& s' _4 c1 u, n3 R# T- E
  362. - n0 f: b5 @, d/ B6 K' t
  363.        // Ring0代码) _" l+ B6 s; [: J1 g# ~1 D' }, b4 P
  364.        Ring0Proc:0 A+ `7 |7 ]* a& @& _
  365.        PUSHAD
    7 }8 S& {3 p" @+ }1 `
  366.        // 查询IDE设备是否存在
    7 D6 J  G. ~2 S! M  z9 ]& ?1 U! J' o
  367.        MOV DX, dwBaseAddress
    0 t# T7 t% f7 N9 _
  368.        ADD DX, 7
    8 ~6 z% E+ w4 O' B" y
  369.        in  AL,DX
    / \6 }2 }: G1 @& }5 n( b
  370. # b! i; Q: e3 c+ {4 m0 c- _, y1 E
  371.        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回8 q2 {9 o4 N& c" M
  372.        CMP AL,0xFF$ c! W( E; k; J, l- X0 ?+ _
  373.        JZ  LeaveRing0
    6 Q: `+ r/ L" u5 J- h
  374.        CMP AL, 0x7F
    ) S, |/ S4 m/ `  Z0 ~: l
  375.        JZ  LeaveRing0* A8 X% @- x% P3 s

  376. ) l, D9 d$ O" }* ?1 H
  377.        // 设置IDE设备存在标志) K6 \' h  m( v9 D: K- k7 Q  X
  378.        MOV btIsIDEExist, 1. G3 J$ Z7 I7 w- V; K

  379. $ o" G9 }  r- L9 C  D
  380.        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
    4 z, T' C) t* p% t: O5 o
  381.        CALL WaitWhileBusy% }3 n: Z# G7 ?* G7 M2 q' }; H
  382.        CALL SelectDevice& J6 i" t  s: ?

  383. 0 R$ I  q6 d. w
  384.        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏+ ]: v  [/ S" Y5 o1 R  c
  385.        CMP  btIsFirst, 16 o$ }! {9 S+ p" x" |6 a
  386.        JZ   LeaveRing0
    - \" [9 K5 ?: m- N
  387. , ~0 p" n: g0 _& y, }, ?
  388.        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???% f0 h, d" h2 v- D7 }/ Z
  389.        CALL WaitWhileBusy6 d7 \0 Z1 ^6 S& y1 {/ e7 J
  390. 2 X% A8 v* L/ T$ A; G
  391.        // AL的值等于cBit06时,不存在驱动器,直接返回# d/ E( k1 {; u# h8 s8 t, M
  392.        TEST AL, btBit06
    . m% W# l% F. q
  393.        JZ   LeaveRing0
    # i' f' w. B$ _6 |: S# T

  394. 2 F; X& E2 a7 [- S
  395.        // 设置驱动器存在标志
    ' \6 i: X. P# U- J
  396.        MOV  btIsDiskExist, 1
    1 {! i7 G' G( S& m

  397. * b2 w: s2 t/ r! L
  398.        // 发送存取端口命令, g0 E0 f: s9 X. v( |( ?) m4 k
  399.        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,' o1 g* Y! [5 J% M2 M- C
  400.        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
    5 ~7 q+ x  f0 u# ]) b
  401.        CALL WaitWhileBusy4 a1 q  c6 d) l
  402.        CALL SelectDevice    // 设置主从盘标识4 K9 F( ^* M( v& q- i2 f% b: M! _
  403.        MOV  BL, btAtaCmd      // 发送读取命令6 R5 ~2 R$ e5 b! O) J5 c
  404.        CALL SendCmd2 @0 r4 q5 S, K
  405.        CALL WaitWhileBusy. L8 P& I) E3 a3 }& k# x

  406. 2 S$ J" g% E- o
  407.        // 检查是否出错
    + F: v% X  o/ b- c: Z
  408.        MOV  DX, dwBaseAddress/ o+ ~$ f8 ~: [. P
  409.        ADD  DX, 7
    # k  C6 R# i& f' n- f4 ~$ L# i

  410. * A. x7 g% C) Q
  411.        in   AL, DX
    + |/ N: B- K4 O$ B( Y6 \
  412. 7 ~' C4 q% B; A& V9 E0 B, U" f
  413.        TEST AL, btBit00% W5 S4 K- g% h6 {, ?6 [
  414.        JZ   RetrieveInfo   // 没有错误时则读数据
    9 M* B8 u% L/ C. w" p! S" J
  415. 4 r# X9 p0 Q' _! H
  416.        // 如果出错,则进一步尝试使用ATAPI设备命令+ w' F; o0 p7 K( B1 H
  417.        CALL WaitWhileBusy# U3 i- l# N! K
  418.        CALL SelectDevice* J4 M& P: o) A% N
  419.        MOV  BL, btAtapiCmd
    5 A  e( c. m0 ?+ e6 a
  420.        CALL SendCmd* H0 O% Y) [& q7 \; h
  421.        CALL WaitWhileBusy2 D( A! n) n' \

  422.   \, J) h5 |% {* O" T4 Q( T2 Q6 l
  423.        // 检查是否还出错
    3 i/ u" ^3 o" u' e% ^
  424.        MOV  DX, dwBaseAddress$ |, w6 |$ o. M0 z+ \/ v2 I! h0 y
  425.        ADD  DX, 7
    1 x% ^- C  U9 ]8 w7 ]! D7 U
  426.        in   AL, DX
    5 a/ i5 A" p" X% X+ N, }
  427.        TEST AL, btBit001 P1 l8 r7 [- E' S
  428.        JZ   RetrieveInfo   // 没有错误时则读数据
    . \4 O$ B+ ~) X9 L
  429.        JMP  LeaveRing0     // 如果还是出错,直接返回$ Y4 N/ m* q; i- e0 j

  430. 6 z  D; q% I0 u, }$ z$ t8 |
  431.        // 读取数据
    2 H, Q2 ]9 X# x- V) P; Q& Y
  432.        RetrieveInfo:
    ) j: L$ J$ [0 y! v8 v

  433. . c0 n6 w4 Y5 b7 ?) y5 K$ a
  434.        LEA  EDI, wOutDataBuf7 R, L. E. f( g7 q6 e! ?8 {
  435.        MOV  ECX, 256
    ; d0 w4 ~, a. c5 N; u
  436.        MOV  DX, dwBaseAddress& g% \% b( [; u
  437.        CLD
    3 a: T" u. Y6 q" l
  438. + t% Y0 P8 h0 Z% {! \
  439.        REP  INSW$ y; D  l( z' z- I; l, o
  440. ) ~, z, s/ k0 x% a/ u
  441.        // 退出Ring0代码
    - N9 n! x: ~4 F% t( w( ^* p
  442.        LeaveRing0:
      T% S  c/ `) Q5 v3 d# v$ n; X

  443. 9 |/ W5 U! Z: f4 M" T
  444.        POPAD: m  N$ \5 Q$ A+ R9 k* p
  445.        IRETD
    $ [6 T4 C0 {4 l! ?& O; l% V; [

  446. 5 q3 k# d0 Z3 t: _
  447.        // 激活Ring0代码
    7 y, P+ P# |  p; ^
  448.        EnterRing0:8 E/ A# F# T2 k# T9 m, N

  449. - F1 a! c0 M- m7 }; h1 n" ~4 G
  450.        // 修改中断门- b3 c* @$ S- K! e  n7 w) d, W
  451.        SIDT FWORD PTR btIDTR13 [0 d- z3 u4 c; R+ }) i) p  n8 ^
  452.        MOV EAX, DWORD PTR btIDTR1 + 02h
    7 _! n/ u1 t! B, w9 B& J
  453.        ADD EAX, nHookExceptionNo * 08h + 04h3 D6 y/ M: P- }. ^, X1 ~9 p7 X: B/ X
  454.        CLI
    ; {+ w' A# |* @

  455.   w4 Q/ S& }! \+ W. v0 ?- y
  456.        // 保存原异常处理例程入口
    # Z! p9 X: }( G6 O! N2 r
  457.        MOV ECX, DWORD PTR [EAX]
    , I+ i1 ?9 n: L# u
  458.        MOV CX, WORD PTR [EAX-04h]
    6 f  g$ {4 L  c* j2 u5 ^
  459.        MOV dwOldExceptionHook, ECX* U% x+ ~* F0 f1 d" J: K( u
  460. 3 I9 I) C  h6 L( b3 S
  461.        // 指定新入口. k$ _9 J5 T% B/ r+ Q
  462.        LEA EBX, Ring0Proc0 Z' ?$ A( [% b
  463.        MOV WORD PTR [EAX-04h],BX
    : F& [" H8 K- |) n
  464.        SHR EBX, 10h
    3 j$ k3 L# b9 q: G8 M  N- c- N
  465.        MOV WORD PTR[EAX+02h], BX1 I7 O+ x( Z6 `
  466. 4 O; C) F8 N. Z0 }0 I3 Q8 A9 |
  467.        // 激活Ring0代码1 r  N* l! `2 X+ d
  468.        INT nHookExceptionNo+ }7 _0 m2 r6 Y/ H5 k/ p( j
  469. 8 d0 N: Z4 L. G4 p6 H0 l# [- V, r
  470.        // 复原入口
    / c/ b) ^$ |& Y9 ~
  471.        MOV ECX,dwOldExceptionHook8 d) u: B9 H% ?1 T
  472.        MOV WORD PTR[EAX-04h], CX0 C7 i5 b) b% O" Z( Q- q- }8 h
  473.        SHR ECX,10h9 ]3 B  w7 {0 F
  474.        MOV WORD PTR[EAX+02h], CX
    " c5 S' s& I( m. Y) _. C9 X
  475.        STI
    ! _  s9 a6 \7 O6 l9 f7 e4 G# O
  476.    }
    2 S$ I; n5 y9 p( U& O
  477.    if(!bIsFirst)
    + ~6 C' B! r3 \- X9 g+ \
  478.    {
    4 t  I5 W. ]8 F: W% n6 b
  479.        bIsIDEExist  = (bool)btIsIDEExist;. K# b9 n: ^; [0 ]8 W' ^) Q) K. r
  480.        bIsDiskExist = (bool)btIsDiskExist;
    , f4 o7 N+ C9 H, A
  481.        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));+ v/ A- q( g- {
  482.    }
    / b) Q: f; e9 B
  483. }
    # W' S( k$ J( z# k
  484. //---------------------------------------------------------------------------
    3 d6 [4 r, p% A
  485. // 调用方法:
    ; Q4 ?9 ]5 r- k& T0 W
  486. void __fastcall TForm1::Button1Click(TObject *Sender)
    ' R+ b! W" Z2 \0 J2 c
  487. {* x0 h+ R- o6 E1 {
  488.    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);* l& P; ^8 }9 d' b; ^: _$ i' B
  489. }
复制代码
发表于 2005-8-15 01:00:45 | 显示全部楼层
晕乎乎。。。怎么看8 洞阿
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-6-18 08:03 , Processed in 0.022833 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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