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

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

[复制链接]
发表于 2008-1-6 19:59:06 | 显示全部楼层 |阅读模式
代码框架,你所要做的仅是修改WQL语句,具体可看MSDN。以下代码为简介起见,一次返回所有的CPUID或硬盘厂商系列号
! B9 x/ ^0 o4 R0 i; q- U- a) {3 [. h
  1. ( i7 h8 J! z$ e8 W
  2. #include "StdAfx.h"
    - ^( ~: Y6 x3 h6 t% m4 A+ \
  3. #include ".\puiddisk.h"* M+ l- e- u  o: |! G9 h  e
  4. #define _WIN32_DCOM5 |* `' O7 `- O9 r7 G0 e5 L
  5. #include <iostream>& v8 e% \9 o8 i. T
  6. using namespace std;
    & Q" B9 T. w  E4 H& K$ C$ ~
  7. #include <comdef.h>) V; F0 r! ^, L# h3 a
  8. #include <Wbemidl.h>
    6 s; N" I) w0 V( b9 g

  9. 0 o& }% l: {: |3 R# U
  10. # pragma comment(lib, "wbemuuid.lib")
    - A" D3 J& g/ ]& k5 s, g
  11. CpuIDDisk::CpuIDDisk(void)9 ]7 O& f8 w; \. e4 T) [' V
  12. {
    * F' u- d9 V: T  X6 V: }
  13.     GetInfomation();
    5 N+ l' N& l5 i3 Q! w8 y
  14. }' q1 H& z# \, c& _  ^' f/ _
  15. 7 u$ e# n' }5 m
  16. CpuIDDisk::~CpuIDDisk(void)( f# g, q, ^" ?+ w2 F
  17. {3 U" j" y( ^' E( i
  18. }
    - o: A; P: H! |6 J
  19. int CpuIDDisk::GetInfomation(void)
    + Y0 y5 e3 J. P9 ]4 j
  20. {
    ! K* a! F0 b% {: I) z
  21.     HRESULT hres;# h" W% |; n7 M7 d4 Z) q
  22.     //步骤1:不是必须的,COM只须也只能初始化一次
    : {0 [4 B! e: Q
  23.      hres =  CoInitializeEx(0, COINIT_MULTITHREADED );
    , C) X' @( C/ i
  24.     if (FAILED(hres))
    9 S' i# F! C& d& C* c9 @+ J) v4 q7 y
  25.     {' B( H" x3 ^) \( q
  26.         return 1; //初始化COM异常:注意,COM只须也只能初始化一次/ [6 Z7 [( V- C
  27.     }
    9 y/ i( ^1 o7 G# s. x" e+ b1 k
  28.     //步骤2:不是必须的,COM只须也只能设置一次
    " L9 [7 y! J; ^9 n& k6 l2 R
  29.     //Set general COM security levels
    / d- X" C6 Y4 U; _5 l/ B
  30.     hres =  CoInitializeSecurity(
    6 B( s, l, H# u' g+ d( Y$ I- |/ u
  31.         NULL,   _" Q+ Y6 D( e5 I4 {  l
  32.         -1,                          // COM authentication. \  N. a0 J3 }$ z% H8 q& q: _
  33.         NULL,                        // Authentication services
    2 ^4 A; S4 T7 s! ?. r' s
  34.         NULL,                        // Reserved
    5 [; }$ _- I" ~5 E8 c3 m
  35.         RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication 8 _' Z- R  m. q  R# f" d4 P+ j# ^
  36.         RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  5 q- D2 ]9 h. m. a; K
  37.         NULL,                        // Authentication info
    1 _) d# `7 i/ o/ V4 h4 @2 @2 r
  38.         EOAC_NONE,                   // Additional capabilities
    " A8 S( @' a' o" W
  39.         NULL                         // Reserved( b5 y0 E: e" J- t
  40.         );0 d5 Y& S2 W6 I8 `4 R
  41.                       # x3 N# N) y3 ^# S* Z& D6 ]
  42.     if (FAILED(hres))* Q) m' _+ G6 i
  43.     {
    ' _( n5 h( \# d- N" N9 S
  44.         CoUninitialize();. i' j+ |  V  f; }  A- y9 Z& v
  45.         return 1;                    // Program has failed.
    - i4 V2 X/ m: b* ^* T
  46.     }& t+ a# o" h, j$ l
  47.     ' g" }) a" h- U9 {
  48.     //以上不是必须的,若已有“::COMInit();”,则要跳过. B' K/ ^* e8 U& k3 r2 Q  \2 R
  49.     //步骤3: Obtain the initial locator to WMI
    $ \, u+ M7 m4 a% p% i( v; n
  50.     IWbemLocator *pLoc = NULL;' h- f! b: Y: v& ]7 n: w
  51.     hres = CoCreateInstance(
    & P, V4 R# O5 J/ Z, s
  52.         CLSID_WbemLocator,             $ ?+ e/ t( e6 i$ S8 e7 x4 Z
  53.         0,
    " h, j. y3 t& i5 A
  54.         CLSCTX_INPROC_SERVER, , R' Q6 z0 s4 {% u+ C2 o+ v
  55.         IID_IWbemLocator, (LPVOID *) &pLoc);9 Y6 B/ w2 R% _- w7 A; y

  56. 4 [. @  X$ ?" e; I. W8 N- {
  57.     if (FAILED(hres))+ x" y( b; A+ U1 _
  58.     {* j' R: S' l% R% n4 d' e! V/ ?5 _6 C
  59.         CoUninitialize();! Q7 m' O6 C% _, h& W! q
  60.         return 1;//Failed to create IWbemLocator object( [9 g' T7 x$ N% {: C  x
  61.     }
    : T* F  U2 s& u* Q: b+ m
  62. , V# W7 R5 x8 y: o, b
  63.     //步骤4:Connect to WMI through the IWbemLocator::ConnectServer method  k8 S+ \3 m) p' P" k& X$ U
  64.     IWbemServices *pSvc = NULL;
    * h: U" r: B; p* E* F. \
  65.     hres = pLoc->ConnectServer(3 v- |% f% Q* X7 k  W3 J
  66.          _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace" v: W  g- ^- `" @
  67.          NULL,                    // User name. NULL = current user' |4 b! x  i7 p0 W5 O1 y
  68.          NULL,                    // User password. NULL = current
    2 I- x7 ~+ ~% v; T1 _5 e" m. b3 p
  69.          0,                       // Locale. NULL indicates current- D- V$ ^: G7 X) p9 s
  70.          NULL,                    // Security flags.
    / E, w% l, L2 x! {
  71.          0,                       // Authority (e.g. Kerberos)
    4 O: {' B  b4 p9 H+ E
  72.          0,                       // Context object % r, `. \% c. I! k9 G1 D
  73.          &pSvc                    // pointer to IWbemServices proxy% Y0 E; I- ~" a- M
  74.          );
    ' M& t2 w/ U0 R7 q- x
  75.    
    : M! T  q/ z; \# M, C; Q# V
  76.     if (FAILED(hres))( |: }5 p' W  {% F
  77.     {
    0 ^4 D  o% Z- h/ f# {! V9 Z
  78.         pLoc->Release();     
    5 G8 _9 S+ w/ M$ }
  79.         CoUninitialize();5 w/ V2 W8 R- H. T* Q
  80.         return 1;                // Program has failed.
    ' [* s* J% ?6 g
  81.     }
    * Z+ b, Z; i' y, Y5 M
  82.     // 步骤5: Set security levels on the proxy
    1 O/ Y6 D' V: z  P+ _" n
  83.     hres = CoSetProxyBlanket(# t. i/ I  v0 `) I4 e
  84.        pSvc,                        // Indicates the proxy to set2 r$ z( n4 g* P- [( a* _" H" a
  85.        RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx4 m/ D# ?3 E. l( j
  86.        RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx
    * F5 ~* D% o" a7 c1 ^
  87.        NULL,                        // Server principal name
    6 j4 Q1 v7 c* J1 B! P% _: B9 ~
  88.        RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx
    4 i" u6 a2 N. j
  89.        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx2 T6 r9 k6 N0 D" e( R) b
  90.        NULL,                        // client identity$ C' J% H0 F. V
  91.        EOAC_NONE                    // proxy capabilities
    9 R7 z: D3 ~3 @& o: }
  92.     );
    / |9 T/ @$ P9 H- L  k( ^

  93. + o6 }" c% L6 L! @, G
  94.     if (FAILED(hres))! H. E( l+ ?$ y; N- H$ h7 u
  95.     {: M% A3 X1 _$ ?+ D
  96.         pSvc->Release();
    8 L5 U; ]% E" l' o
  97.         pLoc->Release();     
    : v: Y$ |! Y* O# [+ t
  98.         CoUninitialize();
    9 h5 A: N1 J& y6 v3 M% C
  99.         return 1;
    $ E0 A) H9 o; `! e/ V. x/ F
  100.     }
    0 |3 j8 \3 k% I
  101. , ~: e0 E- ?0 a% O
  102.     // 步骤6:Use the IWbemServices pointer to make requests of WMI ----
    ) J. \- A: O" A* x. B
  103.     IEnumWbemClassObject* pEnumerator = NULL;
    ! G; z# c! w; U
  104.     //计算CPUID% x2 f, o7 `3 H. l8 R
  105.     hres = pSvc->ExecQuery(  K2 _* [9 n6 H( [0 H* t4 e" p# h
  106.         bstr_t("WQL"),
    6 s# y1 X- _; C* j8 K0 V' M
  107.         bstr_t("SELECT * FROM Win32_Processor"),//Win32_OperatingSystem
    8 @3 X& [8 S+ F5 Q5 M5 `9 p$ Q9 p
  108.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 7 t+ X2 Y5 j$ ~/ P
  109.         NULL,
    9 J! t' D% u, s& a+ S0 h* P
  110.         &pEnumerator);
    * m2 ]6 T) E% W
  111.     7 }" `! f8 e6 F+ z
  112.     if (FAILED(hres))
    ' k. c, a$ |0 p8 k5 r. ]
  113.     {3 d$ v1 i! O- b5 I
  114.         pSvc->Release();/ Y" H7 A4 K4 V. D; A! g/ v
  115.         pLoc->Release();
    1 h2 o: H; n/ o6 F
  116.         CoUninitialize();
    ) J' y: y- l3 y/ ?" y& _: ^: ~
  117.         return 1;: t7 b0 B) I% ?" w8 y- U
  118.     }
    / O* t, O7 q% I$ G
  119.     // 步骤7:Get the data from the query
    * {: B6 P; z  {+ f9 t
  120.     IWbemClassObject *pclsObj;
    $ p) B) Q+ D5 R. O/ w# F# q" H
  121.     ULONG uReturn = 0;
    6 n9 @% l4 }/ t4 f: H/ F. r: {
  122.     while (pEnumerator)
    0 T. h, ~  t5 r
  123.     {
    1 f7 ^, m5 O: i, q. q% g0 S
  124.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
    8 R+ W+ O- N0 k+ K4 |9 [
  125.             &pclsObj, &uReturn);
    ! ~: J: J8 y) {5 X$ ^

  126. " h2 C& S* f* n
  127.         if(0 == uReturn)7 ]2 \" M/ ]- ~5 z+ \0 S, C
  128.         {- o/ T* |1 i& I- ~5 T) ~  B
  129.             break;+ w4 x$ ~/ A: Q
  130.         }
    1 B* `% Y( M0 z. H6 t+ \1 u% I
  131.         VARIANT vtProp;" A" g: ]0 L8 j1 e& I- e
  132.         VariantInit(&vtProp);& r3 Z  b1 d6 ~( @
  133.         hr = pclsObj->Get(L"ProcessorId", 0, &vtProp, 0, 0);/ Z( U( g& t9 D7 Q
  134.         strProcessID=_com_util::ConvertBSTRToString(vtProp.bstrVal);//strProcessID:类级变量
    9 l$ X9 |6 c8 b/ ?
  135.     }- }3 \( O: a3 H& q7 T

  136.   _  P3 A) P& L, a
  137.     //计算硬盘系列号
    + {* p5 ?9 j. y! T/ j
  138.     hres = pSvc->ExecQuery(1 [+ X0 g5 F4 f2 `" G
  139.         bstr_t("WQL"), , D6 d) G/ g  T! C1 y$ u
  140.         bstr_t("SELECT * FROM Win32_DiskDrive"),
    ' D& E- W1 s% n  T
  141.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, - ]" H" X* G6 G& q
  142.         NULL,
    + X3 U: H# T- B. x- |
  143.         &pEnumerator);
    # M% d+ [( O. [3 u

  144. 7 {' d$ ~6 j$ i
  145.     if (FAILED(hres))
    6 n; P/ g# ~+ u$ k- A: N) W* U
  146.     {
    5 L4 k4 J! A7 k7 h2 w
  147.         pSvc->Release();
    ' d  M% L! n3 v- U
  148.         pLoc->Release();
    5 s& J' t$ R  c1 B! U1 y
  149.         CoUninitialize();" \/ E) Y% Z. m1 v
  150.         return 1;
    3 A: ~6 |9 h9 ?7 Y, Y6 Z
  151.     }0 n  P6 o. n7 r, l8 V; u' j
  152.     while (pEnumerator)6 m$ I2 _+ G  R/ z8 k/ m+ J- W8 y' \$ ?
  153.     {
    5 z: L5 I- G" `3 u4 |6 e
  154.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
    0 \9 J  \2 p3 \3 C1 u: P
  155.             &pclsObj, &uReturn);# h, f  q) s& B) o
  156. $ |- J) F6 y* L; u: @% S, p
  157.         if(0 == uReturn)
    7 {. y/ `1 i; U
  158.         {
    6 ~$ c! m9 Q$ @( Q5 {+ _; Z. M
  159.             break;
    . u. z) h& l8 D1 S9 d3 _: P; e
  160.         }. U: |: B$ w8 j' r

  161. 5 x, T! m8 Q4 V* t5 a
  162.         VARIANT vtProp;
    / x. J6 g! s' F! \, ~$ P; t
  163.         VariantInit(&vtProp);& |: {- d; u  z8 H) z) E' C
  164.         hr = pclsObj->Get(L"PNPDeviceID", 0, &vtProp, 0, 0);
    + \/ F6 T; o8 G/ v5 z# h. M$ x, I
  165.     strDisk=_com_util::ConvertBSTRToString(vtProp.bstrVal);; h/ v- x7 }! a& U) U
  166.     }
    0 Z6 D& V' b$ S4 d$ d! g4 n

  167. + E6 t7 L/ n0 J& ]
  168.     pSvc->Release();
    6 e( n' E; J, U9 O; j7 Z
  169.     pLoc->Release();
    # n4 d  ~# _- _' M0 l; d
  170.     pEnumerator->Release();% r* ?% U4 L: c& {6 Z, i. i" s- _$ p/ Q! K
  171.     pclsObj->Release();
    ; d: I  @( R1 e* P' p. U$ r6 g" Y
  172.     CoUninitialize();# v1 m/ |6 q& |, S
  173. 6 n: Q! _9 Y$ K. h0 z
  174.     return 0;   : n1 a+ m0 ?7 U( M2 c0 O
  175. }+ o: T/ x2 f: D8 O( X& t
复制代码
 楼主| 发表于 2010-10-11 19:21:05 | 显示全部楼层
本文代码经ccrun(老妖)在Win2k下试验成功.8 p+ i' b. C' \6 }1 K* q2 H  P* P

4 j: J7 O2 J; V) ?#include <WinIOCtl.h>2 G# a9 b( \& I6 r3 u% [: O* ]
#include <stdio.h>  ]7 D0 d- l% F" G; Y

  r& D3 R  }5 M+ R#pragma inline' }& z4 s9 s( r# g" m. Y) f6 x
//---------------------------------------------------------------------------
3 E' G, g# `- y, ~8 _8 x// IDE NT/2000/XP专用变量. C" V: `& @8 H. n, h% |
#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS/ g$ |, b6 Z  R0 n, m
#define DFP_GET_VERSION         SMART_GET_VERSION
: d% z; x9 e- B- i#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
  r5 m+ L& o, P#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
# l) E/ \) m8 k8 \' h* J
9 v' S: Z; J' B+ }& b5 h8 h) F$ rconst WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令( H; t" E9 [; u* q2 L3 v7 ]3 d) S
const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令: w2 @% k+ b; O. s3 T6 H

$ k, y3 \: A0 m- t$ P7 Q' @2 bconst int MAX_IDE_DRIVES = 4;
# D* M  y; ~( T' {
6 ~) t2 u3 c2 Y, n' n: u; J% H# r. f// SCSI专用变量4 B5 W1 Z! A! I) e
const DWORD FILE_DEVICE_SCSI             = 0x0000001B;
' G6 W6 p; @9 @const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);8 Z6 w, Q% ~' }  Y& \$ [. W: Y
const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
, ]  A2 p2 S7 _: W9 J6 Uconst DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;; a9 q& b) `  t( ]# ~; k4 v- M
0 w7 l, H0 K! F0 `9 G5 Z4 x9 R
typedef struct _SRB_IO_CONTROL
& y" M9 I* v) z* k{/ T! W* j9 s  I1 }
    ULONG HeaderLength;" h4 ]- \* ]3 n- ]3 s3 e
    UCHAR Signature[8];
0 C6 E) O4 P9 {    ULONG Timeout;
' \+ ?, w+ N3 u/ S    ULONG ControlCode;: Y2 c. k: f1 z1 K2 I+ a4 s
    ULONG ReturnCode;6 y, |0 n( w9 U2 _
    ULONG Length;
9 M- t: I9 Q: y1 d' P$ ^9 B* ^, x}SRB_IO_CONTROL, *PSRB_IO_CONTROL;: L, S5 h9 K6 j8 Z0 z* y7 t; F
. Z( W, D3 d( H' _
// 读取的主函数4 R0 X- A; M3 @8 p2 X/ }) ]" D( }
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);7 y. [. T" p5 ~" W7 N/ Z2 @4 ~
& d9 k% A* r8 W) I, }+ {1 d
// 辅助函数
0 P! \; J4 K! _# C: e% g" k  lchar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);9 w& A4 S6 [0 i8 ^; t6 N, _: M. p. C
// NT/2000/XP函数/ Z. b  q+ M; n. |7 |1 H8 [( o
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
0 [0 e2 H* H- R' O4 S4 |bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
. {- p$ Q0 }) ~! l/ {! `        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
, V7 y+ J+ e* G! N        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
, R3 H, X7 }1 I, A// Windows 9X函数- ?. c# }' ]7 j) Y7 u" R, f
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);! J/ @  P. k( T  M4 K5 a2 K% n1 m
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,5 X6 n4 R1 n/ G/ B
        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
( j1 U& }% ?4 F2 B# f$ a! R- R( |7 L  F9 S; d3 a
// SCSI读取函数(for NT/2000/XP)
& R- ]* ~1 Y% hString __fastcall ReadIDEDriveAsScsiDriveOnNT();0 A- C% N6 h5 i/ I# L: z  j
//---------------------------------------------------------------------------; ?' a; t+ `9 a' j5 Z, b
// ReadPhysicalDrive
) {! P+ z+ S7 W% ivoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)) g$ X4 [' v; `9 e$ _2 U) c+ j
{
1 B  j! H9 d& r+ Z& N( v" M1 h/ E    switch(Win32Platform)
; e& C9 n/ u) e* |' Y2 S    {( Z% J* L% A* B6 m* b  I& E  Y
        case VER_PLATFORM_WIN32_WINDOWS:2 R# ?: i  T  p; T
            ReadPhysicalDriveOnW9X(pSerList, pModeList);
* K+ Q) S- Y" ^3 Y0 n            break;1 O# {! G5 w6 i  e# K1 d
        case VER_PLATFORM_WIN32_NT:
! J0 o- ?+ r8 |, }, z& o            ReadPhysicalDriveOnNT(pSerList, pModeList);
' x4 `, l( H4 y: M            break;- s5 b4 |1 a8 [
        default:
; x% g1 U$ d" v! a( g" D" A0 a$ H            break;) z2 Z  a. [7 G" k9 s; A2 d. v
    }
1 A8 }; C: ~2 d* `}! s5 y' D, B* t2 Y; Z( ?  J
//---------------------------------------------------------------------------2 n7 G3 e% u- P- a2 z2 o
// ConvertToString
2 C9 }+ c$ ^  S1 P, S& O) V/ @char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)- Z0 ]2 D+ M! t' ?8 M
{
" s9 r8 F+ M! j4 A+ `    static char szResBuf[1024];/ l, m" A9 u. f2 L+ n0 |
    int nIndex = 0;" X+ N  A3 ]5 M8 |; d; j1 W
    int nPosition = 0;
