找回密码
 注册
查看: 8016|回复: 1

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

[复制链接]
发表于 2008-1-6 19:59:06 | 显示全部楼层 |阅读模式
代码框架,你所要做的仅是修改WQL语句,具体可看MSDN。以下代码为简介起见,一次返回所有的CPUID或硬盘厂商系列号/ M4 J5 |  j1 L1 K" x7 D
  1. ' H: Y1 Z3 y9 l# ?9 _; o
  2. #include "StdAfx.h"4 J0 v9 r/ P7 B! {
  3. #include ".\puiddisk.h"
    - X5 P. J  n) }% J" I
  4. #define _WIN32_DCOM  M/ U' k. n/ n& y" u" `+ A
  5. #include <iostream>$ P* [" V' F! P* T% z1 J
  6. using namespace std;
    ' Q) y  v& A% l# d
  7. #include <comdef.h>1 [9 U8 u- G% N. @
  8. #include <Wbemidl.h>$ W0 t+ R/ L7 F8 K# Z$ h, g

  9. 8 K7 }' w# r8 X5 ^/ W9 f/ \4 E* X% M
  10. # pragma comment(lib, "wbemuuid.lib")
    6 W% w9 D7 n0 Z; Q$ m1 g
  11. CpuIDDisk::CpuIDDisk(void)( n& A! q9 _; Q# O7 |
  12. {
    7 R2 w( n2 r0 j# r
  13.     GetInfomation();: ]  N8 p8 t6 r' n  i$ N/ m
  14. }- l, i8 _/ S: V5 l

  15. # C" S5 w' I! ^5 J) @; a
  16. CpuIDDisk::~CpuIDDisk(void)' F3 M+ c; F0 v$ z* Y
  17. {
    & c, |" f8 a. F. C1 g) M
  18. }' `0 o* |, z) K# ]) X5 ~9 d
  19. int CpuIDDisk::GetInfomation(void)
    : Q" w6 h, \5 R/ L. I
  20. {( A2 Z, Y- {5 F8 N1 F; [8 ^/ G
  21.     HRESULT hres;
    / \- b! E* L% u7 Y$ |7 J
  22.     //步骤1:不是必须的,COM只须也只能初始化一次, V5 O" v, }+ l* D1 s- M
  23.      hres =  CoInitializeEx(0, COINIT_MULTITHREADED );
    ( C, `  H  g: P# d3 M0 g
  24.     if (FAILED(hres))
    - \* r, x8 ^, Y
  25.     {  i' c3 d" h$ b$ W0 ?% T2 S- J1 _
  26.         return 1; //初始化COM异常:注意,COM只须也只能初始化一次
    + c6 v' `: I0 D8 j" r0 b; T+ G: Z
  27.     }
    % ?9 X: |9 k) @" @/ b7 a. q% I
  28.     //步骤2:不是必须的,COM只须也只能设置一次$ {* d0 _9 B. i" o/ w" j1 Z
  29.     //Set general COM security levels. P8 ]  u! n4 L/ s# g; u
  30.     hres =  CoInitializeSecurity(& ]4 s! `+ h- U) [) q
  31.         NULL,
    0 `2 v1 v; m4 s; {4 H$ |4 ?
  32.         -1,                          // COM authentication1 ~' Y& q0 O" u3 ^' \$ b7 y
  33.         NULL,                        // Authentication services8 i5 E7 v. S; @; W: F: E1 v5 j
  34.         NULL,                        // Reserved7 u7 L; R2 ^6 O$ E! _- K) r; F
  35.         RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication 1 @: F, r! ?7 |0 j( u: M5 w
  36.         RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  
    2 Z) ~8 k! j, T
  37.         NULL,                        // Authentication info
    ' P8 l& U0 F0 r; [" ]
  38.         EOAC_NONE,                   // Additional capabilities # ?6 U; X) J# T& F
  39.         NULL                         // Reserved5 V/ _5 z2 O/ f- `8 P
  40.         );& U+ R4 x" t+ |2 a& x
  41.                       4 g2 U% d! }# q  B6 p* b
  42.     if (FAILED(hres))) l# s7 I& Q$ ]7 d  q7 d7 D
  43.     {
    . y( W4 q7 e2 C' k* i9 P# P. J- L
  44.         CoUninitialize();4 j" X' ?* \) z; n. y/ m6 r
  45.         return 1;                    // Program has failed.8 k1 x4 i+ }9 F5 W* R1 V/ v
  46.     }
    4 ^# G% `7 ^+ ]) x8 Q% o+ }
  47.     : d; i: m8 d& p4 Y$ f1 P6 R& _
  48.     //以上不是必须的,若已有“::COMInit();”,则要跳过
    ; ^. a0 _0 z6 z( u' h/ h8 y
  49.     //步骤3: Obtain the initial locator to WMI
    # c6 ^1 K5 l% ^; f% N3 C1 U+ l
  50.     IWbemLocator *pLoc = NULL;6 }- T: Z0 Z  D
  51.     hres = CoCreateInstance(# o* R5 {$ h3 |6 V
  52.         CLSID_WbemLocator,            
    2 Y8 b$ U$ k1 S2 g4 ?7 m
  53.         0, ( i7 ?/ A% `5 o/ z
  54.         CLSCTX_INPROC_SERVER, # O% O% _4 v# b7 F! l2 a
  55.         IID_IWbemLocator, (LPVOID *) &pLoc);
    6 P3 u4 A) J9 Q
  56.   ^- `) Y. T  \  B2 l
  57.     if (FAILED(hres))
    ( x' H/ o" s& ?0 Y' w* c
  58.     {
    ( J! F8 j' Q/ b* K! d
  59.         CoUninitialize();* e6 k; T+ H7 w
  60.         return 1;//Failed to create IWbemLocator object! S$ l6 x8 \+ R+ j
  61.     }9 W% N5 x' c7 z  E  O6 t/ a
  62. 6 R/ e( p, e$ f% d% A9 t2 U) W
  63.     //步骤4:Connect to WMI through the IWbemLocator::ConnectServer method$ z# M, E# \( e/ S! L
  64.     IWbemServices *pSvc = NULL;0 }1 ]4 q! x! x- o5 p5 x5 o# f+ e
  65.     hres = pLoc->ConnectServer(- @' f( P, j, Q+ L
  66.          _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace1 P- |8 q2 l  h# e# @) P2 Y
  67.          NULL,                    // User name. NULL = current user
    $ ~0 z" \4 B6 ?* V% n  f& |2 {
  68.          NULL,                    // User password. NULL = current6 l' I8 a) S1 M' b. g/ U9 U" Q. ~
  69.          0,                       // Locale. NULL indicates current
    2 w$ y/ z9 y* [! e: t; a: A
  70.          NULL,                    // Security flags., `* \6 v* r2 F4 M" Z7 M- e5 h
  71.          0,                       // Authority (e.g. Kerberos)) [/ M, e. j9 X5 o
  72.          0,                       // Context object , O# t7 V) h1 g
  73.          &pSvc                    // pointer to IWbemServices proxy
    / L+ ^+ p6 {- x) w& s6 U; n
  74.          );( g# m5 \/ }! n# I( y3 y
  75.     : n- a! @7 `( ~% [$ D( q
  76.     if (FAILED(hres))
    ) E8 k5 y/ i5 o5 {3 d
  77.     {# |" v, H: C5 P/ D7 n* a# r
  78.         pLoc->Release();     0 I* W7 {  @. m" I$ T! T, t% c# N
  79.         CoUninitialize();, ^* D; x" E/ \, S! j  X
  80.         return 1;                // Program has failed.4 B# Y, m$ [5 v
  81.     }; v( V7 w9 \+ [/ R
  82.     // 步骤5: Set security levels on the proxy
    0 M0 _- L0 H+ u9 y
  83.     hres = CoSetProxyBlanket(
    2 B3 J. S1 E+ Z5 @7 J' Y% z- i6 u
  84.        pSvc,                        // Indicates the proxy to set9 R0 s/ K- B, j4 d% P- c+ p' T
  85.        RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx
    : ]3 s5 w5 b8 f7 r
  86.        RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx
    0 W' m" y$ P$ }" @2 S
  87.        NULL,                        // Server principal name 8 a7 E% v" O7 f: B% M0 A' ?# H
  88.        RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx
    ) e8 n/ s4 S" G
  89.        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx/ O5 Y4 B- s" j9 L- G
  90.        NULL,                        // client identity" u! G) J! x, z( b! V& E
  91.        EOAC_NONE                    // proxy capabilities
    6 ^" R) Q; j: d% h; t, m! F0 ~
  92.     );! F$ A. f9 S  m

  93. % j) g" k5 s( _! d2 j3 j' h& H+ {
  94.     if (FAILED(hres))  b& c: ^1 G) s. p- F. o! e& r" l
  95.     {" k  }+ q; }3 X9 i  T# X# ^3 v+ N8 |
  96.         pSvc->Release();
    * J2 V9 q: y/ B/ s9 d3 C1 d
  97.         pLoc->Release();     
    # z  i. c1 }/ j* M6 C% r1 q: [
  98.         CoUninitialize();
    , L- U" H4 r# d+ @: d4 o
  99.         return 1; - N6 l  o6 [$ U" e. |7 K
  100.     }
    5 g2 x) G  Y2 J) X! F
  101. $ x; ^1 ]9 X+ }  R8 ~- P" p. E
  102.     // 步骤6:Use the IWbemServices pointer to make requests of WMI ----
    6 f) x/ C  o/ y4 i, e1 ~% Y
  103.     IEnumWbemClassObject* pEnumerator = NULL;/ [- B0 j/ h4 v* d" l% e4 y
  104.     //计算CPUID! w7 `9 u2 ~* c/ L- R
  105.     hres = pSvc->ExecQuery(" F: w3 Q2 n# I, f- n3 `! z! D
  106.         bstr_t("WQL"),
    2 {8 |( P( d" b
  107.         bstr_t("SELECT * FROM Win32_Processor"),//Win32_OperatingSystem5 g) ?8 |1 ~% M) F; {1 E
  108.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, : E( C. U' D0 r
  109.         NULL,  |( w9 D2 b. Y$ [+ F: T' z
  110.         &pEnumerator);
    ) T! w( R1 c+ u7 r* R0 [) h
  111.    
    1 j5 a$ U  V) o0 }$ d) T. j
  112.     if (FAILED(hres))+ O) c8 h' s0 t' r2 @  A3 l
  113.     {3 a$ A4 A; N  u- ^* \( o' B% ?  N+ C" d" k
  114.         pSvc->Release();
    % [1 b, N6 F7 w' _3 u" f. F. L
  115.         pLoc->Release();
    1 B- u1 V; `) \# p& b% U
  116.         CoUninitialize();& l. |7 G" a2 o+ a- }8 x
  117.         return 1;
    - j* J- ^2 Q% E' l% B# m
  118.     }
    : t' K3 t  ^% E1 _- F+ N! B* ]
  119.     // 步骤7:Get the data from the query 3 ~" F9 n+ ~( G+ \% r: l, v5 w
  120.     IWbemClassObject *pclsObj;
    * B' x$ n$ e4 O0 l2 \' U7 j
  121.     ULONG uReturn = 0;
    $ s: D9 F; g' h' a+ s" Z5 F
  122.     while (pEnumerator)( k7 l+ C9 u: n! h
  123.     {1 m3 O. u* P) W' `5 v
  124.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, ; l4 v4 r! W, h5 s6 w
  125.             &pclsObj, &uReturn);
    % u7 e$ a* h) ~3 t9 o

  126. & P8 N8 x( j- F% l
  127.         if(0 == uReturn)
    + c, F. ~. V5 ^: n9 i6 m
  128.         {  x% i2 ]+ B2 p% S4 ]
  129.             break;
    3 K  N0 [9 R% Z- `# ~/ x" u/ \
  130.         }0 ?9 `& D+ Q, _# E3 }# ]; w' D
  131.         VARIANT vtProp;
    3 Y- k3 s4 w, b
  132.         VariantInit(&vtProp);2 V3 N! L+ v- I( x2 p
  133.         hr = pclsObj->Get(L"ProcessorId", 0, &vtProp, 0, 0);
    : D7 N8 k9 [5 H5 P: |
  134.         strProcessID=_com_util::ConvertBSTRToString(vtProp.bstrVal);//strProcessID:类级变量! w$ C: u1 K1 p5 E# G  p7 p
  135.     }
    4 U5 |6 g$ t( {/ s
  136. ! i  q7 e* Z8 b8 {( [( A
  137.     //计算硬盘系列号
    1 k4 C8 s( a  J5 R, r, t
  138.     hres = pSvc->ExecQuery(
    . \% b! x+ ~* _  F: s. m0 [5 f- f
  139.         bstr_t("WQL"), $ `6 s- [1 K! o# P, s% a
  140.         bstr_t("SELECT * FROM Win32_DiskDrive"),, Y( Z4 Q) g) j' T( f1 w- q7 ]
  141.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
    8 z4 k- S: a0 d4 v4 c6 |7 l9 x1 L
  142.         NULL,
    0 k5 C$ V( g8 h* r, m3 O0 p
  143.         &pEnumerator);
    # w; p6 c; P% K" t& s+ {7 T
  144. , ^9 C+ }' O: _( U2 v2 Z+ n
  145.     if (FAILED(hres))
    9 [9 h  B4 @' r! M- @( O" h
  146.     {5 Q  A$ e" m) o' p
  147.         pSvc->Release();
    0 I0 O3 A8 I5 ^2 j! o
  148.         pLoc->Release();6 g. _: ?9 Y7 H3 w
  149.         CoUninitialize();) n! N& t2 |& p5 i  k; K3 ?
  150.         return 1; 9 n1 b7 g. k* I+ [* S3 v7 {
  151.     }  U; G, D" M5 u; U  N
  152.     while (pEnumerator)- E2 Y+ ~  V4 W
  153.     {3 s0 O: W2 s# H- q2 f( D; _$ p
  154.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
    8 q6 o, ~7 L5 R* a3 s' K7 }
  155.             &pclsObj, &uReturn);
    2 _# V; z& [8 z( A  i7 |

  156. ( t8 ^0 T- \0 @
  157.         if(0 == uReturn)+ l0 p/ `4 X% Z- r# q
  158.         {
    ; @; R' m- E' C) O5 F$ _, E* J
  159.             break;. u5 T9 C/ `# o* ?
  160.         }
    1 [7 B/ O4 ?& C* H

  161. 2 t. F* K0 k7 Y- C
  162.         VARIANT vtProp;" J+ q% I" F2 t$ i9 w6 M7 J/ c
  163.         VariantInit(&vtProp);8 n6 j) E# ]3 i6 a8 A+ Q
  164.         hr = pclsObj->Get(L"PNPDeviceID", 0, &vtProp, 0, 0);
    $ h! `# I4 Q- E9 b3 [- R
  165.     strDisk=_com_util::ConvertBSTRToString(vtProp.bstrVal);
    - r, S* B7 i/ k; P: u# @! m2 u4 k
  166.     }" Y7 j, D1 l  {0 @4 E! U
  167. + s' i4 m# s9 a- [- F/ c" Q# g* [
  168.     pSvc->Release();: d0 L: Z( k! D- _8 C' g& e) o+ S
  169.     pLoc->Release();
    4 _5 g+ ~+ L1 T6 X% \  |- J
  170.     pEnumerator->Release();6 A2 N! F1 y% c* h
  171.     pclsObj->Release();
    1 T- P+ t& _2 w- z/ j
  172.     CoUninitialize();" K+ \. {0 t. X2 K' @4 Q4 E: p

  173. % [8 ?, ^3 g, Z
  174.     return 0;   
    ' {, |7 M9 Y4 b; m2 Z* ]
  175. }4 t* O& N  D( G) r& G$ I
复制代码
 楼主| 发表于 2010-10-11 19:21:05 | 显示全部楼层
本文代码经ccrun(老妖)在Win2k下试验成功.+ N2 v# d2 v! Q

, t# E& P6 J; Y9 V* E#include <WinIOCtl.h>, G- w; G9 w6 G
#include <stdio.h>
% l3 R3 m  z& o8 m4 ^  W2 N3 f
. ~+ ~5 e( p$ @6 Z9 K% v#pragma inline- w3 ?) a- u# O) e; L1 X" q* |
//---------------------------------------------------------------------------& W  Q% G$ W* g+ W% g
// IDE NT/2000/XP专用变量4 k8 E3 c2 I1 q( a" T
#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
  @6 e* W8 T- C" R#define DFP_GET_VERSION         SMART_GET_VERSION8 z; n  I# B* X& y
#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
  z4 {8 `+ g+ B3 l, x+ Y#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA  r3 G0 G* i9 W+ R" n

& m1 N, s& O6 s, }" Z" Fconst WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令
# T) x# a( W  f2 f- O8 pconst WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令1 Q* W! n: O: m

: ?/ Z( z) c- A0 R* `const int MAX_IDE_DRIVES = 4;
& M& k7 ^1 W+ c* S8 ]5 @* [
/ h* w' ^# \2 u1 q& M0 {/ Q// SCSI专用变量
8 p9 z, G1 q3 ]) A; Sconst DWORD FILE_DEVICE_SCSI             = 0x0000001B;
" z) \" U5 r* f/ sconst DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);, Q9 l" L% M+ s
const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition. w8 T  l- |; a% F' y- a
const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
% H5 z- f/ a3 L
: _) E5 n+ |8 F2 L/ ytypedef struct _SRB_IO_CONTROL! C5 s+ D4 F( l' S  a+ D9 u
{
  x/ l/ ]6 c8 t* c5 v    ULONG HeaderLength;8 a: D- k8 c) O" _& Z
    UCHAR Signature[8];" y( Z, K8 s$ G5 x1 j; C" T/ \/ U
    ULONG Timeout;
3 x, D; g( L. ~6 b1 m) J+ e: y    ULONG ControlCode;
; g* D* b$ B+ f& h* j8 ]    ULONG ReturnCode;
' C# @2 S6 ~# R/ y: ^    ULONG Length;
( i0 g/ r) Y6 o- l* m( _}SRB_IO_CONTROL, *PSRB_IO_CONTROL;
+ Z# c3 d0 \1 t/ L6 |: t  }% r# p( E) X9 K9 h9 s  O$ G7 j/ a
// 读取的主函数
0 i9 p0 t% z/ z* pvoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);/ J5 P) N6 Q+ j5 ~1 A- K. n" l
( V. S7 o; v% i, U! ^* n
// 辅助函数
" C! g$ W! \7 C& {: |& @: Pchar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
$ R5 D& ?0 o3 U) O( i7 K// NT/2000/XP函数
) m8 {( s2 l2 b  [4 W* U8 \' gvoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
+ w+ w# z3 `0 h* [( y' Bbool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,* c' J: z# a2 b. Z8 e
        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,5 K  x* O  ^6 i# j! ?9 l6 n2 j
        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
# b) s; E7 _" H! Q4 |// Windows 9X函数
7 U, M4 X" ~& t( S  V4 q0 zvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);5 H3 g; G6 o8 H, Y" I. @
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,! Q" p! M. S6 X- |2 D
        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);: u7 l* w, k  z# x% }, D; }& N
8 n5 w/ ]8 Z5 i+ G
// SCSI读取函数(for NT/2000/XP)
$ b! d5 E5 W  rString __fastcall ReadIDEDriveAsScsiDriveOnNT();
: x  V8 S5 D8 W" i$ z//---------------------------------------------------------------------------8 p% {# X9 t; O' J! V
// ReadPhysicalDrive
$ u9 ^5 ^5 Y) r9 u  e- }void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
7 n! u( U3 Z+ G# R: f5 @, o{
6 G2 N: v# l4 x9 t    switch(Win32Platform); D0 k; S: ?  o
    {3 I$ O* a8 a4 ?0 u
        case VER_PLATFORM_WIN32_WINDOWS:4 p9 x8 g' m. x& J2 l  e6 S, C
            ReadPhysicalDriveOnW9X(pSerList, pModeList);6 F& D0 p6 f; f5 Y
            break;6 M/ O: e: V- T- f
        case VER_PLATFORM_WIN32_NT:
& F3 O9 f7 v  _& G            ReadPhysicalDriveOnNT(pSerList, pModeList);
2 A& J" x; Y9 H5 T# D, w            break;
1 \) `$ T* p2 B1 ]- q5 O        default:: O+ h+ Z# p. o. W
            break;
! d' c9 y7 r/ ^+ W    }
4 t9 h# u7 j8 A9 ~}
# W9 O( F/ ]. C( b" h; N5 e//---------------------------------------------------------------------------
2 |, M; \2 k7 H6 N// ConvertToString3 i2 R# P# M5 d  x
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex). ~1 D# f! \4 X6 X
{6 X  W( j* u. C$ S
    static char szResBuf[1024];. E* z5 x6 ]9 q/ Y3 \
    int nIndex = 0;& [/ G, Z3 e2 q1 T4 Z/ G1 m. g
    int nPosition = 0;
: o9 b+ r" m% i( |) D+ e
6 C9 K# p$ \) K    // Each integer has two characters stored in it backwards
8 o  D# v4 ?! C* y    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
5 K1 I1 A: W0 y% R$ {* n    {
4 Q- y& _" P. r7 M        // Get high BYTE for 1st character( y$ n, D# K2 t1 h" H5 i
        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
1 R" e4 ^' M, D, m0 |1 E( q  [        nPosition++;# p' i* C3 h& i0 M& J/ `: E0 P0 i

$ u$ c2 z4 m* g" t        // Get low BYTE for 2nd character2 t( _% O1 _0 y
        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);! o. O# ?6 x4 E' }% ?2 e
        nPosition++;# g; C3 E' t0 c+ f( C. n
    }
  T! H5 G* W1 K2 G* l( d& M* \* e
    // End the string
: d4 g: z7 e) Z- z$ i5 L# T. N    szResBuf[nPosition] = '\0';  {6 F$ O' _7 i5 H) w2 c, R, D
- M; k& S. g) a" n" C: [5 b
    // Cut off the trailing blanks" c9 B& A1 s2 i0 }% c( u' m) f0 g
    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--); Z; s. l) v0 P0 ]. W) \
        szResBuf[nIndex] = '\0';) z7 ^0 O6 G, g0 ?

" T  Y: A; V* y6 |' |    return szResBuf;
( G+ N. O1 u2 g}$ [2 L" E6 k! ~) Z
//---------------------------------------------------------------------------$ _- Y# }- E; W0 M: [. @: N
// Winndows NT4/2000/XP 代码
" r( \! L/ y7 ]6 S//---------------------------------------------------------------------------. R  s& {6 j& ^. T+ f
// ReadPhysicalDriveOnNT- s* f; l: O1 ~: u+ x. k) j: g8 I; ^
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
7 ~1 A' {5 m/ ?* q$ F{
  {3 ^# x  O. R8 Z) l1 L    // 输出参数
: |; k( X- \; t5 F5 {- A/ l' n    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];$ j/ D  R" l7 Z. }. {5 e, o

# P2 y" S, h- t% w- _% o! y' ?    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++): x8 ^# e, W" B8 r
    {/ j4 e. X6 ?% x3 x& `
        HANDLE hPhysicalDriveIOCTL;% Z% S7 [2 Q+ W  A7 T7 W' K
        char szDriveName[32];, G6 V3 L6 K6 H

. W1 O1 i3 Z+ P; a3 L: u        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);" v  G6 n- Q) u6 ?$ Z' X% Y
        hPhysicalDriveIOCTL = CreateFile(szDriveName,: l8 a' U* C. j# u
                        GENERIC_READ | GENERIC_WRITE,
6 V( |5 X/ e" V$ O                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
. ^5 U1 p& d$ g5 O  G% E' _$ [8 T                        OPEN_EXISTING, 0, NULL);6 r) ~2 c2 K, x% ~* X
  ]. M2 j* l/ f8 R5 t& h6 l) A
        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
4 |; m$ ?& H" w( N2 E" k( q        {
( M' e+ J, h; j8 e) i. `            DWORD dwBytesReturned = 0;" w' W# t) I  e5 Z+ @
            GETVERSIONOUTPARAMS gvopVersionParams;
( R( ~8 v' ~% D' e) U
- F) m+ D3 g7 P# y( z/ f            // Get the version, etc of PhysicalDrive IOCTL
: L, ?& Y2 I( h) ]. R6 I0 B            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
  I! W+ y$ n* k" U
- r# Q, o" V5 l2 X1 t1 X3 y, Z            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,3 s% M5 v$ H! b" u) B/ ]
                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
3 P& w' p* p! C% R# U# }1 _                    &dwBytesReturned, NULL))
" h/ C. q- j( O& k            {4 e$ z, _- a% k$ N! c6 z5 G
                continue;
, N! W6 u* ?& }, p7 w$ x            }
+ P: `# D4 n% C8 D/ H" n' K& y. B4 g$ N% C5 L9 d
            if(gvopVersionParams.bIDEDeviceMap > 0)
  D) f+ g  W. W* m6 P  b            {
% Q) o! U# Z( _' a9 M3 I( T( k                // IDE or ATAPI IDENTIFY cmd
7 X  Y/ E% m  j  \' H                BYTE btIDCmd = 0;
) S& Q2 l1 E. u; v* T" k7 a" ^                SENDCMDINPARAMS InParams;
1 l' K# U) E. G8 V; B; `. y                // Now, get the ID sector for all IDE devices in the system.- E+ w; Z9 r7 h* l+ O$ P3 \, R
                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,8 ?, k9 C' _/ w+ R2 l% ^' o) }8 c, b
                // otherwise use the IDE_ATA_IDENTIFY command
% d3 I0 k- A: n5 S                // 具体所得结果请参考头文件中的说明# O  Y/ M0 G+ r$ j/ Q( C
                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?, U8 }; G5 L3 }1 S% k' \
                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
8 h  n( _0 q2 z9 k5 W' r7 U                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
  w3 k2 D. |* m- {6 d9 S) q8 m/ D                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));$ V1 y- `! O3 a3 y' ~1 @0 \
3 ]. m7 x: |% h8 \$ y) e
                if(DoIdentify(hPhysicalDriveIOCTL,
. a( S8 S% b4 [  m; Y2 j                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,8 n$ l# [- n4 o6 W
                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))( p1 |" n* s0 x& @8 z
                {
5 ^3 r' \# g2 i( d/ l5 W                    DWORD dwDiskData[256];
/ _: R2 X( u" }" r9 A0 M  T: ?                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
( o. z2 Z& n$ R& k: @0 c$ Q                    char szSerialNumber[21];
$ ^! e& u' Q) _7 j6 s                    char szModelNumber[41];
" K# R$ B% Y/ V. M$ v8 L4 p. X' i( q7 H7 }; ~
                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;8 r! s6 s  E2 O0 W5 R+ o1 |
                    for(int i=0; i < 256; i++)) D# ~) P4 `" d5 p. h. ?
                        dwDiskData[i] = pIDSector[i];
- |, z; w5 n/ v5 V$ E" a                    // 取系列号
7 F" o1 x0 J" k0 n! c% B: n                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));5 A0 W! y3 ^2 H. N8 C/ J0 t
                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));+ w5 V0 Y! d6 d! s4 _

, {4 `# _5 O0 z7 Z7 r                    // 取模型号
4 m, }6 f& O/ s' E1 a2 W* x3 q* f1 I                    ZeroMemory(szModelNumber, sizeof(szModelNumber));
3 a7 ?8 k+ y, J: V7 V                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
# ]* l! o! O1 T$ n4 g1 ]
) H6 m% I- @% r2 K6 `$ n6 y1 W6 q                    pSerList->Add(szSerialNumber);
, L$ |( M$ h. u9 c0 o/ H; q                    pModeList->Add(szModelNumber);0 W  u3 L% N9 r" O. ^
                }
) Y6 U- z- E4 L2 b* k) W1 Z7 n            }
  a* t# B# C* s7 E& e            CloseHandle (hPhysicalDriveIOCTL);: C( f" g- x. }0 N+ m' D; [
        }( n) i4 i! v, a% \/ \
    }
