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

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

[复制链接]
发表于 2008-1-6 19:59:06 | 显示全部楼层 |阅读模式
代码框架,你所要做的仅是修改WQL语句,具体可看MSDN。以下代码为简介起见,一次返回所有的CPUID或硬盘厂商系列号" ]5 G* q& y$ O" P; v, o
  1. $ P  e. R$ ~4 }0 Z' Z$ r
  2. #include "StdAfx.h"
    " `" q$ n# F2 @7 f! H" J2 K
  3. #include ".\puiddisk.h"
    1 q' I( [, D: V( G8 k5 L
  4. #define _WIN32_DCOM% h: k1 n% D7 K, z( C
  5. #include <iostream>- x2 Q& I4 [5 e! B3 T* T7 {
  6. using namespace std;
    7 h/ l9 ^/ c" A/ ^, }, q8 z" ~
  7. #include <comdef.h>8 A/ Z8 T$ `  f0 A$ [( A, V' H. B
  8. #include <Wbemidl.h>% |: Y! W' x/ r2 ~- h1 e
  9. : s# {& e5 [' H& n; ?0 o
  10. # pragma comment(lib, "wbemuuid.lib")4 R4 \  _3 n! v( L8 \/ a. `
  11. CpuIDDisk::CpuIDDisk(void)
    * A; X$ J( s, n! X* _  U  t5 j+ k
  12. {& I( Z; `8 n. A" z3 ~# w4 |% N
  13.     GetInfomation();
    6 Z# V4 r, ~; W
  14. }
    + ^( n3 U7 g. x+ D

  15. 6 S; b4 r! V; A( w5 z0 ^
  16. CpuIDDisk::~CpuIDDisk(void)  }3 [# B" P3 W( V9 I. j  o! j4 E
  17. {
    + b  i% w3 B1 l- Y" m, {
  18. }. \( B1 {5 O6 _8 _+ p
  19. int CpuIDDisk::GetInfomation(void)
    0 j% z  @, j) p7 ^. q+ b5 w. |; A7 Z1 G
  20. {
    2 Z0 O6 Q2 N% M6 v, ~5 O; j
  21.     HRESULT hres;9 c$ X) G/ k! {" J
  22.     //步骤1:不是必须的,COM只须也只能初始化一次; i$ C. E' c( ?
  23.      hres =  CoInitializeEx(0, COINIT_MULTITHREADED );8 K6 y3 z5 r, _8 T( y/ M8 G  k
  24.     if (FAILED(hres))4 R  U% K/ K) I* L" w2 [- ?1 d9 [% E
  25.     {
    1 e5 [# Y4 B' A3 W$ t0 s; a
  26.         return 1; //初始化COM异常:注意,COM只须也只能初始化一次
    / o% Y9 p. B4 }, I4 O
  27.     }4 a* G4 ]% L  M" l' J
  28.     //步骤2:不是必须的,COM只须也只能设置一次! F: n, }2 O9 @/ }. I/ Z5 H
  29.     //Set general COM security levels. ^! p$ S1 Z; x5 X
  30.     hres =  CoInitializeSecurity(3 I' E0 ]" ?% Q  d* |& K$ F
  31.         NULL, 1 X, F# t( e, y- M9 F8 ~
  32.         -1,                          // COM authentication, Q/ d/ L: Y" ]$ c+ n: p
  33.         NULL,                        // Authentication services
    & p6 v" F4 p6 B, K% v  i! u: B& Y, e) q" C# m
  34.         NULL,                        // Reserved5 Y. f: {9 k! p, I2 a
  35.         RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication 5 Z' m( O# m$ d) a- {* A  L( \
  36.         RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  1 V7 \( N: e9 l& y8 Z; `( I
  37.         NULL,                        // Authentication info% h5 Q" {' I8 [; n" {1 G% D$ X3 J0 Q
  38.         EOAC_NONE,                   // Additional capabilities 2 `2 m% j% o0 y7 D; r
  39.         NULL                         // Reserved, R" t. D9 X+ h1 }1 w' x/ l
  40.         );
    0 g( z  |/ ?% b" H% o6 B4 v" U
  41.                      
      I/ L9 b- j- Z7 G2 G0 e
  42.     if (FAILED(hres))
    0 V% K& ~, V- M. l& P% [: M* X
  43.     {' w* L! w+ z5 J, m. b
  44.         CoUninitialize();. i( |: l# Y3 |/ x" C
  45.         return 1;                    // Program has failed.8 z3 }% i2 D2 `% F  A7 m/ M8 d
  46.     }
    " ?0 o0 g9 Q% I* L; E  c% Q
  47.     ' \( `+ @0 u7 ?9 d" n6 z3 P" y
  48.     //以上不是必须的,若已有“::COMInit();”,则要跳过7 R+ f/ C# G& i$ p! ?% P' a1 u. s: I
  49.     //步骤3: Obtain the initial locator to WMI 4 M  p; U* h" e3 Q0 A4 `
  50.     IWbemLocator *pLoc = NULL;
    # ~% ~- v/ m# v: b/ I( C" t
  51.     hres = CoCreateInstance(3 D6 s* C, R5 T' i
  52.         CLSID_WbemLocator,            
    ! n0 f" u8 T& R+ B9 p( l5 _4 |
  53.         0, 3 A+ G, L, y" B1 Z4 m2 t
  54.         CLSCTX_INPROC_SERVER,
    ' l) }2 D+ h( s; z% U! h
  55.         IID_IWbemLocator, (LPVOID *) &pLoc);2 V# K( {, \/ B  y: W
  56. # ?. W! O5 x7 s# x) V5 t7 U
  57.     if (FAILED(hres))
      b) A( h7 R) w3 e# ^
  58.     {
    ' @$ ~, p- H4 v/ Q- q) E& Q- t
  59.         CoUninitialize();
    ) R/ y+ _# K" B6 ?! E7 y
  60.         return 1;//Failed to create IWbemLocator object
    7 y* G5 }3 \) X6 ]' b+ k* Z" M- ?
  61.     }) E. @3 R& l+ U5 @/ z8 @

  62. % x1 @2 s, @$ N  N0 j) N2 N7 ?
  63.     //步骤4:Connect to WMI through the IWbemLocator::ConnectServer method5 J& C( f. L& X
  64.     IWbemServices *pSvc = NULL;
      |8 V' J" \* @9 a/ v
  65.     hres = pLoc->ConnectServer(
    4 y6 d9 Q4 d9 e6 l
  66.          _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace7 ^# u7 g) }2 K. o, z- h
  67.          NULL,                    // User name. NULL = current user
    5 R& c7 m$ ?' Z% m3 x/ }
  68.          NULL,                    // User password. NULL = current  z8 e) k0 p! A6 w0 H( b
  69.          0,                       // Locale. NULL indicates current1 F* B1 m3 G. ]1 |1 G4 i
  70.          NULL,                    // Security flags.( ~2 C" v5 s6 l1 R- f7 H
  71.          0,                       // Authority (e.g. Kerberos): I$ k0 ^  B+ R2 |0 A& Y  y
  72.          0,                       // Context object 5 i3 I+ n, c$ ^! h4 N" N! B% A
  73.          &pSvc                    // pointer to IWbemServices proxy7 G' S0 a  @9 O' |2 [9 ~  x
  74.          );8 \" q* u4 t# w3 Q
  75.    
    % G. u* W& `8 V, p! i( g# a  I4 m6 R
  76.     if (FAILED(hres))+ V! @+ e; d# O+ I+ R4 G6 b
  77.     {! Q& H) k% b# j
  78.         pLoc->Release();     
    + B7 V& u0 {3 I# P6 C
  79.         CoUninitialize();
    8 Y3 n0 I: v+ J* k! f
  80.         return 1;                // Program has failed.
    8 w5 ?3 x3 \0 {: D8 s1 v
  81.     }
    & X) E) ?0 ~3 I) O1 O* P: A
  82.     // 步骤5: Set security levels on the proxy6 X; ?+ P' A' {0 {* j; H
  83.     hres = CoSetProxyBlanket(
    ; k. {, i+ t( `0 @+ ^
  84.        pSvc,                        // Indicates the proxy to set) q( S( \9 V4 ^0 d+ `
  85.        RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx  \. r$ X1 z8 s' D9 v3 b: b0 r
  86.        RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx' p/ i& r: w: A6 D  L! N, z
  87.        NULL,                        // Server principal name
    ( ~4 _& @( v( j1 n0 R* A
  88.        RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx + `4 ?3 g0 H  A. x* K! S
  89.        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
    9 w7 V& ^) T) K
  90.        NULL,                        // client identity
    ) ~. k$ |$ k2 h; K" B) _
  91.        EOAC_NONE                    // proxy capabilities
    2 o5 s7 k, p; m! ?3 m
  92.     );+ Y3 Z$ f$ Y* }3 r0 T& Z3 c; i9 y

  93. / w5 t4 E" C0 U6 `+ ]
  94.     if (FAILED(hres))  `" E. V  K# b7 ?: G2 |
  95.     {
    # f6 u2 H$ J! J/ n
  96.         pSvc->Release();+ Z$ D7 q0 \/ S5 M" g- t; y, V
  97.         pLoc->Release();     ! {& T" H- b, P1 j
  98.         CoUninitialize();
    5 |# M+ _+ m# O* o3 x
  99.         return 1;
    + [9 h/ ^' i1 ]/ m) M
  100.     }2 z: g/ @& a. j9 L8 p
  101. 0 O3 Y/ ?  q8 Y, H
  102.     // 步骤6:Use the IWbemServices pointer to make requests of WMI ----# @6 ~4 f% [+ S4 _" ~0 f" M7 A
  103.     IEnumWbemClassObject* pEnumerator = NULL;
    8 Q, a- ^& D* p: J* m* i+ s
  104.     //计算CPUID
    6 @4 x" f7 k" [9 n$ a) _
  105.     hres = pSvc->ExecQuery(
    $ {& @& J: x, a) _# h
  106.         bstr_t("WQL"),
    ! ~( s0 o4 y+ T) A2 I
  107.         bstr_t("SELECT * FROM Win32_Processor"),//Win32_OperatingSystem6 R2 v# C) ~/ X
  108.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
    % o1 |- E( M( G5 t6 d% v
  109.         NULL,( _2 K; V2 ?% Y! A* Z2 D
  110.         &pEnumerator);
    , t; c+ N. Z5 B; N4 i& D
  111.     & v! A! g) V! c
  112.     if (FAILED(hres))
    " e6 l$ T/ [4 x* ~. G
  113.     {8 n/ L1 Y- ^- b2 k# n/ L  ]
  114.         pSvc->Release();1 ?" ]. N3 A4 ~
  115.         pLoc->Release();
    9 P/ z% V7 ^; V8 I
  116.         CoUninitialize();
    - W2 z3 V0 Q) R: I8 C- D8 N
  117.         return 1;
    : ^# j+ t$ b1 O* ]& x/ V- |+ D
  118.     }
    ! b' Z0 R/ M- D) G: h9 s
  119.     // 步骤7:Get the data from the query ; [9 E1 O9 v: h" Z
  120.     IWbemClassObject *pclsObj;
    ! ^- _" T/ D. {
  121.     ULONG uReturn = 0;7 z7 B" _/ d0 _$ E/ B
  122.     while (pEnumerator)  b2 K$ s+ [+ ~9 K1 d7 W0 F
  123.     {
    . e! d  G4 Z! j7 h) d$ u
  124.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, % ~5 g& J1 r' [; m8 X
  125.             &pclsObj, &uReturn);
    / t3 ^0 T* i1 |; O( f
  126. 5 q7 f' D! i* S" `6 G
  127.         if(0 == uReturn): x3 P; S1 D, V/ v
  128.         {/ V1 m0 c8 @& R- y! b# {) ]+ E8 X, E
  129.             break;
    8 p+ A: T/ P5 E' s4 j
  130.         }
    6 {8 S- d: Z! f" T6 Q
  131.         VARIANT vtProp;
    % p1 H& j& E' Q. p$ _3 p+ |
  132.         VariantInit(&vtProp);3 i- W  W- e/ i2 H5 Q* y4 j0 ~
  133.         hr = pclsObj->Get(L"ProcessorId", 0, &vtProp, 0, 0);7 E, r2 D4 m$ X% z8 M
  134.         strProcessID=_com_util::ConvertBSTRToString(vtProp.bstrVal);//strProcessID:类级变量
    - v: }/ ?4 z/ e( l
  135.     }
    9 h+ d# ?. f" Z
  136. - o  @' D6 i7 @+ ~
  137.     //计算硬盘系列号
    " O) a$ s+ E% J) M% f. G6 M# E. D, b
  138.     hres = pSvc->ExecQuery(" h: n3 k6 H3 I
  139.         bstr_t("WQL"),
    ) s& P8 Z: _/ M, Z/ A0 B
  140.         bstr_t("SELECT * FROM Win32_DiskDrive"),, K6 J% t* l( D+ A0 V0 F
  141.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, $ }" [3 C. |+ B
  142.         NULL,
      @/ _, j" l# f
  143.         &pEnumerator);
      @/ U1 _2 A& j% M3 U  @

  144. - ~; g: Z) [4 O8 y$ z# V
  145.     if (FAILED(hres))1 g! N. }8 ?0 b) j$ c
  146.     {) B# B; f; W" [& S; }" C
  147.         pSvc->Release();4 }6 r8 K: X, U! z. Y& A8 S" g9 i) O
  148.         pLoc->Release();
    - N! K2 m* }7 I: E! s2 U& I
  149.         CoUninitialize();9 ]: O' }8 e- Z( e0 }! F; C  I
  150.         return 1;
    ' q2 |1 R2 L; @( L3 E% S- k
  151.     }) A& Y& I! I8 F5 N
  152.     while (pEnumerator)
    * @& h4 ~8 A' R" ]7 `$ D) q; ?2 t
  153.     {
    $ ?8 V% n# s/ H- _
  154.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
    7 P  S. Z) ?7 A. q- L5 X( i
  155.             &pclsObj, &uReturn);
    ; m2 u* X* w$ Z
  156. 0 ^0 S) s. a7 `& [/ f: h" ^" u
  157.         if(0 == uReturn)5 ]! f4 j( S$ X; s
  158.         {
    6 r( q& ~  Z6 G1 Z( v9 d& F
  159.             break;
    9 g' A3 r7 C" A
  160.         }
    ' z' L- C" i6 e, T

  161. : W6 F& A# m# v
  162.         VARIANT vtProp;  b& i4 q8 ^( D+ l: S
  163.         VariantInit(&vtProp);
    ! ^. T$ c; U, i
  164.         hr = pclsObj->Get(L"PNPDeviceID", 0, &vtProp, 0, 0);8 `4 @! S: t; q: l& A7 v
  165.     strDisk=_com_util::ConvertBSTRToString(vtProp.bstrVal);# V; c2 e1 c& b
  166.     }6 F3 m% x  [4 ]/ I" d' Y4 d
  167. + J' m" m2 R% ~1 [2 n
  168.     pSvc->Release();) L- @9 `8 c2 i! \- Y
  169.     pLoc->Release();* h9 R5 ~( }, Z( o1 F1 p
  170.     pEnumerator->Release();0 c2 o- [4 V/ E% ]1 t
  171.     pclsObj->Release();
    + z3 Z8 z& l* Z4 A3 o
  172.     CoUninitialize();# B2 Y, V6 Y/ \; y; B9 G' a7 D( O

  173. + B  F7 O% y7 E" J3 b! @+ Y
  174.     return 0;   % L& ?3 T& l. q- w+ l. |! [
  175. }4 l; U3 p4 @: P- ~( M) D9 l- p
复制代码
 楼主| 发表于 2010-10-11 19:21:05 | 显示全部楼层
本文代码经ccrun(老妖)在Win2k下试验成功.& ~) B/ |; C! w( G& t2 `) m' q* I

