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

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

[复制链接]
发表于 2005-8-11 11:42:04 | 显示全部楼层 |阅读模式
  1. #include <WinIOCtl.h>
    . w$ n  U( E/ D# l- U7 e/ i' d  B
  2. #include <stdio.h>
    # U- B( R; p0 u5 ]; e$ A# U: C! S

  3.   l, o+ x, E6 s1 R. j, d
  4. #pragma inline
    3 s3 l- P6 C; v# R5 M; s: P2 M5 [
  5. //---------------------------------------------------------------------------
    * F2 s+ a# w8 W& N2 W% m# [4 ]
  6. // IDE NT/2000/XP专用变量8 Z/ I" v4 `, w) o( K! D6 Z
  7. #define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
    + Z# G( G' W9 f8 e
  8. #define DFP_GET_VERSION         SMART_GET_VERSION
    4 m& O# ^! }3 n: S) Z
  9. #define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND6 ]/ ]; c8 Y6 k' D: n- V6 Y9 h
  10. #define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
    6 r% e; Q& H2 q$ r8 u

  11. 3 ?4 v+ ]# T- Y
  12. const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令4 a' ]1 M' e" {6 v  \; j/ ]" H" ~8 f
  13. const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
    ) f- Q% L. U# Q/ ^- s6 F- I9 @# b
  14.   {/ X7 M4 L2 u$ [( Z+ }- j+ U
  15. const int MAX_IDE_DRIVES = 4;
    2 Z% A! }0 ]8 z7 k
  16. - E" a* C  {, F, S
  17. // SCSI专用变量
    ' T% V8 q" [& w* m# U0 k
  18. const DWORD FILE_DEVICE_SCSI             = 0x0000001B;
    ) K% t4 K0 n, O" {
  19. const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);9 W/ i4 [8 p* ?, O. M2 Q
  20. const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition8 |; J8 }% w' Q7 h) a  m9 Y
  21. const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
    2 X  {' D2 Z7 c  R) n
  22. 3 ]1 K- V/ Z5 g+ }; e3 l: J  d
  23. typedef struct _SRB_IO_CONTROL
    : o5 }1 X  O  n! x! I
  24. {
    " L. p8 }" L0 s! D- [$ ^
  25.    ULONG HeaderLength;9 F% M; a! S  }$ r# D7 L  s, L
  26.    UCHAR Signature[8];2 b6 _9 j; `- K1 Z  l/ C! J
  27.    ULONG Timeout;
    9 V3 b- a4 l1 r
  28.    ULONG ControlCode;
    * y  J9 ]1 P* h! N* N' [) M" P& v: @
  29.    ULONG ReturnCode;
    3 I& |) Z5 b; ]( T& G  g1 s
  30.    ULONG Length;
    : z" ^2 x; h4 L( F% ^6 M! C" G
  31. }SRB_IO_CONTROL, *PSRB_IO_CONTROL;
    5 ], ^) L* }  H5 Y4 p! h/ M4 A" h

  32. . {4 _- k6 N! [$ t1 z
  33. // 读取的主函数! j$ \3 B" N0 a! ^4 I* s( P9 c
  34. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
      Y2 d2 p9 `; F- R9 ]! `& O5 W

  35. - F' w& D% o1 ~  _, |( Y( z( L6 T  a
  36. // 辅助函数
    $ y4 M6 _. ~2 c. A
  37. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);" e3 y" G2 @. s. K; U
  38. // NT/2000/XP函数. ?7 l& m9 C/ J8 s
  39. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);) [) T  y  @# d+ T
  40. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
    & |4 Y2 z* Q5 S7 G& t: x* k# R
  41.        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,9 w9 ]) y# Q# O' a
  42.        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);: b: u. p5 d- U, X* Y
  43. // Windows 9X函数
      j3 n" Q( L1 L: ?, `& U  x
  44. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);
    ! S6 a/ H" V6 j
  45. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,/ I. {) @" z/ L
  46.        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);# A+ ]1 E" T" M5 [* e
  47. 8 y9 H, s7 Y1 f+ U! D
  48. // SCSI读取函数(for NT/2000/XP)7 l: E& q' C& ?  ?& ~
  49. String __fastcall ReadIDEDriveAsScsiDriveOnNT();
    5 ]) P! x3 g% V4 j1 O% Y: ?9 q" Q
  50. //---------------------------------------------------------------------------4 i1 x" O" H  o# h
  51. // ReadPhysicalDrive5 h& F  t$ _9 L
  52. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)# M. @( X; b7 Q2 p+ {4 L$ E8 K
  53. {% t7 g: ?" r$ x2 S
  54.    switch(Win32Platform)
    ! s( N6 S. p9 ]% f0 D' r9 d
  55.    {
    ! r# M7 N/ F4 a, i
  56.        case VER_PLATFORM_WIN32_WINDOWS:
    3 A# h1 ?6 W) ~; H" O& Q' C7 M2 P0 a
  57.            ReadPhysicalDriveOnW9X(pSerList, pModeList);
    0 e- N+ h5 o3 @2 x& ]+ @8 \
  58.            break;4 R) ^  w9 B) M9 z2 f* c
  59.        case VER_PLATFORM_WIN32_NT:7 x' ^; F8 O5 |) Q6 X8 X$ B
  60.            ReadPhysicalDriveOnNT(pSerList, pModeList);6 d/ \; K7 p: k' _9 n. {8 Q
  61.            break;6 I5 p8 h$ P7 c* y+ r4 s, k
  62.        default:
    2 ^5 j5 q) X& _
  63.            break;
    ' M- h7 A: |4 u/ e: g: o9 B0 j
  64.    }
    . }( n) Q. e' M
  65. }; W7 g2 ^- O: ~5 z5 ^, m' L/ s% _
  66. //---------------------------------------------------------------------------
    & U6 q& Q4 K5 j% ^  E7 j
  67. // ConvertToString
    ( a4 T7 W6 _  e" A9 b+ \
  68. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)7 e8 g7 E3 ^+ S3 N  S
  69. {
    & A; Y) b' C  {  j) c; U8 `9 R
  70.    static char szResBuf[1024];7 M& i* O' c. D# Y6 k6 `3 K
  71.    int nIndex = 0;5 A; w/ w# B/ S0 M' f7 c
  72.    int nPosition = 0;
    $ T4 o& R. m# I6 a
  73. ) E5 l$ s! ]4 d2 H+ A# I4 w
  74.    // Each integer has two characters stored in it backwards$ \" P) W& p+ ^2 y; n" A* W- A8 g) G, f
  75.    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)6 Z7 T, {" d; E6 U- M1 f- r
  76.    {; p) T/ s( Z% V7 o
  77.        // Get high BYTE for 1st character& M3 i2 W) `" r+ {" W! _5 i5 V: s
  78.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
    : d5 s0 g: [1 Q
  79.        nPosition++;
    $ r: \+ D8 a2 l3 Z' T

  80. . \, T! r  E7 j+ T3 B
  81.        // Get low BYTE for 2nd character4 [8 N0 I) u& c. A7 \) R) I/ V' C' ~$ \
  82.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);5 Y* Q& T, R) _& c! t
  83.        nPosition++;
    * i0 x7 W+ e' x' ~, d
  84.    }
    8 s1 G' ?) x, A! J' S% S

  85. 6 o( Z: x& T& v8 [0 H* Y. @
  86.    // End the string" N; A% |0 Q% k" c
  87.    szResBuf[nPosition] = '\0';2 P$ H" x* e; Z. f2 Y
  88. 0 b/ h& S. y; L; A$ f
  89.    // Cut off the trailing blanks
    0 G) Q) w1 r( m+ o3 o& @
  90.    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)# n& h8 ?4 q; X* b9 ?. C% w% i
  91.        szResBuf[nIndex] = '\0';
    " e% {. X+ ~; z6 Q

  92. " X0 ^/ @% E& N9 J
  93.    return szResBuf;! ~! M; J" V7 U3 \9 a
  94. }
    & H3 ]8 @- Q) [8 c' l; ]
  95. //---------------------------------------------------------------------------
    % i) l. Y6 c# z2 E5 e+ K' r: Q
  96. // Winndows NT4/2000/XP 代码
    1 w" X, F. d* Y
  97. //---------------------------------------------------------------------------# O1 z# K6 H# K3 N- T7 n
  98. // ReadPhysicalDriveOnNT1 C! C4 @5 \2 U& ]; w
  99. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
    % Q  o+ \" n! x2 a/ {% A& p
  100. {% y: [2 P$ x0 L
  101.    // 输出参数
    ) P0 z# s* S: I3 A- Y) N
  102.    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
    2 V2 V  a0 }! s# E4 h6 s2 t# U4 N
  103. 1 }' Q& B4 `' p/ k
  104.    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)7 d8 A, N$ h( R( O
  105.    {
    9 ^9 z9 B$ C" @; [) A, P2 d
  106.        HANDLE hPhysicalDriveIOCTL;; `2 e: Z$ W" H' I# _3 G; N
  107.        char szDriveName[32];
    ( p9 U5 C/ z( k/ w' j

  108. 2 ^* ]; e, O% z5 g: z+ G
  109.        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);# R# t5 U9 Q& n( V  S
  110.        hPhysicalDriveIOCTL = CreateFile(szDriveName,# D# @+ T( e& C% t( m
  111.                        GENERIC_READ | GENERIC_WRITE,6 m# W2 h) J1 |, f* L' F* n5 t
  112.                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
    / A5 z8 U7 z0 ^% S
  113.                        OPEN_EXISTING, 0, NULL);. r8 I# L1 b6 i  O

  114. * Q/ Y9 A) q& M) m+ [% C" g  e
  115.        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
    8 g4 Y7 L% m% K
  116.        {
    - a' N* _) d4 {9 R# v' a  @( _
  117.            DWORD dwBytesReturned = 0;; |4 V! x8 q" a' s" P0 h& c4 i
  118.            GETVERSIONOUTPARAMS gvopVersionParams;. D. S8 R4 e2 _0 t
  119. ; I. f) M9 x9 \9 l7 ]; i+ r
  120.            // Get the version, etc of PhysicalDrive IOCTL* V) ^: |4 h/ M1 w: L, h, p: ^
  121.            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
    ) v! L" I0 u- a& f

  122. + h7 c: Q% N8 G6 B9 ]6 w
  123.            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,! k3 c# q) R& y, V& o" R
  124.                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),% f: L( L3 G' H" b
  125.                    &dwBytesReturned, NULL))
    , s( J5 Y$ d/ o8 a% o
  126.            {5 x1 ^1 k1 h7 M: y( B
  127.                continue;. i0 G" m: u( a/ a* B3 _
  128.            }6 [& H$ F3 G! H9 l8 D! s

  129. , ?) y) f3 \6 ~7 J
  130.            if(gvopVersionParams.bIDEDeviceMap > 0)
    8 }7 A8 D  |: Y. m3 D" L% V
  131.            {
    ( k0 v. ]" U+ G5 \1 T+ J- C
  132.                // IDE or ATAPI IDENTIFY cmd+ `/ S% \7 d; Z" O. J: G% b. k
  133.                BYTE btIDCmd = 0;' j. e% F' @* x2 O9 W% M
  134.                SENDCMDINPARAMS InParams;5 p3 T! q) U2 Z) V  t: E  d6 G
  135.                // Now, get the ID sector for all IDE devices in the system.5 e- ~2 w: u$ E: E4 f2 X, R
  136.                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,( t9 \4 I# b7 t# u+ O. c0 s
  137.                // otherwise use the IDE_ATA_IDENTIFY command
    * {8 g2 r' v$ Z+ `' N8 m
  138.                // 具体所得结果请参考头文件中的说明
    ; t& }, v; I: C9 @, N3 T  `
  139.                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?! \0 J$ z; @6 R0 ]+ P1 H+ B
  140.                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;5 ]# g0 F" X& a# n
  141.                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
    * F6 a9 I3 N' q
  142.                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));# T. o$ R/ I0 q3 |$ _' A
  143. % C5 V. l: V" {
  144.                if(DoIdentify(hPhysicalDriveIOCTL,+ u% Z& p( r' M; o
  145.                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,$ r1 u- q0 D* ~1 ]5 n8 w
  146.                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
    % i7 K" V, N' j/ l- W
  147.                {' e4 o1 ^. t% Z$ f+ R
  148.                    DWORD dwDiskData[256];
    + e2 k% m- n: x6 g% T& _. e8 p
  149.                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
    ( `$ H/ C: p& H" m  B' n8 S2 N# ^
  150.                    char szSerialNumber[21];
    6 I# z) H' q" B: V/ u5 B# b& C
  151.                    char szModelNumber[41];2 {* f9 z( O6 t. ~4 I+ m; f" O3 U, ~7 r
  152. # n( C3 V) p. }' r" G- U; x
  153.                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;4 ]( ]. P7 a- ?" Q1 O) e* g
  154.                    for(int i=0; i < 256; i++)
    % ]. }# K9 r* N8 t* x
  155.                        dwDiskData = pIDSector;
    6 j2 Y2 J# |7 s8 q3 R
  156.                    // 取系列号. ]/ |( e: b8 S; h: B$ H
  157.                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
    . P) ?/ z- _6 I& A
  158.                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
    ; l- ]+ z9 R- {" F+ X( o
  159. " h- r$ @1 J$ P0 l: V
  160.                    // 取模型号; h1 m) W. T5 [, B- ~. Z/ x- s
  161.                    ZeroMemory(szModelNumber, sizeof(szModelNumber));- L) }! Q. U* e- T
  162.                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
    . B9 v/ m8 @* ^0 ^9 h; w) @# p
  163. 5 K; b. |) t8 `/ r* U4 ^
  164.                    pSerList->Add(szSerialNumber);5 e5 [* I# J3 [. U
  165.                    pModeList->Add(szModelNumber);4 ^' e0 W1 N' @  W
  166.                }4 @; m; X. e1 @$ P
  167.            }9 O0 n1 A) Y" b2 }+ J8 a7 n3 C1 h
  168.            CloseHandle (hPhysicalDriveIOCTL);
    4 @4 H2 q% o. h4 @2 i: n; b
  169.        }
    " L7 {( f& N9 |+ n
  170.    }, D& ]4 |* m9 \1 j: R  q
  171. }6 V/ N8 {3 |$ J  Q
  172. //---------------------------------------------------------------------------4 ~9 y8 s" Q$ A2 y8 K0 X
  173. // DoIdentify- m* T: l: u# F8 p$ n
  174. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
    , I+ }: S6 J/ f+ s
  175.              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
    , i1 ]7 k; [  D# R( o. U/ p2 j
  176.              PDWORD pdwBytesReturned)
    9 W# @& m8 |, F
  177. {. }0 v+ w3 W1 h! v* l
  178.    // Set up data structures for IDENTIFY command.
    " d5 B3 N- ~" h" _, ^9 _$ ]
  179.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;- S4 R' [" A$ E: A& l
  180.    pSCIP->irDriveRegs.bFeaturesReg = 0;
    6 W% p# [/ T% p" \" ?
  181.    pSCIP->irDriveRegs.bSectorCountReg  = 1;
    / Y: N0 k1 q0 o5 @$ M! Y
  182.    pSCIP->irDriveRegs.bSectorNumberReg = 1;5 s1 U3 `' ~1 t5 \( h; A, z9 `
  183.    pSCIP->irDriveRegs.bCylLowReg  = 0;  R- f4 h# R% ^* W% {0 y) V
  184.    pSCIP->irDriveRegs.bCylHighReg = 0;& Y* p$ |( A; h( l

  185. 6 S6 D" c( I0 O, K& d
  186.    // Compute the drive number.(主盘和从盘所对应的值是不一样的)4 w; ~& v6 v# ]4 n  k# H
  187.    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
    9 Q0 ?8 D; [2 t

  188. 4 s5 u' w. f% s+ o! D
  189.    // The command can either be IDE identify or ATAPI identify.$ o4 G7 ?: [" s6 l; z: O
  190.    pSCIP->irDriveRegs.bCommandReg = btIDCmd;- S" t. P$ A' C: t1 S* A$ D' I
  191.    pSCIP->bDriveNumber = btDriveNum;8 O( R1 |0 o7 t+ t+ b8 N8 b
  192.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
    2 s; @% J: n; h0 e- ^
  193.   D9 L" s5 O$ m# Z* |/ U) I( m
  194.    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,/ G. U! X' d: p; c- U+ ^
  195.           (LPVOID)pSCIP,5 r) @( M& S* D0 ~1 x
  196.           sizeof(SENDCMDINPARAMS) - 1,
    ; o3 X; Z1 j) K/ n6 }" K
  197.           (LPVOID)pSCOP,
    : z3 e- J* H' |5 f: I' Q
  198.           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
    8 A3 Z, y; h2 X" O2 a
  199.           pdwBytesReturned, NULL);8 [  D* k, g8 J: A
  200. }
    1 _( j+ X3 p" V% V* q1 E
  201. //---------------------------------------------------------------------------
    9 v( g$ W4 S& w3 ]) N
  202. // Windows 95/98/ME 代码
    $ y# h! d' |5 I  G- n# i
  203. //---------------------------------------------------------------------------
    ! y# g$ Q. u! t: M  M/ ]* \4 s
  204. // ReadPhysicalDriveOnW9X
    2 w" N+ y" e: W
  205. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)' s3 Y! e( q# [+ B1 {2 c
  206. {1 A  w1 ?3 K- o# y9 f+ ^
  207.    WORD wOutData[256];% V1 ?: ]" `( e7 c# {
  208.    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
    8 ^* S1 I% k; O
  209. ) D6 X# t- n3 I; v4 ]9 r, G! g$ _
  210.    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
    , ~: h2 o! T, \( h0 [. E
  211.    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以( V6 ^& M+ H$ d# z. b. m
  212.    // 避免蓝屏的出现。(期待高人能指出原因)! G: b. D0 p4 e5 a
  213.    for(int nDrive = 0; nDrive < 8; nDrive++)
    9 S/ ^+ k1 r& q2 o
  214.    {: K; F9 Q, R2 h
  215.        WORD dwBaseAddress;
    9 g$ O& ?% s. e4 n1 b
  216.        BYTE btMasterSlave;         // Master Or Slave
    % F0 U/ L1 y' [6 U8 |) T
  217.        bool bIsIDEExist;+ O; `$ c$ m5 ^, A' b5 H* c
  218.        bool IsDiskExist;
    1 c9 X5 u5 t/ `  n6 w' W
  219. $ T4 i. t! B+ Y& [2 X- `3 e
  220.        switch(nDrive / 2)0 A, P3 c$ D6 o; j
  221.        {5 w4 ~- ?( z8 _2 m/ @, t' h" c2 m
  222.            case 0: dwBaseAddress = 0x01F0; break;
    . ]2 S& c) h1 e. D6 ~" |  y* U: _
  223.            case 1: dwBaseAddress = 0x0170; break;+ Q* g8 C$ t2 j+ k7 B
  224.            case 2: dwBaseAddress = 0x01E8; break;
    3 G! Q& l/ ]: o, H" ?
  225.            case 3: dwBaseAddress = 0x0168; break;5 @6 K/ q" S7 S
  226.        }
    & }9 r* a/ y+ X6 @) a6 W. T
  227. , B+ Y, I6 N7 l( x8 k+ o, R, \1 _6 X
  228.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
    % n7 a% ?5 U+ a- L

  229. " _9 D& p* e" y/ ?
  230.        // 进入Ring0) x) g# Z* e( l. `! z' L
  231.        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
    $ }( G( N! i* b/ G7 F' x" q
  232.                bIsIDEExist, IsDiskExist, wOutData);
    ) h$ H% W, H& }( Q& X, C9 T+ i
  233.    }
    ! p1 Y3 C) _7 c. G7 Y  ^

  234. 0 ^. t: L2 H7 e! G
  235.    // 开始读取/ l( q/ |) j+ r9 g
  236.    for(int nDrive = 0; nDrive < 8; nDrive++)
    9 `) |. k( ~* U$ Z7 A/ x* ~: f2 Y
  237.    {/ q3 Q+ s* e3 c. D( O7 e# s1 h
  238.        WORD dwBaseAddress;
    + C, l& h8 E: c5 N5 @
  239.        BYTE btMasterSlave;         // Master Or Slave
    # n) ?( v4 T, p) T
  240.        bool bIsIDEExist;
    ) ^& N( Y# H2 [
  241.        bool bIsDiskExist;, I! `; G9 q' ]* B. F1 Q$ A, l
  242.        switch(nDrive / 2); L7 k9 v" h' o2 Q7 e4 Q
  243.        {/ T5 S+ [+ Y2 R
  244.            case 0: dwBaseAddress = 0x01F0; break;
    : G0 h7 n: {: D5 [7 C2 n% b( h
  245.            case 1: dwBaseAddress = 0x0170; break;! E, o# R6 _0 M+ T1 L+ U
  246.            case 2: dwBaseAddress = 0x01E8; break;4 c5 G9 y0 J! C, p* z3 H: a& L6 B
  247.            case 3: dwBaseAddress = 0x0168; break;
    5 q1 D" W+ @1 h8 X# r8 i* g  @& y1 w
  248.        }$ ^3 f8 H( U% F4 n' E
  249. 3 Q/ h) m. F  o, R% F* u
  250.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);* w4 t" D3 }$ q* D

  251. ; [3 s+ Y4 L( }. F& F- k
  252.        // 进入Ring0. u- {; e0 y: A8 v9 B  C
  253.        bIsIDEExist  = false;  X* u1 g" z0 x+ A
  254.        bIsDiskExist = false;$ b. }" C) \0 X
  255.        ZeroMemory(wOutData, sizeof(wOutData));
    , _/ `$ l9 T2 {+ K7 I
  256. * i' Y5 K% P7 \: m' m% r
  257.        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
    6 o- \; _" q4 H6 V7 q
  258.                bIsIDEExist, bIsDiskExist, wOutData);# {4 f! d- S1 v9 `
  259. % K  s$ e8 X8 e' y: s9 f: f
  260.        if(bIsIDEExist && bIsDiskExist)
    - B. l7 a- [4 ^+ ]4 M
  261.        {7 n( V4 K% R  w; L
  262.            DWORD dwDiskData[256];
      }/ w4 E+ P: p$ Z+ s, T; d% i
  263.            char  szSerialNumber[21];9 W. J$ j1 C! v" H, ~3 U
  264.            char  szModelNumber[41];- Y- t8 }) c& f: l9 f' e6 E9 o

  265. : [* Z- y* {9 f" e$ b6 H
  266.            for(int k=0; k < 256; k++)
    3 J% d$ N7 D. ~. J
  267.                dwDiskData[k] = wOutData[k];  X7 Y: {9 Y6 X. h: ]2 |
  268. : H2 E$ L- q; |0 Y, w
  269.            // 取系列号
    7 B/ @/ K- M5 Z* K: S! i
  270.            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));' J7 q4 S& r7 n4 `4 C
  271.            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
    , b2 Z! x. |0 M8 p) [, X4 ]

  272. ' ~% b* `4 S3 O4 w+ B3 \
  273.            // 取模型号, D5 |( k( w. M/ |
  274.            ZeroMemory(szModelNumber, sizeof(szModelNumber));
    9 J# f+ \- K/ S# s2 l
  275.            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
    ; e; E/ x: t/ _

  276. , X4 w% G" W! ^; J% H4 V
  277.            pSerList->Add(szSerialNumber);, u  _; h: L5 q/ O" p: ~
  278.            pModeList->Add(szModelNumber);# q4 \+ n5 d9 j# {$ a' ]% q
  279.        }& j( J1 b6 O6 v
  280.    }
    # ^, q$ |- {5 r$ R; }# P
  281.    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);; R9 N0 S& {/ y. ?6 x6 V2 q
  282. }
    9 t% _; Z+ M, r6 }+ Z: ^
  283. //---------------------------------------------------------------------------
    ; F5 r3 @) o9 j) U/ e
  284. // ReadPhysicalDriveOnW9X_Ring0()& }# A& {; f1 V* W5 M$ Y+ U
  285. //8 F" f: H8 g& s6 l
  286. // dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
    2 N7 B0 I, b* C. K- j/ ^/ I; b! L
  287. // btMasterSlave = Master(0xA0) Or Slave(0xB0)
    - k2 m0 ^+ C$ A
  288. //---------------------------------------------------------------------------
    7 J7 K: `% d7 y: M' X% X
  289. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
    * m. l. y$ c, |" K/ R
  290.        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
    4 @& V3 P  x  v" S# J8 ]6 h
  291. {
    * _7 P% H( }- `; y7 d0 G& _
  292.    BYTE  btIDTR1[6];
    " J( K/ E( t$ Z8 q
  293.    DWORD dwOldExceptionHook;& o' I/ O2 t  J6 e, I  w0 l# Q
  294.    const int nHookExceptionNo = 5;
    ! w% [7 l; ~7 f) S$ M8 k5 e2 D
  295. 1 j5 d6 o: i8 [- t  _4 H) [2 d4 Z
  296.    BYTE  btIsIDEExist = 0;
    4 u, h6 ^/ F2 S2 x* C
  297.    BYTE  btIsDiskExist = 0;) a( z+ R9 H7 ^
  298.    WORD  wOutDataBuf[256];' [: k3 t& m& S0 }+ X9 l8 p
  299. . h7 u# N" K6 G
  300.    BYTE  btIsFirst = (BYTE)bIsFirst;9 I9 n; w5 l+ O5 l( i5 e- P
  301. $ W' Y! I+ k! f. g  m* j
  302.    const BYTE btBit00 = 0x01;
    ' n5 b; Q+ S, ]- w- e
  303.    // const BYTE btBit02 = 0x04;
    ( ]: J7 @2 L6 E2 y. Z
  304.    const BYTE btBit06 = 0x40;
    " W1 \) w4 N- ~3 [% o( a+ C$ h
  305.    const BYTE btBit07 = 0x80;/ ]- \! ^* G; |
  306.    // const BYTE btERR  = btBit00;
    5 h  o& }: |" A- R- Q3 h: `+ o
  307.    const BYTE btBusy = btBit07;
    % |1 n5 J# S1 @# D
  308.    const BYTE btAtaCmd   = 0xEC;
    + z* `# e4 I! ~! d8 r
  309.    const BYTE btAtapiCmd = 0xA1;
    + J  f/ J, n' o' r; N* E" ?/ W
  310. : G* `- O0 M9 X) M
  311.    __asm
    , H( n. l; q! Z0 e/ u* M1 I
  312.    {
    0 v1 a- t) ]9 ~: u- f3 H1 W' t, L1 ~$ v
  313.        // 必须先执行这条语句
    6 \0 x8 |) M! p0 R
  314.        JMP EnterRing0  i' U% O' p; I) Z1 `2 D

  315. 1 X/ C9 C( F  P3 @
  316.        // 定义过程
    ! J, J- J: r! V% F* r; C9 @$ H
  317.        // 等待IDE设备直到其不为忙为止
    4 }7 A! @' ?8 c
  318.        WaitWhileBusy proc
    8 t- [. z; q. j; T3 X

  319. & G# v* W/ l) E1 R& v2 {" J  ?
  320.        MOV  EBX, 100000
    5 x( G+ s5 c8 j& D  g$ }4 K$ e- o& h1 E
  321.        MOV  DX, dwBaseAddress( B' m6 N' y, ~, T: H4 m
  322.        ADD  DX, 7
    " E; c8 f% h- l" ^5 n0 c- @

  323. - _/ k# b. W# F
  324.        LoopWhileBusy:9 ~' ]. Z  ?) o# S, C
  325. : E/ x# m$ }: \9 d6 C7 R/ y
  326.        DEC  EBX
    6 K5 c$ l( K3 O9 _$ c( N& _. Y) Y* N
  327.        CMP  EBX, 0/ V% j: ]8 v4 {& H
  328.        JZ   Timeout
    ) m5 X. J& F; A. `9 H3 z' J2 N3 O- S
  329.        in   AL, DX
    5 p$ |+ e6 v$ F/ m/ G1 N
  330.        TEST AL, btBusy
    ' S' c# U( U( G- z% W0 i
  331.        JNZ  LoopWhileBusy
    . g2 S7 ^) C' u  z1 ?4 K
  332.        JMP  DriveReady- V# s% H4 z3 @) T- @% l

  333. + h; p3 j4 w% l5 n' X$ P- r+ I5 U$ z* t
  334.        // 超时,直接退出
    ) ~2 Q$ R4 K2 n7 U& B, |( g
  335.        Timeout:
    4 }0 F7 {. u1 G6 d: y/ z
  336.        JMP  LeaveRing0
    + c* M/ k9 c! j
  337.        DriveReady:# v7 b7 A1 J/ W- x* u6 F* m
  338.        RET8 M3 K2 L' W0 f" N4 e+ j& |
  339.        ENDP   // End of WaitWhileBusy Procedure8 u9 C( @! U, j! B$ r) ?7 y

  340. 0 n1 T( l* _% u8 L' d
  341.        // 设置主盘和从盘标志
    + Q9 M; S# ]. c. V; j
  342.        SelectDevice proc
    + S8 r" H: z0 T* Y
  343. & m8 E2 V" G! g# i  [
  344.        MOV  DX, dwBaseAddress
    - J- ?1 ~* W: w; t
  345.        ADD  DX, 6- m  C! X, }  e5 Y5 G
  346.        MOV  AL, btMasterSlave
    , ^, ]+ r$ I( U/ s$ v
  347. ) w& q7 U* x6 I- E8 D4 A- y$ L
  348.        out  DX, AL; W( Q7 Q. a* o- T2 U8 b5 v
  349.        RET
    0 T- A/ V9 G0 E8 t+ S5 Z
  350. 5 h: [& J/ M- K3 s) a4 {
  351.        ENDP  // End of SelectDevice Procedure5 J* R5 n1 k2 i! B9 B8 ^) i
  352. ) `1 C: q0 p( Q
  353.        // 向IDE设备发送存取指令2 Q  r% k9 d; Q! \3 ^$ D. _
  354.        SendCmd proc
    - m/ u1 X! z' ?' U/ q1 w
  355. 9 b3 U2 P" W5 i' ^6 G
  356.        MOV DX, dwBaseAddress
    : h. V3 Y# B0 m0 r' J' [
  357.        ADD DX, 71 A# u( u9 c$ _/ A
  358.        MOV AL, BL // BL是主从盘标识,在过程外设置$ a: C  @  a2 E5 r
  359.        out DX, AL3 j; y2 G1 R) Z! A3 d  Q
  360.        RET: s8 ?0 v* X% n3 j  n- G
  361.        ENDP  // End of SendCmd Procedure
    " X! M; n4 f; f& D% o) H9 b9 p

  362. / V2 Q, y" O, J- H; D. _( x
  363.        // Ring0代码, A( R& q& K+ @6 P5 o6 O
  364.        Ring0Proc:
    6 y; [" w! ^' S$ ]
  365.        PUSHAD! Y! J$ A3 E$ T, V4 l0 E% S
  366.        // 查询IDE设备是否存在
    " E/ f2 ?/ j/ f1 m# Z' m# o# \
  367.        MOV DX, dwBaseAddress
    0 Y. I+ J  W4 v
  368.        ADD DX, 7
    # `" w' @. a6 G: S1 x
  369.        in  AL,DX" W0 A) s5 \: M5 @: ^/ V& D# n

  370. ( V/ d' y6 u* S$ g+ [
  371.        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回$ L! c4 O: D, `+ Y; k- w# H9 `" W
  372.        CMP AL,0xFF  }6 D/ I( O4 `
  373.        JZ  LeaveRing03 j! k, y( A4 ]1 ~+ M" f1 L
  374.        CMP AL, 0x7F
    1 S* ]4 I; }6 c/ u5 o+ _) Q: l0 X
  375.        JZ  LeaveRing0- v, f1 Z/ m* P2 w1 _8 t  Q) k% Y

  376. : e9 j1 I( L6 u- X6 `3 U. e  S
  377.        // 设置IDE设备存在标志; y( a8 ?5 @' O$ ^0 t
  378.        MOV btIsIDEExist, 19 b$ m+ d$ u) y% H1 d8 t

  379. 6 y) S, Z, I' r# T# g+ P
  380.        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
    + a' u. K+ k$ S
  381.        CALL WaitWhileBusy
    # i, G. |( l4 I$ j6 O
  382.        CALL SelectDevice
    7 w; s# A) }# k! K2 ?& l6 X  O$ |
  383. " f& Q3 u6 M4 Q4 v
  384.        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
    1 u4 t7 O- c" D+ M
  385.        CMP  btIsFirst, 14 b, c+ j' K3 E' T# D" J
  386.        JZ   LeaveRing01 ^6 u7 N0 I2 G7 P9 S& }3 @& i
  387. 2 _+ o7 z7 R2 l' P+ t
  388.        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
    , o- [3 g4 g/ ~5 |  P  r
  389.        CALL WaitWhileBusy5 f5 n. p. i( _6 B: `: o

  390. * \* r$ Q. O& O, D' v) _
  391.        // AL的值等于cBit06时,不存在驱动器,直接返回7 s3 l+ C1 P7 N
  392.        TEST AL, btBit06
    7 p" k0 N: g" b/ U8 {6 [  P
  393.        JZ   LeaveRing0/ _- }/ b; H  h, M

  394. 6 |4 \3 B  W" g+ P5 m! d) N3 _3 o  q
  395.        // 设置驱动器存在标志+ a% w* [! n5 W+ {" p, Z8 m4 [. V' t2 ~
  396.        MOV  btIsDiskExist, 11 c) J4 g' H# V

  397. + B5 p0 w" g9 {/ K* ?3 x. i
  398.        // 发送存取端口命令  M: p$ R7 D: v  I
  399.        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,8 z3 s% @" O, o) ]+ _
  400.        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
      ?/ l; k" i9 A# x7 H: u
  401.        CALL WaitWhileBusy
    0 T: B  w3 |. Y3 G- G' j
  402.        CALL SelectDevice    // 设置主从盘标识
    . }6 `7 @& u  }4 ^
  403.        MOV  BL, btAtaCmd      // 发送读取命令% B( w9 d* Z; f" }( w3 d/ \$ N
  404.        CALL SendCmd
    ! L5 H: p8 q# h8 ^
  405.        CALL WaitWhileBusy+ _$ C. m' @2 f" R+ @* O5 T
  406. - |- L7 L5 y; N/ V) H4 k
  407.        // 检查是否出错
    2 j  p/ Q7 V$ u
  408.        MOV  DX, dwBaseAddress9 b+ @$ L2 G( Y; W" T
  409.        ADD  DX, 7% T  G" {  z% x# x$ n8 l, t

  410. ' ~2 Q; g& |" M9 b& E& j2 z
  411.        in   AL, DX
    9 ^7 L. D4 g. w% c4 X
  412. , m3 f1 o' j7 I4 Q6 S9 m5 X
  413.        TEST AL, btBit00, N9 {: B7 P% `3 a. Y/ k+ \- C
  414.        JZ   RetrieveInfo   // 没有错误时则读数据2 K. Y  {2 j0 T3 A
  415. ' e5 G+ u% z3 q! p# Y
  416.        // 如果出错,则进一步尝试使用ATAPI设备命令
    ) L. \' Z: m/ g
  417.        CALL WaitWhileBusy
    % _/ J0 J$ B- h1 s
  418.        CALL SelectDevice
    4 v% V6 ]3 h8 C# L
  419.        MOV  BL, btAtapiCmd( Q3 Q; |3 {9 T  p9 I% f. D. D
  420.        CALL SendCmd$ C8 t; y; H- Z  q) c# }
  421.        CALL WaitWhileBusy
    . K6 m4 k1 d# w: m3 t0 J

  422. $ }7 B4 M/ _, u' I& I
  423.        // 检查是否还出错' m! G' m4 H! X3 y$ C
  424.        MOV  DX, dwBaseAddress
    6 b' F$ z+ j8 c- k9 m7 Z) f4 ^
  425.        ADD  DX, 7
    ! b- V! X2 m6 |7 r
  426.        in   AL, DX
    " Z# J/ G$ q4 W4 n
  427.        TEST AL, btBit00
    1 P: c% u& g7 X/ i% m% Q1 z3 }
  428.        JZ   RetrieveInfo   // 没有错误时则读数据
    5 e% P4 j: u/ ^
  429.        JMP  LeaveRing0     // 如果还是出错,直接返回8 a; V% e  g0 a. S! J3 `$ [
  430. + k, y3 M- I" @
  431.        // 读取数据
    % T6 P8 ~0 I0 g& [7 l1 a6 t
  432.        RetrieveInfo:
    9 ^3 @7 Y' F9 f% v5 W* D; D( V
  433. ! I  Q  Z  W0 N  D# \/ b- k
  434.        LEA  EDI, wOutDataBuf
    4 m$ j2 \1 f1 X& N
  435.        MOV  ECX, 256
    : H9 u$ L% j; J' j# K% Y: f+ G
  436.        MOV  DX, dwBaseAddress
    0 {& b: V" h- M3 L
  437.        CLD
    / j+ B' }2 R& B: l, L
  438. 3 D- ~$ x6 e  D6 ~3 g# i# x
  439.        REP  INSW
    - p9 ]- o8 e# o8 U! A! o

  440. 7 j8 G0 `) w! R
  441.        // 退出Ring0代码
    6 ]  |0 L6 q0 M. F& m  s/ `# C( w
  442.        LeaveRing0:3 e* D+ x; u. c9 Q/ J, E" @" u5 R7 h: L; j0 w
  443. ! j3 Y9 {- `3 B& z4 A, `
  444.        POPAD, }1 j% T  N! L/ L0 Y% L' O2 P
  445.        IRETD) m6 T* v4 a% a" ]! z
  446. 7 c! o! z, O0 V1 y3 T. G1 M7 H  m' G& U
  447.        // 激活Ring0代码2 }& |7 \  [; r3 S5 n' }; n1 N
  448.        EnterRing0:. W1 m/ {$ t. f( J& N& u

  449. ) L8 E" Z( U+ u5 t
  450.        // 修改中断门
    6 z2 D# {2 P% b# b2 W9 ^. W/ T; z8 l
  451.        SIDT FWORD PTR btIDTR1
    5 B4 r8 {$ d! L
  452.        MOV EAX, DWORD PTR btIDTR1 + 02h/ `- p9 m5 z, @1 o/ o
  453.        ADD EAX, nHookExceptionNo * 08h + 04h/ C2 t* N4 W8 o: O) q+ @; Z; ^3 O3 w
  454.        CLI  b, W7 V8 C$ _

  455. : S8 g7 I1 m4 w! e0 {9 Y% S' b
  456.        // 保存原异常处理例程入口
    6 j. d/ N3 g1 h( ^  g
  457.        MOV ECX, DWORD PTR [EAX]
    ) U# \8 E8 A; Z- Y, P& U  G; u
  458.        MOV CX, WORD PTR [EAX-04h]( f1 c; U) l. X  g; N
  459.        MOV dwOldExceptionHook, ECX- u/ r! R  i: m1 g) d* G. y" d
  460. 7 @# [5 n& c1 A3 t
  461.        // 指定新入口
    1 E1 {$ s; y* h2 a% f, X" ^. f
  462.        LEA EBX, Ring0Proc
    % n, _( q- c# f9 @, z9 X) u+ H3 m
  463.        MOV WORD PTR [EAX-04h],BX# U  U2 F. t* i' Z0 k% c) U9 {
  464.        SHR EBX, 10h
    % K5 V% E& Y5 X( w$ a
  465.        MOV WORD PTR[EAX+02h], BX, [' e, r4 ^2 T) A, \
  466. 4 ?; \6 D2 s; c0 {) e/ c
  467.        // 激活Ring0代码
    % x$ f6 f1 P' _) \% F. b+ J  H
  468.        INT nHookExceptionNo
    ; Y9 |% p6 c8 f; k$ |( \

  469. ) C, B  [( M) T5 B9 `# e
  470.        // 复原入口
    ! C3 W1 b( A& ~( _
  471.        MOV ECX,dwOldExceptionHook" j; y# _# n/ Z9 `7 u0 D
  472.        MOV WORD PTR[EAX-04h], CX8 H$ Y3 R8 j4 l9 z( j- B4 b0 G
  473.        SHR ECX,10h
    # F" h- i' h. A1 H
  474.        MOV WORD PTR[EAX+02h], CX0 p! X& |$ N+ m+ Q# o5 k3 p1 Q8 c
  475.        STI
    0 q* {* n! r% F
  476.    }
    6 f  B. ?2 `. d# `
  477.    if(!bIsFirst)
      D3 p/ k7 {  e- z& D' f; V3 W
  478.    {! h- l. n( y# q' q% v
  479.        bIsIDEExist  = (bool)btIsIDEExist;* M7 @; C( @7 T  B; E9 T
  480.        bIsDiskExist = (bool)btIsDiskExist;' P% `* G2 J7 ~5 G
  481.        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
    ( A# U2 \$ Y8 l
  482.    }
    6 K# D. w0 m9 R( D: e
  483. }
    ( A( r2 x( o. y" U( R
  484. //---------------------------------------------------------------------------
    . ^) N7 h5 Y4 A
  485. // 调用方法:+ J" q  m( V+ t$ \( L
  486. void __fastcall TForm1::Button1Click(TObject *Sender)
    6 X. d% P2 ^# _- M! x6 r: r
  487. {
    / _$ I) j! A9 C7 }! k
  488.    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
    ; S6 n* |  x% Y
  489. }
复制代码
发表于 2005-8-15 01:00:45 | 显示全部楼层
晕乎乎。。。怎么看8 洞阿
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-5-2 10:35 , Processed in 0.022219 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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