2 Q, |2 k" ]2 T& |/ U8 k& V}, |% a2 ]# F  L/ y/ ]
//---------------------------------------------------------------------------1 \0 `! Z: K: `1 i
// DoIdentify
& e  K" H: w1 |: @+ l3 lbool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,9 ~. h# X% P, n
              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
" u' p. i7 d. `( C: t+ E# ^& I              PDWORD pdwBytesReturned)
" P( T: y  j0 K( w( M3 f{2 S  l6 ~2 ]# ?
    // Set up data structures for IDENTIFY command.# k+ s  e% O" {$ ^* x
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
% t* t2 F6 `% X3 e# d% g    pSCIP->irDriveRegs.bFeaturesReg = 0;
8 l8 S8 v; y" a: e    pSCIP->irDriveRegs.bSectorCountReg  = 1;! w% ^6 X- S6 a; G
    pSCIP->irDriveRegs.bSectorNumberReg = 1;2 {) P, W0 K$ V( N+ }
    pSCIP->irDriveRegs.bCylLowReg  = 0;5 f. o2 f1 y9 k0 i: M+ @: m
    pSCIP->irDriveRegs.bCylHighReg = 0;
6 l7 P* j, T+ y" }, t% s
5 a! `% x& S; [    // Compute the drive number.(主盘和从盘所对应的值是不一样的)
) t; z2 b% L/ w/ D5 @8 \2 v: }    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;. b+ n! S4 a/ [, G& `( q  C

1 |7 Y3 ?3 d( D8 A    // The command can either be IDE identify or ATAPI identify.
6 h# D. ^& s  O7 J0 T    pSCIP->irDriveRegs.bCommandReg = btIDCmd;' @& O9 {2 p9 G/ h( {
    pSCIP->bDriveNumber = btDriveNum;2 Y9 ]- }* I! }# I
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;- W+ n+ z4 [+ n5 n3 ]

4 ]' t/ |4 B( @1 P    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
$ l) r# p, N( h9 ^           (LPVOID)pSCIP,
+ h+ |) g0 h7 }3 J: J           sizeof(SENDCMDINPARAMS) - 1,: a" Q/ H0 v! Y  }9 L7 r: @+ N
           (LPVOID)pSCOP,
% J7 M" W6 F8 W- U% |6 `           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
! c: D2 B2 p- h3 f1 }1 p           pdwBytesReturned, NULL);
, m0 C+ L2 [, c2 Y  h5 J4 Y}* @/ V" ~& c( a, \+ f
//---------------------------------------------------------------------------! o. \  d( c. K% a  c
// Windows 95/98/ME 代码, j/ w( w4 D! P) K. W! W
//---------------------------------------------------------------------------, X! i: \4 S9 X0 G& V
// ReadPhysicalDriveOnW9X
7 q+ v- H# [2 I, K1 O: d2 r! j; @void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)2 ]* y5 ]( ]5 ^2 `6 W: ~" q5 ]
{
7 j2 R* t! G; K8 _$ K) n! U% u    WORD wOutData[256];
7 i1 I2 ]) U/ H0 ~" a# l    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);3 c7 X# I2 {" c+ [
: {9 g1 j  _& Y" X% M. ]6 z3 H& M5 x
    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。/ C% P7 P6 U3 o: P; m
    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以. H( Z+ Y" U4 j3 Q: L. X7 z
    // 避免蓝屏的出现。(期待高人能指出原因)$ f3 i* ~7 v! B8 m, {# m$ o
    for(int nDrive = 0; nDrive < 8; nDrive++); |7 J/ W$ _1 o' T) }
    {/ ?+ S. \9 m* D% E7 K: B
        WORD dwBaseAddress;& T# C  e& x8 f
        BYTE btMasterSlave;         // Master Or Slave8 k/ B% o! F1 Q/ q. V
        bool bIsIDEExist;2 Q& L0 j1 `8 a- O) ?- }
        bool IsDiskExist;
7 x  W: \% z. w3 q% ~* n
8 t+ P, `* n6 O4 I& e        switch(nDrive / 2)2 F+ G8 M: @3 ?) v3 T; p
        {# M. K$ y9 F$ }* V" x
            case 0: dwBaseAddress = 0x01F0; break;
. r6 O: l" Y! O5 G            case 1: dwBaseAddress = 0x0170; break;2 H$ y8 i, ~' C7 j
            case 2: dwBaseAddress = 0x01E8; break;- k, p. D0 }/ E/ q. \
            case 3: dwBaseAddress = 0x0168; break;
9 A+ y0 k+ R  w        }+ ?& D5 F! f6 V! F- m# J- F( e
) q* c* V- Z) d: c; p/ L1 C
        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
