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

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

[复制链接]
发表于 2005-8-11 11:42:04 | 显示全部楼层 |阅读模式
  1. #include <WinIOCtl.h>
    3 D: U5 K8 X% n; q$ Q! K
  2. #include <stdio.h>1 K. m4 m4 [; K1 E

  3. ! Q  e" v8 H; e# y8 Z2 @
  4. #pragma inline( G( D& i  t, S# ^% ?& q% _
  5. //---------------------------------------------------------------------------
    + |4 Z% n1 r- l- z9 I( _8 {
  6. // IDE NT/2000/XP专用变量
    . B0 d- i* o/ n  A% r) T) f
  7. #define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS/ F: y5 ~4 R4 O+ a
  8. #define DFP_GET_VERSION         SMART_GET_VERSION
    ! O7 w; B8 {4 D# ]3 r  M3 t
  9. #define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
    $ i8 N0 s, Z2 [& N# T% A" ~
  10. #define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA# l' f& I! L1 }* B) `5 Q

  11. 7 F% I- f1 X) q$ Y3 O
  12. const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令
    . f0 p5 h& ^% v
  13. const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
    + W# G- f1 E( }8 f0 n( y
  14. . p5 {5 I. m- A6 M3 u
  15. const int MAX_IDE_DRIVES = 4;1 x. p( P: `% _) M* Z5 I
  16. ) v$ j! ~0 x  I
  17. // SCSI专用变量$ ]9 H! L; b! R# o1 Z+ ?
  18. const DWORD FILE_DEVICE_SCSI             = 0x0000001B;
    / W1 S* u- w$ C: w: z- w3 H
  19. const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
    5 N3 t$ e) D# {  a8 `6 M7 ~
  20. const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
    . y$ m% t6 t* b( y* U( p
  21. const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;, ^( ?$ n) A1 X

  22. 5 y; Q4 N7 I! m5 m4 S+ |" I5 h
  23. typedef struct _SRB_IO_CONTROL
    * J! K' x3 B: N: A
  24. {
    . G6 i+ p6 _/ f. }4 T+ t
  25.    ULONG HeaderLength;: m0 x& v9 F% E  a
  26.    UCHAR Signature[8];
    . `5 {+ R8 k4 v! Y
  27.    ULONG Timeout;
    / w+ L$ W# }  [' F7 o
  28.    ULONG ControlCode;
    & Z2 T2 d% ?4 f3 G" M* [
  29.    ULONG ReturnCode;
    1 n. h$ D# ^3 c
  30.    ULONG Length;
      K5 t  [# z+ |" F; ?" _0 c4 G/ O
  31. }SRB_IO_CONTROL, *PSRB_IO_CONTROL;
    & r+ _0 s6 v* l9 u

  32. * W8 [1 w% F" v. z6 a
  33. // 读取的主函数4 G7 d  j3 |) a+ M3 d
  34. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);  E" h( v8 I3 L* H% T# `. @
  35. - q# l: h: q- g* Q3 d
  36. // 辅助函数* W3 d. f9 _. V
  37. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
    2 M- Q' w5 e5 j6 D) M( }
  38. // NT/2000/XP函数
    6 B+ z7 [1 t& s. F( a1 N
  39. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);2 h$ C9 y% z, p; c9 Z/ W
  40. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
    + u; U6 f1 k' a
  41.        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,8 |- G9 {9 P: S9 y* S% Q1 W4 G
  42.        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);( E' S4 R" |+ T) H4 t
  43. // Windows 9X函数. Y" t4 o. i' s1 q7 M6 ]$ Y5 Y: A; v. t
  44. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);3 _: ]- ^& @# t% x8 A$ R
  45. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,! s$ ]5 T% ?8 _+ a, Z" i* y
  46.        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
    , H3 q: x9 V) y  g# U2 {

  47. 4 A3 k0 K: l, Q
  48. // SCSI读取函数(for NT/2000/XP)
    2 G9 t0 \  _4 U
  49. String __fastcall ReadIDEDriveAsScsiDriveOnNT();
    & v; M( d! I6 S" W
  50. //---------------------------------------------------------------------------
    $ j( m9 I8 f2 m$ I$ l# u1 p! U
  51. // ReadPhysicalDrive+ `8 u7 E5 ?/ L9 T) X+ |5 \
  52. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
    & D1 `2 L0 T5 r- s
  53. {
    $ r, l! [  J' c6 [0 |; h
  54.    switch(Win32Platform)( Q/ U4 V- X" c) v& t
  55.    {1 a2 A# c. m' S& w# w. c4 y
  56.        case VER_PLATFORM_WIN32_WINDOWS:
    : |6 l% e( W- M8 R( s  c! D1 z
  57.            ReadPhysicalDriveOnW9X(pSerList, pModeList);, k2 s. T/ k  R1 D, o; a0 _
  58.            break;& q9 }$ a& b- R$ A2 E
  59.        case VER_PLATFORM_WIN32_NT:
    / B' b: G8 }1 `' X2 I4 G/ e" e
  60.            ReadPhysicalDriveOnNT(pSerList, pModeList);
    % m- D5 a$ }$ x! `
  61.            break;% O# f- m& @% t
  62.        default:
    % P& I/ B" ]# m5 }; U4 c
  63.            break;* q6 t& e% `1 v& m: h
  64.    }
    # ], k. r% P# A8 q3 T& m. b
  65. }0 t, t5 Z( ~' F$ |( \- y; g, ?
  66. //---------------------------------------------------------------------------
    9 X" y) s( s& e
  67. // ConvertToString
    ) e& l+ d& |" h# h+ O9 s2 R, }
  68. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
    + v! d, Y( j) F/ |) z
  69. {$ F+ Z/ r/ O, u# e( G! u8 `6 v' a
  70.    static char szResBuf[1024];% N; d. h% a! c4 e" u" ?: \
  71.    int nIndex = 0;) H1 J$ ^2 H( V8 e- ~* m7 a
  72.    int nPosition = 0;2 F# @! i" C" L' P, Y' |

  73. / f) z4 K/ D4 \7 I2 F
  74.    // Each integer has two characters stored in it backwards5 e4 m6 d- ?6 f, U: g' j4 W  T
  75.    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)1 H1 t. p6 G6 k2 p
  76.    {7 D% o6 v; n) @8 _' L4 O1 c* j. I
  77.        // Get high BYTE for 1st character
    , r3 o" a  d; ^1 j: j0 @* W' b
  78.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);  H9 u  i' l$ P1 O: v& o9 P
  79.        nPosition++;
    / [, k# k* O  t0 s* b- p
  80. + H' c" e  [  y5 Q$ \* x4 E
  81.        // Get low BYTE for 2nd character
      m0 D) B" `9 V/ m- i
  82.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);4 j4 ]! P" k, g' c% S5 x
  83.        nPosition++;
    1 M8 e, @' l6 O5 U
  84.    }. z1 ?! `/ |& \2 {6 W( D. U

  85. + @: ^" u4 Z2 D$ J( T
  86.    // End the string( d$ S# f1 i( a$ y" K
  87.    szResBuf[nPosition] = '\0';
    1 |- m4 l7 t: m; S" b1 \4 G! F

  88. : Y: d7 J/ T  W/ a% `! r+ ?! K9 I& f
  89.    // Cut off the trailing blanks# X6 w3 X: j% v- t( ^- d
  90.    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)+ P" |  y7 @5 l' Z7 ?% }
  91.        szResBuf[nIndex] = '\0';( Q+ j+ b6 P  ]4 F: N

  92. 3 p* Z9 ^9 w; y0 n; \" J
  93.    return szResBuf;- V8 g2 [* G, Q+ w/ O
  94. }% Z/ v  p% `7 F! _* g! `
  95. //---------------------------------------------------------------------------
    8 f3 D' ?: B, P2 t
  96. // Winndows NT4/2000/XP 代码1 a0 }9 N: Y- P! Q( |1 `  b1 n
  97. //---------------------------------------------------------------------------/ h4 l/ Z3 v7 |" O; F
  98. // ReadPhysicalDriveOnNT
    , n: X) P) C  _; x. w7 H
  99. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList): B! `& b* V/ ~# e( y' H
  100. {
    - J: L2 U, P! Y9 B& \2 x
  101.    // 输出参数, F, Z$ c% f9 h) ~
  102.    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
    8 Z6 A4 }# d6 ?9 F3 X; k
  103. 9 [1 g9 _2 @' O  E
  104.    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
    $ T/ c; {: \# {
  105.    {* [4 ~" z( ^( S4 \) t! J
  106.        HANDLE hPhysicalDriveIOCTL;
    + `( E" b7 h1 t3 [" ^
  107.        char szDriveName[32];
    3 _2 t) O' K5 P3 B' Z& u7 H/ |

  108. ( m0 t6 }, [- B0 E6 r: m2 [5 z. v  u
  109.        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);5 M6 w- A4 P% J  T- T: W6 ^2 t
  110.        hPhysicalDriveIOCTL = CreateFile(szDriveName,$ }$ t$ F6 \( k3 k- ?( p7 l1 e
  111.                        GENERIC_READ | GENERIC_WRITE,* [. D1 w* o- X& g1 L/ ]8 s
  112.                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,( Y. x" ?0 z* J6 S! D
  113.                        OPEN_EXISTING, 0, NULL);
    3 R4 x: k- k" ~7 |  d+ n
  114. - k$ t" g# ?9 z4 p* Z2 s
  115.        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE); X1 b7 M& G( U+ r: n; f/ F
  116.        {
    6 D0 W2 P/ a. q1 N7 a/ `
  117.            DWORD dwBytesReturned = 0;
    - }( f4 S  T; \/ g9 c/ R0 v2 [* D7 K, a" p: N
  118.            GETVERSIONOUTPARAMS gvopVersionParams;" C: Q! v& |: Q5 Z8 E/ i! T$ F% U
  119. ( C. w2 b( Q- z
  120.            // Get the version, etc of PhysicalDrive IOCTL
    0 }' ?1 h9 r" ^, S+ Q8 J
  121.            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));3 n/ n8 ~% E( m# G( j0 N! R$ Z

  122.   e' g3 h$ e' `+ j% |3 }
  123.            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,* ]9 R( R1 \$ F  ], L( l$ i
  124.                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams)," U, m0 z- W  b4 w5 O4 J
  125.                    &dwBytesReturned, NULL))* k" p6 p8 y( s( y) C$ N0 U( t
  126.            {- K& a0 c0 ]9 N5 `
  127.                continue;- r; s+ m/ e# D, j2 _" V
  128.            }
    ! P& x. @: g0 e* u8 y

  129. 3 h5 O* J# }8 ]" w" C
  130.            if(gvopVersionParams.bIDEDeviceMap > 0)6 a- P; q/ B7 T9 H
  131.            {. n1 k0 A9 I5 `. w: o, @9 U
  132.                // IDE or ATAPI IDENTIFY cmd7 R) ~; X$ q* j; |7 x
  133.                BYTE btIDCmd = 0;9 t1 c0 `" n$ q
  134.                SENDCMDINPARAMS InParams;- c, e8 A8 P& [) m/ L% ^# T5 H
  135.                // Now, get the ID sector for all IDE devices in the system.+ V2 |1 W1 H9 Q9 U7 T
  136.                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,* ~0 a) O7 R7 o. h  Q5 _
  137.                // otherwise use the IDE_ATA_IDENTIFY command
      G5 E& l: q$ O$ m0 y) [
  138.                // 具体所得结果请参考头文件中的说明
    + ~- _# v. B2 q* M5 p
  139.                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?( C) Q; N" ]3 e
  140.                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
    $ V! i2 ]; m5 {( A. z
  141.                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));" ?" i$ z( S. L" u) `5 x& O6 G
  142.                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
    8 J5 x+ n; A3 x) U2 o2 B

  143. 8 A5 ]; H! k9 l
  144.                if(DoIdentify(hPhysicalDriveIOCTL,0 \7 M' h5 G, m0 c- g; P6 }
  145.                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,& i& a) y9 }$ R/ J
  146.                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))! j$ [. a) u  ]- B7 v9 R  A3 A
  147.                {
    1 a& S. U* x3 g6 ?0 X1 e
  148.                    DWORD dwDiskData[256];
    5 r8 _" g& k2 {
  149.                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
    % ^! w" k% x. w& v. H
  150.                    char szSerialNumber[21];
    * b2 `! V. b4 n
  151.                    char szModelNumber[41];  t1 D1 S* h, A; A

  152. - @' a1 j* C: k( T
  153.                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
    0 Q# z$ ]# X& N9 h" O/ K+ j6 M0 @
  154.                    for(int i=0; i < 256; i++)
    9 n3 o* m$ G! m/ u! O; ^
  155.                        dwDiskData = pIDSector;
    0 r" `1 R2 m) `
  156.                    // 取系列号3 o6 V/ l" x. {. E( Y
  157.                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));) N& V# ^7 F' ^  _
  158.                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));# w) k+ t! L8 q+ h3 o3 `* @8 o+ N

  159. ( U  A% {' Y8 o9 {& j: V& p/ h; r
  160.                    // 取模型号2 X( D6 m& F! G6 ?
  161.                    ZeroMemory(szModelNumber, sizeof(szModelNumber));3 ?( |* U+ n) ^9 W5 z
  162.                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));$ ~7 d1 i- d6 e& E* u

  163.   R3 }- N' ]: m- @; e  j$ T
  164.                    pSerList->Add(szSerialNumber);% O. r2 N# W9 I3 E, D/ {$ m9 {
  165.                    pModeList->Add(szModelNumber);7 e, A0 E% l. L4 `' K
  166.                }
    / V4 e9 O6 V' y7 k( F
  167.            }
      I- Y6 U4 F  ^( D2 r$ c# ?+ t# S
  168.            CloseHandle (hPhysicalDriveIOCTL);
    6 O6 {' A# x  e3 m
  169.        }/ O" I4 O2 p% e" C
  170.    }
    % n* r0 X, Q  ]+ P2 P
  171. }
    ' D" C: ^& b0 y/ Z3 X  z
  172. //---------------------------------------------------------------------------9 N5 w  n2 q5 x& [5 B3 e# `
  173. // DoIdentify8 ?" O; J" k. \
  174. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,  V* n) s0 i# t: M! A  z. B5 E& m
  175.              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,/ k! d# ?, j: U9 }- z% P  p9 S0 s* X  w
  176.              PDWORD pdwBytesReturned)
    & e5 w' A- z/ A) v- x
  177. {
    2 a/ f# b( _7 |* {. S
  178.    // Set up data structures for IDENTIFY command.
    + J+ i5 e1 O+ T* i" A+ z- ^
  179.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;/ c; l9 \' q) b, h4 N, F/ m7 @
  180.    pSCIP->irDriveRegs.bFeaturesReg = 0;" R3 T8 H/ O  A, Z" v, C
  181.    pSCIP->irDriveRegs.bSectorCountReg  = 1;
    . A" Q7 E6 |! k1 C5 H
  182.    pSCIP->irDriveRegs.bSectorNumberReg = 1;, T. J0 p! _  v0 P! z# s; H
  183.    pSCIP->irDriveRegs.bCylLowReg  = 0;
    9 J( n& S2 t( v( k
  184.    pSCIP->irDriveRegs.bCylHighReg = 0;; Q: S5 V4 U% j' ^
  185. 4 H4 J; t0 L- Z: J/ [; K
  186.    // Compute the drive number.(主盘和从盘所对应的值是不一样的)1 B8 C# f( P& {# ^" t/ w
  187.    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;: i6 G" j# l" U8 H. F5 B$ E4 Q
  188. 3 E" [; B5 y* u8 L! I
  189.    // The command can either be IDE identify or ATAPI identify.
    / Q  s# j. c& I
  190.    pSCIP->irDriveRegs.bCommandReg = btIDCmd;) ~0 Q7 N& K6 j/ o6 I
  191.    pSCIP->bDriveNumber = btDriveNum;% m6 q/ Q; a, T& F/ d
  192.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
    * o. L! B4 ^6 k+ `

  193. 2 w4 V/ f& D9 W
  194.    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
    4 T$ z. o% P9 e& J" i
  195.           (LPVOID)pSCIP,2 B7 N- K. J. x" V. N  x. X
  196.           sizeof(SENDCMDINPARAMS) - 1,0 _( y8 _+ w+ ~
  197.           (LPVOID)pSCOP,
    " ]3 p0 t# H& ^
  198.           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
    ; ]# p) y# x4 ~3 u) W
  199.           pdwBytesReturned, NULL);0 c) F! l# \4 v4 N
  200. }
    $ |3 h; v& l- H/ O' T: Q% l
  201. //---------------------------------------------------------------------------
    7 y3 _& l" l( v7 A& j; [
  202. // Windows 95/98/ME 代码
    / U; ?3 L6 d& I! u; P
  203. //---------------------------------------------------------------------------0 M6 F  J# r' w7 |! @/ D
  204. // ReadPhysicalDriveOnW9X/ P% c" k, D# v4 Z* _* O6 P
  205. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)& x; Z' E% e3 u0 c
  206. {! n6 E* _; Y- N9 v  r# ?3 m! r/ @% {
  207.    WORD wOutData[256];
    & w  H' v% T0 Y8 a4 z9 r5 B$ ~3 f
  208.    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);2 b; y/ k. D& K
  209. 5 l  q8 P% N/ A# p  w
  210.    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。. {+ [( r/ m& ^9 z
  211.    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
    , t; }7 ~  e2 I2 l5 L
  212.    // 避免蓝屏的出现。(期待高人能指出原因). j7 x% s. ~, ~  F7 H# C+ Q0 R
  213.    for(int nDrive = 0; nDrive < 8; nDrive++)) e* p* K( k% c9 Z
  214.    {" j+ z0 q% O! M# F" g4 i
  215.        WORD dwBaseAddress;
    ! {' b  r; F$ h' ?  j
  216.        BYTE btMasterSlave;         // Master Or Slave: H* I+ B/ p/ K1 T
  217.        bool bIsIDEExist;( t2 {+ D* R$ N* y, N7 u$ j' V9 i5 I
  218.        bool IsDiskExist;
    , E' z. M# H2 I: [) Y) B7 x4 W3 Z

  219. , ]- L9 r& n4 u- p
  220.        switch(nDrive / 2)
    ' A. g7 G( @1 I' T3 K( l( B/ X: ~
  221.        {
    / y& O- F& f: `, }* L
  222.            case 0: dwBaseAddress = 0x01F0; break;+ U5 w3 j" c. G# l: @5 D
  223.            case 1: dwBaseAddress = 0x0170; break;
    ; r0 A4 s3 w4 u  M" L
  224.            case 2: dwBaseAddress = 0x01E8; break;7 t4 V$ G* w2 f$ ~) S, A; C# y# _
  225.            case 3: dwBaseAddress = 0x0168; break;
    , N8 G/ `: g5 \6 ?
  226.        }- u$ R' A( G0 B! O$ }
  227. , @% T; Q8 ?6 M/ r
  228.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);) t+ N; ?# n" m" J/ m, H' [: x8 y

  229. + {+ ]1 P& b& f5 z! N: `- o
  230.        // 进入Ring0' d. i$ m8 M- B5 D
  231.        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,# z9 R/ D2 n) K% ^' h& L# K( {- e3 a6 f
  232.                bIsIDEExist, IsDiskExist, wOutData);
    . F, c/ a9 Y  q2 B3 q
  233.    }$ y8 E: E" |0 s$ k4 R0 [
  234. * i- t6 ~1 j1 H) t2 x. S1 d) F0 R
  235.    // 开始读取
    6 Q* }" `) V2 B5 o; l8 n
  236.    for(int nDrive = 0; nDrive < 8; nDrive++)
    4 A2 K9 K) G/ \/ @" \9 S) W( D$ ~
  237.    {' l3 f3 E, X; l2 `. r% D2 q
  238.        WORD dwBaseAddress;
    * c& w4 C" Z( O" B/ F9 D( V/ _2 |# c$ u
  239.        BYTE btMasterSlave;         // Master Or Slave7 Y4 w+ @, P$ D9 L! @
  240.        bool bIsIDEExist;
    & K' @  V" W6 j7 \2 @2 ~2 D0 e* d8 ?
  241.        bool bIsDiskExist;
    * ^3 x& v! }* K9 S' H
  242.        switch(nDrive / 2)
    5 W# t% r7 A9 g0 {' K1 b9 I6 E
  243.        {. a$ S+ @7 y% k
  244.            case 0: dwBaseAddress = 0x01F0; break;
    - z7 z- T& F+ w3 E' O# X/ g  s- q
  245.            case 1: dwBaseAddress = 0x0170; break;
    3 `* U# |: b4 x' ^" Z) h
  246.            case 2: dwBaseAddress = 0x01E8; break;
    ( S) k4 b# ^6 `3 {, t. M
  247.            case 3: dwBaseAddress = 0x0168; break;
    / h+ \- V  T+ `3 @9 c6 w% w
  248.        }
      _, `" t8 C1 e' W
  249. ! Z  n$ w0 J3 E" G3 z3 H
  250.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);9 J& F' k  q" q1 b) G" ?
  251. 5 ^' ]' }7 q# L; b
  252.        // 进入Ring0
    1 I4 w& G% e' N( `8 D" D: Z
  253.        bIsIDEExist  = false;
    , c# O# {# P: T# q/ X1 f5 d
  254.        bIsDiskExist = false;( ^( C" s" B) N3 _( h
  255.        ZeroMemory(wOutData, sizeof(wOutData));9 S" \, Q0 S4 P7 j# d

  256. : p7 K7 m* l9 a8 Z; o
  257.        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,1 ]. }# ~# H" S) B
  258.                bIsIDEExist, bIsDiskExist, wOutData);2 N4 l9 t% L: @) l7 e
  259. , o6 \+ r! E0 P
  260.        if(bIsIDEExist && bIsDiskExist)
    * r; F) o1 M3 Q( s# n4 v, c) S4 u
  261.        {4 H- M% A# J* ^6 T/ B) k: {, v
  262.            DWORD dwDiskData[256];9 X4 G! p: }: C, y
  263.            char  szSerialNumber[21];1 x5 }, S' t0 q9 Q5 z4 r5 V
  264.            char  szModelNumber[41];# U) \: v* w/ v0 U  ?& O7 [! F8 k
  265. # R# d) n6 p  H9 n5 w) @
  266.            for(int k=0; k < 256; k++)7 ~# m# j6 U  e4 A" o; L
  267.                dwDiskData[k] = wOutData[k];" {1 I9 P6 v: [2 o

  268. ; ~6 D) w* K+ U: m
  269.            // 取系列号
    / o2 ]) q! Y7 E* I2 O( p+ I
  270.            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));+ }  S" w% O1 y8 d' T
  271.            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));# W; `7 B6 a) ~6 `

  272. $ W2 B; y, u2 ~
  273.            // 取模型号) i  c9 U' K' U, h7 Z) m# l5 A
  274.            ZeroMemory(szModelNumber, sizeof(szModelNumber));
    , k% a! M2 S# L
  275.            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));, v4 ]' `! S' b" K9 `) D
  276. 5 l5 F" h$ M' G- x  {- u& O- C5 h. n
  277.            pSerList->Add(szSerialNumber);
    4 h7 a, L: q$ |0 w
  278.            pModeList->Add(szModelNumber);
    % _; B  h2 o9 ^- K) {5 r. D
  279.        }
    ( C. \; @; f+ q) W$ b; r
  280.    }' P, p" i# ^" v
  281.    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);; W; q8 ?) }& X) {
  282. }
    0 v- o) f0 Y8 s3 U
  283. //---------------------------------------------------------------------------
    # R+ x6 [# D  {- W3 ~) V5 L5 }
  284. // ReadPhysicalDriveOnW9X_Ring0()
    1 T6 G4 a& J  `  a# Q! t& l2 k+ _
  285. //
    / h( {6 A0 V1 K1 p8 N
  286. // dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
    5 H5 k+ L3 j( w5 j) S
  287. // btMasterSlave = Master(0xA0) Or Slave(0xB0)
    ' X7 ]  y0 r: s$ p/ |
  288. //---------------------------------------------------------------------------
    ' t5 P, P$ X6 P* g; l
  289. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,. B% Q4 K8 A. D1 z% d
  290.        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)! [' g8 @6 o/ E$ D! u
  291. {
    9 o9 n' ^, ]1 O
  292.    BYTE  btIDTR1[6];
    * R6 \' h; ~% u7 t+ |
  293.    DWORD dwOldExceptionHook;2 }/ @5 f$ K* l; P
  294.    const int nHookExceptionNo = 5;
    . h/ n- G, G' \( [

  295. " R& c+ F' U1 P
  296.    BYTE  btIsIDEExist = 0;) W5 [2 Y9 V7 g! s# @. Q
  297.    BYTE  btIsDiskExist = 0;
    2 s- A( a$ b- X  O
  298.    WORD  wOutDataBuf[256];
    5 f$ ]; L5 @0 {5 W' W

  299. , u$ j- U4 [4 z& t3 x6 ^' \6 m$ y
  300.    BYTE  btIsFirst = (BYTE)bIsFirst;
    & C" l% y6 d& [
  301. ; J! B& y0 g( R0 T
  302.    const BYTE btBit00 = 0x01;( P7 i& K3 V) {
  303.    // const BYTE btBit02 = 0x04;/ n; n7 O; c, z3 n! r
  304.    const BYTE btBit06 = 0x40;/ W. V7 B7 z% g% q6 j
  305.    const BYTE btBit07 = 0x80;
    9 h! G  U9 i! ~* o/ g, W- q0 l
  306.    // const BYTE btERR  = btBit00;- u- h' Z4 i* m. q5 i
  307.    const BYTE btBusy = btBit07;; `4 k$ H3 c9 \
  308.    const BYTE btAtaCmd   = 0xEC;' X1 w$ G' u1 t; R, ~5 ?
  309.    const BYTE btAtapiCmd = 0xA1;! f! [+ r% ?) F- D
  310. " F: ^: H& S( L
  311.    __asm
    , a- R8 f& c' Y8 p
  312.    {0 `. F" e2 O& f9 E. b- l% }0 N4 \
  313.        // 必须先执行这条语句
    + m8 ]$ T; W0 l9 X4 v9 E
  314.        JMP EnterRing0
    & C9 B( I8 [) E) p  x$ G
  315. 6 T8 [8 N) m  L8 K
  316.        // 定义过程
    ! H; m% q+ y9 ^. o3 a& Z% z5 t
  317.        // 等待IDE设备直到其不为忙为止2 P. v/ l/ J* q7 R; w
  318.        WaitWhileBusy proc
    ) k& b6 p$ ~' a7 @" {

  319. 1 j- J( L: }1 f+ G1 [/ i
  320.        MOV  EBX, 100000
    / C( }4 j4 b5 r# A5 h0 p
  321.        MOV  DX, dwBaseAddress$ _8 ]  h5 m4 _/ V8 ]3 E1 |. J
  322.        ADD  DX, 7
    ' t' f3 n2 D% l! G, Z$ m/ W
  323. : Z$ J& `0 \: N
  324.        LoopWhileBusy:
    $ m9 @3 ~0 P2 [" x3 Y

  325. 3 w. [/ |8 M9 m6 z1 I4 a
  326.        DEC  EBX9 |6 o# p, K0 {7 z  ^4 e
  327.        CMP  EBX, 03 Q% X+ o$ x9 K) y. U
  328.        JZ   Timeout5 L2 k# m- P" e  Z2 s
  329.        in   AL, DX4 g; L$ E1 u  |* @1 a! y8 d
  330.        TEST AL, btBusy
    / U% f/ m5 M; x! m& F: N) o9 r
  331.        JNZ  LoopWhileBusy; q4 E) l( K  E7 p- U
  332.        JMP  DriveReady
    + ]: P  f% M1 l" Y( g" I

  333. + s& Q; }9 S* D2 a" X
  334.        // 超时,直接退出+ n. u: I& @* g5 \) K# e
  335.        Timeout:
    " E5 Y* I; o7 a1 e4 M3 K% S7 t
  336.        JMP  LeaveRing0, m* W$ A: |' z* a3 T" H6 V
  337.        DriveReady:8 Z% z  v  D2 `# F9 R
  338.        RET& G# t7 G# P  U' t" H) q* x
  339.        ENDP   // End of WaitWhileBusy Procedure
    0 q/ Q& Y- I# Z

  340. , Y7 n% f9 T7 T+ d. O; j
  341.        // 设置主盘和从盘标志
    ' V& q! Z$ A" `" F) m4 i& q$ _
  342.        SelectDevice proc% z5 w7 [3 }& p) v9 H) e5 |8 h& Q

  343. 9 \9 k) p2 k2 `' E+ L2 U3 V# S
  344.        MOV  DX, dwBaseAddress4 e; n) m3 k) Y0 j
  345.        ADD  DX, 6
    ; |+ X+ [2 G& d' t: q" v: W
  346.        MOV  AL, btMasterSlave; w9 y2 B) i. @6 `
  347. * [; M6 \8 u4 Y* P) u& \- j
  348.        out  DX, AL
    ( ]9 e8 U7 Y' P* _8 N
  349.        RET
    + P' R1 t% {. n; m( O/ `

  350. - L* {) ^8 E2 G- d* K1 x
  351.        ENDP  // End of SelectDevice Procedure
    7 g* ^* i- b5 J8 G8 z: }1 Y. ~7 c
  352. 7 N5 D2 ]; _- ^8 s
  353.        // 向IDE设备发送存取指令
    ' {1 b' M7 Q8 V. Q5 i7 ?
  354.        SendCmd proc- F% s8 n" M$ f$ q

  355. 3 G# U4 U& |" n& y7 K7 S. @: k4 R
  356.        MOV DX, dwBaseAddress
    6 G7 T/ X6 S# a+ I0 k
  357.        ADD DX, 7
    ( H3 v/ M1 L- W3 g5 k- A4 c4 e
  358.        MOV AL, BL // BL是主从盘标识,在过程外设置* J0 p3 M$ Q1 ?# z: _7 ]4 a
  359.        out DX, AL
    6 z9 l  p1 s  t& A+ J! E' Y( t$ m
  360.        RET
    9 {  s0 k( F+ Q3 a3 K# T" b$ Q. c
  361.        ENDP  // End of SendCmd Procedure
    ) ^, q: K( z9 {$ ?* K9 F8 I+ Y
  362.   _/ g6 g6 b0 ~
  363.        // Ring0代码+ X9 X9 a3 l5 w
  364.        Ring0Proc:; n  V& r# M% h& \0 |- t* ]3 c
  365.        PUSHAD+ j, l6 ^; P; p( N8 z
  366.        // 查询IDE设备是否存在; M/ r6 E% ~: m& ^' w
  367.        MOV DX, dwBaseAddress' [' C0 n" W5 I! G. }7 c/ T# z8 ^
  368.        ADD DX, 7
    % o8 B+ |+ @+ R# {  {
  369.        in  AL,DX/ }/ I3 H2 l1 ]- |& z8 H5 s
  370. 9 Q6 u/ t: ~* f% d! Y  ^/ d; d2 l
  371.        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
    ' M8 M% P% p, N5 S9 p- _: \% t
  372.        CMP AL,0xFF4 k+ {) S& H9 l
  373.        JZ  LeaveRing0
    4 }+ w& @4 M, |* H* P& R' c
  374.        CMP AL, 0x7F
    & ?- \* J9 }1 n( y
  375.        JZ  LeaveRing0* B% \) I: l! Q2 q' a3 K8 ]1 d
  376. : \" k" {' w9 H( p+ ]0 ?! J
  377.        // 设置IDE设备存在标志
    ; v" p3 L' B9 q3 x& `
  378.        MOV btIsIDEExist, 1
    - [; N5 O: l& B. q5 V5 ^

  379. 5 x+ z% v) E% {/ {: C0 H1 r
  380.        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
      U5 k: M; v' w$ p4 l0 y
  381.        CALL WaitWhileBusy
    % {0 L* k- ~: J9 I% [) C9 f2 c
  382.        CALL SelectDevice
    . u% C8 O* _9 l# g

  383. % A( g0 J4 G9 S2 A. }# ~
  384.        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
    3 e7 e' Q3 ?& [
  385.        CMP  btIsFirst, 1: ?' R* W, \% C' l
  386.        JZ   LeaveRing0
    ( ^! r+ R5 o' }) ^
  387. 6 K: V' B* C6 P! [8 |$ }' z) O
  388.        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
    2 @$ d3 o4 ]" U* _4 p2 |& i" @
  389.        CALL WaitWhileBusy
    / Y" h* s9 ^5 r0 _! v; B* V5 z
  390. ! v0 Z) N; m3 D" K3 w4 x
  391.        // AL的值等于cBit06时,不存在驱动器,直接返回
    0 G- M! w" U  y1 k6 @
  392.        TEST AL, btBit06$ m1 @9 M. t* P) H/ L
  393.        JZ   LeaveRing0
    2 X3 e+ j' D; V
  394. 6 p! I. }. _) E# V* n
  395.        // 设置驱动器存在标志* F* u3 V0 D& A
  396.        MOV  btIsDiskExist, 12 |6 S1 g' G( Y* ^% L
  397. / _" v. L( i% G/ h1 Y2 a
  398.        // 发送存取端口命令6 g# x% x. @( m2 a! q" k) c
  399.        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,# @+ z" H1 i% f) v
  400.        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
    6 Z1 E% `9 R. ?
  401.        CALL WaitWhileBusy6 W& C5 N. w) U" \) _7 F
  402.        CALL SelectDevice    // 设置主从盘标识2 `, f1 z. _9 z+ V3 \" ~
  403.        MOV  BL, btAtaCmd      // 发送读取命令% X* W6 ~, Z! D; }. E9 z
  404.        CALL SendCmd3 x+ v  k# i5 p/ Y) q
  405.        CALL WaitWhileBusy
    % A! _, F: _/ g$ [. |2 k
  406. 8 V& z# f: n5 {% k2 H% O7 m+ X
  407.        // 检查是否出错
    - c+ B' W4 C: Q; M
  408.        MOV  DX, dwBaseAddress
    : X9 [9 ~& o2 y9 ?
  409.        ADD  DX, 7
    7 x2 b  X/ L' J: r/ m7 T
  410.   [4 A! \, i0 z- f$ a( g$ ]
  411.        in   AL, DX
    1 x9 h& Q: k5 E0 q$ R0 w# [

  412. ; h) b; Q, j% O2 t+ S% s
  413.        TEST AL, btBit00
    % l6 v7 T" N! x; C
  414.        JZ   RetrieveInfo   // 没有错误时则读数据
    * P! b3 |6 ?* f. S9 U( S
  415. 9 L! L- j) v1 X
  416.        // 如果出错,则进一步尝试使用ATAPI设备命令1 w2 \; n: V9 `# ^, B* Y
  417.        CALL WaitWhileBusy
    ( G6 b# Z: A( }* A& ]" P8 s& q6 x
  418.        CALL SelectDevice$ R6 a& G" |0 N: L& R6 M
  419.        MOV  BL, btAtapiCmd' m0 m4 y# b! F& J: m+ t$ m
  420.        CALL SendCmd
    4 ]( F. c1 q" Y
  421.        CALL WaitWhileBusy$ O0 N- O1 x6 O; {. {! I0 [

  422. 1 J: m+ }1 j% t: ?7 h/ U* p& c
  423.        // 检查是否还出错
    * B" n8 Y3 W  X- X1 f
  424.        MOV  DX, dwBaseAddress% r; W4 z! }8 ]% J' @
  425.        ADD  DX, 7: U( D$ T$ p0 e) q/ h
  426.        in   AL, DX
    1 F" _8 A3 ~- m: |8 O1 F
  427.        TEST AL, btBit00
    4 @, n. X# X. a7 t5 C9 z! ]
  428.        JZ   RetrieveInfo   // 没有错误时则读数据! p+ ]! q7 {! A# k4 x" W# b
  429.        JMP  LeaveRing0     // 如果还是出错,直接返回6 E2 I. W, W% r  I- ^$ ?! d  C4 r2 r
  430. . _, s$ N: V7 M8 C: T- T
  431.        // 读取数据
    + q3 Q3 A/ u. e$ t% b" U- y2 u
  432.        RetrieveInfo:6 K# ~" ?9 g! [$ ]
  433. . R& _2 k& Z$ `: e3 k, W
  434.        LEA  EDI, wOutDataBuf0 j1 C: \* v+ Y* H0 @/ ?0 F* v
  435.        MOV  ECX, 256
    6 q; A% d' Q( ^' z' @5 M0 b
  436.        MOV  DX, dwBaseAddress
    " X' Q$ M% i% V% W$ x
  437.        CLD
    / r3 s2 U7 P6 E" W3 G# M3 A& v! t
  438. ( ?1 j5 `" Z8 b* R. e% s
  439.        REP  INSW
    , M2 W+ S: Q3 T" c1 |

  440. * N8 c9 {/ t6 {5 I6 {# A
  441.        // 退出Ring0代码8 \: c! o  k" q% P- {  ]
  442.        LeaveRing0:
    ) K; @$ g0 z) w

  443. # j5 W4 x! g* y8 d) i/ ]2 ]
  444.        POPAD$ i& B- P3 g6 Q; `9 [/ l" F
  445.        IRETD
    3 l: r+ Z# I7 I8 w) z% ~
  446. & b( d/ W" b* X: A' P
  447.        // 激活Ring0代码1 f) U) \' E1 `0 ^' j3 K" _
  448.        EnterRing0:
    $ m, m5 F6 [0 s' P
  449. % }: \( m8 U7 v7 F- n
  450.        // 修改中断门
    - g7 e% N# S4 v
  451.        SIDT FWORD PTR btIDTR1& s, R9 d# g5 F7 i$ u+ ^
  452.        MOV EAX, DWORD PTR btIDTR1 + 02h
    6 U; e9 H! }$ X* V2 H' n6 b; ]8 a
  453.        ADD EAX, nHookExceptionNo * 08h + 04h
    5 y5 x) l! S1 q/ D
  454.        CLI% i- p- S# [2 O* Z+ Z
  455. 7 j- N; t/ O# H- y
  456.        // 保存原异常处理例程入口
    & D( x+ S3 C# f& O" B; A, Y2 c
  457.        MOV ECX, DWORD PTR [EAX]
    6 ]9 @4 l3 J; O. m
  458.        MOV CX, WORD PTR [EAX-04h]
    ) }' E# Q3 h$ U4 \5 c
  459.        MOV dwOldExceptionHook, ECX: n# c) X$ s* H* y4 r' e  s

  460. 4 ^" T/ c0 o6 N' g" F
  461.        // 指定新入口
    , u& Q* M0 |3 ~" f" }1 r* ]
  462.        LEA EBX, Ring0Proc
    5 q* u8 Z$ W( K) L# H  U) ^5 u
  463.        MOV WORD PTR [EAX-04h],BX
    2 h$ R, R- [8 Z/ f' N" R
  464.        SHR EBX, 10h
    4 I5 k% r) x( M* \
  465.        MOV WORD PTR[EAX+02h], BX8 l: x5 q+ X, W7 {
  466. : f/ e  v3 S0 O) t
  467.        // 激活Ring0代码
    : X3 S" Z2 g3 E) j& j2 \
  468.        INT nHookExceptionNo
    : j3 K6 h/ o# y
  469. ( J6 [5 w# G2 w3 {2 e  I
  470.        // 复原入口
    * r8 L3 N' w# b7 [2 [; D
  471.        MOV ECX,dwOldExceptionHook( s1 l: Q; D) N/ a% x" q
  472.        MOV WORD PTR[EAX-04h], CX5 h4 @# f$ u6 d% ]4 `, E" g4 x
  473.        SHR ECX,10h
    8 s# T) h. T& v; Z6 Z
  474.        MOV WORD PTR[EAX+02h], CX& }( B" j( K7 u! g3 W
  475.        STI
    9 s, Z0 ~1 T0 s3 E0 {) |
  476.    }( t* F& Z: C( Y
  477.    if(!bIsFirst)* x+ d' a+ Q! b6 M
  478.    {
    ) w+ d7 o* v; X, B( c
  479.        bIsIDEExist  = (bool)btIsIDEExist;3 l  B$ M! _: ]
  480.        bIsDiskExist = (bool)btIsDiskExist;
    % X4 o2 j1 W( }' ^% L; M8 J
  481.        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));. D. r. e4 ]) ]6 q3 t8 S* f
  482.    }
    # q7 m' b3 f2 K) }$ j: M
  483. }
    & D6 c+ Z' m+ s! ]$ H/ F, W! y! o
  484. //---------------------------------------------------------------------------! Q# C1 s: @7 H* O' L9 K% i
  485. // 调用方法:7 _% h. H7 ]4 q+ T; A
  486. void __fastcall TForm1::Button1Click(TObject *Sender)" N/ F6 n  s6 Z0 C
  487. {
    5 C, i* E, y' ?$ P' ~
  488.    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
    4 J; P; R& k/ r& n) U
  489. }
复制代码
发表于 2005-8-15 01:00:45 | 显示全部楼层
晕乎乎。。。怎么看8 洞阿
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-6-18 09:00 , Processed in 0.018107 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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