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

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

[复制链接]
发表于 2005-8-11 11:42:04 | 显示全部楼层 |阅读模式
  1. #include <WinIOCtl.h>
    - M+ j% Z' d5 U& Y( |) ?9 K
  2. #include <stdio.h>3 d8 g9 o3 C5 h: [; T0 j
  3.   B" U  i+ ], M
  4. #pragma inline
    , [' t7 Z  Z' p/ Z% i5 U, L
  5. //---------------------------------------------------------------------------
    - b; L. I3 n5 v3 V8 G+ H
  6. // IDE NT/2000/XP专用变量- r' T9 i3 ?5 @! P: d' v9 h2 ?
  7. #define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS, \  _# Z! s6 E8 s! u
  8. #define DFP_GET_VERSION         SMART_GET_VERSION3 [7 R; D. I1 `/ w, _# `
  9. #define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
    , Z3 M  s' _& \7 M! O9 a
  10. #define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA" j$ }9 M1 L% A' C& N
  11. & D& f0 M0 R( B/ T3 P6 c4 r: ]2 T2 v8 j
  12. const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令
    " e. v0 y& y9 k* s1 L3 i
  13. const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令! G" K% o% v8 _3 ~
  14. 7 x" N' ^, j' g
  15. const int MAX_IDE_DRIVES = 4;; X# V3 ~% m4 G; L, M3 P+ v
  16. 2 F; K9 u5 Q" i/ g
  17. // SCSI专用变量
    1 K0 ^3 v% \: l+ Q7 k: O* q# _, \/ Y
  18. const DWORD FILE_DEVICE_SCSI             = 0x0000001B;
    ! N* t# `! H; v6 m! x) z
  19. const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
    1 F8 }/ o! z" Y1 h9 W
  20. const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
    7 d  H/ {: x+ n5 P' L
  21. const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;# {6 \2 g3 Q2 J# k' _' M; v

  22.   l3 {% Z. q: i" W; Z& X
  23. typedef struct _SRB_IO_CONTROL6 c( }7 p* |6 l) K& r
  24. {8 q9 y+ {2 K: o( _3 m8 S% ?' I
  25.    ULONG HeaderLength;7 I& B, h. }# a
  26.    UCHAR Signature[8];
    ' K1 W% H2 s  k- w
  27.    ULONG Timeout;# j8 d$ T* s$ M* D3 z4 U
  28.    ULONG ControlCode;% G. `/ ~0 j" N
  29.    ULONG ReturnCode;3 h2 K4 b5 m) S- G
  30.    ULONG Length;
      n* C; M9 k; Z! U2 b, g
  31. }SRB_IO_CONTROL, *PSRB_IO_CONTROL;
    4 w2 O3 E9 t4 q' D6 T% M. I

  32. 4 V4 D7 c1 r$ B8 I2 @$ P
  33. // 读取的主函数
    + k+ `9 ?$ s8 b# {( }
  34. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);7 Q2 S! G4 b2 b0 f! u
  35. 3 v3 U3 s( B6 C5 R. ~
  36. // 辅助函数# Y" O* c& `7 j/ H/ w
  37. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
    # P% \% |4 N  B4 w. D& e+ E: P
  38. // NT/2000/XP函数
    : n8 a" F+ a9 |1 r* P
  39. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);, R5 q1 f7 F% m1 C) |/ q3 R0 a- c5 b! M
  40. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
    & ^! J: H. a% }" @
  41.        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,6 G2 f6 x4 s! E/ f5 u- C3 s2 g, \
  42.        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
    4 O$ d# k" l) ~1 `& a7 @
  43. // Windows 9X函数
    ! \% X8 a/ d/ Y1 W/ U! H
  44. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);6 R& D9 ^; ?2 g. J& K7 Z" _2 T8 O
  45. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
    8 o  l8 U( B0 `3 _$ C* \- Z* {
  46.        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);3 F9 f, u& z# @0 d! [9 G& x  O
  47.   u7 |( G" E5 N1 }! V: Q
  48. // SCSI读取函数(for NT/2000/XP)* c$ ?" O) V" V! G2 [
  49. String __fastcall ReadIDEDriveAsScsiDriveOnNT();' {- Y4 q6 C3 B0 P) A7 `; z
  50. //---------------------------------------------------------------------------
    7 }6 C  N8 S% f* Y9 s. X! L! m
  51. // ReadPhysicalDrive, P- R' z6 c/ v  ]2 e7 e, y% o
  52. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)/ u. c3 Y$ T! K. b# r" V
  53. {- K- S; U( v& w
  54.    switch(Win32Platform)
    ' |  n, ~3 q8 A& S) d
  55.    {  P; q" M% p. _7 n8 [' S6 X
  56.        case VER_PLATFORM_WIN32_WINDOWS:1 E! {4 F& X$ z( L( e6 Z! p- ~
  57.            ReadPhysicalDriveOnW9X(pSerList, pModeList);
    3 e# u0 z7 `, _; ^; l
  58.            break;
    + ~6 L$ P0 u$ i) Z8 b, e
  59.        case VER_PLATFORM_WIN32_NT:
    , b1 d# q: `4 f: H. v6 M& i3 p: K
  60.            ReadPhysicalDriveOnNT(pSerList, pModeList);- O% h' q; d& \! h2 g4 [# _, \
  61.            break;$ @; _+ b9 S+ @) d  \8 _
  62.        default:
    ) @1 @- E4 b. h) P/ N$ G
  63.            break;  ~0 x3 ]4 j  b. w8 k
  64.    }. Q9 Y" D8 [/ d3 t+ J
  65. }$ h' t/ C; E" f  h( w! A5 Q
  66. //---------------------------------------------------------------------------
      s* K& x! y* J
  67. // ConvertToString8 K, B* d. s4 i9 ~# i
  68. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)7 L" l6 ?3 W8 E7 _" Y3 D
  69. {
    " b; r& j. |1 A- h& R
  70.    static char szResBuf[1024];) y1 I, W8 Q6 w
  71.    int nIndex = 0;; A( n& [2 f& \" X" M8 u8 ]! D" }
  72.    int nPosition = 0;
    / ~  Q& L0 `( R( _: k+ x$ J) F
  73. 0 Y$ J, F! r% \+ n4 {
  74.    // Each integer has two characters stored in it backwards
    ! t7 ~7 k" \8 ?; s7 h
  75.    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)# a$ e; H" {3 [& [8 a
  76.    {
    ; |+ I0 J) f1 m
  77.        // Get high BYTE for 1st character
    % g/ g- x5 M. y; j* Y& {1 T/ T
  78.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
      z" D9 h/ [9 j
  79.        nPosition++;
      g8 L1 y9 k% m* \7 x! R- E, D
  80. ' M( {* k' i; [- j4 T% f% C
  81.        // Get low BYTE for 2nd character: S" C& }( K: t! B1 L8 |  O% r
  82.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
    6 @8 [& L5 t; @! `) t- Q0 t
  83.        nPosition++;
    , b0 c0 D, E. O: O7 O- z, P
  84.    }2 s8 _1 t1 Q. G) h' t) S
  85. 7 N8 i: ~4 p9 o. W' w
  86.    // End the string( k7 K- M/ @. J2 C) b* I6 S
  87.    szResBuf[nPosition] = '\0';
    % P$ u0 Y. \# N. V3 r
  88. % B  s: {9 i* V' A3 u. X
  89.    // Cut off the trailing blanks  K9 b% v4 x/ R. P1 @. J/ Q$ S4 u
  90.    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)# P3 S& i* k% E* f/ b0 ?5 Z8 @
  91.        szResBuf[nIndex] = '\0';+ a% ?6 ^8 k6 s- p

  92. * r; o4 Q. Z$ k$ q7 Z
  93.    return szResBuf;, s: ^+ F6 z" v" t5 H4 J) G2 A+ C
  94. }( u5 |+ }3 e" J' x$ J+ n2 y
  95. //---------------------------------------------------------------------------
    3 a4 q! V; L" A; u7 j
  96. // Winndows NT4/2000/XP 代码
    ( d) F1 v: u* I6 X  N, x
  97. //---------------------------------------------------------------------------% }/ x9 f1 R9 }1 B; l4 H
  98. // ReadPhysicalDriveOnNT9 q: @# w, g" n
  99. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)4 ?( m2 U, Q; s+ U1 \/ ?
  100. {3 x% l9 }3 ~5 \% A; H$ S1 E1 P3 k! A. e7 n/ V
  101.    // 输出参数
    - E1 ]9 [- L& u" j
  102.    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
    / s$ b# z3 D) a8 o* _  `7 c9 b
  103. 4 U; G' Z/ N5 U$ @1 ^2 U: t
  104.    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
      x  E' Q! W$ p7 {( s; r
  105.    {4 @/ l/ L+ D* H! Q, B& C
  106.        HANDLE hPhysicalDriveIOCTL;
    5 C; s) Z3 s9 E9 L. ?
  107.        char szDriveName[32];' C0 N5 n5 U0 R, G6 b$ I4 |+ _9 v
  108. * T2 p) E' \1 b9 R6 V$ W1 K' @
  109.        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
    $ C2 J# j5 N; d% ?9 Z$ }
  110.        hPhysicalDriveIOCTL = CreateFile(szDriveName,, U1 V" O% P- j; j
  111.                        GENERIC_READ | GENERIC_WRITE,; n6 W9 ?0 ?. B8 i. f
  112.                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,: K  u; I* h% V/ K1 z& \
  113.                        OPEN_EXISTING, 0, NULL);3 R% D+ ^% Z% }" J, X
  114. . Y( M. g: Q5 [
  115.        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE), s; y; T# J- M* x. }1 g/ M$ T* E; e; E
  116.        {. ]" k! Y' j4 O5 b  ^- \; \# _. m( [
  117.            DWORD dwBytesReturned = 0;6 K9 H2 G: q( ]9 [/ S
  118.            GETVERSIONOUTPARAMS gvopVersionParams;
    # X0 z0 K; Y& A. }4 p) x  W1 P' Y

  119. 2 g! m4 x/ I1 [$ D
  120.            // Get the version, etc of PhysicalDrive IOCTL
    ! w/ H! b2 V; I0 J/ |8 j
  121.            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
    3 Q- z) x) ^' N4 S6 S4 ^

  122. 3 k' t: l5 d: |) T6 f
  123.            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
    ; x( Y; A! i. ]/ K
  124.                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),, N% Z- p3 {; E' e( l+ s
  125.                    &dwBytesReturned, NULL))
    ( y  [7 T+ K8 m; ^
  126.            {! G$ D" A5 G0 w' s/ y% N$ b' S
  127.                continue;
    . ~( p" e* N4 Z, [
  128.            }
    ; K( T8 x: x3 c; ]2 z' K% z

  129. 0 N) A/ x& |4 \
  130.            if(gvopVersionParams.bIDEDeviceMap > 0)
    2 I7 p( @/ [  A0 b( S$ E) L
  131.            {
    . T8 o% I8 p, }6 U
  132.                // IDE or ATAPI IDENTIFY cmd* j0 {+ d* c* x: N* o+ ]
  133.                BYTE btIDCmd = 0;& X9 q! H- u! K3 g+ r% {! J- z* v
  134.                SENDCMDINPARAMS InParams;
    + t3 K" R) H) h/ n8 |3 P+ k+ F2 A
  135.                // Now, get the ID sector for all IDE devices in the system.
    0 ~8 b. `2 e& z' b( \/ y; i8 j( f0 e
  136.                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
    9 F& Y; r$ m' ~% D, j6 e
  137.                // otherwise use the IDE_ATA_IDENTIFY command/ N8 S9 g' t# I2 ~* _( L& `
  138.                // 具体所得结果请参考头文件中的说明
    / J* `) U& z3 L0 b* O  E: M) `
  139.                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
      ]- z5 E8 o1 o' p- V/ M
  140.                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;5 F8 t/ C& X7 O; e& F
  141.                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
    % N! y8 V" d2 e0 X. D# T
  142.                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));/ M: |) h0 b3 l6 _3 n# q

  143. & K' x3 u! Z( \# J0 I8 L
  144.                if(DoIdentify(hPhysicalDriveIOCTL,
    . I* t1 e! w. L) x$ D7 {
  145.                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,2 f; Y5 t0 w* I5 }, f3 v2 U
  146.                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
    * k2 J3 M  X+ q  L. u' \
  147.                {
    3 N( |" q$ X  B. a- {
  148.                    DWORD dwDiskData[256];; j5 |4 `$ W, r  |, i2 o0 t
  149.                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件) M& \3 }; r8 q3 Z
  150.                    char szSerialNumber[21];7 y1 J1 F8 W/ R" V) ^7 h
  151.                    char szModelNumber[41];5 E  i7 T* P" M2 h% ]/ R
  152. - ?) w" f1 ?! E- L
  153.                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
    ) ^; z' H) C. y7 {9 I/ z5 P
  154.                    for(int i=0; i < 256; i++)
    & n) ^5 u* h9 `9 W& T
  155.                        dwDiskData = pIDSector;* S# g4 \% s2 V) h! K" Z
  156.                    // 取系列号
    $ s9 d' k; ?& Y
  157.                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
    3 q1 a# N! Z1 v' b$ {
  158.                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
    2 M# ^9 k+ p8 @$ z% U7 |" m

  159. ' W% p! ]8 e9 W1 S* k) k2 j' M
  160.                    // 取模型号' [+ H0 e/ k$ B4 ~2 L8 p
  161.                    ZeroMemory(szModelNumber, sizeof(szModelNumber));' E9 C/ @& {& ~7 v% E: N% U
  162.                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));9 i" l% k& c* W6 W3 P; F. U
  163. 1 T2 W& a  g; ~# g" g. e
  164.                    pSerList->Add(szSerialNumber);' H; f4 I) X0 m) z3 U2 ]/ h, I
  165.                    pModeList->Add(szModelNumber);
    " z7 a- d* l/ ~9 v
  166.                }
    : q7 C' o7 ]( W) M" n* j3 x4 Q
  167.            }% L* N5 @  D9 z. Z( [; `; F. ^+ ~
  168.            CloseHandle (hPhysicalDriveIOCTL);, u: N  N+ R; @; U  ?
  169.        }
    2 `8 X, i4 M+ ~" v6 L5 J
  170.    }
    : r/ ~; S; x/ Q! ]: j; ]4 |
  171. }
    : P" ]. B" u5 F1 y5 P( P9 I
  172. //---------------------------------------------------------------------------
    - e8 P5 C: W6 J' I% p
  173. // DoIdentify
    6 B$ q2 U$ I8 A3 [) s$ Y* B
  174. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
    * v, j1 _5 t+ I8 ~3 v$ x  @
  175.              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
    5 H  v" c1 P( `7 E2 U! R  o# {
  176.              PDWORD pdwBytesReturned)
    ' f- `* O2 U# x# m- S! ?  N! t
  177. {! I' H& b! Z- U; R; X# U) J/ e
  178.    // Set up data structures for IDENTIFY command.
    ; n2 s+ s( h' x- U6 O6 g" d
  179.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
    " F  s# ^2 Z5 m4 ^
  180.    pSCIP->irDriveRegs.bFeaturesReg = 0;# e3 Y  \1 b' g+ E% }9 T
  181.    pSCIP->irDriveRegs.bSectorCountReg  = 1;4 z& y6 P  x8 p  H- _7 Y8 h
  182.    pSCIP->irDriveRegs.bSectorNumberReg = 1;
    : [2 B0 ~2 @, D! @6 G7 O# q
  183.    pSCIP->irDriveRegs.bCylLowReg  = 0;$ j, B. k: x  i' X
  184.    pSCIP->irDriveRegs.bCylHighReg = 0;1 O, O9 h3 D- B) L, E1 }4 x, x' n
  185. ' F5 O$ k7 v3 w/ Z* L. r
  186.    // Compute the drive number.(主盘和从盘所对应的值是不一样的)
    / C1 W! I- {, w  ]- X
  187.    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;, h, B. q1 k; _7 ?, z

  188.   F: a3 m$ F$ I: {
  189.    // The command can either be IDE identify or ATAPI identify.
    & ?3 D. j' a: m  E
  190.    pSCIP->irDriveRegs.bCommandReg = btIDCmd;
    5 o0 U" s. M. L- _2 K9 u
  191.    pSCIP->bDriveNumber = btDriveNum;6 y6 {$ l8 m' q# ~! z2 E: F
  192.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;+ K0 t% x, I4 `9 i7 I* K
  193. 8 ?$ u* D6 {2 C8 v! f
  194.    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
    * r' P- N1 j& k
  195.           (LPVOID)pSCIP,
    3 @$ s+ l$ j; `* g* `% m9 i  C
  196.           sizeof(SENDCMDINPARAMS) - 1,4 S- U* |* S. i8 c1 k2 k6 l# h. O5 [
  197.           (LPVOID)pSCOP,: [9 M% V6 S; Y1 a- s& Y
  198.           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,; V( b0 W  M% p* B5 A/ ^1 K8 j
  199.           pdwBytesReturned, NULL);  {' u' T7 Z8 m, ^$ l% U) J. {5 m; H. y
  200. }' C" Q7 U  [/ h1 Y, c2 \
  201. //---------------------------------------------------------------------------9 U" R: {# F2 n
  202. // Windows 95/98/ME 代码% M) y$ N; N+ ~& q8 n* U
  203. //---------------------------------------------------------------------------& u9 @" s9 T( \( A2 X
  204. // ReadPhysicalDriveOnW9X) w# j! L4 r# K" L
  205. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList). @! l: C) L1 j
  206. {2 o# E4 p/ y' }  ?" Y4 }1 c
  207.    WORD wOutData[256];/ I) }' f9 |8 w% g# L
  208.    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
    $ ]" T7 B3 L4 H/ f! u

  209. " Z$ W( B! P% H5 U$ D6 |
  210.    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。6 |  x  M" n: U; k$ i. D% n
  211.    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以! R- o$ f& U5 I/ d1 S. o
  212.    // 避免蓝屏的出现。(期待高人能指出原因)
    1 B/ y  D& s8 Z4 I
  213.    for(int nDrive = 0; nDrive < 8; nDrive++)
    ' s% o& J; f  Q3 f  T& _
  214.    {6 s6 h9 T, l" n8 W
  215.        WORD dwBaseAddress;. V% \; N6 `( r' y% _
  216.        BYTE btMasterSlave;         // Master Or Slave
    ; b2 V, G: Y, i2 c( l
  217.        bool bIsIDEExist;
    4 U4 P1 Y, Q, M/ X: J/ M
  218.        bool IsDiskExist;
    / j5 `1 k: W- A5 |" v2 Y
  219. % @8 J$ O2 E! e$ H
  220.        switch(nDrive / 2)
    - p7 K$ _" w/ G9 _( o
  221.        {# c- V4 o; S. Z# _' @2 M+ h
  222.            case 0: dwBaseAddress = 0x01F0; break;
    : l4 v+ H) h0 D( _( ^$ T* L/ p
  223.            case 1: dwBaseAddress = 0x0170; break;
    % W3 F1 l; ]* q' t0 m: [- n
  224.            case 2: dwBaseAddress = 0x01E8; break;. X, Y* S* I. M/ Q: U- j0 E
  225.            case 3: dwBaseAddress = 0x0168; break;
    " @* y$ j% G8 X( e0 D. p
  226.        }
    & H9 M0 G7 W2 l
  227. ! i9 k1 S/ f( B1 |% o
  228.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);7 O% ~* e4 G9 {; j1 W& q

  229. % x- o; T9 @, ~3 T
  230.        // 进入Ring0
    ) ^) g/ g; w7 W2 m/ O
  231.        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
    6 [9 U& b& j4 N; `% }+ Q
  232.                bIsIDEExist, IsDiskExist, wOutData);
    ' l0 X7 Z1 ]0 r0 b' l4 p  f: k  I
  233.    }( r+ |( E' V1 y) T3 X6 u4 d7 l
  234. 6 J0 L% \' G' M5 [
  235.    // 开始读取- c0 K; N' j0 V2 H" J" t- E3 g# w
  236.    for(int nDrive = 0; nDrive < 8; nDrive++)
    / ?2 W7 [' j0 f, A5 j! N
  237.    {9 i  ]7 M0 m" ^
  238.        WORD dwBaseAddress;
    " w8 F/ ^3 W' X: @; i+ y3 }
  239.        BYTE btMasterSlave;         // Master Or Slave
    ! Y1 h/ b) K$ K# z! V4 o9 P
  240.        bool bIsIDEExist;! `% r7 V, J# n5 h: C: j  [
  241.        bool bIsDiskExist;; V, G7 B  x9 ]$ d
  242.        switch(nDrive / 2)
    $ E9 k! w9 S, ]1 b% @! b
  243.        {3 S5 t1 w# u& Y# e
  244.            case 0: dwBaseAddress = 0x01F0; break;$ B2 V: a6 C7 Z* ]  b8 g
  245.            case 1: dwBaseAddress = 0x0170; break;7 b8 H% A! n% f' k/ g
  246.            case 2: dwBaseAddress = 0x01E8; break;) E: a/ }# L- V
  247.            case 3: dwBaseAddress = 0x0168; break;8 F& a5 O/ q, E
  248.        }8 }6 b0 ?* N' A) \7 @
  249. ( Q6 k. u% b8 x
  250.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
    & I0 ^2 Z- r% s5 X) `8 F
  251. % p! h. Q: N3 b- S$ m% `  z
  252.        // 进入Ring0
    7 B: P/ S9 B0 u, t, j/ c* ~9 V
  253.        bIsIDEExist  = false;& A5 ^: F  ~+ e0 o) S& H3 G
  254.        bIsDiskExist = false;4 B, B5 f. D. }
  255.        ZeroMemory(wOutData, sizeof(wOutData));( z" {* ?" K1 J% ]$ ^6 v4 M

  256. & d* ]7 s/ g9 A2 P0 c9 o0 \
  257.        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,& B- Y7 t5 n, W
  258.                bIsIDEExist, bIsDiskExist, wOutData);. J9 L* Q& }. L) W
  259. - R+ T+ x0 `0 H  z
  260.        if(bIsIDEExist && bIsDiskExist)" o) w* @  H4 L* V4 [& H
  261.        {( R# c- r0 E7 D4 }* @/ R+ B
  262.            DWORD dwDiskData[256];: h: ~" u0 F# h
  263.            char  szSerialNumber[21];
    $ `: s. m2 u- s3 u( t* Z
  264.            char  szModelNumber[41];8 e8 ^' a4 _5 O% M

  265. % ?; ^  q  x/ `. u# _
  266.            for(int k=0; k < 256; k++)6 v/ a* D1 ]$ M1 p% c% o
  267.                dwDiskData[k] = wOutData[k];
    : _- E+ U4 f: F2 x, E
  268. % t7 L8 c# X; I* \9 g7 l4 _
  269.            // 取系列号6 p( F: t& q3 S, I2 }) z( i$ w8 G
  270.            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));. [: ]0 ]5 ^5 M; j3 O* n3 A  I7 n
  271.            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
    % U6 b) z3 J3 @2 F2 [

  272. 5 B0 J! ~$ m* l$ r5 U
  273.            // 取模型号
    2 f& R% n  \7 k) x; {; Z
  274.            ZeroMemory(szModelNumber, sizeof(szModelNumber));
    " z. P' [: a0 x# j. g
  275.            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));6 t7 S) x2 ?* }' k5 b$ X

  276. % h/ H6 {& o3 W  R$ w8 g
  277.            pSerList->Add(szSerialNumber);
    7 y8 a: e( q$ q5 h, ~1 y; k
  278.            pModeList->Add(szModelNumber);8 d( \) M* A* o: I; \# [# I
  279.        }* A! u9 x# U+ `, H& M0 P/ n
  280.    }
    ' y! j2 L/ t6 O7 N% V2 h
  281.    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
    3 b% ~$ _( G' _8 I. ~4 f
  282. }
    " l  L) J0 a$ I0 c) l; T
  283. //---------------------------------------------------------------------------, _# x. s4 K' g0 M
  284. // ReadPhysicalDriveOnW9X_Ring0()
    " o+ f# a) o0 y
  285. /// a2 F: ^3 p+ q
  286. // dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
    2 Z' \' h- @/ u( Y# h5 g: I
  287. // btMasterSlave = Master(0xA0) Or Slave(0xB0); G& i4 I  P) _; R( b1 B5 c+ C. z
  288. //---------------------------------------------------------------------------4 Q/ @8 h' E6 @$ _- e
  289. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,. R/ _; V/ N) F, z) E# {: A' o) A
  290.        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
    & f# F1 D0 U7 I8 s
  291. {+ o& G0 X- Q7 x  E+ A
  292.    BYTE  btIDTR1[6];0 [% z' j8 \3 k6 g
  293.    DWORD dwOldExceptionHook;
    0 u8 U% q0 j3 S0 \
  294.    const int nHookExceptionNo = 5;
    4 G0 j- F3 D2 A& k* S* w) h

  295. 0 o8 ?' P# L) ^( ^  A
  296.    BYTE  btIsIDEExist = 0;0 y% h7 j( }! P4 \0 z' k- E
  297.    BYTE  btIsDiskExist = 0;4 F4 i2 ]" ~; g
  298.    WORD  wOutDataBuf[256];: K/ l* D' S! N
  299. # L% M4 |- @( r4 |
  300.    BYTE  btIsFirst = (BYTE)bIsFirst;
    2 o  Z/ ?; R! l: {! q

  301. 9 g2 y: E: J% }: w
  302.    const BYTE btBit00 = 0x01;
    6 ^) T. d7 |; m* L
  303.    // const BYTE btBit02 = 0x04;7 Y6 g* X- O7 @: T! i- E
  304.    const BYTE btBit06 = 0x40;3 H( B' I2 c( W) c8 H3 v
  305.    const BYTE btBit07 = 0x80;( Y2 e, V8 E, x: B
  306.    // const BYTE btERR  = btBit00;
    2 p; @, t9 o2 n2 U& [, J) m* a1 j
  307.    const BYTE btBusy = btBit07;
    6 z' s4 K" }7 t/ h
  308.    const BYTE btAtaCmd   = 0xEC;
    ( B; w; n3 @6 S/ T) I
  309.    const BYTE btAtapiCmd = 0xA1;
    ! l' E( J" |- T8 R# X8 [. R
  310. ! M8 h$ T9 {- x" I* B" A2 b
  311.    __asm/ D4 t1 K) W0 x  Z- k, l
  312.    {& O! P8 E3 v0 w4 |7 G1 p5 o$ n9 \1 P
  313.        // 必须先执行这条语句9 r  A. G& J: M; e. f
  314.        JMP EnterRing0: I2 z. k" ]8 R, w* z( Z

  315. 7 r& x% W+ J& }5 F* V7 q& T
  316.        // 定义过程" n5 L7 D* a; X! O+ }5 e4 A
  317.        // 等待IDE设备直到其不为忙为止; @3 ]* D) B$ e- Q4 I
  318.        WaitWhileBusy proc# S; K& l# I: a3 H
  319. ! A1 a( F0 z. n: |1 T. C
  320.        MOV  EBX, 1000007 N+ A! W6 _9 ~/ I5 s' M8 Q
  321.        MOV  DX, dwBaseAddress
    ! g5 C0 c1 F1 n. L
  322.        ADD  DX, 7- X. h7 R2 U1 \0 M  W' l) Y  B! ?
  323. 1 ^; W" i$ ?4 N- o
  324.        LoopWhileBusy:
    $ |" ~, g) I- p/ ^
  325. - t  ?1 ~4 k. i8 X' ?; I6 _5 D! s
  326.        DEC  EBX- Z- v8 r6 n$ Y) ]- U/ c4 M
  327.        CMP  EBX, 0' |5 P) L& J3 V' r* I! L
  328.        JZ   Timeout
      P2 g8 f/ ~  o1 x7 L
  329.        in   AL, DX
    . g. O* F3 C' F. [1 M8 i2 I* e
  330.        TEST AL, btBusy0 M' T1 E* _4 v- @+ K9 j
  331.        JNZ  LoopWhileBusy# O' m3 K0 Q3 _' M3 N
  332.        JMP  DriveReady! a4 J" T3 J+ L: d8 e

  333. " Y  P) h, k4 @) T! e# P; [
  334.        // 超时,直接退出
    8 N0 @$ V8 H: p9 @* U
  335.        Timeout:: {0 ], [% v- f/ i' `0 U
  336.        JMP  LeaveRing0
    8 B& C5 |) `% [5 z
  337.        DriveReady:
    . Y& M' ]0 P. Z
  338.        RET/ a) W8 B- q3 o. J: [
  339.        ENDP   // End of WaitWhileBusy Procedure# w  f6 V" z0 V! P0 `) V
  340. 2 F+ J- f  P$ a; ?& X( y
  341.        // 设置主盘和从盘标志
    ! x, T2 y' G, S# e! A. J
  342.        SelectDevice proc
    - M- B' {* g, D4 |. C

  343. ! `6 L* h+ k! \
  344.        MOV  DX, dwBaseAddress/ X( d% V0 b" t5 J' R6 x% G- m
  345.        ADD  DX, 6- u; A+ I- E* e" ]2 E
  346.        MOV  AL, btMasterSlave1 J  H; c8 u+ [' w

  347. ( A1 G& D& |8 ~1 d" E, y6 v8 k
  348.        out  DX, AL
    8 x4 W8 K5 f3 }/ M4 b  p
  349.        RET
    ( r1 Q9 V5 G' B' q! d
  350. 8 e# _$ X' L0 l3 B) `( Q/ R
  351.        ENDP  // End of SelectDevice Procedure
    ; o/ z1 s& |6 x; y& E* }
  352. 7 V- s- @  P5 ^
  353.        // 向IDE设备发送存取指令6 I6 X1 T3 K4 u1 ?2 F2 s4 q5 `
  354.        SendCmd proc3 L! ]1 e1 l1 \3 o  L9 x
  355. + ~4 i2 Q  e. D4 ?7 y/ f
  356.        MOV DX, dwBaseAddress
    3 k5 @. L' W4 O( A; C
  357.        ADD DX, 7
    1 a, y& n& {4 ^
  358.        MOV AL, BL // BL是主从盘标识,在过程外设置6 T  I2 ^+ {/ L* e0 a  d
  359.        out DX, AL
      r1 `% k8 }! c: z: T# X
  360.        RET& j6 u" n5 |. d6 Z+ d4 \4 h
  361.        ENDP  // End of SendCmd Procedure; q  X( {# |5 y/ O! f2 g* W
  362. ( l9 S: g- I7 g* }1 Z7 O  `. B
  363.        // Ring0代码
    6 r; B4 B: Z8 H( q/ z* n7 e5 ?" d
  364.        Ring0Proc:! D8 s1 S' w# r+ ^
  365.        PUSHAD9 ~; B; j* V+ w; n0 N9 U  @
  366.        // 查询IDE设备是否存在
    8 H$ N0 `4 r$ k) X9 P2 Q' f
  367.        MOV DX, dwBaseAddress
    . Z4 N- U/ j9 ]9 L* b
  368.        ADD DX, 7* z/ H. k# W* j
  369.        in  AL,DX, m7 K. J; f# c* m: O/ T; }7 ^# {

  370. ; l( s/ [& _2 ~$ S. x
  371.        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
    ' a& p$ {: J, [  ~9 g$ i7 x/ G
  372.        CMP AL,0xFF. t* J+ p: {- h
  373.        JZ  LeaveRing04 r) i! b( r; h' W' S7 \" t
  374.        CMP AL, 0x7F
    8 }: U  _. j( d- x  |
  375.        JZ  LeaveRing0
    1 l: \! a) a, \% O+ Q5 B- m/ s

  376. : T9 U8 E; z" `% A. n: ~: c
  377.        // 设置IDE设备存在标志$ w* F& O/ r0 H3 u. Y5 e7 }
  378.        MOV btIsIDEExist, 1
    ) A6 F$ v, j7 L' i* d

  379. . B: g7 E& T2 b
  380.        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)/ r. P' H0 E. j& `9 W# \/ G
  381.        CALL WaitWhileBusy
    ( E$ ~* w8 t& ?5 l3 s& h9 m& Y$ q
  382.        CALL SelectDevice
    % R4 S. d" s" G3 d2 C- ^# m
  383. ) x2 _; k5 B4 F: z$ V! Q$ L" T$ L
  384.        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
    ; {$ y" g# T+ H" l5 J  v
  385.        CMP  btIsFirst, 14 S- v5 |3 \" K7 r% ?1 h
  386.        JZ   LeaveRing0! V) ]" q* p$ D
  387. 6 p" |. c- \1 F' E% \3 N" w+ w; v
  388.        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
    7 }# [) t# e6 H
  389.        CALL WaitWhileBusy
    , u/ v- L  z6 S

  390. 0 X3 Q$ j3 f+ ~8 |$ G: _
  391.        // AL的值等于cBit06时,不存在驱动器,直接返回, z+ B7 ?" s. U2 }
  392.        TEST AL, btBit06; G* g7 F* ?& m8 t4 ~0 ^% C1 O
  393.        JZ   LeaveRing0
    & E' a2 C8 I! D3 O, d7 n

  394. 6 F5 j9 [. w# S" I/ p& \
  395.        // 设置驱动器存在标志
    , s( G( D* K3 k  k# S. A$ C( ~
  396.        MOV  btIsDiskExist, 1
    " x  e) x9 d$ u2 j" O6 C' R
  397. , _! e# i* b/ t) q" N. \
  398.        // 发送存取端口命令4 p# ^, I$ y9 \
  399.        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
    # U, t8 u! N/ y  X% U4 f
  400.        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
    $ N" U  W  ]; U7 I
  401.        CALL WaitWhileBusy
    ; f8 w3 F1 @0 |; v2 N
  402.        CALL SelectDevice    // 设置主从盘标识
    + ~* b: f+ Z" ]$ n: n1 v4 }  c7 f
  403.        MOV  BL, btAtaCmd      // 发送读取命令
    5 m: y) A6 Z! _5 l
  404.        CALL SendCmd
    9 h* b+ x; c2 r1 b+ Y
  405.        CALL WaitWhileBusy
    " s% q  ]0 m  }+ s* A
  406. / R" O; T5 p; J" g6 y, l! B
  407.        // 检查是否出错7 d4 A1 a3 ?# _( q1 u+ H! X
  408.        MOV  DX, dwBaseAddress; X0 K7 Z$ e% K' {: b; @
  409.        ADD  DX, 7
    4 n4 @4 V% M# V/ ]6 Y% V
  410. 9 G+ i7 o1 H8 B5 S: o9 A0 y7 W3 ^! e
  411.        in   AL, DX
    ' n' U. k0 G) G; K
  412. # O9 ~2 e( N4 t% a9 R3 q7 U8 d
  413.        TEST AL, btBit00
    ' a3 g4 `" m% A) o
  414.        JZ   RetrieveInfo   // 没有错误时则读数据% i% S' o9 |. B0 A' V

  415. ' {: R/ d8 T: n- v/ o& O. c
  416.        // 如果出错,则进一步尝试使用ATAPI设备命令
    : w( f, H( U) Y3 M& o2 j/ ~
  417.        CALL WaitWhileBusy
      P$ @: _+ y" Q! l) P  y
  418.        CALL SelectDevice5 L- E* {% s1 S" x# D
  419.        MOV  BL, btAtapiCmd7 }+ W* Z7 w$ c; g+ Y( c  }- G
  420.        CALL SendCmd
    5 x9 ]1 a! }) A  a/ J9 Y3 K
  421.        CALL WaitWhileBusy
    & z4 o3 R% o3 V- A
  422. . F0 e: z1 g. A, t7 L6 F
  423.        // 检查是否还出错
    : O% D* |. c9 n3 ?
  424.        MOV  DX, dwBaseAddress
    ; }* e2 I" n8 h1 b8 I+ ]: }
  425.        ADD  DX, 7, ?( R9 H- y4 K- L# t( i
  426.        in   AL, DX
    / s& \+ W% i$ l# m4 C4 n
  427.        TEST AL, btBit001 J. k+ E* r% {' P! S* j
  428.        JZ   RetrieveInfo   // 没有错误时则读数据$ U+ C0 K1 l- f# u- o
  429.        JMP  LeaveRing0     // 如果还是出错,直接返回% u  ?# u7 v' z$ j
  430. + P0 D: g. p9 S# S% F7 u
  431.        // 读取数据
    5 l3 l3 w* t4 t
  432.        RetrieveInfo:
    2 j1 X9 @. l5 X, V
  433. " ~$ D- O. Q5 z
  434.        LEA  EDI, wOutDataBuf# \  R  N! @5 c& N; p4 o6 f5 J. B
  435.        MOV  ECX, 256! M6 ?" g4 o' G/ z
  436.        MOV  DX, dwBaseAddress  Q: E4 \  l9 t7 I
  437.        CLD
    , ~; z. y, c2 @, p3 d* O
  438.   G2 P; G5 |% [) K9 V
  439.        REP  INSW  O3 M- |5 y0 C3 h( ]+ m2 z

  440. 4 A- h6 c) C; s4 A
  441.        // 退出Ring0代码
    - g0 N+ D- W/ Q+ l8 @! q
  442.        LeaveRing0:, h$ m/ b8 _: M# [; [# b5 s! ]- B8 B8 ]

  443. ' W+ f" A# ^$ n2 j. n  F, g) @
  444.        POPAD/ E1 g: z" Q: P3 A  |/ c
  445.        IRETD# S$ A1 K- s7 z7 m( |; |

  446. ) {5 ]; A: F2 f( n: b
  447.        // 激活Ring0代码
    - Y. g( q% V; M( B
  448.        EnterRing0:
      U2 F. p! w1 z2 N' }$ D
  449. * ~+ b3 Z6 f  a2 A) }+ B' P
  450.        // 修改中断门2 g" o, y/ D: W+ K
  451.        SIDT FWORD PTR btIDTR1/ M) w7 c/ i( A8 Y% ~
  452.        MOV EAX, DWORD PTR btIDTR1 + 02h
    $ i; a% j, L! [7 F/ e8 p. V+ J
  453.        ADD EAX, nHookExceptionNo * 08h + 04h& w' F) C& W, R2 g
  454.        CLI! M: Z/ C8 `2 B: P  l
  455. 9 }5 Z: x, o. g, Q
  456.        // 保存原异常处理例程入口
    1 G1 Y0 b& I' ^# X
  457.        MOV ECX, DWORD PTR [EAX]8 T9 e- U) d4 f0 v! N9 L& X
  458.        MOV CX, WORD PTR [EAX-04h]( {1 O8 E$ Z* K0 n6 d* J
  459.        MOV dwOldExceptionHook, ECX$ O; u, A2 q3 Y. }; J( Z+ K+ D

  460. # c9 d$ u3 X) x* D/ A! @8 f
  461.        // 指定新入口
    : [/ Q0 x; `1 y/ z& u! m
  462.        LEA EBX, Ring0Proc
    / W9 H& |: Z1 y( x8 G7 I* x8 Z- N
  463.        MOV WORD PTR [EAX-04h],BX
    5 D3 z% b. |& T. N& k: l' Q9 [
  464.        SHR EBX, 10h
    1 Y! h; ]: w2 A1 F5 C  v( V. @/ S
  465.        MOV WORD PTR[EAX+02h], BX
    2 P9 ~5 w* h2 {2 F7 p
  466. + u6 c7 l4 a# i; v: M
  467.        // 激活Ring0代码9 t2 {0 P9 [! M
  468.        INT nHookExceptionNo* }; ?( s4 e  W3 d) h* P5 e

  469. 3 u  p4 ~. T3 t! Z1 p. l/ C
  470.        // 复原入口0 o% ~. q% ~# ^
  471.        MOV ECX,dwOldExceptionHook
    9 K) D' X+ o, ^% G$ L
  472.        MOV WORD PTR[EAX-04h], CX7 ?& _0 w# n: D
  473.        SHR ECX,10h! O4 X$ u: r% G
  474.        MOV WORD PTR[EAX+02h], CX
    % h- V; C  D: u* }# Z7 Y- E# y
  475.        STI8 r: m$ F" V0 K; ?' U! d, @
  476.    }
    ; t4 I: h" \/ p$ V
  477.    if(!bIsFirst)
    8 C6 V( a9 h) g
  478.    {
    ' J. o# r8 ]7 K
  479.        bIsIDEExist  = (bool)btIsIDEExist;
    : t. {; i8 d' A, D% E' {3 `* C
  480.        bIsDiskExist = (bool)btIsDiskExist;" x- v- O2 {, i6 o0 Q5 g  ]
  481.        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
    ' o, o% d/ Z+ M, _- f, @
  482.    }" k- w1 V+ `$ m8 k+ H% x, L
  483. }
    , s7 F$ Y0 j9 Q
  484. //---------------------------------------------------------------------------2 S. y1 U" C( D# G7 b% S
  485. // 调用方法:) J% k" t( F9 n& e
  486. void __fastcall TForm1::Button1Click(TObject *Sender)
    3 b$ v0 @* b' [/ k! `* z
  487. {" x# l1 f: `0 N! ]2 Z
  488.    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
    + m& m. m& ^" h" p  U0 F3 ?3 S2 s
  489. }
复制代码
发表于 2005-8-15 01:00:45 | 显示全部楼层
晕乎乎。。。怎么看8 洞阿
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-6-18 08:47 , Processed in 0.019074 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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