$ }: R9 a* O- X" E
  j2 B8 u8 ^0 f% x' ?        // 进入Ring0
8 ~( W; F( h4 N  T        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,2 |7 m: k+ b5 d; \3 O
                bIsIDEExist, IsDiskExist, wOutData);
' y4 C- S4 a6 N4 X) T    }
5 g! ?% N1 P3 \  H9 i% x6 C* [3 q1 x. ?; d, V  `9 _% Z7 w) c* ~
    // 开始读取4 \% D% g6 V4 l8 N/ K1 U4 W  l! f
    for(int nDrive = 0; nDrive < 8; nDrive++)7 C: h: Y/ f' E! z3 F! ?$ [9 Q
    {' E) a4 a7 r9 V5 h8 N3 C
        WORD dwBaseAddress;1 h$ ]. O; ^8 \  i3 S  r9 y
        BYTE btMasterSlave;         // Master Or Slave. x( f- C2 L" y$ \
        bool bIsIDEExist;7 y5 R1 L1 n0 b" K/ [3 K5 I( S
        bool bIsDiskExist;$ b; P8 `# ^3 h: u' `
        switch(nDrive / 2)! Y; a( C2 c2 y, V+ g/ _) M
        {
, |8 {# u6 L2 w' T" I9 A            case 0: dwBaseAddress = 0x01F0; break;  _- q; N! Z' a, F9 Q; @* j: I
            case 1: dwBaseAddress = 0x0170; break;
5 O1 L$ i4 _# ]8 A! j. h0 P            case 2: dwBaseAddress = 0x01E8; break;6 o; q1 H, z7 v0 S3 F
            case 3: dwBaseAddress = 0x0168; break;; I0 s7 t6 L7 U! j
        }
- ~) F3 D) i8 `0 {6 N( K5 n. T! Q$ l, `
        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);1 _. f" i& N' `