. c: L+ P. I% b3 B#include <WinIOCtl.h>% T( n$ I! m. j! f
#include <stdio.h>
. T$ v' H* m7 d1 k
  h- D1 q3 N7 I% q6 D  \0 g#pragma inline) ?4 }2 |1 a- G4 M; X! Q
//---------------------------------------------------------------------------
( Q# L  {5 W0 |$ ^# T5 o. b- |// IDE NT/2000/XP专用变量9 K$ x* G# Q5 m4 E# W2 B
#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS/ T+ U* {+ \2 ^% ?
#define DFP_GET_VERSION         SMART_GET_VERSION
* W1 x$ h' ]$ A! ?( k- L8 H! _( R#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
4 @5 j* P! W9 X+ g#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
3 u2 u* Y" y/ f. M( t; W3 F# q! A0 c* w& l9 F. V
const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令
9 {! C* s7 L( nconst WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
" r- g) y) W- K8 C2 c6 v$ O7 o  Q6 K0 m5 u! h0 h/ ?& Y
const int MAX_IDE_DRIVES = 4;
. y  c# @( |; t
1 V: J8 d- C6 s0 w- q0 x" R// SCSI专用变量2 \- a6 k9 q. Z+ I
const DWORD FILE_DEVICE_SCSI             = 0x0000001B;
* F, K- c2 l+ F* u! Oconst DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);2 ^/ w( f- A6 C
const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition: `' ]5 v! Q1 W3 @; b; i# W: a7 G$ p0 N
const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;8 }. l( S- m9 S2 v
7 h/ p7 V4 s" c
typedef struct _SRB_IO_CONTROL
  F* w8 K$ E4 {! [9 j! L8 V! \{
6 H& h, Q- w) N" a, g6 h8 e' I) S/ c( e    ULONG HeaderLength;8 P- W: B( {: t. o! k
    UCHAR Signature[8];* j4 C& I6 H/ a) D* @) B7 n8 w5 D
    ULONG Timeout;& f' `0 ?' a' F7 a3 T- {! n: w
    ULONG ControlCode;
9 M- f* Y( |+ I5 k) N    ULONG ReturnCode;
# a' ]) T% i8 L! A+ ?" y* H    ULONG Length;
  i" Q% ?! A/ i( G5 [}SRB_IO_CONTROL, *PSRB_IO_CONTROL;
% f$ o1 x* t- u% |- O9 C1 l* ~. C' Z- }* ]/ l* C& D( @# M
// 读取的主函数
2 }3 U; G% I7 q7 Y2 zvoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
/ G$ d. e5 n+ y+ I* {. l# i+ |2 |$ o% n9 h8 z
// 辅助函数8 @& E4 t% F: p1 u" v7 V; F
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
# l! h' Z$ C0 D// NT/2000/XP函数+ F* @/ X" r* [( O' q
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
) `) I! A0 b$ {0 T6 abool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,- \) Q. g1 A8 M: Z
        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,1 j' U2 V1 [. o
        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
7 m4 I- f7 P& Q# G: ]2 A// Windows 9X函数: \5 F% X5 Z: C- G3 ~
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);2 L& w7 U+ e( f9 Q
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,. x! G+ `- o' @
        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);0 o6 _# F8 e1 k  R' k$ p; G- t

; v# Z6 _2 `( e' V+ `# ]# N// SCSI读取函数(for NT/2000/XP)
  t* J. n8 o' y3 S  F- G' `, }' mString __fastcall ReadIDEDriveAsScsiDriveOnNT();
9 ^4 N6 q4 ]) G! W5 E. J8 Q! X. ~$ |//---------------------------------------------------------------------------7 }8 {2 A/ Z, k+ _5 H
// ReadPhysicalDrive3 I. t) N- |  X" A  G# G
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)9 V0 y+ U0 R) B! \0 U, q+ X
{" C: a6 G! ?& p; E; f/ a# W1 e
    switch(Win32Platform)
& |' e; K2 F" z    {
6 k+ T# ~- o% {+ g& Y3 q: f        case VER_PLATFORM_WIN32_WINDOWS:* ?" ?: b: R& Y
            ReadPhysicalDriveOnW9X(pSerList, pModeList);2 D; ^! Y" \! `
            break;
0 t6 _3 n3 o& D. K* ~) S: \! c        case VER_PLATFORM_WIN32_NT:
( d( t2 w0 L: s. d- [% Q8 N+ q            ReadPhysicalDriveOnNT(pSerList, pModeList);
* a0 L# N; _: L9 L; S            break;+ C# D" k  e7 O( ?  M# f* h
        default:
- q' l/ s; L% O% X# l( O            break;
" s' f8 d* n+ E+ j# V+ z) D    }1 B* P" A) Q" y) @! a: r
}1 B; {# ~1 c* f- T9 c% n! N
//---------------------------------------------------------------------------
3 w( `7 I) }! A// ConvertToString+ J! m, e& n9 H  p6 X, Q
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)  Y! L& a: s7 p7 {; p6 E8 D
{
6 s. W* s( Y3 q    static char szResBuf[1024];0 K4 L. l5 f  Z% f9 D3 M2 h  z  t
    int nIndex = 0;2 G# w. G$ q7 e
    int nPosition = 0;' h1 \9 I3 T* U8 B# q; q

8 J) B9 b1 N$ l9 F    // Each integer has two characters stored in it backwards  y) E& f5 v. b
    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
( i/ V, i2 K( m4 a    {* |8 |! Y# P% s( a+ k3 o7 R/ h
        // Get high BYTE for 1st character
2 C' }# j# V% K. H$ s        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
: |5 G+ d, u  F  ~0 V1 e        nPosition++;
+ K& C% |+ g* j1 @& @1 t+ D
3 h. V' c! n; }        // Get low BYTE for 2nd character
$ U# v: z& O( E' R* Y, @3 H        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);, m- b( S' E4 }% q1 S
        nPosition++;# T* L' l( ~! A+ P% G
    }
% `# s. n) b2 e) b
& J# p: \. f2 M: `9 Y    // End the string
. H  n" E% k/ |- p6 z+ F    szResBuf[nPosition] = '\0';
2 A* x8 o. V% ?0 E* A' b  b, y& z' B6 M6 B  Y  L, Q& ]
    // Cut off the trailing blanks3 N/ w7 P+ q% R9 _/ u
    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)( @! ~+ I) D" y) A/ @- T
        szResBuf[nIndex] = '\0';& n+ `, n: r; a0 ]7 a) ^$ t8 q

! W! ?2 J  A7 N8 ]5 p4 m    return szResBuf;4 F1 m  P: X3 @% C
}) [: W5 y& U, i" I6 t1 ?
//---------------------------------------------------------------------------1 X; A- f8 n; e! o, ]- L7 E; Z4 |+ t8 f
// Winndows NT4/2000/XP 代码
5 h3 B( ^  S. f  m8 J//---------------------------------------------------------------------------* P5 s) j+ o* B, f0 p% X3 _
// ReadPhysicalDriveOnNT
$ {- ~, a' v% i+ N) u5 Q6 {3 M6 Ovoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)5 h/ Q% {) U0 D5 u. H
{2 m! P, y  z- c/ I. m
    // 输出参数
0 }9 T% j/ E+ Y) a0 H+ N! O    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
/ Q$ {% w5 k# f9 R
$ K. H/ A8 ?, G+ h& U% k    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)5 {! M$ }5 G' i# U
    {5 c# d& F8 `- W8 F$ p
        HANDLE hPhysicalDriveIOCTL;
$ h# W+ [- W9 Z! M+ i        char szDriveName[32];1 y4 y) o7 d, Q# u
! k; \6 k* \% }5 Q9 U8 u; e5 A
        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
4 h- z/ E  K$ ^2 v4 X% S7 C        hPhysicalDriveIOCTL = CreateFile(szDriveName,. f, J. `7 G# e* h* J6 r( i
                        GENERIC_READ | GENERIC_WRITE,0 }4 |5 n+ R$ R% f
                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,/ Y! L# g% J4 U) E
                        OPEN_EXISTING, 0, NULL);
9 W7 [& t+ [2 u) a8 O# l% @, k+ B! m
        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
4 H9 e8 W* S  j3 b. {) G" J        {8 s5 h, V, m) Y! R7 b. J
            DWORD dwBytesReturned = 0;: `$ @7 e/ [0 e& u
            GETVERSIONOUTPARAMS gvopVersionParams;
8 ^& V7 N7 I5 z* e
  o4 I0 b: e3 `- G6 {6 U            // Get the version, etc of PhysicalDrive IOCTL) t0 B+ f- c. G3 h/ e
            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
3 `. `; V$ S$ }+ |8 A2 ?2 W0 T( u) h) o/ @' t; P, `/ Y. Q
            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,& ^  o& p2 D3 A
                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
% S$ P/ }7 }' o5 U$ r' `" W                    &dwBytesReturned, NULL))
1 E, e% C6 ^# u            {
2 Z7 T7 P- d( C, m2 k/ C% n( _                continue;; O) ~* g  h; M9 p* r" N
            }
7 W, i+ N5 z- f, j! L7 {( L1 i) r  [$ G+ D
            if(gvopVersionParams.bIDEDeviceMap > 0)
; v3 |* I' j0 g) ]0 {            {$ f5 ?$ u7 N2 i+ Q# o. ~2 Q( w
                // IDE or ATAPI IDENTIFY cmd
5 `6 A' G+ c- e( q                BYTE btIDCmd = 0;8 P' U2 w) ]6 B1 y1 Z& V$ a" B
                SENDCMDINPARAMS InParams;8 H; U1 G7 ]  Y
                // Now, get the ID sector for all IDE devices in the system.6 l" P- a+ Y9 y5 s7 |$ L! E
                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,0 l! z" s" m. A+ U$ |
                // otherwise use the IDE_ATA_IDENTIFY command- b: v9 t% _) \
                // 具体所得结果请参考头文件中的说明5 x) l8 n* M) F
                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
