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

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

[复制链接]
发表于 2008-1-6 19:59:06 | 显示全部楼层 |阅读模式
代码框架,你所要做的仅是修改WQL语句,具体可看MSDN。以下代码为简介起见,一次返回所有的CPUID或硬盘厂商系列号! W7 V4 g! n6 _5 P$ L& q
  1. : i# ?) b+ @! ^& D
  2. #include "StdAfx.h"1 y" @, d( q: Q1 o
  3. #include ".\puiddisk.h"  \- S& f8 o$ ]# ?8 Y/ G5 L7 `
  4. #define _WIN32_DCOM! G4 r- M) ]; J4 c- p' G0 v8 ], l
  5. #include <iostream>
    * m  S% B  j1 h3 ~; U( Z/ I
  6. using namespace std;% T( A; d2 ~* B# [" R
  7. #include <comdef.h>
    9 ~/ [& X3 v2 D. D* @+ _
  8. #include <Wbemidl.h>' b5 o5 g  ^- i, l: E0 @$ M1 u- G  T. M

  9. / E. C: u  ^6 a9 n6 m
  10. # pragma comment(lib, "wbemuuid.lib")
    , v# q" Q% g. h/ N
  11. CpuIDDisk::CpuIDDisk(void)
    . e( H  W7 r$ l
  12. {
    8 |" \5 C- y2 @- b2 G" h
  13.     GetInfomation();
    * m7 e0 W, ~  g7 Y9 f* h- ]! \
  14. }
    ! J5 T2 E9 @- y
  15. - }; P4 t0 Q) ~) V' F
  16. CpuIDDisk::~CpuIDDisk(void)
    " b% T. l+ n2 K, f
  17. {
    : G% ]; m, s5 |7 L
  18. }9 p/ u/ l/ r3 D# i$ D5 L
  19. int CpuIDDisk::GetInfomation(void)' j4 j5 u. K/ C' N- ~
  20. {
    4 g- T1 S: g7 y" R
  21.     HRESULT hres;
    3 h2 Z* x! l/ d5 A# H
  22.     //步骤1:不是必须的,COM只须也只能初始化一次$ k$ \  t% Z6 ~. {& w
  23.      hres =  CoInitializeEx(0, COINIT_MULTITHREADED );
    1 Z! e3 b; L) \
  24.     if (FAILED(hres))
    . P, F6 y: h& S0 s. [, l
  25.     {
    : }, b0 p7 e6 A- _: I3 X( s
  26.         return 1; //初始化COM异常:注意,COM只须也只能初始化一次* ^/ |6 `- X6 b5 X% |/ s
  27.     }0 j+ U3 e$ R& n
  28.     //步骤2:不是必须的,COM只须也只能设置一次
    5 L& S" K& s0 [% P, X8 x2 I" J
  29.     //Set general COM security levels
    " f4 J! ~6 T0 L/ g6 O& u
  30.     hres =  CoInitializeSecurity(
    $ b) L/ A! p# o, |* ~& j
  31.         NULL, 6 O  j; c% [; u2 |: Z
  32.         -1,                          // COM authentication; A' {3 `/ b" L' E: V  [
  33.         NULL,                        // Authentication services4 J4 s& h* ~, T7 }
  34.         NULL,                        // Reserved; q6 Q0 j  `( @1 [8 |
  35.         RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication 5 p2 c& r/ [0 L+ E
  36.         RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  - l% Q! j1 l2 X+ t$ z
  37.         NULL,                        // Authentication info
    4 w* b. k7 y, v) d9 N* j
  38.         EOAC_NONE,                   // Additional capabilities & }6 m( `5 Q2 i7 R6 Q
  39.         NULL                         // Reserved
    3 H: d2 i! M- K% g1 ~2 d) q
  40.         );# [3 \, i0 h" ^( V. W9 @& S6 t
  41.                      
    3 G6 p, m2 E6 d* i. A* ?* t
  42.     if (FAILED(hres))* X9 X! P- {# `; {7 H2 A
  43.     {
    * H3 m7 Z8 f: M4 _
  44.         CoUninitialize();- E9 A7 @  P/ s, l! P+ u
  45.         return 1;                    // Program has failed.+ ~0 f, }8 \6 ?8 b0 f
  46.     }
    ! [+ L( E$ r, `$ C  }$ {* o! x
  47.    
    6 W$ P. u% y( t" x
  48.     //以上不是必须的,若已有“::COMInit();”,则要跳过9 z/ n' f- e/ o. k
  49.     //步骤3: Obtain the initial locator to WMI
    / F0 x! j9 s6 f0 _6 }" K
  50.     IWbemLocator *pLoc = NULL;
    4 I# k! x0 d# J6 d) ]) k
  51.     hres = CoCreateInstance(
    + f) V& Z; O& {8 K
  52.         CLSID_WbemLocator,            
    6 C$ m: J1 h; w4 z+ c6 x% T9 d  W
  53.         0, 8 n9 R- u" v5 C; k$ o, r
  54.         CLSCTX_INPROC_SERVER,
    / q( v# p% r  P# P' w# h7 M; T$ ?
  55.         IID_IWbemLocator, (LPVOID *) &pLoc);8 }. w$ ^9 M2 A$ [( B

  56. % y: z, B4 h6 W+ Y. S9 D6 |9 \+ b
  57.     if (FAILED(hres))
    * A* \3 e: U3 j& w; y6 J
  58.     {, u2 l1 |) ~+ h  \+ Z( ^9 r
  59.         CoUninitialize();
      g! k9 H4 V7 |$ r0 L0 S
  60.         return 1;//Failed to create IWbemLocator object
    4 o  m- A& J9 D# z* K+ r
  61.     }) R8 i/ S6 n2 y

  62. 0 {# C4 E* J7 C
  63.     //步骤4:Connect to WMI through the IWbemLocator::ConnectServer method
    3 s8 _8 _* j. o5 Z% Z
  64.     IWbemServices *pSvc = NULL;- C& r2 A5 F3 M
  65.     hres = pLoc->ConnectServer(
    # |) N+ m% O6 a  `, N( B
  66.          _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace1 Y) J, d, }- v8 c. F6 {8 ^/ o
  67.          NULL,                    // User name. NULL = current user! C! {# f! P# v1 q' `6 V
  68.          NULL,                    // User password. NULL = current
    ; b; k. H  G! o6 @
  69.          0,                       // Locale. NULL indicates current
    7 u: D! e, j  l4 d
  70.          NULL,                    // Security flags.( x0 O6 c+ h: ?3 _% I/ m, g
  71.          0,                       // Authority (e.g. Kerberos)9 ~) Q9 ?, O5 d* V! g
  72.          0,                       // Context object & _- }( C, U0 q) E
  73.          &pSvc                    // pointer to IWbemServices proxy
    : ]8 L+ ^+ t: E6 ~9 K1 n1 P# c
  74.          );6 z% W) R8 @' a  `/ H( Q
  75.    
    # {7 u  u, U) o! F
  76.     if (FAILED(hres)), q& G' t  _8 y" Z3 Q" y
  77.     {
    1 B. q1 [& g' \% F4 E
  78.         pLoc->Release();     + ~2 c! i/ d7 t+ f- L2 l: ^, K( E
  79.         CoUninitialize();
    7 q, c/ K$ u/ X/ F3 d
  80.         return 1;                // Program has failed.5 o" _3 |! [, g( D$ u* V4 j, R1 |
  81.     }$ O1 \% Q0 i9 t, O
  82.     // 步骤5: Set security levels on the proxy/ p9 n* ]7 Z: b2 M9 B: D# K
  83.     hres = CoSetProxyBlanket(7 G5 k+ Y3 [5 J7 q+ c6 u
  84.        pSvc,                        // Indicates the proxy to set( x- q, [3 K% C. d8 A  Q# u8 m
  85.        RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx
    : w: |+ Q: N- A' t$ z9 @6 W
  86.        RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx( M4 R3 U' @/ X8 B( J
  87.        NULL,                        // Server principal name 6 D9 U% [* G& k% c
  88.        RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx 9 q& ?* k0 Z0 w" h2 q
  89.        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
    - n: ]: V8 Q+ h& Z8 z3 c7 e
  90.        NULL,                        // client identity
    2 k: _( b3 J( n' s
  91.        EOAC_NONE                    // proxy capabilities
    7 k) ~2 t) A0 L  O, G3 T
  92.     );' i" ]+ x* H+ m7 D5 ]

  93. & y# ~  p0 T. a! G0 ?) I
  94.     if (FAILED(hres))9 }! Z* r2 T- e, A- ]% _9 c
  95.     {
    ) G& z) v6 p, w, ]9 @3 J; M
  96.         pSvc->Release();
    6 a+ p9 K! C) R. a8 D# }. T
  97.         pLoc->Release();     
    & m5 k: D8 r" B. @& d7 T& f) Z
  98.         CoUninitialize();
    % m( ]2 }& X5 }: P
  99.         return 1;
    - Z3 H3 Y4 c) r3 @5 F# f7 l! I
  100.     }
    1 G5 q7 k& m' H( m! c0 I0 x

  101.   h2 \  G1 @: S" L8 V' k
  102.     // 步骤6:Use the IWbemServices pointer to make requests of WMI ----; M2 e1 \9 _. s' b/ F3 \2 A
  103.     IEnumWbemClassObject* pEnumerator = NULL;9 w, i, D5 x6 x. s# M
  104.     //计算CPUID6 L4 l# x$ ~4 {" b9 V1 H% |7 a0 `* ?
  105.     hres = pSvc->ExecQuery(* J3 D; @# `& Q0 @& m6 ]
  106.         bstr_t("WQL"), , o, m& ~$ t8 `5 u4 [" t2 |/ [, F; c
  107.         bstr_t("SELECT * FROM Win32_Processor"),//Win32_OperatingSystem
    8 D( V2 K0 W$ b4 v
  108.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, / ~0 ~$ S' z3 G- \$ J
  109.         NULL,: w  |+ c/ f. T  i% @+ D) I
  110.         &pEnumerator);
    7 `+ y/ e; `( c# R& H
  111.    
    + P! f  |/ R4 n; K
  112.     if (FAILED(hres))6 d) n! l. n3 b3 i% U8 `5 X
  113.     {5 N" Y% J0 c% K* |/ v# y
  114.         pSvc->Release();6 v) P7 O- i% y4 C2 A& T9 h- h* b( z- j
  115.         pLoc->Release();
    % z, `8 {  p1 n! _* ^3 |
  116.         CoUninitialize();
    " ?% ^2 t0 H8 _: I- \8 G& e1 j
  117.         return 1;
    . S) B: N4 U/ w1 x/ b
  118.     }
    # b1 G$ q: e5 m1 n# G
  119.     // 步骤7:Get the data from the query
    1 A/ d3 ^0 G) h5 f8 R- ?* o) i
  120.     IWbemClassObject *pclsObj;
    8 \- u9 n8 N% m1 U
  121.     ULONG uReturn = 0;
    . X! E: T: B! q: z  x
  122.     while (pEnumerator)
    , h' w/ S5 U" Y% t5 x! ~5 ?. }
  123.     {" a1 S) b( I# ^' [' @+ I* W. p
  124.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
    . v1 M! s# C0 O' `8 c: ]
  125.             &pclsObj, &uReturn);
    1 F* O" n# B7 l+ l- U
  126. : ^& O5 z# [" J7 v7 S7 O
  127.         if(0 == uReturn)
    + N& H! p3 G: Q& S' s8 e. T/ y
  128.         {
    % c  I- c% ]; u) T& K
  129.             break;4 o& d* ]" ~) k% M. h% x% F4 Z
  130.         }
    ! I8 c% N; |$ c+ k
  131.         VARIANT vtProp;: K: ?0 I( O; T8 G- }# Z+ m
  132.         VariantInit(&vtProp);
    8 Q1 E/ w: Q+ ?  t- E, E
  133.         hr = pclsObj->Get(L"ProcessorId", 0, &vtProp, 0, 0);
      @, N. k# f- n
  134.         strProcessID=_com_util::ConvertBSTRToString(vtProp.bstrVal);//strProcessID:类级变量7 R) r0 F) B/ w2 _6 r7 [
  135.     }
    " k7 O' w' F% J2 |# h" d% m: s0 Y

  136. 2 P0 [' I1 y3 H* n6 l# O1 B. N
  137.     //计算硬盘系列号& l! ~! n0 U8 V/ ?
  138.     hres = pSvc->ExecQuery(
    ( R4 |' @3 c% _9 o' v. z6 w& i; |" B
  139.         bstr_t("WQL"), ! G' M) M3 [  n6 s& R" E
  140.         bstr_t("SELECT * FROM Win32_DiskDrive"),
    ) n, K/ t) b& e8 e& F8 U
  141.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
      p1 B1 C- A; N
  142.         NULL,. s  s! a9 m8 V% W5 K
  143.         &pEnumerator);
    : h  c6 w- [% R5 O$ j

  144. $ f( a/ r$ X$ k
  145.     if (FAILED(hres))
    # m0 w4 d5 i8 O; L
  146.     {
    . l  M7 q$ r% U+ c
  147.         pSvc->Release();8 M9 N2 c- |5 d) S) O6 |6 x
  148.         pLoc->Release();
    : K+ g/ N) m/ W3 _0 n9 |  D6 R
  149.         CoUninitialize();
    / D6 F) r4 X+ x8 ~$ q9 C8 k: E5 ^3 m
  150.         return 1;
    . |7 K2 C& Y& M* y1 w& }% Q! E' V
  151.     }) z7 D' [* R/ W6 m1 M. G
  152.     while (pEnumerator)9 v. Y9 R( c/ @  j& b9 {  |) u
  153.     {
    9 o/ Y. y; U+ K: o, J8 r
  154.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
    * ~0 J2 O; K) E5 y, i6 g
  155.             &pclsObj, &uReturn);/ t, i, A5 m, y# z8 i0 q8 m2 f+ X
  156. # {0 Q0 i8 h! ^/ L, K" _" l
  157.         if(0 == uReturn)/ Q" P+ |0 J4 G+ p; R
  158.         {
    - W% R# E. b7 }# m) Q
  159.             break;: G/ o% }2 j2 F( t
  160.         }
    ' x5 B& G& @5 v4 g2 X9 `
  161. 6 l' o, b+ C- t5 c
  162.         VARIANT vtProp;6 }3 [( o4 E+ X  q. Z) q
  163.         VariantInit(&vtProp);% r3 H; y4 Q* V8 s2 H% B- g- s8 z
  164.         hr = pclsObj->Get(L"PNPDeviceID", 0, &vtProp, 0, 0);
    - Q/ {0 ]: {3 t8 j0 r
  165.     strDisk=_com_util::ConvertBSTRToString(vtProp.bstrVal);. P+ T. c4 ?1 g0 \, C* X
  166.     }# \& i' x3 N5 X& R0 Y" p. i1 p

  167. ! N# v  Y* l4 O7 |2 j
  168.     pSvc->Release();0 {& e" T! y: v" ]1 `  `+ ?
  169.     pLoc->Release();
    8 r4 `; a1 P; G7 q# }, V
  170.     pEnumerator->Release();
    . A$ ~' v) }/ H/ n, [. S
  171.     pclsObj->Release();! ~: n3 C  N* {" x5 L6 S
  172.     CoUninitialize();" C6 J: @3 e3 D4 t

  173. 0 [$ ~( `5 ~% F8 F0 ]* N
  174.     return 0;   6 k6 C0 n; I8 r8 }' B1 w
  175. }
    ; i2 `: h0 |2 C* k
复制代码
 楼主| 发表于 2010-10-11 19:21:05 | 显示全部楼层
本文代码经ccrun(老妖)在Win2k下试验成功.
" T! e  \) N4 i1 E1 |! P( J& n: m& E4 E/ M
#include <WinIOCtl.h>
( L9 B: _1 L  M: s) q, a1 D( J#include <stdio.h>
  |' S% f# K3 |* u4 N3 ^- h: X$ R- K2 K) T. j; f5 d( N
#pragma inline* [$ V  |; J8 j
//---------------------------------------------------------------------------
8 [* D* r, o: w! K// IDE NT/2000/XP专用变量
/ _4 _3 Z$ o5 ]5 Y! q3 K2 F( G; e" G( }#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
9 F' F5 @/ Z- o1 p/ t( w8 M0 K* W- V! g#define DFP_GET_VERSION         SMART_GET_VERSION
0 B! |: P6 o; O& G7 Z- {' K#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND" ]/ N/ c: w- j0 V4 l+ u& z
#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA) c( V- ~6 I& ~: A7 d2 a% U4 G5 O

8 V' C) \7 u) k& U8 V" Gconst WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令* j/ K' L. c4 g, M8 @8 y
const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
. d- U$ |, y+ G, Q! i1 B
- E3 ]' O+ ]/ `const int MAX_IDE_DRIVES = 4;8 n6 X) |3 B$ M  ~