3 ?! f$ U3 E3 f1 I        // 进入Ring0+ A1 \8 B8 O" f
        bIsIDEExist  = false;+ t# x+ h( i" ~5 d  \! c! l
        bIsDiskExist = false;' U- X0 m' W  l% E5 q. W
        ZeroMemory(wOutData, sizeof(wOutData));
. c5 x6 C% S# P! T9 T( p8 t9 V- [, t1 J* e; M
        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,$ y% a7 f1 {8 w6 c
                bIsIDEExist, bIsDiskExist, wOutData);
% }; h0 E  J( H3 J1 W6 H. S& I
: ]7 |, e# q; i; j6 R        if(bIsIDEExist && bIsDiskExist)0 P; H) s( B: e- e
        {
+ R5 F1 e/ Y1 j8 O8 ~7 ]            DWORD dwDiskData[256];
3 K! {2 j4 y6 u4 g            char  szSerialNumber[21];8 C0 z4 L3 Y8 ^* r
            char  szModelNumber[41];# [2 f( P3 }5 U2 d0 `/ |& s

  R' e' t% {: J            for(int k=0; k < 256; k++)( a3 N! v3 ]( n5 X2 z$ K
                dwDiskData[k] = wOutData[k];/ N+ I0 W. a' o# A+ \0 E5 X9 `
' d; r: o8 _- J0 M- E% t8 n
            // 取系列号: w7 F8 F3 P0 m) M; d% Z
            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
2 }* L" A1 E$ w  n3 j            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));' x- M' p" `: S$ K3 n4 B1 L
! b8 e6 H, S" Q, Z
            // 取模型号: U0 B; U; G5 ^: U6 i
            ZeroMemory(szModelNumber, sizeof(szModelNumber));
$ k/ q1 f; j% T+ F4 k            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));* i/ S& Y: j. v* k8 r

7 m% N0 k* y3 k2 c* w, ?2 B            pSerList->Add(szSerialNumber);% m9 q+ d0 T& K8 K8 w# I
            pModeList->Add(szModelNumber);
( u% y( ]0 T/ a2 M, t        }
  f  i4 r+ O1 `% A4 Y5 ?- h    }: a! c, e0 M# z4 P/ N7 f
    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
0 f1 D0 {. x! B) ^7 L# ?}2 W9 y4 L" Y0 x1 M
//---------------------------------------------------------------------------2 i. h/ r5 ]+ z& P# ?$ ^- b
// 为防止不负责任的转载者,在此注明原出处信息,请见谅。
  m7 R. G$ b" L2 d// 资料收集整理:ccrun(老妖),欢迎光临C++Builder研究: http://www.ccrun.com& J2 B' O8 U; C  k% B! k
//---------------------------------------------------------------------------. R1 u8 h& S' B
// ReadPhysicalDriveOnW9X_Ring0()$ ]5 T/ o4 N: s! T* X
//
3 G  r1 O" Q5 |// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
# b+ X" Q4 T" [// btMasterSlave = Master(0xA0) Or Slave(0xB0)" j0 E* b. \2 }( N. u
//---------------------------------------------------------------------------1 v$ u% d# r- B
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,: v! N+ ~% X- {$ f% ~7 L3 M: V
        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)2 V- |+ e0 ^, a. z, S2 d: _( D) R
{; ^  {% i6 z. I- s% R, j8 h
    BYTE  btIDTR1[6];: t# D" p' C! Q* p  m0 e7 n  u
    DWORD dwOldExceptionHook;: h1 j; X# N+ u! Q1 s1 u
    const int nHookExceptionNo = 5;! V& y0 B1 G/ V* x' V* F  ]" {  m
& ?# V4 c$ M7 x2 w
    BYTE  btIsIDEExist = 0;% T2 z7 b; s- n
    BYTE  btIsDiskExist = 0;
* n/ a) v( ?: _    WORD  wOutDataBuf[256];  J; x- ]- F4 |) Y: R0 v+ ]  A3 O
8 p* }" q$ v! q* T, ]6 Z6 I
    BYTE  btIsFirst = (BYTE)bIsFirst;' O8 Z, ]4 x" z8 z% ^; C; w

