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

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

[复制链接]
发表于 2005-8-11 11:42:04 | 显示全部楼层 |阅读模式
  1. #include <WinIOCtl.h>
    ( O/ |4 |$ S7 G
  2. #include <stdio.h>
    ' K* Y: o* \, w# u% K7 B
  3. " ~& @; `. ^$ a' u1 x, x% W
  4. #pragma inline
    . {/ N. ?3 U) m+ |# @
  5. //---------------------------------------------------------------------------
    ( g6 A7 E2 |0 f) i1 b5 G
  6. // IDE NT/2000/XP专用变量
    . B. S7 }8 u. v8 o" ?; J: u
  7. #define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
    ) z" h: a( F+ [
  8. #define DFP_GET_VERSION         SMART_GET_VERSION$ P) b% U' n8 `& N. ]
  9. #define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
    1 K, C& T2 H1 c4 d" b
  10. #define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA8 e0 K) ]# A- R% K

  11. - b# k$ |2 W; }9 E5 e
  12. const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令
    " E( g' ~. B/ @) r* P4 l. z
  13. const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令$ c' B" \( [# v6 I0 n, X: {$ \
  14. ) v' H' D. n* T1 \% K, k
  15. const int MAX_IDE_DRIVES = 4;2 O. |3 Q" `2 a9 z) J% Z
  16. ( t3 z2 G: F, h
  17. // SCSI专用变量' D% m4 F8 z+ u8 M) X$ u. g
  18. const DWORD FILE_DEVICE_SCSI             = 0x0000001B;, n# Q7 ^2 |) S7 b
  19. const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);2 `) c; ]# z9 L$ x; ~% Q  X
  20. const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
    1 P5 U+ A  u: c* |% f
  21. const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
    5 @' e+ ?- J, y' T+ z  ]8 U# s1 S7 I
  22. 4 W  \7 ]7 d8 H; z1 J
  23. typedef struct _SRB_IO_CONTROL
    6 |( K% X1 O; I3 l' ]' n
  24. {: R/ p  o* n# M# X* V, m+ }8 n
  25.    ULONG HeaderLength;
    4 r# y% N# V% G/ R
  26.    UCHAR Signature[8];8 t! W9 m" {) J! k
  27.    ULONG Timeout;. k9 O8 o; z4 c) r+ h' y- `
  28.    ULONG ControlCode;2 E+ R1 w2 a: ~# f, t( j
  29.    ULONG ReturnCode;
    % w; N% O' \+ o* U
  30.    ULONG Length;
    6 E, X) ^& y% W+ |
  31. }SRB_IO_CONTROL, *PSRB_IO_CONTROL;1 ^' f$ F! J* x4 {
  32. 0 \* ^2 f/ u/ D4 _- z
  33. // 读取的主函数
    7 f' ?* }) x& q- T4 u7 {
  34. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
    " F3 ^# j( w: ]% q) {5 h
  35. 8 o7 E- r( O% P7 s* N. F4 F
  36. // 辅助函数" T6 o8 t0 l. P) Y$ S
  37. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
    5 ^- S5 n# L/ H, X# ~. R1 ^" V
  38. // NT/2000/XP函数6 m$ d* D/ {, Y" K6 u3 s9 W
  39. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
    9 }1 `) }2 }: w1 ~
  40. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
    7 R( B: ?7 y9 q# R# w
  41.        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,5 N+ T4 H' \. u. \
  42.        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);" R- g9 U4 b0 s
  43. // Windows 9X函数
    + Q' p7 l4 A- h6 A8 p& K$ o6 Q
  44. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);: d; l3 A# b, K7 C
  45. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
    & x' Y. C8 \; b) l+ F
  46.        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);# _, ^/ f1 I: ^/ N: `
  47. " v& u# Q5 T- U
  48. // SCSI读取函数(for NT/2000/XP)
    $ J$ }/ a; ^5 y) G) h/ S4 f
  49. String __fastcall ReadIDEDriveAsScsiDriveOnNT();
    & d9 u0 E6 T% ]& v# D
  50. //---------------------------------------------------------------------------1 K/ r  b0 o2 r2 k5 L; S* B
  51. // ReadPhysicalDrive) i5 \  I& e: e/ [* X. N
  52. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
    3 `; \- ?8 w$ X! Y
  53. {
    ( E7 I" ^! a$ L2 E5 n# v. h5 P1 ?
  54.    switch(Win32Platform)' x  e- b  _8 |) y# u
  55.    {
    8 t6 |! z" L6 s& y
  56.        case VER_PLATFORM_WIN32_WINDOWS:
    % M3 f# F; z- p+ k! B  E
  57.            ReadPhysicalDriveOnW9X(pSerList, pModeList);
    - k; M% _$ y+ K' t  A9 z
  58.            break;
    / C0 z2 o7 \8 n$ b5 Z
  59.        case VER_PLATFORM_WIN32_NT:6 R+ r5 h* Q0 f
  60.            ReadPhysicalDriveOnNT(pSerList, pModeList);
    # F' _6 c% \7 P8 M
  61.            break;7 T7 H5 c$ ?+ H( |6 D
  62.        default:
    & d$ u9 p. s' |! K+ _9 y4 u
  63.            break;
    & T& k4 P, M& P. W, }: E
  64.    }  [( _( ?4 _2 D2 M$ T# ]5 c+ X5 f# J
  65. }& P7 |6 `7 S  c8 {
  66. //---------------------------------------------------------------------------
    + f/ w* P* G0 {9 Z1 `9 A# r; o
  67. // ConvertToString2 X# }) z* Q% o/ {; A
  68. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
    * B% a5 v6 N: N! h& K9 w/ V
  69. {
    ( {; g6 B) C( f" R6 Y1 N+ b
  70.    static char szResBuf[1024];; w0 T' v) @; x
  71.    int nIndex = 0;! R5 N: K( h( ~0 M5 S+ v4 o
  72.    int nPosition = 0;
    8 ?! }4 t, N! v* O. t

  73. ' N+ w" J% |% e
  74.    // Each integer has two characters stored in it backwards
    ! f* G7 F5 U( E8 s! \
  75.    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)0 B3 U  i# {. w6 |. e' |
  76.    {
    . [0 x6 }  V' C0 `! q
  77.        // Get high BYTE for 1st character! D; t) f% `4 o- B/ y
  78.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);0 m. |& @+ ~* h6 t
  79.        nPosition++;
    * ]. A$ z( ?. G2 m3 ^

  80. ( k/ e+ B# \9 I, F# E: H: D
  81.        // Get low BYTE for 2nd character
    & L0 `6 _& C) R; r$ @  N, l5 S3 b
  82.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);1 }5 n6 z# Z6 e/ k4 Z8 F$ [4 Z, }
  83.        nPosition++;
    . w' [4 G3 m& Y
  84.    }
    5 L( f8 b8 d; d
  85.   P; p: T1 E4 u+ f$ ^- B
  86.    // End the string
    , c: i! ~( C3 @3 p4 a" o# W4 y
  87.    szResBuf[nPosition] = '\0';8 @& C' |4 T4 E: y4 v

  88. 3 V4 @: v7 K; o0 _. E. [: ~4 \; x
  89.    // Cut off the trailing blanks
    4 Q3 R/ P3 T; X' F8 I3 a
  90.    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--): j" k7 K1 Z* q- y9 X
  91.        szResBuf[nIndex] = '\0';$ }+ P2 }: S- ^' a- ^  d

  92. ! V* X2 j0 J9 ?' Z2 A1 f6 v" N
  93.    return szResBuf;; ^7 s% K7 P5 x$ X
  94. }1 f; z" G$ h1 K/ F, o, _2 R) f* w
  95. //---------------------------------------------------------------------------
    ) C- q- @/ n# t8 h/ c7 A0 x$ n1 C
  96. // Winndows NT4/2000/XP 代码9 K4 e* m4 E* V4 r2 n
  97. //---------------------------------------------------------------------------
    / N; _& [% F" C# ^+ b4 M
  98. // ReadPhysicalDriveOnNT7 X5 V; v+ `0 H
  99. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)+ @' W; C# {. `& s" T
  100. {1 A5 Z5 l$ N+ o9 _  k1 v
  101.    // 输出参数! L+ m* {- a  ~# X3 b5 A
  102.    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];- ^1 J6 b7 Y+ H+ y; v+ c

  103. 3 Q0 l' F# f( t0 D
  104.    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
    ( v: }8 t5 m  z
  105.    {
    0 Z3 c  [8 q- X
  106.        HANDLE hPhysicalDriveIOCTL;! e/ ^+ x/ P; {0 ]; A$ T8 e
  107.        char szDriveName[32];  ^3 ~+ ?$ T7 b8 G" c
  108. # ]: U7 z4 g$ u5 e  @3 O8 q
  109.        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);0 t: g; U) \$ r+ L3 m) D, F9 b) j
  110.        hPhysicalDriveIOCTL = CreateFile(szDriveName,: n9 {( \2 `' Y0 F; ^
  111.                        GENERIC_READ | GENERIC_WRITE,$ \/ r2 F4 H& @6 }
  112.                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,) X$ |% a- [( P3 n( Q* k5 m- E
  113.                        OPEN_EXISTING, 0, NULL);3 s% Y9 v2 e6 a' a

  114. 9 Q$ J8 r0 T, ~& r
  115.        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
    6 G2 C- a- h, a5 w: y
  116.        {
    9 @! B. k1 X9 k" B# \
  117.            DWORD dwBytesReturned = 0;
    ; w' X: h3 A. Z: j
  118.            GETVERSIONOUTPARAMS gvopVersionParams;
    2 _. _  a4 M% U

  119. 1 W5 `1 O5 b9 M
  120.            // Get the version, etc of PhysicalDrive IOCTL' O. M% [; _1 H1 [6 |' G( F
  121.            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
    ( d9 s5 U9 |; F) m# I

  122. 9 k" T0 p8 w$ u, T- G
  123.            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,9 f: A* B; s% V: ~- o) E
  124.                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),8 \- Y( t/ `+ j* G
  125.                    &dwBytesReturned, NULL))
    4 Y$ M, @0 ?" [, }% k
  126.            {
    4 r' A. @# o5 l3 D! W# |4 X
  127.                continue;
    ; S& y: L8 H1 J2 a
  128.            }
    2 z% {0 l) R5 `4 O3 e* P/ t$ H
  129. - H3 \6 R0 U, \0 z& m* A
  130.            if(gvopVersionParams.bIDEDeviceMap > 0)
    1 b7 a, s( {6 ?6 U# ?
  131.            {
    9 B2 ~$ H: Z9 T  j
  132.                // IDE or ATAPI IDENTIFY cmd% s* j9 y6 w  ^' j9 q; H' v0 j
  133.                BYTE btIDCmd = 0;
    - Y, m( l' N* d3 B2 r' u  U8 K
  134.                SENDCMDINPARAMS InParams;
    5 x8 S; g1 R0 t  v% Y1 [, u; A6 w
  135.                // Now, get the ID sector for all IDE devices in the system.
    " D" u$ Z: h! p4 X9 \  F
  136.                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
    0 j& q3 ]+ \0 P2 Y
  137.                // otherwise use the IDE_ATA_IDENTIFY command
    ; |: t, [) K0 w6 Y; N( O
  138.                // 具体所得结果请参考头文件中的说明  R2 S* ?9 U1 }+ R% f7 N* n
  139.                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?7 @( \" i" S  n+ {3 P/ [
  140.                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;  l2 u7 ?1 E. q9 p5 Z  a: f7 P; |
  141.                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));" Z! Z3 q3 t$ r6 j; w
  142.                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));2 B" `0 j- B9 t' C# K/ @
  143. 2 ^/ w+ U9 v5 S& F# Y
  144.                if(DoIdentify(hPhysicalDriveIOCTL,6 U" l( n, z9 `- b! ]- \1 B3 b' }
  145.                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,8 n* d; h' `# C. ^
  146.                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
    # x8 x0 \* o% A$ a9 y3 y
  147.                {
    $ D0 r8 m0 E/ L
  148.                    DWORD dwDiskData[256];" d1 w2 I7 U4 }2 N5 h
  149.                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件1 ^% O- k' u7 W9 i* B
  150.                    char szSerialNumber[21];
    # W- s9 d- e: K5 j" x+ y
  151.                    char szModelNumber[41];
    4 j7 Q! b( ], T* {6 y3 m; P
  152. $ Z; L" H( j9 g
  153.                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;/ A* a) \, j; l' N( _0 r. F
  154.                    for(int i=0; i < 256; i++)
    " o6 F5 o' P  k, e2 ?$ H% i' `
  155.                        dwDiskData = pIDSector;
    : h. D! m: v+ F8 E; T
  156.                    // 取系列号. B( F* d" f  u: Z) O$ O2 ?
  157.                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
    # X5 N$ l( S6 }8 O5 v) `9 G
  158.                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
    * b5 w  m7 c, q+ V
  159. 5 N5 m6 F, h* ~# `# r; Q: j$ y
  160.                    // 取模型号
    " q# ^5 I+ k; J7 d2 ]
  161.                    ZeroMemory(szModelNumber, sizeof(szModelNumber));
    7 C' Y1 D" R  G/ S+ l( ^1 f4 p+ W
  162.                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
    : N( k% q: s/ f- t% }

  163. $ X8 _; t4 g& |5 ^! M3 B
  164.                    pSerList->Add(szSerialNumber);
    ( [9 n* M/ j. [! D/ |9 |
  165.                    pModeList->Add(szModelNumber);8 H% A! R5 r$ [$ r* Y4 C7 ~
  166.                }$ E0 c/ i% ]9 [: Q6 G- r
  167.            }
    4 A/ H# ~8 ]' r. ]2 Q, M4 ~
  168.            CloseHandle (hPhysicalDriveIOCTL);
    7 k5 q  \6 A; {/ X
  169.        }
    / z; p9 P2 G3 v! ?
  170.    }$ y+ B0 ?& d) {' E0 l& l0 C/ t
  171. }! L; k; ~0 ]% x* `2 K0 f! g: G5 W
  172. //---------------------------------------------------------------------------9 ?- ^& H* W& o1 ~0 \" s  b
  173. // DoIdentify
    * m' m0 W  t& M8 B+ T; S7 ^
  174. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,* i# T8 J, V; M, K( M  A
  175.              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
    : i7 `9 P6 U; U: X
  176.              PDWORD pdwBytesReturned)  c. U3 ^* |  y) y: h; S$ o
  177. {
    : e& ?$ r+ p& j; d' a0 h
  178.    // Set up data structures for IDENTIFY command.- l+ a! d. {% r/ v
  179.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
    5 o1 o/ q8 @& ?5 Q, j8 Z/ @
  180.    pSCIP->irDriveRegs.bFeaturesReg = 0;. w* _4 ~8 f% S* ~. M- B2 ?
  181.    pSCIP->irDriveRegs.bSectorCountReg  = 1;8 y. k9 }+ }, x9 N( ?; q0 ]- |
  182.    pSCIP->irDriveRegs.bSectorNumberReg = 1;
    ; [. ~: B1 O/ O4 `
  183.    pSCIP->irDriveRegs.bCylLowReg  = 0;
    ; v* }5 X; Y: o$ W5 c' f) c7 j' h
  184.    pSCIP->irDriveRegs.bCylHighReg = 0;
    : t2 a# Z  \. I( ^

  185. ( R% b7 ?. p* s5 V9 W
  186.    // Compute the drive number.(主盘和从盘所对应的值是不一样的)8 B  N; L' X2 U7 ]+ M
  187.    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
    ; |9 h7 G; t  U5 G& z
  188. 3 T$ g# l* ?. R
  189.    // The command can either be IDE identify or ATAPI identify.
    0 d% r6 ^- f; b# m( Q
  190.    pSCIP->irDriveRegs.bCommandReg = btIDCmd;
    1 p4 r( l9 w  P/ h; x
  191.    pSCIP->bDriveNumber = btDriveNum;
    . M: V/ {( T8 q4 Q. D9 T& t
  192.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
    $ O) e3 U' a! A' S( R
  193. , K3 z# K; K" j( N( c6 I% e. x0 f
  194.    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,0 ]# @1 ], [: u5 p: D" |4 H* e
  195.           (LPVOID)pSCIP,
      c0 Z6 |4 d0 X
  196.           sizeof(SENDCMDINPARAMS) - 1,
    7 b5 a+ X7 ]" Y1 K  L
  197.           (LPVOID)pSCOP,7 j, {1 k. w; k  L8 X( Q
  198.           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,$ G; b2 R# C& D) k  H
  199.           pdwBytesReturned, NULL);
    3 f% q; |" H* h: l3 d
  200. }
    ( B# o: X8 J6 f$ q' A* v/ j( O9 r: D
  201. //---------------------------------------------------------------------------
    ! P9 f' W8 t/ c7 Q5 d, |4 C
  202. // Windows 95/98/ME 代码
    $ x4 d. N) F1 Q, u  \) r
  203. //---------------------------------------------------------------------------% z$ o% U' A6 ^6 ~5 w! s
  204. // ReadPhysicalDriveOnW9X
    1 H1 i9 a# G" C, \/ i
  205. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)/ e6 v$ U( b! V$ i0 u
  206. {% K2 v9 D, f; h* F
  207.    WORD wOutData[256];! P% n& T$ E. I+ p% M
  208.    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);! q7 R& f0 ]( W3 m) p

  209. 8 V; C" _/ h8 z( a1 M
  210.    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
    2 }, c5 T+ N1 W. o$ h- U8 F+ h
  211.    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
    1 P. R; F( D, a* A7 m
  212.    // 避免蓝屏的出现。(期待高人能指出原因)8 e, X. \# ^1 a* V' s
  213.    for(int nDrive = 0; nDrive < 8; nDrive++)
      \. l" u& q2 t( j
  214.    {$ |6 o" V- z! U0 l
  215.        WORD dwBaseAddress;3 ~/ ^% [% W  H6 ?9 F" q9 y
  216.        BYTE btMasterSlave;         // Master Or Slave
    $ X- M% u0 |3 K" Z
  217.        bool bIsIDEExist;; K* u& q( f; i% t) L; J7 D# {
  218.        bool IsDiskExist;
    : K- y/ d8 p1 B  e

  219. / U& v4 I- e$ j- s- n! V
  220.        switch(nDrive / 2)' i4 Q, V8 o* d3 R, L/ D
  221.        {
    + |" [/ W4 r9 R
  222.            case 0: dwBaseAddress = 0x01F0; break;
    # }0 G& K! l; W6 ~7 b8 ?: i& F
  223.            case 1: dwBaseAddress = 0x0170; break;
    5 e6 p, V& ~0 e7 A1 i* b
  224.            case 2: dwBaseAddress = 0x01E8; break;2 o5 e# e3 |+ m/ l% ]: y
  225.            case 3: dwBaseAddress = 0x0168; break;* m! A' l9 X: A* _& s* d
  226.        }) ~, N$ b3 ]' u) F0 E
  227. & O! C7 z9 o* ?% N# o
  228.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);: R. ]8 G$ U; {0 v  D( ^$ K$ X9 B
  229. 0 ^; d; V" p- {) r; P2 n
  230.        // 进入Ring0+ j4 L! T5 K8 Y4 W; Z
  231.        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,$ K" j: [2 X7 Z$ b9 Q- H
  232.                bIsIDEExist, IsDiskExist, wOutData);4 A0 m# D+ e2 p& F+ i4 P  B" X
  233.    }
    " b9 U+ L/ p" `6 T5 b$ l
  234. " k  c+ U) A  H" a0 I! e6 c- A! V) ]9 V6 T
  235.    // 开始读取- r0 m/ j0 r0 D- e
  236.    for(int nDrive = 0; nDrive < 8; nDrive++)& w" o" S4 U# o) k- H/ O
  237.    {; K8 ]$ u+ \( N9 f
  238.        WORD dwBaseAddress;
    1 R' b2 \% x+ ]1 M2 p) D
  239.        BYTE btMasterSlave;         // Master Or Slave
    4 S! B/ z! s0 I) H! q, C
  240.        bool bIsIDEExist;" B+ Q: [' p' K; k  e/ l) N4 s
  241.        bool bIsDiskExist;
    ; X# @$ B$ \4 H. b8 Z" h
  242.        switch(nDrive / 2)
    6 ]9 Z% g" O4 x& E1 b
  243.        {
    2 F/ \% X) Z3 h
  244.            case 0: dwBaseAddress = 0x01F0; break;9 ^4 K# f9 L8 _
  245.            case 1: dwBaseAddress = 0x0170; break;
    4 G6 o/ q& k$ G; B/ G  g6 R8 Q& I* j* m
  246.            case 2: dwBaseAddress = 0x01E8; break;  @2 N2 F7 ~* f. ^5 ]& q: ]
  247.            case 3: dwBaseAddress = 0x0168; break;
    8 X' _; t) W# ~( e+ T2 \
  248.        }% O9 p, \* Z8 C' t) W2 Q

  249. $ u( g3 A$ N% h& D9 V- s
  250.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
    ' S3 M2 `7 f% M# z; n- c7 y

  251. ; a, N# o  h0 q2 Y# ~9 B, h- p! Q
  252.        // 进入Ring0" P) E! y) a5 N/ A+ G
  253.        bIsIDEExist  = false;( b+ q& s, f1 F& T
  254.        bIsDiskExist = false;) ^, H6 g7 n( S  a
  255.        ZeroMemory(wOutData, sizeof(wOutData));
    5 z2 I) e# x3 a: M! q! B

  256. 3 S- [1 b! z! ~2 s
  257.        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,, E6 a- I' x% h" q
  258.                bIsIDEExist, bIsDiskExist, wOutData);
    ) D. {1 R7 a7 C+ ?! L, ~

  259. ; R* }( x1 m+ ?- r9 S% R
  260.        if(bIsIDEExist && bIsDiskExist): ~5 ^( r. X5 a
  261.        {
    6 c, L) A* E, j9 [
  262.            DWORD dwDiskData[256];/ x3 m9 k2 u$ q6 v$ k
  263.            char  szSerialNumber[21];5 L/ B+ u# E5 v  |  ]
  264.            char  szModelNumber[41];
    ! Y2 M+ ]) u! ]& M
  265. 9 D3 @+ i- F9 R9 M
  266.            for(int k=0; k < 256; k++)
    6 Z8 n0 O2 _6 Z1 J, Z
  267.                dwDiskData[k] = wOutData[k];6 i9 R# O# V% w9 B5 D

  268. : Y$ j3 ]  H% ^/ S
  269.            // 取系列号
    1 O. W/ g* b& Z/ _* D" r
  270.            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));) m- Q) x2 e/ x) r: G3 x/ N3 w
  271.            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));3 i8 Z( c; H/ g2 L+ ^' E& G2 m% d

  272. 1 M7 M) [. A  |
  273.            // 取模型号: l* y' f( Q3 D/ Q7 ^4 D
  274.            ZeroMemory(szModelNumber, sizeof(szModelNumber));+ j! r0 ?( a: N* a
  275.            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
    : b7 E1 S6 Q) E

  276. ( I* z$ c- K" |$ b2 e  x1 _
  277.            pSerList->Add(szSerialNumber);% ?2 W* s# G# r! ^9 c: t: A
  278.            pModeList->Add(szModelNumber);: ]6 A" y) b. B$ p. n
  279.        }
    ( {1 w2 v( L& w  R3 L2 `
  280.    }0 h4 j5 k5 c! G: ^# h1 |$ G& _
  281.    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
    2 m0 O! m1 o$ A/ R
  282. }5 S4 ~- m9 r5 W2 ~8 c1 m
  283. //---------------------------------------------------------------------------
    6 b6 ]  Z. L8 E: b# k) N
  284. // ReadPhysicalDriveOnW9X_Ring0()8 n; I! M% A% g
  285. //1 S9 S3 t; \- w, I3 n' P  Q' W; M" p
  286. // dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
    8 s* Z4 ^# O& W' x  |; [& C
  287. // btMasterSlave = Master(0xA0) Or Slave(0xB0)2 `, B6 o( R" |; B
  288. //---------------------------------------------------------------------------
      {8 C% ~8 H3 i. F4 Z
  289. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
    6 O0 l( G/ K9 D. l; f7 U; F! f
  290.        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
    % R) _, ^) J8 g) ]! N
  291. {
    7 J5 s* g' X' [' u- X
  292.    BYTE  btIDTR1[6];
    0 U, A) W7 r/ n1 ~( K
  293.    DWORD dwOldExceptionHook;! x- E) K& a2 j! w4 K/ L
  294.    const int nHookExceptionNo = 5;
    ; k( z5 L+ l2 d% T7 u$ O
  295. " v: N: \8 B* B7 H0 [
  296.    BYTE  btIsIDEExist = 0;4 P3 ^2 T$ E7 p5 W' E
  297.    BYTE  btIsDiskExist = 0;
    4 F  f: N4 e# b5 b2 r" j
  298.    WORD  wOutDataBuf[256];6 c: u. d  y$ Z/ A% V

  299. 1 x1 o4 J! t8 ]9 T, `* K
  300.    BYTE  btIsFirst = (BYTE)bIsFirst;/ G# u7 r2 |. O8 y& b5 t* K
  301. # w' c: y) y2 |; s2 O
  302.    const BYTE btBit00 = 0x01;
    8 l& {3 }# k0 O7 Z! F
  303.    // const BYTE btBit02 = 0x04;7 E9 g3 r9 I' L- x6 ^
  304.    const BYTE btBit06 = 0x40;" w! c# j0 E4 `. o6 N4 d7 a
  305.    const BYTE btBit07 = 0x80;  w. w* C! ?% V7 S9 p/ R( S
  306.    // const BYTE btERR  = btBit00;$ h( c% S4 m1 q9 Y5 S6 m# ]5 Q
  307.    const BYTE btBusy = btBit07;
    & A; s' q( `2 }1 _; F7 T1 f5 ]
  308.    const BYTE btAtaCmd   = 0xEC;
    ) n: q- T( o/ i% ~4 [6 C/ b2 w, k7 B, S
  309.    const BYTE btAtapiCmd = 0xA1;: @4 y8 s9 A2 x6 U0 Q

  310. / E$ p1 Y! U. q/ s: a1 P
  311.    __asm
    2 e4 d) F3 z+ S8 D1 b3 n! p8 U
  312.    {
    . N8 y9 a/ N& B+ ]
  313.        // 必须先执行这条语句
    4 c/ W7 J7 ?$ N- @
  314.        JMP EnterRing0
    5 m# G9 S/ J7 A/ W3 a

  315. 1 ?) m7 j/ l' [2 W4 P
  316.        // 定义过程
    : r" z, z1 X3 x' o# M
  317.        // 等待IDE设备直到其不为忙为止
    $ F. }% V% w5 X* P
  318.        WaitWhileBusy proc$ K) w$ O/ f1 R3 }5 B. T5 v1 v9 F
  319. ( L- T8 d0 `& ^4 N. V
  320.        MOV  EBX, 100000
    ) k! m- ?! ?3 a) g  X1 H! ?9 p. @
  321.        MOV  DX, dwBaseAddress
    , |' Z% A, D7 G
  322.        ADD  DX, 7
    2 ]" a1 k1 ?6 K/ l; _6 p- o1 ]' h
  323. 6 Y+ i6 A; {8 s* f
  324.        LoopWhileBusy:
    % n* U' G9 m# R) l1 [+ L# Y9 D

  325. ; F+ V( X0 s- k4 h/ k! c
  326.        DEC  EBX  r" F' Z. d/ `+ ~# p, b
  327.        CMP  EBX, 0& U3 |  c0 h# V! R0 r
  328.        JZ   Timeout' U- n2 y" O+ D2 _4 {7 y
  329.        in   AL, DX7 ?, ]3 T* K/ ]3 j( L/ f7 C0 K
  330.        TEST AL, btBusy
    / V3 Z7 I1 N0 v, L) }
  331.        JNZ  LoopWhileBusy0 c5 t7 b9 k( q0 U
  332.        JMP  DriveReady# Q3 o2 }! N( c5 O. [
  333. ! o2 J4 [# O- h% ^
  334.        // 超时,直接退出
    + j1 s$ j8 ?: a( O; b) W
  335.        Timeout:: a& e- D7 `6 `7 U2 Q1 G3 E
  336.        JMP  LeaveRing0
    0 s* i8 t" j6 _7 S. K! }" x# R" ^
  337.        DriveReady:
    3 V8 w9 h* b! p% y: X) a, E3 D) {
  338.        RET
    * o4 @+ ]& |: Q' N# G0 S9 X5 I
  339.        ENDP   // End of WaitWhileBusy Procedure
    , }0 ]$ Z9 {$ ]. ?. ~3 \9 k

  340. : d" W' p( w6 {- n6 O+ j
  341.        // 设置主盘和从盘标志& ]3 r$ ^$ I" u" J6 ^& h8 p' L
  342.        SelectDevice proc/ p5 f, Y9 ^- W: b
  343. - A, w- s) R. _$ _  R8 E$ y
  344.        MOV  DX, dwBaseAddress
    6 p5 z1 [# L- v
  345.        ADD  DX, 6
    & M& u8 a( A" X/ r
  346.        MOV  AL, btMasterSlave: h) R8 H$ P/ G
  347. ' ^2 w# z5 W  q
  348.        out  DX, AL
      B! `4 w1 X+ o9 o
  349.        RET" e2 `1 w/ ]: t

  350. . n2 a1 R3 r+ e6 s
  351.        ENDP  // End of SelectDevice Procedure9 q; H9 g. G5 G* q/ A; [1 E
  352. 0 O/ j! g5 Q9 g6 K  p. E! M
  353.        // 向IDE设备发送存取指令8 G3 t. d8 a. ~( ]5 c+ z! R6 g
  354.        SendCmd proc* J) q2 n' c) o
  355. 9 b- f& B3 ?2 v+ D6 X0 S" h% h
  356.        MOV DX, dwBaseAddress
    9 W" u. J1 W4 h/ H; P
  357.        ADD DX, 7
    / R1 W  ^( a- z8 |
  358.        MOV AL, BL // BL是主从盘标识,在过程外设置6 c% c: a, ]- v; r: N
  359.        out DX, AL7 a( o; {+ \9 s4 D
  360.        RET
    7 b# ?3 v) F3 h% u; w) b
  361.        ENDP  // End of SendCmd Procedure
    7 i) h! X, ?8 C2 c" ]. D

  362. , n3 O! F; G; o* P+ ^7 w
  363.        // Ring0代码
    ; u) w3 i  r6 t5 Y( U
  364.        Ring0Proc:
    : M' ?- Y) v( q" \
  365.        PUSHAD7 X/ w+ }9 L8 [8 ~5 B: h
  366.        // 查询IDE设备是否存在( H8 b/ g2 p9 [+ P7 `1 r% s
  367.        MOV DX, dwBaseAddress7 R7 V0 g1 R# @+ A5 r' C3 }
  368.        ADD DX, 7) B/ f) @4 I) J5 F* r6 n# \
  369.        in  AL,DX, m! R% c. @! \* I, ~

  370. 4 {! \; l3 w+ p" I
  371.        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
    8 u2 \$ g' I4 Y. _. ~2 W
  372.        CMP AL,0xFF1 T6 ~0 R! F+ }+ s# i: b8 ?
  373.        JZ  LeaveRing0
    6 L2 O: f5 e$ Y
  374.        CMP AL, 0x7F
    & J& Q+ a- H4 \* q# u3 W
  375.        JZ  LeaveRing0
    0 s/ U5 e9 x$ E0 W
  376. # A4 P" }! U- `$ r# i, ~# q% J6 W. O
  377.        // 设置IDE设备存在标志
    . q1 ~% n& v: U
  378.        MOV btIsIDEExist, 13 i$ I( B1 M7 C" V7 [6 N/ V8 |
  379. : V' A( [+ O, F) e$ X4 Q
  380.        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面); q& W# ~" p4 v* K; a
  381.        CALL WaitWhileBusy
    5 j; ?' C3 s2 t1 j. L6 f7 k+ c
  382.        CALL SelectDevice! q! I6 J  l1 x3 v. e: R
  383. - k' N5 P0 @5 G! o7 @- |0 a* }
  384.        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
    4 q. o4 R* D- H
  385.        CMP  btIsFirst, 1) K8 F) `* o$ L' }+ J
  386.        JZ   LeaveRing0
    % x4 I0 Q+ t9 S3 a" r

  387. ! Z( [6 }5 c9 ], B" h
  388.        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
    ' [4 ^' A, k6 h0 k6 {0 D
  389.        CALL WaitWhileBusy
    3 e" W% R2 u: G) j2 z# [0 c

  390. + v" l+ C( f7 b) X
  391.        // AL的值等于cBit06时,不存在驱动器,直接返回
    ; H+ D! r* r" h% i) F4 {( ]7 o# C
  392.        TEST AL, btBit06: a1 ]& ^  g) s2 _, a: g5 M- n
  393.        JZ   LeaveRing04 }1 Q$ Z0 c0 p% U8 ?6 S* Q/ F

  394. ' R" A# t4 v' }6 z& J, G
  395.        // 设置驱动器存在标志/ T; A/ G7 x  y+ L
  396.        MOV  btIsDiskExist, 1
    7 v7 J9 I, h) t) N) W- D

  397. * K" l  X+ F9 K* C
  398.        // 发送存取端口命令
    5 Z7 o. Z( \% `/ }) j$ u
  399.        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,! a5 u- z5 {0 s" F! Q* C
  400.        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
    1 @6 p1 f7 N: o+ R' ^9 C! D" U
  401.        CALL WaitWhileBusy
    # `* q  {- K; Q0 _5 |$ D
  402.        CALL SelectDevice    // 设置主从盘标识
    4 a; D( m0 @4 D- x5 Z0 H, F& [
  403.        MOV  BL, btAtaCmd      // 发送读取命令
    . d3 K5 g# g% }: D$ P: P5 c
  404.        CALL SendCmd% x, F9 |6 Y& a+ k2 _
  405.        CALL WaitWhileBusy
    * ~" E' R: n4 y( t, {

  406. 0 W% k. z1 y! q. b( f
  407.        // 检查是否出错( ~; p* A. U* Q3 d1 \
  408.        MOV  DX, dwBaseAddress
    7 U8 p5 t5 P3 r* q/ G0 Q. b
  409.        ADD  DX, 7
    ( y$ q3 B2 L9 B5 q& h
  410. + E: |( f6 q, z) P5 _/ M5 M) Z, T
  411.        in   AL, DX2 e1 N: f6 G0 e4 ^

  412. 4 q7 a9 x& h, p9 Q% q* Z
  413.        TEST AL, btBit00+ o- ]/ h$ W9 b
  414.        JZ   RetrieveInfo   // 没有错误时则读数据
    ! E( L0 e( B* L) ~( I7 `$ z* N, _1 p

  415. 2 L* }/ U/ {+ k  e. t
  416.        // 如果出错,则进一步尝试使用ATAPI设备命令
    + r: C% ^* b/ [8 h
  417.        CALL WaitWhileBusy! `8 U0 |5 J$ U% A8 T
  418.        CALL SelectDevice3 T5 y  |, ~% N+ \
  419.        MOV  BL, btAtapiCmd
    6 t; V( j+ H; R& A
  420.        CALL SendCmd$ T& |+ V$ j4 i1 L+ z3 g3 Y# _
  421.        CALL WaitWhileBusy
    . s% K3 i# Q5 k: L* S1 M! m# L" x
  422. - F3 g- {0 l) H& V
  423.        // 检查是否还出错
    - @5 ]3 x( b# q: Y+ a
  424.        MOV  DX, dwBaseAddress- E" b% T- i: k- g
  425.        ADD  DX, 72 N4 i& ]+ r- E$ z) \9 T) B% `
  426.        in   AL, DX
    7 V; f' a, Z) N! Q6 a" ^3 I0 }
  427.        TEST AL, btBit000 r1 T* ~0 W6 F+ V: H1 E! [
  428.        JZ   RetrieveInfo   // 没有错误时则读数据
    1 d& u8 F/ D, ?+ N; `
  429.        JMP  LeaveRing0     // 如果还是出错,直接返回6 j! R+ |* w* A2 c% j" r0 L

  430. . [7 I$ g0 ?$ K7 z3 Y
  431.        // 读取数据# r6 H0 p- [1 P
  432.        RetrieveInfo:
    $ Y' D; Q# E5 F$ @* b
  433. 5 r2 W3 l1 q  f0 d
  434.        LEA  EDI, wOutDataBuf
    , V* R# R0 G. ~7 }& [+ o
  435.        MOV  ECX, 256
    3 B9 S: i: A# V2 o9 {  D' I
  436.        MOV  DX, dwBaseAddress% m0 C+ k$ n: E$ @$ Y1 x7 n! L
  437.        CLD) t) J+ Z2 U0 b# h# M
  438. - G5 j" |7 }: \! D, w% ?8 V
  439.        REP  INSW6 ^" W1 l8 p: P4 J3 y$ I3 R5 T
  440. ! w( [9 b* J% K" i
  441.        // 退出Ring0代码
    8 l, V- D' E, x2 Z0 e* ]- F
  442.        LeaveRing0:
    ' u; F) c3 ]6 e" A: H" \. W
  443. / M6 H' ]$ J1 V
  444.        POPAD. P' _, G/ @3 e  {' v) v
  445.        IRETD
    1 a$ v9 _! z2 P! j

  446.   V7 K% \/ k+ F$ O" G8 P# {
  447.        // 激活Ring0代码- R7 @1 M9 q$ q7 R8 W0 G+ B5 W
  448.        EnterRing0:, @0 d/ C' p) M+ p7 U$ x( x- y! W6 ]
  449. / h/ l3 o' E; a( b: m! P
  450.        // 修改中断门4 X3 w" T, k/ U% p0 o3 S
  451.        SIDT FWORD PTR btIDTR11 o" h$ d0 T8 ]9 c, g8 F6 z
  452.        MOV EAX, DWORD PTR btIDTR1 + 02h
    % @& ]# `" g% u5 r! L
  453.        ADD EAX, nHookExceptionNo * 08h + 04h/ e' O' t+ W# o1 y- n
  454.        CLI, h- x" x6 f2 b0 c

  455. * l% t/ u8 F$ R! ~7 V) g* C* e/ s
  456.        // 保存原异常处理例程入口9 q0 ]% Q: ^) Y& d. Q
  457.        MOV ECX, DWORD PTR [EAX]' R/ ?  o, c+ h$ E  |
  458.        MOV CX, WORD PTR [EAX-04h]
    4 V$ g1 Y+ o9 ?# ?6 \+ P3 O1 s7 _
  459.        MOV dwOldExceptionHook, ECX4 s) |- e2 J- G$ |0 n3 \* ~

  460. 0 C5 {* X  o: B: L5 A0 B# [
  461.        // 指定新入口" x! q" J9 G* C2 m( ~. {1 }
  462.        LEA EBX, Ring0Proc
    " e% k0 n2 `6 c7 }7 F* V
  463.        MOV WORD PTR [EAX-04h],BX
    9 J- G) B8 Y; j
  464.        SHR EBX, 10h5 a/ O, \. M' L# f
  465.        MOV WORD PTR[EAX+02h], BX
    9 e$ H, e) E! ~9 l
  466. * G+ [. S5 ?1 L/ f7 i8 E. \5 w1 ^
  467.        // 激活Ring0代码
    7 J7 A% |3 `, H; K1 S% a
  468.        INT nHookExceptionNo8 q' N' X  H0 x/ ^" }( B
  469. & m4 O! H8 n" M2 M3 Q8 A
  470.        // 复原入口
    " }, \: v* Z2 u* W
  471.        MOV ECX,dwOldExceptionHook
    2 X# f& N4 d7 ]$ ]7 {) r
  472.        MOV WORD PTR[EAX-04h], CX
    ( w/ w% i7 n! Z
  473.        SHR ECX,10h  s& D' L* |+ t" [% Z
  474.        MOV WORD PTR[EAX+02h], CX1 ^! n& [3 c$ m( v1 I0 `
  475.        STI( x0 a0 V% z4 j% ?. ]
  476.    }$ W, B; J) Y# A' N* C" P
  477.    if(!bIsFirst)
    , x( g6 m; e6 ~2 {! N$ r! n
  478.    {) n  u- h4 Q$ B) w+ o' q0 _/ E
  479.        bIsIDEExist  = (bool)btIsIDEExist;
    7 o) S; g# k1 h( R* m
  480.        bIsDiskExist = (bool)btIsDiskExist;3 C# D( [) s! o  \/ N' n  ?( b' U
  481.        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
    ( I- v' q7 X6 ~$ j" b
  482.    }
    * d7 p, a& m6 M) G$ w
  483. }8 q" S1 \# k" b
  484. //---------------------------------------------------------------------------  h6 f& g* l  G) j% H
  485. // 调用方法:; D% P- D5 T3 ]( B
  486. void __fastcall TForm1::Button1Click(TObject *Sender)& j- C- n, O, X, Y5 c5 Q( N4 d( W
  487. {: T6 [& w* z" A. w. p
  488.    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
      Z+ W; S7 Z% y7 R% ~; f+ @
  489. }
复制代码
发表于 2005-8-15 01:00:45 | 显示全部楼层
晕乎乎。。。怎么看8 洞阿
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-8-9 06:27 , Processed in 0.035952 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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