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

C++获取CPU和硬盘系列号的源代码

[复制链接]
发表于 2008-1-6 19:59:06 | 显示全部楼层 |阅读模式
代码框架,你所要做的仅是修改WQL语句,具体可看MSDN。以下代码为简介起见,一次返回所有的CPUID或硬盘厂商系列号
. Y/ n( L9 D2 N3 ~

  1. ' z; m) S5 v, N$ F; H+ t# V
  2. #include "StdAfx.h"
    - N: ]) P! S! Z
  3. #include ".\puiddisk.h"
    " i4 }. g( [; C) g' z
  4. #define _WIN32_DCOM, p2 {! Q; t% R
  5. #include <iostream>
    6 D3 v0 l1 O0 N1 s5 {8 z6 E$ e, ~
  6. using namespace std;
    6 V/ i- `+ n8 c/ b, d, s- W7 p
  7. #include <comdef.h>' [. L/ O; f8 a2 `1 g+ B
  8. #include <Wbemidl.h>8 {! h9 e% R% M2 D  j6 G

  9. , `* F, k# j1 H- y  C# p, a
  10. # pragma comment(lib, "wbemuuid.lib")
    / ]$ M% J2 \, S; Q
  11. CpuIDDisk::CpuIDDisk(void)/ S3 D6 J: p1 T% r# h
  12. {
    % @% @. k% O- s$ E/ ]
  13.     GetInfomation();
    7 V7 ]" }) L5 K' o
  14. }5 ^  N7 U3 O% n  m# r
  15. " X! p  N# m- J  q" X  z* U3 G0 g
  16. CpuIDDisk::~CpuIDDisk(void)
    9 c( i6 U% n. h2 A
  17. {; j7 \+ V( N4 |+ O* L0 y
  18. }
    5 D+ G% _7 E1 x% F
  19. int CpuIDDisk::GetInfomation(void)
    0 B7 m3 @" S* n1 S& L" f% Q
  20. {
    1 W8 G7 c( q/ I" o" D
  21.     HRESULT hres;9 A5 z/ p+ y/ {: K9 H
  22.     //步骤1:不是必须的,COM只须也只能初始化一次
    " Y; j( M4 O& X; l# F
  23.      hres =  CoInitializeEx(0, COINIT_MULTITHREADED );
    4 v1 u/ b: U& q! t2 @
  24.     if (FAILED(hres))" Z6 {2 Y( ~& Q( M5 s
  25.     {  I1 ^3 P' v" S4 S, g9 q' o
  26.         return 1; //初始化COM异常:注意,COM只须也只能初始化一次
    - D1 J9 Q, l6 B6 n- H* O; L( c
  27.     }
    & n4 h6 l8 T' ~) E' H+ d" q  K+ ?
  28.     //步骤2:不是必须的,COM只须也只能设置一次
    8 Z  l: R1 N5 G# R
  29.     //Set general COM security levels
    4 z* ~) Z# X" R& \) L3 M9 N
  30.     hres =  CoInitializeSecurity(
    4 v5 D: Y* i4 M$ s
  31.         NULL, : t1 H% F* p& R) Z
  32.         -1,                          // COM authentication
    7 J7 N( k# Y3 e" c
  33.         NULL,                        // Authentication services
    & ~# B5 r1 Z- @7 N# D  ~, D3 l! F
  34.         NULL,                        // Reserved
    , N. v9 a9 I) Q9 I# G- s" R8 [+ |$ ~$ Q
  35.         RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication
    , q' ^; k% m2 i: h0 N0 j/ V0 j
  36.         RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  
    ) m! Y* T) C  [" S4 h$ I! w
  37.         NULL,                        // Authentication info
    2 S7 F: ^8 ?% }0 E: \2 L
  38.         EOAC_NONE,                   // Additional capabilities
      `( ~, \$ ~9 H; z( }9 G3 e5 c, Z
  39.         NULL                         // Reserved
    " X. y8 c0 ?' O% d. w, H  G
  40.         );
    2 W; r" n; K9 \9 K5 h# w% L% z/ U
  41.                      
    ) J! v4 ?( ?0 m" ]
  42.     if (FAILED(hres)), p6 G- J; K/ D/ N4 f/ [' G
  43.     {- ?. o: x' V2 |' [
  44.         CoUninitialize();8 f/ K! b4 m& b5 H
  45.         return 1;                    // Program has failed.
    ; \4 d# x+ L( Z: _1 F- f+ Z$ G: r
  46.     }  Y4 M2 c# }& l) ~  p
  47.    
    2 u& \& d# Z7 @/ g5 Z' K
  48.     //以上不是必须的,若已有“::COMInit();”,则要跳过! m" O) ~4 u* m7 L' B6 D- @
  49.     //步骤3: Obtain the initial locator to WMI ) n8 p9 t/ y8 d0 {$ A
  50.     IWbemLocator *pLoc = NULL;
    + {0 M$ m: J9 S5 z( R
  51.     hres = CoCreateInstance(
    7 o: }& A7 B$ S! ?2 p& w6 r
  52.         CLSID_WbemLocator,             0 N5 W, P3 A' {+ e; |, L
  53.         0, " e! r& T. P9 n( R: j
  54.         CLSCTX_INPROC_SERVER,
    - T1 P% R% x/ H7 @/ `- w+ T
  55.         IID_IWbemLocator, (LPVOID *) &pLoc);$ H: I# M  E9 x- i, Z, o' t
  56. 5 j: L2 Q3 K# ]
  57.     if (FAILED(hres))3 q3 P9 {9 i5 I
  58.     {7 X  u3 v7 y; a. t
  59.         CoUninitialize();9 ~  Q' U3 N$ B5 y, q+ U: o3 v
  60.         return 1;//Failed to create IWbemLocator object' R  m/ u# Y9 L/ T- @
  61.     }0 Y2 O" o. j3 ], [+ x$ U

  62. % U/ ^& }2 k- S/ s% D
  63.     //步骤4:Connect to WMI through the IWbemLocator::ConnectServer method
    + S9 U, z' ]) Z
  64.     IWbemServices *pSvc = NULL;1 }" `9 {" ~- Y; ]5 g6 ?
  65.     hres = pLoc->ConnectServer(
    ( f- ?  n  y& n* _
  66.          _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace
    ' h5 J* b2 @1 T9 a& m: K; A/ J
  67.          NULL,                    // User name. NULL = current user8 _% p5 H: g, T) d) R- V- g' b
  68.          NULL,                    // User password. NULL = current
    / W% D# S# P0 P( h5 C
  69.          0,                       // Locale. NULL indicates current
    6 h/ S  ]5 H/ x6 R8 q! V0 \8 Y6 `( f
  70.          NULL,                    // Security flags.7 e. |6 }1 y5 F( j) B
  71.          0,                       // Authority (e.g. Kerberos)
    0 s2 k. h1 ^/ ^1 U9 G
  72.          0,                       // Context object ( M, Z3 s  M2 c9 k# i# R
  73.          &pSvc                    // pointer to IWbemServices proxy. |$ j: l% ?# O: ?  C5 f& ?
  74.          );
    - K: p8 k' B! n* L0 \+ V) n4 r) F
  75.     $ B- l5 e' f1 k( N
  76.     if (FAILED(hres))0 r2 G. ]1 V' c- p
  77.     {
    5 W0 ]: |0 h+ P( p# P
  78.         pLoc->Release();     
    2 E6 c1 J3 E/ p# @: }2 B
  79.         CoUninitialize();
    , H/ z3 G1 |' P1 a: J% q" M
  80.         return 1;                // Program has failed.2 N; `. d  w% H- Q1 g
  81.     }; }# ?$ q  r& N$ f, ^
  82.     // 步骤5: Set security levels on the proxy! X$ l% ?! g" i
  83.     hres = CoSetProxyBlanket(
      ~. v+ r9 c0 b8 W, f0 f& r
  84.        pSvc,                        // Indicates the proxy to set7 @1 N% W: W3 x3 T: |0 T3 y
  85.        RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx# k3 o* ?3 l# b# x( {
  86.        RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx
    3 m+ K1 q9 H" r/ s! s6 U
  87.        NULL,                        // Server principal name 2 ]$ W5 m' W/ {/ Y/ e! e
  88.        RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx
    % ]/ J. d9 g4 u! J
  89.        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
    ! X  X1 s1 s( \/ @4 n# R
  90.        NULL,                        // client identity
    ! y) T& ?2 m$ S8 [) b
  91.        EOAC_NONE                    // proxy capabilities . S" }+ w1 E' g9 T+ n+ C* B( a' v
  92.     );/ c' |: p$ \( z
  93. 4 i# N0 v- R9 ~( _2 A) [
  94.     if (FAILED(hres))
    ) I$ F- c4 h- @: H7 }
  95.     {
    ! @9 b2 c- k. P# M; @' K
  96.         pSvc->Release();: I4 i* j# P+ X- M
  97.         pLoc->Release();     ) K# Y/ S& c0 n- Q
  98.         CoUninitialize();
    ; e" L. F+ C) {: M! A9 z, l( X
  99.         return 1; : M5 {& Y6 F3 }( s) u4 O
  100.     }
    ) F5 j0 _2 j' P) G

  101. & ^( y& d( X( R# i3 @
  102.     // 步骤6:Use the IWbemServices pointer to make requests of WMI ----
    - Z7 H4 ]8 i+ D* b: x
  103.     IEnumWbemClassObject* pEnumerator = NULL;
      V' d8 A+ g- P1 k) I
  104.     //计算CPUID
    ( X0 ^' u9 k' C% \2 v, m* B0 z
  105.     hres = pSvc->ExecQuery(3 k2 G: u0 [8 _
  106.         bstr_t("WQL"),
    ' W8 [) ~: J8 d+ V  B
  107.         bstr_t("SELECT * FROM Win32_Processor"),//Win32_OperatingSystem
    - J5 S3 p5 [" C9 S
  108.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
    5 Z  K3 p! H/ P1 T+ t
  109.         NULL,
    3 h3 h1 |+ g% h
  110.         &pEnumerator);
    ( Z* ~7 E5 w* g; M* V! R+ D6 ?( A
  111.    
    2 H, s. v0 Q& y0 ]# ]9 g
  112.     if (FAILED(hres))
    : }" _7 H  C* X  \# W  m6 Q8 q
  113.     {
    / u" @" `# G8 ?0 _4 ?
  114.         pSvc->Release();
    7 a$ L8 T7 q% d* W; s
  115.         pLoc->Release();
    & a2 |2 L$ P! ^
  116.         CoUninitialize();
    & u. I6 @! q* m: [+ a) K$ A
  117.         return 1;- \( T) G, i% {/ E1 g& u
  118.     }/ V  J0 A3 t8 n/ V- q
  119.     // 步骤7:Get the data from the query
    ( J% f& Q# S& K0 H% n6 }
  120.     IWbemClassObject *pclsObj;
    ; M* O$ [4 p# E+ }2 T5 R$ j
  121.     ULONG uReturn = 0;+ D* T* C) _# o1 T7 g7 m1 A& g/ A
  122.     while (pEnumerator)' c8 {) J& c# D1 A
  123.     {
    , _. U0 K5 L& v$ l0 }8 X3 u9 }
  124.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, ) l9 K& L/ v) q& \/ u5 ?
  125.             &pclsObj, &uReturn);
    0 n1 X- \4 v. Z& k* D! f
  126.   k$ U7 C; Q9 u9 a1 Z6 a/ M- }" |  b2 F
  127.         if(0 == uReturn)
    0 g" o8 w) m9 A0 G. ]2 w: c
  128.         {$ I  E- Q( p% Q4 X0 g% c7 i4 {' t
  129.             break;
    ) i$ u1 b+ U. _+ g! I
  130.         }6 v) `2 _$ B! r# C$ m1 W+ |
  131.         VARIANT vtProp;$ s: @$ }: M! C3 z
  132.         VariantInit(&vtProp);8 R5 m+ A- V1 p! [! x; r
  133.         hr = pclsObj->Get(L"ProcessorId", 0, &vtProp, 0, 0);1 F+ S, P3 d! ]
  134.         strProcessID=_com_util::ConvertBSTRToString(vtProp.bstrVal);//strProcessID:类级变量
    ( x3 T+ }) ]7 _* A, m. z1 H( f
  135.     }- P& K; H4 |* W% J) H3 [0 Y
  136. 4 T3 [4 A) m  r5 \4 v' L
  137.     //计算硬盘系列号
    ; o( E) A9 L5 u
  138.     hres = pSvc->ExecQuery(
    0 N3 y  a; I$ D1 f
  139.         bstr_t("WQL"),
    5 Y  Q4 D" E. n$ r
  140.         bstr_t("SELECT * FROM Win32_DiskDrive"),4 l0 E* J+ P9 r" a) Z
  141.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, ! N. D( m. X% K2 J
  142.         NULL,
    7 P/ v; R/ F% M# i) v1 O
  143.         &pEnumerator);6 i5 X7 ]! a! y2 f, O7 J  n
  144. ! T) D1 V; ], k' @; S& G3 m7 G
  145.     if (FAILED(hres))8 [  N- C. e% k# a
  146.     {
    ! B: E( V2 N, j; ^+ b
  147.         pSvc->Release();' B3 e* M. h5 ?* l( x
  148.         pLoc->Release();
    6 D/ P1 X# `8 }% o6 M% u
  149.         CoUninitialize();7 u- W) k0 E( ?9 N  a- H
  150.         return 1; ; V$ G( x+ m0 U
  151.     }
    ( ~# \6 w) }% |& M  ]- i
  152.     while (pEnumerator)
    % Z0 T1 U& Y' s6 |& B! {) B
  153.     {
    , e* i( B% L: P5 e1 p7 S! e% ]) C2 v8 V
  154.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
    / b8 h' u/ |2 }& {
  155.             &pclsObj, &uReturn);7 M( X1 X! Q; {6 @+ D  v$ `' l- p
  156. 3 j7 P/ r: @3 t
  157.         if(0 == uReturn)
    3 C# S3 m; {5 ~2 q! j% Z5 j+ a
  158.         {
    ' ~1 [% k9 Q1 ]; u1 R4 f3 \
  159.             break;7 E; O( I  i& F9 J  {
  160.         }
    6 y: k5 w* |4 s1 s! O9 s9 v/ v0 c
  161. 8 X- q+ Z. Z% z9 }' W' ^
  162.         VARIANT vtProp;8 h# k- A7 C& Y4 |
  163.         VariantInit(&vtProp);
    ; U; D, c5 A5 F% \) f& W. Z3 R
  164.         hr = pclsObj->Get(L"PNPDeviceID", 0, &vtProp, 0, 0);" n0 F6 W* O* Y- A9 h
  165.     strDisk=_com_util::ConvertBSTRToString(vtProp.bstrVal);: \% P& M, Q: y
  166.     }/ S* C& z5 U+ r7 H1 l* ~0 L- b

  167. ; `# q# s/ h& q& P  t# |7 w# `
  168.     pSvc->Release();
    5 Y' ]* H  O" X% t
  169.     pLoc->Release();
    2 J4 k9 W! {1 Y- L
  170.     pEnumerator->Release();
    % \. Q  {, B7 Y2 B9 J  v% a! m
  171.     pclsObj->Release();
    " S8 ~+ V6 ~7 K. _( M3 E) ~6 C( c2 L
  172.     CoUninitialize();
    ; T5 G0 V4 o8 Y# |$ Z: b4 T( |2 W
  173. / p0 u5 x+ q. m0 }- T( t
  174.     return 0;   ! m0 @0 z% B) C; W
  175. }6 G* F  y9 r; A! k* @
复制代码
 楼主| 发表于 2010-10-11 19:21:05 | 显示全部楼层
本文代码经ccrun(老妖)在Win2k下试验成功.# [( u1 Y: [1 C) ^- j: L) V4 [( Q
6 ^2 V1 t% }7 \0 r) E( Z0 w
#include <WinIOCtl.h>
, Y1 s9 D. D" s. F. f, v8 M3 ~#include <stdio.h>* }- B/ a8 u3 \
: N# g, Y! V. i4 I; k
#pragma inline, N8 W7 h8 n" c! c0 U% R
//---------------------------------------------------------------------------$ t3 J; ?* W; i
// IDE NT/2000/XP专用变量
" _, a. q' q0 V( S, R) n- c: M#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS# K0 @: i6 C9 l: o  n8 B$ I" J) m
#define DFP_GET_VERSION         SMART_GET_VERSION% L' y0 e6 L7 L) ?8 R
#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
6 Q8 h+ V$ C& o2 G5 S: ]#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA3 d4 t- k9 h8 e2 n0 V: {( y9 d

' b& Y$ W, `$ i+ r4 `const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令9 \0 C- ?: ]' z8 F3 B3 B$ B# b" g1 U
const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令) q, W+ z, k( \6 }6 m4 r

! U6 X+ g0 e* `/ ~, fconst int MAX_IDE_DRIVES = 4;
9 U9 o6 u* C8 B, Y8 Q# o4 E) P: k* H8 K/ I% G
// SCSI专用变量! N. b) A$ J6 |, f% q
const DWORD FILE_DEVICE_SCSI             = 0x0000001B;. d+ R- W& k, R
const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);7 a0 N2 h, z6 q- Y# K. [
const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
- X, C: H! x7 _% M0 }+ H8 gconst DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;) a6 Z3 Q+ r7 j* R+ W9 m4 z
1 ]7 i. n9 z0 T6 R, i( o
typedef struct _SRB_IO_CONTROL
) n  D8 g1 ?& `# [- r  A% A{
1 w% A2 i" ^& y2 C" V, M; ?+ J    ULONG HeaderLength;$ X* z  ]5 B$ ]9 R  `8 O$ l
    UCHAR Signature[8];5 ^; [5 L( x' b" J4 L: j* a
    ULONG Timeout;& M- J' s* ?# S/ E/ Y
    ULONG ControlCode;
+ i  P% X& ^8 \( c    ULONG ReturnCode;
$ G; c1 `) ?$ R" ?1 Q1 W5 `) O    ULONG Length;' K' u+ d' N( s( J0 X7 R( _! X
}SRB_IO_CONTROL, *PSRB_IO_CONTROL;
3 H0 H) }7 i0 F# u7 |+ e1 q4 u" E) m
* |# k; e# D  e; O5 q2 N, b" x// 读取的主函数
2 s: U, O# Z) x4 H: W0 b9 ivoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
# d1 i1 I+ v, F- K7 }
* A  B6 H! C' p9 f// 辅助函数
8 D: R) f1 Z- Q" _$ Y. x% lchar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);, }  p. U/ _" y, s2 g. O
// NT/2000/XP函数
* J" u- D% M4 Z5 s5 |; Svoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);3 U. @- F' \1 l0 V- Z8 R
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,  Q8 v& \' M) h
        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