2 [9 a& K+ P/ ~( t0 U# ^// SCSI专用变量
. h$ |9 X* J( i; Q% nconst DWORD FILE_DEVICE_SCSI             = 0x0000001B;/ B8 ~5 K& x$ ?7 m% e' r1 ~
const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);/ }5 H/ _2 k# S7 k' X5 T
const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition" G' y( I: Z) S& n% [4 {0 \9 B
const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
7 B7 h# G, M) m6 p! i/ c' E& y: E8 j. Q( s. g$ b+ ^
typedef struct _SRB_IO_CONTROL! K9 C( A( ~! g: Z/ I3 X
{% V" ]; ^1 {5 }& z* t8 N1 d. M8 |
    ULONG HeaderLength;
9 V- [+ C0 [1 O4 _    UCHAR Signature[8];$ v! ?9 n" u# x
    ULONG Timeout;
2 c) |, A9 u; I3 q7 [    ULONG ControlCode;
" n3 ?3 f, V7 V3 K1 b( r% I: Y$ z    ULONG ReturnCode;. W# [; i6 A$ G7 k- D8 Z3 l
    ULONG Length;$ f! T) B& i: j: y. g! P' n4 e
}SRB_IO_CONTROL, *PSRB_IO_CONTROL;1 e) y% X) D" F( X

+ [" J9 W# M3 G  {# v( C// 读取的主函数5 N0 E. \3 C0 }3 i' X/ \
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
; T! S! @: t6 A2 r, o
* e1 M% f' f2 F+ k2 y4 d8 n$ J& e// 辅助函数% g" [* F: h1 B9 |: }$ P& O
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
+ p* o  r' ?: |+ O// NT/2000/XP函数  {# G7 ~  [0 d0 Z- [
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
/ p' D! J. ^' e! N  W3 Rbool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,9 @) _) c5 e+ T
        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
# \, }7 i5 Y' [8 X& i) e7 I( |        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);* u2 y. Z( M7 h& f" k: c
// Windows 9X函数- d( Q2 F) P9 j7 Z5 J0 L% \" f2 L
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);
) W+ D. a8 ?2 {0 x* zvoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
( q% z7 n7 Q/ e' ~5 E) G        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);+ t  J1 f& G( v+ v' T

! t  k) a2 l/ F+ G+ l6 p" \7 z// SCSI读取函数(for NT/2000/XP)
  @: Q) g# S! O6 bString __fastcall ReadIDEDriveAsScsiDriveOnNT();