( q" g$ P% U6 P    const BYTE btBit00 = 0x01;
% O" R& S/ v# v" Z9 s1 J0 ]    // const BYTE btBit02 = 0x04;3 l0 ~$ q% f, {( u. n+ K0 ?
    const BYTE btBit06 = 0x40;7 v" L& b9 V( h9 p- O% l0 T
    const BYTE btBit07 = 0x80;
4 t8 a8 s* Z3 S( K# z5 N% b( g    // const BYTE btERR  = btBit00;+ V% N! `. v7 ~) f& w7 Y5 }
    const BYTE btBusy = btBit07;) R1 M7 p4 p. J
    const BYTE btAtaCmd   = 0xEC;. l$ Q4 g) K" b: E6 o" g( x
    const BYTE btAtapiCmd = 0xA1;) b  _3 ]* f3 V. a7 z/ Y! Y

3 \% V, L* B& T# P( y# d    __asm9 [8 e" b4 k9 n) j6 r
    {
# d7 B' _4 V1 ]" F        // 必须先执行这条语句
$ x& T  s: D. |. r9 _5 m8 |        JMP EnterRing0
5 h0 R9 q0 }) D8 u9 }9 R, I; y7 x  }# P- y2 n( o& P7 h5 j0 e$ [
        // 定义过程
