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

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

[复制链接]
发表于 2005-8-11 11:42:04 | 显示全部楼层 |阅读模式
  1. #include <WinIOCtl.h>2 G# b! d+ ^; k
  2. #include <stdio.h>" p7 ^/ k% z6 T: a; k: W( Y' A
  3. $ _& A+ o8 ~+ h! _7 L* D
  4. #pragma inline
    ' t: A8 G$ \6 \" ~4 U) s
  5. //---------------------------------------------------------------------------
    : e0 w, O+ ?" \8 Z( W
  6. // IDE NT/2000/XP专用变量
    8 a; h. u: n8 O; g9 V
  7. #define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
    / p# H* B4 I4 f" K9 P
  8. #define DFP_GET_VERSION         SMART_GET_VERSION* l+ H' m, w* |. c7 o1 \# K2 w
  9. #define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND  L2 y% W- y$ ^: l7 w; v* G( o2 j' J
  10. #define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA; {0 M6 k, R! O& s+ k

  11. " F. ^. Q, p2 t- |. s
  12. const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令
    & R6 k' ^# [% H, ?' c9 P3 ]" ^- ~' J
  13. const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令( b1 J: E. |; E/ X. b
  14. ' m3 \, l. Z1 m% @. t3 J* A
  15. const int MAX_IDE_DRIVES = 4;1 [- j. h, e- B4 o+ D- g& O9 R

  16. 4 l! w7 @, r" U' Q- J" p
  17. // SCSI专用变量" M' h: U& _# [/ f
  18. const DWORD FILE_DEVICE_SCSI             = 0x0000001B;- c4 k" T, R2 z
  19. const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);3 @) S1 e* u  r
  20. const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition) ?. \* n( \- W! x: V
  21. const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
    , z) \: ]' d3 R. h8 X8 |
  22. ( ^' t/ ~  k# U' J
  23. typedef struct _SRB_IO_CONTROL
    ! y$ R' |  s; `0 g
  24. {
    $ D/ Y$ `' F# r2 B# W+ y$ a
  25.    ULONG HeaderLength;
    9 j3 `+ J; X: [4 ?; v" R! h4 j
  26.    UCHAR Signature[8];
    0 E7 A. M' A9 F4 I5 @5 J( ~0 o' w' H
  27.    ULONG Timeout;
    ' H) Y% F/ S* C
  28.    ULONG ControlCode;  B) P5 S% W9 X! d. E
  29.    ULONG ReturnCode;
    * @. y( ~1 q, c$ `
  30.    ULONG Length;: Q) I- v3 i0 f
  31. }SRB_IO_CONTROL, *PSRB_IO_CONTROL;
    ' @) n8 k) Y" O8 A9 w$ K$ t$ F

  32. 3 R) j- Q% A8 n
  33. // 读取的主函数8 i5 L$ c1 f" u5 W
  34. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
    * e7 V* T! x$ Q7 p  D+ U4 c

  35. 0 q9 z5 O6 p0 j  b9 ]0 `( }
  36. // 辅助函数, V/ u9 ?  `$ T) ]" s- P3 h3 h( b
  37. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
    ; \0 w- W4 U3 M: B& x- s
  38. // NT/2000/XP函数
    4 t7 |4 [) f) e* C- X1 [: m7 \
  39. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);$ m$ F7 a6 {7 c6 B, v
  40. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,3 Q* S& K0 u# t1 K% `/ ^
  41.        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
    $ i. L6 i& N- E) @3 L0 T- G
  42.        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);' b# q7 G; y# K7 n& F( _7 m6 b
  43. // Windows 9X函数
    ( H1 m0 x6 m5 v3 F; j' r/ W5 g
  44. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);
    ) i. S; U! {2 |, H$ v
  45. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,* ]- \. |. |) x0 r1 r7 ^
  46.        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);5 \! V& E0 ~% t

  47. ) m; c9 X$ y! [- l' P* f" L4 z7 ~
  48. // SCSI读取函数(for NT/2000/XP)  c$ K* X+ @9 d0 w& a
  49. String __fastcall ReadIDEDriveAsScsiDriveOnNT();
    3 P) N8 P) v. ~
  50. //---------------------------------------------------------------------------% f) p* z- D8 z# B
  51. // ReadPhysicalDrive
    * M3 W: V) E. L: _' v& ]. f
  52. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
    ( {" m' u+ Z5 e; H. g
  53. {. H2 m( W$ K; Q- M( m
  54.    switch(Win32Platform)" u! d6 h! V; D- O) Z* O
  55.    {
    9 ^/ t  D# _: p& w
  56.        case VER_PLATFORM_WIN32_WINDOWS:, A/ ^2 ^& Q3 D  F% j/ T, n1 I  Y
  57.            ReadPhysicalDriveOnW9X(pSerList, pModeList);* |5 ^$ ]7 Z5 R8 ^' F, k
  58.            break;
    & L9 A- J. \/ V# m2 m$ X
  59.        case VER_PLATFORM_WIN32_NT:
      ?' q4 J4 A! v/ m9 \$ h
  60.            ReadPhysicalDriveOnNT(pSerList, pModeList);' h9 G0 x2 m6 i- b7 w; f
  61.            break;
    2 _7 u: H$ z7 g6 o0 b
  62.        default:
    & O, a" U; p' q- x  r: E
  63.            break;
    9 ^* K* p) k4 r* ^7 u) O6 ^
  64.    }2 D' ]# g. a  F7 @( |# b
  65. }- a/ W2 x# Y1 f+ K9 ^! o2 _
  66. //---------------------------------------------------------------------------( |& Y  P) Y: T3 h
  67. // ConvertToString
    & }+ K! P- g# Q6 Z
  68. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex): R+ q  `- M" k! Z# {
  69. {% @( R" T% g. d' t' {! ^; J$ b
  70.    static char szResBuf[1024];
    ; j) O. @8 k/ j5 ?; g. U4 g
  71.    int nIndex = 0;. x; l0 p& K+ `8 ~& o- W
  72.    int nPosition = 0;; [+ E& t3 v1 c' t
  73. % H% z4 \7 {& @/ U+ y
  74.    // Each integer has two characters stored in it backwards8 Q, x7 U! [8 F+ g- f
  75.    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++), |6 Q$ P9 B  f8 M) s9 ~' c* x
  76.    {; W  g- ?6 f, ?
  77.        // Get high BYTE for 1st character
    5 V9 z9 A+ N4 o9 T+ a+ @
  78.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);$ ~; K! a' d2 x& g3 W/ V% A4 n3 |
  79.        nPosition++;
    4 S" d$ p" z9 L0 f

  80. ( L/ o! i' L, ^& e9 @. I
  81.        // Get low BYTE for 2nd character( c0 x8 Z# x. M# o: k! k
  82.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);# y4 i  u+ Y  u7 b( g: K9 x
  83.        nPosition++;
    8 ~7 T* i  i9 h' I# e7 M
  84.    }9 i8 X0 [+ S7 ?# I
  85. / @# o: R2 v! J0 v/ f: z; S
  86.    // End the string" n' W& `% ~& p0 }6 H$ W  }
  87.    szResBuf[nPosition] = '\0';
    " b, J! {$ ]/ ?2 p) `/ C/ v

  88. / ?1 G% c7 K, f, K: X3 m( \
  89.    // Cut off the trailing blanks
    " C. J! E1 G1 k
  90.    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)+ B/ ]4 v0 j3 g  _5 H! e1 m2 x
  91.        szResBuf[nIndex] = '\0';, t; o5 P0 c1 ?1 v0 L1 b

  92.   q5 l% e/ ]. E. d
  93.    return szResBuf;
    ; n# z  s2 t* O0 F  i1 d
  94. }2 s6 d# U; p. F8 B3 v
  95. //---------------------------------------------------------------------------
      S7 z2 F  g+ ?6 M( L4 Z: o( b
  96. // Winndows NT4/2000/XP 代码9 ]7 J4 Y" ^; a1 ?
  97. //---------------------------------------------------------------------------
    # O4 R+ O; g9 }/ k' f
  98. // ReadPhysicalDriveOnNT7 k$ \7 j9 K( F9 J% i
  99. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
    4 ], d5 f9 i: A" v+ M/ H/ b+ A
  100. {
    9 `0 J- C2 a0 t4 g
  101.    // 输出参数. L# G+ B* Z3 Y! ]0 F/ E# l
  102.    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];5 c" J3 o9 s( I$ W! ]/ z

  103. 3 X8 x( _  J3 w% ^% O4 a
  104.    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
    * n/ I9 J/ d  v/ g. Q( e: _8 Q/ C
  105.    {
    5 F$ q: h* ^1 `/ J1 p
  106.        HANDLE hPhysicalDriveIOCTL;
    ' X( @" a' u1 o( Q/ R# L2 }
  107.        char szDriveName[32];
    : r) M: ^0 l1 ~2 A" Z& L- c( r! S
  108.   e4 k/ X# a9 |" w4 u9 N
  109.        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);3 q/ V/ C% J3 I5 f, x3 c( q* ^8 I8 v
  110.        hPhysicalDriveIOCTL = CreateFile(szDriveName," {6 v( I8 e) J9 m
  111.                        GENERIC_READ | GENERIC_WRITE,
    ( m6 L  j) E! u/ l& ?" d
  112.                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
    7 U5 Z8 U# E" a7 W: S8 f
  113.                        OPEN_EXISTING, 0, NULL);
    ; X/ G! F' K  T, r
  114. ( _/ W- m, o: w. |8 i5 B
  115.        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
    * h" \7 `; I2 C+ W  _6 y& F
  116.        {
    - Z8 ~8 O4 X0 l6 \2 h: \
  117.            DWORD dwBytesReturned = 0;( {3 o" @, s& p7 P$ O) a
  118.            GETVERSIONOUTPARAMS gvopVersionParams;# S" ?& M) m- W6 n
  119. " _% S% e- R% r
  120.            // Get the version, etc of PhysicalDrive IOCTL
    * B: r, M0 a" Y. R1 N* s
  121.            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));) h7 Q3 D: Q" X, ?2 B- J7 W3 [
  122. 1 U" @. @% ]/ [" d8 D( x
  123.            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
    5 k( ], ]$ w5 |
  124.                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
    9 f/ Z4 }2 |2 ^# l  O) c% ~
  125.                    &dwBytesReturned, NULL))
      \/ _2 |/ c  o4 p
  126.            {5 p* o6 E4 v3 k
  127.                continue;- y- |7 ~: F( }* |; W
  128.            }* a; d  i6 f9 b& V1 @

  129. 1 P8 z( c% v& ?( _9 g+ M5 f! ~4 }
  130.            if(gvopVersionParams.bIDEDeviceMap > 0)
    ) N* \" `1 q/ j+ N/ t: N: K# R% D
  131.            {
    . f! Y* z9 c3 ^
  132.                // IDE or ATAPI IDENTIFY cmd+ z  S- e' O7 o+ V6 \' K
  133.                BYTE btIDCmd = 0;
    1 A5 Y* y7 v$ u4 B- J1 `! F) ^
  134.                SENDCMDINPARAMS InParams;# ~* X: F! B$ ?7 r
  135.                // Now, get the ID sector for all IDE devices in the system.3 _! L* c) u# M
  136.                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,/ A# D5 |) _- x# x; K
  137.                // otherwise use the IDE_ATA_IDENTIFY command
    9 ~& W) b* N1 ^  h
  138.                // 具体所得结果请参考头文件中的说明
    ) U0 }! i0 s* K' E) j
  139.                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?3 k/ |4 W2 ?% s: K5 v$ I3 X
  140.                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;* G  ?! ~1 [- `9 ^+ N. d/ A
  141.                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
    ! u" b8 H! N3 D+ n5 s2 c
  142.                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
    1 x2 ]# \1 j8 v- b/ t
  143. 4 T" X4 \6 ~2 L. e1 C& D) ^2 i. G
  144.                if(DoIdentify(hPhysicalDriveIOCTL,
    ! p. @. q/ `# D. g4 q
  145.                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,, n6 \8 m6 R9 ?$ z, z! l4 J7 f' {/ d
  146.                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))  |# T, a" a+ N
  147.                {
    9 o% d! e* \* P$ K% s* F
  148.                    DWORD dwDiskData[256];
      t6 ?) a5 R! `* a) U
  149.                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件8 n( z1 L+ Z1 E  r- \+ i: Z
  150.                    char szSerialNumber[21];
    / r4 W2 E+ t3 }1 u) w& j
  151.                    char szModelNumber[41];" B3 _- ?4 X3 ^5 K) q$ S
  152. ' N; n* P" T) E  y- e  C
  153.                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
    : J( F) m% ^# E7 j4 w
  154.                    for(int i=0; i < 256; i++)+ Y* k: l. |# ^
  155.                        dwDiskData = pIDSector;) D& V4 J7 V$ G9 c0 Z  C, I
  156.                    // 取系列号
    " F( F4 V: P5 ^, a3 _
  157.                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));9 B9 `: y$ A9 d6 E7 R, y( t
  158.                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
    ' t4 v. C8 e; y' `

  159. 3 U) w8 w2 X; R# `' C" V
  160.                    // 取模型号7 d: `  P8 r8 Q5 g/ z2 [
  161.                    ZeroMemory(szModelNumber, sizeof(szModelNumber));
    / W# E7 T9 i& {( G& O
  162.                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
    * E4 o1 H+ \- P. D) M) ]
  163. " T. F9 C+ k  v% `4 M1 X
  164.                    pSerList->Add(szSerialNumber);
    - M" r& a" [+ D* M
  165.                    pModeList->Add(szModelNumber);% t8 O3 `! z, U
  166.                }
    0 L! K7 H9 r, [: o5 h
  167.            }
    1 P4 _) x: y) n# X
  168.            CloseHandle (hPhysicalDriveIOCTL);: ^. d1 M7 n2 e* }. L
  169.        }# ?% g/ ?9 g) x- q1 [* O
  170.    }
    , |% X- q( m: Y% _5 ^7 P, b
  171. }/ O/ @# ^" V) P* E, [4 V
  172. //---------------------------------------------------------------------------
    - G4 H7 D" N8 S& V9 T' z- y& Q
  173. // DoIdentify9 H6 u/ P4 k1 `: }, Q  z
  174. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,) ~' e4 P* \3 t0 T
  175.              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,* |& F/ D$ g# c7 K6 [  o
  176.              PDWORD pdwBytesReturned)' F: m: @; C& f: q1 Y+ W5 F/ C
  177. {
    5 W5 F9 \" E" y% N/ I0 z
  178.    // Set up data structures for IDENTIFY command.: B- o+ p$ e8 g  A- u% k' r  M
  179.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;$ u# a$ [3 f: g, o- T* [$ M$ E) F1 J
  180.    pSCIP->irDriveRegs.bFeaturesReg = 0;
    ( _' g1 F* k5 n1 G8 i
  181.    pSCIP->irDriveRegs.bSectorCountReg  = 1;
    " M( i, [+ u7 Z6 z
  182.    pSCIP->irDriveRegs.bSectorNumberReg = 1;/ D# m% {( T/ [; m$ D
  183.    pSCIP->irDriveRegs.bCylLowReg  = 0;# a( _  z4 h3 P6 U; U
  184.    pSCIP->irDriveRegs.bCylHighReg = 0;8 Q# d, p# y! c, H9 N
  185. ; @% k! f7 f( _
  186.    // Compute the drive number.(主盘和从盘所对应的值是不一样的)
    ' P! K8 x, [7 _7 K' l
  187.    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
    # ~' ^# a4 O! s4 P$ y) R

  188. 4 {2 L$ }0 n+ ^3 q2 [. ~8 n0 [0 g
  189.    // The command can either be IDE identify or ATAPI identify.
    ' Q1 B- z& ]# M) G) z' N
  190.    pSCIP->irDriveRegs.bCommandReg = btIDCmd;+ y/ i, R) [& F/ m  I7 |
  191.    pSCIP->bDriveNumber = btDriveNum;
    . f" F1 P+ u" A$ E; S& C7 n( k
  192.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;4 e. Y) T# p1 d5 v) h6 F
  193. 3 f  t. n# ~5 \8 U1 K% ]6 F
  194.    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,% D7 i1 x* w6 U' b
  195.           (LPVOID)pSCIP,
    , O/ N3 o; C* f. k
  196.           sizeof(SENDCMDINPARAMS) - 1,
    6 C, W1 l; `+ F' ^2 j' }6 A6 W
  197.           (LPVOID)pSCOP,
    : I" ]& q6 o) q  s& X  S, r
  198.           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
    # h2 G1 y! _! l
  199.           pdwBytesReturned, NULL);
    5 X- B: n# K! P) L8 l
  200. }9 K1 ]4 }; G) J1 _- r
  201. //---------------------------------------------------------------------------
    & A1 D& b3 f" `( X8 v  ?% |0 j
  202. // Windows 95/98/ME 代码
    1 k4 N3 g6 P2 H* s
  203. //---------------------------------------------------------------------------
    ; J0 }2 x& s7 ?( r
  204. // ReadPhysicalDriveOnW9X
    ! V, p0 ^% p5 ^/ @3 l
  205. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)7 [( N& q, F$ u. i0 t+ J  |1 N& k
  206. {
    ! M7 P, R1 G+ X9 y
  207.    WORD wOutData[256];/ O! X" B, o1 C$ t
  208.    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);; n7 e; d/ A- s# C6 |. S
  209. 1 s8 @1 c* B& [7 Q8 c. B
  210.    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
      v. |7 b8 d+ N  F8 y6 S
  211.    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以- r. C3 u/ W! U" O0 d$ J' Z3 \
  212.    // 避免蓝屏的出现。(期待高人能指出原因)7 j0 K/ m& p  U
  213.    for(int nDrive = 0; nDrive < 8; nDrive++)
    $ R" ~. f6 |  M. D
  214.    {- f9 @- S9 K5 G% v4 }( L6 U2 O9 A8 Q
  215.        WORD dwBaseAddress;
    4 g  v2 {+ H* k
  216.        BYTE btMasterSlave;         // Master Or Slave2 O4 z  [. _, c8 [" z
  217.        bool bIsIDEExist;
    9 r8 _, E8 w5 W1 s- L
  218.        bool IsDiskExist;/ e( }' @% N. l% b- c
  219. 5 T* ~! n7 P: t2 C+ h7 E& }- k
  220.        switch(nDrive / 2)
    8 y9 a2 g: s* [. d; Y2 e4 L* R
  221.        {" s. q, `. @' l$ K6 \
  222.            case 0: dwBaseAddress = 0x01F0; break;
    7 @4 u* T7 y& c' y0 R% }
  223.            case 1: dwBaseAddress = 0x0170; break;
    ' a/ w" G5 x, B& J1 y9 p/ K! @. Q" T) e
  224.            case 2: dwBaseAddress = 0x01E8; break;! X& [! T2 f. n" W* U- i- i
  225.            case 3: dwBaseAddress = 0x0168; break;
    ! S; h. ~6 M# S; Z( d
  226.        }
    / G1 \" z/ e) _7 N$ B
  227. ' ~) A3 O5 S% @4 x: |/ R3 T
  228.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
    2 H7 N8 l/ ^* i8 n

  229. ! O4 l& u+ b3 [  _" _6 D$ z" s
  230.        // 进入Ring0" `5 h8 n. Q% i9 m
  231.        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
    : u+ t' [4 a/ U* h& H
  232.                bIsIDEExist, IsDiskExist, wOutData);/ r* P) N3 t+ B( j; Z1 x
  233.    }
    , K; s- H% j: {! D0 X) M

  234. 2 q! f9 n6 Q% o' K8 m4 m1 x
  235.    // 开始读取0 p% q4 d- D: d: Q1 g
  236.    for(int nDrive = 0; nDrive < 8; nDrive++)- a5 o4 Q, }# C5 G/ R
  237.    {
    9 g- i  ^! i7 o$ `6 Y8 }, J
  238.        WORD dwBaseAddress;! |/ P1 e0 \$ z. h  I; F
  239.        BYTE btMasterSlave;         // Master Or Slave: Y& y& p) t7 X( _& x: e/ o( E8 I
  240.        bool bIsIDEExist;
    + g+ j* ~4 {: }' Q0 A
  241.        bool bIsDiskExist;
    % ~; B, o4 a0 d  ?2 F6 c6 A
  242.        switch(nDrive / 2)
    8 G% F6 Q, r+ s* ]" r; t. F' U
  243.        {
    * y4 Q8 m) ^( ?
  244.            case 0: dwBaseAddress = 0x01F0; break;
    " l. a# H2 P% R' u7 k
  245.            case 1: dwBaseAddress = 0x0170; break;
    # p# t& s, E2 ~# t, S5 L0 u. R
  246.            case 2: dwBaseAddress = 0x01E8; break;" b! [0 B! N; j1 ^  M
  247.            case 3: dwBaseAddress = 0x0168; break;
    ( x5 r# e- p5 V
  248.        }
    ' Y# j: I' r% Z8 ?) `9 r0 J6 n
  249. : [& V% ]) {( ]) C* `& F
  250.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);4 S% E& `' v4 {$ n

  251. . q0 Y6 J2 p! J7 h$ {
  252.        // 进入Ring0
    % V7 A) J6 t7 T1 d& s
  253.        bIsIDEExist  = false;5 {# i5 H& l$ Z- R
  254.        bIsDiskExist = false;' J. S( O1 `' M& C7 k4 t* [
  255.        ZeroMemory(wOutData, sizeof(wOutData));; g5 {9 u2 I9 R1 ~2 J3 N$ {

  256. ; H. A- d; Q; e: d5 Z( C) h
  257.        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,5 c4 Z3 B5 s) P$ {% |
  258.                bIsIDEExist, bIsDiskExist, wOutData);- w8 w. r' z- Y

  259. & _% Y. Q: V6 q$ I4 r- m' m2 x% N
  260.        if(bIsIDEExist && bIsDiskExist)+ }, T" F  D2 s, S. F: _4 ~+ t
  261.        {
    9 E$ Y4 W) P6 O) T& a
  262.            DWORD dwDiskData[256];
    ' n- v  F& |6 |7 S$ \; W
  263.            char  szSerialNumber[21];8 \2 w( f0 O$ I; \6 R3 x
  264.            char  szModelNumber[41];! X$ @' b9 L$ t$ c4 r/ \+ r
  265. 6 ?9 M* ^" ?/ }- Q6 g) E6 V
  266.            for(int k=0; k < 256; k++)
    7 U" Q6 [/ o7 @& k* F( S5 z1 W
  267.                dwDiskData[k] = wOutData[k];, k9 ?8 `# p  [, r

  268. " a4 a) z8 b/ |9 d# q
  269.            // 取系列号
    * n( p" {% c) x( w
  270.            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
    ! ?4 b/ _% q( z+ B
  271.            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
    7 c6 q0 T6 G# [" X3 O
  272. $ p& M. c" `# F5 R* V' f: ?& u
  273.            // 取模型号
    9 H- @/ _1 r4 V* p4 {
  274.            ZeroMemory(szModelNumber, sizeof(szModelNumber));+ R! S4 m; ^4 I7 u* n; P" K0 S( P. _
  275.            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
    + D5 G; D0 W7 N8 p
  276. . X& |# k! C) \6 H( V" ]% }2 U
  277.            pSerList->Add(szSerialNumber);& ~. r' c3 {4 K" y6 M
  278.            pModeList->Add(szModelNumber);
    8 X. m; d* P8 g
  279.        }0 B3 W* c. x( V" V) H: ^
  280.    }8 Z& c$ \3 ]" ^& o  R+ l$ Y
  281.    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);& W$ c/ k! v. y5 L0 Y
  282. }
    1 `/ [5 S2 O. N, B* ]) |
  283. //---------------------------------------------------------------------------
    " v/ F1 x) L+ h$ D* j8 x
  284. // ReadPhysicalDriveOnW9X_Ring0()
    . q2 M& ?7 n" W! b2 `; k! n1 M2 f7 m
  285. //# w, m" G, B6 N
  286. // dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h1 N/ R% p- o4 f0 v& p7 @  h
  287. // btMasterSlave = Master(0xA0) Or Slave(0xB0)$ [7 P7 I4 Z8 E& f2 Q7 V3 z; T
  288. //---------------------------------------------------------------------------
    7 h, N8 t$ L0 Y5 \
  289. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,$ L3 M0 _# D' n1 e, B# g0 |
  290.        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
    / }$ b' }! u, U# p; ^
  291. {+ f9 X- b3 x; h
  292.    BYTE  btIDTR1[6];
    ! f% [& f" c* d
  293.    DWORD dwOldExceptionHook;  g* Y$ o' _' Q# E% }+ i
  294.    const int nHookExceptionNo = 5;) v+ u; R4 Y$ G# j0 |6 ~( a
  295. % N/ R! _6 `$ F; H% y
  296.    BYTE  btIsIDEExist = 0;
    % _# i/ B; G% @% s# k$ h5 x
  297.    BYTE  btIsDiskExist = 0;
    2 g: `/ E! b) V
  298.    WORD  wOutDataBuf[256];0 r9 d& k. B* [4 @, X. X% b2 c1 j/ I

  299. 8 B7 j% u' G. f& W
  300.    BYTE  btIsFirst = (BYTE)bIsFirst;
    , ~8 A5 J* v# E
  301.   `: j3 w% V* P! a8 }6 g& \0 x
  302.    const BYTE btBit00 = 0x01;
    6 G0 o8 {9 a% r: @- e
  303.    // const BYTE btBit02 = 0x04;
    # H, }" }: E/ J% g$ K& j3 V' J5 [/ g6 B+ s
  304.    const BYTE btBit06 = 0x40;, Q/ O/ j4 B3 ~% ~# B: ?0 z  B
  305.    const BYTE btBit07 = 0x80;/ j7 M- O& p! A3 ~- X# x' {: M2 G
  306.    // const BYTE btERR  = btBit00;
    * V/ _. L9 R% O( J. N3 I
  307.    const BYTE btBusy = btBit07;
    / M8 j$ U- g* \% t/ r8 N
  308.    const BYTE btAtaCmd   = 0xEC;* q0 k# [% v5 S& M& F/ d
  309.    const BYTE btAtapiCmd = 0xA1;
    ) q3 B0 N$ c7 k* ^: G; I" i3 u

  310. 0 A$ Q, t* M3 u5 I1 Q" ]
  311.    __asm
    7 @5 n4 Y0 f6 Q# b; D: m- Y
  312.    {
    1 k: n9 D5 d& `) P+ ~! p8 r0 @
  313.        // 必须先执行这条语句
    , E: \$ B! k! {4 t6 U& s4 l1 U& O" U
  314.        JMP EnterRing07 g4 j5 O' O. |" S9 k4 @" ]0 W* R, Z

  315. # v1 j7 h2 L+ N6 Y1 Y
  316.        // 定义过程' I  h- B- g& e6 ^5 q9 c- G2 ^
  317.        // 等待IDE设备直到其不为忙为止5 f% K1 n2 F/ R- f9 O* Z) Q( ?
  318.        WaitWhileBusy proc. g8 m, z1 L3 I3 h4 g2 _- r( [

  319. * q# N2 t$ V8 |: b7 {0 ^" A
  320.        MOV  EBX, 100000; D/ N& P* U4 u! Z7 X
  321.        MOV  DX, dwBaseAddress
    ! L" x4 N; d* O  E3 b9 M+ p; f. ]
  322.        ADD  DX, 7
    % e/ |2 O! I/ c2 P' n# j

  323. 6 _) X1 {& k9 v; a  i$ p4 `/ ?
  324.        LoopWhileBusy:
    & S4 u6 x2 \: V* V% N

  325. 8 E1 d) {9 D" J; I* V- i
  326.        DEC  EBX
    : z; s, }# g/ B
  327.        CMP  EBX, 0+ }9 M6 f; H- m$ V( F
  328.        JZ   Timeout
      }5 t% t8 d6 W4 f! q
  329.        in   AL, DX
    * f" o7 \; l8 O3 }* s
  330.        TEST AL, btBusy
    / [6 A% _# z6 l$ S4 z7 v8 {! M' f1 `
  331.        JNZ  LoopWhileBusy
    ; M" t4 q7 g+ x3 q8 x6 S% J! u( E
  332.        JMP  DriveReady
    0 ^( B5 z: k; k% w, C" x

  333. ) z" s" E; k- d5 p" ^
  334.        // 超时,直接退出7 X" Q- A# l8 s2 T8 O4 U
  335.        Timeout:) m: U. C& e) Z2 D: ^
  336.        JMP  LeaveRing0
    $ {2 ^/ \! j5 `* I0 z
  337.        DriveReady:
    2 E  w7 M/ k! E. b
  338.        RET5 o  I8 K* I" d& R
  339.        ENDP   // End of WaitWhileBusy Procedure
    # W  U; F0 w& ?% M2 o* ?' u) F. d' r. `

  340. 2 Y# B6 \8 R1 ^# v' @, F
  341.        // 设置主盘和从盘标志0 c* Y) r. P) x1 `, a1 Z
  342.        SelectDevice proc' P6 f% S+ a, E
  343. ( m2 }, C$ Y" s( y% W" x
  344.        MOV  DX, dwBaseAddress) s6 j8 F1 f1 \# W
  345.        ADD  DX, 6
    7 o$ q3 e0 {- w/ s5 n9 k
  346.        MOV  AL, btMasterSlave
    0 B# H' _$ c" ^* e- e8 K% V' Z  y
  347. . }6 n" ?$ K' w. T0 [, a2 ]
  348.        out  DX, AL
    8 G3 j, a- v  x* K5 t( b% L
  349.        RET1 x1 @# |  j- F! P' _9 q

  350. ' x: A% B4 {+ t* {
  351.        ENDP  // End of SelectDevice Procedure
    " P; `& w8 I* X% v
  352. 9 M8 C5 U& ]+ s$ w- v
  353.        // 向IDE设备发送存取指令' }- ^7 [) O7 g) e  l, Q$ F
  354.        SendCmd proc
    ; P) c5 I5 T6 W2 d- U, G- [* t% \% g) t

  355. $ N* p( v0 m; z3 {( L
  356.        MOV DX, dwBaseAddress
    * D6 R! Z3 m, R: C
  357.        ADD DX, 7$ s5 V+ e( N5 l* G) w, y9 Q
  358.        MOV AL, BL // BL是主从盘标识,在过程外设置
    ; T; S# a+ L0 i- ^. Z6 z! N
  359.        out DX, AL, e/ S* w0 G3 A0 b) ^
  360.        RET8 H5 G# Y8 Q" Z5 ?* m
  361.        ENDP  // End of SendCmd Procedure  r# \; q7 Z4 J: e; P5 `

  362. 4 q9 ?- b. a4 t& V  U# g, U6 n: C
  363.        // Ring0代码
    / `+ l7 \8 J+ t6 z8 E
  364.        Ring0Proc:
    " Z% k% N0 a( k* ^% P$ I9 E
  365.        PUSHAD; Q" T+ w0 r  w" h9 z, M3 X$ M4 J9 j
  366.        // 查询IDE设备是否存在
    2 \2 P- m9 I' O: j$ K: ~4 m
  367.        MOV DX, dwBaseAddress& J& f+ g, _! ?
  368.        ADD DX, 75 u1 l8 L( c' i' j
  369.        in  AL,DX' l& B7 ^' z2 I' v5 I7 C, d$ f7 e

  370. 3 ?5 s- ]+ \8 ~$ z7 ]- s
  371.        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回* _: X, K! m3 {! U& |, i
  372.        CMP AL,0xFF( \, p8 N. ]% f* I4 ^8 l6 |+ r
  373.        JZ  LeaveRing0
    4 r3 F& f5 G2 d. F! t
  374.        CMP AL, 0x7F! p2 f! x& K  \, r# O# G/ u
  375.        JZ  LeaveRing08 W% o( h( p/ J
  376. ) H, s8 c/ G# ^" }! s
  377.        // 设置IDE设备存在标志) l9 K7 W' v1 }4 u9 M" q
  378.        MOV btIsIDEExist, 1, s3 \# w7 P% t. \  b5 D

  379. 2 z5 A' }  n* {: l1 S/ O
  380.        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)' h& ?# m( C  u: `, `
  381.        CALL WaitWhileBusy4 ^6 U. K, H( ~+ k+ l$ U8 L
  382.        CALL SelectDevice) u# x4 L( u# X8 P
  383. ( {* ?: r" M# R6 q3 G( S
  384.        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏' ]8 X3 Q* G* D$ t# w6 Q
  385.        CMP  btIsFirst, 13 `, W# y" U$ i$ V
  386.        JZ   LeaveRing0
    % p$ F! ^- O! f  x, T) I$ K, w, s
  387. 6 t1 D3 s& f& `
  388.        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
    % g+ ~; [5 q. i8 v+ X6 {
  389.        CALL WaitWhileBusy
    4 `0 e3 K& j; K) G
  390. ( }! u4 M; N4 I% h
  391.        // AL的值等于cBit06时,不存在驱动器,直接返回
    ' z+ D" L: Z2 I6 K" a' O; H% H
  392.        TEST AL, btBit06
    6 h, m+ X# A& X3 c
  393.        JZ   LeaveRing0
    7 R" x$ H$ ]& j- n+ G7 z5 G' K
  394. 2 j1 |+ h1 }8 ]4 J. L; H
  395.        // 设置驱动器存在标志
    * E7 V+ T7 c! K: N
  396.        MOV  btIsDiskExist, 1
    * e2 ?. M+ k' ]! V. g/ M* X( q, b

  397. ; J  ?; i0 p  z9 o& S  S
  398.        // 发送存取端口命令2 T2 N  J" m9 h/ C4 z$ V
  399.        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,3 \$ _" ]7 H9 e* @- W& ^6 J
  400.        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
    $ X; F/ Q5 V/ k8 d
  401.        CALL WaitWhileBusy6 Z( d9 x: Y3 h- }3 K7 U
  402.        CALL SelectDevice    // 设置主从盘标识
    3 ~3 ?7 P" C) d# I1 J9 w
  403.        MOV  BL, btAtaCmd      // 发送读取命令3 b2 _. o% D9 Q7 V' h
  404.        CALL SendCmd
    8 P" V5 e  v+ @" n1 ~/ }3 {
  405.        CALL WaitWhileBusy
    : L: H$ ~. H1 Q( V
  406. 0 Y8 m$ N: Z6 M
  407.        // 检查是否出错6 Y6 Y' L( r. d% b) v( ^+ R# c& D
  408.        MOV  DX, dwBaseAddress
    " o: ^3 G7 P! R+ F0 [" {# l7 d
  409.        ADD  DX, 79 l: Y. R- \; X8 c" o5 u

  410. ( \8 y4 ]! J: {" `! j
  411.        in   AL, DX0 Q7 ]" T1 h! ^  f* H- x' z; Z

  412. " W0 X) k# L6 z. T
  413.        TEST AL, btBit00* o2 A% E& Q4 v# y3 ?2 t' p
  414.        JZ   RetrieveInfo   // 没有错误时则读数据
    ! K' N5 C' t+ t5 K4 e- i

  415. 3 O) t" y# p# ]- l9 v8 F3 [
  416.        // 如果出错,则进一步尝试使用ATAPI设备命令
    6 g% ^5 n0 p$ a7 H5 K* M- j2 d
  417.        CALL WaitWhileBusy/ Y) T- h! _/ \& r8 |: c
  418.        CALL SelectDevice) t% {+ }/ ?+ U0 f4 Y* F
  419.        MOV  BL, btAtapiCmd
    6 \# \8 u7 V) |' s+ W
  420.        CALL SendCmd
    2 B, B+ P0 G2 z7 B1 n
  421.        CALL WaitWhileBusy
    8 m" s% B& \0 \# R+ m

  422. - d* M2 m& V* l$ ]: `
  423.        // 检查是否还出错
    , f1 j9 U- K; I: D
  424.        MOV  DX, dwBaseAddress
    " o6 @; p% x% P6 {4 v  l
  425.        ADD  DX, 7
    ; I( G$ R  k, U. ]: ]
  426.        in   AL, DX
    ' |; z& E: ?1 z8 ]: @( U3 g* [
  427.        TEST AL, btBit00
    ( A. ]4 V0 K  E1 W. y) f! P5 ^
  428.        JZ   RetrieveInfo   // 没有错误时则读数据
    5 w1 w' x: A( g8 [
  429.        JMP  LeaveRing0     // 如果还是出错,直接返回+ [! \1 ~' }% ]; ~% z: q

  430.   p& O( s5 v5 x* ?3 g
  431.        // 读取数据
    0 {, e* A! P) p3 q( u
  432.        RetrieveInfo:1 S# U+ \4 \0 ?# c+ {

  433. : l4 D  s2 `8 L6 {" o$ r$ E
  434.        LEA  EDI, wOutDataBuf
    8 d+ b% Z) n, a0 j; q
  435.        MOV  ECX, 256+ h+ ?5 \- P; U6 H  y8 u- v3 B7 k
  436.        MOV  DX, dwBaseAddress
    ! Q/ B$ C+ j4 M8 d, x
  437.        CLD- B' _' j; |1 ?' q2 j2 L
  438. : s& g3 h1 w1 _* s
  439.        REP  INSW4 B, d0 T7 Z' X. V* X( N8 N( g
  440. ( N$ i5 y/ m8 l7 m
  441.        // 退出Ring0代码% ^2 H% }+ _* U% A3 i
  442.        LeaveRing0:, }+ a$ l& X! S) d8 b" G

  443. : l% O- ?% D( T* `2 V4 `7 G9 {
  444.        POPAD1 ^. B) Y1 `& G3 s
  445.        IRETD
    ( ]  l. ~, s* Z, a: A* }, `

  446. 5 H6 ~4 Z2 g+ k6 q5 j3 I- ]6 I/ O, W
  447.        // 激活Ring0代码) N9 b5 P; t1 c2 K7 Q# |6 {$ b
  448.        EnterRing0:
    2 \9 u+ u) ?  l; c4 P1 ?( \

  449. / s+ p2 F1 r4 t5 x" _; c, r
  450.        // 修改中断门
    1 N7 k8 {, q  @6 @- N: l9 ~" W
  451.        SIDT FWORD PTR btIDTR1& n- G7 k8 a- K0 U  K( j% H" z  s9 u
  452.        MOV EAX, DWORD PTR btIDTR1 + 02h- P- I3 d. h# M( Q, p8 O1 u1 C
  453.        ADD EAX, nHookExceptionNo * 08h + 04h
    0 M; R  B& G: Y
  454.        CLI
    ' \1 C$ U/ T8 j# b* v1 F
  455. * c$ B! C+ [0 f) a, B6 [
  456.        // 保存原异常处理例程入口# X* n/ f$ V2 R+ }
  457.        MOV ECX, DWORD PTR [EAX]' e* j7 T. |7 P. e2 H% P0 h' K. S7 [3 I
  458.        MOV CX, WORD PTR [EAX-04h]
    6 x: S1 k# D. k5 \
  459.        MOV dwOldExceptionHook, ECX% v6 K# j+ T* `. k- t
  460. 6 D& y  _8 ?2 \( e' i
  461.        // 指定新入口
    0 v  E1 G6 ?; T/ p7 o9 A7 B
  462.        LEA EBX, Ring0Proc
    ; _' C' ^! U+ l! }; a! Z0 }
  463.        MOV WORD PTR [EAX-04h],BX
    & H; M: Y( x5 J' L( _
  464.        SHR EBX, 10h5 f7 x0 r) q" y' b2 d: z
  465.        MOV WORD PTR[EAX+02h], BX* F9 x: U% k1 I- N  S
  466. ) w( D* r3 }# S5 z) m
  467.        // 激活Ring0代码  R( x* U+ T* J- F. F/ y) A
  468.        INT nHookExceptionNo! J4 c& e2 a& |/ ^7 a& ^
  469. 1 d* q  M; i/ b7 u' o$ {
  470.        // 复原入口
    : F6 s  r" D; _& E' r& N1 J
  471.        MOV ECX,dwOldExceptionHook
    $ j, T& s' Y2 i! b& c/ \8 }
  472.        MOV WORD PTR[EAX-04h], CX
    9 A* _9 }. N4 R0 G) Q* E
  473.        SHR ECX,10h
    4 C9 v) \+ |/ ]' S- o6 S, k
  474.        MOV WORD PTR[EAX+02h], CX8 j4 t4 @) v5 H$ o) ^
  475.        STI
    % ]8 `. @: Y8 I  @% ]
  476.    }
    9 k: i  d  H0 Q' B8 p$ t
  477.    if(!bIsFirst)/ C: n2 @. h$ B& z
  478.    {
    $ f5 `% @1 c! Y+ W
  479.        bIsIDEExist  = (bool)btIsIDEExist;6 z7 s0 F9 x' Q$ y
  480.        bIsDiskExist = (bool)btIsDiskExist;0 Q4 d; j$ O6 i
  481.        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
    ; m8 r# H2 b$ ?7 g3 K$ }5 ^6 e) F
  482.    }0 S$ r, @2 _6 E0 g, @1 k
  483. }( G. \( X" \# ^- a0 w" S4 \
  484. //---------------------------------------------------------------------------; z' @- c4 B0 L4 [5 V
  485. // 调用方法:
    ; Q% {# M0 Q1 h- x3 C
  486. void __fastcall TForm1::Button1Click(TObject *Sender)' d* p( Q3 `. C6 G" c% e) F; `( h
  487. {
    ! y7 E- i+ V# |/ n+ n* Y/ ?# G2 Y7 f
  488.    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);% x/ d1 @2 b- @* s- \  @
  489. }
复制代码
发表于 2005-8-15 01:00:45 | 显示全部楼层
晕乎乎。。。怎么看8 洞阿
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-10-2 07:30 , Processed in 0.019365 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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