. _/ L( X9 U/ Y' d) d# h6 Z//---------------------------------------------------------------------------
$ |' m3 W+ d* P  ~* A4 V5 S8 P// ReadPhysicalDrive% A5 z6 }+ e7 g" M
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
2 ]6 f- Q0 B9 P  C0 K0 f/ l{. q; ?; J3 B0 I5 D9 X
    switch(Win32Platform)
: o4 L+ Z: A4 h: h    {
, M: A/ k: q* n        case VER_PLATFORM_WIN32_WINDOWS:
6 [7 y* D1 Q, M& A) C' u" o            ReadPhysicalDriveOnW9X(pSerList, pModeList);. @! q2 _$ N& }
            break;
  Z# o$ C3 Y5 [        case VER_PLATFORM_WIN32_NT:: O  ]1 F( S1 H; S# [
            ReadPhysicalDriveOnNT(pSerList, pModeList);  Q9 M5 P: Y) q$ Y+ l
            break;" R( B& V3 K5 w* N$ G
        default:
, a- v5 a8 E/ x, b$ A8 s$ _            break;
2 J" k: v, k) ?' i4 v    }* i' y) H: k; @0 L
}
# J/ |7 x# C. b6 [( O//---------------------------------------------------------------------------
/ j# s6 H; q8 V& Q4 o5 Y// ConvertToString
$ n* R2 L  [( f: ]% d; ]7 e$ ochar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
4 j! G1 J: b% F* ^6 _$ s, i{+ P) J/ I" p. }) Q% S8 O3 Q
    static char szResBuf[1024];4 z+ A: u( F) ~# T% @$ g: X- U& S
    int nIndex = 0;