1 f+ ?; r" F* p9 Y0 R9 [        // 等待IDE设备直到其不为忙为止
, A1 g/ g" K# e+ T; ~( |* n4 Z        WaitWhileBusy proc  @( I  z4 h+ \  @, _1 w! z' }
# d, G# V( Y5 v$ O/ b$ [
        MOV  EBX, 100000
% W  f( g" A5 z* S        MOV  DX, dwBaseAddress# L4 V( L0 Q  Y8 i, G; ]! D6 G
        ADD  DX, 7; {7 l+ c3 d; B' @  X
, U' p+ O; u2 d) c, X! s5 y
        LoopWhileBusy:
4 d* h0 O* X3 H: ]
( m0 P1 U! W, P$ {5 [        DEC  EBX
$ A6 N# m. T5 t2 g0 R: X        CMP  EBX, 0$ Q" e8 P1 l- V5 @
        JZ   Timeout
* |4 r6 q9 P! J* O, s6 a/ P* s+ V8 F        in   AL, DX
% _5 [8 x0 c! q9 @6 J. k        TEST AL, btBusy
! [3 }; y, L) Q2 O        JNZ  LoopWhileBusy
- A# ]  L! f1 p% C3 {' ]        JMP  DriveReady
1 b5 Q' K2 w, ]# {
6 P' s9 Y, I3 a/ @* |# x        // 超时,直接退出
9 S4 r0 F) u3 ?) v        Timeout:8 ^$ l/ i9 A+ x: Y" \( n
        JMP  LeaveRing0
6 C) `- v3 _' S# s* K4 P        DriveReady:, t# A- a* e! c. B- A
        RET5 [1 Z0 x; r) [* W7 |$ q
        ENDP   // End of WaitWhileBusy Procedure! `/ A) T% L) _

