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

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

[复制链接]
发表于 2005-8-11 11:42:04 | 显示全部楼层 |阅读模式
  1. #include <WinIOCtl.h>
    + C+ l( i' f5 T( v1 }/ c
  2. #include <stdio.h>9 _6 W- z! ^/ g/ o+ r6 }1 s6 G' Y

  3. , I0 ^; V6 b( E, a8 e7 {# A
  4. #pragma inline
    / U4 l0 g  V) M3 p
  5. //---------------------------------------------------------------------------
    4 H: B+ J! ]7 I4 F0 \' a
  6. // IDE NT/2000/XP专用变量
    8 y$ X, b9 L. B$ F$ U+ g' l+ A  E
  7. #define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS9 l: \( T- _) z& l2 ^
  8. #define DFP_GET_VERSION         SMART_GET_VERSION' j& q3 F8 T5 O4 l" Y
  9. #define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
      E2 M1 A* `# H3 p
  10. #define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
    ( @: |* ?4 C/ X+ v. B; z

  11. " C* x# p6 C3 _; R) t  a
  12. const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令
    9 S4 m: s4 Y; ?
  13. const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令- ^" y* L- o( L3 w4 q3 J# {
  14. 7 s8 L$ Y/ b) z) k! z
  15. const int MAX_IDE_DRIVES = 4;
    ! |- K9 e( d6 w1 H! s) i

  16. ( T6 T9 e# Z/ S. p: u2 d+ ^
  17. // SCSI专用变量
    : s6 n" R) ]$ v6 L, q1 k
  18. const DWORD FILE_DEVICE_SCSI             = 0x0000001B;% r! }' s7 B: Z5 C/ M4 O' E
  19. const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
    , f8 q- d% N& e5 `
  20. const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition% u1 I. ~7 q4 X+ o8 H
  21. const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
    9 K* C) R' N6 M5 t2 |% f& t( ?

  22. 7 Q( ~- V& a7 z: V
  23. typedef struct _SRB_IO_CONTROL
    / u0 c2 N2 f' F9 T
  24. {" N8 m& h( c. L0 f; }7 _2 \& f
  25.    ULONG HeaderLength;
    4 s3 `1 j" g! P% r  R( x1 J* N
  26.    UCHAR Signature[8];
    3 V$ A) f/ r2 v- J
  27.    ULONG Timeout;5 C& p+ B0 r& V1 O+ V8 s8 s  m
  28.    ULONG ControlCode;
    . V8 i7 q3 ^' U7 s% P) L
  29.    ULONG ReturnCode;
    " n. v) o4 |! L2 O5 r8 c7 G' @
  30.    ULONG Length;
    # n  h! S  s1 x# A5 H9 d
  31. }SRB_IO_CONTROL, *PSRB_IO_CONTROL;/ e9 q: {, {# |

  32. 8 t* u- Z% a0 T2 k& b3 n* z
  33. // 读取的主函数$ v: W. F0 f9 l
  34. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);/ g2 P$ r# r6 d4 Y& `

  35. # y; C- r/ M% H3 E' k" X5 S# {
  36. // 辅助函数
      K' \% H9 D+ }. o( X
  37. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
    2 I% \4 E! T+ Z
  38. // NT/2000/XP函数
    ! k& T: ]9 o  Q9 ]
  39. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
    ( U% y) b6 q! v) e' J
  40. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
    # d8 g' `1 d0 z  F0 x0 @
  41.        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
    / F/ V# r& \/ x3 E8 K6 d( g$ b
  42.        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
    ' s) N8 H! @7 U* i; A
  43. // Windows 9X函数
    $ g6 F8 v0 o7 @0 F3 ?
  44. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);
    / _3 m9 ~: a/ s9 w1 _8 K/ C# @
  45. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
    , o- N$ I: h4 i# u0 s
  46.        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);; x* @  q0 N" l
  47. 3 ^, d( G( N2 [$ j  u
  48. // SCSI读取函数(for NT/2000/XP)
    ' K6 `7 H  P9 h5 l; ^4 H  C
  49. String __fastcall ReadIDEDriveAsScsiDriveOnNT();
    2 `& D7 q9 H2 `
  50. //---------------------------------------------------------------------------
    % m: E) K% E6 J" W
  51. // ReadPhysicalDrive
    - H0 T% d& V/ G' d* E) y4 i0 x" v7 u
  52. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)) o8 o* K6 t4 F( b5 E
  53. {
    5 F8 T) G- N5 I* `) c" a7 J
  54.    switch(Win32Platform)
    7 y+ g, A9 y( K
  55.    {
    + Q* X# O" w  W2 `" w9 v" t6 M
  56.        case VER_PLATFORM_WIN32_WINDOWS:2 y2 H& Q& g  H- W7 y
  57.            ReadPhysicalDriveOnW9X(pSerList, pModeList);0 m$ Y! m* z! Q- r% Q+ H
  58.            break;) H  i2 N( Y" s. [+ t5 e$ m
  59.        case VER_PLATFORM_WIN32_NT:/ I0 [: b# v' D4 U% D1 k
  60.            ReadPhysicalDriveOnNT(pSerList, pModeList);
    - u9 [  ^9 X* l' f
  61.            break;: u9 L0 g8 n/ u1 ^$ J
  62.        default:( l; P- @' M: F8 n; a
  63.            break;' c1 u4 y+ ^/ M6 G3 t
  64.    }
    1 h2 N. B- z! M8 C: K7 {' e
  65. }
    . G+ _3 v7 y6 a0 K% w  S& h
  66. //---------------------------------------------------------------------------
    ( z* T0 `  S: f( t/ u* C
  67. // ConvertToString! d0 j! I2 \; P' ]  B6 y, F* ^: L
  68. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
    8 \% j) \; x# T+ O: T
  69. {/ c/ B% O8 _+ E, U
  70.    static char szResBuf[1024];
    0 K1 g& s1 D+ A
  71.    int nIndex = 0;
    / H( M4 D% o4 o5 m' w9 H
  72.    int nPosition = 0;% Q3 r! E, u- M4 e
  73. ; p# q! Y! M( ^+ N
  74.    // Each integer has two characters stored in it backwards
    ' z) S+ _1 K7 P/ P  `. R' u
  75.    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
    7 Q  e6 F; D" M; S! f
  76.    {1 A/ f) _3 U  m2 U
  77.        // Get high BYTE for 1st character
    1 |5 a; A5 W0 E0 g
  78.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
    / F7 ^, Q" c: k9 A4 x) q& {% A; ]1 Q
  79.        nPosition++;9 F* [9 h4 b, o( z1 W
  80. ! M! P$ s' W0 ^. P0 f% o( |
  81.        // Get low BYTE for 2nd character" O$ \, J) t" L! P
  82.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
    1 I4 j2 y4 X" y9 j3 l. K' g7 r5 Z
  83.        nPosition++;
    ; D3 u7 k( k' C" r- a2 a5 s
  84.    }
    ; m$ V* v% ~4 @( h7 _* Z

  85. , u$ d7 B4 o% O! y
  86.    // End the string
    - N5 ?& ^2 \( |5 _% r- P
  87.    szResBuf[nPosition] = '\0';9 [4 a7 b! G9 d0 U! ?& }, ~4 ?
  88. " ]$ p  O: c* Z. J6 H, }9 D
  89.    // Cut off the trailing blanks' ^. k$ G" T& n, E; ]. \6 M; _
  90.    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
    . h5 e$ ]+ z! e) O
  91.        szResBuf[nIndex] = '\0';4 y+ g6 w2 f. P* Y8 _$ b/ K

  92. 5 v* F/ e6 ~6 _# M0 ~
  93.    return szResBuf;( s/ Z2 T# {/ D% t+ {6 z
  94. }1 k3 b; s/ c) ]- r# t+ F- B! R
  95. //---------------------------------------------------------------------------
    $ N7 E) `5 k7 a, Q# }# |
  96. // Winndows NT4/2000/XP 代码
    / t! X$ E1 O8 h& H6 C5 Q! z
  97. //---------------------------------------------------------------------------
    4 J) l' d9 }9 {" W$ }" E
  98. // ReadPhysicalDriveOnNT; h; G6 p2 A* Z2 r
  99. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
    . U' n9 J/ r9 {# K+ K
  100. {
    " o+ w0 ~! l  q) X2 W1 d6 q& h) R& V
  101.    // 输出参数
    + y  H( ~5 M! F
  102.    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];! u5 M! m8 _+ E: L

  103. " w! @) Q: L, i/ }2 ~! K
  104.    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)" I6 H( a5 |2 T! ], e
  105.    {. K( i2 R: q. l; G! j7 N
  106.        HANDLE hPhysicalDriveIOCTL;# L$ `) B! n" v2 g  n6 R5 J
  107.        char szDriveName[32];
    " t/ W1 F% R3 k) W4 o6 p
  108. " e7 O  W% y* u4 T
  109.        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
    4 Z. ]4 M  S% p. F4 i: R; M
  110.        hPhysicalDriveIOCTL = CreateFile(szDriveName,
    , `, D8 D) f' x6 }. [) B8 Q
  111.                        GENERIC_READ | GENERIC_WRITE,( ^1 d2 L# l7 e9 V2 M. U9 q' z
  112.                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
    + H/ F! c: }  B  g
  113.                        OPEN_EXISTING, 0, NULL);" {1 w0 o1 Z, D' S0 K
  114. " k* r- ^: u% e
  115.        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)* P; o0 U# e( @, ~; w9 |0 s5 w! l
  116.        {, L7 n( P9 I, V. B9 g" e
  117.            DWORD dwBytesReturned = 0;
    % ]% H# N! K. c. Q
  118.            GETVERSIONOUTPARAMS gvopVersionParams;
    7 y8 [' Q( w: y' j0 L
  119. & {0 M; r5 a8 T! ~
  120.            // Get the version, etc of PhysicalDrive IOCTL$ G  n% i& E- [! I+ m
  121.            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));0 T' {# V- R, Y2 a* t

  122. , `$ s& V; ^0 J  J4 R% E+ O' m
  123.            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
    ; |% ~3 `, v4 H
  124.                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
    2 q; Y- K0 a+ w% Y) f
  125.                    &dwBytesReturned, NULL))
    0 H; U) s5 i/ E7 \/ j! `1 c2 H
  126.            {- n) x; m$ [' y9 @' k, t( @4 y
  127.                continue;. R' E& S7 g! }# N0 p: p* R( b# W2 x" r
  128.            }! J; n5 A! q  v& }( e0 P8 f# A

  129. / B5 z& w2 H  f  }+ ?, c
  130.            if(gvopVersionParams.bIDEDeviceMap > 0), j9 ^  o! o" K: o4 k% T% I: g+ F
  131.            {
    ) l2 c) ]8 e7 E3 U  z! E
  132.                // IDE or ATAPI IDENTIFY cmd# h, J$ Q1 k) _$ x8 V, [
  133.                BYTE btIDCmd = 0;
    5 N! b( l, M- ~: L; f# q
  134.                SENDCMDINPARAMS InParams;
      V8 x4 j$ o4 H: o0 U4 l
  135.                // Now, get the ID sector for all IDE devices in the system.3 U" A! D. m6 i9 J, U# _) M3 y8 z# S
  136.                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,7 A, p! B, r1 d4 e" Y
  137.                // otherwise use the IDE_ATA_IDENTIFY command) b; J8 I; U& v* z+ q8 j+ [7 ~$ F
  138.                // 具体所得结果请参考头文件中的说明7 [- Q( p1 ~- g4 n
  139.                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
    ) a% f. r( y. _2 S2 |, q  B" ?2 `
  140.                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;# N+ Q% e% `, Q. S0 _* P
  141.                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
    1 T4 ^" o2 d5 E: h' a
  142.                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
    ; O+ I) O5 ], D( B5 e

  143. 5 m, w* L! A* x5 f. A- B9 y
  144.                if(DoIdentify(hPhysicalDriveIOCTL,, b& ]  w( k( h/ v7 w( U
  145.                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
    ( i3 F+ v4 X  u5 |& ~: i8 a
  146.                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
    % N/ X7 {9 k0 G" n* m
  147.                {" }, u: L# x* @. p9 G0 N/ |% i
  148.                    DWORD dwDiskData[256];
    0 s4 K+ L. W, o/ _. F
  149.                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件+ M# i" y  g; {. Y+ w& I/ G
  150.                    char szSerialNumber[21];
    - _( t8 N( f$ q! y* w. m
  151.                    char szModelNumber[41];( p! e1 `( C6 |; q! \; e( O

  152. 6 n9 O2 ]/ p: W! R
  153.                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;7 X9 D( b2 C1 B" K9 G3 N2 o
  154.                    for(int i=0; i < 256; i++)/ k# {& X) r" M0 M# V
  155.                        dwDiskData = pIDSector;0 k$ j$ }( |! c; [" h+ v, R1 u
  156.                    // 取系列号" ^1 J! o- o4 l8 ~5 J- O& q
  157.                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));7 B- y. ^& ^& A$ ]
  158.                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
    / H# F8 Y0 j1 _  X( {0 E" T* Y3 L

  159. 3 _7 a/ U; M- Y8 F1 F
  160.                    // 取模型号2 e/ @- }9 I- ]. }5 u7 R; |, e
  161.                    ZeroMemory(szModelNumber, sizeof(szModelNumber));
    0 c% ~/ m( k  P8 C5 y5 Z1 \9 a0 [
  162.                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
    - ?# n: E2 ^5 |- ^; _1 e* [+ S0 B
  163. " N( {$ O* e9 |* B" `5 }
  164.                    pSerList->Add(szSerialNumber);
    4 a% p. ?3 z" G
  165.                    pModeList->Add(szModelNumber);5 j; g6 O9 |7 R8 w  F. |2 R/ x' m
  166.                }
    : E4 Q1 K- S' |: z4 S+ m
  167.            }# n* x4 ~& }/ r" T% c
  168.            CloseHandle (hPhysicalDriveIOCTL);6 A0 v: e+ ]' U
  169.        }
    ; {- g" m$ @/ @$ {5 D
  170.    }$ g' l! R" Y8 h2 r
  171. }
    2 I& s" O6 F& p% g
  172. //---------------------------------------------------------------------------, U  x3 x4 d5 I7 W1 [
  173. // DoIdentify: y9 d; j/ T* u) D' W2 q" J
  174. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
    1 L+ b3 S% Z! C# t9 u
  175.              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
    # f+ q; G4 Z1 m7 k: a1 a" G/ h# t$ u: Y
  176.              PDWORD pdwBytesReturned)/ \3 W$ |" w% w
  177. {
    0 Z! P0 `( O. M* i' |6 I
  178.    // Set up data structures for IDENTIFY command.1 D! \+ m* C5 L3 I, q
  179.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;! O4 Y0 H( J) E2 B3 q2 s+ v* y
  180.    pSCIP->irDriveRegs.bFeaturesReg = 0;" Q4 s; ?) c5 ?; I( L  r
  181.    pSCIP->irDriveRegs.bSectorCountReg  = 1;
    % t0 H2 F( j! E- R& v
  182.    pSCIP->irDriveRegs.bSectorNumberReg = 1;0 c: O* }6 g% n% I
  183.    pSCIP->irDriveRegs.bCylLowReg  = 0;
    7 y: q0 h$ D* M1 n* B1 U9 p
  184.    pSCIP->irDriveRegs.bCylHighReg = 0;: m+ g8 z9 F8 Y% H' I, j
  185. * I  k+ }9 x+ O
  186.    // Compute the drive number.(主盘和从盘所对应的值是不一样的)  b' A7 j+ L, N4 B
  187.    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;6 Y' [/ E  e0 b5 }" D
  188. 5 q* U$ X$ d0 D9 [( B
  189.    // The command can either be IDE identify or ATAPI identify.3 d$ _0 J: S+ g' X8 W
  190.    pSCIP->irDriveRegs.bCommandReg = btIDCmd;0 p: d6 H9 D! p* i% m0 X9 ]
  191.    pSCIP->bDriveNumber = btDriveNum;- C. d) T9 m% Q# E8 w4 Y( j5 `
  192.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
      C3 k# a! s) L5 f8 w( ^! H* J" |2 r: D

  193. ( y' K" a: j/ a* s
  194.    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,. M1 Z: O- t  _+ }3 k
  195.           (LPVOID)pSCIP,# ~: V2 g" W6 ?1 Y4 n# y1 B# e
  196.           sizeof(SENDCMDINPARAMS) - 1,
    ! Q+ O- O1 [3 w8 O3 [
  197.           (LPVOID)pSCOP,) n% l  X3 o! {' Z. H& C7 C
  198.           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,. S1 m1 R5 E7 A% |  b. H0 [! @; L
  199.           pdwBytesReturned, NULL);. L* k3 h5 Q% l6 G2 i* ~1 G
  200. }6 m% L& q9 A: T5 O0 j# i
  201. //---------------------------------------------------------------------------
    . q3 j4 K  U- M2 J8 A+ u, b/ Q
  202. // Windows 95/98/ME 代码
    $ y2 F2 C; }; j# m
  203. //---------------------------------------------------------------------------
    0 Z$ ~7 S, Q5 {7 n# v
  204. // ReadPhysicalDriveOnW9X
    . \; @7 e+ V2 Y* D( p, |% R3 Y
  205. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList): k6 G  F7 b7 v0 L$ ^& B
  206. {
    7 a& r; x/ A+ [! t6 ]  |  ^+ ^$ C
  207.    WORD wOutData[256];
    6 y/ s  Q  G& }8 z- n9 ]
  208.    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);% m& B0 s; F, w: J. d

  209. / X% e! J) y9 n$ f" N( u
  210.    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。+ ^8 u! _! A; V& u9 A
  211.    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以$ M- {" p& _" F8 d
  212.    // 避免蓝屏的出现。(期待高人能指出原因), \  ^6 Q3 f+ \* z4 P
  213.    for(int nDrive = 0; nDrive < 8; nDrive++)1 a% h. A1 h6 P7 n
  214.    {; G5 ]3 Q& W  v
  215.        WORD dwBaseAddress;
    9 h9 `+ Q/ O7 K; ?! ]1 V
  216.        BYTE btMasterSlave;         // Master Or Slave
    " J7 S$ |% c5 ~2 a# M- n6 T8 l& R
  217.        bool bIsIDEExist;4 E: G8 p" g% t) `6 Q
  218.        bool IsDiskExist;$ }, o! P, v( P( o9 E0 k

  219. - ^; S7 q7 a; H7 F/ P+ m7 ?
  220.        switch(nDrive / 2)" Z4 V8 S2 y8 c8 Y% t
  221.        {) r8 R6 a7 U* ]$ ~+ E
  222.            case 0: dwBaseAddress = 0x01F0; break;
    4 a" a4 T& H- }# r
  223.            case 1: dwBaseAddress = 0x0170; break;5 b# F) |( m4 H, R7 D% N
  224.            case 2: dwBaseAddress = 0x01E8; break;
    & {# P( [# h' Y/ f+ l, D/ n8 U8 |
  225.            case 3: dwBaseAddress = 0x0168; break;6 C+ {% ^, C  z) w3 U( }
  226.        }
    * |% z$ Y( V  j" ^" t

  227. 1 H! \" L$ X: Q' _9 e
  228.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
    5 ~* E' T9 G4 s
  229. ! A! o) q  |( s+ o' U4 B, p
  230.        // 进入Ring0
    ) J; u. d7 m* \4 q
  231.        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,, [) V  f+ c1 t1 i% F+ k: r
  232.                bIsIDEExist, IsDiskExist, wOutData);/ J1 x( c; r. J: X( p
  233.    }5 @8 u7 ~. b) W" }9 e) }  ?6 w
  234. 3 H0 b! K! q% x8 R+ |$ H2 m# A
  235.    // 开始读取, N- n& ^/ G, a, i% Y7 ?8 b' s0 l
  236.    for(int nDrive = 0; nDrive < 8; nDrive++)7 W6 Y5 B% q; F2 f" i( N$ F
  237.    {3 m) a- N9 P2 s+ ]6 e0 _# v
  238.        WORD dwBaseAddress;
    : z2 x* S8 S! B$ R2 G. s* p
  239.        BYTE btMasterSlave;         // Master Or Slave" R3 l& q( @9 M
  240.        bool bIsIDEExist;# ~( o3 q  s/ S* H! j5 M% j* T
  241.        bool bIsDiskExist;! V. W  ~; B6 [0 S1 X( ]6 s0 x, m
  242.        switch(nDrive / 2)
    4 E+ \% K; F3 E7 i( w0 e. R1 f5 R
  243.        {0 D8 h9 |& \$ k2 ?
  244.            case 0: dwBaseAddress = 0x01F0; break;$ E& |4 V, _% Q$ \4 k
  245.            case 1: dwBaseAddress = 0x0170; break;( p- L0 R6 s5 w8 D/ T- t
  246.            case 2: dwBaseAddress = 0x01E8; break;
    ( x+ B  N3 ^* k' G
  247.            case 3: dwBaseAddress = 0x0168; break;+ T8 u  p2 V# L1 _; O- d
  248.        }
    ' x  z; w1 x" j# ^% f
  249. 8 G4 b) V* P3 z% q  S* Y: G' x/ c
  250.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
    , o! m4 f) `) x3 r! e! X: t- R

  251. : v! t3 W9 `" N8 k
  252.        // 进入Ring0& a- e* v& K- r3 ]6 m
  253.        bIsIDEExist  = false;! \; {( r! J5 x
  254.        bIsDiskExist = false;! i$ w) C: k, o7 `" q) G
  255.        ZeroMemory(wOutData, sizeof(wOutData));6 K4 X$ X9 t. ?; [* z* r$ L

  256. 9 j7 N5 g" G8 J3 u
  257.        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,6 A) K4 b& h2 p6 Z7 C* @1 b
  258.                bIsIDEExist, bIsDiskExist, wOutData);
    & M+ Y1 D' @3 |9 `1 L0 e
  259. - y  V% H& E7 n6 ]+ d
  260.        if(bIsIDEExist && bIsDiskExist)5 x4 |% ^- {1 P
  261.        {- d! G! p% ^3 Y& r5 ~1 P  O
  262.            DWORD dwDiskData[256];1 V5 _7 @: h& i- r8 i
  263.            char  szSerialNumber[21];2 y+ ]4 r7 B% U. J) O) i$ t3 k, o
  264.            char  szModelNumber[41];
      I9 f9 y/ i& Z; {3 I: R8 g

  265. 3 K  l, N; I/ k( x" z$ m7 x" I. }  L
  266.            for(int k=0; k < 256; k++)
    7 p$ U9 i' L. q  _: w4 W2 x+ R$ v
  267.                dwDiskData[k] = wOutData[k];1 }9 A8 C" n, p, K9 J

  268. ' `' r! o1 R6 _" u: m
  269.            // 取系列号5 x# o& d2 \  b+ H! j" ]6 `( V
  270.            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
    0 v1 W$ S) Y& q) r. Q
  271.            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
    / E) i/ {/ P1 S4 B$ [5 }7 J

  272. * a' m8 ?% g) i! B4 ~: l
  273.            // 取模型号; O* y2 X$ \' M5 N" T3 e
  274.            ZeroMemory(szModelNumber, sizeof(szModelNumber));. E, r7 k- i; i6 @
  275.            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));% A: Y* d2 a: h# ^; @

  276. % r/ Z$ q% O4 Q! @6 i8 n
  277.            pSerList->Add(szSerialNumber);
      C+ u: _. I# W
  278.            pModeList->Add(szModelNumber);* O& W& R* ]# d: ~' Y" P' V5 [
  279.        }
    2 j# M: \% j4 k; R, i7 `* `
  280.    }
    8 S( F0 E( U, F$ C' U& X$ Y
  281.    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
    1 W$ i, B2 @! x" p* X  H# \6 ~
  282. }% [3 c. x2 x7 D+ g2 |2 n% R2 b% Q
  283. //---------------------------------------------------------------------------5 Z( w- r& }7 Y3 V7 _* c' y
  284. // ReadPhysicalDriveOnW9X_Ring0()1 J& F. X( w8 E! P8 z  p
  285. //
    8 ~" n, n4 x- a& v
  286. // dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h: ?5 p+ z( X8 ~1 w9 h
  287. // btMasterSlave = Master(0xA0) Or Slave(0xB0)
    & e6 ?8 h2 i& ~& l& F  ^$ q
  288. //---------------------------------------------------------------------------
    4 b6 j. k7 p& L2 ^8 q
  289. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,  z7 q! w  V) x0 X) v/ ?# q
  290.        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)  }) J* b- F1 [# O
  291. {0 X8 d- j9 M! q3 l7 i9 x7 Q
  292.    BYTE  btIDTR1[6];
    7 u9 I3 c+ _+ T
  293.    DWORD dwOldExceptionHook;
    ; A: i8 n( v8 W6 G/ H- s; L9 q
  294.    const int nHookExceptionNo = 5;
    6 f; z6 T4 x: e% E+ Q$ U0 F4 g4 L& G; D

  295. 6 g2 P- p4 L4 H% Q/ J
  296.    BYTE  btIsIDEExist = 0;0 |# S1 G0 T: L
  297.    BYTE  btIsDiskExist = 0;* `) h$ L: a. m
  298.    WORD  wOutDataBuf[256];
    , w3 N+ a+ Y" u& A8 h* }+ C

  299. . W0 U- r3 d  E4 e
  300.    BYTE  btIsFirst = (BYTE)bIsFirst;% X; J: @" J( [& i! ?( B  N2 p. `
  301. 3 P1 @1 w7 O& b! U& o7 c* X+ ^2 n
  302.    const BYTE btBit00 = 0x01;
    ( M  T8 s  k- P& u- Z3 y
  303.    // const BYTE btBit02 = 0x04;  k6 M. w1 p. C" `% R$ g
  304.    const BYTE btBit06 = 0x40;; M8 o; Y7 t8 Z4 C- _& c
  305.    const BYTE btBit07 = 0x80;
    0 p( F1 r3 w3 ^! q# j, c
  306.    // const BYTE btERR  = btBit00;
    9 C! l0 q0 \# t- j1 h/ F& N
  307.    const BYTE btBusy = btBit07;
    6 X0 y, d! o  V; S5 {. G& g
  308.    const BYTE btAtaCmd   = 0xEC;; J" |& P) s4 V( {- c
  309.    const BYTE btAtapiCmd = 0xA1;6 v) E' x2 u- A+ p  E. Z! _
  310. % Q. Q8 ?+ s% b2 i* x) r
  311.    __asm5 j4 i$ Z/ u$ M! F/ C$ s
  312.    {
    + n/ A1 e$ w8 [6 E( Y/ L! w5 [
  313.        // 必须先执行这条语句
    6 D8 g1 r* F- i8 p
  314.        JMP EnterRing0, p4 m, L  q1 Z; T
  315. + a; z5 t9 H, p$ U4 f- o! C
  316.        // 定义过程/ Y& V0 x  X3 C& X! O- S
  317.        // 等待IDE设备直到其不为忙为止
    ! J3 Z9 V( h( B* W, o* K1 Q
  318.        WaitWhileBusy proc! d# a. f. V3 G% |' q$ X

  319. 1 x9 ^, ?$ w, r. \) q9 u
  320.        MOV  EBX, 100000
    ) G& \' a8 o0 l$ R& A
  321.        MOV  DX, dwBaseAddress
    ( m0 f, T' B8 ]2 I* ]& `5 M
  322.        ADD  DX, 7! q% Q8 ]. v1 g* H# b
  323. % s# Q/ n$ ^& r4 _8 H$ F
  324.        LoopWhileBusy:( Z6 u; g: O/ E, P0 y. R

  325. ; G" r8 ~' k" D  h0 Z7 T" w
  326.        DEC  EBX, T8 u; S4 p  Q! Z( ]# k5 {
  327.        CMP  EBX, 0
      x1 {$ `) a6 v: n. |9 K: M$ v7 A& P
  328.        JZ   Timeout
    2 u' A9 ^0 r2 m3 a1 q( P
  329.        in   AL, DX
    * ]: M; P/ u4 I" T: ]
  330.        TEST AL, btBusy' H, v4 Q7 U0 R2 {
  331.        JNZ  LoopWhileBusy
    ( k5 O/ }. P& U4 I
  332.        JMP  DriveReady3 p& \% ^( C; u5 t% U7 }3 k4 A2 Y
  333. $ J% B# N. A0 }1 w$ q: i
  334.        // 超时,直接退出
    & x: K3 N: ?% S$ U5 b* v" T
  335.        Timeout:
    7 q3 Z; U2 I1 d$ F! u
  336.        JMP  LeaveRing0
    ! G5 A* ]" u, u+ w  G1 a+ q3 d; J
  337.        DriveReady:, d9 n3 z' B4 A) k, W- ?
  338.        RET
    . }' ~0 a5 ]% y+ }. O
  339.        ENDP   // End of WaitWhileBusy Procedure. j" T# ]# d# ~
  340. 1 ~& b* H5 J( o+ L' @6 @" a: S
  341.        // 设置主盘和从盘标志, k* O. ]2 T, ?$ \3 `
  342.        SelectDevice proc
    ' W2 N. P0 }( Q- Y1 f/ z. D- J7 Q
  343. , u, a+ j  |* n3 }0 q
  344.        MOV  DX, dwBaseAddress) `: B( O) B7 {' a! O0 x9 H
  345.        ADD  DX, 66 K) Y5 i5 L2 [# T3 e+ I
  346.        MOV  AL, btMasterSlave
    0 E. ~% ^7 K" H
  347. 5 n1 a+ V, r& q& B0 A
  348.        out  DX, AL2 Q- u5 b$ }/ e
  349.        RET
    ; \/ [# j+ c% D0 ]5 T- o

  350. 8 t1 `( @; j2 C  i/ @0 H3 M( G
  351.        ENDP  // End of SelectDevice Procedure9 h0 B  Z% ^9 m6 U% [2 P
  352. & E3 j. a  T; y" D7 [% R+ B
  353.        // 向IDE设备发送存取指令
    4 R9 S7 M2 Q- r9 K+ L
  354.        SendCmd proc
    + O) H, j1 m* c# j
  355. / b# t2 j) ?, @( A+ T7 Z
  356.        MOV DX, dwBaseAddress
    % k! J0 j3 e8 u' |( s% y
  357.        ADD DX, 74 y0 Y; z0 D: [4 W* X- g4 t
  358.        MOV AL, BL // BL是主从盘标识,在过程外设置
    / ?' s' Q2 D8 o: c; m" k
  359.        out DX, AL
    - D2 f& L7 y* s: f* s+ X. [
  360.        RET
      d5 ~- @# d1 |6 m4 P
  361.        ENDP  // End of SendCmd Procedure" \$ W1 f$ \  E$ z
  362. : W* e. ]! z( B7 e
  363.        // Ring0代码
    ; x/ E: t2 F$ Z- G
  364.        Ring0Proc:# a# k  u. w$ D* q/ A) ^) \
  365.        PUSHAD8 _% O0 {$ Y& q6 B
  366.        // 查询IDE设备是否存在
    7 H  u4 j/ J/ Y5 ^# i: R) g4 e- O
  367.        MOV DX, dwBaseAddress
    # M8 Q3 {7 d; m" ~+ w: v
  368.        ADD DX, 79 X$ c7 Q8 n; L9 t/ f* \, o! T
  369.        in  AL,DX6 k5 S9 s6 j( p
  370. 5 ^) C6 ]6 g7 e. H" j; p2 x5 M
  371.        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回' M( `5 D$ x+ [. }0 s. o
  372.        CMP AL,0xFF' G+ f# ?" d  ~6 D0 ]
  373.        JZ  LeaveRing0
    % C2 y9 d) l7 G3 N6 g! c, u3 w
  374.        CMP AL, 0x7F
    6 s! v$ V& @+ F- J/ h6 B
  375.        JZ  LeaveRing06 |( |; m2 U- L, C

  376. $ E" o8 {/ Q( c2 w
  377.        // 设置IDE设备存在标志
    + K3 I! _5 r( A. c$ u6 L
  378.        MOV btIsIDEExist, 18 ]! n  R. X! x/ D. f! [8 \

  379. 7 s* x, G" \# ^* Q7 ]; D
  380.        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
    " [5 K& h: U* ?4 `4 W
  381.        CALL WaitWhileBusy
    / ~- Y# d( [( L  l7 E) X. d( @
  382.        CALL SelectDevice
    % V5 b* }7 b( i1 O; p
  383. - A5 u) K: ]8 _* @
  384.        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
    6 C) ~% \& F- P$ v4 H9 K
  385.        CMP  btIsFirst, 1
    & D8 }6 E1 _, \- G
  386.        JZ   LeaveRing00 {$ \6 Z- ]+ u4 Q5 }
  387.   g( W3 R$ _, q/ O$ l
  388.        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???  f; L4 ^) P. P4 C$ }4 U& B- }
  389.        CALL WaitWhileBusy8 a1 N( N  x' j" A5 r
  390. & ^  R, ]# |! J/ y7 S4 b
  391.        // AL的值等于cBit06时,不存在驱动器,直接返回: W8 D" F- h# ^7 [$ Q- R# D* @
  392.        TEST AL, btBit066 g; y0 T/ A* z9 `8 x3 s
  393.        JZ   LeaveRing02 ~# ~5 X. ^  j: v

  394. 4 E" |# k: c' H5 V; R9 O
  395.        // 设置驱动器存在标志% }$ V. a* Z; o9 h% w
  396.        MOV  btIsDiskExist, 10 a' O8 i9 J! b  U& {, J

  397. / H5 h  R2 E7 [: ?8 t7 W6 ~) T8 M2 j" s
  398.        // 发送存取端口命令- @" {; h& k& h, ?" m3 m
  399.        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
    ' s) f/ q' z) L
  400.        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令3 f) m$ [: I6 i) B
  401.        CALL WaitWhileBusy: P* I4 u$ S9 A+ }
  402.        CALL SelectDevice    // 设置主从盘标识2 d: v4 s; W* o2 d
  403.        MOV  BL, btAtaCmd      // 发送读取命令" m1 x: X7 h+ k& j% a9 }
  404.        CALL SendCmd* K. U! I1 w9 Z7 X# a" @
  405.        CALL WaitWhileBusy* f( J+ s5 t/ O% `+ m
  406. " ~/ D3 N; z% C; t- H: |. e: V9 \
  407.        // 检查是否出错6 ^. X1 t/ p1 d( _+ {
  408.        MOV  DX, dwBaseAddress$ T0 g/ L; u5 D% I% [$ l6 K
  409.        ADD  DX, 7
    % r! Z0 k1 w8 ~* `$ Z' R
  410. " Y* w0 I7 a. n; O- k
  411.        in   AL, DX  @2 H; i4 ]! ?& P* _0 r

  412. ; [) Q% Q5 a  Z* e4 L2 d
  413.        TEST AL, btBit00
    % Q) i' C5 d. J+ T& _: i( p" |" A* W
  414.        JZ   RetrieveInfo   // 没有错误时则读数据3 D* C/ V1 h! C: {" A! j
  415. - ]* N9 @+ w1 B& ~. Z, i8 [$ _2 J
  416.        // 如果出错,则进一步尝试使用ATAPI设备命令
    . y% Q) j/ I/ Q" O; q( @& `$ R
  417.        CALL WaitWhileBusy
    # o3 U" M2 v( z: C* ^6 G+ G
  418.        CALL SelectDevice& m! |- w6 G; d% R$ ?  T
  419.        MOV  BL, btAtapiCmd
    9 ^# |* `, z- {4 ]% Z/ j" j
  420.        CALL SendCmd) M" F% }1 ]0 ?! D1 w
  421.        CALL WaitWhileBusy& O! e4 q' l1 V/ j! q
  422. ) P5 n# V( p7 @( ~# @. T
  423.        // 检查是否还出错1 q3 s& C$ m) q
  424.        MOV  DX, dwBaseAddress
    # v# E  W, P# T5 F' [/ |
  425.        ADD  DX, 7
      ]2 B* ~) q0 ^8 z0 E9 g
  426.        in   AL, DX
    + b  f" {7 l. X4 V# q
  427.        TEST AL, btBit00
    " U* o* m7 h) r# n' s4 R( ^
  428.        JZ   RetrieveInfo   // 没有错误时则读数据
    5 S1 s8 E7 C! R! |4 S9 C
  429.        JMP  LeaveRing0     // 如果还是出错,直接返回
    + s% D7 }! V! p4 k/ P. X/ `* L
  430. - J- h  [4 s4 H9 t
  431.        // 读取数据
    9 R0 M9 V0 H+ P" G
  432.        RetrieveInfo:7 @* @9 Z7 t  s0 S, c2 N
  433. , j3 }' Z6 c8 S& d& `# F
  434.        LEA  EDI, wOutDataBuf5 w5 H- n5 a' c# Y. T
  435.        MOV  ECX, 256
    / h/ a& F; }" o) Q
  436.        MOV  DX, dwBaseAddress
    # s/ J7 [" U" U% T
  437.        CLD
    0 H  }$ f5 ]9 R

  438. 7 ]1 T# a! t  X" o. |" K3 }0 ?
  439.        REP  INSW. M! A" E2 ?) N' o0 G# f
  440. - T" h$ ?1 `- C+ Z0 P
  441.        // 退出Ring0代码
    % e3 w( m  J6 N9 ~3 g* p5 ~6 N: M
  442.        LeaveRing0:
    ' v+ f; E2 K' j' p+ N
  443. / R; P# J$ n% r
  444.        POPAD/ v* Y$ u' s) _# k
  445.        IRETD
      ~) U* c/ n$ H% `( B

  446. , ^: a* ^. Z! p1 a  J( |( C! h
  447.        // 激活Ring0代码& U( n" {# u5 s' B2 g' g, K: W/ }
  448.        EnterRing0:
    & c1 v) g( m3 |( O! k. w( L6 f9 Y! A
  449. 1 ?6 x" v9 k, H$ A) n' ^4 I
  450.        // 修改中断门
    4 C& X% S, j* K9 G1 ?5 c2 a7 z
  451.        SIDT FWORD PTR btIDTR1
    ! a4 d: G" N% z1 a
  452.        MOV EAX, DWORD PTR btIDTR1 + 02h
    " h* O! z- A4 N1 D. B! ?) O9 `3 B
  453.        ADD EAX, nHookExceptionNo * 08h + 04h7 L/ p' L2 m& a$ @& s9 X
  454.        CLI
    & f7 n) U0 S$ ~8 l+ ~9 @3 Y

  455. 3 x  C  n# G9 i7 V. {& X
  456.        // 保存原异常处理例程入口6 G# ~- ]2 n# }
  457.        MOV ECX, DWORD PTR [EAX]
    . q1 z( y5 C2 ]3 K4 w" N' o$ w
  458.        MOV CX, WORD PTR [EAX-04h]' @! C  |. {) U, L' A8 Z+ X
  459.        MOV dwOldExceptionHook, ECX
      F0 y' u6 ~% F
  460. & Y8 p/ t3 Y4 Z* C
  461.        // 指定新入口
    ( L! l' s7 r* U4 L7 b
  462.        LEA EBX, Ring0Proc
    & s) u2 x0 `9 |$ Z; s
  463.        MOV WORD PTR [EAX-04h],BX
    1 g- e6 u7 u" S$ f' B* ^+ t: f& O9 K
  464.        SHR EBX, 10h
    6 k+ |# ~7 X, S2 l6 z
  465.        MOV WORD PTR[EAX+02h], BX
    # x0 i. I: @! W; `/ U- a$ T! w

  466. ) ?( v/ T0 T" o8 T& L0 m1 a% v
  467.        // 激活Ring0代码
    4 ?% J( a% R7 [$ G' i0 e
  468.        INT nHookExceptionNo9 K1 H5 A6 x( \8 U

  469. * ^, D. p" l  P9 T: C
  470.        // 复原入口
    ! M; t4 `2 a& |+ Q( M1 o+ V$ W) x
  471.        MOV ECX,dwOldExceptionHook
    0 ~; U9 `. t, F
  472.        MOV WORD PTR[EAX-04h], CX
    2 x7 t" |. V! n# q0 E6 U% [/ @
  473.        SHR ECX,10h
    ' u* ?, j- u8 A) K& k1 _
  474.        MOV WORD PTR[EAX+02h], CX* G' y( d+ x8 v( q- b# s
  475.        STI
    $ i$ b" w  d9 b  {6 Y2 g
  476.    }. [: q+ I* _( Y0 }: N4 v
  477.    if(!bIsFirst)
    - a3 `) I9 F' F/ A
  478.    {! |6 |4 G( B8 y& O
  479.        bIsIDEExist  = (bool)btIsIDEExist;! g! ?! e( b5 U  g1 D
  480.        bIsDiskExist = (bool)btIsDiskExist;# I7 S* N/ J& ?4 X
  481.        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
    ; T/ e$ n% [' T- ?8 x3 Q' R
  482.    }
    : e) I! G% \9 F) x7 V2 q* [
  483. }% y& q) S% K1 W; E8 A# P7 v+ M- g+ S
  484. //---------------------------------------------------------------------------
    $ w: s* `% W( B+ F' H, t
  485. // 调用方法:2 X9 V4 b5 |, _) A" ^4 k) ^( a: f
  486. void __fastcall TForm1::Button1Click(TObject *Sender); d1 K1 R# L' C( t! b. G0 F
  487. {
    6 `& J- t9 W1 ?9 U4 U
  488.    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);" F0 N  Q+ M, p+ M
  489. }
复制代码
发表于 2005-8-15 01:00:45 | 显示全部楼层
晕乎乎。。。怎么看8 洞阿
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-6-19 08:39 , Processed in 0.016032 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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