" g$ h$ {/ B  o9 `! [" i3 C                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
: F2 r$ ^) t( g$ {! D% U                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));6 U0 Y* F+ F* e# }  ?0 X$ L
                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));2 p4 }4 n& Y2 s5 P/ T8 O
; E. v( j+ y. d
                if(DoIdentify(hPhysicalDriveIOCTL,+ a' f8 R- y& }
                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
4 B* F5 Q: a" d5 ~) g                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))! o& Q" f' c  c$ C8 r
                {
1 l1 q6 Z  P" {, Y, h1 g1 P; W                    DWORD dwDiskData[256];
( C7 x$ ^+ z/ n$ ?, W                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
2 L: y. N' ]8 [, d7 f. I1 g+ j, K                    char szSerialNumber[21];
! u0 q4 l1 [- `7 R9 |                    char szModelNumber[41];' d' A3 N% }' A4 @

' S! c6 M" J/ W$ E3 u! C* C                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;6 ^0 i  d  C7 ~) R8 j' e0 v
                    for(int i=0; i < 256; i++)3 d5 F# P8 r0 S7 `. z
                        dwDiskData[i] = pIDSector[i];* f0 X; [8 K/ m  K4 r5 X3 s
                    // 取系列号2 c5 A& T1 C& u4 v
                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));, h9 N! G+ p! N, _: \6 [, @* V& U6 ^
                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));; V+ N8 }' j* Z' v: B
$ F2 E8 [/ [( r8 A4 H0 T8 N/ p3 P+ |
                    // 取模型号
/ T) Z2 E) Q" H7 Q; ^                    ZeroMemory(szModelNumber, sizeof(szModelNumber));
! Q1 T* D1 G4 E3 x  \                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));3 I  u# c- H: z
2 o4 S' a: H1 U! r. n2 T
                    pSerList->Add(szSerialNumber);( {2 p. C1 V1 |
                    pModeList->Add(szModelNumber);
0 U/ b5 ?( d' o, i9 T' q- }                }0 P# S8 Y4 o* [$ V6 u( u$ y" i
            }& a- e) a/ S' T) I$ g
            CloseHandle (hPhysicalDriveIOCTL);
( J) o3 Y% p2 _6 _4 I7 m$ p        }
7 F5 O2 q) R( ?1 c" U( k    }! d$ E0 ]! b( {4 ]0 Q+ M6 x
}8 V- J4 F  D+ e3 q
//---------------------------------------------------------------------------' \' V" {7 I( J7 v9 S  O0 Y& D! V3 G
// DoIdentify
7 Q5 x1 ?# q& lbool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
+ X/ d# D# r+ N2 h              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,# S% Z9 d* w: t' u1 L1 [( B! ?3 o4 i
              PDWORD pdwBytesReturned)$ h- Q" @: I5 Q9 V) L: J. P
{
0 s. ]$ w2 G; I8 o6 g    // Set up data structures for IDENTIFY command.0 ]  K' k2 F# g: M' Z/ b
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
# k+ R6 u) R, }0 X2 Y    pSCIP->irDriveRegs.bFeaturesReg = 0;5 U9 [* P! I4 l  h2 \+ l
    pSCIP->irDriveRegs.bSectorCountReg  = 1;