+ D+ e& u: Y! s        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
! S8 M. x- x1 p7 l5 `% j// Windows 9X函数
# z1 _6 z9 o4 f  w0 d( R) S3 j& Q' r, }void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);+ j, T6 F' y; i( U
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
$ B2 ~' }, Y0 e. O1 c0 w' ~        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);. {3 ~+ t6 G& I* ^  D$ i6 f+ B7 u) [
- m" T, d( G5 ?" B
// SCSI读取函数(for NT/2000/XP)/ ?$ w- G' i3 Y, m& z, \
String __fastcall ReadIDEDriveAsScsiDriveOnNT();
4 n  c7 L0 Y9 O//---------------------------------------------------------------------------1 b" |0 J4 d" f" p
// ReadPhysicalDrive1 i) d0 }" l! R3 A1 [; `& t& {
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
- U' J5 g2 Z3 c% w; s' ]{
+ x5 ~' k9 W, B5 L; E- K4 l. z8 T    switch(Win32Platform)
  V/ P6 v$ z6 C    {
8 s4 j8 E3 V' C5 g        case VER_PLATFORM_WIN32_WINDOWS:
$ ^" j1 S8 J# Y! r  }; ~            ReadPhysicalDriveOnW9X(pSerList, pModeList);
" t) O' j% ^' Q/ m5 d* V            break;
& q& }) g" f0 R* x5 A- i        case VER_PLATFORM_WIN32_NT:
- K% z+ Q8 X# T/ @+ m6 F            ReadPhysicalDriveOnNT(pSerList, pModeList);
3 E0 \  W) \& ~+ _0 d            break;
. R- h' e# X7 m8 I, y& b3 u        default:. E  [$ K0 g; [4 e# l" k# n
            break;2 i( g$ B1 |' T0 M6 N* e5 E, G
    }
