找回密码
 注册
查看: 5203|回复: 1

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

[复制链接]
发表于 2005-8-11 11:42:04 | 显示全部楼层 |阅读模式
  1. #include <WinIOCtl.h>
    ; c) H' s* p  q* d2 ^
  2. #include <stdio.h>
    ( P9 L3 x- T) ]8 X2 w6 M
  3. 1 w# @# R" P3 S& ], |
  4. #pragma inline
    , G2 [0 ]3 i- X) V' s) u. J0 R
  5. //---------------------------------------------------------------------------
    5 h" S; h" s+ [" [7 g" w& b
  6. // IDE NT/2000/XP专用变量( R0 J, n- b8 J+ X2 P) o3 J
  7. #define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
    , q' m- \; M& |: d3 k8 ~$ {& h1 l
  8. #define DFP_GET_VERSION         SMART_GET_VERSION
    7 k. D+ e# ^# J8 ?
  9. #define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
    5 t+ R3 g  q9 d& B/ P/ k  n) {" K
  10. #define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA0 t2 |7 O, ?6 B/ R" b, Z
  11. 2 e+ t5 `0 k0 k2 p: U7 B0 y7 }
  12. const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令  y: K% l/ Z+ y& i6 B( [- \3 i
  13. const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令  k$ X7 M6 b; f; a  B- c
  14. ) G# E: ]% b/ J- h( c$ Z
  15. const int MAX_IDE_DRIVES = 4;
    0 U# c% b. i/ L, b0 H! l+ Y

  16. & `: M7 J% s' V5 o6 u. X% J% |
  17. // SCSI专用变量2 n4 Q+ ^1 Y, J  r
  18. const DWORD FILE_DEVICE_SCSI             = 0x0000001B;
    1 }+ Z- V3 Y$ g, r' |- p% ^2 I' \
  19. const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);( y4 o& }6 K: }( O2 e
  20. const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
    # ?* D9 L  _3 A+ @$ x5 G! o
  21. const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
    + Z5 D# l4 I/ X/ H+ B

  22. 3 K4 i1 T, g; \$ h* p, M
  23. typedef struct _SRB_IO_CONTROL
    9 i  y, a. j+ O$ L8 H' \( Y
  24. {
    " l0 B  J3 W. F) X
  25.    ULONG HeaderLength;
    / t( J6 [4 J. @
  26.    UCHAR Signature[8];
    3 r/ b6 |- _, V  g0 T2 m/ P
  27.    ULONG Timeout;
    3 J) z" K" J" x. l$ p7 E' a! f
  28.    ULONG ControlCode;
      i$ d4 y' R- Y5 p9 \/ X1 u8 E5 l
  29.    ULONG ReturnCode;$ G8 S7 N* J. J5 F" C: r9 k- G
  30.    ULONG Length;
    + L1 C: i3 {6 [# Z* w3 F
  31. }SRB_IO_CONTROL, *PSRB_IO_CONTROL;
    2 Q' h2 Z( n! V+ t6 b) h/ ?
  32. ! `# ~* h1 g3 K* X3 X4 g
  33. // 读取的主函数2 Y+ A4 y4 I) l; ]$ T
  34. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
    . j: `& X/ `9 k# Z1 B) a6 \

  35. " m8 C5 Z+ b& f+ w5 Z
  36. // 辅助函数+ F5 B- e& g$ i7 ]9 @8 B
  37. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);6 W3 r7 ?: F6 p& U
  38. // NT/2000/XP函数
      Z( G2 X, ]$ B: V% k
  39. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);& l7 G% W: }) o, p8 ^, b
  40. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
    * K+ l2 r. k1 j$ J0 ~
  41.        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,0 S' c; W1 B+ E; I8 O: w/ N5 ?
  42.        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);2 t% y+ ~! Z* J* B) _( h
  43. // Windows 9X函数
    ( i% v. ~! k! T2 }9 O/ s% p( j
  44. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);8 R$ H* J7 c' g  ?3 {
  45. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
    1 X; X6 g9 O" m- \: w; d
  46.        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
    1 r6 d6 t- v* p

  47. . _* a3 X  R( U
  48. // SCSI读取函数(for NT/2000/XP)
    9 c, J; E( {8 O( f
  49. String __fastcall ReadIDEDriveAsScsiDriveOnNT();
    2 S/ v5 K8 c2 ?  n7 o" e
  50. //---------------------------------------------------------------------------
    & M! R8 k- q. i: k$ n
  51. // ReadPhysicalDrive" o/ `5 N1 H5 Z) e& i3 F' A2 V% X
  52. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
    $ h) R: y- ~# Q% a9 g3 n
  53. {# P6 k6 y  a; J8 g3 i3 S, O
  54.    switch(Win32Platform)
    # c5 w$ p8 x$ n- n3 r
  55.    {
    " U- g2 f5 _% N8 s0 z! r+ L  |
  56.        case VER_PLATFORM_WIN32_WINDOWS:
    / d, |" h. u3 S4 X* M
  57.            ReadPhysicalDriveOnW9X(pSerList, pModeList);, F* a" `4 i9 o$ n2 F
  58.            break;% q$ }8 P3 d& J# F" m
  59.        case VER_PLATFORM_WIN32_NT:
    * n. \: H# B  t' |8 z6 t7 R
  60.            ReadPhysicalDriveOnNT(pSerList, pModeList);
    ; Q) h- n% D' K* c  s; O) p7 U! r
  61.            break;
    0 U" L" M! I' C0 h+ Z$ w# }
  62.        default:
    " n8 O8 f. C0 s% I* Z! }7 Y
  63.            break;
    1 f: l. r" f5 M/ J
  64.    }
    $ M4 M* R: q+ c1 l% A7 V
  65. }0 W4 ]( z% X5 x) T( n3 o( J0 W
  66. //---------------------------------------------------------------------------
    , }4 G9 k/ @' I" S, d
  67. // ConvertToString
    % d4 v# d$ M& V
  68. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
    7 G  m$ {0 L% F$ w6 q/ D
  69. {. d9 X7 J+ }! f7 a( ]& C
  70.    static char szResBuf[1024];
    2 f5 o& {) X  |
  71.    int nIndex = 0;5 G* g; b* S! H! Y% o$ W% }. q
  72.    int nPosition = 0;
    ! y; l% L% m: R" [! y2 Q8 L  r

  73. 6 G; u& k- [. ?
  74.    // Each integer has two characters stored in it backwards
    9 Q: |* Z# Z+ t8 J- d0 t+ t
  75.    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)% ?: u, ]# l7 f
  76.    {
    4 @* @3 x: G2 T1 q- E
  77.        // Get high BYTE for 1st character
    9 V0 Y8 o, P2 w$ |
  78.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);" i2 l: I4 G5 O9 _
  79.        nPosition++;
    $ D- }' f; j' P5 C

  80. ( m/ h' j( {8 ~9 v  S
  81.        // Get low BYTE for 2nd character
      _; `. O% |& v1 `
  82.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);0 v6 @1 a/ z+ A# K# W& ^& ]
  83.        nPosition++;
    ' p3 O4 z+ E) x7 @0 t! ]) u
  84.    }
    . G7 |/ S0 K; M; D
  85. , l! h1 g' Q9 V. w
  86.    // End the string  I- l* J5 N/ g  a& N+ c
  87.    szResBuf[nPosition] = '\0';
    2 r2 F1 |' D& M! n/ v
  88. % \  ^, x8 ^0 y2 P) e0 e6 v
  89.    // Cut off the trailing blanks
    # Q" i: ^# r3 g2 g; s' \4 n: C; X
  90.    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)" r8 {7 x2 r1 m7 j
  91.        szResBuf[nIndex] = '\0';* ~8 F, z: }% V

  92. 3 |" W4 a; \- P; \0 v2 W7 g
  93.    return szResBuf;
    + L- e% p" Z5 b" e% Y
  94. }0 v) a, `1 t  X5 [# U' ]
  95. //---------------------------------------------------------------------------. R# ?  H, A5 f
  96. // Winndows NT4/2000/XP 代码- a6 D2 Z6 h4 G7 c1 T
  97. //---------------------------------------------------------------------------
    7 u7 [3 F  F  S$ H# ^
  98. // ReadPhysicalDriveOnNT
    , ~0 v0 M; O# R- G2 P9 |8 j
  99. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
    $ J+ h# d3 b% h& K- B, s: `7 F
  100. {
      I# a" a" ?; F$ V3 i
  101.    // 输出参数: W$ u' k" Y* Y1 Z9 S6 p# H: E
  102.    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];- X. _" U& F: |* \
  103.   W# ?: t; ]# Q: c2 b9 c& n7 s6 i
  104.    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
    + K  A& f, f2 A* d6 N
  105.    {
    2 ]( P, N9 l+ T
  106.        HANDLE hPhysicalDriveIOCTL;! h- i3 V  [" {, K( ]1 Z
  107.        char szDriveName[32];
    0 M) Y% n; O1 s5 L/ s; q
  108. 1 m( S; y# v* h0 A, q& H2 n
  109.        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);2 d; B. h+ }% T( U; @! g
  110.        hPhysicalDriveIOCTL = CreateFile(szDriveName,, X8 C" C5 I1 z, S. M
  111.                        GENERIC_READ | GENERIC_WRITE," b$ ~, A3 z6 M2 ~( p# J* J$ {
  112.                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,0 p; w- D7 k) K* H* V- }2 z2 h8 z
  113.                        OPEN_EXISTING, 0, NULL);! I+ o8 D) A7 S$ a4 y
  114. ! c8 ^& E' z' |3 O( n" D5 n3 u( R- a
  115.        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)0 d# P: U( F8 t+ b4 |: Q
  116.        {
    & T+ ~; L! x+ E8 o% y
  117.            DWORD dwBytesReturned = 0;8 r3 Z! ?2 V, Z7 u/ C# g8 H
  118.            GETVERSIONOUTPARAMS gvopVersionParams;; K  [: E" W* w; J% F. ^

  119. $ g. g# M! Y) A( m
  120.            // Get the version, etc of PhysicalDrive IOCTL
    / P/ I# c6 g6 `. C
  121.            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));( f  u. c( _% }

  122. # o1 `* P: g5 n# J
  123.            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
    + O5 ?; U( W2 f$ _
  124.                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),2 T+ U* C+ `' u5 a+ v. q
  125.                    &dwBytesReturned, NULL))
    # {7 \4 F. H7 f; ^$ s6 ]3 j/ w
  126.            {
    . t1 G6 D. j  K/ g$ i1 G
  127.                continue;& T8 p# K0 \  @8 J% Q- d, M, R
  128.            }! @  R  g. b; w' ?; N2 G: G7 a
  129. 4 e$ ?: W2 [8 }7 d% M
  130.            if(gvopVersionParams.bIDEDeviceMap > 0)
    4 b+ w7 }$ T' L! ~' [# p) k( X
  131.            {
    + [* R2 ~4 u8 N* I, `2 `* O  ~
  132.                // IDE or ATAPI IDENTIFY cmd* H8 W* ^0 Q( r7 X% l. n( t% u
  133.                BYTE btIDCmd = 0;& W# H5 ]6 _8 e/ z& L  P
  134.                SENDCMDINPARAMS InParams;1 ~- }9 l, G) p
  135.                // Now, get the ID sector for all IDE devices in the system.; {) V  J: M4 T6 M( A
  136.                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,! F: U% q' J+ z5 H1 e
  137.                // otherwise use the IDE_ATA_IDENTIFY command
    1 x9 V/ m8 S: Z7 A- v3 g
  138.                // 具体所得结果请参考头文件中的说明: _: e7 W/ C1 j) K1 ^  l4 \) E
  139.                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
    4 m! F4 |% D! {3 p% |% \
  140.                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;3 y+ U6 }6 @3 `6 q9 }
  141.                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));3 P$ [( p6 I3 |, O( t; S
  142.                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
    + o$ f/ a5 m/ U$ W

  143. : ]" _8 V- ?" ]
  144.                if(DoIdentify(hPhysicalDriveIOCTL,7 x5 z$ S( |, P5 J( E
  145.                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
    % ^' F6 W' s1 f9 ?6 \
  146.                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
    8 d+ p, V4 \' g! o/ G& a$ v
  147.                {( _5 u8 ?# E; k- o( i
  148.                    DWORD dwDiskData[256];$ k5 b  e0 Z. n" \! |
  149.                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
    % r0 Z' J9 m; r5 ^" o0 a7 q
  150.                    char szSerialNumber[21];
    : r, `) Q1 F/ ~
  151.                    char szModelNumber[41];
    5 S- J! I5 f1 C: R
  152. 0 ]% G/ R' T- m" I: o
  153.                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
    ! t6 X& q9 P' \/ C/ T
  154.                    for(int i=0; i < 256; i++)- u* V5 p  T7 B/ F3 _1 g
  155.                        dwDiskData = pIDSector;2 d( I7 x3 r8 F4 {5 n# @
  156.                    // 取系列号  Y/ c# i9 F* S5 V. k7 [
  157.                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
    * |, X5 |0 ?) |7 W) i. a5 J
  158.                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
    ; Z% x$ Q* f( z) Z$ `. M

  159. 5 P2 w' y; C) S
  160.                    // 取模型号
    ; V4 l5 i& C) x, h( m& _* S* P2 R, a
  161.                    ZeroMemory(szModelNumber, sizeof(szModelNumber));; R2 e1 ~2 t! w/ Z( O
  162.                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));- E# p  A6 s# v

  163. ; ?. ^  k, T) D. Q
  164.                    pSerList->Add(szSerialNumber);! ~! @/ z; R+ e& i0 Z
  165.                    pModeList->Add(szModelNumber);
    ) b% Y$ @8 N/ b) A/ B, E- n* O6 ~
  166.                }
    ' s* R; _; X2 C# I6 Q" }
  167.            }: h9 l1 j+ i. f/ ~- r4 i! M/ J
  168.            CloseHandle (hPhysicalDriveIOCTL);
    8 M' o6 {: N, `
  169.        }8 L5 T) v7 t3 Z/ n" C- b3 D
  170.    }
    # e, _  V2 B# f3 I2 n' D7 k. H
  171. }: a1 v# ]( E7 S- t0 o
  172. //---------------------------------------------------------------------------7 z6 ]: D5 }/ \( C" B3 J
  173. // DoIdentify
    ( X' ~! ]7 [: ^7 ~4 O, v: s, k; `
  174. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
    ! e9 O2 K$ u9 ~
  175.              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,4 k7 b, D# w5 E+ r7 x
  176.              PDWORD pdwBytesReturned)
    ' q# A, i* ~7 v5 D
  177. {% j& i5 X8 }) Z% n3 ~3 F7 r
  178.    // Set up data structures for IDENTIFY command.
    & A0 q' ?0 q5 A% I8 K! {" t
  179.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
    9 }, {2 I; U" U0 s: J3 a
  180.    pSCIP->irDriveRegs.bFeaturesReg = 0;
      S& {! T6 N! k/ D% V8 U
  181.    pSCIP->irDriveRegs.bSectorCountReg  = 1;
    & n0 A7 f) B: D, I" \% @+ H- }
  182.    pSCIP->irDriveRegs.bSectorNumberReg = 1;
    ! Z2 N3 m- P2 C6 ^0 A
  183.    pSCIP->irDriveRegs.bCylLowReg  = 0;
    $ A" m  l( D+ `. d4 S
  184.    pSCIP->irDriveRegs.bCylHighReg = 0;1 i) T( L+ S- T
  185. / Q5 ?" a: J. ~! y
  186.    // Compute the drive number.(主盘和从盘所对应的值是不一样的)
    3 F: l4 h9 _" |. Q: r2 f! Z
  187.    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;+ H# \0 @) z2 P# l8 L

  188. 2 ?4 d2 T1 F' Q0 n$ h( X
  189.    // The command can either be IDE identify or ATAPI identify.
    : c* k4 B& t" A6 Z! H7 d
  190.    pSCIP->irDriveRegs.bCommandReg = btIDCmd;
    7 R+ `/ f! \7 A' L" _, l
  191.    pSCIP->bDriveNumber = btDriveNum;$ Y* }/ ]6 M6 t) i1 E
  192.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;! j  k3 ?& E  X7 x" T

  193. ( ~* ^8 w6 ^+ z$ v3 R
  194.    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
    5 A7 [2 k1 w: E9 ~3 h
  195.           (LPVOID)pSCIP,2 U7 d2 J, P  c; @$ t7 U/ b
  196.           sizeof(SENDCMDINPARAMS) - 1,$ B8 l, J$ u! L3 N. c+ G
  197.           (LPVOID)pSCOP,
    7 ~) {1 a# c$ f; {' O# J
  198.           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
    $ d0 x6 E" @8 x9 N/ [# B5 `/ G
  199.           pdwBytesReturned, NULL);; _- _0 k8 w6 _
  200. }
    . b3 [& ~0 s# p' N3 a' M
  201. //---------------------------------------------------------------------------. Z' L/ ]& L+ u5 {
  202. // Windows 95/98/ME 代码' P: q( E) e6 Q0 R. @5 \# v, _* k
  203. //---------------------------------------------------------------------------: z: c) b- e; r  ~: V2 m
  204. // ReadPhysicalDriveOnW9X. y* r* D0 U8 _- ], d9 c4 ~
  205. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)9 s7 z2 s5 K; t9 Y8 s8 G: v
  206. {
    4 Q& x# R$ b$ M; b3 Z* r
  207.    WORD wOutData[256];
    : _9 w$ [6 c! J3 u/ a/ ?
  208.    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);! L& y: D( O5 _( ^

  209. " Z0 m+ g0 U, k" m
  210.    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。" n6 ~/ s6 w( A4 C  B' Y0 q
  211.    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以3 D$ \0 `6 V2 w) |7 p2 u
  212.    // 避免蓝屏的出现。(期待高人能指出原因). b  I/ C! H  }7 ]
  213.    for(int nDrive = 0; nDrive < 8; nDrive++); I5 m  \2 A/ d8 Q3 m9 ?
  214.    {. @# z, W) D& M  m' h% f, V
  215.        WORD dwBaseAddress;
    ) C8 u& N) A' U' h+ ]7 e
  216.        BYTE btMasterSlave;         // Master Or Slave
    3 o  ]# v& J. O5 }+ p# ?6 s
  217.        bool bIsIDEExist;
    : r! _& A! D, h& n) e. s5 K
  218.        bool IsDiskExist;
    2 V3 j5 _7 [7 H2 M

  219. - E5 p9 T1 j6 x
  220.        switch(nDrive / 2)
    3 b: T$ ^- V* p
  221.        {3 k5 _7 s5 J# w/ k+ C( I
  222.            case 0: dwBaseAddress = 0x01F0; break;' \2 {  r2 v: G( c1 u) g
  223.            case 1: dwBaseAddress = 0x0170; break;
    5 r9 i; t" k* _; M6 Z+ q
  224.            case 2: dwBaseAddress = 0x01E8; break;( R8 f8 |% M1 ~$ B0 u8 z
  225.            case 3: dwBaseAddress = 0x0168; break;
    3 y- t0 u! G  o
  226.        }
    4 z# B! {2 E3 ~8 r& O& n  |
  227. + m6 M% ]. {& M5 d8 _
  228.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
    $ m3 |! F+ r! o% q$ P
  229. 7 d% s4 v& J* U3 V0 k& N
  230.        // 进入Ring02 Z9 F/ J2 y: q5 Z
  231.        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
    # t# F$ }0 P- r1 g# k! o$ D
  232.                bIsIDEExist, IsDiskExist, wOutData);
    8 f8 J( K7 y" t$ p; D/ T
  233.    }
    $ G- _* S' Z2 }0 Z
  234. ' S4 e, o$ W) Z! s
  235.    // 开始读取6 t2 X8 s, ]/ H$ h7 }' t. O" C
  236.    for(int nDrive = 0; nDrive < 8; nDrive++)
    : u& n9 l$ l" `" o8 ?. ~
  237.    {
    ( k* G. X$ `% C
  238.        WORD dwBaseAddress;9 U/ F9 O7 N' T% I9 v* q  d
  239.        BYTE btMasterSlave;         // Master Or Slave
    # x: ]* n- N+ L9 }5 e9 }( s2 o; q
  240.        bool bIsIDEExist;1 l+ A! A0 |9 x! y/ |
  241.        bool bIsDiskExist;+ ~/ b, j: r& \$ ~8 z( z0 B4 Z( W5 f
  242.        switch(nDrive / 2)
    ! Q$ Q5 `) h2 {, ]
  243.        {
    4 |" g& d( O$ u, W5 q' }- o! `5 f' L
  244.            case 0: dwBaseAddress = 0x01F0; break;4 a: \, m; [1 Q! I0 d# O
  245.            case 1: dwBaseAddress = 0x0170; break;
    + z4 Q+ y8 N3 k4 M/ L& `
  246.            case 2: dwBaseAddress = 0x01E8; break;$ U' Q4 |+ D5 w9 G$ H( e
  247.            case 3: dwBaseAddress = 0x0168; break;8 f1 u. C$ K! m# E2 k! U- z
  248.        }
    0 P- \% q3 l1 N5 |
  249. ' a) n; t+ K5 l/ O! t1 r# h
  250.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
    ; J# C$ M' ?7 R6 @( {9 [
  251. ; Z2 @- U6 P) L+ \  Z
  252.        // 进入Ring0
    ; I& M3 X5 G$ x
  253.        bIsIDEExist  = false;* h. H, W  o5 h1 X
  254.        bIsDiskExist = false;+ B1 `' }  _/ c
  255.        ZeroMemory(wOutData, sizeof(wOutData));
    - L5 m8 P- R( c

  256. + p9 b7 z4 ~# h( u# ?
  257.        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,) @2 l5 m2 ~* y" K5 c, ^
  258.                bIsIDEExist, bIsDiskExist, wOutData);  I  @* C" a( q6 _9 X5 v# p: C) @" P
  259. " i) ?: o, _  y- _, f6 O  e
  260.        if(bIsIDEExist && bIsDiskExist)4 L9 o: }2 l0 c$ [3 X
  261.        {5 R. f' l0 \! f5 s0 t0 K- T
  262.            DWORD dwDiskData[256];
    : O& k3 C: I' _- D0 ?: \) s
  263.            char  szSerialNumber[21];0 i2 {, ?- g. ]' z% n
  264.            char  szModelNumber[41];" R/ H/ k* n2 z( ~# l
  265.   ?+ ^/ Y# I$ W4 Q$ B4 D! P1 h
  266.            for(int k=0; k < 256; k++)- i  R5 e6 q; A. ^
  267.                dwDiskData[k] = wOutData[k];
    " @( {) H1 k" C6 k% V

  268. ' F1 S( d- Y8 f7 P) ]' Y  ~
  269.            // 取系列号
    . ~. z- O9 t0 Y3 j5 m: i
  270.            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
    * E) Q: l+ [' k+ c
  271.            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));* D# M/ \6 q% e" n+ `

  272. ) s9 e2 q/ S1 |- X( o2 k1 a
  273.            // 取模型号
      s3 z+ o( o/ x& y- R
  274.            ZeroMemory(szModelNumber, sizeof(szModelNumber));  Z# k$ F. b- m5 S# p. n; a1 u
  275.            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));' ^7 W$ o  k" [7 O) O3 Y$ ~2 Q5 f

  276.   z' [7 x; `; L% y$ m, O
  277.            pSerList->Add(szSerialNumber);/ L- R$ i6 X5 U$ b& n& d: T
  278.            pModeList->Add(szModelNumber);" k. c* ]+ ^2 {  r) D
  279.        }* B, S' D* H& a* V, J9 Z
  280.    }
    4 }  Q( e# o6 e2 Y' ?  H
  281.    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);: Y( L6 c" a6 i! f6 @% J3 ~3 P' x# `
  282. }
    % {( ]* G0 [) [. s; C2 b; v
  283. //---------------------------------------------------------------------------
    8 d: {1 M! m4 v
  284. // ReadPhysicalDriveOnW9X_Ring0()" `" \2 O' I( ?# k+ z* v9 S9 U; R( Y* Y
  285. //' T) P4 V% v  I) ~
  286. // dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
    $ Z% D# }1 H0 t2 ?5 E1 W0 ^
  287. // btMasterSlave = Master(0xA0) Or Slave(0xB0)
    # K$ R. i1 E* ]
  288. //---------------------------------------------------------------------------
    3 A8 i4 H* ]% j
  289. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
    ) C: E; o1 k% R1 h) F7 c  J: _
  290.        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
    4 K; K* t4 T) P
  291. {
    . I- A* B4 B! ^+ z  J3 i/ g
  292.    BYTE  btIDTR1[6];  p0 S) Z) S. J, T. p
  293.    DWORD dwOldExceptionHook;* Z" e3 {% G* A: l, Q
  294.    const int nHookExceptionNo = 5;
    ' |* D9 D2 e- Z# j7 e8 ^, j% z

  295. 3 x% x0 `: k* L
  296.    BYTE  btIsIDEExist = 0;
      ~9 l. m3 k6 o7 @! g4 I3 {  U
  297.    BYTE  btIsDiskExist = 0;
    ' s7 ~  p* B4 d& l7 R% i2 a
  298.    WORD  wOutDataBuf[256];& `0 V0 C  t& R% C; Q
  299. ( A" [" X( [7 E
  300.    BYTE  btIsFirst = (BYTE)bIsFirst;+ u  K; z% f: b/ u1 `! S% u
  301. ! u: `$ q2 l) a/ H3 w% P4 C# L
  302.    const BYTE btBit00 = 0x01;
    3 s7 H! }, H, P0 n* I
  303.    // const BYTE btBit02 = 0x04;
    5 z7 n" `) U6 q
  304.    const BYTE btBit06 = 0x40;
    . V5 p! f/ s: b( ~4 k' @6 W3 y
  305.    const BYTE btBit07 = 0x80;
    / @0 V( f  {3 x6 y/ q& C0 s
  306.    // const BYTE btERR  = btBit00;
    ( W/ t. B- s' g3 x
  307.    const BYTE btBusy = btBit07;9 u& y1 z& W0 [* O
  308.    const BYTE btAtaCmd   = 0xEC;
    - X* j1 g8 ~1 F" [* d$ t% k
  309.    const BYTE btAtapiCmd = 0xA1;
    - }8 g6 w7 f9 D& V

  310. 5 \7 j% j$ v- m4 d' o$ P2 \  E$ Y1 s
  311.    __asm
    1 A  o+ ]* V+ I* {$ ]: s; r
  312.    {
    ' f& B: D% X7 q1 x2 f3 M7 k! F; a5 c
  313.        // 必须先执行这条语句) U7 x4 w6 D* B  _0 [8 o9 p
  314.        JMP EnterRing0
    % r! L8 b6 z6 G# g1 t, J: \- X
  315. # v' E8 e) T5 Z9 i+ i6 U. q" L
  316.        // 定义过程
    , \2 W6 }1 X" ]3 F. }
  317.        // 等待IDE设备直到其不为忙为止* ~2 C( n! J& h
  318.        WaitWhileBusy proc
    ' P& @  p& O# ~& u* x2 m6 L$ z
  319. + @7 c; ^5 p3 u# M) O
  320.        MOV  EBX, 100000. G0 ?& }+ t8 c" P! U' Y1 Y2 D+ D8 I  F; t- G
  321.        MOV  DX, dwBaseAddress
    - m7 W" c! a- b$ h- s! L: |  P
  322.        ADD  DX, 7
    ; W2 ~4 s7 {. h# P# w
  323. * Y( b2 a. ^9 n" q" _: S( T
  324.        LoopWhileBusy:! R5 E4 d/ q% |9 }
  325. , z. `1 `1 h9 h* m. G, K/ \
  326.        DEC  EBX# ?$ [+ S/ Y- V( C7 u/ _) \
  327.        CMP  EBX, 0, J1 T8 i" C3 n
  328.        JZ   Timeout
    $ ?5 s; \* p; l2 H
  329.        in   AL, DX
    1 ^$ {3 Z; H, [# {
  330.        TEST AL, btBusy
    ( L5 T* c0 [; e0 W  v; ]
  331.        JNZ  LoopWhileBusy
    6 B9 R9 m1 f+ i! S
  332.        JMP  DriveReady' h+ C( |1 e$ T1 N, O
  333. # |% F# F& z, D% `
  334.        // 超时,直接退出
    ' p: X( b0 `* x
  335.        Timeout:
    3 j! O* g$ S- K! w8 b; ?! [" ~
  336.        JMP  LeaveRing0
    5 ]3 k9 T; P4 |* J. C: C
  337.        DriveReady:# E6 Q* T. [5 f) D
  338.        RET4 d8 n4 g8 d9 L, W7 t4 ?
  339.        ENDP   // End of WaitWhileBusy Procedure  L7 E" C% D5 A5 |9 e

  340. % ~6 n7 }& f# a3 X1 b( h2 m
  341.        // 设置主盘和从盘标志
    + N& h/ Y1 o# L  i# Y
  342.        SelectDevice proc
    / T6 L2 l- U& k% L6 x
  343. , D1 D8 ]$ C2 u- o
  344.        MOV  DX, dwBaseAddress8 N* l% C* ]  M' _. h. I
  345.        ADD  DX, 6
    " S* I( q' W6 l) _
  346.        MOV  AL, btMasterSlave
    0 i7 r3 \9 u, p9 @9 u7 Y
  347. 8 v  @- \2 n7 T
  348.        out  DX, AL
    5 V# t# \) \$ {
  349.        RET
    : f7 @& t! V$ u( Q3 D3 ~
  350. # S# v" j# ?0 Y% v0 s3 I* z3 X
  351.        ENDP  // End of SelectDevice Procedure
    + M: c9 r# N5 ^3 y' I$ }& O6 k

  352. " j  O1 p2 _3 C: f& q1 F/ I& Y
  353.        // 向IDE设备发送存取指令: {+ o* v5 q1 p7 v2 I9 r* f2 Y
  354.        SendCmd proc
    , C& _( y1 S0 t

  355. + H$ @  e( G1 T1 H; `. z3 U" Z" C
  356.        MOV DX, dwBaseAddress# C2 }# c2 M4 y5 M; q: m
  357.        ADD DX, 7
    + B% f. X% l/ S+ Y1 k, X& y
  358.        MOV AL, BL // BL是主从盘标识,在过程外设置
    " E) F- V; U2 m6 v/ g+ B
  359.        out DX, AL$ Y: o/ N7 ~9 d" \! L4 D
  360.        RET9 y, c* Y/ _3 a7 K# G6 n) h
  361.        ENDP  // End of SendCmd Procedure
    - R! ]* e/ b% U7 ]* s

  362. * e0 Y6 t  J( f# k
  363.        // Ring0代码( L/ [' }; O  o1 ?! e* {( w8 E
  364.        Ring0Proc:2 L' c+ W% H6 v
  365.        PUSHAD( _8 q( }2 `( e4 v
  366.        // 查询IDE设备是否存在1 S: N# o! z& B" f3 }
  367.        MOV DX, dwBaseAddress3 P2 U4 `: \- u: W/ A& u* m5 X6 ]
  368.        ADD DX, 7
    $ }  c8 M, O5 o/ c. K
  369.        in  AL,DX$ w' ]( D( P2 v
  370. ; Y; t( @5 ?% _+ ~  P# ^& c) J
  371.        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回8 \' w2 s% M& f9 x
  372.        CMP AL,0xFF
    9 x& V- P: N/ T8 w2 }7 o
  373.        JZ  LeaveRing0
    : D! u: r  y% E1 j  a
  374.        CMP AL, 0x7F
    $ \5 X/ B) B" W5 X
  375.        JZ  LeaveRing0$ g7 O7 w" U8 w9 O4 q! ^

  376. 9 t$ M4 K% |+ h& a7 [
  377.        // 设置IDE设备存在标志5 y3 _& V" K& O1 R
  378.        MOV btIsIDEExist, 16 j  K, z5 n5 b* D8 n. H& B+ C

  379. % c' O) K- S; w
  380.        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面). L  r+ y# @! m
  381.        CALL WaitWhileBusy5 b# K, u, [3 X+ p7 d# n
  382.        CALL SelectDevice
    ) f5 b0 K! k* v1 c1 \: h1 K* E
  383. * S/ D. s9 Q; H* ^4 u+ ]0 K
  384.        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏% A6 a+ i7 s, c4 d' Q: F8 u% X
  385.        CMP  btIsFirst, 1# r. |3 p- H( d$ F
  386.        JZ   LeaveRing0
    ( Q& h( {: B1 f# q; K; I2 p' Y

  387. & D/ U7 ~6 n4 P$ V
  388.        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
    % }  K( t6 u3 L. W: e
  389.        CALL WaitWhileBusy
    ( _" [; P! @) e3 x  Y

  390. 9 u7 U# x1 j. ]+ v7 |
  391.        // AL的值等于cBit06时,不存在驱动器,直接返回. e0 O# y. P/ d& K5 O7 B6 Q/ F
  392.        TEST AL, btBit06
    * {" P7 Y) [5 G/ _- U2 `6 H
  393.        JZ   LeaveRing0
    * D* H" E/ P2 w( K0 b$ n  h

  394. $ u' h3 ~* m$ j) [1 C) f. e; D
  395.        // 设置驱动器存在标志
    7 l8 x6 P& h/ ]$ e% c
  396.        MOV  btIsDiskExist, 1
    + ?4 h- N% b: Q
  397. % L# w5 Y$ W) _! ^9 f* F# D
  398.        // 发送存取端口命令0 f0 n# \& [  t! J: r
  399.        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,: W/ v9 F& b( W3 \# V3 m- x* T
  400.        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
    8 T* a. X3 E0 K, `* i; a
  401.        CALL WaitWhileBusy/ V( @4 {9 n( b
  402.        CALL SelectDevice    // 设置主从盘标识
    ! B. E3 s" q6 B" @3 P
  403.        MOV  BL, btAtaCmd      // 发送读取命令3 }2 [; P' ]: [
  404.        CALL SendCmd
    0 j5 L' z! h  `2 u/ o6 q
  405.        CALL WaitWhileBusy3 L0 r) A& ?: }
  406. 0 o+ o+ r+ R* z5 f1 N' Y
  407.        // 检查是否出错  X6 Y7 }2 ^3 ^+ D
  408.        MOV  DX, dwBaseAddress' p# E& d; G* v4 F4 X
  409.        ADD  DX, 7
    + }* _& U; }+ E5 Z- s( t

  410. 7 _) j$ n4 f5 }' ]" A: V: X' t
  411.        in   AL, DX
    + Z7 q6 w0 v5 ]9 d* |
  412. : `' b: S. F2 R+ Y
  413.        TEST AL, btBit00
    + q1 n1 h; x5 V2 f/ X* |
  414.        JZ   RetrieveInfo   // 没有错误时则读数据
    3 _, b0 _' y, V: D+ J; x" L) P
  415. : c8 @0 b# N3 i! d  E0 ~
  416.        // 如果出错,则进一步尝试使用ATAPI设备命令6 U6 h' w& p' r7 u& A
  417.        CALL WaitWhileBusy: I- [# H* `- ?0 K) C2 h( o( _
  418.        CALL SelectDevice
    9 O  T/ h3 ^$ r  ]. V, V# ^
  419.        MOV  BL, btAtapiCmd
    + k& f( \- `8 c) I
  420.        CALL SendCmd* ^+ a5 G- q1 D- F
  421.        CALL WaitWhileBusy
    $ b" |6 t* s5 ]8 x* v

  422. / U- }. O+ c+ Z* u  h% Z
  423.        // 检查是否还出错) i/ ^: Z+ D4 s- r  ^
  424.        MOV  DX, dwBaseAddress
    6 M1 W9 D: P3 G, f9 K
  425.        ADD  DX, 7
    " @0 t/ H. J9 Z# P
  426.        in   AL, DX& f1 I+ Y! M. ~- c2 J
  427.        TEST AL, btBit00' y0 c. B4 ~$ w+ Y" @
  428.        JZ   RetrieveInfo   // 没有错误时则读数据) ]% f' K( d8 C' w6 B- R
  429.        JMP  LeaveRing0     // 如果还是出错,直接返回
    0 h3 ?( N3 S1 l  M0 x
  430. 7 n+ W# W( J$ ?0 o$ v
  431.        // 读取数据
    7 z) [9 p5 u- w8 W2 n- I
  432.        RetrieveInfo:
    3 r8 F; j. p9 e. s5 X) l
  433. , c$ B7 Y9 g- Z$ b/ V- L' \: s4 {4 D
  434.        LEA  EDI, wOutDataBuf
    2 T* g8 P% R, Q4 r
  435.        MOV  ECX, 2568 n# A8 [2 v7 h3 V; h
  436.        MOV  DX, dwBaseAddress* P9 W; u, n1 }; T- z
  437.        CLD
    ' O2 y! _( o! I# w0 Q; E
  438. 4 |8 m# ^2 G6 w3 L- m
  439.        REP  INSW
    9 i# w) K/ J5 n% N- Y

  440. - N+ L1 @0 b: `; o% ~& a
  441.        // 退出Ring0代码, N- ?* t) C1 D0 a: f
  442.        LeaveRing0:' o, P1 f" H- U- f8 ~- h
  443. 9 k2 m+ f- y: A3 l' R$ h& w$ h
  444.        POPAD& u7 E  e* ]9 Q) X% b6 f/ T
  445.        IRETD
    1 K4 M! l7 u3 d4 e# |
  446.   I' w  G- ]# \& `' r2 p
  447.        // 激活Ring0代码* J& M- A7 V' R2 o% ?& [5 r" _7 q
  448.        EnterRing0:
    2 H. c9 r$ r' v; `$ x4 E

  449. ) }$ \3 u* K7 ?; t( |/ \( c
  450.        // 修改中断门  i9 N. J6 v3 W$ i- b8 o/ Q
  451.        SIDT FWORD PTR btIDTR18 V3 Y$ y* L: m4 q) ^
  452.        MOV EAX, DWORD PTR btIDTR1 + 02h
    + L, C2 k" s0 t' ?. J) w
  453.        ADD EAX, nHookExceptionNo * 08h + 04h
    + e1 l# g. K+ }3 d+ z4 V, U
  454.        CLI/ I+ v: g, J0 A/ i$ M% q# \6 t
  455. 6 F, t; n" Y' X% g' J+ i
  456.        // 保存原异常处理例程入口
    : V4 f" `: P! v- H
  457.        MOV ECX, DWORD PTR [EAX]+ Y; ~/ V$ A2 A- d: y4 W' o
  458.        MOV CX, WORD PTR [EAX-04h]
    . P! G- }$ N0 u$ e' o
  459.        MOV dwOldExceptionHook, ECX
    " |) a! k- @4 L/ F3 F$ O5 ]: y
  460. ; W2 m. `! q+ ]" }
  461.        // 指定新入口) }3 f2 X& U; Q2 R1 b3 E
  462.        LEA EBX, Ring0Proc* l, |  ~/ ?! N) Z
  463.        MOV WORD PTR [EAX-04h],BX, N0 I+ I4 I# y- Y7 N
  464.        SHR EBX, 10h
    ! i4 |* W, P3 @0 n* S& h* X) M
  465.        MOV WORD PTR[EAX+02h], BX1 j+ ?# c! Q0 ?8 d/ |

  466. . ~, E) `/ |* t" I/ z- `
  467.        // 激活Ring0代码
    : t5 r3 X( z* v8 |$ m
  468.        INT nHookExceptionNo( g8 J, c- o; A5 m

  469. 6 m5 m' L0 m, V6 E; `
  470.        // 复原入口
    ' d7 x; N' y; G. m
  471.        MOV ECX,dwOldExceptionHook0 L. ?- r7 u" F! n. |" f  H8 g
  472.        MOV WORD PTR[EAX-04h], CX
      a, a1 j1 ~% c+ z( f, }  L* Z* V
  473.        SHR ECX,10h
    ' J- w) I# o9 C
  474.        MOV WORD PTR[EAX+02h], CX( v/ _) v: W. [6 p
  475.        STI6 A) R; p7 n+ u8 `2 N4 r
  476.    }
    : x2 h% `4 W, s- |* Z
  477.    if(!bIsFirst)6 t+ \4 A! z% f) ^. n
  478.    {* a' J7 N  f; ~5 r5 \/ O
  479.        bIsIDEExist  = (bool)btIsIDEExist;$ y9 @9 p" w( ^* j! I2 ^, b8 M5 h
  480.        bIsDiskExist = (bool)btIsDiskExist;) Q/ E7 \, l' ~8 {8 W
  481.        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
    6 b1 i: I$ s" w; v' _
  482.    }
    ; S5 ^2 N7 p& ]# X$ Z
  483. }
    # a4 e! ~" X/ d6 P) l7 i
  484. //---------------------------------------------------------------------------
    : F4 m: ]% M# {9 k. r8 p: c. V
  485. // 调用方法:" e& ]9 v2 b5 ^7 X  {
  486. void __fastcall TForm1::Button1Click(TObject *Sender)' R5 o: B$ g+ K0 [# V% j$ {
  487. {
    " v  @, V+ h% `" u3 |5 }
  488.    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);( h. R6 R9 u+ e
  489. }
复制代码
发表于 2005-8-15 01:00:45 | 显示全部楼层
晕乎乎。。。怎么看8 洞阿
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-10-1 20:48 , Processed in 0.021863 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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