( S- S( g$ \4 J1 m. q- n
! ^0 L4 y; T$ }2 Z) s* J  \    // Each integer has two characters stored in it backwards
- f  q& C& Y3 y* t    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)5 @5 n& {9 O" [; O1 m
    {
, M0 o" k# c* l, b9 @        // Get high BYTE for 1st character
% Q! E9 X, P$ v1 I( i; t/ U        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);# M( G) X/ r, I8 E
        nPosition++;  {, T8 p$ g3 _$ A) z: r

/ I- `1 H9 |/ r) y- Y4 d" g5 X        // Get low BYTE for 2nd character5 N! f( f' c. l) _
        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);' z/ b8 o5 Q3 L6 f9 T
        nPosition++;
2 s2 w5 R1 d; {& Y" T    }. n/ X) h3 Y0 w+ B

& @3 ]. W: q( L  }    // End the string$ {5 u6 `8 T+ u5 c, l6 ]( |
    szResBuf[nPosition] = '\0';: B6 }- e( h5 l9 Y

$ B/ W3 |8 Q8 s9 m2 F! c$ D: _; V    // Cut off the trailing blanks
* S* B( ^* U) d, }: X! [$ E    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)# i9 t0 p0 p6 V& W% W
        szResBuf[nIndex] = '\0';+ W& k/ p' M, M
- h, D. M; u7 l+ X$ j0 j9 S8 d
    return szResBuf;
$ ~" y8 n; d3 N0 b- g5 A}
) M/ C/ h# F' H( r. J//---------------------------------------------------------------------------: U! m. ^4 s6 Z1 f3 P' {
// Winndows NT4/2000/XP 代码
/ K: y5 Q/ ^) X) }! h//---------------------------------------------------------------------------
; g4 Z1 f+ ?# |; s- x// ReadPhysicalDriveOnNT
( o: ?# z3 F% s' Hvoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
! Q9 Z& d, `% s4 a7 Z3 }4 F{, D5 @8 \. Y7 ~, R6 C+ Y- q
    // 输出参数* D' s$ K1 N& k) C6 z, k
    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
/ z; L) R& \& ]+ T8 t7 y5 z$ W# g6 J. N" }; R% }# C) r, ^
    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)* N1 q1 _5 Q; K3 u* B4 T
    {
, z+ ^2 u) e' ]/ f' h! G6 y- a        HANDLE hPhysicalDriveIOCTL;
/ K) n# f4 k6 |# J* ?        char szDriveName[32];
9 s4 N3 b5 y4 K4 L1 P8 X3 a+ b1 }3 [2 v) h" E
        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
! i2 H) P0 Z4 M% J        hPhysicalDriveIOCTL = CreateFile(szDriveName,4 I/ R% L! I/ Z7 k- v
                        GENERIC_READ | GENERIC_WRITE,/ x( v: M* D  f9 F+ y
                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
8 o- e6 M9 u" e1 \8 e                        OPEN_EXISTING, 0, NULL);
5 y+ Z: c7 @0 ]" f8 C1 q1 Y6 H! i, v4 W" V6 X" m5 W
        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)6 N0 _4 {; V0 P' L2 {' S8 }
        {
; Y7 P. O3 I4 i; p$ L" Y            DWORD dwBytesReturned = 0;
0 y! R9 z+ [$ p# U            GETVERSIONOUTPARAMS gvopVersionParams;
! L& Z2 ^" n; n5 F( |
6 Z. M& g0 b/ R. j' v: q8 _; h            // Get the version, etc of PhysicalDrive IOCTL
4 f# x! ?! [4 S$ I( O            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
4 r- X; l4 A8 w8 _+ R& d3 }7 e7 H" c# ^0 |
            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
- ^& M5 K# D% t6 Y5 m3 e                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
" H  n+ c( K6 \! n! g/ B  C                    &dwBytesReturned, NULL))4 _7 Z6 f- `* T7 @2 h0 [. t# U% l
            {
  l- v4 O0 c, m- c' R2 k; S                continue;8 [' U) k6 X5 q2 I" S* ~
            }" T0 K' f2 h0 P+ F% o

3 ?2 D% k% o7 G1 J# |9 p            if(gvopVersionParams.bIDEDeviceMap > 0)
1 O' n. Y# M7 Z            {
- o  q) ~6 |  t! t& q9 C# f                // IDE or ATAPI IDENTIFY cmd" m5 `, b4 y- R
                BYTE btIDCmd = 0;