/ h& [2 n6 i& @5 i# s+ v1 q% A}3 L+ }# f2 t& a+ T3 v) `9 e  m% w
//---------------------------------------------------------------------------
! t1 ]1 i$ J" ~+ e$ Q: }9 M* ]// ConvertToString
" L6 q7 P, R' Dchar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
! k1 k  W+ j; @* F{
: V: f1 n, l# p; n9 D    static char szResBuf[1024];/ h3 {+ {, E0 V
    int nIndex = 0;, C* n: G  x* f
    int nPosition = 0;2 s6 G" Q0 j( i

; U0 O! a- U6 R  ?1 `" q* f    // Each integer has two characters stored in it backwards
( y, m) R8 \( u: O7 R6 q    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)9 r+ \, R2 m4 G0 l$ x% J' ~) a6 p+ C' s
    {
4 M- C; p% m# s        // Get high BYTE for 1st character
* x+ r* B( r6 Z# O$ i% I        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
, |" u$ l( J6 m- T7 R4 a' Z! j        nPosition++;3 Z& J0 u% q1 r4 t4 n

( W$ _6 e2 Z/ U( f        // Get low BYTE for 2nd character' x4 {5 v4 q& w8 j$ ^
        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);5 E: t' l, A: H! L
        nPosition++;
( Q& O1 b7 g2 F" y) \. b    }5 Y8 ~( y& y. C2 p8 c9 C9 o0 i5 G

! q+ w7 {& T/ Q! O    // End the string
0 T7 s: `0 _, B5 P    szResBuf[nPosition] = '\0';' q# m, B' V# N1 E
' A4 n6 G, {9 A  Z! Y7 t/ E  w
    // Cut off the trailing blanks
% B6 i. u3 ^1 N0 f" N9 E    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)+ V) w9 _1 j9 l% u7 ^; I% p, |
        szResBuf[nIndex] = '\0';
, G8 d& a9 L8 t- y
/ G% @' Y+ v* X/ K/ M+ v; }2 H    return szResBuf;
/ D  d1 O/ {8 c5 L1 K; P4 R: J1 Q7 a}
; N! R( s! [1 H/ e7 s$ M  p; f//---------------------------------------------------------------------------: C0 K5 n& p; X5 B5 A) f( U
// Winndows NT4/2000/XP 代码& a0 D- u& F5 ?" C9 Q4 L
//---------------------------------------------------------------------------  O, A8 _! x' i1 C( f% _; }2 `  T
// ReadPhysicalDriveOnNT
. a( M! c, N8 H7 v6 B5 M$ lvoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList). Y4 _$ |3 k. ]% s0 _
{2 {/ C0 t! m* T9 X9 B
    // 输出参数
0 ?! b: \" a) j4 D8 R! J    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
+ q2 I$ ]# Q+ }1 t
) t' i2 s7 {, c) J    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)% h/ Y, |& K' O0 D2 S1 {6 D- @
    {0 J! k8 P# a1 {; {; U* F3 P- s( b/ q
        HANDLE hPhysicalDriveIOCTL;
, b: u, z$ w, g8 H# G) I! Y        char szDriveName[32];: b$ n2 p  H4 v! ~0 P/ z- \  n

. O+ `" V5 L  T; m        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
8 Q7 c2 ?+ X( T# P        hPhysicalDriveIOCTL = CreateFile(szDriveName,
& ~6 Y" Z8 `: n4 ^2 s3 G* J                        GENERIC_READ | GENERIC_WRITE,
/ C5 d4 U5 g5 G1 {' v                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
, U6 [7 e+ _% s" y5 g' {                        OPEN_EXISTING, 0, NULL);
* k5 d+ a- e' Z2 X% J
) i: F1 L1 m: v0 j' O7 V        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
7 U% P: q8 t7 U8 _; U% }        {
% D! I6 a- X3 O. d$ u& y            DWORD dwBytesReturned = 0;
1 ]  \5 X$ z% ]9 Z5 M            GETVERSIONOUTPARAMS gvopVersionParams;
' V/ M7 A/ W) J" z' q/ T* o. [6 B* x
            // Get the version, etc of PhysicalDrive IOCTL/ M- i. Q! ]; s0 M' {
            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));( _. \1 o" R2 c
: ~' D' n  V+ `+ u1 Q
            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
/ l% h) F5 R* T! v  H& H' o0 t+ i                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
0 o: `' B. f/ A* {9 E- a& _                    &dwBytesReturned, NULL))
0 l6 Z' q" L, s- O& l/ v! J            {: T) u0 c& k7 T9 ?7 m! s8 X7 f: E# y
                continue;
, d& u1 U% W7 U1 @" p; t            }
& z0 f) ]) D# j# [3 j
6 @& `# I7 N$ C' F% s6 `* e            if(gvopVersionParams.bIDEDeviceMap > 0)
& v( X( G$ c" u" {; z. C( C4 a: Y            {9 k2 o" {4 X- ~7 r7 D6 e/ U
                // IDE or ATAPI IDENTIFY cmd
  f0 P4 C) l. {# @: H+ |, z- ]7 t                BYTE btIDCmd = 0;
6 b6 z* F9 y% ]  l) G* q% ?                SENDCMDINPARAMS InParams;
2 K- S9 h- p, }5 b) k' t- Y                // Now, get the ID sector for all IDE devices in the system.2 L. I8 ]) m  a3 K, [+ Y2 R! x
                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
6 [4 c( L. E0 R$ i! m                // otherwise use the IDE_ATA_IDENTIFY command  A* n" \- }+ M& |7 m( A. t
                // 具体所得结果请参考头文件中的说明! {1 X; ^! P* i9 e9 o. U$ C" X$ f
                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
; X& A; ~' h" O. H) O! X6 [                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;$ b* z0 y: C; q6 A( g3 Z
                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));' Y4 C) l# N% C4 E
                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));& S/ q* s* p6 b% H8 L; t