% h0 |  a; h5 O# h3 d+ K6 B    pSCIP->irDriveRegs.bSectorNumberReg = 1;* M- r3 u( C) L5 l) `8 U, l( Q
    pSCIP->irDriveRegs.bCylLowReg  = 0;7 b1 M2 c0 |& U( L
    pSCIP->irDriveRegs.bCylHighReg = 0;
- l& f$ ]$ S$ c9 H  J6 H. N
" z' R+ R$ b- }  }; `6 ]    // Compute the drive number.(主盘和从盘所对应的值是不一样的)
. s  ~! P% B% y) M$ V' S    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
9 D  M! n& ~$ [# F  i# I
$ L: c  g" T- e( O% R8 _# O    // The command can either be IDE identify or ATAPI identify.9 ]1 P9 `7 c4 v# J
    pSCIP->irDriveRegs.bCommandReg = btIDCmd;' ^, V' _* v; v* S9 t$ m" P
    pSCIP->bDriveNumber = btDriveNum;
- g4 Y- b0 W5 }  ^    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
6 j3 X. e5 r* O, V
/ n% V2 P: M; c4 ~    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,, ^( d6 x4 s6 X3 W7 ]6 [
           (LPVOID)pSCIP,
( U  }( Q# ~. x' I2 ?$ K+ `0 C8 q' M  O9 q           sizeof(SENDCMDINPARAMS) - 1,2 [4 Y# C  K% Y. b$ }
           (LPVOID)pSCOP,: y( l- A4 {# o( e- _
           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,9 B3 b) b" F: Q/ W; q8 }
           pdwBytesReturned, NULL);0 {! }1 f, v8 Y+ S" b: Y6 v
}  ?0 [  v9 t" J; N; z7 i4 ~+ {
//---------------------------------------------------------------------------& K: r8 S" M. |6 R. P- T
// Windows 95/98/ME 代码7 x& J' F6 X: v$ m
//---------------------------------------------------------------------------2 r) T9 k4 z+ k4 a% B
// ReadPhysicalDriveOnW9X
3 q6 ]5 ?6 @7 Y# K3 m2 K2 M1 Kvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)
1 ?3 v) l0 i% Z; a0 x$ _{
4 I& t) p7 z3 \, l5 K    WORD wOutData[256];# N+ i$ W; v+ E; M- }5 j, U
    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);4 F) J  x" [; A