3 ^+ r! Z& u# x* p    int nPosition = 0;& D6 l' M; F8 A- ~( l
! g% X( i' H& E4 S( m* z) B- Q
    // Each integer has two characters stored in it backwards" ^1 Z3 Z; c& ~9 {& m5 H
    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
8 V* d+ N* G9 T. a    {2 g. m( @. r; D1 }8 q
        // Get high BYTE for 1st character) a- |; S/ `% x" r" ]. c) _
        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);. U: d/ R- y1 `# N& H8 R6 r! ?
        nPosition++;4 f6 {! r9 i# ]

! Q9 {1 w3 y( a; z: P. p        // Get low BYTE for 2nd character
. \2 E1 T) q$ p  z3 M        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);% h3 Y- i' V2 Y' @2 {( V
        nPosition++;
0 z, c: \3 X" i& ~; K0 Q    }; K) K- I5 A5 L+ z+ k( d
- [2 X0 I2 ?0 z6 d7 `. K
    // End the string
6 u9 n7 _9 @  P8 m6 k    szResBuf[nPosition] = '\0';& v' j9 z0 H* A7 q3 O- e6 d

! b% h9 _: }& N( R' R% Y/ ?! i    // Cut off the trailing blanks
4 Q$ _5 ^% N' R8 h    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)3 r$ o5 A$ p& }6 R2 R  V
        szResBuf[nIndex] = '\0';
9 v' S8 m3 Z5 V% X
- V3 H* t" W. L' ?    return szResBuf;
- X  W2 C" ?4 k8 q, ~}  n4 }+ p# w& m! i/ W% D+ I! z& s7 B
//---------------------------------------------------------------------------
) f2 J. K* B/ i, S- H* i+ c  y, d" b* W// Winndows NT4/2000/XP 代码4 e1 y, m  z. Q7 U
//---------------------------------------------------------------------------
: Q! {9 \* k  t6 e// ReadPhysicalDriveOnNT$ n: X7 ?+ J. @  U9 u& C9 b3 ^
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
. C# b9 D$ W( |$ y7 V, z{
5 u, ]0 A% b. A/ x' K0 z8 v4 ~+ D    // 输出参数, ]" d1 M; s( w* K+ [2 @- v+ ^( F
    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
& j1 V4 R$ b1 O$ ~! G$ ~5 b6 T5 w' r
    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)/ g! p8 w6 w) D' t: l
    {5 e2 r  Q% p9 N) P
        HANDLE hPhysicalDriveIOCTL;; i9 h& m3 T5 |
        char szDriveName[32];
+ e6 V- ?# j+ p2 W. j) y2 X' [9 i3 ~# P; i
        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);* k% F7 f: u4 |, R& i( A0 _* f" Q5 R
        hPhysicalDriveIOCTL = CreateFile(szDriveName,
. L( Y2 r# Q. c0 c2 a5 ~, Q                        GENERIC_READ | GENERIC_WRITE,. C  i$ P4 X7 t; K; X% @  w
                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
: _% l) e& x8 _" N8 d9 Y* w                        OPEN_EXISTING, 0, NULL);5 y3 ^2 W) |; h8 Q  z' H+ F: F
1 }; P; D: d; m+ Z: ^, Z0 N; D  V
        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
: s/ }! ~/ h7 w0 j  k) o        {. ]& G3 @6 k' G: F! W& P: H- y
            DWORD dwBytesReturned = 0;: Y* Y7 P$ x8 Z! Y" F- Q
            GETVERSIONOUTPARAMS gvopVersionParams;
- V3 N% O: l: }4 `% ?- g8 |0 I4 F; J7 z
            // Get the version, etc of PhysicalDrive IOCTL+ {3 Y0 o  i6 U( {* a; P/ a
            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
9 ~' l- |3 I9 ]* f
5 k5 H' G) A$ K: L7 e" l9 @$ |7 F/ c            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
  h) L( e1 G! P: I0 J                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
, U/ s1 \  B: q" A                    &dwBytesReturned, NULL))& N' H# G: Q4 R9 ]% E, G: ^
            {0 u( t: L; k% c5 @; A& }
                continue;
" M7 _, w8 ~9 @            }
3 Q  R$ g! _4 y$ v- y" r+ l. ]. o3 P/ B' b
            if(gvopVersionParams.bIDEDeviceMap > 0)& R! r% M, H' |
            {
) x9 b: j/ P4 Z6 v7 j                // IDE or ATAPI IDENTIFY cmd5 N# w  k! c3 e/ z9 L& b* |
                BYTE btIDCmd = 0;
* j% K3 i% ?  r! T& L                SENDCMDINPARAMS InParams;
2 E' I* o! j" ?                // Now, get the ID sector for all IDE devices in the system.
' |. w! F+ R: O1 p8 v$ K4 N                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
5 Z$ Q$ a1 W& l                // otherwise use the IDE_ATA_IDENTIFY command3 `, N& r; [  J2 o" H
                // 具体所得结果请参考头文件中的说明2 k9 A, k: i7 E4 Z
                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?* W9 l( q  {, a5 {( D0 I& p3 q/ i
                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;: o& s/ ?+ p0 k$ T; c: a8 d1 s
                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
+ s3 U; d% r0 m3 e                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));6 x, n3 r+ }( x

$ G9 v- e0 x$ n1 y+ N0 j. X                if(DoIdentify(hPhysicalDriveIOCTL,; V5 ?4 Y& r  g9 J
                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
' L6 b' A9 Q& f, \: u' W                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))6 C0 ~4 F0 C3 }0 ~. u8 O3 `1 `$ d
                {
. _7 ?! B6 L5 p8 x2 D% f                    DWORD dwDiskData[256];
( A7 o8 ]1 s( `5 G3 Z5 q                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
3 O3 ^! T" _+ j" `. A/ o9 D                    char szSerialNumber[21];+ T: G, y9 S2 G0 {5 w( Y
                    char szModelNumber[41];+ R$ S: y8 T0 q" t: h5 ]
( a9 t- N+ D# R; Z- G% t
                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;- a( v$ ~3 |" l" g
                    for(int i=0; i < 256; i++)
# ?# @% x& C/ j" o+ X1 }# s                        dwDiskData[i] = pIDSector[i];/ |$ t7 j3 |, B: w) c
                    // 取系列号" J* P, V3 P3 p, R' m+ Y+ a1 ~
                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));! x" f6 n8 w$ h( W
                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));6 g/ f# ?4 D4 I. j1 U; b: ]8 }

; m8 Q6 @4 o* l4 N                    // 取模型号; J0 h( ~$ L* R- F2 x
                    ZeroMemory(szModelNumber, sizeof(szModelNumber));. F5 o1 [2 r/ ~; s
                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));: v; ], A) B  }) Y. |

; ]3 C4 p+ j; r7 \* w+ T                    pSerList->Add(szSerialNumber);# N' R. s) [6 ~$ @" T- G
                    pModeList->Add(szModelNumber);. M( t+ {$ X6 t; ]) l: o
                }
