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

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

[复制链接]
发表于 2005-8-11 11:42:04 | 显示全部楼层 |阅读模式
  1. #include <WinIOCtl.h>
    ; k9 h$ B- J/ d, O& I$ X$ X
  2. #include <stdio.h>* k5 w4 o. L" K5 N! A  i: t
  3. ' t" M% f6 D! a# P; q2 ^/ q
  4. #pragma inline, i5 X7 O" o# J2 O! m- e8 B* q: H
  5. //---------------------------------------------------------------------------
    ! h! ?8 I: H1 A# t, P: o) \
  6. // IDE NT/2000/XP专用变量
    7 v. b4 ^0 |+ G+ G
  7. #define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
    9 ?+ k5 S1 F$ x$ L0 D
  8. #define DFP_GET_VERSION         SMART_GET_VERSION: y" a0 B3 p  |* V
  9. #define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
    ) g# B$ T" n& {) F& V5 V
  10. #define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA0 @8 N' b5 a5 O3 f! N# p

  11. ) ^3 M* T- a5 q0 F4 ]  N% s' j: W  t
  12. const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令# N% k5 z+ `8 y0 V
  13. const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令: w+ b- |% c0 A- ~
  14. ' g8 c( G: W/ f( r. M
  15. const int MAX_IDE_DRIVES = 4;" P3 j' `: D+ |( {

  16. - v% k' {5 a8 I4 a5 k
  17. // SCSI专用变量
    4 l$ y! f2 w$ y) i" P8 C
  18. const DWORD FILE_DEVICE_SCSI             = 0x0000001B;
    ! _$ |9 A, _1 o# N8 c
  19. const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
    7 A" i  R7 e  v4 x8 M
  20. const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
    : t) `. i; ], e, ^9 D- V1 u$ r
  21. const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;7 o' x+ i  J) z+ ?. h

  22. 0 I" A) D" ~, v; C* G
  23. typedef struct _SRB_IO_CONTROL4 a4 m3 f6 c5 q' V
  24. {
    ) `) q" c& Q& Z: x2 T
  25.    ULONG HeaderLength;4 O4 i, Z6 C; t/ F' I1 t. f
  26.    UCHAR Signature[8];; R% r/ z: H* ]+ C  p6 F
  27.    ULONG Timeout;
    " H; i, t/ k# t: p5 A5 _6 t5 |
  28.    ULONG ControlCode;
      u5 Z+ U1 `1 J( `8 y" y/ ?
  29.    ULONG ReturnCode;
    8 }+ H7 {8 k' C/ |$ q0 J, G
  30.    ULONG Length;4 C8 Q" w; \, @5 f
  31. }SRB_IO_CONTROL, *PSRB_IO_CONTROL;) P- Y8 j$ f; W; v: b, e# {
  32. * d) C4 d. y. M% J- K) V4 `% P
  33. // 读取的主函数$ w0 ^% `" E& \7 Z5 X8 W( b: n
  34. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);5 y) y! A2 u, f% P, ?

  35. 3 p/ ^, {& }7 `6 N/ H
  36. // 辅助函数
    - {; l$ r" ]# u; V3 B  R8 B( b
  37. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);. ]* d: C# R5 q2 W
  38. // NT/2000/XP函数9 r2 A6 Q1 l) }2 k' ~
  39. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);! ~' }3 Y. M9 s
  40. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
    0 f) }( T( U  _- a# ?* P3 ~
  41.        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,2 `) {4 r* ~! O" ~8 B7 M
  42.        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);/ z4 U1 o1 D- P& H, y& }* j( y
  43. // Windows 9X函数1 z/ y( I! u+ E) F# E6 o5 E
  44. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);$ ]" a0 Q' G' d" W- }+ l6 J
  45. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress," O8 ?1 \' x! w
  46.        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
    1 ~# Q. I- M* s- C
  47. % x* o' D, f6 D# h5 Q! |2 ?
  48. // SCSI读取函数(for NT/2000/XP)* {/ o2 d& q9 c0 j
  49. String __fastcall ReadIDEDriveAsScsiDriveOnNT();) H8 h( F2 l5 i4 X3 ~$ b( V
  50. //---------------------------------------------------------------------------
    1 v, q% Z7 P% `6 ]) s+ l+ ?5 M
  51. // ReadPhysicalDrive
    4 {& B" m; G  @( o' W& X0 l/ \. x
  52. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
    0 v- h+ i1 `& T' U
  53. {
    2 T- Y1 g# p' d: O* _  t) F; K* e
  54.    switch(Win32Platform)9 b6 H% p3 |- g# b
  55.    {& u3 C' f" @5 D+ Z
  56.        case VER_PLATFORM_WIN32_WINDOWS:) Z: A( Q) _2 G9 J6 }
  57.            ReadPhysicalDriveOnW9X(pSerList, pModeList);# u( ^' |( W1 j0 `! n
  58.            break;
    ) y7 N; w' V1 l! b7 ^" M* N+ a
  59.        case VER_PLATFORM_WIN32_NT:
    * k3 D+ U" l; ]
  60.            ReadPhysicalDriveOnNT(pSerList, pModeList);
    : p* j0 I3 O( r
  61.            break;
    ! \9 R5 k* T$ P( ]  ?# Z2 S* F
  62.        default:( W: {; v/ ?4 ~& x1 m
  63.            break;
    4 Z$ K7 B( z* Q) a6 l) D- u
  64.    }6 T0 i% g9 c  o! x
  65. }
    8 [( |. z' `$ U! T; {; e& s/ R
  66. //---------------------------------------------------------------------------
    ' @& J3 l9 }. g* ^: ]
  67. // ConvertToString, J* J4 u& d- z
  68. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
      ]2 O' V7 t- b, f+ e& O
  69. {
    6 d2 t# @0 o' i0 `8 a, a5 g+ b
  70.    static char szResBuf[1024];
    3 P. E' P7 n  y6 U- M
  71.    int nIndex = 0;
    & _, F- \9 N6 o- x' p
  72.    int nPosition = 0;' ~7 F6 `+ T8 W+ I6 H

  73. - }, D4 S8 P; O  {  o7 c: U
  74.    // Each integer has two characters stored in it backwards
    . m5 T% U. X8 r5 X; j' h- t$ Q! r
  75.    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++). v6 i1 x8 s' E& b% m9 H
  76.    {% h; q/ [! I6 O: b3 G7 H
  77.        // Get high BYTE for 1st character& j) C" f2 n3 A; i
  78.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);! y& m6 J7 L5 A7 Q. M. `4 l! d% i9 C
  79.        nPosition++;) S9 O8 |+ @' j3 t$ u, l

  80. % a2 w3 {2 y% z+ `2 J4 D, G
  81.        // Get low BYTE for 2nd character
    9 t0 A2 H- U& A& ]% B
  82.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);& @0 m# p' R6 p+ c
  83.        nPosition++;
    * I/ s- x5 D$ n. q/ _6 K$ T: _) M
  84.    }; @) e! X  W) A. H8 s3 M) S7 b0 G: s
  85. 7 d& N  M2 g+ R* v5 S0 x1 A9 S
  86.    // End the string
    ( ~% |2 X9 S' r% ]
  87.    szResBuf[nPosition] = '\0';6 j1 u  R& [( b& ^( r6 v/ C
  88. ; M; j' X' f5 i( A
  89.    // Cut off the trailing blanks; v& Y" j2 b, o/ d2 w' ]
  90.    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
    , c4 Y8 `$ D! T0 W5 o
  91.        szResBuf[nIndex] = '\0';
    : n# x8 T. c) o! q

  92. & P4 `' a4 @! j! z; S& q0 S2 h& o- r
  93.    return szResBuf;% w: v: Y% |! h- [$ A
  94. }
    + d/ q/ v4 |/ Q1 c
  95. //---------------------------------------------------------------------------& ]/ J  f1 c5 y& \- \# y
  96. // Winndows NT4/2000/XP 代码
    ; V8 \8 H  n, |1 e/ Y5 R
  97. //---------------------------------------------------------------------------( V% D  w- r1 q
  98. // ReadPhysicalDriveOnNT
    ! Y, C7 F# U4 V+ q
  99. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)! L: z2 J7 R3 _& x% Y3 c# U
  100. {
    6 b( @0 @( N4 c, O/ N: |
  101.    // 输出参数
    1 s9 [( E% J! v0 V8 H  r
  102.    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
    / j8 V& g) |' t

  103. 3 _2 X0 M  I* m6 A# i1 K1 p% g
  104.    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
      S# L& D6 i! |
  105.    {
    ' F8 o- ?5 z. @: F& M
  106.        HANDLE hPhysicalDriveIOCTL;
    , a+ j$ c/ X; T' k) H, k
  107.        char szDriveName[32];
    + m$ g, ~4 U- @) }
  108. ! A: @$ E$ K% a9 \8 q1 R4 W
  109.        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);% F6 Y& l4 F! i: W/ ?+ a
  110.        hPhysicalDriveIOCTL = CreateFile(szDriveName,+ Z5 x# j( g4 \  p# q6 X7 ?
  111.                        GENERIC_READ | GENERIC_WRITE,
    : {/ O% b6 y. L% H
  112.                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,, Z0 B& y$ V% g# U; x" N
  113.                        OPEN_EXISTING, 0, NULL);
    : w# Y9 ^. i* r2 E. K& B

  114. 1 Q" ^4 q! t4 I
  115.        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)0 h5 Q( w; z" z  b  G7 A5 m
  116.        {7 V: Z$ _7 d5 E
  117.            DWORD dwBytesReturned = 0;3 A" d; m* L9 H7 Q3 f8 T
  118.            GETVERSIONOUTPARAMS gvopVersionParams;
    , `: f5 ~, X4 T5 I5 g0 Y' f

  119. 6 c( C2 F9 o4 z' F
  120.            // Get the version, etc of PhysicalDrive IOCTL
    $ `1 G; b: E$ k) U# k7 R; v; _3 H
  121.            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));" {- i2 T' [7 j3 B8 P
  122. 0 y4 o5 F; p& p: S* w# u6 o
  123.            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,7 d6 s5 O4 [) ^
  124.                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),6 n  H6 J/ u% D) r( Y9 y+ Z& f
  125.                    &dwBytesReturned, NULL))
    0 Y) S! Y2 F3 {1 X  n& F
  126.            {
    8 x- B  }4 _+ q9 [7 S' W& F
  127.                continue;
    $ @8 i, m6 Y! k' S$ o/ g0 A8 I( I5 q
  128.            }
    & O9 w4 j- @- @* u5 z4 q
  129. $ {- U5 p9 J8 ]* [4 T3 f
  130.            if(gvopVersionParams.bIDEDeviceMap > 0)! d, U/ i) h1 _( R# H2 z8 Y
  131.            {
    1 t( [1 m5 b* p
  132.                // IDE or ATAPI IDENTIFY cmd8 o5 ?' _# M3 T# `, Y
  133.                BYTE btIDCmd = 0;
    & b0 d) h- f3 Q7 S8 ?1 R
  134.                SENDCMDINPARAMS InParams;' E6 [' I& B5 D( D* I* j( c. k
  135.                // Now, get the ID sector for all IDE devices in the system.& q( k5 [- t" J2 v5 a# T8 R$ W9 _0 p
  136.                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,' q1 b- \7 U8 F( F. v
  137.                // otherwise use the IDE_ATA_IDENTIFY command' X- _0 o  W$ n* ?; I# r9 h
  138.                // 具体所得结果请参考头文件中的说明
      e9 Y. s. s6 \* j8 A
  139.                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
    5 _1 @" Q- d/ \9 |8 \* v+ M+ X
  140.                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;. G1 _/ C6 `/ u; m$ K8 U/ r# |
  141.                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));1 K$ f$ b7 g" j& N0 b3 z
  142.                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
    2 P8 Y6 o& J( u& c5 Q

  143. / r1 T1 m! e/ I( Y- T" y5 b
  144.                if(DoIdentify(hPhysicalDriveIOCTL,
    2 y; D" o' X% L* j) {* m: P% U
  145.                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
    0 n/ Z5 z, g0 m: G/ I, |+ a
  146.                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned)): R/ M3 j* v! e5 j0 L- H6 O
  147.                {1 V# V# `# E8 h! |7 X
  148.                    DWORD dwDiskData[256];
    : D* S9 d- w2 j7 @( [8 x
  149.                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件: t( @3 j6 K& P3 i! s; o  O
  150.                    char szSerialNumber[21];- }& x+ v2 a4 `' Y- L$ \: i
  151.                    char szModelNumber[41];
    0 z% V- T2 A$ E# ^( g
  152. ( z7 s+ {1 \6 R  F+ {
  153.                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
    ( L8 v/ O* H# f1 g$ i0 W; D
  154.                    for(int i=0; i < 256; i++): t9 V/ A: D3 d; H  _, g' F$ P4 O/ p
  155.                        dwDiskData = pIDSector;
    8 l; ?8 Z' r& j# @' A
  156.                    // 取系列号: t$ b# B# E; {) M( \: d) X! u* R
  157.                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));0 I6 T' Q) [" V3 {7 J- c# u5 K' N
  158.                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));$ J# z0 }! e- i" O, r; c

  159. ' L  X  Q3 U+ K! G* j
  160.                    // 取模型号8 F4 {$ e9 M7 h+ q' p7 B
  161.                    ZeroMemory(szModelNumber, sizeof(szModelNumber));
    0 S8 a* t- a' K0 C* H' Y
  162.                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));$ Q6 Q7 i8 H4 H; Y2 h! P  L# V" ^
  163. 0 d: w" a& X2 z, k- f; d. x! B9 g
  164.                    pSerList->Add(szSerialNumber);
    7 O% G# O, J! m
  165.                    pModeList->Add(szModelNumber);
    # `( s) ?' h8 l+ v# s& L# k
  166.                }
    3 s" s* f6 f9 M! D
  167.            }
    : a* M, a$ }) M+ R
  168.            CloseHandle (hPhysicalDriveIOCTL);5 ~6 ^; {( f( U0 A
  169.        }6 e; v3 L! F4 F6 w& u# O
  170.    }! r9 V: x. L7 l9 ^# ]
  171. }& u8 B2 Z; M( q1 w9 g  _) K% q1 a
  172. //---------------------------------------------------------------------------
    " d9 A" w5 F& p/ t* V1 @3 F2 b2 q
  173. // DoIdentify
    * O% E2 G0 k8 ~* k
  174. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
    ) h* k, M1 x' d4 |; }! V' }
  175.              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
      R* Y; z2 c+ Q
  176.              PDWORD pdwBytesReturned)3 S) B7 Z/ g& J
  177. {$ t4 n; }3 c: Z% O7 L
  178.    // Set up data structures for IDENTIFY command.8 u; Q3 w( T! o# P; a
  179.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
      N! X& _2 L; R4 s" t- f  V; v& P
  180.    pSCIP->irDriveRegs.bFeaturesReg = 0;
    $ D0 d& _% z) {1 R- ]
  181.    pSCIP->irDriveRegs.bSectorCountReg  = 1;+ u( a# \. G7 v+ r9 C9 T
  182.    pSCIP->irDriveRegs.bSectorNumberReg = 1;
    # f0 n/ W1 v2 m5 h5 \/ p7 D6 Z6 S
  183.    pSCIP->irDriveRegs.bCylLowReg  = 0;1 m/ g; \4 V3 [' Z, Z/ E) N
  184.    pSCIP->irDriveRegs.bCylHighReg = 0;
    ; O" T" l6 X6 K; @( Z4 w

  185. * e/ Q) d* q- s7 ~6 g4 C6 o& ]6 [
  186.    // Compute the drive number.(主盘和从盘所对应的值是不一样的)
    ! D2 r: H/ D& A1 y9 W# P
  187.    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;7 E; ^( s$ O# t

  188. 3 `8 J- h7 h( m  q" {. U
  189.    // The command can either be IDE identify or ATAPI identify.8 q0 Z  g4 K. t$ n9 s
  190.    pSCIP->irDriveRegs.bCommandReg = btIDCmd;
    ' n8 F: M; l" B7 e! J# L
  191.    pSCIP->bDriveNumber = btDriveNum;1 |2 [& V8 Y0 U8 Z
  192.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
    , o5 Z* A; B# J
  193. + p7 R( P1 P9 Y  U4 X- x
  194.    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
    ( C1 h# c$ b8 `( v7 \9 c# U  A1 L
  195.           (LPVOID)pSCIP," s, F# K/ E9 D; T5 u
  196.           sizeof(SENDCMDINPARAMS) - 1,( X4 ?) \6 A/ s6 w/ P! [2 N' L
  197.           (LPVOID)pSCOP,
    ! E3 h" n/ G* N  C  x
  198.           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,( Z8 W" w1 X; q: X  N) W# Q
  199.           pdwBytesReturned, NULL);
    0 N8 k# ^' \; |1 h4 D, v: e! c/ H3 f& t
  200. }
    . a# E' U1 H, \2 V1 S
  201. //---------------------------------------------------------------------------
    1 m9 W* X; t& H/ N
  202. // Windows 95/98/ME 代码" V/ b: F: |2 Q: G) z
  203. //---------------------------------------------------------------------------
    " \- v! U2 R& z: R" A
  204. // ReadPhysicalDriveOnW9X
    : P( O6 G4 a3 {: Y" W
  205. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)
    - O! T' P. K+ ~. ~1 O$ p0 s) r
  206. {
    3 s/ {3 i4 V5 U% W% _# X
  207.    WORD wOutData[256];
    7 U1 w/ |8 `2 r
  208.    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
      n; [4 l) |: J( s0 n* X

  209. 7 O' b6 w: h  R+ [
  210.    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
    . X% F0 Z- p( R7 J% J
  211.    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
    4 r2 |# S3 j8 h0 Z0 B% ^
  212.    // 避免蓝屏的出现。(期待高人能指出原因)+ P" K7 J' [5 `$ d9 d
  213.    for(int nDrive = 0; nDrive < 8; nDrive++)
    $ ^6 v; ?6 S0 _
  214.    {
    1 J3 K; Z+ X9 Z) o- V
  215.        WORD dwBaseAddress;6 m+ ~* \$ z4 f
  216.        BYTE btMasterSlave;         // Master Or Slave4 x1 m& x- }  v* D/ p, A3 f" W
  217.        bool bIsIDEExist;
    1 ^2 a( G' M$ r0 L
  218.        bool IsDiskExist;
    ! E# T9 Y9 B3 t& u+ ]3 ~

  219. # B( n6 M3 r6 L, g% J  A0 I" T
  220.        switch(nDrive / 2)% u" E" N7 X, O4 i) |' h# ~
  221.        {/ \8 y7 L% l) u7 F2 S" R4 h# S- W' S0 j
  222.            case 0: dwBaseAddress = 0x01F0; break;
    4 V! G* H2 b( x- ^; [
  223.            case 1: dwBaseAddress = 0x0170; break;8 h+ N; D: ~$ f2 o' m
  224.            case 2: dwBaseAddress = 0x01E8; break;1 p1 c. V" Q6 B0 I6 j
  225.            case 3: dwBaseAddress = 0x0168; break;
    * ^/ B' X8 r; M5 N5 y
  226.        }
    8 f4 k" N% [3 z
  227. 3 T6 |% ^: \. @9 p* |
  228.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);) t  l; r! |) P+ ?+ W

  229. - |$ Y& a( z' C! }, o6 P
  230.        // 进入Ring0
      C* R: O7 n( w: ]! \7 q
  231.        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
    6 B, Y, n  ]$ q  [
  232.                bIsIDEExist, IsDiskExist, wOutData);! v7 \' t3 m& E. X
  233.    }
    7 Z9 ?2 ~& W9 h& \
  234. : i9 U  o+ o; @9 m! f) S$ M( E+ b
  235.    // 开始读取. V& S  }! L/ c% R. x2 l/ O
  236.    for(int nDrive = 0; nDrive < 8; nDrive++)
    ) x, m0 U! t- C: r  H0 z1 E& d
  237.    {2 o2 F- i  S, k
  238.        WORD dwBaseAddress;- _+ t  D$ [/ z, Z
  239.        BYTE btMasterSlave;         // Master Or Slave
    : m/ [9 U" x. Z+ H
  240.        bool bIsIDEExist;
    / a: C/ i6 c8 C# @" Q0 B0 A- r
  241.        bool bIsDiskExist;
    ' L3 o$ l9 l( T) p4 u+ p$ M% L( A
  242.        switch(nDrive / 2)- L9 n0 r6 P! m' H5 p1 b) Q' O4 O
  243.        {
    ( a# j% j# t% W5 o( S
  244.            case 0: dwBaseAddress = 0x01F0; break;
    4 A$ {1 Z; p0 H9 F2 R
  245.            case 1: dwBaseAddress = 0x0170; break;# r' B* G# D2 n" i; z
  246.            case 2: dwBaseAddress = 0x01E8; break;
    7 X% ]( @1 T+ l  _' Q/ \
  247.            case 3: dwBaseAddress = 0x0168; break;$ n2 h# a4 }2 j! o! w$ q9 [0 @
  248.        }9 p% ?0 m6 S; N

  249. ' i; i: |- H8 k: s- p
  250.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
    3 `2 E6 g* {2 ]$ r: O
  251. 0 N- q. ]/ ]& y& r3 S0 x5 Z
  252.        // 进入Ring0
    : T  ~, C/ D; V; c; S
  253.        bIsIDEExist  = false;
    , n9 o! c% H  Y( N. q* O3 X! S+ N
  254.        bIsDiskExist = false;5 A8 A# o) h6 l( P+ W+ u
  255.        ZeroMemory(wOutData, sizeof(wOutData));
    ) f2 r  ?9 \8 _' c
  256. 9 k' ]& X. u; j: w( p! `
  257.        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
    : o4 \/ V7 f1 Y8 s# t  _* `
  258.                bIsIDEExist, bIsDiskExist, wOutData);
    ; [1 X; ]" F- k

  259. " d; F' g! m2 c+ d
  260.        if(bIsIDEExist && bIsDiskExist)% E8 N* Q* j* u, z
  261.        {0 R# y- G- S' o
  262.            DWORD dwDiskData[256];
    9 W; H( s9 u! M2 V- w( }
  263.            char  szSerialNumber[21];2 l! V3 F: w' j1 {# Z- D+ K
  264.            char  szModelNumber[41];# ]0 o7 Z. L7 R7 g" a6 y! b

  265. + Q7 ^, x" `- E; K2 V2 w: D
  266.            for(int k=0; k < 256; k++)& e9 C# U7 ?+ J% x2 V- B
  267.                dwDiskData[k] = wOutData[k];) C  S; H% e; v/ M

  268. 9 u, l7 S; }' ]% g# w, c- B
  269.            // 取系列号$ O" _7 s! U; `. }3 z7 Q; p, f2 F; L* m
  270.            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));) n! S/ M& P: k  H2 H6 O6 j
  271.            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
    : v" Q7 ~8 A7 J  p* X2 Y2 v

  272. ) ]% J" L6 h( d8 P3 p& m
  273.            // 取模型号
    4 s+ R2 E/ t4 X
  274.            ZeroMemory(szModelNumber, sizeof(szModelNumber));6 v  s" E1 e  J/ G& W; T( r
  275.            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
    4 z" s! t8 ]% `
  276. . N5 d7 q) d: q) L& ~
  277.            pSerList->Add(szSerialNumber);' M: @6 h5 m; \" r, M' i2 L3 N+ G
  278.            pModeList->Add(szModelNumber);8 j& T* t" X1 l
  279.        }$ o0 c! D- x1 f0 [7 x# y, m
  280.    }
    ; O" k) |/ u$ C. E9 F7 L' K
  281.    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
    + G: @) p; w6 E# O/ t/ B
  282. }
    3 S; T4 u; ]: H  A# p8 b+ ~
  283. //---------------------------------------------------------------------------# t8 T' K9 ]- T/ J' y% N
  284. // ReadPhysicalDriveOnW9X_Ring0()
    ! G  {2 q) H9 {" L4 D
  285. //
    ! o% i' S8 K$ N3 t0 A
  286. // dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h1 [* H: D' }0 }1 Z
  287. // btMasterSlave = Master(0xA0) Or Slave(0xB0)
    # k) R( j" S% `! e+ Q! Y4 F
  288. //---------------------------------------------------------------------------
    , O5 b5 P& F, s) B
  289. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,1 V8 v" w% Q0 R7 |
  290.        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
    ! Z6 ~+ @1 h1 c9 c) t) U3 ~9 u
  291. {- a! W8 l! h* |- e1 ?% x0 t$ d
  292.    BYTE  btIDTR1[6];
    7 i, m# G' o) u# d6 R2 c+ ^
  293.    DWORD dwOldExceptionHook;
    ' U+ A1 J/ T7 m9 K2 A
  294.    const int nHookExceptionNo = 5;
    6 _3 M1 @0 ]$ U+ s

  295. ( D6 ?+ e! w' e' P) u( a% q3 W$ R
  296.    BYTE  btIsIDEExist = 0;
    & j! r8 M3 `1 S7 H0 C  T
  297.    BYTE  btIsDiskExist = 0;- i( ]# x( o9 H: X
  298.    WORD  wOutDataBuf[256];
    - A1 n) i4 J9 e8 G. B+ ~  p' K

  299. # v3 h# f- x, F" F7 M
  300.    BYTE  btIsFirst = (BYTE)bIsFirst;
    8 X) j) v' `2 K9 m( m- ^  f

  301. 8 M- E8 D- \/ Q( J# E! `
  302.    const BYTE btBit00 = 0x01;6 i3 p' V- p: M. F- Y( v
  303.    // const BYTE btBit02 = 0x04;5 H6 ^8 Y3 V: d" x  W
  304.    const BYTE btBit06 = 0x40;
    , s2 _( ?8 ?' y% z" z: `
  305.    const BYTE btBit07 = 0x80;8 b" s  b( F# v# E# H+ x" F
  306.    // const BYTE btERR  = btBit00;8 Z* M) l7 I0 V! Y
  307.    const BYTE btBusy = btBit07;
    5 Q$ F& K8 I+ ], I( }3 I; F8 s
  308.    const BYTE btAtaCmd   = 0xEC;
    3 S7 K& C5 \* W# Q
  309.    const BYTE btAtapiCmd = 0xA1;
    + @% Q' l& l3 V9 Q

  310. ' A+ [# U% d4 T0 L* I& N
  311.    __asm
    0 G$ L1 x2 y9 D8 S4 T
  312.    {
    5 t' H" N6 Y" `* G4 @* I
  313.        // 必须先执行这条语句* h/ [6 m0 e5 A
  314.        JMP EnterRing0. j5 _  D5 k# ~- G  _' K

  315. 1 ]5 e8 G+ k/ Y9 r
  316.        // 定义过程
    9 m% q0 `% F/ @9 \! P
  317.        // 等待IDE设备直到其不为忙为止
    ) ?( j( P: S1 N7 L9 ^; T( x
  318.        WaitWhileBusy proc
    & ~) s, J  x* o/ L

  319. ; K% W- O, X+ \  _0 J" l( T  Y- x9 ~  W
  320.        MOV  EBX, 100000
    ( A8 t  L, e2 p7 M* p
  321.        MOV  DX, dwBaseAddress& R0 C4 X& @! k8 o$ ?
  322.        ADD  DX, 71 y0 {2 W- Q8 m- e- k0 e

  323. + S: E( ^6 }7 p- ~' G- U9 M
  324.        LoopWhileBusy:- X2 J" w& v) w& v3 [
  325. 9 L9 Q% w2 n; ]( Y/ f1 |
  326.        DEC  EBX
    3 w; @( X+ K& K5 }3 V3 {5 j
  327.        CMP  EBX, 0" S1 @" T! I, Y+ P4 z
  328.        JZ   Timeout
    2 R% ]0 m2 Q; h, B! K
  329.        in   AL, DX( E; N2 _5 W+ i
  330.        TEST AL, btBusy
    ; V  q' f3 B  H3 `1 W" v
  331.        JNZ  LoopWhileBusy
    / C% ~2 l0 b& {: }8 ^
  332.        JMP  DriveReady
    + ]  i. w$ k+ g$ |6 W" g6 ?

  333. ( u3 B( n: u" k0 ]5 A/ O5 S
  334.        // 超时,直接退出7 s1 G1 P1 n$ K( r& a* N. l6 o
  335.        Timeout:
    0 ~3 v& I& i. _" z# ~; ^
  336.        JMP  LeaveRing08 h; V& Y* Z+ {* |$ k
  337.        DriveReady:
    4 \$ d" g3 y% m8 p# A/ u
  338.        RET# ^+ T( C5 @' _( C  j, ~; b
  339.        ENDP   // End of WaitWhileBusy Procedure
    6 L) M+ g; _' t" `1 s0 b
  340. * U, W  r' V1 d
  341.        // 设置主盘和从盘标志
    + X8 Z4 S! Q- G* F
  342.        SelectDevice proc
    & ]. l9 r8 z; y7 B" C

  343. 8 R; K5 z/ J& M8 d
  344.        MOV  DX, dwBaseAddress
    / H8 J7 I! x" L9 y
  345.        ADD  DX, 6
    % u$ s1 H+ _) M+ p  F  t
  346.        MOV  AL, btMasterSlave3 N; x( N3 V! |" c6 c/ e

  347. - U" e  {& s' W" h
  348.        out  DX, AL
    2 J' U/ S/ M$ M5 P/ m
  349.        RET
      \  N) O. |' s! F

  350.   v9 q, ~+ S  B" O
  351.        ENDP  // End of SelectDevice Procedure2 D/ G) ]1 v, i. d" K( d" ^
  352. ; G; Q) L1 P( O2 u1 }: |5 B
  353.        // 向IDE设备发送存取指令- U; r, s8 v" [% D, Q
  354.        SendCmd proc
    & L5 s1 V& S" o7 m; w2 D

  355. * C. e. X( B% Q) `, T, J6 H
  356.        MOV DX, dwBaseAddress
    1 t0 n2 i" E* g7 W! r9 V" y, k* I  S
  357.        ADD DX, 7$ S+ g6 d/ |- T: r. P3 k- h& F3 C
  358.        MOV AL, BL // BL是主从盘标识,在过程外设置# a4 w0 J( Y, g) s5 o
  359.        out DX, AL
    ' P6 z" a3 g; w! ]1 q: L
  360.        RET/ h$ s7 d2 Q* g  m: h8 Z6 U4 B
  361.        ENDP  // End of SendCmd Procedure
    - V; Q# [( o, x7 G

  362. : z) c0 f* A' Z! N  r) h6 J" Y
  363.        // Ring0代码! o) U! W$ T8 s7 p2 ?# s5 M
  364.        Ring0Proc:7 e6 ?- B4 g4 t" C9 ^
  365.        PUSHAD! _: Q( S# f, j" N& \
  366.        // 查询IDE设备是否存在8 {/ o6 }! ], u* N
  367.        MOV DX, dwBaseAddress" T* A+ V7 O$ x
  368.        ADD DX, 7
    4 J1 G' C. q4 T# @7 h" x
  369.        in  AL,DX4 n' V0 K: K' o7 N, K
  370. " X* v. n) [& d% l
  371.        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
      Q! P0 S- F3 m# e" w
  372.        CMP AL,0xFF
    * n1 s! O  c8 y6 x+ V" v6 y
  373.        JZ  LeaveRing0
    + b6 R, [) p9 S- s
  374.        CMP AL, 0x7F7 _1 p' |9 k( N' t' D
  375.        JZ  LeaveRing0
    ( X, E& F! j$ G& t4 Q) B

  376. , _1 @8 O7 Z( j- M# F
  377.        // 设置IDE设备存在标志
    3 e* n- F$ o6 S5 [5 I% E4 k  u
  378.        MOV btIsIDEExist, 1) y) P5 n. `4 w$ S
  379. : |( x- S4 \  C
  380.        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)0 N! v9 u! H5 {" T. m7 O! b) Z! r
  381.        CALL WaitWhileBusy/ j% F4 H8 B* f, ^
  382.        CALL SelectDevice
    . p) k3 {/ [$ v  t
  383. % m+ L$ Y3 S1 p" `
  384.        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
    " r# K1 I* z* v& o
  385.        CMP  btIsFirst, 1; m5 F8 W( {1 j. X  U& _" y
  386.        JZ   LeaveRing0! ]7 j8 ^: b3 a4 T
  387. * w6 ~4 v3 \6 z1 q& B) h. T$ B5 S
  388.        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
    3 T' F% k/ _- N2 T8 Z
  389.        CALL WaitWhileBusy! f4 b8 h, ~0 n9 Y  B0 r
  390. 2 Z7 r& Q. O: p; f- f
  391.        // AL的值等于cBit06时,不存在驱动器,直接返回
    1 e, v0 `* n. L9 n5 h8 i# \# T
  392.        TEST AL, btBit060 D0 J# H' r. |- ^- j& m  l- e
  393.        JZ   LeaveRing0
    4 @: Z  k2 h; Y0 g$ o& @! Q+ A1 K

  394. ' T1 H7 Z; [" _" z
  395.        // 设置驱动器存在标志
    ! u, k" l$ h7 {) T
  396.        MOV  btIsDiskExist, 19 f/ b) W3 Z2 u. l
  397.   Z: v8 f5 z% B5 m* \8 [
  398.        // 发送存取端口命令- D! s. @8 V- v/ }" Q
  399.        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
    - P* A; Y/ N& T0 T3 P2 c) S- {! r
  400.        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令* O2 b! A5 u) B- i
  401.        CALL WaitWhileBusy2 D3 B( K8 r) r7 @3 o
  402.        CALL SelectDevice    // 设置主从盘标识
    6 W" s6 L9 ]5 [$ g
  403.        MOV  BL, btAtaCmd      // 发送读取命令
    9 P% H: H8 C2 A% B( o) c! N7 k5 L
  404.        CALL SendCmd
    . D( P8 `/ B. U$ {+ \
  405.        CALL WaitWhileBusy6 Q% Z3 `7 S- B0 z! Z4 B! i! w0 [4 x

  406. ' w6 V- V1 x7 P4 }+ P( l
  407.        // 检查是否出错
    $ ?2 z+ I8 P% I7 ]
  408.        MOV  DX, dwBaseAddress
    ) P/ S; X1 G. {5 `6 e
  409.        ADD  DX, 7* X& u% q9 @' \# f: k6 F

  410.   ^. ]+ i# x. w
  411.        in   AL, DX
    * Q! c3 i' N1 q; F
  412. . B/ B+ L8 S. K4 s: X
  413.        TEST AL, btBit004 h$ ^& p+ O, H) D! l3 f
  414.        JZ   RetrieveInfo   // 没有错误时则读数据. A" m: q7 I3 v; \
  415. / N1 G' [9 x/ T1 S2 [3 e( G
  416.        // 如果出错,则进一步尝试使用ATAPI设备命令, [! v* Q5 _- t3 u. P
  417.        CALL WaitWhileBusy9 |0 R/ v; ^+ c) w2 S! B, |% W
  418.        CALL SelectDevice
    8 n) u5 @5 a" Q  e7 Z
  419.        MOV  BL, btAtapiCmd
    - }7 Q5 M3 d7 m
  420.        CALL SendCmd7 x0 q  l  ?& u* y
  421.        CALL WaitWhileBusy
    , \& ~, U9 m: f  B; t! [6 W

  422. ) V- B0 D$ g0 M6 p" f0 Y
  423.        // 检查是否还出错: v. P) \) H- V" `' G. y- O
  424.        MOV  DX, dwBaseAddress
    5 K; k; H2 `% @$ k8 R, M- B/ k
  425.        ADD  DX, 7
    $ K' S! c& z& g) ?  u' h
  426.        in   AL, DX
    & x) |7 T/ u: x2 Q
  427.        TEST AL, btBit003 o1 y1 J9 v& j2 P: P3 W
  428.        JZ   RetrieveInfo   // 没有错误时则读数据
    ' P* U2 a* D0 ~6 y
  429.        JMP  LeaveRing0     // 如果还是出错,直接返回9 w7 ~/ S9 q+ n

  430. & `) D2 }  ^7 M$ M, X
  431.        // 读取数据, ?# b, N; T$ A. m( |/ J9 _
  432.        RetrieveInfo:
    5 J, z2 |8 B* D: a% Q

  433. ' y) N6 m8 K1 t" f  j; Y
  434.        LEA  EDI, wOutDataBuf
    4 ?, T" k7 L* `+ u$ x- w: ]% D
  435.        MOV  ECX, 256
    6 [# {7 ?- p3 k" N. X
  436.        MOV  DX, dwBaseAddress+ y" o- q  s) p6 X4 e% f8 ]
  437.        CLD3 `" \, f3 o/ K, ?- Y7 i% v! M
  438. 8 x) _9 R% s$ h  Q
  439.        REP  INSW5 d( |' z2 b7 l5 p* q* F# b% _9 B  w

  440. 2 z3 F6 X; F. T. d8 d1 W
  441.        // 退出Ring0代码" ~% b) Q3 t3 q4 _6 ]& R' U& w  j
  442.        LeaveRing0:
    , q& o: k4 h& v( x  y1 x/ B4 F' A

  443. * [( c) J1 t: \. W- w
  444.        POPAD& }4 F7 \( _5 E( R8 X# [& }' I4 p
  445.        IRETD
    7 I( e$ Z+ E! e0 @
  446. + V) c$ Q/ I1 }; W) h2 w4 C
  447.        // 激活Ring0代码# ?/ k) B/ I- m0 u2 R: @
  448.        EnterRing0:: E! @, V" w6 _" d6 Q" C( n

  449. 4 M1 N, t5 Q8 u8 h9 P% w. R
  450.        // 修改中断门9 A( H8 v5 f2 t# b; D/ g* `
  451.        SIDT FWORD PTR btIDTR1
    , ]: g% y% G# Q  D
  452.        MOV EAX, DWORD PTR btIDTR1 + 02h
      P) _1 Y# t/ s% M2 U- Y$ F
  453.        ADD EAX, nHookExceptionNo * 08h + 04h8 V9 X! C; R8 {9 D
  454.        CLI. N9 {9 X( \1 o

  455. * f1 `6 P3 i5 s% }  R1 W& E
  456.        // 保存原异常处理例程入口
    5 \6 ?. S! I" |% B) \8 V
  457.        MOV ECX, DWORD PTR [EAX]
    ' B3 N. z2 M+ Z/ |/ m. k& p
  458.        MOV CX, WORD PTR [EAX-04h]" Z6 S4 ]( }# E/ ~2 r% d  h" f" |* }
  459.        MOV dwOldExceptionHook, ECX# x, F  [! I& r  v* F# j8 ?
  460. 8 m( R; s2 a+ K" f$ Z
  461.        // 指定新入口; M, I) G. u6 ?4 e" O8 @6 ~
  462.        LEA EBX, Ring0Proc- n) b, h0 G# v  g  I6 S, P" ~
  463.        MOV WORD PTR [EAX-04h],BX7 D& T7 p3 `/ C2 Z& M; t/ Z
  464.        SHR EBX, 10h$ ^& P3 @* ]4 c4 {& D/ q; i
  465.        MOV WORD PTR[EAX+02h], BX0 W1 G6 e$ s( H8 t( ~- ?- ^
  466. 8 l( O4 D* P4 t- [3 _: K
  467.        // 激活Ring0代码" p5 ]7 y% _, A& s3 |9 r
  468.        INT nHookExceptionNo
    9 L5 }# z0 P. w3 t0 o9 y: d& j
  469. $ q! h3 j# ~& N/ |2 i
  470.        // 复原入口
    * Q. O( v1 [1 v
  471.        MOV ECX,dwOldExceptionHook
    5 ^5 k# C: e% B6 ]& x
  472.        MOV WORD PTR[EAX-04h], CX
    3 A# f% Z/ D$ B. V  V" G
  473.        SHR ECX,10h" L9 p8 H  W! V! U/ n0 l
  474.        MOV WORD PTR[EAX+02h], CX
    ( M4 u4 R/ ~- e8 v. d* N0 x8 \
  475.        STI
    9 ]" u- b' Z% ]5 |; z
  476.    }( g: G2 R6 S" ], n" {& n
  477.    if(!bIsFirst)
    ! S& g7 Y5 d* H& @" f
  478.    {- v" W; ]6 }% ^0 s& G, O/ Y
  479.        bIsIDEExist  = (bool)btIsIDEExist;2 a3 v& `) A, t+ Q3 g; e8 o0 R) U/ M
  480.        bIsDiskExist = (bool)btIsDiskExist;0 E/ u' _& R7 {. h. a  R% b; {
  481.        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
    $ Y. j+ F; P( ~, u1 {
  482.    }" j5 U: _$ j: D
  483. }3 z  @: `: T9 `& i4 g, n6 r. @
  484. //---------------------------------------------------------------------------( a. ~& G9 a' {0 U& d
  485. // 调用方法:
    * ?( z7 \; ]6 I
  486. void __fastcall TForm1::Button1Click(TObject *Sender)
    9 z% U3 O- W+ n
  487. {
      M$ P+ o- K; }- F& {/ w2 i- T8 U
  488.    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
    : U9 l+ \9 D: n2 p# W/ l$ K" b
  489. }
复制代码
发表于 2005-8-15 01:00:45 | 显示全部楼层
晕乎乎。。。怎么看8 洞阿
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-8-13 23:50 , Processed in 0.019550 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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