5 x- Z+ |7 |% y& H& ^8 R    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
+ V8 C7 [+ [& {0 Q    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
) n$ Q9 S( S+ b0 ]# }- U8 o    // 避免蓝屏的出现。(期待高人能指出原因)
& B2 L: A4 }+ R! K$ I: C7 ^: f    for(int nDrive = 0; nDrive < 8; nDrive++)
* ]' H1 K& L8 p    {
( N' A* v' j9 P8 e8 e: E( ]        WORD dwBaseAddress;1 S8 k+ b) C& z
        BYTE btMasterSlave;         // Master Or Slave9 _" t3 `+ X2 a6 ^
        bool bIsIDEExist;
* L7 m4 v/ |8 d: D; n7 M        bool IsDiskExist;1 ^/ h* @: x) _- w
3 r  J$ s- O# u
        switch(nDrive / 2)+ Y# u* r2 E9 u' a- ?
        {8 m- g; ?. ], i/ g. M
            case 0: dwBaseAddress = 0x01F0; break;
4 s$ R0 L, w) c            case 1: dwBaseAddress = 0x0170; break;6 c) e2 i/ d: E% V
            case 2: dwBaseAddress = 0x01E8; break;
6 q* e' y* ?2 i8 }' m3 B            case 3: dwBaseAddress = 0x0168; break;9 ~+ F3 ?+ o$ }# r
        }0 z4 C0 I/ j7 H* q, d
) d; s6 Z4 p! l; _2 D1 b
        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
1 Q! W8 J0 J8 ^" `# F$ [7 W0 a% y$ j  {; K
        // 进入Ring0
8 S; {+ L: S: J1 b  ~# ^( B" Y        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
/ u) r5 v4 M% u                bIsIDEExist, IsDiskExist, wOutData);
. t5 f+ \# b% D5 f3 _* E    }' \: L! T5 _& u