, K5 Y3 t9 s- K7 T- H            }
1 s- y# J+ ?+ c2 L5 z, N            CloseHandle (hPhysicalDriveIOCTL);
: K" E# f/ Y. e+ N        }7 t, k, V2 g2 H2 j8 s
    }
) g$ S/ o1 j+ J7 b  |3 h}
- Q% k% w' l1 M( O//---------------------------------------------------------------------------; o6 O) H4 w, X4 p, \2 t6 h7 a9 F
// DoIdentify2 G9 y' K4 m2 L, x1 ], q
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,/ a( p; I( X% ^, M" {# D. j
              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,( R: K! u* E$ j" U5 _% p4 H
              PDWORD pdwBytesReturned)
; ~0 a' J) l5 m& q! l$ y/ |{6 H% n% y/ Z- }; k1 S' x( `
    // Set up data structures for IDENTIFY command.
' a7 W2 F  `4 B  n2 @    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;/ M) ^$ j& `: v
    pSCIP->irDriveRegs.bFeaturesReg = 0;6 x* [2 K# x/ d; z. ]5 H( F
    pSCIP->irDriveRegs.bSectorCountReg  = 1;
, G6 F  E9 x! }( l0 h    pSCIP->irDriveRegs.bSectorNumberReg = 1;
6 g! q; z' ~* c. m7 I: o    pSCIP->irDriveRegs.bCylLowReg  = 0;! z& q9 e: D- ^+ z, _( v
    pSCIP->irDriveRegs.bCylHighReg = 0;
) u" G3 D' _! y' |* A
% i4 p+ m1 b( x! @0 n" w    // Compute the drive number.(主盘和从盘所对应的值是不一样的). b9 ^, V! A; ]9 I
    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
" Q* }  T+ `6 p( y+ ?6 x: G- p; t7 s# ]
    // The command can either be IDE identify or ATAPI identify.; {: S0 S* Z6 F% G' `
    pSCIP->irDriveRegs.bCommandReg = btIDCmd;) K% b# J7 F( q
    pSCIP->bDriveNumber = btDriveNum;
9 ~8 y! r: f6 _/ V; B4 u0 \' h    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
+ z9 ?  s" {8 p0 Z
  p" w4 p7 z' o$ K; \5 P    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
9 T0 p: M$ V: a; W           (LPVOID)pSCIP,# n5 p4 m( b) a2 |& P" x2 p
           sizeof(SENDCMDINPARAMS) - 1,
8 f' i& x! r2 a           (LPVOID)pSCOP,
0 j( f& o% r. N9 u; G3 l           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
2 {# _5 f* m/ |           pdwBytesReturned, NULL);
% B/ B( ^* o1 N# @( F: R}
1 P6 [: f- [: C! X; t2 _//---------------------------------------------------------------------------" P: d2 ]* K9 r# B
// Windows 95/98/ME 代码
. M4 g' k) N9 {  r2 [( j//---------------------------------------------------------------------------
) \% U% y" S# f1 K# {// ReadPhysicalDriveOnW9X
6 M' E  I3 M4 {4 gvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)
+ K" Z$ ^, A0 H/ \5 e{8 z8 D# Y; ^3 U5 d9 _( e+ v9 V
    WORD wOutData[256];0 r: l: Y" b$ s5 p
    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
" _- h9 W0 }  o1 v& t. b. `7 l: y! O' R6 s& M; f+ \: h
    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
* k( j4 w6 ^" M8 U* a* T    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以. Q! D" [+ e1 {/ J& Q# L5 x
    // 避免蓝屏的出现。(期待高人能指出原因)0 e" f  ?$ S2 p" n3 ]- J. e4 j' D9 |
    for(int nDrive = 0; nDrive < 8; nDrive++)7 X+ @( z, b( F# O  [7 y
    {
5 W7 D* V" h2 c/ c6 [  c! W$ h! Q        WORD dwBaseAddress;
" P7 [9 i8 t" L& \2 q9 g" r8 L* |        BYTE btMasterSlave;         // Master Or Slave& F0 L, x0 g8 {1 G; k
        bool bIsIDEExist;
+ f. ]" I( I  d0 ]1 ?$ q6 M8 l& L' f        bool IsDiskExist;
& `& y  ^3 x: ~4 K& n" ~! b4 r8 Q" S3 E) b" H
        switch(nDrive / 2). A3 v/ l3 ]3 r  F7 ~/ u
        {) d! s. i* b+ e$ ~) i0 x& J. Y+ P
            case 0: dwBaseAddress = 0x01F0; break;- Z: G; P4 w: C: ^* k3 K
            case 1: dwBaseAddress = 0x0170; break;" H1 I. [0 q7 S- J# f. b
            case 2: dwBaseAddress = 0x01E8; break;& y$ H; a) c0 M$ z3 ]3 L( E
            case 3: dwBaseAddress = 0x0168; break;) x7 C5 `3 f% h+ @: z
        }
3 g6 K0 Z1 D; n  `* c. G) Y7 l; r5 f" D: n6 z1 H. i& x
        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
) I2 v; r7 K7 d# l
) M  F! f0 I+ P! ?        // 进入Ring0, _7 Y9 l( X' Z0 e. A8 [
        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,  A. }' H  r/ S& n
                bIsIDEExist, IsDiskExist, wOutData);0 e: Y: V2 P/ {- A
    }
9 v- y/ a: B( d2 T, `, F% r0 B1 L, R/ K2 t6 v
    // 开始读取
1 f1 V" s! |9 z- {! a    for(int nDrive = 0; nDrive < 8; nDrive++)
3 o% W1 V% T) J$ a    {0 J/ H4 A- k& z0 C( h
        WORD dwBaseAddress;
7 G2 h8 e/ J+ h: s# N5 t        BYTE btMasterSlave;         // Master Or Slave7 r4 ?1 H: q" b1 y, {
        bool bIsIDEExist;
- S3 z8 f, U9 O        bool bIsDiskExist;3 [* J. P/ w6 F! _! a. y
        switch(nDrive / 2)' z" u' W- Y) ?& h4 W5 j! B
        {
% Y" B' _! O0 m: V9 g' o( I0 E1 t2 O            case 0: dwBaseAddress = 0x01F0; break;# \( n  U3 w8 x( T6 Q$ g
            case 1: dwBaseAddress = 0x0170; break;: e/ `) L% R/ V! d% K% d
            case 2: dwBaseAddress = 0x01E8; break;6 T# ~7 m; c, \# B3 f$ m
            case 3: dwBaseAddress = 0x0168; break;' L, G' S- E2 W% V. N  M
        }
  S' m' n, T0 u/ P& a& _, M
3 g7 F$ z3 ]. Z; X1 D1 j% o        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
# }" ]& S( m; W* V0 b* M7 t
0 G1 z9 Z8 ?) ~0 c3 v        // 进入Ring0
8 B; |- r. w1 j7 {, `3 H" c        bIsIDEExist  = false;
; ~, A& q" L0 W7 n        bIsDiskExist = false;0 n* a7 [& L' _: H" @
        ZeroMemory(wOutData, sizeof(wOutData));
- g' ^: ?) r+ I$ l5 [- _, W1 C* ^2 ^& W1 O1 `
        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,4 U0 {8 ^- n: q0 ~  o
                bIsIDEExist, bIsDiskExist, wOutData);( u0 `( k2 O  }$ Q8 P/ ^/ m1 M* h" i

4 n6 t/ l' N1 H8 ?7 U. w! ]( M' n        if(bIsIDEExist && bIsDiskExist); y9 U7 T" q; M& k: f- S1 ?) L
        {3 D& X& W4 s- z/ o
            DWORD dwDiskData[256];: V7 X# o# k+ I" S' o
            char  szSerialNumber[21];' n7 P/ Z6 n+ l; b2 ]
            char  szModelNumber[41];
& z/ t/ F* L9 H) C  k- X9 J
: p5 u/ x8 ?! n" A5 K3 x. Y; B- o0 w$ m            for(int k=0; k < 256; k++)
0 E. [$ s. R2 Q. A. b                dwDiskData[k] = wOutData[k];/ O5 f5 Q& K* V) T6 z
  _) G/ \" T. E5 y: |3 V) P* \
            // 取系列号) m( O# B# X: U% ?' n/ w
            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));4 r' r. I2 X, H! C/ {/ x1 P# _9 ?
            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
: ~% n3 C- _$ n8 [6 t5 Z4 _: h" a* c" W. O( U7 T! R# v: s
            // 取模型号) @1 R2 y' a; U% N! ^
            ZeroMemory(szModelNumber, sizeof(szModelNumber));# Y& T: E2 S+ r& p
            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));# Q0 C6 F0 B, M% m

9 S2 q  g, H2 g9 ~% @1 ~! [            pSerList->Add(szSerialNumber);
% n3 ?3 ^- E" k( \) o  K, L            pModeList->Add(szModelNumber);
' H: l; _& c$ C& r3 l        }
/ s' b' Z! y- b- ^$ @    }% U( h/ {8 q4 O: W, A
    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);' s( _) L7 M6 a* t& S* [# r
}' i6 p/ Y& A$ w7 b. u
//---------------------------------------------------------------------------
4 P$ H3 @5 R/ a+ j// 为防止不负责任的转载者,在此注明原出处信息,请见谅。# N6 N" T5 K6 b7 p
// 资料收集整理:ccrun(老妖),欢迎光临C++Builder研究: http://www.ccrun.com7 {; C( @# d: k6 b" v! g) C/ E5 ~
//---------------------------------------------------------------------------: T: l0 F8 m2 X( j9 _/ a( }% L
// ReadPhysicalDriveOnW9X_Ring0()! i) @' @" b2 v, o8 Z9 _; a
//
$ N7 ~7 T6 P, r- ]// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
2 K+ z# C' ^) W) w: o) F* x! q// btMasterSlave = Master(0xA0) Or Slave(0xB0)
8 `, @8 V: c9 i, W& Z//---------------------------------------------------------------------------
" B5 T$ b% J1 P4 H! r! dvoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,* S6 F. t1 @$ l' P$ ?
        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)* ^# k- n. t' K6 k  g* I8 q
{$ Y7 r, ?% S6 d1 A& r
    BYTE  btIDTR1[6];
, n( O2 Y0 |) P) R) J$ t8 z5 j    DWORD dwOldExceptionHook;, p- h, m$ ~9 |; \: ?% @
    const int nHookExceptionNo = 5;; t$ ?9 M; X: X- I- z" o
9 g5 J9 ^1 L! V; \0 H1 o* F, s: A& g
    BYTE  btIsIDEExist = 0;
1 V' T% r2 u3 p1 O: g* w9 F    BYTE  btIsDiskExist = 0;
6 L4 a. v5 Q' {2 ^3 ~% k    WORD  wOutDataBuf[256];
2 d1 T7 v1 e& N' }/ o5 v1 Y
% e$ X4 \8 B, ^( n2 T& g5 x: l$ U    BYTE  btIsFirst = (BYTE)bIsFirst;
$ K( d+ W: p$ O. l  k! ]4 f2 b( l5 w" G3 T, c3 t
    const BYTE btBit00 = 0x01;  x) I2 }' a) q. H6 ^3 S  T) K
    // const BYTE btBit02 = 0x04;
* T5 {% A6 z0 G/ i6 z" W" a    const BYTE btBit06 = 0x40;7 n( ?" q! s- D, [7 _6 y
    const BYTE btBit07 = 0x80;8 h, r0 I6 s+ {& e, }( c
    // const BYTE btERR  = btBit00;
8 e8 |% N( _4 G0 d6 h1 b+ _! q    const BYTE btBusy = btBit07;
# m* Y; d; L; e- d- P- \    const BYTE btAtaCmd   = 0xEC;
" s: `. J+ z! |- h    const BYTE btAtapiCmd = 0xA1;
! ?8 {' w0 ?; @2 H4 b' Y% @: H/ r7 v2 d
    __asm
% w' @1 R) U' `% f5 j    {
" D- H; U2 D! I' q% ]        // 必须先执行这条语句
8 M0 T& ?; \, x        JMP EnterRing0$ l! {* [. c+ b

& @) A* Q, U: q/ N4 ^        // 定义过程
) T7 ]( Z; c6 o/ J5 }4 Y        // 等待IDE设备直到其不为忙为止& H. c4 ]6 W) z, J, j
        WaitWhileBusy proc
/ A( h9 q" u/ F' K9 ~
5 V. W* r* M/ u! ^  L9 L        MOV  EBX, 100000
; `0 z  s) r3 I        MOV  DX, dwBaseAddress; ]6 H7 ^8 y9 O6 c6 `2 A
        ADD  DX, 7% n- F) N3 r& U7 \+ ^

; {* I- _. R2 q2 e7 \        LoopWhileBusy:
! b% H' w/ a' m7 M. t5 E. v% }2 G6 }- _9 Z  R) F- w8 S. b
        DEC  EBX
9 n. i' t3 [3 }5 i. F4 H        CMP  EBX, 0/ W3 _4 W8 a3 L' t/ Y# P
        JZ   Timeout
: p# g  E  R( g! C% n        in   AL, DX+ ~/ _) x$ F. \; Y* @4 }
        TEST AL, btBusy
9 y  O. M/ m/ E6 j, r4 Z/ V        JNZ  LoopWhileBusy
" k& u) r# r* r, h4 ~        JMP  DriveReady" v5 e3 d5 M. Q
; |2 c/ F/ A8 M, P& k$ s
        // 超时,直接退出' J6 }, B6 Q% W9 k! O5 |
        Timeout:
3 A) h! X! L2 A        JMP  LeaveRing0/ p1 O* c+ z* B! H
        DriveReady:/ d! ?# Z! Z  W/ \7 q: D8 R9 Q- Y# k
        RET
9 B8 ]! [( w1 d) h+ {, e3 d        ENDP   // End of WaitWhileBusy Procedure% K4 e' }9 Y, Y+ y+ Z$ K3 m
; U: _! N' z" o7 F, {9 y- _
        // 设置主盘和从盘标志* ^+ O! d/ h+ u0 u! S5 I
        SelectDevice proc  X4 M! i8 c% B& l  H
' G6 L! q1 k% m8 V5 S
        MOV  DX, dwBaseAddress$ X  R# z/ i+ \6 @& W
        ADD  DX, 6
6 ^6 p+ r# P) w        MOV  AL, btMasterSlave2 e+ r" [# O# i, d  o

( |9 V$ {1 N9 i$ r0 T! H        out  DX, AL7 o6 L* C3 F. L9 D5 o9 _
        RET8 d/ i8 K& _& L( `, _' s: E

' M7 z9 ]% m* y6 W        ENDP  // End of SelectDevice Procedure
- X% Q9 _0 B' y; J) _  t. y. n8 g3 p- g+ E3 y& C" T( O3 t! }9 j. @3 y2 M
        // 向IDE设备发送存取指令+ u; ?6 G  w3 n) S9 I2 j1 J5 z+ x
        SendCmd proc
$ W( ]  f$ \9 x9 g
, P, i" w3 N+ R3 L2 i        MOV DX, dwBaseAddress
. d6 h  I( S" c( O        ADD DX, 7
7 X, s. W& O! v        MOV AL, BL // BL是主从盘标识,在过程外设置4 X/ `$ m) U7 h# q7 u  Q
        out DX, AL
8 v2 h5 ~; w: Y9 y4 g        RET" `$ q& O7 O# G. J6 U: X; ^  [
        ENDP  // End of SendCmd Procedure" L" c1 f& [  `5 ?1 [2 J+ v
1 v) q8 x1 P( b* j
        // Ring0代码
6 @: G* _7 T& Y+ k4 O        Ring0Proc:# ^1 e/ C: r2 e+ k& d
        PUSHAD3 v& @" U2 p4 g& P7 C% T& E6 Q0 C
        // 查询IDE设备是否存在
; |3 z: ]7 r: R. l6 T        MOV DX, dwBaseAddress
# r; K2 o9 ]; p5 R7 s8 a        ADD DX, 7
9 f4 A7 Z. _& n: v+ ?9 d        in  AL,DX
! j- [; o& G- `' H& R
, d, |/ [! B1 C( w+ N/ m        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回$ T! E: }7 {1 m( U
        CMP AL,0xFF# Z9 |5 o( V  d& _  H5 N
        JZ  LeaveRing00 \; W, u0 l3 g2 e* t; V9 a+ f* B; ]
        CMP AL, 0x7F' M4 ^! |* {" [5 N9 o% `5 [. r
        JZ  LeaveRing0
! D1 i) P; z1 u# X, F: ]3 I% ]  E, [- a2 _7 l) i7 w' N/ Z
        // 设置IDE设备存在标志
2 f: P7 S9 p; t( }/ i2 {$ \        MOV btIsIDEExist, 16 Q4 Z# G# Q3 G1 i0 D4 k+ i

+ |( Y# l) N8 X& y        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
0 q$ X$ X* ?. A        CALL WaitWhileBusy. I+ n7 g+ b# m7 h( z
        CALL SelectDevice% @- P* r) K) D: Q+ ?

# ^# z5 V4 `* q        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
8 g4 V% g  t# L$ e* h: |3 n  S- r        CMP  btIsFirst, 13 j- n4 V" w* n+ s. F
        JZ   LeaveRing0. _- p1 U7 r7 a4 L

, v; R3 P7 n5 s. e6 L5 {        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
; R2 J& B" N' j# M        CALL WaitWhileBusy
5 J+ x- ?- r+ @2 X, v
- K5 v$ \: q, R4 H7 D( |        // AL的值等于cBit06时,不存在驱动器,直接返回
- b" z6 v" Y& c' j; I5 Z        TEST AL, btBit06
+ P0 G5 w. o0 w' ?        JZ   LeaveRing0
6 K( `' j, n, C* L+ J, c) |0 Y" E% i- X! f8 q3 e/ q/ V
        // 设置驱动器存在标志
. l% v' L. r5 w; _. d        MOV  btIsDiskExist, 1
) D5 x( \4 d- y! u0 b1 C; r. [% X( q" D  `" {* U7 q
        // 发送存取端口命令
  G$ n0 _  R- u& j% C        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
, |% P% }2 N% W1 }" |& ^9 _        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令: C! ^; t' {- x: f/ Z2 [8 S) @8 q
        CALL WaitWhileBusy7 N6 X6 ~; z* a1 @8 v  ~; K. ]
        CALL SelectDevice    // 设置主从盘标识
( J/ u* K" G# W: U* S  a. t        MOV  BL, btAtaCmd      // 发送读取命令+ w1 ]: a; X$ J! _1 Q: d4 P. y
        CALL SendCmd2 p1 E' ^  M) E4 q& p  y
        CALL WaitWhileBusy7 W0 t! i: Q) i8 ^8 y& T
( S4 }. R7 i% V# k# `; J4 D
        // 检查是否出错  l. f, {' t! H# c3 o! `2 c
        MOV  DX, dwBaseAddress
+ D" e+ m/ ?  j4 o# P        ADD  DX, 7
- s( R2 a/ F6 w- Q1 o  j  r* k0 U" h! z! \2 z, h1 @  d6 M* R
        in   AL, DX
& }6 L1 t' U9 y5 R" R. K' X/ s0 D# q  H( T% B% I9 @$ e
        TEST AL, btBit00: ~: t+ ?8 _' Q% T5 k
        JZ   RetrieveInfo   // 没有错误时则读数据: M" s2 f: K6 w5 ^' {& h
* r; G' n; ^( T  y
        // 如果出错,则进一步尝试使用ATAPI设备命令  W+ \5 E: k$ E
        CALL WaitWhileBusy
+ i3 O8 U7 S7 K% \$ U; ^        CALL SelectDevice# @, z8 t! @# @. p5 m+ x
        MOV  BL, btAtapiCmd/ R1 R  Q# }3 Z5 |& T1 E
        CALL SendCmd
5 m6 ?' M/ e9 `0 C2 s# g        CALL WaitWhileBusy+ F  S9 }4 u! q& c3 {/ W5 p, m

& q- t9 v, ?# u* `        // 检查是否还出错
( P$ i% U5 R' S9 ^/ v5 ?        MOV  DX, dwBaseAddress
, S1 U1 C5 W" P; e2 |( {        ADD  DX, 76 [( R0 _" Q$ X/ B  j+ Z7 X
        in   AL, DX# A$ `; h: }3 ~6 j+ ^# X
        TEST AL, btBit002 W5 l# q0 X& |. O' [, i- T8 p6 h
        JZ   RetrieveInfo   // 没有错误时则读数据
; Q! X  k1 G$ [' [        JMP  LeaveRing0     // 如果还是出错,直接返回6 D2 {9 f% C+ W0 \
- h7 q" X7 ~* ]3 Z! E; J; W/ V  e
        // 读取数据
, Q& I* I5 |! T/ x  T        RetrieveInfo:/ B1 |) ^/ \2 M* ?( b8 |& U7 Q% G9 [
! U: n5 p( U3 b
        LEA  EDI, wOutDataBuf0 G! Y4 p" u' L$ G( b2 _
        MOV  ECX, 256& f2 g- L5 w5 g4 K3 n4 R, ?  _. l
        MOV  DX, dwBaseAddress
2 v* O+ m' \, _; h  r% p        CLD
& N' J- v4 j# P
* x8 N8 b' y( a* B% B        REP  INSW
9 b0 y# V' M  L! w7 x1 P0 v3 f7 B: G
        // 退出Ring0代码
0 D  O( i/ j* f5 z  D' M7 P4 _        LeaveRing0:
$ `0 e% A+ D) ~4 ?* E: C8 @' t& t$ k2 Y7 V) S& W
        POPAD
9 V4 ?" B' R' h. d/ Z0 u6 h: J# A6 n        IRETD
8 J/ H2 Z  z9 J4 }% `# a, y, @
: S( C0 u8 Z5 D3 F* G* D7 ^  i        // 激活Ring0代码/ o  M' i$ M7 X% _: k$ v
        EnterRing0:' U% @( C. D' F- u

* e7 y. S. N1 c0 g0 }: E        // 修改中断门
! U. M, x1 F- R# l+ K: S3 d3 l        SIDT FWORD PTR btIDTR1% U+ J- C* b! z; k2 ?0 a) O9 H
        MOV EAX, DWORD PTR btIDTR1 + 02h
1 s6 J: {: z; i* q; c* v        ADD EAX, nHookExceptionNo * 08h + 04h
, S/ Y/ Q3 {8 v% v% e        CLI
. s) |- I- t( v& @9 I
" u0 J$ \' t. I5 C; J8 c        // 保存原异常处理例程入口
, {) }2 F4 a7 Y        MOV ECX, DWORD PTR [EAX]  I: f; K" p6 ?9 T" {, V8 `
        MOV CX, WORD PTR [EAX-04h]
1 F& Q$ W, C& B1 y: q9 C        MOV dwOldExceptionHook, ECX" B+ a! m. A$ f9 N4 B6 ?

- q% c- [& f; m0 V; a# x* T        // 指定新入口
3 j) W: B/ r4 Q$ S        LEA EBX, Ring0Proc' J6 n  D+ s) {5 h! I: Y* i
        MOV WORD PTR [EAX-04h],BX- ~) g  \6 r, `! I) r( ^
        SHR EBX, 10h( E9 h5 g/ D- W4 h4 X
        MOV WORD PTR[EAX+02h], BX
: v0 \" {1 K( L; b2 V( \$ A! D' V# Z! N. \% f: d- R/ ~$ N
        // 激活Ring0代码
( U) ?. a5 z4 L5 q        INT nHookExceptionNo- X1 R' A9 ~2 v. w$ z  ?
% c( U+ v$ [5 ^3 _& c8 s  y7 |
        // 复原入口6 p0 h6 q4 A+ p3 v# J# {
        MOV ECX,dwOldExceptionHook
( S4 k3 B5 f5 K$ H        MOV WORD PTR[EAX-04h], CX
/ E! O* Q- Q8 G) z0 H( Z        SHR ECX,10h3 c5 ~  H- c1 w8 X
        MOV WORD PTR[EAX+02h], CX" E3 D; d% j, L3 V* j6 B* g
        STI
7 X) U: N8 Y3 b, s    }
8 a2 |9 `/ H) c    if(!bIsFirst); d5 q" a0 u7 h5 A8 k# X. p
    {
! x( g2 t: D/ u5 C        bIsIDEExist  = (bool)btIsIDEExist;) H/ o, E9 J- ?4 \0 |7 C2 E. f  Q
        bIsDiskExist = (bool)btIsDiskExist;# D! Q7 ?/ v* T7 |; P
        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
4 L; d* U) K8 H; p" q4 U; A    }
' t/ E* D$ T( |}: q7 Z' U. G3 z3 o5 H0 q5 A7 P& y
//---------------------------------------------------------------------------
/ d% b# \# n; l* v// 调用方法:
  R8 [& N7 x9 M2 v- m1 O! v6 @9 P/ Tvoid __fastcall TForm1::Button1Click(TObject *Sender)( U7 z. Q+ T  K9 \" {
{
5 Q& X7 m/ k7 O4 g8 X% S+ y    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
; d2 o$ e2 w/ s8 p+ A# D( T- [}
0 x! q7 R! ^3 X
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-5-19 10:44 , Processed in 0.028897 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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