- ]/ j! t: H$ z& S        // 设置主盘和从盘标志0 _- j6 |- l! N; o3 l9 W* [
        SelectDevice proc* ?3 e, C) k8 L7 c

' y& R0 ~; ?" n. U: E        MOV  DX, dwBaseAddress2 d4 s& B1 E0 G  i) T
        ADD  DX, 6; t& M6 o' O7 O3 W  \1 m' k. {5 J
        MOV  AL, btMasterSlave" ]3 G3 L; L: N! P) {+ P! d
5 S  w* W2 N2 e% M
        out  DX, AL' _, O! j& Z& Q1 Y3 d
        RET' @  m6 ?8 [. J* H- x
7 T( ~; K+ f! p
        ENDP  // End of SelectDevice Procedure
# R3 j' H+ q5 I1 }) v; h2 A& R, `3 O: J) t: o
        // 向IDE设备发送存取指令4 X9 J- i7 C  h
        SendCmd proc
8 n0 p& D" U, Y" {- d( t5 F" b0 {1 `2 C& ?/ L  ]
        MOV DX, dwBaseAddress: C3 V* p5 N0 x9 c+ L
        ADD DX, 7& R5 C4 W% S9 X* V5 t! o2 ]/ \$ O
        MOV AL, BL // BL是主从盘标识,在过程外设置
" K0 t/ m1 S- V        out DX, AL5 L. x' r0 c# C* \  H
        RET
  l- s# X( C3 q. V5 b        ENDP  // End of SendCmd Procedure
" B2 u- Z: K* [6 S/ V* r
1 f. n. z3 G4 [        // Ring0代码* X6 N% [6 U) U9 l: I: C
        Ring0Proc:/ t. Z2 J3 \; I: ~% L8 P5 q$ D! }
        PUSHAD+ [5 e4 }9 E, }. U
        // 查询IDE设备是否存在9 \- C$ }" [+ p; e, b8 R$ l+ L
        MOV DX, dwBaseAddress
/ V" v1 g, P3 `1 D& ^+ {; w        ADD DX, 7, l2 g7 q- v6 |3 s
        in  AL,DX
6 j& |8 N# {+ l  S  R8 p9 ^. @& W$ j0 V! d
        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
/ l4 z6 w) {# _. Z' {        CMP AL,0xFF" F9 ^& ^. |- A. x$ t: `+ a# i8 I! r- v. r
        JZ  LeaveRing0. @. p7 j! R1 R4 g; ?8 l
        CMP AL, 0x7F+ O( v; \$ _6 Z; k5 k
        JZ  LeaveRing0" W, k+ l: `- o5 e  {
) x% X$ u' R1 P! o
        // 设置IDE设备存在标志
0 F$ M, l2 t/ r) Q& v        MOV btIsIDEExist, 14 b' {( B- v0 W5 X# }
2 d. b: W- B3 v' i- t# ]4 n
        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
& U0 _  W2 l6 D2 |# K! M        CALL WaitWhileBusy
4 a. d. n- S4 G3 `) ~        CALL SelectDevice
# z% J7 `0 |" N# @9 y9 ~; [! [8 }- h% l7 n: ~) n" |" q
        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
! @5 z/ k3 n+ z        CMP  btIsFirst, 1- S  v4 O4 |  C/ J! g. `8 a
        JZ   LeaveRing0& c/ Z& L, p8 p; p
6 J4 t, h: a* k  ?( |4 _
        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???6 e+ E9 R; f/ v# q& I9 [. D  `: |
        CALL WaitWhileBusy  B$ h  t+ o1 O" H
3 s: d" ~+ b$ w, ]( j
        // AL的值等于cBit06时,不存在驱动器,直接返回$ p0 p' C8 w+ ]
        TEST AL, btBit06
9 t) A1 H% I2 m" r0 f" i7 C        JZ   LeaveRing0
/ B: g* Z% D, {) n" J; |& \' U" C7 }% V7 `+ q
        // 设置驱动器存在标志
- R$ n! e) `5 A4 n# A% `        MOV  btIsDiskExist, 1" S, }1 o  F' X  X: \