+ J6 t7 I: R: w- E                SENDCMDINPARAMS InParams;
2 B( o6 k2 O3 W& [                // Now, get the ID sector for all IDE devices in the system.4 z$ ^, M* [9 ~7 {7 B. V7 S, B
                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
$ _& w8 g5 W4 ]5 V1 A                // otherwise use the IDE_ATA_IDENTIFY command- g4 x: L$ }! L+ Z
                // 具体所得结果请参考头文件中的说明
0 |6 G5 Y( X/ o: V" s/ l9 Z8 _& X                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
: [2 P  Y! c  k7 ~& T' }                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
3 a* `/ g4 ^4 D                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
# L6 f8 V; [( _3 n, F* R5 s                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));1 J4 a+ I8 u2 Q7 I& Y; q% A" d

, x8 ?; ^0 x$ c- C                if(DoIdentify(hPhysicalDriveIOCTL,
* w5 }1 C: d; U. V( w. B  J2 v) a                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
! u6 i+ Y* S0 B% ^                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))# {& F0 {- D$ G
                {
8 n9 N8 w* s8 q                    DWORD dwDiskData[256];
. I& ]0 T# h+ l5 {! j, n* r' ^                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
; u6 H  H; u& G& _# N% d                    char szSerialNumber[21];
. i& G7 H8 V  `/ f1 U$ Z                    char szModelNumber[41];
7 R" b+ ?+ A- x* U' O3 j8 q
  O( t* W/ S  f7 d# M                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;& L8 F2 i- N; T+ G
                    for(int i=0; i < 256; i++)
" n+ I6 T3 Y) y, e2 x" v                        dwDiskData[i] = pIDSector[i];
8 I: ]  J7 d  V                    // 取系列号; ~; O2 E/ V8 R) ~5 k
                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
4 J4 d( X/ ~( ~, ?# K, W8 G                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));+ z, L' }& q' C# H; E: N
2 Q8 i) m6 Y7 n0 u
                    // 取模型号
$ f: r) \% D. m+ }                    ZeroMemory(szModelNumber, sizeof(szModelNumber));
% S* R2 u% f0 B6 A2 n' S, r  b4 T8 S                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));1 {$ b" @6 b; u9 k' T! M& ~
+ M/ J1 h$ L: E6 ^( n1 g/ `
                    pSerList->Add(szSerialNumber);( ^6 L3 c/ y$ T' O7 j
                    pModeList->Add(szModelNumber);# r' ~* ^3 R# l3 m
                }6 O5 y0 S; s  m6 e* M
            }
4 p+ S- x" J0 R6 y# z4 g            CloseHandle (hPhysicalDriveIOCTL);8 P$ n/ E1 J1 [, w$ T
        }5 s% s* Z- P( {) e) m( h! A
    }! B5 G2 p/ |* @' M
}+ V' k! F/ ^& r) I/ w2 b+ p4 e
//---------------------------------------------------------------------------
$ {# W' y( ^+ N3 ~// DoIdentify2 [$ q2 X" z. c
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,4 Z/ j. ~, Y. p7 _5 Z
              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
7 ~6 F$ x- u8 b& q) |3 V0 r; F) i              PDWORD pdwBytesReturned)
4 w* [- |: r8 `0 q- ?{  `# Z  E9 J+ R0 F/ U4 ~1 ^3 t
    // Set up data structures for IDENTIFY command.
4 ~. |/ z) K: J    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;. G' n) f, r8 W4 ?$ u4 ?$ X" J/ j
    pSCIP->irDriveRegs.bFeaturesReg = 0;8 H; q8 V* |1 l  z5 R4 q
    pSCIP->irDriveRegs.bSectorCountReg  = 1;
& v' W, C$ G, O# J+ }    pSCIP->irDriveRegs.bSectorNumberReg = 1;$ C9 p- k* G. u# U* Y- E* \5 Z
    pSCIP->irDriveRegs.bCylLowReg  = 0;2 t' N! |" Z6 [" P( v1 G, \/ h
    pSCIP->irDriveRegs.bCylHighReg = 0;: @  c' C- ~4 Y% O5 g1 _" ?& E2 ~* j

' x. ?6 x4 p1 B6 G    // Compute the drive number.(主盘和从盘所对应的值是不一样的)
, ?4 _+ D! p0 @( S& A    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
& L0 a- E/ ]  X
4 G+ N" J4 `: E' b    // The command can either be IDE identify or ATAPI identify.2 m0 n) X. y2 m# s* T0 L8 h
    pSCIP->irDriveRegs.bCommandReg = btIDCmd;. i9 _" Z4 O+ R, h
    pSCIP->bDriveNumber = btDriveNum;! Q/ {: F( X* b, s2 b( w
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;- K6 J( E2 R0 U7 M  n# R1 R

" g" S6 n1 \+ s# ]$ }. ?1 n/ X8 e    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
7 C% H! c0 |* F0 g5 [           (LPVOID)pSCIP,
9 q7 x: n+ F- i' c" E, H% V           sizeof(SENDCMDINPARAMS) - 1,
# H# T% r+ e. e: T0 ?9 N6 S- m           (LPVOID)pSCOP,
; p2 |8 c1 c, T4 k! a, E           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,8 M+ N$ c, ?! t
           pdwBytesReturned, NULL);- R$ q$ e. |: v
}( N: T# r$ A1 f  M
//---------------------------------------------------------------------------  p, Z: M$ j! _# ~
// Windows 95/98/ME 代码
  y! H8 f+ b) J9 ~  ]5 A//---------------------------------------------------------------------------! |; v2 @) h  H  e$ q8 I
// ReadPhysicalDriveOnW9X
, W  Q: g1 E8 B0 v8 E! {) `2 y9 S% avoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)! u0 U4 ^1 Q5 k4 X# c8 h- a6 S1 W
{
' d+ P- U6 |8 _( B3 k. D* c    WORD wOutData[256];
% s" I: u; G  q7 g' ?: a    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
& S, V2 R1 ]: s- q5 o
/ O  r7 z7 C/ [    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
3 a: M- ?8 e3 S' X8 `+ r+ s7 I    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
" m& K% b9 ?% a" x    // 避免蓝屏的出现。(期待高人能指出原因)
0 x  E% _" c  N$ M# Y8 S4 I    for(int nDrive = 0; nDrive < 8; nDrive++)
; L7 O3 _! a2 D    {4 P4 r  j+ M. G& ?6 w: M# p- d% i: P
        WORD dwBaseAddress;- v1 H1 r% J' G5 i  o% m! x
        BYTE btMasterSlave;         // Master Or Slave
% I/ Q. l) p& S7 N        bool bIsIDEExist;
: d' s4 g% C  P0 g( p' B3 m        bool IsDiskExist;9 v) ]2 p1 y( j& `$ Y& \
1 g$ k3 j0 S& B7 Q) p+ s' L
        switch(nDrive / 2)
+ d. D: v( {6 P- t        {
! ~$ c. b* o  ?            case 0: dwBaseAddress = 0x01F0; break;) q9 H  r* ?* {+ A6 o* ?' \$ y
            case 1: dwBaseAddress = 0x0170; break;5 ?8 h  y# r/ N7 B! L; w, B
            case 2: dwBaseAddress = 0x01E8; break;
9 |6 P7 C+ G# X  A1 {3 g            case 3: dwBaseAddress = 0x0168; break;
& h$ M) h4 \# j6 s; l        }% _, ]9 g2 x4 w, h, R' ?
3 A9 z8 M3 k4 \1 L* V2 z+ n
        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
) x* Q8 F7 Q6 f4 ]: U3 I. F# D
- L" V3 c- d7 E" a6 x( {4 l        // 进入Ring0
2 O% ?$ u- f$ ?1 r        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
* K- `! j% m7 Q4 C' G, X/ d9 n9 X                bIsIDEExist, IsDiskExist, wOutData);
+ [& o$ U! Q: }    }) J& l4 |3 ~' X0 t+ S

( D( I: R' |7 H  I    // 开始读取; o, r! _0 o" b7 Z8 o
    for(int nDrive = 0; nDrive < 8; nDrive++)4 K0 t) F$ k1 ]0 H6 a/ c
    {+ f, j  o' U# q; M8 `3 f/ E
        WORD dwBaseAddress;
, y0 i. Z% \( V5 d$ Q+ W) J& n        BYTE btMasterSlave;         // Master Or Slave
% F$ ?4 u- q/ N3 G2 T        bool bIsIDEExist;
( T, i! R1 \6 Y/ Z3 [7 P        bool bIsDiskExist;
' y9 T: t9 L( h* v. h7 P: e. D        switch(nDrive / 2)
& J1 u# M" ?! J8 V6 {        {& [" e& ?& U# |
            case 0: dwBaseAddress = 0x01F0; break;: o5 h# {0 ]) z' y7 a% C
            case 1: dwBaseAddress = 0x0170; break;6 k0 n7 V% o  d( h4 v# P
            case 2: dwBaseAddress = 0x01E8; break;$ A% S2 A. i( P. Y
            case 3: dwBaseAddress = 0x0168; break;
" c) w$ l6 j, A4 m        }4 ~* x/ |/ ?8 n: L# v& x- d8 c; R( L
  p& Y; v& G% N5 p  W/ F6 m
        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);% R% c# n' E3 }. e) |

- I0 M3 q5 C; a) l8 y        // 进入Ring0
' L! z# p; V( P: ~! \        bIsIDEExist  = false;
& y$ w0 M% p6 I        bIsDiskExist = false;
0 v4 w) k# u$ N, j        ZeroMemory(wOutData, sizeof(wOutData));! A$ k, o' [8 E* H6 t

, p8 R) G( K/ l* p9 W% r        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,( @/ r% g  |  c6 L6 @4 Y* b! g
                bIsIDEExist, bIsDiskExist, wOutData);" ~; D$ M+ Q) Q$ s7 {) u8 Z$ Q
( R& E' p9 C: u/ Z0 ~, d* @% R; L
        if(bIsIDEExist && bIsDiskExist)5 ]. Y0 K5 f0 c* x7 g) O
        {
4 F% `8 B  e$ m! Q            DWORD dwDiskData[256];1 s  g* Y/ `8 I" z7 `% g3 P( n+ `
            char  szSerialNumber[21];; }5 |' w+ o5 u9 p+ T9 F' @
            char  szModelNumber[41];4 S( s: V7 S8 b/ h6 L$ |

0 ~* }& Y! u3 X) P( l            for(int k=0; k < 256; k++)
  |9 Z, Q6 V+ m  a! }: S                dwDiskData[k] = wOutData[k];2 A: j4 W: k$ d4 g! @4 e

3 D$ I7 U+ A1 o- Z& ?6 h6 o            // 取系列号6 P7 ?# V3 z! G* U- u) N
            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
" t6 z- |; N; i# w& v            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
: E+ c9 }3 P' Q! ~# }6 v$ w
5 U. r, G2 I6 w" V( G            // 取模型号
4 N. ]! S& A2 g            ZeroMemory(szModelNumber, sizeof(szModelNumber));+ R: M. V0 k( X
            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
- N. g$ h/ i5 L0 U" b- i; c' J, R
            pSerList->Add(szSerialNumber);
! a& B. p: s$ i/ c            pModeList->Add(szModelNumber);
3 q% G# H. O$ E! p* x# w        }
" i) \- p  G: N$ h1 ]2 n0 M    }
" m' P, W8 Z, ?* A! F) x- n    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
: u) U" Q% r& \2 _}: p# O( E. T3 K9 ?' _
//---------------------------------------------------------------------------( z4 K7 C4 C# z) D- ], \- A
// 为防止不负责任的转载者,在此注明原出处信息,请见谅。" N) ~( P7 [5 M' |- S1 W
// 资料收集整理:ccrun(老妖),欢迎光临C++Builder研究: http://www.ccrun.com+ l' }8 o- C9 y$ v( _5 K
//---------------------------------------------------------------------------
( v6 @5 F- r8 Z( H  J4 n; r' c, R( E// ReadPhysicalDriveOnW9X_Ring0()
* \- V2 M' J) w% K- ?//$ x/ M5 R+ s2 ^/ m5 Q1 n( f/ c. g
// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h4 A+ b% ]( Z$ d* B3 g
// btMasterSlave = Master(0xA0) Or Slave(0xB0)- z' l5 _# Y/ w9 p4 Z- c
//---------------------------------------------------------------------------# o( Y4 x$ I0 A5 n3 o
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,5 N. `. y& t8 t9 Q7 p# R
        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)9 v  V% v$ `  q: b
{! A& V' @- b$ V1 ]; g+ _/ Z
    BYTE  btIDTR1[6];
! E, ~/ d* D* Z% I- B! o4 H! E    DWORD dwOldExceptionHook;
$ ^0 K2 S  ]& p* h( b    const int nHookExceptionNo = 5;' \  w( x5 }. G+ z2 i

/ r! G5 r! c2 h# S2 f/ ]    BYTE  btIsIDEExist = 0;
6 m" W8 f0 f9 u4 J8 _    BYTE  btIsDiskExist = 0;( N3 f& ~: m% a/ v) E: N
    WORD  wOutDataBuf[256];' C1 q% F7 a- G( G& t# ^
4 ]: Q& x- H  Y( E7 e) ^
    BYTE  btIsFirst = (BYTE)bIsFirst;4 \  s$ h* ]" Z3 ]0 v  I% H
7 ~, |1 D* I) K. m, Q2 O: f
    const BYTE btBit00 = 0x01;
0 m/ V7 V. n9 |" n- y; Z, e; c    // const BYTE btBit02 = 0x04;  c! e3 t# ~7 K! G$ a: s
    const BYTE btBit06 = 0x40;
0 H0 P7 N( U9 h/ S  Q2 H    const BYTE btBit07 = 0x80;
7 G+ Z: Q: l- k3 E: b    // const BYTE btERR  = btBit00;
/ ?+ C1 F; s, S    const BYTE btBusy = btBit07;
( Y* R3 A( S9 M& w    const BYTE btAtaCmd   = 0xEC;
* _' u# Z( q2 [: V$ _5 u    const BYTE btAtapiCmd = 0xA1;1 H/ u, y2 E9 G
8 X$ ?) A& ]! Z/ D4 ~
    __asm; ?5 Z9 f0 }5 d! k9 ~  t7 a6 K3 Z
    {4 M" ~- l$ m4 s7 b* U- @% j
        // 必须先执行这条语句
: L  g3 N: \4 E0 x( b) q9 \        JMP EnterRing0
3 T6 b! |, A1 l/ w% |1 u
# i; }, Y% m# j' k# X        // 定义过程
* Z, p$ @, ^0 e( [2 M5 }        // 等待IDE设备直到其不为忙为止
3 a' j) C$ P- S* E# W        WaitWhileBusy proc% w  Y4 \' K, l3 e) w

+ w# x& B' A6 y* j        MOV  EBX, 100000
: Y" j% Z. k0 m; ?, t( I* \        MOV  DX, dwBaseAddress
( u5 y, I6 z4 |5 ?. ~        ADD  DX, 7
! V. m" T, y4 ^( V) X
# g5 R$ I  G2 F9 l/ F, n3 y        LoopWhileBusy:
1 ^' ]! _! \- C, A% x3 A2 J  {% M4 n3 g, t; s# V+ c
        DEC  EBX
# W9 {0 E  Q. Q( @7 p4 Q        CMP  EBX, 01 S$ n; F( m8 r' m2 S
        JZ   Timeout
. |; z! k+ k' h% d+ f  [        in   AL, DX+ c$ ]9 L  C" C& m, y$ T" E7 Q9 w
        TEST AL, btBusy; ^" C# Q; v$ r# p# M
        JNZ  LoopWhileBusy/ S/ n1 g, d" _6 B0 g1 H3 `
        JMP  DriveReady
* V. [5 T+ F% k) J- `$ M: C! {" O" E3 }, Z! e1 R
        // 超时,直接退出! E  o8 k' |* b$ p8 U
        Timeout:& N, |0 F; e1 \  H1 V3 v
        JMP  LeaveRing03 {* D2 l- J8 Y. S- e' z8 D' A
        DriveReady:; x) J8 S+ b  o3 L4 G3 M
        RET
! v( k: b% Y- M        ENDP   // End of WaitWhileBusy Procedure
5 }! P# t$ `/ k( e  ?& B& Q0 S
7 @5 a( I  t2 A, L0 A7 W! C0 H5 \+ `        // 设置主盘和从盘标志' r7 S6 O: `' p" d
        SelectDevice proc. V2 c- s2 O' X6 Q# y- m2 w3 ?
' `. O+ e: l8 ~
        MOV  DX, dwBaseAddress
7 K' J& [5 ^4 ^5 A7 Y' N4 t        ADD  DX, 6' |7 |: z( f& I4 b3 C8 n* R
        MOV  AL, btMasterSlave
$ ?7 ]4 l9 X9 F  f6 t" b% a. f5 i+ U7 Z  j: Z4 |. z
        out  DX, AL( ]  M+ W. D; Y$ c6 T* f, k
        RET4 _" ^4 `/ S% c" z/ r7 b& H- k
' u1 i5 b$ W$ @+ d4 |' y4 R# ]; p1 s
        ENDP  // End of SelectDevice Procedure0 D: w: p( X( I/ e; l3 j2 J

" c7 M4 a3 N& X  {        // 向IDE设备发送存取指令7 t* J5 @, g, g/ K8 @5 O- p, t# _
        SendCmd proc+ ^% P; N% w. X, Q  W6 J7 y

4 }: W/ y9 B4 E8 r9 E        MOV DX, dwBaseAddress% Z# C& F' G4 c% Q; s, ~& Z
        ADD DX, 7! i$ Q4 {7 m: e* G  Y0 }# W3 H* w2 y
        MOV AL, BL // BL是主从盘标识,在过程外设置6 [$ K+ w2 W: O& O9 Z( T
        out DX, AL- N2 g4 Z( w$ J
        RET
& [; G( |* L0 I  @        ENDP  // End of SendCmd Procedure7 G8 }9 d! R) C4 j

5 h; Q; s: A: j( R        // Ring0代码
- I" F: P$ }3 o+ K9 A# r7 [        Ring0Proc:# S3 T3 p8 z* C1 L+ w
        PUSHAD# U$ H, ?  _+ @# r
        // 查询IDE设备是否存在
( L0 J& n# a: D% D5 O        MOV DX, dwBaseAddress
. Q' A: K4 a3 d- @5 |        ADD DX, 73 c' z" W% e. K
        in  AL,DX
0 t* n6 m9 j" z% X( h$ j9 P# t' r7 K" E0 ?2 I, U! m
        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回* \" X0 ]2 w( J( D8 B6 Z
        CMP AL,0xFF, s3 ]! |4 L$ H3 \4 P, h
        JZ  LeaveRing0
) a  v& j3 b) t1 l; @! X$ u0 N        CMP AL, 0x7F
! j; U9 A0 t: `, m$ H% T8 F' s7 W        JZ  LeaveRing0% ~+ _- p/ j: N/ j
  h. }0 z5 C1 e
        // 设置IDE设备存在标志
" G5 n7 V# A# z        MOV btIsIDEExist, 1$ H  `* u% T# h8 a8 D. e; H9 l( i7 n- ~

% M3 f5 u0 w2 e' p4 a6 H        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)4 O! D7 ?3 N) t3 O% l
        CALL WaitWhileBusy* e- y1 ]* q4 |. x. h- c! S
        CALL SelectDevice" Q, A# h3 u" O: |) N

* n) c2 g! H' T) c        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
( m  T7 |, \% k        CMP  btIsFirst, 1: P5 S8 [9 g; I. w0 }0 V
        JZ   LeaveRing0  y% b  c* W* `. `0 F! v

, D- v3 f+ P4 c* p/ }5 ~3 j+ \        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
- n; n! t$ h$ z) o        CALL WaitWhileBusy
. C% Y6 M$ w$ d- d4 f8 ^9 s6 w% w# s8 c7 Q
        // AL的值等于cBit06时,不存在驱动器,直接返回
& i* g4 R6 Y  ~& z        TEST AL, btBit06
, m: ]3 ?1 g( x5 {  M: @        JZ   LeaveRing0  \6 x; q: E* v- p3 g
( E+ n* T4 m; k$ w6 a  h
        // 设置驱动器存在标志2 g- @: \1 S# @2 T9 N
        MOV  btIsDiskExist, 1. D8 g3 l" V0 b5 s, Z. F
/ `7 P' i/ {5 z5 H) l, \
        // 发送存取端口命令* @: W8 Q( B2 H% s4 y
        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
8 S1 b: s$ p4 r2 B2 z4 {        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
  p7 v- a- S6 j6 ]        CALL WaitWhileBusy& l8 i9 y  _1 Q3 ~0 E
        CALL SelectDevice    // 设置主从盘标识
, M* _+ G% |2 k# Q5 B: }        MOV  BL, btAtaCmd      // 发送读取命令$ }6 D# j: q4 b! l# I% h- g
        CALL SendCmd) a6 H5 u) o6 b) z
        CALL WaitWhileBusy. z7 _: d+ u, c& o, ^& W; Y. X

2 _% S# U- F0 T) p        // 检查是否出错
" h% D% A. V8 D) m: ~        MOV  DX, dwBaseAddress
7 t' @9 o2 K% e) R. t) m) q$ T        ADD  DX, 7
% w& Q; V5 L2 D
& v) {3 d" w1 k. k* }0 D        in   AL, DX
+ m- c% q* j( {7 F2 Q- q- }0 }3 E+ N4 j& }# \/ G! b) a
        TEST AL, btBit00
* S6 r8 u* w: Q* J        JZ   RetrieveInfo   // 没有错误时则读数据# y1 |7 M5 c* ^+ J2 ~! \0 i) O
$ ]( F. p8 t+ Z3 l; z; M. u6 g
        // 如果出错,则进一步尝试使用ATAPI设备命令3 u& x2 i; v2 k1 {( e- l
        CALL WaitWhileBusy# n& O! [$ \2 ~. `# c/ H& @. E
        CALL SelectDevice
; k9 u: q8 `8 u+ \1 t        MOV  BL, btAtapiCmd3 o- w# X* O0 \
        CALL SendCmd
( ?( f& ^1 \& y! I        CALL WaitWhileBusy
3 b  S& ]* m" R/ y, W5 R* c$ h" [6 N
        // 检查是否还出错7 o+ q  L8 K8 v7 p
        MOV  DX, dwBaseAddress
2 \9 V/ _4 y/ T) y        ADD  DX, 7
& @8 X! P% x# g7 C8 @( K        in   AL, DX
8 T: I4 e( Z) |  b0 `4 ?        TEST AL, btBit00
& n- |1 t* R+ }7 t' w3 z$ u        JZ   RetrieveInfo   // 没有错误时则读数据
4 l% b3 h4 c! P8 E8 \        JMP  LeaveRing0     // 如果还是出错,直接返回$ t3 ?1 {; ^- |. e6 {1 [& i, _

3 r; [! p6 P" u        // 读取数据
. F: J8 B9 }/ }" d. o1 V& x: K  S2 k        RetrieveInfo:4 y) v. k/ ]" ^& x) Z& H" I- W( t

' @% q* X7 G. X# R* h+ D. I        LEA  EDI, wOutDataBuf% x. E0 M3 F/ s/ U" t) ?. ]
        MOV  ECX, 256
) o" @* |$ ~+ U# c6 J        MOV  DX, dwBaseAddress! _9 F( L4 O2 |& E% b
        CLD3 |5 a0 k+ p2 s: @
