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

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

[复制链接]
发表于 2005-8-11 11:42:04 | 显示全部楼层 |阅读模式
  1. #include <WinIOCtl.h>
    " Y! W! g4 f; P. a/ l
  2. #include <stdio.h>
    # p  x! ~( b/ F% }

  3. 1 i$ Q9 \% Z9 e$ y( x
  4. #pragma inline
    3 k7 G" ]9 O9 U/ O
  5. //---------------------------------------------------------------------------
    8 Z- r; j! L( _$ f; I
  6. // IDE NT/2000/XP专用变量
    ; J4 G/ _4 |4 L& l
  7. #define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
    1 M# @, `7 M7 t) x
  8. #define DFP_GET_VERSION         SMART_GET_VERSION
    4 v: H3 g# [3 u8 g
  9. #define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND. }9 n4 ?$ F% |$ @$ I6 m
  10. #define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA& f9 I: \, n0 H; a& X
  11. 1 S( V/ ], Z, z9 |7 @
  12. const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令1 ~* H4 u# J9 K
  13. const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
    $ {: ?- H' F) {$ {7 B  R" T
  14. 5 \& Y# b  V  y5 D6 G6 Q' L
  15. const int MAX_IDE_DRIVES = 4;* ]* L  f# @( M) {" B- Z  O

  16. 5 x; P. z& B5 h% K& p
  17. // SCSI专用变量
    9 Y8 N; \- a/ w1 z' {9 ^) I9 K
  18. const DWORD FILE_DEVICE_SCSI             = 0x0000001B;1 s9 ~$ D! i8 q0 l
  19. const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);5 C- ^- D5 h5 ^# o! q& {. E& ]9 o
  20. const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
    9 H$ W& ^$ M- B4 z( \3 @; u; ~/ I
  21. const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;, f+ w+ \+ @2 N: M( r
  22. 6 ]" ^* _1 O" ]
  23. typedef struct _SRB_IO_CONTROL/ i( t1 t% y$ [! H
  24. {% ]8 N% j5 z2 k! a$ }
  25.    ULONG HeaderLength;. h( V+ g. D2 h
  26.    UCHAR Signature[8];+ S  d  h8 |7 m/ K3 N+ ^* _  `+ I: e
  27.    ULONG Timeout;
    8 F' F' x. E" o# M
  28.    ULONG ControlCode;
    % R* Y6 ]/ U+ c, |, `
  29.    ULONG ReturnCode;
    9 z1 \' h" J+ }. U( I5 P! |
  30.    ULONG Length;  U6 a- [3 b( \
  31. }SRB_IO_CONTROL, *PSRB_IO_CONTROL;
    & _. n! W5 E+ f- }6 d

  32. 6 \! n& I# e& K+ ]$ i3 k- v
  33. // 读取的主函数1 }+ I4 g& Q  ]" E
  34. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);5 B8 W' a/ b+ t( Z5 t

  35. * Y- S1 I* B6 z# [+ \0 x, g
  36. // 辅助函数& P0 W% i% t% T7 \
  37. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);9 o: C( X3 z4 t% C1 e1 B6 W  S5 y
  38. // NT/2000/XP函数5 o# x8 u1 G8 K$ W, e7 A. o% r
  39. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
    $ M  h% `/ y( Q& R
  40. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,' P1 O3 t1 Q; A
  41.        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
    , v0 U/ c3 y- p% W9 L2 [" w
  42.        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
    . e% ~! A2 P2 I" r0 v, b
  43. // Windows 9X函数
    8 E2 b+ B* X: G( E/ I
  44. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);
    0 Z1 n% E  r8 y' I$ O. I1 z) t: O
  45. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
    * C$ ^% t# g1 J8 P' d: Q  `
  46.        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
    8 M' ~, K: k# `! q! ?3 g

  47. ' u7 a* S/ q) t) Q2 M3 T
  48. // SCSI读取函数(for NT/2000/XP)6 E6 A$ Z( j/ m1 d7 @8 |
  49. String __fastcall ReadIDEDriveAsScsiDriveOnNT();
    ; N' U5 p; |: A$ r  r! Z
  50. //---------------------------------------------------------------------------
    0 A& i5 U* r* M, m% D
  51. // ReadPhysicalDrive  X9 I4 A, O$ e$ \
  52. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)$ i+ J: @3 n: D0 |
  53. {# E. B1 G6 t% {# n; r5 H
  54.    switch(Win32Platform)& Y6 x; s: s: w9 Q6 D
  55.    {, n* n! H$ j! U& I8 x
  56.        case VER_PLATFORM_WIN32_WINDOWS:
    4 X/ {7 H9 Z7 K( V% [4 P6 M
  57.            ReadPhysicalDriveOnW9X(pSerList, pModeList);& r% N" r$ ?2 f- I, K
  58.            break;
    8 [" {' D( W9 }
  59.        case VER_PLATFORM_WIN32_NT:
    ; V6 |6 ^! L( c& s
  60.            ReadPhysicalDriveOnNT(pSerList, pModeList);. `: R% V5 e, k7 c5 y6 a* u0 p
  61.            break;4 c1 e. M( N# c7 @, i1 I: W
  62.        default:+ z  U6 p& s$ T- Q) N/ E, ]- M
  63.            break;
    ' v; z* n- d8 q4 }& p  ^
  64.    }$ L2 X. Q; M' t. m0 A5 g
  65. }1 o0 p' Y# [# ]% y
  66. //---------------------------------------------------------------------------
    0 F; M/ Z' Q) K
  67. // ConvertToString
    9 B! T* R2 Y& |& t8 ?- r6 H
  68. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)" w& n/ D) v  |7 f/ S5 ^, b' s! B
  69. {
    ! Y/ O% ~  X7 G- U
  70.    static char szResBuf[1024];
    ' x+ _# r  |7 O
  71.    int nIndex = 0;
    7 h  x5 _# {2 A2 t' e$ v
  72.    int nPosition = 0;5 a, I' |: v# l2 `8 \% w
  73. 9 r' ?% G7 Q& \0 T4 M5 i7 i
  74.    // Each integer has two characters stored in it backwards! f& |9 j- u; n8 r9 S* b* s( k
  75.    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)6 T, D+ `" T  E9 i  K* E
  76.    {. ^1 `8 M! F% ^; C
  77.        // Get high BYTE for 1st character
    ) P+ I# \/ m5 V  B( [9 Y
  78.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);1 L2 K! ~0 \+ t# c5 d
  79.        nPosition++;
    - ^$ G  ]. r: a4 _

  80. - J, G% p9 Y5 b. d1 `/ ^
  81.        // Get low BYTE for 2nd character7 j. v) U( i0 b' ^$ V- E! D6 \( ?
  82.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);0 u, G9 m( M) r4 n- \9 C- W1 V8 |0 h
  83.        nPosition++;
    . T6 ^6 Y" e. B1 X4 b' n
  84.    }6 ?8 @7 [  V2 j! X; a6 m' x& S

  85. " i, Q3 [4 k! r3 N% O. @
  86.    // End the string. T8 q1 o1 P' @
  87.    szResBuf[nPosition] = '\0';/ h7 f) J* y2 C! N' {+ X/ Z. m  C

  88.   x; i! L. M( Z* r! t
  89.    // Cut off the trailing blanks* J' S- \- W: x3 i. C5 [4 A
  90.    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)& ^. k* |: t9 x/ Y
  91.        szResBuf[nIndex] = '\0';1 O6 ?& u! W% [* n* a( U

  92. & ?0 W9 ]* ^$ `) z$ T( }: |
  93.    return szResBuf;
    - z. R3 m0 Z. b
  94. }
    * v* \; n6 p5 {! b) r0 o* x0 ?! \
  95. //---------------------------------------------------------------------------" k( v/ w; W' R7 \: m4 s
  96. // Winndows NT4/2000/XP 代码1 H/ ~7 L" P7 f0 }& j
  97. //---------------------------------------------------------------------------5 k$ F3 u; ^  p& ~, Q  d
  98. // ReadPhysicalDriveOnNT
    ' V3 v5 L( T; R/ K
  99. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
    % R! I7 j7 D$ e: G" z' g6 L9 I: _
  100. {0 t- x! o2 F1 q8 f& R/ l# Q
  101.    // 输出参数
    , d! i9 c6 p5 c
  102.    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];- K1 m( B8 u1 v
  103. " a4 |: {' e2 s' J0 o
  104.    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
    ! h$ g- I2 B* ?: j4 b
  105.    {
    ( \0 {& w, V5 h; V
  106.        HANDLE hPhysicalDriveIOCTL;! L/ O2 T1 y7 K' V' [, W; _8 ^
  107.        char szDriveName[32];7 P$ @+ A( N0 ^! ^

  108.   N1 g/ g: M5 U# z! _3 x6 s
  109.        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
      E+ I& `- U+ D# A2 V
  110.        hPhysicalDriveIOCTL = CreateFile(szDriveName,' b9 M: ^2 M. `7 w7 U
  111.                        GENERIC_READ | GENERIC_WRITE,
    ! T/ A' M1 x6 y9 P6 V! `
  112.                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,# G* }) B( {% G7 J* U! G* [
  113.                        OPEN_EXISTING, 0, NULL);* A4 V# c* W; _

  114. ' x; {# w: @2 r7 M
  115.        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
    6 u) v6 F/ b2 J
  116.        {
      L2 L  Y7 {) C# ?
  117.            DWORD dwBytesReturned = 0;1 t& G, p, X6 `
  118.            GETVERSIONOUTPARAMS gvopVersionParams;. f8 E# ~! L0 Z1 `& h3 l

  119. 3 ~0 T8 D& d6 o) n1 w  E7 p
  120.            // Get the version, etc of PhysicalDrive IOCTL
    , N1 \) R, U# Z9 t+ C3 E7 }
  121.            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
    " E/ T6 G" C6 T- q
  122. % N$ {& N3 w% L+ U$ O
  123.            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
    ' U2 u" C9 ]) w* h! f  v2 n6 ]
  124.                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),3 J5 x' f$ M! k% w% |2 z
  125.                    &dwBytesReturned, NULL))9 \* r; M& s- p0 l3 M; ]
  126.            {
    6 @  {1 y% O, G9 N. z
  127.                continue;
    1 z4 c  W' u: ]- b3 x
  128.            }
    + W" R+ l( p& `" ]9 a
  129. - {' U+ \7 u0 C6 M$ w/ g0 J
  130.            if(gvopVersionParams.bIDEDeviceMap > 0)
    ) R4 R! I8 x2 ~2 H% F& R
  131.            {: e2 E% H$ C0 n$ A0 n) G
  132.                // IDE or ATAPI IDENTIFY cmd
    ) G3 b) {; _6 \# }8 W
  133.                BYTE btIDCmd = 0;
    1 w- B  m8 H# p8 ?
  134.                SENDCMDINPARAMS InParams;
      _/ N. Z9 e4 Z* ^
  135.                // Now, get the ID sector for all IDE devices in the system.
    4 z4 t6 |! j9 J* y( k5 a
  136.                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,3 }8 ]" e6 m# H! ~$ [
  137.                // otherwise use the IDE_ATA_IDENTIFY command# f8 G% X: u3 [2 Z
  138.                // 具体所得结果请参考头文件中的说明
    $ m' X- b7 j, m) Y9 N( G
  139.                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
    9 G2 L. q7 C1 Y. ^" [
  140.                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
    * n+ [& b+ _5 I( [( e9 n0 _
  141.                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
    6 Y  {$ _7 i3 v
  142.                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));( |( L) ?% f  l- u1 J, d, z  I
  143. 7 l% x6 Y2 p0 C% B( n
  144.                if(DoIdentify(hPhysicalDriveIOCTL,. e1 `) c+ B5 S& k* h
  145.                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
    % ]; J: O. E* \6 _( r6 I
  146.                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
    + l6 k( j+ y. p5 H% \* ~
  147.                {
    2 X: e8 }5 y6 i/ L
  148.                    DWORD dwDiskData[256];
    5 G; `+ d0 v; ?9 \6 m
  149.                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
    $ N0 @2 y& v& W1 h) J! K5 {* `
  150.                    char szSerialNumber[21];' p0 L: c" B" }# P& N- v. X2 [
  151.                    char szModelNumber[41];' ~# `+ V; \5 c
  152. # K0 R& t  O6 u* \# F
  153.                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;+ c$ l9 Q- F2 J4 b  a
  154.                    for(int i=0; i < 256; i++)1 [- D( _- k5 ]) M( D" [$ E8 O, e4 g' F
  155.                        dwDiskData = pIDSector;
    : m; `/ k! H9 X- ^! z
  156.                    // 取系列号
    6 y) t, r$ C& L' Q3 s
  157.                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));8 L0 q4 P$ K! {0 H: B; Y; A0 ~
  158.                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));7 G( W% I0 w3 r9 O

  159.   w1 y$ T3 n0 [/ V! R- f1 d8 B' K8 q
  160.                    // 取模型号3 ^. u( S1 x7 `
  161.                    ZeroMemory(szModelNumber, sizeof(szModelNumber));9 Z8 i7 N& T6 m- K
  162.                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));% M4 Q5 s1 O$ J8 l& [
  163. ! V- j: H% S1 U# Z" Z& b- Z
  164.                    pSerList->Add(szSerialNumber);
    6 |  [3 c% `0 t5 d* N
  165.                    pModeList->Add(szModelNumber);
    ! ^3 I8 K" s; A$ R
  166.                }
      I  I3 R. \7 }: K' n" t$ V: a
  167.            }
    ( {* I( {0 Y2 d
  168.            CloseHandle (hPhysicalDriveIOCTL);
    $ y3 m( c( G% N/ P  F  A, t' {7 D
  169.        }
    * J) d2 O" u! `# `: L# v
  170.    }/ l: l; j* h  n, i! @: p9 m( T( v, U. Q
  171. }0 y2 ?( p: [' B9 b+ ?+ |+ W7 T5 S) ^
  172. //---------------------------------------------------------------------------
    . E! k( z. y. F! h! b: |4 i- I4 u
  173. // DoIdentify
    / {5 p+ d# P: h* F
  174. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
    1 [8 V( S# q" _0 H- @, d, }, C
  175.              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
    + k5 `& m6 w: q7 Y% B' r) c
  176.              PDWORD pdwBytesReturned)3 d) d  R+ _" O/ i2 d$ D
  177. {, n6 d; t9 N' S* ^) F# y' v
  178.    // Set up data structures for IDENTIFY command.
    ) j5 F' V( P$ y" |
  179.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
    # S' D7 Q/ ]2 b5 d
  180.    pSCIP->irDriveRegs.bFeaturesReg = 0;
    9 N1 S3 |6 }1 x  F. _6 P
  181.    pSCIP->irDriveRegs.bSectorCountReg  = 1;
      v" j9 ]8 m& D% K+ d
  182.    pSCIP->irDriveRegs.bSectorNumberReg = 1;
    & z% W( e; @; _
  183.    pSCIP->irDriveRegs.bCylLowReg  = 0;) P+ Z/ X$ \) W/ v' e5 C
  184.    pSCIP->irDriveRegs.bCylHighReg = 0;
    ' G3 o% ]+ S" j% R# W9 _& _

  185. % y- Z9 a7 g( u* o; R! u) ]
  186.    // Compute the drive number.(主盘和从盘所对应的值是不一样的)
    , ~) F7 b% V% k, o" r$ U. M5 {- E+ |
  187.    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
    2 Q0 S2 O' y& ~% q

  188. . S' g+ P7 c8 `) T; k3 S
  189.    // The command can either be IDE identify or ATAPI identify.
    , O3 b" h! R, F3 m: t
  190.    pSCIP->irDriveRegs.bCommandReg = btIDCmd;& L0 g! ?/ \3 G, B
  191.    pSCIP->bDriveNumber = btDriveNum;
    9 y7 o0 |& ^7 R/ z, J5 p
  192.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
    8 {! r% E9 n9 E. x: J+ O

  193. 0 x; Y, [$ b( c6 T$ H
  194.    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,0 ?5 N$ D1 Z: v0 n# i/ a$ R& S+ P: n7 d
  195.           (LPVOID)pSCIP,, l* r/ J8 ~6 |
  196.           sizeof(SENDCMDINPARAMS) - 1,7 t! l8 i6 P3 ]
  197.           (LPVOID)pSCOP,5 ^& \$ b2 y9 {% V& c& o+ Z6 w
  198.           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
    9 ]2 O/ O9 l1 ]7 M
  199.           pdwBytesReturned, NULL);5 }' \0 H0 }1 ?6 I( m, D
  200. }' y  T1 ~5 c7 w1 B
  201. //---------------------------------------------------------------------------
    * N& U1 J$ w: ]) L" S$ Y# i
  202. // Windows 95/98/ME 代码
    & E2 ~% W+ {. {7 H- l
  203. //---------------------------------------------------------------------------
      _% J) r* e1 e- B6 D
  204. // ReadPhysicalDriveOnW9X
    0 M' Y: `* `1 [; V  _: Z  W
  205. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)
    + [- `) |+ D; o7 S- A! Q0 _8 h
  206. {
    + i8 M; Q: X8 v6 \& [6 x7 E( V/ `
  207.    WORD wOutData[256];
    , @; E# |  }  V) N) R
  208.    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);) `0 {3 [) I2 k, _$ m+ F
  209.   t; o* m' d  t3 C; I2 P/ n/ }
  210.    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。: d# }4 F& O+ t; z  {4 p$ Q
  211.    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以. ^8 }  o; c- _2 V3 f
  212.    // 避免蓝屏的出现。(期待高人能指出原因)
    " [9 b, Q: F* k5 E
  213.    for(int nDrive = 0; nDrive < 8; nDrive++)3 o: t' ]2 p6 e! D0 C) l& H+ ~
  214.    {
    ! n* w! E: V& P! L6 R2 z
  215.        WORD dwBaseAddress;4 v; `/ t" \3 B; l& M$ K3 c
  216.        BYTE btMasterSlave;         // Master Or Slave& ]2 `+ y8 t9 D& B3 j" N8 f& M
  217.        bool bIsIDEExist;' {+ g# d& ]7 G  |# D; I1 s- e# w
  218.        bool IsDiskExist;/ D3 v: B% P# V  d
  219. 0 `: D- P, u. J& K
  220.        switch(nDrive / 2)
    0 q4 ~% a; F% K9 w- _7 x- k# T
  221.        {# G' Q0 I) w$ n  f0 q: R
  222.            case 0: dwBaseAddress = 0x01F0; break;
    & q' N4 M, f3 r: ~4 i
  223.            case 1: dwBaseAddress = 0x0170; break;( k% e3 ]$ s2 \' K
  224.            case 2: dwBaseAddress = 0x01E8; break;3 B3 e5 y  Q8 Q/ ]2 i/ @
  225.            case 3: dwBaseAddress = 0x0168; break;
    9 \( _* e0 e4 F# J
  226.        }+ I7 C+ B# L) o! Z8 F2 l- X
  227. / h1 I* w) I# K6 i' e+ L4 f
  228.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
      `6 Q# r% ^: y. Q/ |" z& h& h
  229. 9 Z: a: f" p  I8 m0 R* T! P
  230.        // 进入Ring0% h! w: e3 E3 }% A7 o
  231.        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
    0 g* L5 t. R& y5 u% g8 p; D, r. n8 M) P
  232.                bIsIDEExist, IsDiskExist, wOutData);  R( S  ~" ~3 d4 L
  233.    }9 N" k; z( i) g
  234. / x' M. X5 T" Q9 G. y/ ]: G
  235.    // 开始读取
      K/ J2 Y' E" K* q  k. l# j
  236.    for(int nDrive = 0; nDrive < 8; nDrive++)( s! v9 O* T* y# Y5 v
  237.    {: C, n* ]6 T, [3 Y8 T& D
  238.        WORD dwBaseAddress;' _) b; _7 u- `5 I* e, `
  239.        BYTE btMasterSlave;         // Master Or Slave  _, l. q6 V  @$ v
  240.        bool bIsIDEExist;: @5 J3 ~" M6 g/ W
  241.        bool bIsDiskExist;6 a9 S  _& ^9 j) L
  242.        switch(nDrive / 2)
    8 q4 O. ?; Q0 b. U
  243.        {
    0 g( f; v) z  R5 h& v1 {
  244.            case 0: dwBaseAddress = 0x01F0; break;: i0 b) k' [& Q- J! t) s
  245.            case 1: dwBaseAddress = 0x0170; break;
    4 Z4 ^) z3 j1 O$ R
  246.            case 2: dwBaseAddress = 0x01E8; break;( R1 [9 L6 b) h* w
  247.            case 3: dwBaseAddress = 0x0168; break;
    1 n% z7 ]) S) Y$ J
  248.        }5 ]8 l& e' a  H: F: _
  249. 9 d- n+ ~& B  i/ m! y' p" x, A
  250.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);8 V5 j4 a' j0 i) Y: q

  251. 2 J6 U  {* \6 ?7 @: K5 d: e
  252.        // 进入Ring08 ^9 h, R  d* o9 L! d+ w/ D: Y
  253.        bIsIDEExist  = false;! ~1 x% P& k5 G
  254.        bIsDiskExist = false;
    2 j4 g  a5 T' E- X9 @# B2 l3 m2 O
  255.        ZeroMemory(wOutData, sizeof(wOutData));
    & x! C6 B& v! }7 C
  256. 7 ]1 Y. w6 r. R( h0 d( F8 o, ^
  257.        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,6 M, V4 T  q: {/ G: B& O) X6 Z
  258.                bIsIDEExist, bIsDiskExist, wOutData);
    - h( r3 L8 p: `/ ^* M# X6 j

  259. 6 }# Q+ I, W4 N' v/ z7 }# D
  260.        if(bIsIDEExist && bIsDiskExist)" p7 v. O6 K; x- [! D. b
  261.        {
    9 N! r, Z" ?$ d" q
  262.            DWORD dwDiskData[256];
    5 j5 E& D- O7 q
  263.            char  szSerialNumber[21];
    ' I9 K* w" j5 Q9 U+ W
  264.            char  szModelNumber[41];, r- x0 ?: y4 J/ H3 \. T# @/ {+ M

  265. ' f1 C7 Q' J3 ?! I( P9 @8 o
  266.            for(int k=0; k < 256; k++); r; `! Q( [0 o! k
  267.                dwDiskData[k] = wOutData[k];( }( A3 `  }7 j: D. S! I

  268. " ^/ o# y' c, n6 Y) Q7 E' E
  269.            // 取系列号0 f) ~% E; N3 n% |' |
  270.            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));( M; d% H3 v/ Q
  271.            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
    $ p/ T: L4 q* p4 ?/ H2 T8 q0 N
  272. $ \5 }/ O8 S2 {& L
  273.            // 取模型号
    % A1 W$ W+ }' G) {* @) Q
  274.            ZeroMemory(szModelNumber, sizeof(szModelNumber));4 u  k. C8 ?& @2 R, l8 O
  275.            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
    8 I, |  v8 n& k2 g
  276. % @: s: F7 G* k, T9 e, R$ q, P
  277.            pSerList->Add(szSerialNumber);
    8 [5 b: a' i. m) Q: t% r4 S& X
  278.            pModeList->Add(szModelNumber);. U4 W/ l# F+ e; t, H' p9 x- G
  279.        }& C# b( w4 x6 y! Y$ E
  280.    }  w  w' i* j% |. @* N) j) q7 u0 b$ i0 w
  281.    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);, S5 ^* b+ \- ]  |) p' a# e' [
  282. }9 w& F  w/ v# ?$ T6 i
  283. //---------------------------------------------------------------------------
    9 x( d3 N4 o2 x3 J( g9 D- h, X5 o
  284. // ReadPhysicalDriveOnW9X_Ring0()6 Q' m4 i' ]4 T- @
  285. //' l" b* K$ G( \* n1 Y
  286. // dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h' _6 R: d3 _8 t4 f* F$ G1 ?  l% i
  287. // btMasterSlave = Master(0xA0) Or Slave(0xB0)
    ; f4 K/ y' V" y8 D( B
  288. //---------------------------------------------------------------------------
    ( h8 V' P* S& O0 U
  289. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
    ) s( w2 c& T1 a9 k8 o
  290.        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
    : j/ d! N/ p" w- h5 S
  291. {: N- \! u2 l- I% p; d: |
  292.    BYTE  btIDTR1[6];
    ! c& b: j% k6 {( m" T
  293.    DWORD dwOldExceptionHook;
    * ^8 ?) ~3 Z" w3 @2 W& d) a  X
  294.    const int nHookExceptionNo = 5;
    2 X" @# k/ L" |- Q2 Y7 e
  295. ! A% S2 q# J( w" J- t; Q  A
  296.    BYTE  btIsIDEExist = 0;
      k: i1 e  s* k! l
  297.    BYTE  btIsDiskExist = 0;3 ?4 n1 J. {6 L
  298.    WORD  wOutDataBuf[256];
    0 n# X" q- A. s
  299. " l5 i+ g# ?$ W* t3 x
  300.    BYTE  btIsFirst = (BYTE)bIsFirst;
    ; ~* d$ d+ S* V8 _; A$ ?' B, y) `

  301. 8 c* G* A; [) p4 C6 h2 j
  302.    const BYTE btBit00 = 0x01;
    2 W' w/ ?& q3 Q& G$ ~+ }
  303.    // const BYTE btBit02 = 0x04;
    . t0 X; [+ `8 O  [5 k
  304.    const BYTE btBit06 = 0x40;6 n$ X" I0 k3 I
  305.    const BYTE btBit07 = 0x80;
    7 f) G8 }( O4 g7 I) U; j) [4 ]6 K  m
  306.    // const BYTE btERR  = btBit00;
    + a8 Q2 `; z0 j8 R
  307.    const BYTE btBusy = btBit07;
    * Q' S* @1 k7 }( T$ F
  308.    const BYTE btAtaCmd   = 0xEC;6 J) w4 c5 K) k* J# Z
  309.    const BYTE btAtapiCmd = 0xA1;
    # g" a9 q# M: M

  310. ' w/ I3 t- \4 y' [5 a
  311.    __asm/ {4 V1 @. |  e
  312.    {
    / Q( y8 R7 k: e( I6 A
  313.        // 必须先执行这条语句% F5 v4 d  G7 i( D4 l* q4 s
  314.        JMP EnterRing0
    " E, H0 H( a/ k9 h

  315. % X  z* v3 @3 x+ |: u. J
  316.        // 定义过程  T% ~' W- w  Q3 B! N# q
  317.        // 等待IDE设备直到其不为忙为止& E) X& A# f1 N3 p1 C: v: W
  318.        WaitWhileBusy proc
    ' r4 }1 ~8 K( V8 e2 v

  319. ( v& S5 j$ j% R6 x! Z) S  M
  320.        MOV  EBX, 1000009 d9 W1 k: h' f5 \! \. c8 J. S
  321.        MOV  DX, dwBaseAddress
    . ]7 n6 z% u' y
  322.        ADD  DX, 7: I! ]3 H% w3 w9 I; f" @* c0 D
  323. . H7 ], f! w" F5 R
  324.        LoopWhileBusy:
    8 L3 H+ g% G: T  [  t  b1 g5 c

  325. 7 k! {+ D! A- y) {: C3 F' O
  326.        DEC  EBX
    . V- O2 W1 t( k7 }! v
  327.        CMP  EBX, 09 s, C3 @$ P! U6 M
  328.        JZ   Timeout
    + |0 W9 ]4 T' |5 \
  329.        in   AL, DX' E1 b; P( D3 {
  330.        TEST AL, btBusy
    1 w& o& _4 F8 w. e; o, d" Z
  331.        JNZ  LoopWhileBusy0 ]  |* H9 a+ O' t( Z! e/ a
  332.        JMP  DriveReady+ d+ Z4 Z5 X& J, T/ `0 Q

  333. 0 l! D# `. X$ ~, E. p
  334.        // 超时,直接退出- o/ V: r  F+ r0 S6 `3 ?
  335.        Timeout:
    * o" Z- R3 K  A
  336.        JMP  LeaveRing0
    - N- d3 V0 ?6 M
  337.        DriveReady:; O4 v, L) w+ b+ q' Y
  338.        RET3 t% L& ~9 K$ L' }$ ^1 U0 }
  339.        ENDP   // End of WaitWhileBusy Procedure& j) O0 F1 p) `) Y5 g

  340. 9 o( H3 d5 L/ O" Y
  341.        // 设置主盘和从盘标志2 W( P4 L" Y3 m; T
  342.        SelectDevice proc
    $ a9 V2 i: w. f1 i  y3 K8 [( L/ D
  343. 0 |2 [, P3 Q$ z& O( F6 I' I
  344.        MOV  DX, dwBaseAddress+ S2 N9 s) H! A+ U5 d
  345.        ADD  DX, 6$ ?6 r$ z" Y6 D/ X! M8 L5 ]* U4 \" H6 L
  346.        MOV  AL, btMasterSlave
    ( Q: U6 q" D; z1 `
  347. 2 N- u5 }+ D1 O5 U* {! R( ~2 L
  348.        out  DX, AL
    % {8 Q+ w; F! e0 y8 l
  349.        RET
    5 N' {0 F2 d' x2 a2 F5 c! _1 B$ v

  350. 3 ]1 _1 M6 \4 s
  351.        ENDP  // End of SelectDevice Procedure
    , e; Y# S, ~  l( z

  352. * ^* h& e6 G+ q7 ]' m$ M1 x
  353.        // 向IDE设备发送存取指令
    1 U' m, \6 H% \
  354.        SendCmd proc& ?# q* e) ^; t7 g, h: k
  355. # w4 U1 z- l" r9 l& [" o! ^
  356.        MOV DX, dwBaseAddress" ?8 M! o" ^) ~$ r
  357.        ADD DX, 77 f/ b! V- b' @0 s+ }
  358.        MOV AL, BL // BL是主从盘标识,在过程外设置0 I% X. ^# l' q/ N- e
  359.        out DX, AL7 V/ B  O' \! B2 o
  360.        RET
    3 t1 V8 y' h0 ?$ h
  361.        ENDP  // End of SendCmd Procedure( M$ T6 |& F& Z

  362. % m8 f- c8 h* ?" {& v% Q) @: S( g/ y3 e2 n
  363.        // Ring0代码, @, o- B" v0 d  a7 Y8 t
  364.        Ring0Proc:
    ' |$ X2 @/ J5 n) G6 O' n8 F
  365.        PUSHAD: e. G* g& }8 h5 c4 y
  366.        // 查询IDE设备是否存在
    1 `6 Y& P  z/ S# q3 F5 s
  367.        MOV DX, dwBaseAddress, q6 v5 ^# ^8 U  e& e, W0 [
  368.        ADD DX, 7
    8 ~. a/ j+ ]/ U) N9 N
  369.        in  AL,DX
    ) v. W  W, q, C0 I# {$ ]

  370. / M  M5 @# A8 h* j) \& ~9 u* e
  371.        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回) p6 U$ i, i5 j* `/ Q
  372.        CMP AL,0xFF- ?' `% w  j- M$ D4 T
  373.        JZ  LeaveRing0
    ! h; @  }3 C7 F' |
  374.        CMP AL, 0x7F
    & x# Z7 m3 O2 O& z/ L& `8 Y
  375.        JZ  LeaveRing0
    4 Q5 Q  p5 J' L( O( a

  376. 5 T+ p  V0 H% w1 O0 x. Z2 H
  377.        // 设置IDE设备存在标志
    , T& P8 O6 t# i, e6 Z
  378.        MOV btIsIDEExist, 1& j9 [& t9 e2 {: L1 ^) X
  379. - J: k3 n  h# v5 C* z: I+ V& J
  380.        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)4 \) s" J6 X) l9 l( m
  381.        CALL WaitWhileBusy# g, j) }) Y5 F/ ~% ^7 b2 H# Z
  382.        CALL SelectDevice8 T: w. v/ Q$ Y3 \
  383. # m% H7 p$ Y& T. ~: K; K0 k) r8 Z
  384.        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
    8 B+ Z3 W% ~* B1 I
  385.        CMP  btIsFirst, 1
    2 M! c* `. @  O/ f9 I6 \
  386.        JZ   LeaveRing0
    / T# Y8 S9 [* D. K; T
  387. 5 U# s. g. {( G! T8 B
  388.        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
    ( u* U: r& h; z
  389.        CALL WaitWhileBusy
    . I; E% l! d0 z" J) \' h) R  q
  390. # `/ g8 r* x' z  l6 n
  391.        // AL的值等于cBit06时,不存在驱动器,直接返回8 [( [! x6 M* Z( J! }  r
  392.        TEST AL, btBit06$ p, Q; }% h0 ?0 i& l' Y
  393.        JZ   LeaveRing0
    # W+ x3 g) b  Y
  394. * }) t! f5 Y8 O9 n9 I# K7 B+ q
  395.        // 设置驱动器存在标志+ O( r/ r/ l) P: {* ^
  396.        MOV  btIsDiskExist, 1
    2 H7 `0 X+ t7 }8 _
  397. * e, u) @5 B+ F1 O& F& s- b
  398.        // 发送存取端口命令
    3 Y* p0 h0 P3 f6 i
  399.        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,$ S4 o6 w. M& u3 i% W9 ^  v6 w, M
  400.        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
    6 |5 c1 C- z" l0 X) b
  401.        CALL WaitWhileBusy- D1 p2 ]  z( P* ]. }5 ?
  402.        CALL SelectDevice    // 设置主从盘标识: j% g  ^# s; m# t* S
  403.        MOV  BL, btAtaCmd      // 发送读取命令
    . ^8 Q4 a- R" m- y7 w6 W- U
  404.        CALL SendCmd7 o1 x* g. [0 W$ r
  405.        CALL WaitWhileBusy
    8 a2 Z' |0 x9 R4 P& D

  406. : Z1 P+ ]; o; f6 K3 `1 v3 y
  407.        // 检查是否出错* T# g7 A3 i0 l$ t. C6 w
  408.        MOV  DX, dwBaseAddress# R% i+ g0 f- s4 D0 b5 w
  409.        ADD  DX, 78 B* }+ J1 M; \9 ?3 F

  410. . b& t* D4 ?. @, C. B: A* X3 m
  411.        in   AL, DX
    * w0 o. t8 y( U5 I; K( a% v% \

  412. ; n8 C6 x0 Q/ G3 W1 @; W
  413.        TEST AL, btBit002 t" e$ w+ N4 C) p( u- \
  414.        JZ   RetrieveInfo   // 没有错误时则读数据
    : v0 ?7 L2 o* D1 o5 u

  415. 8 L; P' V" Y6 b& C
  416.        // 如果出错,则进一步尝试使用ATAPI设备命令# P! v; x( p: f! e1 K/ B
  417.        CALL WaitWhileBusy7 U# l- |) ]6 [/ Y
  418.        CALL SelectDevice6 u* o, @6 h0 {; L# Z, [
  419.        MOV  BL, btAtapiCmd
    4 p' U) X* R' D5 N8 f& R
  420.        CALL SendCmd
    6 X. O% z/ Q% V/ E& F  _+ e
  421.        CALL WaitWhileBusy
    5 P) K$ }+ O0 T8 ?) Z
  422. " A& d0 Q6 ]8 B3 F
  423.        // 检查是否还出错
    8 C: h" k' S* t+ y9 j
  424.        MOV  DX, dwBaseAddress
      _9 Q; B7 I2 D" ?; ?. k
  425.        ADD  DX, 7
    2 B. s* N, N8 A2 Z1 \* [1 j7 l
  426.        in   AL, DX# P8 o! d4 c* {2 G; M' |7 p- Z
  427.        TEST AL, btBit00+ v6 I& ?) g6 B/ \1 t
  428.        JZ   RetrieveInfo   // 没有错误时则读数据
    , p4 R  X9 D2 a2 Y& h! C
  429.        JMP  LeaveRing0     // 如果还是出错,直接返回
    - R+ y, k% z$ x3 }! P$ O

  430. $ g. h- Z- l& W, F' f; ?& [
  431.        // 读取数据2 {" c9 {1 |  L3 K- ~
  432.        RetrieveInfo:
    - N, g$ w) h8 u3 m$ O

  433.   D3 t- L: o; L2 W8 B5 H# E
  434.        LEA  EDI, wOutDataBuf
    3 Q+ l. `+ Z9 T& m# w$ G
  435.        MOV  ECX, 2568 ~2 ^+ g* n" k( v; Z( W. _' z
  436.        MOV  DX, dwBaseAddress) n5 p/ v9 m/ L, O
  437.        CLD' z1 G6 t. f3 |' X3 }# o

  438. 8 i. Y3 t- }: z) e
  439.        REP  INSW, U* A7 E2 S8 r$ t. A6 ^, O2 f

  440. 9 T& _( J+ Z& \# S9 N
  441.        // 退出Ring0代码
    5 I# p; R! |7 q6 Z( }4 ~+ ?
  442.        LeaveRing0:5 y7 |! Q8 l& c* C

  443. " K5 L! M& e7 t/ d8 c# k7 \
  444.        POPAD
      P8 A" Q! a+ k; t- L/ e) d& \# O
  445.        IRETD
    8 H9 t* I$ [# _
  446. " p5 J1 R& Y0 _3 f. l# A
  447.        // 激活Ring0代码
    . o- u+ y1 i) I& q+ p  y
  448.        EnterRing0:, T% T! p$ j- ]  l9 X' {  `" g5 W
  449. * F6 K/ o$ a; w* R4 e
  450.        // 修改中断门7 n7 c0 G& B/ f# W) }7 h
  451.        SIDT FWORD PTR btIDTR17 `( @( P/ s4 v. E9 U/ J
  452.        MOV EAX, DWORD PTR btIDTR1 + 02h6 x& S! u5 g# R) _
  453.        ADD EAX, nHookExceptionNo * 08h + 04h
    ) ?( S& J: t0 q) [/ N0 J" `+ H
  454.        CLI
    5 r8 Q, S' A0 y
  455. ( p0 G6 R( [" Z$ }! c6 ?
  456.        // 保存原异常处理例程入口
    % U! n* i0 I& x0 p: |$ j
  457.        MOV ECX, DWORD PTR [EAX]
    1 c7 M  n9 Z- U7 j7 S
  458.        MOV CX, WORD PTR [EAX-04h], c9 c2 i: K4 F3 O6 p, D# c$ {7 }
  459.        MOV dwOldExceptionHook, ECX0 f6 ?* z# u' r0 o0 O

  460. 1 v3 ^, G; f) J3 n) y% _9 O
  461.        // 指定新入口; j7 l' I  Q% `) D( J
  462.        LEA EBX, Ring0Proc4 E  k! `- U' V: B$ C
  463.        MOV WORD PTR [EAX-04h],BX
    ' y! M+ {5 v3 f0 o# b" k, d8 P
  464.        SHR EBX, 10h
    ! [. u* U, c4 f. j6 P8 b
  465.        MOV WORD PTR[EAX+02h], BX
    3 `9 U. i. _. v6 \7 x) R3 Q
  466. ' _% Q2 s, z3 Q: H: e' F
  467.        // 激活Ring0代码
    , k" n$ D. l4 [4 p! D. f' T* ]; d# R
  468.        INT nHookExceptionNo4 O( d" b# i7 p' Q5 n" B
  469. ) z# U$ Z" F! }% j( i' X' R
  470.        // 复原入口
    . R: h; e3 j  {$ e7 J, I2 k
  471.        MOV ECX,dwOldExceptionHook2 V7 H& ~2 ?% C1 X
  472.        MOV WORD PTR[EAX-04h], CX% Y+ n- z  W8 ?8 v9 Z! z1 f, i8 Y
  473.        SHR ECX,10h/ b, Y' c" @+ j" g- c# v% L# I
  474.        MOV WORD PTR[EAX+02h], CX. ~/ i7 Y+ v9 [$ q1 }4 y6 I
  475.        STI
    - P4 H5 h$ Q* Z9 n& o6 c
  476.    }
    # z, T6 M! {9 z( d# `) ]" T1 i
  477.    if(!bIsFirst)
    ' w* D" A" C" Z) U: B. ?4 m# z" M
  478.    {$ F% \* h; H" ?* k5 ^
  479.        bIsIDEExist  = (bool)btIsIDEExist;
    ! K3 G8 X, L7 b% m  U5 j3 O$ ~
  480.        bIsDiskExist = (bool)btIsDiskExist;
    7 s- K  B9 c5 C) b( }+ V3 w$ H
  481.        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
    # g9 e  q$ s0 G& f/ i
  482.    }
    ! t( Q. _% C, n, b
  483. }
    4 X4 B8 L( S) A% A7 ?* j7 ?
  484. //---------------------------------------------------------------------------
    + _0 I4 }8 c2 g  X
  485. // 调用方法:* Q  C- ~/ Y0 b/ C& v
  486. void __fastcall TForm1::Button1Click(TObject *Sender)
    * _5 Z' W0 C& \& \8 [
  487. {
    9 P" M. R" h6 l% V
  488.    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
    $ m% r2 {9 g0 |, a, S; t5 N; [
  489. }
复制代码
发表于 2005-8-15 01:00:45 | 显示全部楼层
晕乎乎。。。怎么看8 洞阿
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-11-14 23:43 , Processed in 0.021552 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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