2 h2 X( [2 z7 i5 C% E3 z    // 开始读取& t; W: M1 G+ V+ e
    for(int nDrive = 0; nDrive < 8; nDrive++)
, m0 c9 L+ W- }" {7 N    {0 X2 V" N# t8 v; V% `
        WORD dwBaseAddress;
* X- a+ i" M! e: P        BYTE btMasterSlave;         // Master Or Slave
/ g; S! W5 s5 _, b1 J! k: t        bool bIsIDEExist;
3 n6 ~0 I7 V; i) s" O        bool bIsDiskExist;
1 ~- V! Z. d' M        switch(nDrive / 2)
7 j0 w! T$ u( G3 I+ L1 t* N0 I        {
. k! N: |, n1 e' n& T9 P" z            case 0: dwBaseAddress = 0x01F0; break;
) w" M& K1 n% a            case 1: dwBaseAddress = 0x0170; break;% t; M; O$ b$ r3 ]0 y4 t! f* w
            case 2: dwBaseAddress = 0x01E8; break;$ Z+ M) y. Z5 X. f8 a% s
            case 3: dwBaseAddress = 0x0168; break;( z, W( m" R0 R, A0 J, j/ d7 j1 [
        }
. D4 R0 {1 J/ O4 E* f8 h% C
  @% |& U6 A* _        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);/ j+ V! d: V& @, i2 a( G; e8 {

7 c. i9 d' x' n5 R3 Q0 P        // 进入Ring0) s' d5 Y) G6 r3 V' f2 Q9 h* X
        bIsIDEExist  = false;
4 e4 z1 w( u$ J/ a0 A        bIsDiskExist = false;
9 y& \3 w# U2 z7 T" E+ m& t        ZeroMemory(wOutData, sizeof(wOutData));
+ A1 m; G# s0 b5 y0 x
* P" D  M" I" m& D$ y1 N        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,3 Y; x! I- x# n# ]
                bIsIDEExist, bIsDiskExist, wOutData);- l% }& e0 [% m0 m$ Q% P% Q. l4 `& _- D

/ B( H, W$ L* Z7 ^2 X- A; N        if(bIsIDEExist && bIsDiskExist), {* S$ j7 H1 G( `
        {) K) t" K& I3 {/ t/ y- J
            DWORD dwDiskData[256];0 L! q- w) U; i7 j# @  y( R
            char  szSerialNumber[21];
  S* t" k% q3 {* e: V            char  szModelNumber[41];. o7 Z( l1 i# k; Q
# \' s* L$ Y' u; e# U* r
            for(int k=0; k < 256; k++)  t4 M( w  `2 W& ]+ I, ~
                dwDiskData[k] = wOutData[k];
0 \4 A5 h6 g4 `, \1 k0 o2 G, r
6 z1 V' t% z2 t' R+ b            // 取系列号
& P; @+ ?. N& T9 a* i            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));2 E7 b5 |$ g" Y) T
            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
6 k/ X  {" Q  [0 }! X( k
/ F2 k% E2 M$ Z/ ?+ Y, O/ S$ ]            // 取模型号
( A2 q: g1 [0 T' `+ I) W7 ~( M, S            ZeroMemory(szModelNumber, sizeof(szModelNumber));
( Z, b/ t. x9 j            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
2 p. j( o9 u) }; @, n& `
5 k3 `* B4 u, E6 O5 x            pSerList->Add(szSerialNumber);8 V0 {, M: Y) D4 W6 l) q$ W% b
            pModeList->Add(szModelNumber);
! z9 ~3 x2 L! w$ m: |7 x8 Y        }
5 }" ?7 j; ?( F0 y0 j& }    }- O7 J8 ~7 R8 V
    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
2 g0 G; t* Q; G" j6 R}
; @$ q( q0 }; u. A//---------------------------------------------------------------------------
+ |0 m" y/ b6 X/ X// 为防止不负责任的转载者,在此注明原出处信息,请见谅。
* J7 l" _8 v# l* M: x0 [  I. L// 资料收集整理:ccrun(老妖),欢迎光临C++Builder研究: http://www.ccrun.com
0 h; \; c- C' @  y& _$ T//---------------------------------------------------------------------------* \& g' n% @) r0 z
// ReadPhysicalDriveOnW9X_Ring0()
' `/ D7 R# a. d0 ]* \3 @; u//
" y7 m0 t4 q) F# V" k// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
* H& s$ V! y# z7 f// btMasterSlave = Master(0xA0) Or Slave(0xB0)7 ^9 p3 \$ k% Y3 H3 O) u1 S
//---------------------------------------------------------------------------* z+ o# |2 Z6 ~0 j9 s; z
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,% y$ N9 w' ~7 C# @7 X: M. ]& T
        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
5 Q- {: l1 w9 B' i6 ]/ M, |{
7 P, H- S% c8 y5 u    BYTE  btIDTR1[6];; [% Z+ z6 Z) |7 ]5 T' B: l) M
    DWORD dwOldExceptionHook;% i4 O1 C; h  j1 n3 J# U* l% n/ ?* H9 g8 r
    const int nHookExceptionNo = 5;