9 w5 a/ P( ~* Q; S; x        // 发送存取端口命令* ?/ b) A# ?$ l8 \% }7 @7 O3 }3 G
        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
6 I- n; `# Z8 v% `        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令/ _( N9 N) c7 k7 r! n
        CALL WaitWhileBusy
7 A7 G' o' G6 }6 \* G. G8 y1 `        CALL SelectDevice    // 设置主从盘标识
# z: k# m2 ]2 k  J' U        MOV  BL, btAtaCmd      // 发送读取命令
. n. B2 ?- F8 K/ V% B0 ^0 f: b$ B, U7 z        CALL SendCmd* X# l/ |1 B9 l+ v) b
        CALL WaitWhileBusy, d- P5 j* O! P- v* t

# h. v( D6 N$ c4 {        // 检查是否出错
1 b7 k/ ]! c0 D# c  ^1 U; ^/ H        MOV  DX, dwBaseAddress- j; R  @7 A8 v, Z3 k
        ADD  DX, 7- Q) I' D" K. C, u' Y2 p

1 l1 ]) y' E9 `: B0 @2 a+ G5 J$ W        in   AL, DX; I4 |  K% ?( _5 }/ J

9 H0 s# X# [- Q. V        TEST AL, btBit00
) j: `- [. e0 {5 i  o5 M! p        JZ   RetrieveInfo   // 没有错误时则读数据
- P' D$ ^' \% G0 [; O4 `3 }( p) c; T/ n) ]& z
        // 如果出错,则进一步尝试使用ATAPI设备命令# U& Q+ H( P5 K/ y& P/ C; d
        CALL WaitWhileBusy5 f" Q3 |# |$ C( ~1 B# z4 ?9 k. p" o
        CALL SelectDevice
7 R1 c( j$ E9 Z5 i) @        MOV  BL, btAtapiCmd
1 \1 `1 E' }7 W' Z, E: s        CALL SendCmd+ f( k9 E% O! W  w! T# r
        CALL WaitWhileBusy
/ T& L4 G3 ]' a( e: \" G6 ^" H1 c, Q3 H5 A/ d0 K
        // 检查是否还出错( z5 P6 i* j0 w
        MOV  DX, dwBaseAddress
8 ]3 ?/ w- y6 x+ D7 ^2 Y        ADD  DX, 7
5 ]1 H' Z8 p; w; Z1 U        in   AL, DX6 R. @4 \# F7 L8 s9 j6 T
        TEST AL, btBit00$ a+ e! N# ~) n# ]. a" Y1 [
        JZ   RetrieveInfo   // 没有错误时则读数据. _& [, J8 [! s6 j
        JMP  LeaveRing0     // 如果还是出错,直接返回( _, A) Q- m5 S% b0 L
! V; {# f  W/ |& N4 [
        // 读取数据( O7 X* R# c$ t  F$ i& w
        RetrieveInfo:+ c- D* r$ g: k

5 C: M: L% R- w        LEA  EDI, wOutDataBuf
6 q9 K) Z* D* i( e        MOV  ECX, 2568 u4 F1 S) S( S5 F9 ]- h
        MOV  DX, dwBaseAddress' f, }4 U/ j' L$ P! e
        CLD
1 J) N7 R9 j! J, q$ ?) A
0 ?8 @" H; t$ w) w. D        REP  INSW' N) c- X$ q0 [9 l- ]/ T
4 `3 V( E( N4 e# G8 W
        // 退出Ring0代码  ?- w% A, T# T- b! f8 e
        LeaveRing0:
9 q4 b* @( _- N, {. J. A/ m% O. [' S
        POPAD
3 K- T8 I  V3 A  K6 |' ?0 `! `3 F        IRETD0 k! f: v* m9 a, ~( c
4 D+ [+ I0 o) R* _9 v! {7 I
        // 激活Ring0代码+ T: z+ a! r) K
        EnterRing0:/ D4 T$ N6 w' y3 w
# Z/ |5 T. Y( I: f5 z8 L% ~( z
        // 修改中断门  c/ D. U" ^" e  O) r' y
        SIDT FWORD PTR btIDTR14 Q9 w0 m, @. c: C
        MOV EAX, DWORD PTR btIDTR1 + 02h5 [+ A" z! D+ E3 F
        ADD EAX, nHookExceptionNo * 08h + 04h
. \) O% |& u0 d! [: \" K5 r6 z* P        CLI
: B3 K. R! T6 A3 S6 h3 i4 Z/ l* [* b9 Y0 C7 z
        // 保存原异常处理例程入口6 p. P1 U/ Q4 _9 h; F! c. ~
        MOV ECX, DWORD PTR [EAX]# z% [4 l, o: H# u+ q* [
        MOV CX, WORD PTR [EAX-04h]
9 }2 U+ ]# ~! S) H, z        MOV dwOldExceptionHook, ECX
- Z2 E2 f" S3 j+ P3 `/ G5 {* c5 {0 t$ m. R; @
        // 指定新入口7 Q8 B3 B; \# ~: @3 r
        LEA EBX, Ring0Proc( Q1 k2 z. @/ Q( y, y, P
        MOV WORD PTR [EAX-04h],BX. F& _; h) q4 `3 j: |# Z' j
        SHR EBX, 10h
5 @# U  R' N; n( g        MOV WORD PTR[EAX+02h], BX0 Y( D7 `9 H: s
) P, q8 F# i) Y8 d9 e) u
        // 激活Ring0代码; W% a2 X: ~0 `6 r) H9 W1 M
        INT nHookExceptionNo# k$ X; K( n( j8 U
$ u; l! }, q5 @1 l! v; @
        // 复原入口
# x  i; s& F: y1 S3 c        MOV ECX,dwOldExceptionHook
- D3 J" N) f; T; g        MOV WORD PTR[EAX-04h], CX
* P  I; e- ~0 n: `& Y' u        SHR ECX,10h& ]/ v1 Y% e0 f) s
        MOV WORD PTR[EAX+02h], CX
( ~9 j$ W  }- l5 H% L        STI
( P9 ~" Q2 i1 |" w6 x    }
8 k% d% E: w. n* n; D: l    if(!bIsFirst)
/ Q& _2 K3 m2 I. T& p+ {    {
# J4 I8 J& {0 y1 T2 o2 S        bIsIDEExist  = (bool)btIsIDEExist;0 R2 R$ M: p  J
        bIsDiskExist = (bool)btIsDiskExist;
# n* P6 V' F* x- r4 o1 S        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
8 a! y' Z' q2 o! f    }
! @6 p2 D0 j! n4 j- e7 W}
1 l  e' F3 i9 \4 N  d1 {//---------------------------------------------------------------------------$ i7 f2 D# ?7 u, x$ H" Q5 s1 C8 j
// 调用方法:
' a, q  K% y$ u$ W: \; dvoid __fastcall TForm1::Button1Click(TObject *Sender)+ l: x; k3 J) e& p9 h2 `, y
{
) ?! W* Z3 @8 i5 l4 }3 o9 ~; z    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
. ]! K2 a! ^2 ]}
8 N# i- n; r' p; z
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-10-1 21:53 , Processed in 0.020012 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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