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

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

[复制链接]
发表于 2005-8-11 11:42:04 | 显示全部楼层 |阅读模式
  1. #include <WinIOCtl.h>
    * E2 n5 t& `8 ]% u0 j
  2. #include <stdio.h>
    5 Z6 F5 Z/ d$ D: H. o  u: M* `+ j
  3. 6 g' W: D. ~9 \0 \2 t0 a& t
  4. #pragma inline1 h0 Q8 O5 F" M4 Z' R
  5. //---------------------------------------------------------------------------
    ( C- m: D: n* u# x
  6. // IDE NT/2000/XP专用变量
    # d/ v6 [3 B/ Y9 o5 h
  7. #define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
    - N- B( t. C9 q: p" |
  8. #define DFP_GET_VERSION         SMART_GET_VERSION
    5 L" H+ g$ J" \! l3 S) D' n! Q
  9. #define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND# Q" K: ^1 D$ ~, L2 F
  10. #define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA+ A! S# X5 J9 V( H" l5 E

  11. 3 t$ W7 X6 u6 x
  12. const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令. J$ I/ v" V# {9 n: k/ t  H) j
  13. const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令) }* D- j; z* H- i
  14. & Y$ W0 y, G/ D9 ~$ T; K
  15. const int MAX_IDE_DRIVES = 4;  `, U6 x/ W4 i8 b; ?
  16. - ^3 I+ d. u& W2 ?! ^2 [
  17. // SCSI专用变量
    * ~# w, l) }. J- G0 h- ~
  18. const DWORD FILE_DEVICE_SCSI             = 0x0000001B;
    3 j; M; h7 p  }  y( |% J8 e
  19. const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);+ `1 i4 O$ x1 p0 Z$ D, c2 l
  20. const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
    - o, \1 c- m4 R
  21. const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
    9 Q0 D: r: i) X1 x$ s; ?
  22. & U3 v0 K: d  E  n+ ~5 M. N
  23. typedef struct _SRB_IO_CONTROL
    : ~: z5 t- F  t
  24. {
    : o" {* U" J3 H+ y. O
  25.    ULONG HeaderLength;
    " V9 H+ b2 E+ R% D" ?( C- j6 p
  26.    UCHAR Signature[8];, ^+ t" V2 A" G5 W2 ?  R
  27.    ULONG Timeout;
    # P% P; k" g' u2 ^2 r& \  i
  28.    ULONG ControlCode;
    % H! p5 S4 @4 e
  29.    ULONG ReturnCode;6 X$ i' c; r0 j. R5 R
  30.    ULONG Length;+ [6 u- o! C% ^; D
  31. }SRB_IO_CONTROL, *PSRB_IO_CONTROL;
    7 |* [+ i2 B! Z1 B7 |7 N
  32. , o9 b+ J8 G) }( h5 v8 n5 L( y8 f
  33. // 读取的主函数" n- i+ Z3 ?( r. L6 r
  34. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);! r, N7 X& Q* V; n  ]

  35. 7 x& }1 F, {' B' v6 G1 r4 M
  36. // 辅助函数* N+ h  v+ Z1 K: z' m" s) W
  37. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);1 x, f9 E, _' K* i$ ?
  38. // NT/2000/XP函数
    " M' \5 p5 D! w' `" ?2 e
  39. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
    3 L  Z' R2 v$ ]5 @) @2 v* a' _
  40. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,, z& s. Q: ?( q3 l/ H
  41.        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
    9 Y5 \- u! ^0 X+ N" V: n; I- {
  42.        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);0 [  t" S5 t, r* Z/ }
  43. // Windows 9X函数
    9 S9 C( {5 f3 E8 E) K* Q* j; _
  44. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);( F# A9 T4 ?, e* B) X
  45. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,% \6 L: V" E6 u) F+ g
  46.        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
    9 \7 P  H% k! l' V$ \% v
  47. 0 Z; T/ _5 a0 {
  48. // SCSI读取函数(for NT/2000/XP)
    + j  L/ C* J# |, w. v+ A/ Y& M" L
  49. String __fastcall ReadIDEDriveAsScsiDriveOnNT();
    , ]9 U) T# x+ Q' \# L+ z* x: X
  50. //---------------------------------------------------------------------------5 \; n+ f+ V) ^) A5 V2 @- [* e
  51. // ReadPhysicalDrive; i: F* \- ?3 \* k4 o+ c2 G
  52. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)! t2 {" S2 Y. n
  53. {3 Q/ o  V$ D, f! U1 Q! A% y
  54.    switch(Win32Platform)& T) ]! d( I( u
  55.    {( ^' y" b) n  h# w* I
  56.        case VER_PLATFORM_WIN32_WINDOWS:  `# A0 F' b3 V/ K" A+ [+ O
  57.            ReadPhysicalDriveOnW9X(pSerList, pModeList);
    0 g8 g1 D4 b3 u9 f5 R7 {
  58.            break;
    8 \4 m$ K5 [8 x
  59.        case VER_PLATFORM_WIN32_NT:7 f3 Z3 o' ?+ o7 s* S& R2 b
  60.            ReadPhysicalDriveOnNT(pSerList, pModeList);
    1 Q6 ]4 D& p2 s2 i0 Y; `; x
  61.            break;
    7 R; f2 G( K/ L' Z8 _! v  }1 p) s
  62.        default:3 e$ T0 o+ s2 ^7 b( M4 g
  63.            break;
    & x7 W  P1 w6 H& G8 O+ F
  64.    }. i/ u8 d& E. A- D- W, H
  65. }
    8 m) w6 z' T6 w# X) b
  66. //---------------------------------------------------------------------------; S5 J! M7 [4 h- _/ E: G" E
  67. // ConvertToString
    : Z/ X5 n: w$ F! h8 n9 p
  68. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
    5 J( G! n8 l) l  T+ G, w9 M
  69. {* ?- t# G9 E1 e% C# y! G# O
  70.    static char szResBuf[1024];
    ' I1 h. b- u. M% h3 ]4 S* E6 F6 s
  71.    int nIndex = 0;7 m, t! K" b5 @0 V  ]; c
  72.    int nPosition = 0;7 F; p4 y! h8 e# ?9 g0 G3 A
  73. # t6 c" m+ ]$ v4 ~& v  W
  74.    // Each integer has two characters stored in it backwards1 F7 X7 q. S2 T" ?# q4 s7 X" p
  75.    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)" |$ r6 \  |/ v
  76.    {
    & \. _/ r/ d5 d- h/ ]( y. O
  77.        // Get high BYTE for 1st character5 M$ x1 ]* A3 S- t+ v! S4 Y- C
  78.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);' e, _3 [2 q& U9 o
  79.        nPosition++;7 d: |3 O6 }# [% _' O

  80. 2 `( q# V7 w4 D$ {8 Z4 W
  81.        // Get low BYTE for 2nd character
    . A; z* s/ G6 C
  82.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);; c: k/ e- g" ?9 M. D
  83.        nPosition++;0 z3 M, {$ _7 Q: w% y7 T. Q/ E& R
  84.    }. z8 P. s" B$ D: j: z9 }9 j1 @
  85. # K, W5 `5 ]; b- E3 h
  86.    // End the string1 ^  ?, i* g& t4 W5 Q# S
  87.    szResBuf[nPosition] = '\0';
    ! R1 i8 ?8 Q9 c$ v6 V6 z
  88. ) I2 N* s8 m4 X4 O1 @
  89.    // Cut off the trailing blanks% ~! S/ [# c1 @' ?& j) J/ P4 P
  90.    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)7 v* g- U' B7 P- |
  91.        szResBuf[nIndex] = '\0';3 @' k& G: h1 U7 N/ Y
  92. " \5 q5 t7 K4 ], r+ C6 ^3 ?
  93.    return szResBuf;
    + l1 b1 l9 V  _, ~
  94. }8 K6 ], y$ O2 v( v
  95. //---------------------------------------------------------------------------+ l) a( N7 j" N  r
  96. // Winndows NT4/2000/XP 代码
    3 L' e, a0 K' w
  97. //---------------------------------------------------------------------------1 Y0 y3 j/ l4 W$ e0 w5 p3 Y" T
  98. // ReadPhysicalDriveOnNT
    5 S9 S5 a* i, V) r
  99. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)- `: G3 B) _' e* o- H
  100. {
    6 L; P' Q: n' ]3 g* Z) P/ w( Q/ K/ M
  101.    // 输出参数( ^* p  ~2 Y1 f- `* U& t5 z
  102.    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
      r$ \8 x2 v' }" {

  103. $ _! b! R* W4 y4 @- G
  104.    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)  J+ v1 q' E; G4 o8 F9 U
  105.    {0 y! {2 Z: q* `) `. O% N5 p
  106.        HANDLE hPhysicalDriveIOCTL;+ J4 ~" b8 i1 T/ x0 }  S% i( l
  107.        char szDriveName[32];1 P: [) H. i4 y4 }
  108. ' a$ W! M$ _5 L: v1 q2 f, y) b5 {) U
  109.        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
    1 b* I- {! W3 R: P, G7 X
  110.        hPhysicalDriveIOCTL = CreateFile(szDriveName,
    4 V: \% L1 F* u& A+ M* E" C
  111.                        GENERIC_READ | GENERIC_WRITE,
    5 f0 {) m  i7 K) Z% A6 R
  112.                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,8 h: i7 q# g0 G, d# M1 U
  113.                        OPEN_EXISTING, 0, NULL);
    + [  X8 w7 U7 k5 G8 D

  114. 4 B8 u* j! M& e& h7 t1 C* Z$ y: A
  115.        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE); M8 w* C$ H# x( \6 l% Q  e
  116.        {- h! n6 q& E+ |; f- ^1 @  |$ [4 `- P
  117.            DWORD dwBytesReturned = 0;
    ) n) T" I* \$ f5 }( T
  118.            GETVERSIONOUTPARAMS gvopVersionParams;
    4 a8 N1 s) \# ]" F# c$ `0 ^
  119. " s" O; n2 O  d7 o0 x
  120.            // Get the version, etc of PhysicalDrive IOCTL
    ' R5 q2 j: [7 P" @7 ?3 |
  121.            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));* g* P# d! I9 K* U
  122. 7 ?5 R( q8 S( y2 N: m% ]
  123.            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,$ r' ?) G; g5 m! |5 c
  124.                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
    8 J& x& y3 ]8 |& L- ~7 m: e1 V
  125.                    &dwBytesReturned, NULL))
    7 c( T7 G  d, k0 I1 K
  126.            {3 }) z5 X3 J4 j: p: |! K6 C
  127.                continue;
    8 x/ _; r; _1 u3 Y- E3 D9 G4 W
  128.            }
    , X7 K' g# U+ M6 X
  129. 6 _& p# `( k7 w# p( B
  130.            if(gvopVersionParams.bIDEDeviceMap > 0)
    3 Q- [9 h% _8 B4 W8 D, P
  131.            {3 P; e5 K6 T$ v) l! k
  132.                // IDE or ATAPI IDENTIFY cmd/ G7 X+ S" d$ q$ l4 g) ^2 o
  133.                BYTE btIDCmd = 0;) M" x: V1 B9 o
  134.                SENDCMDINPARAMS InParams;) ~6 B( `2 {( m  H4 U7 J8 ~
  135.                // Now, get the ID sector for all IDE devices in the system.3 f: D1 e' Z" v$ H
  136.                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
    4 ]* ^$ `! F6 D' y3 d9 k
  137.                // otherwise use the IDE_ATA_IDENTIFY command) G' b' \3 ?2 o8 q" {9 u* ^
  138.                // 具体所得结果请参考头文件中的说明7 f, q8 ?( Y5 ?" H9 {
  139.                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?, s- u0 ~2 w/ Y1 c' L+ x& ^) M
  140.                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
    ; o* K& z0 K! J" I+ a
  141.                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));( N/ j. O' l# A" Z
  142.                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));% [6 T9 L6 E" C

  143. ! c2 v. o* ~9 x) L, A' O( U0 Y: g
  144.                if(DoIdentify(hPhysicalDriveIOCTL,  t5 o( @8 J# ~
  145.                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
    . G( p4 p" H+ D8 p
  146.                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
    8 M- _; Z6 P, I3 c
  147.                {: \% E& b* U: B; R) y2 |6 T
  148.                    DWORD dwDiskData[256];
    , b( \# X- q# Z6 ~- f
  149.                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件) S9 K/ |  e+ d  g8 j5 m0 Z
  150.                    char szSerialNumber[21];
    ' p2 U# q$ ]; X- }2 _, ~
  151.                    char szModelNumber[41];
    , ?# y# d$ a- @4 r7 }3 \: y
  152. 6 M$ C; z* o+ Y& i: P+ u7 h
  153.                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;0 o- v$ ^! N' k0 u5 n! B# r1 P
  154.                    for(int i=0; i < 256; i++)9 P# B* M( S! a! ]9 O2 T
  155.                        dwDiskData = pIDSector;
    7 ^# y& A  v" [2 e0 y+ I$ [9 k
  156.                    // 取系列号
    / l0 j! `4 e# z- j8 Y8 C
  157.                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));* ~, [; r. {, p' i. u
  158.                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));# a. j3 I$ [) N' x" V5 ^
  159. 9 v1 Z( e. X2 J# g# g
  160.                    // 取模型号
    7 n8 F  Y* d: b) X* J8 L3 i% t
  161.                    ZeroMemory(szModelNumber, sizeof(szModelNumber));
    % m8 i" B) d3 L" J
  162.                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));; O3 B  B- q$ `% j0 k& T8 t  P9 \

  163. , r6 ?7 {8 }9 }' O, U& e1 O# a' [
  164.                    pSerList->Add(szSerialNumber);2 |8 a' U" W  _* E
  165.                    pModeList->Add(szModelNumber);" s* D+ H1 f& Z, R
  166.                }
    ! C# l+ P2 e4 r+ ]# E( w. g
  167.            }4 B4 Y/ u8 Y9 I" l: d/ R
  168.            CloseHandle (hPhysicalDriveIOCTL);- U: |7 Z  b2 j) C' [' O& Q! E% U" R
  169.        }5 ~7 l* @8 {( v4 t# `! [
  170.    }% s! m9 p3 r+ J; x! v5 Z/ i
  171. }
    2 I" P! t/ i# Q  k+ |5 D
  172. //---------------------------------------------------------------------------
    ! r  i3 Q, B" o% h8 d! L( c6 Z
  173. // DoIdentify: r: m* `$ k, d2 p# _- j# f
  174. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
    0 H5 @6 @8 m9 C5 T
  175.              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,- n5 ]9 E6 q, k* X; u1 X1 p
  176.              PDWORD pdwBytesReturned)9 M4 U# _  m5 H& D; d( e) q
  177. {
    * a9 \: C1 K9 Y0 D
  178.    // Set up data structures for IDENTIFY command.7 @  `0 T6 s4 q* R/ p( d/ b9 y
  179.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;, G# t7 i) O, o
  180.    pSCIP->irDriveRegs.bFeaturesReg = 0;
    ! s! N7 Z0 Z1 _
  181.    pSCIP->irDriveRegs.bSectorCountReg  = 1;
    8 E% S  [* C+ x+ T6 |
  182.    pSCIP->irDriveRegs.bSectorNumberReg = 1;& V, L0 Y( C# c# \4 ~. L3 ]
  183.    pSCIP->irDriveRegs.bCylLowReg  = 0;
      [* C' O- B! X  `; F
  184.    pSCIP->irDriveRegs.bCylHighReg = 0;+ c$ w& T* f- u+ o# O6 Z

  185. 8 x' m) d5 n- Q1 y, p
  186.    // Compute the drive number.(主盘和从盘所对应的值是不一样的)
    4 g$ W4 K# f) F- L! ~
  187.    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;6 g! k8 s$ b' Q6 F

  188. 3 r( ~7 ]* D& K
  189.    // The command can either be IDE identify or ATAPI identify.
      B; P' N7 g  }- o2 u
  190.    pSCIP->irDriveRegs.bCommandReg = btIDCmd;
    2 v2 y6 Q# n2 T6 W. {( m8 L
  191.    pSCIP->bDriveNumber = btDriveNum;
    9 G9 Q# Z3 p* k  U& i& R
  192.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;' f3 y, n/ k8 o$ U
  193. ) ?4 L5 t: j" z( U' a' ?
  194.    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
    ; u( L$ y  Z% S7 i( ]
  195.           (LPVOID)pSCIP,
    2 a! L6 x* u  i, V* ]1 l" n& F1 Z
  196.           sizeof(SENDCMDINPARAMS) - 1,) q+ }7 s1 s' n; ?3 |- q" s
  197.           (LPVOID)pSCOP,
    , n2 F# `/ s5 z; D  w  T2 i1 g+ S. \
  198.           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,4 ]: |* k! V" Z1 F; m
  199.           pdwBytesReturned, NULL);9 j& Q; ]6 u# W8 Z
  200. }
    4 @+ _. P$ i9 B6 q
  201. //---------------------------------------------------------------------------
    - ~* |7 ?6 `- \1 }/ [8 Z
  202. // Windows 95/98/ME 代码# ]- W" z+ G! F4 h2 R! P( G5 @
  203. //---------------------------------------------------------------------------0 M, v& K# @# [- s1 R7 l
  204. // ReadPhysicalDriveOnW9X* ]! @) y0 _2 N7 Z4 l) T0 l
  205. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)" _0 N, Q7 g" E' \2 Z7 f' T& ~
  206. {8 b4 L% D  l+ `. A
  207.    WORD wOutData[256];
    4 o) h$ u$ C* o! o0 M
  208.    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);8 |! [1 I4 l; N0 l( X" E

  209. 0 `$ U( o& T6 k! U, R0 Y: v3 C
  210.    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。6 D0 O7 \* r# R9 j0 Q0 v
  211.    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
    , O, Z0 k: ?- t7 T
  212.    // 避免蓝屏的出现。(期待高人能指出原因)
    8 ?% t4 L- ]# _3 p: c
  213.    for(int nDrive = 0; nDrive < 8; nDrive++)
    ' \6 z# w# [! U
  214.    {
    2 x! e# d' e$ D, O: Q
  215.        WORD dwBaseAddress;5 O7 M+ M! Q) J  c: M
  216.        BYTE btMasterSlave;         // Master Or Slave
    & k6 K7 Y9 D- k6 @
  217.        bool bIsIDEExist;
    ) e3 u0 \( a% i) M2 q, s
  218.        bool IsDiskExist;
    " Q4 K$ J- |. D, F+ I3 a: p
  219. * s+ q! B, _* l8 X! o, r4 ?
  220.        switch(nDrive / 2)
      J8 q. G2 n" k5 E9 J
  221.        {
    # D/ {5 {6 p: t$ p; H- B4 K
  222.            case 0: dwBaseAddress = 0x01F0; break;, B& E: n9 F- L+ w* P' D
  223.            case 1: dwBaseAddress = 0x0170; break;
    - o. e- K3 q$ f' l( y4 S1 F) J
  224.            case 2: dwBaseAddress = 0x01E8; break;
    % Y& B& v6 x4 n) F: ^
  225.            case 3: dwBaseAddress = 0x0168; break;
    % ?0 L" E7 c! ?# Y! i! A
  226.        }+ L$ a, j& l$ U1 f) v4 W4 C
  227. % p. w* |2 @& j
  228.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);7 j- d' x4 u! E) A3 w( `5 l

  229. ) p- x/ m1 @# \$ h. X, {7 ~1 M/ @
  230.        // 进入Ring0( \# ^7 K! Y; M) O
  231.        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,) Y' j+ A5 r/ g- H
  232.                bIsIDEExist, IsDiskExist, wOutData);
    7 Q6 S" Y, Y; f( C- f/ M
  233.    }
    5 B* y( s6 t6 ?9 _! ~* e7 W$ y

  234. : ~5 L% S8 v! b9 I3 }: ]3 b7 Y. Y
  235.    // 开始读取
    * ?4 U4 f+ r/ O# ?' q
  236.    for(int nDrive = 0; nDrive < 8; nDrive++)
    - ?9 V, t9 A# u
  237.    {
    3 b0 `, A3 z; c
  238.        WORD dwBaseAddress;$ s) w8 l$ P. M/ X
  239.        BYTE btMasterSlave;         // Master Or Slave
    - [( }0 l, u) T# [& s9 S- G, l% c
  240.        bool bIsIDEExist;2 X& {) G; I9 x
  241.        bool bIsDiskExist;
    9 d* K4 p6 H1 \( `7 o
  242.        switch(nDrive / 2); D1 q; Y9 c) P2 |- b+ f# |
  243.        {% G! D/ o# ^* }# V: ]: ]
  244.            case 0: dwBaseAddress = 0x01F0; break;, F& ~( {8 D4 |" P
  245.            case 1: dwBaseAddress = 0x0170; break;2 F5 x1 h7 X. S
  246.            case 2: dwBaseAddress = 0x01E8; break;5 [' {2 h7 d0 A5 c8 A9 }4 `
  247.            case 3: dwBaseAddress = 0x0168; break;+ I) r5 I6 i0 ~
  248.        }
    4 w9 H, j( a. {" _- E% `9 g  h

  249. 1 [( d1 V9 O" r: T, U$ |
  250.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
    2 W6 @2 r0 a: T( V

  251. 7 @3 F2 [7 t% L4 Z0 t6 H4 v. o
  252.        // 进入Ring04 L6 [, |; Y' ]4 g
  253.        bIsIDEExist  = false;+ Y' g% T* T, v3 L. U
  254.        bIsDiskExist = false;
    5 m+ \# d* Y( C6 {- ^9 v
  255.        ZeroMemory(wOutData, sizeof(wOutData));/ w' e3 X% i9 g  v

  256. 5 B. a8 y+ C$ j# K" y+ }
  257.        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
    & n" p% z8 ?: o& \; B
  258.                bIsIDEExist, bIsDiskExist, wOutData);
    4 |. _' h. Z, Q: D, W
  259. * X9 t2 `1 B( i! f+ o2 S
  260.        if(bIsIDEExist && bIsDiskExist)
    % X* r' O9 i: @% G1 c) i$ y# @1 A
  261.        {/ p; Q' u2 E; T8 `* W
  262.            DWORD dwDiskData[256];
    $ u2 }+ D- q" E( n% ^, Z
  263.            char  szSerialNumber[21];# c, Z, _( f/ n# h; G
  264.            char  szModelNumber[41];4 P/ v2 g* D' _

  265. 0 z( L* u3 s( d  }
  266.            for(int k=0; k < 256; k++)
    . l! q# _  P' U# N! K8 z
  267.                dwDiskData[k] = wOutData[k];, K4 l$ s4 L# S( }3 `) X- k
  268. 6 t' j- d/ x3 d4 ]& e# \; h
  269.            // 取系列号1 K* `4 }( y9 M' @8 b7 i1 S4 c
  270.            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));- W4 ?7 n! c1 x3 F1 h/ H4 E
  271.            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));6 Z- ?6 @& t3 o$ l5 U* J
  272. % V8 A0 _( M4 l
  273.            // 取模型号% L2 u" ^5 K# [4 @
  274.            ZeroMemory(szModelNumber, sizeof(szModelNumber));
    / {+ L$ I& o) e/ @9 `
  275.            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
    % X1 M6 ^' w  d3 S& N7 L, n6 ^" n

  276. ! g) g1 n' k' I/ J0 Y. N
  277.            pSerList->Add(szSerialNumber);
    ) M7 s, L3 k8 u) j; M) c
  278.            pModeList->Add(szModelNumber);7 d* N$ U. @- N* C
  279.        }9 [3 e; p& i/ \; ^/ k& V
  280.    }% x* L5 j3 J7 X4 k8 c& q# E
  281.    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
    1 L% M" n1 r7 X( L3 C5 f) d
  282. }' g6 x! W  h% P5 I
  283. //---------------------------------------------------------------------------. G3 x% y3 Y6 C
  284. // ReadPhysicalDriveOnW9X_Ring0()
    $ d& b* I+ n, j, [- q1 B" v
  285. //0 \$ u* f2 ~# f- K. X4 g/ N
  286. // dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h9 L9 w/ r: O* P- @! U4 ~
  287. // btMasterSlave = Master(0xA0) Or Slave(0xB0)
    3 c6 y$ G. `* a/ R
  288. //---------------------------------------------------------------------------3 Z2 c1 ^( m" S# m1 u( @. k
  289. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,1 p3 p$ A6 ~, _& V2 q5 i9 `
  290.        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData), W4 k& V6 O- g2 D
  291. {
    / A0 y4 E3 a$ L) @$ Z2 d" e( K
  292.    BYTE  btIDTR1[6];  z1 A( i: `5 m( d& o3 i* d) X3 o
  293.    DWORD dwOldExceptionHook;
    ' M$ o1 k3 h, ?" u3 V) b/ f* D
  294.    const int nHookExceptionNo = 5;
    " A) m% i1 I: d% i! }% B
  295. 8 j2 M" u1 g0 z" G/ R
  296.    BYTE  btIsIDEExist = 0;7 T* x4 y5 c8 o& A9 ?
  297.    BYTE  btIsDiskExist = 0;
    , `) g' e: o+ x. E- W
  298.    WORD  wOutDataBuf[256];5 `% H( ], N1 b, F& j4 B
  299. / t  m; I4 y3 Z) O3 P. K/ b9 q  a* c
  300.    BYTE  btIsFirst = (BYTE)bIsFirst;/ }! o. L1 y' f
  301. ! l- O. H/ k0 B" H
  302.    const BYTE btBit00 = 0x01;
    ; P7 D' _- z1 F) a
  303.    // const BYTE btBit02 = 0x04;
    ) H- n1 q2 C7 {, Y4 m( c
  304.    const BYTE btBit06 = 0x40;- [5 m& k) }: X5 L  G$ ^
  305.    const BYTE btBit07 = 0x80;
    - _) }% c- e2 c! |" Y
  306.    // const BYTE btERR  = btBit00;
    & }, ^1 }" n* S, `- \. G
  307.    const BYTE btBusy = btBit07;- @1 a( G6 [- ~  o. W8 I' ^
  308.    const BYTE btAtaCmd   = 0xEC;
    ; T1 ]/ p8 S1 e
  309.    const BYTE btAtapiCmd = 0xA1;
    ( t" D$ p7 o, g6 r0 j) W4 G0 U
  310. 7 n: W( P) z: F; A* v6 H
  311.    __asm9 i7 N# S2 w3 k2 w- Z4 e. x$ m
  312.    {/ ~' V6 ?$ U7 P# [& y
  313.        // 必须先执行这条语句
    # f% {5 Y+ v8 u( G$ q% a1 l$ W/ e% x
  314.        JMP EnterRing0# `+ t' P. d/ `% ]" s0 m0 d; b

  315. $ D0 X0 ?" }: u6 g. e
  316.        // 定义过程" E. v' O$ M% g' p- \% R
  317.        // 等待IDE设备直到其不为忙为止( V% A, ]! m2 W. c, `! D: C7 V
  318.        WaitWhileBusy proc+ R! `9 }# x- k

  319. 8 w; B* ?: H3 N: f; y; A6 B8 h
  320.        MOV  EBX, 100000
    $ ^, A5 w* c  ?' A4 r# \6 s* Y& y
  321.        MOV  DX, dwBaseAddress
    ; v: }% B1 N1 i2 v$ O" X4 N
  322.        ADD  DX, 7& X* x" |1 h0 K+ Y& W: N6 Q
  323. + ]$ }- b/ c- e& u. u
  324.        LoopWhileBusy:
    + p/ `' \5 x  Y# {
  325. 1 H# d! f! n) A6 p( ^7 r
  326.        DEC  EBX% a2 @# \- I7 J: _
  327.        CMP  EBX, 0) m: W/ b+ |: F4 }2 u) [
  328.        JZ   Timeout
    , I  q# v: ^5 j8 i
  329.        in   AL, DX! P1 s& p2 @5 J' d$ C4 L% P) s8 B
  330.        TEST AL, btBusy
    & j* g$ {; o6 b+ _
  331.        JNZ  LoopWhileBusy# H: [& @* Y  S/ W3 ?
  332.        JMP  DriveReady  N$ y; ]4 |, K. X  m9 j3 c

  333. ( o+ @( e6 G: w' ]
  334.        // 超时,直接退出. |1 s' ^! Q4 }1 x2 ]; y0 X: Z
  335.        Timeout:( J& n3 U2 Q+ O& u* z* A
  336.        JMP  LeaveRing0
      f( `# U* `6 A6 B/ r
  337.        DriveReady:
    & h( H" p, @/ m+ c
  338.        RET
    1 ^% o& M3 Y, m0 E( V, S- Z7 S
  339.        ENDP   // End of WaitWhileBusy Procedure7 A* n. }# ]9 r" k+ @" [3 ]- y) |0 t/ R
  340. - o8 @& D  p# _1 C6 N( A# I7 a" }
  341.        // 设置主盘和从盘标志; R. B" g) ]& V: O+ k
  342.        SelectDevice proc
    2 c6 i' y; J  i- K9 s: _
  343. 7 b/ {6 }' O: G1 [. L3 v8 }
  344.        MOV  DX, dwBaseAddress
    % a" I2 d5 V- Q) E
  345.        ADD  DX, 6- U9 O9 A6 |/ s. Y9 e8 j
  346.        MOV  AL, btMasterSlave
    9 A. J1 |% d2 r3 l  x$ U  y

  347. + Y* n2 M' q- ~. C( g4 j9 m
  348.        out  DX, AL+ u! ]% N8 L" C) N  U2 s0 x% W$ y$ s
  349.        RET
    * Q2 g1 u, w; N
  350. 0 a' G& c3 @/ @
  351.        ENDP  // End of SelectDevice Procedure  g8 |) s1 R/ C* O# P
  352. " w1 x5 F' S+ m1 ?$ S2 t
  353.        // 向IDE设备发送存取指令& d% M) e8 _6 O- e$ r! r6 ]
  354.        SendCmd proc
    . C9 l4 l4 \9 ^- |' I" T0 C
  355. + Z9 N! c7 ]% r% d: z' E
  356.        MOV DX, dwBaseAddress: s8 s+ c5 o( j4 ?2 X+ ?0 O
  357.        ADD DX, 7! p. c4 n. m: |- i& N2 w* M
  358.        MOV AL, BL // BL是主从盘标识,在过程外设置
    9 ]% f+ f# y* J" C; u. S! G, G
  359.        out DX, AL" {/ ]6 U, p) S( z
  360.        RET: ?9 D, G1 Q( ~& P8 w# H
  361.        ENDP  // End of SendCmd Procedure, F* H, D5 w8 p( ~; ~

  362. . n  T- H  W! b, O+ x4 b* x
  363.        // Ring0代码
    0 o. M- d# j$ S" d
  364.        Ring0Proc:
    4 {. `% |. o/ t! _- d/ p
  365.        PUSHAD* F* Z3 V) K1 T5 O8 W) d
  366.        // 查询IDE设备是否存在- b6 w5 F: C/ C% @3 t# G* T+ P
  367.        MOV DX, dwBaseAddress
    5 a: Z. A9 {8 `( A
  368.        ADD DX, 7
    ' d7 \' ?' _/ s+ b
  369.        in  AL,DX
    + R% P# U' H1 N- K
  370. 3 \6 A" u2 m! n/ k
  371.        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
    8 A. F7 N* V$ T$ h+ p
  372.        CMP AL,0xFF
    . C6 C" o7 H, V3 J( }  t5 `
  373.        JZ  LeaveRing0
    % f6 A) e" H; T
  374.        CMP AL, 0x7F+ E- s* [! Y) Q" q  g
  375.        JZ  LeaveRing0
    8 b) `2 @3 Y7 s7 W
  376. - @& ^  _; i0 Y5 F5 ]; D
  377.        // 设置IDE设备存在标志
    ! E+ M* p: @! I4 F: I$ C
  378.        MOV btIsIDEExist, 17 `! Z! \, o" a7 ?# l* h

  379. ! _4 W& j: D  Y
  380.        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)1 N1 P& J+ u% I: q6 A# k% }
  381.        CALL WaitWhileBusy
    ' p% k( g$ b: H: `1 e* w
  382.        CALL SelectDevice
    + ?' `: U* y8 `9 Z# Y8 H, r
  383. & l' @6 \$ Z; R, S4 E
  384.        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
    0 {2 B" k$ u8 ?7 Z
  385.        CMP  btIsFirst, 19 V1 S8 P- U6 c$ D+ m! A$ r
  386.        JZ   LeaveRing0
    0 F# V8 E- Z4 a/ h; e/ i

  387. 6 V( Z& R) ]; W4 g) Y# f# ~& N) k
  388.        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???; j4 p8 O* U7 A, t) ?! H- d
  389.        CALL WaitWhileBusy5 r9 E- f- D, M) |2 G
  390. : O: A1 p/ M7 }& h% d6 h9 x, T! p1 X
  391.        // AL的值等于cBit06时,不存在驱动器,直接返回7 R$ C0 j0 z+ F  y, o
  392.        TEST AL, btBit067 |, w  L5 h- j
  393.        JZ   LeaveRing0
    7 A6 V: w: |; ~" q: A' N
  394. 1 x1 Q* Q. l/ Y* ?
  395.        // 设置驱动器存在标志, X( f: ]( }/ u4 k8 m1 c
  396.        MOV  btIsDiskExist, 14 B: d/ M) g  t8 F4 M

  397. ; S. S8 [0 K, O5 d8 P- N6 }
  398.        // 发送存取端口命令
    ; f! Z9 H1 l$ Q. ~* o% P
  399.        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
    . \6 b$ n7 O6 a& D( l
  400.        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
    2 r! i: E6 P! p3 f
  401.        CALL WaitWhileBusy
    4 Y, l! v1 J$ l; Z, _
  402.        CALL SelectDevice    // 设置主从盘标识8 e; ?4 g8 R2 T0 U2 ^' H
  403.        MOV  BL, btAtaCmd      // 发送读取命令
    + v3 @) y2 Q1 @, Z  o7 s
  404.        CALL SendCmd6 _  J9 p" e' F; j2 a) V6 y
  405.        CALL WaitWhileBusy
    0 N8 m  R$ \; u1 K
  406. % M8 m( h( A: Q/ @, b( B6 |9 _
  407.        // 检查是否出错
    4 G+ ?+ E9 ~) S7 s9 a' E
  408.        MOV  DX, dwBaseAddress! a' ]6 V1 @9 A6 s
  409.        ADD  DX, 75 Z  S- c" M9 e9 i& q5 E* U
  410. ; C$ ]+ x2 W9 j( p4 z7 p# V
  411.        in   AL, DX
    + p' R. z; Y+ K& x
  412. / T% |+ W$ b; o! R# q4 H1 U
  413.        TEST AL, btBit00
    8 i9 I2 R) f" W) ~; r; _" `9 j( V3 O
  414.        JZ   RetrieveInfo   // 没有错误时则读数据% }* [. \7 C/ g+ B

  415. 9 H( O- v4 Z7 |  Y/ r
  416.        // 如果出错,则进一步尝试使用ATAPI设备命令
    / A6 @4 U& x& E, K7 J  {) Q7 e) V: K
  417.        CALL WaitWhileBusy4 |# k& V& D6 ~" P$ O
  418.        CALL SelectDevice6 b6 u3 Y6 s) w8 A# @6 F8 l! A& i
  419.        MOV  BL, btAtapiCmd
    , U5 g* C6 u+ u; Z2 s* k' N
  420.        CALL SendCmd
    1 \3 P* `+ q. C6 v! S' O4 V$ K3 T
  421.        CALL WaitWhileBusy
    ; b' Z6 i1 |7 n' s  ^# h

  422. 0 i+ C) G( V# c6 \
  423.        // 检查是否还出错- p3 x" r1 V0 t
  424.        MOV  DX, dwBaseAddress* y/ Y& W9 g+ ?
  425.        ADD  DX, 74 j, e- }9 L  z) d' s
  426.        in   AL, DX" W3 n  Y1 Z8 D% U
  427.        TEST AL, btBit002 m5 z- f) B  y% @8 E
  428.        JZ   RetrieveInfo   // 没有错误时则读数据/ T) S9 x, Q" [, V6 a" M8 ~
  429.        JMP  LeaveRing0     // 如果还是出错,直接返回. ^. f2 j8 K3 v5 z

  430. ; i0 F, Q/ L, }; x2 A% U
  431.        // 读取数据% B* c+ W  g! Y4 r% x) N, i; L
  432.        RetrieveInfo:
    1 a1 h4 A: P" i6 Y% k+ M' g9 }/ u$ j
  433. : p' i/ l! Y7 C  _' R
  434.        LEA  EDI, wOutDataBuf3 l, p. r0 L  f- x# n
  435.        MOV  ECX, 256
    4 G0 Q0 n& t/ ^5 l4 ^4 s7 I
  436.        MOV  DX, dwBaseAddress# `) t# M# S4 _, D. r' E
  437.        CLD4 y. P8 h7 {3 }  S8 ?; M" R3 @8 V

  438. / @! ]6 ^( o, O
  439.        REP  INSW& t' W7 b' _( \+ B
  440. ) v4 }3 t! E5 [
  441.        // 退出Ring0代码) C. w! h" B4 T! \" R
  442.        LeaveRing0:
    4 X5 U. {7 V7 E

  443. - x1 t/ J: [, k: E% v' l1 W
  444.        POPAD7 g, ~. d6 W. q0 ^) }! N
  445.        IRETD
    2 F4 E% j& S) S  d) O

  446. 9 T& c/ B( H9 ^( {- N7 j5 R
  447.        // 激活Ring0代码- ~" h& a) F2 z5 L# F0 X1 c- x
  448.        EnterRing0:
    , k, z9 m7 M5 e6 X( h. X" X

  449. " t) J) @" [; K8 U. ^8 Z
  450.        // 修改中断门% |# N- C: A! o4 z
  451.        SIDT FWORD PTR btIDTR1
    0 @/ X. s1 ^4 |6 t
  452.        MOV EAX, DWORD PTR btIDTR1 + 02h3 o, k& `" ]* {! \- p( @# h
  453.        ADD EAX, nHookExceptionNo * 08h + 04h) T# q, ~  l0 l4 w. [
  454.        CLI7 P; p0 f' v! L  m& [/ x4 U: u
  455. 8 K) s7 N8 X! i0 F  N4 ?" o2 u
  456.        // 保存原异常处理例程入口1 x% a# n, ?1 }
  457.        MOV ECX, DWORD PTR [EAX]
    % r7 Z/ W/ t7 Q: t
  458.        MOV CX, WORD PTR [EAX-04h]
    2 k, }; s1 `0 Z. f! n
  459.        MOV dwOldExceptionHook, ECX0 Z- k  G+ [- B/ Q% }
  460. 4 i# u- v2 X! ?, c- d
  461.        // 指定新入口
    - w4 Y; I- s" `- D5 @$ w
  462.        LEA EBX, Ring0Proc( O1 T% i% }; _7 Z7 L) `
  463.        MOV WORD PTR [EAX-04h],BX& Z! l1 L$ w% ~0 a/ `1 @
  464.        SHR EBX, 10h
    , F% h. A+ W* m0 A- i
  465.        MOV WORD PTR[EAX+02h], BX
    & e* s7 G% I* s: E8 _

  466. ' e# V. c, A# m. s. Y: R$ @: V
  467.        // 激活Ring0代码
      H$ P% K: z7 B. y7 p7 k
  468.        INT nHookExceptionNo# }# `6 p- A; b8 h/ f0 B  e3 o& B
  469. ( K. j8 ^# g2 a3 W
  470.        // 复原入口
    + {. c& @8 x: x
  471.        MOV ECX,dwOldExceptionHook" Z: W4 Q$ p6 L1 U8 ^" Q
  472.        MOV WORD PTR[EAX-04h], CX6 y0 ?7 Z! Y# S0 j) ?! E% W" s# w
  473.        SHR ECX,10h6 {; S( d+ E9 c+ \3 o2 a# q9 Y
  474.        MOV WORD PTR[EAX+02h], CX
    ( l- T: G7 h" I2 h* `- C5 z
  475.        STI+ X' s; |7 R; d% H1 S; {7 U- P* @" ?
  476.    }
    * B- k8 _: m0 @
  477.    if(!bIsFirst)9 }2 b- [- p8 V2 s+ [4 K' E
  478.    {
    1 x. \1 Z+ E8 @. |- L
  479.        bIsIDEExist  = (bool)btIsIDEExist;
    ; v* q8 b' {7 {+ c
  480.        bIsDiskExist = (bool)btIsDiskExist;8 w# @" X* b# X
  481.        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
    ! B5 F% Y" {% j, s9 F
  482.    }
    & k% K6 T8 `+ C7 U/ c( s2 O# W* G
  483. }
    4 I' R) h( \5 j9 w; T, q" Q1 b
  484. //---------------------------------------------------------------------------4 b+ ~0 u# G1 x. T2 W# Y0 j
  485. // 调用方法:
    * J/ V) @; c2 |3 |5 l$ i" g+ n% _
  486. void __fastcall TForm1::Button1Click(TObject *Sender)& u( q" O8 Q$ U( V( |: v0 O: k
  487. {" i" e/ p8 ^1 ?, a8 _) D% y
  488.    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
    ' z+ o  r: }4 _$ E! o# T
  489. }
复制代码
发表于 2005-8-15 01:00:45 | 显示全部楼层
晕乎乎。。。怎么看8 洞阿
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-11-14 21:46 , Processed in 0.021302 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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