/ A# W1 q( a& r8 N$ X# Z" m
        REP  INSW1 r! v/ p4 h8 G$ z$ B6 z* g  P& m
; t! }: Z* h6 @- U5 T4 l
        // 退出Ring0代码1 e( M8 L9 r7 e9 A3 m
        LeaveRing0:& c+ |8 p7 w* X/ a
# E9 l  A+ E2 B
        POPAD2 R; H" l. p6 U% {9 ?- `
        IRETD$ i4 ?" T$ h: O# }* C: e' M
1 a, O  L+ l5 V) `, {
        // 激活Ring0代码
2 t, \1 ~& a* C% O6 ^/ e, _        EnterRing0:
$ g# \* ]1 T$ y) U8 L; s. K5 L( y
* o7 b3 F5 H2 y, |7 L        // 修改中断门+ T3 y- ?5 W3 ?4 ^* t# Y* w
        SIDT FWORD PTR btIDTR1, W! ?: F" E% m$ N
        MOV EAX, DWORD PTR btIDTR1 + 02h
/ _4 k+ |9 z) f# N        ADD EAX, nHookExceptionNo * 08h + 04h
7 F% Z* C* x3 x; e: L- B6 m) A        CLI! A7 _7 y0 r1 i3 y

* R. b) s& r0 }! Q& H$ v0 P# P        // 保存原异常处理例程入口9 }, y; p& s: z+ [5 `& B, Q) F% {: r
        MOV ECX, DWORD PTR [EAX]6 o' a! I' o2 r! G1 Q5 B$ \
        MOV CX, WORD PTR [EAX-04h]4 ]0 x7 A" l" _1 i, H
        MOV dwOldExceptionHook, ECX