6 D+ P6 e- G: a& N% U6 W3 y( C. F8 G0 f( f- a$ b" W6 X
    BYTE  btIsIDEExist = 0;
+ u- c1 Q/ ^4 [  {    BYTE  btIsDiskExist = 0;) G1 Z. P; G8 @0 E! Q1 m
    WORD  wOutDataBuf[256];) O. B0 j5 L& O& A5 w+ f0 V
7 B: o4 h" n. I! k
    BYTE  btIsFirst = (BYTE)bIsFirst;
- K6 G, \3 a7 I6 w  g% ^$ p3 D7 S/ M" H( E* s$ e
    const BYTE btBit00 = 0x01;
+ \! x# t. J7 l+ }7 k    // const BYTE btBit02 = 0x04;% S5 A* X- e$ |+ Q: `% m) ]2 R
    const BYTE btBit06 = 0x40;3 x0 D1 W1 d; s4 m
    const BYTE btBit07 = 0x80;
+ H1 K" }6 p4 K9 g  h    // const BYTE btERR  = btBit00;
5 R4 o; H9 G& g+ Z3 \    const BYTE btBusy = btBit07;* y- S; i* ^" G( G- d* J1 N4 r
    const BYTE btAtaCmd   = 0xEC;
  \0 k, n; B  c' j+ b! Y% m# x    const BYTE btAtapiCmd = 0xA1;/ k0 R9 }9 X0 b6 j) g8 f
3 r2 V3 {8 j- F7 j6 C# `0 m
    __asm
  [9 H! ^! a6 S    {' ^4 _$ E4 ?1 n4 m, ]4 }$ n
        // 必须先执行这条语句$ S' b( K9 s) ?; R
        JMP EnterRing0
6 j; K, L6 ]- R# A& I4 ]6 ]/ ~
7 w. U9 w$ f% u0 B1 p4 ?        // 定义过程/ O1 d7 \- ?; ~* @# d
        // 等待IDE设备直到其不为忙为止
2 w4 g7 N7 W6 D  d8 `8 j        WaitWhileBusy proc, d) R8 t  A- W3 m$ L
7 E7 H: V9 ~7 b. |: r9 g# a
        MOV  EBX, 100000% |+ U0 c4 y5 L
        MOV  DX, dwBaseAddress6 g% Q( U5 C# a4 s- }6 {
        ADD  DX, 72 I) e6 c* M" S  `
- ~( W6 L  J" N) B5 [
        LoopWhileBusy:; ]2 a5 n( S9 d9 n" i7 l( E

9 ~* r3 O% l( F        DEC  EBX) Z4 o: u/ d% T0 s# K$ s- p( C
        CMP  EBX, 0- p& j% Q) }6 ^( f5 b
        JZ   Timeout
$ d- a* \0 D9 k$ o4 ?        in   AL, DX
* W, {7 C" G5 u  s        TEST AL, btBusy2 A4 C0 ^7 p8 m3 S$ ?
        JNZ  LoopWhileBusy) }4 N$ ?* c/ p0 G# V- P' ^  D
        JMP  DriveReady
- C' w4 b: E8 ~, ^9 D4 g3 v- [2 m8 N$ \8 X
        // 超时,直接退出0 F, M- m& }' h* p& P. L4 e8 _  ^
        Timeout:
$ `$ c/ Y# c9 A2 p5 u' C        JMP  LeaveRing03 Z% G, j+ J+ V9 V$ y; c* r
        DriveReady:
+ [7 ?* j& h2 t2 t* r* a        RET
/ C- R& u; v1 d6 Q; L, @: N8 E) ^        ENDP   // End of WaitWhileBusy Procedure  E+ p0 t" ^9 w3 G7 L" Z2 d

9 ^8 l6 L5 y, b. h7 _        // 设置主盘和从盘标志2 T# e4 X& j8 x# Z
        SelectDevice proc' K0 R2 ~% P, i7 d; b. E9 D' G

5 v2 E: C, d% N" N& p4 j        MOV  DX, dwBaseAddress& \" }$ O9 [9 W9 D5 ^& g
        ADD  DX, 63 B2 `1 `% Z* t1 }
        MOV  AL, btMasterSlave
2 D, j2 i  v: `9 {, i; U5 j, w/ G4 ?
+ }; @$ x1 A! r6 D) R9 h        out  DX, AL
4 u& m2 z8 I- O. c8 w        RET
# J1 N2 r2 |# s4 H$ `; G& g4 _  b$ S6 N, G
        ENDP  // End of SelectDevice Procedure% ~. V' v+ ^. C; `7 o* Y7 U0 }" R  |

" _7 W( ?7 N; d        // 向IDE设备发送存取指令
  t2 q3 I) s. I! b3 V        SendCmd proc
% k# Z- s/ v; G* l8 N
. E8 C( e+ o' {& Y- R8 h9 W* x, r        MOV DX, dwBaseAddress
! @  \. [, O) ?/ [2 N        ADD DX, 7
* m7 N9 o4 f* K2 Q        MOV AL, BL // BL是主从盘标识,在过程外设置2 m7 S# W$ U6 R. i7 q- T& `
        out DX, AL7 V( Z+ K: d* O
        RET1 p' i6 {3 T: u2 |$ f" f
        ENDP  // End of SendCmd Procedure
! l  V, Q6 i/ A. W' B1 K9 s6 V- X2 ?) L+ T1 p
        // Ring0代码
* v0 O2 E/ c  L6 P        Ring0Proc:
$ c$ @$ [0 o  b        PUSHAD
" w8 G' P7 c8 [        // 查询IDE设备是否存在  R6 t" A7 {% }# o1 r
        MOV DX, dwBaseAddress
9 Z. K* }3 l) T. {        ADD DX, 7, M# q) L0 [& |# ?
        in  AL,DX. M  U2 k: P3 O/ K0 O! j

7 ]! F- r5 }* k: Z9 z( h: a        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
3 i3 d* k8 P- A7 a: }0 _3 Z        CMP AL,0xFF
- V3 x: X$ o9 w2 Z. A        JZ  LeaveRing0
# x) y# F/ w# u  ]9 J        CMP AL, 0x7F8 Z. R/ c4 ]0 k9 h
        JZ  LeaveRing0
& R: b, i) v' C7 \/ \' N
5 o1 H; w: H/ N' s) e        // 设置IDE设备存在标志; c( ^3 K2 P2 I: i4 y
        MOV btIsIDEExist, 1
4 c5 L" n& i  z3 n7 s, [2 v: ?! H$ T; G* Y( C7 S
        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)2 C! _+ D) S* j" ]) F# j
        CALL WaitWhileBusy