1 R. p7 e( b, z
                if(DoIdentify(hPhysicalDriveIOCTL,
' n$ @" `  i9 J- W                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
6 y$ o2 S  R( _* _" M                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
5 h% J. G. G- Y, L/ I, E                {
/ e; Z5 m9 U$ Y: V2 c! |; f                    DWORD dwDiskData[256];
6 T- d$ H7 t' t1 O, X; t( e                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
2 b% o7 W( s9 \0 x( z                    char szSerialNumber[21];
/ V$ s. U- l* p/ ]                    char szModelNumber[41];
) ~5 a+ W; Z, G# o  d8 i+ O6 f8 A' I$ s7 Y0 z
                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
' |4 {5 p, N; y& |                    for(int i=0; i < 256; i++)
+ m4 G6 \7 x( G                        dwDiskData[i] = pIDSector[i];4 _- k' R1 Q! a1 M! X
                    // 取系列号
* F3 E& \5 S/ p4 n/ J                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
" w3 l4 x+ |# |$ s' e, g0 u! d                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
. ^1 d" w) j! m$ r1 s. J  u9 b) w0 n* x1 ?. W5 K% t5 ^7 r
                    // 取模型号
& M9 a; w, P' p! E) }4 R: |+ A                    ZeroMemory(szModelNumber, sizeof(szModelNumber));' t$ X' @5 ^& X8 S
                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
! F( j7 `1 G4 U0 y3 Y+ x
: ?, F. r8 z. R& |5 y7 \                    pSerList->Add(szSerialNumber);( z: N% O/ n8 w% L, [' D/ g
                    pModeList->Add(szModelNumber);
' n9 C& r' Z% [) H: k. L( J, c4 m                }+ B3 U) _. }/ C! W; V
            }
6 e; b( r# Z9 k* s            CloseHandle (hPhysicalDriveIOCTL);
! k, v5 B2 h6 O$ `" E: R        }( B' P8 C2 s9 f$ j4 u  c8 H& v) j7 U
    }
& \3 C" m" {! {1 ?  U$ r1 k}
' {/ p) ^. ]$ Z5 v) ^//---------------------------------------------------------------------------
4 P4 t' ]# b( A/ ]: `// DoIdentify$ f$ J2 N: |5 l/ r+ }
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
7 K1 j6 i# M+ }& l& |0 f. W7 H              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,. }- J8 J; Y* C, Z
              PDWORD pdwBytesReturned)
7 @+ S' k. m6 M! l; G{
- w- _6 O7 V6 e  G0 t. }    // Set up data structures for IDENTIFY command.# B' Q: o* q" |  N$ r9 I% r" e: q! ~
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;" m  b+ }% q7 w$ E
    pSCIP->irDriveRegs.bFeaturesReg = 0;8 u* K# Y- S: W$ r
    pSCIP->irDriveRegs.bSectorCountReg  = 1;0 J. p; m8 N% e% R! [" }6 n
    pSCIP->irDriveRegs.bSectorNumberReg = 1;
) ]0 c5 ?, P% w    pSCIP->irDriveRegs.bCylLowReg  = 0;9 |" ]& i2 ?" D% u' U1 i
    pSCIP->irDriveRegs.bCylHighReg = 0;% c* r8 o$ b6 G/ j$ c9 U5 t* m

; @* F1 k$ D; H- H    // Compute the drive number.(主盘和从盘所对应的值是不一样的): D2 A5 w# ^# t, \( F. O9 z/ p
    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;& \+ g+ |; X& F9 i

/ r4 b" `) O) P! p, R& c    // The command can either be IDE identify or ATAPI identify.  q0 Q- g9 M) r- W9 M5 K0 X
    pSCIP->irDriveRegs.bCommandReg = btIDCmd;3 t. r# @7 G. r! c
    pSCIP->bDriveNumber = btDriveNum;
1 f$ [. T. q. [. P% h$ c    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
1 ?+ r; A8 h  g/ W8 ?- O, Y( k8 `2 Q' H
    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,3 t/ g* C+ L# j5 D# [7 a5 o
           (LPVOID)pSCIP,/ h& K4 o2 O' G  e, C
           sizeof(SENDCMDINPARAMS) - 1,2 ?6 [. Z  H7 H8 u- @
           (LPVOID)pSCOP,
- z- d, |' n* R) C! A$ R           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,( Q, L+ x6 A  p0 i
           pdwBytesReturned, NULL);0 W9 \5 Q# x# ?9 Q! D7 c8 B' ?$ V
}
' v' A% v. D, r# o/ Q2 U2 r//---------------------------------------------------------------------------
  x7 a' ^  U, y! x" _// Windows 95/98/ME 代码
) s6 h) C" W# Z7 ~& A2 H- X//---------------------------------------------------------------------------
" {1 L% j3 v1 S& J2 g' z// ReadPhysicalDriveOnW9X
1 Z2 l  a- C1 f4 t: R$ \2 Q& Vvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)+ H: z' ~) Z- `- l) [
{
# B1 U' o) W5 o1 N8 R2 s    WORD wOutData[256];
$ a- V$ B# W. c2 x; T/ m5 E5 r! Z' [    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);7 O& ^3 k5 U/ E) K0 }; L

. C* X5 X" m4 L/ J    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。4 c! ~/ K9 c( V6 E8 ]. w, [- S
    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以. Y2 W# }3 B; s6 M
    // 避免蓝屏的出现。(期待高人能指出原因)! l+ Y/ N4 z1 T& S
    for(int nDrive = 0; nDrive < 8; nDrive++)
$ Y: y# K  L+ _# v% b& I    {
+ e0 ?7 M2 }" h+ p0 ]9 c) O' [        WORD dwBaseAddress;. J0 x  \) X" V, W- E! D+ y5 k# [, |# X
        BYTE btMasterSlave;         // Master Or Slave: R# f/ m- E6 m. o$ }9 ^% |9 ^
        bool bIsIDEExist;- v  Q4 M& c- T1 S# a
        bool IsDiskExist;: T5 L$ J1 O9 c; L% D) L

! _) E1 s4 E5 c9 ^        switch(nDrive / 2)
; Q; w3 a3 K% x7 D! r( }! d' E        {
; y* S$ J3 T* H& n- ]6 o7 `, x            case 0: dwBaseAddress = 0x01F0; break;$ z/ z( j# Z4 L: L$ i3 @
            case 1: dwBaseAddress = 0x0170; break;) D0 G% l) e6 d: m3 L0 w, V, ]7 u
            case 2: dwBaseAddress = 0x01E8; break;
4 d5 b* }1 A8 v) W7 \            case 3: dwBaseAddress = 0x0168; break;+ H2 a0 H+ B7 q2 \  z& l4 D
        }4 ^& \  `; }' C. H

6 K2 ~0 ]% n/ C' c% J        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);1 v/ q$ ~; e$ {5 `; ]5 D0 h6 ~" D

- ~' l5 [: o2 g        // 进入Ring0' T* ~8 ~# j8 A( }
        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
; n. `6 g8 s; M! K) I                bIsIDEExist, IsDiskExist, wOutData);  _& W8 ]/ _; l+ o! z% }( k
    }
9 h7 E1 `3 S0 o4 ?! X0 v
6 R  \" N8 B) @# \    // 开始读取
$ u( k% h) s0 y% c    for(int nDrive = 0; nDrive < 8; nDrive++)
& \6 X2 }; P4 _5 P5 b4 D9 \3 h    {
7 o6 X2 H; C; p- l  e7 T0 j5 S        WORD dwBaseAddress;: ]/ E7 V  u5 b! N/ g3 y" |5 q
        BYTE btMasterSlave;         // Master Or Slave
" z+ {6 |5 R' k# g/ v        bool bIsIDEExist;
5 |1 S; A& c& c! V        bool bIsDiskExist;* ]8 O' R- }% J: d
        switch(nDrive / 2)$ N5 b) W& W6 ~( J
        {% B. s8 E& m  p! F! i
            case 0: dwBaseAddress = 0x01F0; break;3 j* U1 M' j! |" i7 a
            case 1: dwBaseAddress = 0x0170; break;
1 N2 H3 Z. X5 |  H3 ~; [/ K+ L            case 2: dwBaseAddress = 0x01E8; break;  q# U+ h; ]! d* L- V" |
            case 3: dwBaseAddress = 0x0168; break;4 W2 H4 R8 J& y* B
        }7 g1 n( H. E: a1 z& U

# ~8 x' D. W% i3 _5 ^" w        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
& |" `0 T' p% z3 A* h/ n+ p! b6 B% }/ Y4 W( D6 f3 Z8 P- P0 |/ `
        // 进入Ring0
4 ~1 c2 Q* g4 Z0 ]5 Q/ f% T        bIsIDEExist  = false;. T9 j- y7 g2 J) L; P( ]
        bIsDiskExist = false;
1 l3 H: |2 ^- {5 v1 ~        ZeroMemory(wOutData, sizeof(wOutData));
7 {- p- T1 g% Y- q6 f. }9 C( h; z5 q8 V5 u2 T
        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
2 U1 ~  j* U0 J# A' }$ P( L$ L                bIsIDEExist, bIsDiskExist, wOutData);" T$ n7 I) q2 g5 Y. l  O

" U8 W6 x8 i/ p2 d9 W6 i        if(bIsIDEExist && bIsDiskExist). x+ h7 g7 B) [* h8 o# K1 u) H
        {9 n( B$ {2 T- s6 Z
            DWORD dwDiskData[256];3 @3 @* Q) |2 f# f: _; x1 g/ j8 p
            char  szSerialNumber[21];
7 ~" s; S$ \$ Z- G- H; `            char  szModelNumber[41];
8 x& Z, C; y6 |( o' H  {8 M7 q" L1 W. |' S
            for(int k=0; k < 256; k++); d) n# q1 q. o
                dwDiskData[k] = wOutData[k];' [& K+ y6 z3 g+ Q+ t8 k

3 D7 ^( ]' {1 u% }9 y            // 取系列号
5 |8 s/ W3 p/ O1 N6 f            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));4 u) b: _2 c( m0 c3 O7 n) P& o1 L
            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));8 L  I( q; u8 k/ v* Y
  V- i$ i& A- P& n! `
            // 取模型号$ {0 U6 ^- p" v' q* J
            ZeroMemory(szModelNumber, sizeof(szModelNumber));. S/ K) X1 z* Y/ p. j& c7 n6 j
            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
% A: F8 S' r0 @3 ]0 j4 p
1 d# k- U# U7 Y, q: ]& ^            pSerList->Add(szSerialNumber);& z: p. _- @$ R* y4 J
            pModeList->Add(szModelNumber);! V# e' _- m# e& ]  H' q
        }8 h& r0 P' ^% I( U) q" N1 m
    }$ Q( H5 q+ e  `; @
    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);2 T8 u1 e/ q, g7 x$ W& B- `( U
}
+ {) I- D% z7 ?  h! T//---------------------------------------------------------------------------
9 b# h  Z3 J6 W9 j// 为防止不负责任的转载者,在此注明原出处信息,请见谅。
" n# `# |$ T- g$ J7 g// 资料收集整理:ccrun(老妖),欢迎光临C++Builder研究: http://www.ccrun.com! a& {" g% Q, N3 J
//---------------------------------------------------------------------------
8 l! B& ~. M! ~( J3 ], ]- k; D// ReadPhysicalDriveOnW9X_Ring0(); L' L/ m3 I" d. n! L9 @, g
//
$ T5 P+ W# T) w// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h, a$ B* Y5 H3 x2 T0 E9 I
// btMasterSlave = Master(0xA0) Or Slave(0xB0)
2 c0 |% G& J2 f5 a7 k3 g2 l2 o2 L//---------------------------------------------------------------------------+ J" c# K0 l+ Q' `% B1 Q
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,0 |6 P9 @; I' G
        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