1 C2 T- t+ R6 G1 R" R4 |4 P# ]! @, m3 k! N$ F' `2 ?
        // 指定新入口7 t9 Z) k: t8 n( \0 U, `/ W
        LEA EBX, Ring0Proc- D  \8 N# ?9 M8 p
        MOV WORD PTR [EAX-04h],BX
+ H, a' O# @+ |8 i        SHR EBX, 10h7 S2 U3 R( I& F2 }) O8 h: ^1 X
        MOV WORD PTR[EAX+02h], BX) t4 M$ q9 S: ~4 E! K! q" T

! Z- h4 W! u. X3 g7 P$ S        // 激活Ring0代码
( z* B* B: B; E3 u+ e; b- t        INT nHookExceptionNo
2 `7 p7 y* {7 N1 Q  z& y& ~) p+ v* P- u. s4 Z: W6 t9 }% c$ j( d& h
        // 复原入口8 ]3 v0 j- g- g% e1 \- K% H
        MOV ECX,dwOldExceptionHook: M  S8 s2 J- K2 A) V
        MOV WORD PTR[EAX-04h], CX5 Y6 Q* x; h9 f. b
        SHR ECX,10h' v  B# d+ D7 S! a# O! @. Z# r
        MOV WORD PTR[EAX+02h], CX
' V% F8 I, [0 M8 [: I1 \        STI; b5 J6 o1 d5 n
    }7 O, m5 L) E8 E0 Z: X+ d2 W- C
    if(!bIsFirst)
1 ^9 M+ S% e. z4 u5 O    {2 j0 E' m' |. t, R/ a, p% ^
        bIsIDEExist  = (bool)btIsIDEExist;
; \: h$ Z% A4 U- G2 b( {- `  K        bIsDiskExist = (bool)btIsDiskExist;/ I0 v4 w' o% e
        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
/ }" c9 ]- _) n' i6 Y% X    }
) Z* f" j0 I+ H2 f}
' s6 |0 \4 ?& [. X0 Q0 v; r+ l//---------------------------------------------------------------------------4 B/ Y+ {% ~" G: I- S! [) A
// 调用方法:
8 z2 K' ^" ~% @void __fastcall TForm1::Button1Click(TObject *Sender)8 N9 m1 k- U! d  e, y
{
% }$ z# C7 r; _# s' h/ M! {    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
/ K: u, G. y  S( f2 Y7 c) C}4 Z  `: J1 g- N, p. e2 K% h$ N4 P
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-5-2 06:49 , Processed in 0.031101 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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