5 m. b7 D: R# I9 Q9 p: t        CALL SelectDevice
, ~( R4 W2 o5 `0 t; r2 A# z% W) ]: K0 R1 Z! T) M
        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏. z# h. A; R$ _0 f5 C1 E
        CMP  btIsFirst, 12 m8 Q# O9 o+ I* x
        JZ   LeaveRing0
; m6 i$ ~$ @; U/ x+ g) o- ~3 H' T) }* H
        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???, m$ w, K; P0 ^' S
        CALL WaitWhileBusy  D" i- {& I% f% H
6 V$ p3 Y& b+ d3 ^8 K7 b. t
        // AL的值等于cBit06时,不存在驱动器,直接返回
% n0 Y" O" |9 s        TEST AL, btBit06% N3 X1 @8 n9 o$ Q7 r) f- p
        JZ   LeaveRing0
: y; h4 L0 n( ~4 ?6 d" E# N' d6 k* m- ~6 q# [; A! m9 z
        // 设置驱动器存在标志
+ X2 W9 I( Z5 @* o3 K        MOV  btIsDiskExist, 1
- M% s0 |5 T4 O! R4 r' b9 N) K# R% ?0 J7 S! \
        // 发送存取端口命令
& _* Q  T  G  s7 f; u; T. F7 O- T5 f        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,! d8 G( X5 t% O+ G" f7 I
        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
5 o6 i0 e% M  J  t8 P0 ~        CALL WaitWhileBusy1 r5 h# d: s7 Q5 k4 h- h/ E1 h
        CALL SelectDevice    // 设置主从盘标识2 b1 o: o# d& i
        MOV  BL, btAtaCmd      // 发送读取命令
, E( q: x* `* E+ x        CALL SendCmd
( p$ L; P0 X, n        CALL WaitWhileBusy; {! D4 `% z  ?4 g- G% X
6 _4 j3 P/ V6 `5 o1 x; e. m+ b
        // 检查是否出错& `: I0 l3 p7 u& Q- C4 X9 {) |
        MOV  DX, dwBaseAddress
# C) G3 m4 E! \1 G5 w+ P6 t' T        ADD  DX, 7  C4 H1 G! v; \
, f5 i) |5 F- {1 m
        in   AL, DX
* ^! P1 U3 t( B3 _
1 s6 O& ~3 M4 O, G( L& H4 i# d        TEST AL, btBit00& f* D1 G) F' z" I
        JZ   RetrieveInfo   // 没有错误时则读数据2 l: w& f7 w+ o, ^$ i- y% ]
4 j) ~7 y  h" w$ z, m
        // 如果出错,则进一步尝试使用ATAPI设备命令8 v. S1 k, _0 r+ r3 S
        CALL WaitWhileBusy! d) M4 C. t* _6 t# Z  o
        CALL SelectDevice
( d: M5 ]2 ^; i0 m% {  W# l        MOV  BL, btAtapiCmd+ O+ V: W$ |& I$ {4 T
        CALL SendCmd' l$ C9 _6 M* D7 ]3 }$ p, B. v
        CALL WaitWhileBusy6 m9 S# P$ j4 t# V8 H0 w
4 r; `3 J9 Z3 V* x: o9 ^, T1 N7 D7 Y
        // 检查是否还出错4 \$ c; z. M( e
        MOV  DX, dwBaseAddress
' ~* ?! q: c% K5 G$ t% V        ADD  DX, 7
, j4 ^# J4 ^2 [        in   AL, DX
9 s- X6 S0 t+ ?3 m, w/ }        TEST AL, btBit00
( w. S% r: A' v9 f1 M2 E! d        JZ   RetrieveInfo   // 没有错误时则读数据
. l0 `8 @5 V5 Z) V        JMP  LeaveRing0     // 如果还是出错,直接返回
  r$ W! x4 u7 h9 `1 i: |+ T/ N0 S$ B+ l; ~# W7 [! }2 d1 v
        // 读取数据3 Q8 z) m6 x4 C6 h, b9 F# j, P
        RetrieveInfo:
$ J9 v$ T( A( y& M7 P; Q+ O, A$ C5 F" e% U" g
        LEA  EDI, wOutDataBuf
3 x9 J/ U$ m+ H1 }& B5 N/ r, B# i8 U        MOV  ECX, 256: h. X8 d% o8 ]  b
        MOV  DX, dwBaseAddress
$ r7 h5 W" V" l; p) e$ [$ a        CLD
1 A5 l$ ?1 |$ j3 G( t% W0 Y$ ?
# B6 y6 T( C2 j/ c* |        REP  INSW
% t& K5 P2 ^) W9 i* \" y( }
$ Q7 l: L. _$ z  [  T        // 退出Ring0代码9 Q1 ?4 s0 ]) M; b) e6 Q( e
        LeaveRing0:
+ O5 v$ b6 r) V3 k  H+ W9 F5 q; n% f2 o
9 i4 L* `; G: X$ b5 v        POPAD
4 D4 _: i5 h' h        IRETD
: F% s8 T7 y+ l0 a: g' v  e3 f" H! H# k& ~! N2 f" N, ?
        // 激活Ring0代码
) r. }0 @* l: G- B! J        EnterRing0:$ I' R9 g& G) i

  {3 U6 W4 Q9 ]# z        // 修改中断门
+ E+ d1 R- g! z+ ?4 s+ w        SIDT FWORD PTR btIDTR1
3 Z$ [+ {' g8 x& g4 _        MOV EAX, DWORD PTR btIDTR1 + 02h, ]" D, Q3 n& a$ C
        ADD EAX, nHookExceptionNo * 08h + 04h& I1 [7 N0 G' N6 a
        CLI
( M: z" q% @9 o" e8 W6 z' k
* ]4 }$ j* H( i* H1 O" p8 o$ }! `        // 保存原异常处理例程入口0 H2 E. _/ w4 ^4 ?* ~
        MOV ECX, DWORD PTR [EAX]1 Q( X4 B# I6 @6 d. ]1 X+ d) j
        MOV CX, WORD PTR [EAX-04h]; J" ~5 S: R! ]0 A* ]/ D
        MOV dwOldExceptionHook, ECX( }* _% H" L& F% ^* }* G4 U4 {% B
: I2 _: y3 C  Y8 k2 _8 U, {1 K, o
        // 指定新入口
7 s( J9 u4 s0 G3 ^6 S$ {; Z% V        LEA EBX, Ring0Proc
: Q; Z  d# `- d4 L) Y        MOV WORD PTR [EAX-04h],BX1 N* j0 }  p/ L  l
        SHR EBX, 10h
% a4 M: X2 G; k' }% P" {        MOV WORD PTR[EAX+02h], BX
6 s' t7 T6 X! ~7 e. f# z
: R, f. m0 r1 [9 b0 [' y2 H6 {) p        // 激活Ring0代码
0 M; s2 s" M. J& `        INT nHookExceptionNo2 T: ]. A! ~& [9 U8 u2 }) ?$ h

% Q2 ?. ^3 h6 Y1 V3 U7 f) o        // 复原入口4 m" g' E4 ?( i
        MOV ECX,dwOldExceptionHook- E3 @/ v$ C, _! z
        MOV WORD PTR[EAX-04h], CX7 _; n- A- k, W8 Z6 v
        SHR ECX,10h
/ |+ J6 U1 H3 q7 \        MOV WORD PTR[EAX+02h], CX
9 F; ^4 _6 _* X        STI8 S$ f$ T, c8 o) b
    }
) `/ _' y; J8 `    if(!bIsFirst)2 e3 o% s2 @" M) b
    {, e1 @; p; v, H3 i4 r1 v
        bIsIDEExist  = (bool)btIsIDEExist;" e# y9 d. w2 B4 f5 J" I4 W, ]
        bIsDiskExist = (bool)btIsDiskExist;) ~$ W& L* @2 u" g- U5 R
        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));7 M' }5 J- a( v6 W9 d% K
    }
) Y) H# _" _& m: \& x. F$ _}
% }; R* |& c) a& E& Y* m//---------------------------------------------------------------------------
5 v) A# w# l1 b' D! ?' @- G// 调用方法:
6 f( J, Y% E0 b7 i$ @! o. M! O6 Tvoid __fastcall TForm1::Button1Click(TObject *Sender)
# u7 z9 l% T! \1 @{  o* M& H5 K4 t  E! ~+ G2 H
    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
: }) Q9 i2 o; h! y0 n8 m}
1 A, y4 A! _" r
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-8-13 22:46 , Processed in 0.018900 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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