, j3 `- C% v3 K9 q+ F1 p, v{& C. I& z' Y" u
    BYTE  btIDTR1[6];
5 |  I) Q, W) J  G' ^    DWORD dwOldExceptionHook;9 J; I; Z1 ^8 R, J* s1 P
    const int nHookExceptionNo = 5;
, g" e1 Y7 }, B
5 U1 l+ o) y# I1 [& {/ H( ?    BYTE  btIsIDEExist = 0;
6 X9 f  y4 B( O9 a    BYTE  btIsDiskExist = 0;
+ l. g' C' e0 P7 N4 @    WORD  wOutDataBuf[256];9 h; |5 M3 c1 t4 E
' N  Z2 x8 J) ^
    BYTE  btIsFirst = (BYTE)bIsFirst;
6 W# K& a4 w, e( I9 {" s( Y
8 a& F; H4 z6 {5 _0 z6 c    const BYTE btBit00 = 0x01;1 S! M  }$ V  z! S( @* m
    // const BYTE btBit02 = 0x04;
2 [5 c3 S* X! y; {' J) T8 C& Y0 \    const BYTE btBit06 = 0x40;; t+ a5 r; l1 ]4 A, m
    const BYTE btBit07 = 0x80;
. c; X8 p: m3 ^) g0 Y8 V    // const BYTE btERR  = btBit00;
1 [. j# @' S' M    const BYTE btBusy = btBit07;5 M$ k0 Y0 J) ?, D- }
    const BYTE btAtaCmd   = 0xEC;* B0 Q% m, _3 f, }
    const BYTE btAtapiCmd = 0xA1;
8 B) p# m& j6 t+ f% p! c/ [0 H5 d# E
    __asm/ v+ t2 @0 L6 }7 j3 R
    {* o/ _3 A' ]  C( j
        // 必须先执行这条语句
3 l1 {4 |' G7 ]- p        JMP EnterRing0# l4 K' z; d! ?) |

- f3 Y" b: U$ H: d        // 定义过程
* _; T+ R0 }! x0 m% r+ D0 W        // 等待IDE设备直到其不为忙为止
* H! _4 |# E% @* S1 f        WaitWhileBusy proc
  z* x" F6 R0 W4 ]) _7 j8 H6 @  t
) d% K1 q; @. f3 K7 g        MOV  EBX, 100000  {3 d# z; f% j& ^! b$ O1 m/ j1 J
        MOV  DX, dwBaseAddress: F$ W- W( I- P2 f' N+ N: ~
        ADD  DX, 7
0 P3 X5 Q3 p. k3 M: ^, q& q/ L2 E1 E1 ?
        LoopWhileBusy:
9 R" L! p9 l' N  @3 c3 N( t/ p* q/ A( @& G0 a
        DEC  EBX
7 Z% K% Q! P9 O8 ?- `, G- s        CMP  EBX, 0+ b" Q4 @) B; A2 q
        JZ   Timeout5 }8 \+ J% w% p3 o, y3 t
        in   AL, DX
6 _' i- c) w& W2 {/ G        TEST AL, btBusy6 z! m# v3 K+ H6 y2 i
        JNZ  LoopWhileBusy! B8 D: o7 N- N" Z& B8 H& [) N; r
        JMP  DriveReady
/ J' t) a4 o& {+ r5 H! t+ j6 a" J/ ?: b6 y; y4 f8 F9 s0 n' n
        // 超时,直接退出' F8 ^: \- s) E. T9 Q
        Timeout:& k/ ?$ f# k" u
        JMP  LeaveRing01 @+ \. n0 j$ X5 B6 \/ }" ^- F
        DriveReady:
; |/ B. D# k  A8 Z' V- z6 i        RET/ w+ C' _' c/ r7 Y% j# r8 O& U& V
        ENDP   // End of WaitWhileBusy Procedure( q: g" A8 N  I4 {* n/ L, p8 c

- Y' ]2 w& L# |5 S# N: K        // 设置主盘和从盘标志
4 N8 ^' Y! D3 z/ b; Y        SelectDevice proc3 H4 i) `9 [8 u5 M. n6 ^" B% l

8 a  d4 J  A2 p) Z        MOV  DX, dwBaseAddress
$ L, z, F# }, |$ |        ADD  DX, 6
' P) ?5 u: b- C. D$ G% n4 j) }( _        MOV  AL, btMasterSlave
* Z2 m1 G5 z( {3 d8 w; ^9 V' @4 m* O$ G
        out  DX, AL
5 j  K& n4 [2 @( F; w5 t        RET: }* t$ _0 U7 _; m; M
( l9 t+ b% N. R, n8 W9 Y0 ?7 y9 s
        ENDP  // End of SelectDevice Procedure2 u# y- K" P9 C8 N
/ @- ?- j, j" n& R8 j
        // 向IDE设备发送存取指令7 e% \* l( [: t) o* @' F
        SendCmd proc% G. y9 i( m. j$ A
" ]3 m# H# p  z3 g( B
        MOV DX, dwBaseAddress
! ~. O$ A% ^4 K% m* t        ADD DX, 7
2 K9 b$ b2 z3 k( M- p% l3 A        MOV AL, BL // BL是主从盘标识,在过程外设置3 E8 F! ?7 r+ `0 X8 n" D/ r# q
        out DX, AL
# m! f9 A# j- P: q        RET
( I. p' O" h* C; P2 ?( [' x* |9 z, U        ENDP  // End of SendCmd Procedure: Q- _' t3 c1 G+ x5 U
7 n& E. l- q. b6 m
        // Ring0代码8 L0 h5 [1 N$ M" F9 R5 n  {
        Ring0Proc:, z+ R1 W- @) j8 }/ x9 X  t
        PUSHAD
7 Q( K1 Z/ D6 E% S" l6 J  l        // 查询IDE设备是否存在
4 O$ P  ?" L: {  I* i        MOV DX, dwBaseAddress) _- e, d) W& H  \
        ADD DX, 7% `/ Y% k! H, s# A) i- f/ e+ `
        in  AL,DX
# D: s1 T% j! n
; m5 O3 S/ R) o        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回% t: w7 z% b. ~% C
        CMP AL,0xFF
! Y- r, h& n) q* e        JZ  LeaveRing0
- H' [/ U. H+ F- R2 V/ I! m        CMP AL, 0x7F
  C) K- K& K: R( B; W( P& _$ I        JZ  LeaveRing0! ^  W5 p# f( t$ q& i* ?
* \7 E! z' t3 B, x4 U
        // 设置IDE设备存在标志) x9 B# q% J" o' c2 F% C
        MOV btIsIDEExist, 1' j8 x# V& n$ ?1 y6 F; R" M7 A5 d

$ {( v. Z$ J) _8 @) z* o6 u7 U! K        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
6 H3 L+ u1 w! |  m3 T% F        CALL WaitWhileBusy
- Y8 m* K. |7 s. H& q6 _$ c, L/ P& i        CALL SelectDevice
1 v" B5 ]% p5 F8 S6 k) W% e/ n2 _) X/ x
        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏* d# `6 w5 Y4 W- w4 }. E3 i" u
        CMP  btIsFirst, 1. \) w  [" b9 _3 J
        JZ   LeaveRing0) m: F# w& u3 n5 w
0 G: U. x2 g; W
        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???9 _0 b: T7 N) h( Z! }
        CALL WaitWhileBusy; s5 Y& {1 N+ C( S

8 i* f9 n* b* s# q4 |8 C        // AL的值等于cBit06时,不存在驱动器,直接返回- \% L( F1 Q  O; E& X
        TEST AL, btBit069 W5 `$ r% r: Q1 K3 R
        JZ   LeaveRing0
  p  j& _: _8 M1 q3 G: V7 D6 X5 |9 l6 o$ M6 B) p; h
        // 设置驱动器存在标志8 b2 C8 T6 ^4 d7 |+ k4 g0 x
        MOV  btIsDiskExist, 14 q1 ^( I0 I+ w9 l( n# Z1 F
. r2 F9 ]7 i* P& n9 H* j
        // 发送存取端口命令
% M6 y8 W- G, ^/ L, `        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
- N9 _6 u5 e  a) ^( e5 |6 Q( Q- k        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
$ U: {9 q" @2 F% v# a, I        CALL WaitWhileBusy, O" H, M( Q0 Z* d. I
        CALL SelectDevice    // 设置主从盘标识' _2 U, T2 i3 s8 z8 J
        MOV  BL, btAtaCmd      // 发送读取命令
; J  s8 w( g, r1 e) w& t" |        CALL SendCmd3 n& c- {# t! `3 f6 [( N9 i& L" U
        CALL WaitWhileBusy) ?, K. C1 [; w2 k% n

: ~( P2 b9 Z! O1 B        // 检查是否出错
8 x* u8 T! x- |+ Z) v$ W6 ^' p        MOV  DX, dwBaseAddress* m) y4 o* m' }
        ADD  DX, 7+ }" q8 c; o' J' E
: {& s! m+ t1 J2 w0 z- f
        in   AL, DX
* [. y/ X% v( ~3 h! A
6 I: {4 a5 Y8 N5 u6 v4 G        TEST AL, btBit002 v/ J+ F+ J. f3 G9 D/ A
        JZ   RetrieveInfo   // 没有错误时则读数据
# {. j4 l6 z9 J- {1 N7 Z; {) E4 l: v# W, F# ]5 P1 A7 d; h
        // 如果出错,则进一步尝试使用ATAPI设备命令- v1 J. X, U9 |: K3 Q
        CALL WaitWhileBusy
- J. o9 {- V7 D+ M  q        CALL SelectDevice
( |3 x; c2 s! S/ q6 M) L        MOV  BL, btAtapiCmd; Q) Q! Q, r' |4 O8 l6 V, \
        CALL SendCmd0 e! T5 o: |- c4 f' K3 ]
        CALL WaitWhileBusy0 H2 n, S+ r+ T

* F) C2 h* R! y$ l) |$ h        // 检查是否还出错6 K3 t2 A0 r* a( U8 M6 @9 ~
        MOV  DX, dwBaseAddress
: O5 [$ u; C8 O/ X: l        ADD  DX, 7
+ X. ^/ ?" O5 l/ m2 S# s/ r        in   AL, DX
. v, d1 t) T! @" o- i) o" y        TEST AL, btBit00
3 {6 B7 `5 c' u$ `& t4 a        JZ   RetrieveInfo   // 没有错误时则读数据% {4 Y0 }$ z: J: ^; Y
        JMP  LeaveRing0     // 如果还是出错,直接返回/ r" s2 x* U7 t1 G5 d6 ~
6 y+ Y" d- C5 i
        // 读取数据
: [4 e1 B% C  F$ \        RetrieveInfo:
6 n' p) k4 H! I" j* J9 l6 q2 L/ v
! M. |0 r! N- I        LEA  EDI, wOutDataBuf# q2 B( z# `& G) _/ I3 C6 W
        MOV  ECX, 256
* D/ u. ~& U5 m, H& s6 s        MOV  DX, dwBaseAddress# m3 u6 m2 x$ e# U' P, B* p
        CLD
* j9 j2 w6 x  ~5 k) _" N/ F5 O; k+ r8 v" X2 ^
        REP  INSW$ y7 v( W: o# B6 M0 G

! V7 i% k. I3 r" [        // 退出Ring0代码
4 ^) B, S" w4 z( N! ~4 l        LeaveRing0:/ X& }6 `/ k6 W1 O. ^# o

4 _& r8 ~6 n: i. d        POPAD) y$ V5 B! S7 Y6 ~' Q6 |5 l
        IRETD
0 Q0 J6 n6 C# P* }7 }7 Y7 `, C: E2 c
        // 激活Ring0代码
, [" @, V& n6 X# L+ A/ F% D        EnterRing0:
7 u$ u' v# @3 \! k# m/ X1 y
  N7 w- k* n! W& c8 h, J& h0 P, G. u& w        // 修改中断门! x0 m' }) X( A% f
        SIDT FWORD PTR btIDTR1" [, W; N+ [0 I8 w' V( ~: s3 X( V
        MOV EAX, DWORD PTR btIDTR1 + 02h
9 J3 R7 d! E5 R) w- L3 P        ADD EAX, nHookExceptionNo * 08h + 04h
3 V" E. M  ]; T9 P3 s" A1 r$ M        CLI
2 n$ @# Z# |4 M5 ]0 H6 u
  ^, x  S; g' v, I( z* s# a4 s        // 保存原异常处理例程入口, E2 _# H! o$ P. ]5 X
        MOV ECX, DWORD PTR [EAX]1 @) g: y) l9 R7 O8 b1 U
        MOV CX, WORD PTR [EAX-04h]3 w. i& b/ I+ [. @+ F8 H
        MOV dwOldExceptionHook, ECX
& _4 k. C  h% T
# x+ g; J. q3 O: H        // 指定新入口& V! [, l5 D7 z' ^/ ~0 T
        LEA EBX, Ring0Proc
/ z8 C; m: L" ^) {9 u* H0 ]        MOV WORD PTR [EAX-04h],BX
( W0 a& @8 Y* ?4 ?- `) t2 g        SHR EBX, 10h
4 f3 \% z9 v  o( Z. ]7 f- h        MOV WORD PTR[EAX+02h], BX
% D& O  i3 C. v/ G/ y% [+ X4 |3 P6 {7 p9 Y3 v  I
        // 激活Ring0代码
8 ^& \0 |- c# L' H% n6 o, n        INT nHookExceptionNo- F7 u" X* r0 E7 ?, D; N

' v) [" V' H6 U$ i/ U" ]        // 复原入口
: f1 K7 i( R. L- u# ?! R# l        MOV ECX,dwOldExceptionHook& E! K1 f8 k0 {+ n* t# J
        MOV WORD PTR[EAX-04h], CX+ P" N* i" ]+ I. g
        SHR ECX,10h
: c/ i8 K8 I# K1 o- f" z0 X- v        MOV WORD PTR[EAX+02h], CX
: E- A' h0 G7 a  J) Z# c! O9 ^        STI
; `) S7 c" S$ K' S  p    }
" `( l% e/ j7 _+ L6 ]5 y    if(!bIsFirst)7 O  x' W7 z! h& F3 u! u; L
    {
; T+ i4 d9 d6 w7 t        bIsIDEExist  = (bool)btIsIDEExist;
3 `+ `! a) o5 p; |7 S        bIsDiskExist = (bool)btIsDiskExist;9 s5 f7 J! M2 j! [9 h! }
        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
; v$ p: J* D4 _    }
( q* ^/ E1 z# X2 R}& Z4 {9 ]7 S: f+ ~( ]6 O. K
//---------------------------------------------------------------------------4 J. C$ d2 }- f
// 调用方法:6 R1 I8 e) ?! `, Y8 v9 P# ?/ y
void __fastcall TForm1::Button1Click(TObject *Sender)0 C; h. n2 u$ R1 @/ v* \; T; S/ H
{
" S- b) A- ?5 t    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
- D) U0 C0 p5 L$ {/ r}2 h- p1 `2 |, B3 B/ l9 |: M4 \5 K
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-6-18 07:59 , Processed in 0.021771 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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