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

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

[复制链接]
发表于 2008-1-6 19:59:06 | 显示全部楼层 |阅读模式
代码框架,你所要做的仅是修改WQL语句,具体可看MSDN。以下代码为简介起见,一次返回所有的CPUID或硬盘厂商系列号+ U# r. P) Z, m. M: ?" F- o

  1. ' {; L% M. Z1 L1 o0 C
  2. #include "StdAfx.h"( v* b' Q5 |# k2 Z
  3. #include ".\puiddisk.h"9 b; x8 x& W  B
  4. #define _WIN32_DCOM
    ' u& @+ j+ h; V* W" a
  5. #include <iostream>
    " d( L: K- ^* ]  [0 A/ d
  6. using namespace std;
    6 e) X- \# p  u+ U  |, n
  7. #include <comdef.h>( \$ _3 _! V3 x
  8. #include <Wbemidl.h>8 t" a' A' _0 Z6 X: w) w; l

  9. 1 _% o9 Y8 l/ M" }) D  t/ l, ]( y
  10. # pragma comment(lib, "wbemuuid.lib")4 `# |8 M5 h# B$ @% B0 R0 Q
  11. CpuIDDisk::CpuIDDisk(void)8 Y; Q" h; R  `3 f5 |4 D" d
  12. {
    - w' I, o. Z, e/ d
  13.     GetInfomation();
    4 V# F! g- e6 R# H& n0 z  E& \
  14. }
    . N0 p! g* S2 m5 T( B: A# }/ j
  15. 7 e. a' W2 ?( t, o7 E- G3 J
  16. CpuIDDisk::~CpuIDDisk(void)
    2 t" b, ~/ P% i' ]" H
  17. {
    - S  N* R6 C4 q! [4 y
  18. }) ^2 _; i( S/ g& y( n# p( ~
  19. int CpuIDDisk::GetInfomation(void)
    ) F1 X/ j/ x5 G3 J; }* Y" u8 I
  20. {
    1 q7 B6 ?: V* K" ~1 \
  21.     HRESULT hres;" R$ G$ m7 j, e- P5 o) i, @/ G8 P
  22.     //步骤1:不是必须的,COM只须也只能初始化一次
    , y0 R  E( z/ v! u& S
  23.      hres =  CoInitializeEx(0, COINIT_MULTITHREADED );+ U7 @( f7 }) j6 {
  24.     if (FAILED(hres))3 B7 t$ G" \4 E+ r+ v! j# p
  25.     {' ]5 ~: F5 U" A4 @8 ~2 B
  26.         return 1; //初始化COM异常:注意,COM只须也只能初始化一次% U5 g$ ^4 n2 }3 h: l8 q
  27.     }
    + N6 R- }, D0 r( G
  28.     //步骤2:不是必须的,COM只须也只能设置一次
    ' q  h- \8 c7 @* t/ \
  29.     //Set general COM security levels7 }- B$ l5 p' G7 N; V
  30.     hres =  CoInitializeSecurity(9 h/ r% [3 W) e  r& O# L1 ?
  31.         NULL, 8 Y0 x5 K6 T" [
  32.         -1,                          // COM authentication& R& E. z; N7 |! b$ V; }9 n
  33.         NULL,                        // Authentication services# P2 h' n% U+ k
  34.         NULL,                        // Reserved8 W- \* ^9 }% _8 v9 b8 K6 w& q
  35.         RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication , n- Y, U% {* ]. E" |) A0 s* I
  36.         RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  ) ?* T7 |' j4 c; L3 Q, m" A
  37.         NULL,                        // Authentication info, ]& X- I/ `8 Z0 I+ r" F1 N
  38.         EOAC_NONE,                   // Additional capabilities + ^  N# a' g( ~( L
  39.         NULL                         // Reserved+ F: I3 B4 r/ b, w- z/ D8 \# k1 E% @
  40.         );
    ; S7 H8 e$ j' I; Y
  41.                       ( W6 r% |% ]/ H4 v. D
  42.     if (FAILED(hres))
    # R2 h" ~0 N% w4 W/ n+ l. O: V
  43.     {
    3 i% \3 T; S+ u4 l% f/ d$ v3 ^' l
  44.         CoUninitialize();8 N* J! M5 V: T/ O* L& _2 i2 p
  45.         return 1;                    // Program has failed.
    1 z$ x6 e2 b4 }6 Q- H
  46.     }/ T3 X( V( b7 c8 k
  47.     5 C* n1 L1 a3 a( S" y' c8 d
  48.     //以上不是必须的,若已有“::COMInit();”,则要跳过  X' H) E2 V+ n/ |4 q
  49.     //步骤3: Obtain the initial locator to WMI " I9 j* y/ a( t3 E- u; R
  50.     IWbemLocator *pLoc = NULL;
    ' u% @( w# f! ^# E8 a
  51.     hres = CoCreateInstance(
    $ y: K% X9 s7 V5 F  B
  52.         CLSID_WbemLocator,            
    . N* U" y; N: h' B5 B& q" {
  53.         0, ; }" N8 t: T+ V+ `4 O: h
  54.         CLSCTX_INPROC_SERVER, 0 |6 s" @4 ?$ a+ w
  55.         IID_IWbemLocator, (LPVOID *) &pLoc);$ |' x% |: l% b* |* ?. H

  56. 4 U/ C9 X4 S; l. Q2 S
  57.     if (FAILED(hres))
    ' K$ z  w; E1 @5 u3 [# B
  58.     {' Q* I$ p' T. q0 Y0 a8 e
  59.         CoUninitialize();
    4 M; X1 x4 u/ F9 e9 U( ^5 F/ _& I
  60.         return 1;//Failed to create IWbemLocator object
    - \7 D0 q( {* U: t
  61.     }2 J' _' o7 T. `, g& U% s1 p

  62. / B+ Z- y+ V+ D$ c5 E8 }
  63.     //步骤4:Connect to WMI through the IWbemLocator::ConnectServer method3 {1 p/ N3 p: H* Z8 ]. J5 g
  64.     IWbemServices *pSvc = NULL;8 ~* R. r0 G' |1 k) ~* q
  65.     hres = pLoc->ConnectServer(
    5 m" w, Q* p2 f  H7 c) s& I% B
  66.          _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace; B: ~0 `$ w. K/ W. c- e' ~
  67.          NULL,                    // User name. NULL = current user
    # x  P) y# e6 V8 k+ D  ?! C
  68.          NULL,                    // User password. NULL = current
    / N- W% L6 S6 G
  69.          0,                       // Locale. NULL indicates current) }" r8 g6 W( u" o, L7 m6 V, h+ O
  70.          NULL,                    // Security flags.
    & Z/ F- \7 l% I6 z0 e
  71.          0,                       // Authority (e.g. Kerberos)$ Q9 I5 [, n. L1 A' ]+ g/ P
  72.          0,                       // Context object 3 h4 ?4 S: f9 _+ C2 d
  73.          &pSvc                    // pointer to IWbemServices proxy
    * ?( T5 u  Y/ N) u0 y( _0 I6 H
  74.          );0 h5 P5 \( u5 z# T
  75.    
    " U2 g5 q- m2 H1 a
  76.     if (FAILED(hres))
    - L, I' c; G2 g: p6 s* Y( D
  77.     {
    6 T5 F; I$ ^1 c3 q' A- f' s. q
  78.         pLoc->Release();     
    7 z/ ?$ H# n* P# _( |. }% V
  79.         CoUninitialize();! P7 a6 M+ u9 I  q* f0 R
  80.         return 1;                // Program has failed.- Z" K# l) i# {+ n) k% Z% Z  \6 M
  81.     }) n0 n# U2 _) J6 i
  82.     // 步骤5: Set security levels on the proxy
    3 Y5 m& W5 {$ A
  83.     hres = CoSetProxyBlanket(
    7 ?. M# q, S. T& }5 {& E# e3 m
  84.        pSvc,                        // Indicates the proxy to set9 y' d/ j1 j# L. N0 r" S' I
  85.        RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx1 q& v+ L8 ]$ N6 X1 w  i6 Q
  86.        RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx
    " B* d5 X. w* y6 n4 o* ^
  87.        NULL,                        // Server principal name , `9 @5 N; P9 U" }- r6 b3 z
  88.        RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx " d4 K) I% T8 K1 C! O; O/ t+ Q+ M" J
  89.        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
    ) x5 I8 a1 L8 C1 n  H  {6 J
  90.        NULL,                        // client identity
    4 E4 H. A5 T1 t/ F5 w
  91.        EOAC_NONE                    // proxy capabilities
    ' ?/ Q) }. B+ G5 U) U/ H: a/ Q
  92.     );
    & q. L, ^$ q8 B3 j. @4 {

  93. " m5 @& }5 `( e9 f1 L( V
  94.     if (FAILED(hres))% e! f  V8 v$ \1 f' L7 c
  95.     {) ~0 n3 R' P! H/ H. }% H8 ~; V% v; T9 Q
  96.         pSvc->Release();+ N: S- Z- A4 d! ?9 v
  97.         pLoc->Release();     $ w% S9 H6 a( P0 Q4 w* D. ?; g
  98.         CoUninitialize();
    , S4 H3 |* l$ m3 E9 S
  99.         return 1; . |+ t, p+ i* J7 K8 _: B
  100.     }
    , o* L' M; D3 C" o1 H: C0 o- {' B
  101. 5 A& F* t9 m9 _# U' f$ I
  102.     // 步骤6:Use the IWbemServices pointer to make requests of WMI ----7 ]' j* r: {, g8 \$ U# _
  103.     IEnumWbemClassObject* pEnumerator = NULL;
    # L+ u7 `6 \6 F, n. S
  104.     //计算CPUID& W2 J5 w0 g1 B
  105.     hres = pSvc->ExecQuery($ |( p% ?6 R; F! j
  106.         bstr_t("WQL"),
    : L9 m1 j. j2 A8 s' G
  107.         bstr_t("SELECT * FROM Win32_Processor"),//Win32_OperatingSystem8 K) }# Q- r/ m0 s4 b; R
  108.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
    * j" q  |, w; b7 e8 Y
  109.         NULL,/ p5 x# P% p: H8 K! _& Y
  110.         &pEnumerator);1 J: l( ~5 v: \" ^, o
  111.     0 I5 h+ i( }9 p9 }$ k8 n% ^
  112.     if (FAILED(hres))4 ~0 H3 r6 L: p" |9 S
  113.     {
    1 h! Z5 Q) r1 L4 R/ z
  114.         pSvc->Release();9 d/ Q2 F4 E0 x# J; C
  115.         pLoc->Release();5 q! E5 c1 U/ B& m" ~! f& a/ j* D& U. S
  116.         CoUninitialize();
    + A, l2 V3 r* o4 G
  117.         return 1;
    - ?( }4 c% V- ?, g* f, c
  118.     }2 S5 C8 `0 l- A' I$ I
  119.     // 步骤7:Get the data from the query
    1 k/ _& D1 M7 L! V2 _$ U
  120.     IWbemClassObject *pclsObj;# ]$ J' h7 \- d, A9 M+ M5 A
  121.     ULONG uReturn = 0;( M) X' p# o: H1 x4 m
  122.     while (pEnumerator)( J* i6 ?5 G( {  X8 O
  123.     {
    , x3 e1 Y  j/ }" E2 O
  124.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, 1 q( J: S- e& H* \  o5 t% O
  125.             &pclsObj, &uReturn);
    / I  J1 t4 K" g: w
  126. * ?" n9 }# ?1 v8 E
  127.         if(0 == uReturn)
    - b" }$ r3 l, R4 L
  128.         {* F9 z8 w9 c  {" P# n$ c
  129.             break;  B8 M- r' N3 h% D# z: k7 v  u
  130.         }
    4 i5 s! Q/ y" r7 X/ p7 e
  131.         VARIANT vtProp;
    / v. _$ c$ L) y
  132.         VariantInit(&vtProp);
    - X$ L" s% j! u/ }& m8 k
  133.         hr = pclsObj->Get(L"ProcessorId", 0, &vtProp, 0, 0);
    , p1 P7 h" F3 w/ \' d
  134.         strProcessID=_com_util::ConvertBSTRToString(vtProp.bstrVal);//strProcessID:类级变量
    ( x' i3 k' J7 ~5 Q, u0 q* ]4 R
  135.     }
    8 A! L' {% k0 ?6 r
  136. : f9 t/ H8 G3 Z& ]/ ~3 l, Y. t) b2 K
  137.     //计算硬盘系列号
    9 y& r8 v5 N+ P
  138.     hres = pSvc->ExecQuery(
    ( Y$ n, v' a" w% s- F
  139.         bstr_t("WQL"),
    7 q+ P  Q8 Y: j3 b& q1 n7 ^) e2 S
  140.         bstr_t("SELECT * FROM Win32_DiskDrive"),  p* G* X  P. i5 i! p8 `4 Q
  141.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, - I3 \9 V9 c6 h  X
  142.         NULL,% ]. g0 e) a, u( J
  143.         &pEnumerator);* n5 R- \" v, z

  144. 4 b; ~* D- h, G4 g- ?
  145.     if (FAILED(hres))! i- ?6 N4 }% d4 }
  146.     {, w8 e3 W. l+ O* b
  147.         pSvc->Release();
    $ V7 g2 p7 \: X) A" q
  148.         pLoc->Release();6 T0 `7 l% b* B  i( \1 ~& P4 _
  149.         CoUninitialize();
    - ^/ I7 S# O& I+ @- k/ p7 e/ U
  150.         return 1; 9 Z1 _  l- f! r) ]" c7 q6 _
  151.     }
      Z- \' U7 i/ d% s! s
  152.     while (pEnumerator)
    . W- S- B( n9 N
  153.     {: u/ b. p" r& n( w
  154.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, / A( K, H4 D3 u9 `1 f0 X  U5 i) z, z
  155.             &pclsObj, &uReturn);8 p$ p9 [- |/ o& p  {1 G( `- s4 D

  156. / H/ ^2 L5 y, I/ n2 H4 D
  157.         if(0 == uReturn)
    . `4 e, V& f2 S; m
  158.         {4 H1 C+ C/ J1 a
  159.             break;4 D; Y: N! m% c$ N" D# I4 G
  160.         }
      p3 E6 ~5 Z5 Z- z+ E; J

  161. ( f( i$ m6 D1 b* i6 k1 H
  162.         VARIANT vtProp;
    ) y/ O* T8 ]5 ~; _% t6 v/ E0 U
  163.         VariantInit(&vtProp);
    0 `) B/ y1 Q  w9 P; R9 W# e! d" e
  164.         hr = pclsObj->Get(L"PNPDeviceID", 0, &vtProp, 0, 0);& R# S. M' b8 I- v) p6 N
  165.     strDisk=_com_util::ConvertBSTRToString(vtProp.bstrVal);
    ; `! i0 \! l$ B& ~# H& n9 }: L
  166.     }
    . \% [& S3 F. G! F! z

  167. 8 m# N5 C8 J0 M4 l
  168.     pSvc->Release();
    * P3 l* {+ R* z; [9 ?' M
  169.     pLoc->Release();
    8 e+ i4 s% Z3 U* j4 Z- v8 w+ }
  170.     pEnumerator->Release();. r5 ]% o, {$ I; u
  171.     pclsObj->Release();: f! A6 M# V; }% v
  172.     CoUninitialize();
    5 \2 m. ]- m" Z- p- b
  173. * {; l! e4 `& j% S9 }" Y* \
  174.     return 0;   , ^, j6 h: v& X
  175. }
    " c4 [' {0 D. W6 \* o3 d
复制代码
 楼主| 发表于 2010-10-11 19:21:05 | 显示全部楼层
本文代码经ccrun(老妖)在Win2k下试验成功.6 F; y+ i! K( S5 e( ~

, r+ y4 @) ]8 C3 y3 Q+ H& ^" ^) S#include <WinIOCtl.h>) ]" u0 _1 L9 u0 i
#include <stdio.h>
* L% T- z7 b6 ?% F/ _7 ~
. Y' i- ~* u& g- N#pragma inline0 }" g# D3 j6 ^
//---------------------------------------------------------------------------
7 T: \" S  U4 `) F! e( l: r// IDE NT/2000/XP专用变量
# b2 a. T0 h5 n5 u1 |$ f6 P1 H#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
: v0 c9 \2 d8 T#define DFP_GET_VERSION         SMART_GET_VERSION: L- P: l2 R8 B9 O5 F9 p
#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
' }1 D0 D; d( j+ o( z5 p. V#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
1 ?" `* Y7 y+ l2 F: {4 Y& Z+ v0 z0 E4 D9 ~8 y; ]
const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令% N+ R" h$ `' E4 Y/ k0 J
const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
2 ]* j. m. c# w6 B& k& a
' D, d! _) p& g+ `4 s, ^const int MAX_IDE_DRIVES = 4;
& w+ z7 H7 X2 c% @7 B4 v, C! x6 Y0 g3 D+ _2 ^! u0 ^" _+ {
// SCSI专用变量
, f# O, m/ e4 c' m- A* }const DWORD FILE_DEVICE_SCSI             = 0x0000001B;
4 s0 J- u) Q3 e4 a; ]4 Xconst DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
0 ^  u7 N3 d. d: U( Zconst DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition) Z, m7 g# @# ^5 ~. _
const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
) B5 u! E# V6 U2 P9 c! V8 H; ?; }1 G5 i  V1 N3 X
typedef struct _SRB_IO_CONTROL
* Z5 q. t) \& q( e2 H7 f{+ h1 g/ e7 ?. F7 M! W; h
    ULONG HeaderLength;
0 Y5 w3 `& b: ?' H2 c  r2 L    UCHAR Signature[8];
4 `, ?9 n: J2 n1 Q" l6 J    ULONG Timeout;" d# c9 D) ^5 I: P
    ULONG ControlCode;; k; I2 p4 G. I3 @: {( ?
    ULONG ReturnCode;
9 s3 `/ v7 i* R8 ~7 M$ ?    ULONG Length;9 y" V% K! J1 H, N! j/ e
}SRB_IO_CONTROL, *PSRB_IO_CONTROL;0 P' o; V  _6 [1 _2 @& d

0 c1 K) |" s  [9 t9 K. d# u7 B// 读取的主函数$ K. i/ H& a; ]& P
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
1 L$ z9 o! `, m8 ?5 `/ f& g. l( j
1 W* L, o0 v: s% L% o// 辅助函数
0 P7 t; X5 |" m$ j  Y$ Tchar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
6 V5 S7 I& [8 z% g/ o* E3 E// NT/2000/XP函数
6 i  I% B1 d. c! \0 Cvoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
0 {% k# R- b2 ybool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
7 v0 G3 l( L! k- y' ?& [9 e        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
: X& @/ Q( @5 L$ T+ d" N/ v        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);. [: ]* f. }# E9 a' n" q
// Windows 9X函数. v3 q- Q/ ]1 _$ |, n! O
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);. K  [9 ~# ?/ j0 q/ J6 E
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
* |* ^) _) H1 x+ I7 q4 \        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
" ~. V8 j0 u' N; g
$ B( G$ ~& |6 F2 F// SCSI读取函数(for NT/2000/XP)2 _( u; j+ J2 y3 n. D
String __fastcall ReadIDEDriveAsScsiDriveOnNT();
, W& R3 r& w9 q3 J& i//---------------------------------------------------------------------------
, r5 ^/ s. z* _3 M  X6 G// ReadPhysicalDrive' G3 y1 f1 \) X$ C1 E0 H
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
* s/ ^; s4 |; N) o{
+ W6 }- O! K$ U% P! d$ J( Z% U    switch(Win32Platform)
9 z$ ]$ Q8 t; }    {! D6 F, P6 b! N( X, T% c! A
        case VER_PLATFORM_WIN32_WINDOWS:
8 p6 b& l" D" v8 N            ReadPhysicalDriveOnW9X(pSerList, pModeList);
* ~1 o" B3 w7 p  `2 E6 Y            break;
- c! a8 x5 o/ z7 W  f- h        case VER_PLATFORM_WIN32_NT:
0 Y& o* U" q: \( W# E6 T0 ]            ReadPhysicalDriveOnNT(pSerList, pModeList);
' b( G: O* u% h  Z0 `            break;
( ~% Y% n/ J5 B) w        default:% U) W/ h0 s, f& v- c7 Q6 c
            break;0 t( k" [, E' {" g* S& H6 b
    }9 g# p/ i) {* A* J' t4 `; @
}0 P. K) E  L% G( \
//---------------------------------------------------------------------------9 ]9 d3 a; c: q% }. v4 i& Y
// ConvertToString3 N. f+ j; ?4 G8 R8 h1 E7 V6 M
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)% w* d/ l! V4 \  Z8 y
{
+ H1 N( A  }2 V! m* `1 x7 Q    static char szResBuf[1024];
( {& k! ?( r+ n1 b1 |( }    int nIndex = 0;3 D+ [8 j, g0 r# m1 s6 n, p" @
    int nPosition = 0;
% s. t/ ]5 Y+ ?7 d9 s9 R/ K
' z: e9 B: a) J7 ^    // Each integer has two characters stored in it backwards
) p0 }% l1 N8 f4 E" p# }; F    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)( _* H/ p, h0 B' }6 z* V1 F
    {
( x, X) B- f3 g5 C+ V6 x8 ^        // Get high BYTE for 1st character
1 C/ S+ `9 w$ t6 p' ]7 V! [        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);9 }* k% y; @. Z" a2 S* E
        nPosition++;* }5 X) Q. i3 K# Y0 Z4 O
! M; o* X3 S. ~$ ~/ ~$ N
        // Get low BYTE for 2nd character5 Y  G$ d( f; ~/ g9 g9 l7 A6 E
        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
6 I7 J/ |6 G. c7 Q! d, y        nPosition++;
9 x, U$ i0 H5 K2 {+ D' H    }
. T- v. s1 _2 x1 `
2 i: C( ?* F) ?' F    // End the string8 y5 C% W4 ^" x% ]% V8 o
    szResBuf[nPosition] = '\0';
1 P/ D+ b. o# u7 F
- b% Y4 n  q! E7 {    // Cut off the trailing blanks
$ z8 t' w( `" R7 s    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)( y0 W) n6 O# z6 G! x( l6 F
        szResBuf[nIndex] = '\0';& }7 x/ [) d+ \
6 P7 t$ R  W& ?+ ]3 h7 l
    return szResBuf;7 |5 m, Y0 _* h/ ^1 A# i! Y* \: t
}
* _4 t' i, z) m& E( p//---------------------------------------------------------------------------
' O2 F5 w: h  F- b1 f' v4 l( o// Winndows NT4/2000/XP 代码# V+ g/ Q) G% M* n' I8 P& [
//---------------------------------------------------------------------------! F3 M$ K8 S5 A( s/ q8 b0 `
// ReadPhysicalDriveOnNT
, ]3 k4 x' B4 M" x: m3 ivoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
5 ?/ g. o6 G% C; W" q; n+ j! }{6 c' @9 A/ A$ E6 Y" q( s
    // 输出参数5 l/ \. b. _0 C& i& r
    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];# T0 m% o: k1 n( J  r. X: q

# ~  W0 {; o7 ?' n( ~! k) N    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++). @0 F8 X3 a* v" j! w
    {
  m1 m6 D! j" W4 ^4 h7 ?; @        HANDLE hPhysicalDriveIOCTL;
& U+ b4 }8 E* r  \2 N, p! H) |        char szDriveName[32];
1 t$ w' T; `+ n% G  g0 [; |/ R6 }# M/ Y! O& F( y- u
        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);9 D/ i, R, T- N5 c
        hPhysicalDriveIOCTL = CreateFile(szDriveName,
5 \  f& J. Y2 b- _* D2 _- P+ L8 B                        GENERIC_READ | GENERIC_WRITE,, C2 f& A9 D) t3 l. H2 _& k
                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
  |  t6 q) `8 n9 U/ I3 I, Z                        OPEN_EXISTING, 0, NULL);
; l8 X3 [; ^0 ^" l8 ^. o; k# G' H% ^1 F
        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE); y) a" n! @2 i1 ]" W4 O
        {
/ D- O# x% ]+ [# {2 \! |! q- C            DWORD dwBytesReturned = 0;3 _- y. c) L- m2 Z2 R- V
            GETVERSIONOUTPARAMS gvopVersionParams;
4 D$ d9 x; l* B: }' Q8 I3 D. H, \; T8 D& b: z+ w5 H2 U: Z- H  r
            // Get the version, etc of PhysicalDrive IOCTL* [7 c8 W- q: D. A* _( M0 _
            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));- r* g* L! o. o. s

+ R  B2 v1 v, I+ v7 u            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,6 m" f  B: I! ^2 _5 M
                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
* O$ T0 @1 {! ?8 e8 l% v                    &dwBytesReturned, NULL))+ U; |. L, |0 N: W& h
            {
/ T  b6 ~" ?  Q8 p/ l0 B                continue;
$ d! c7 {% i( s3 |5 Y, J6 y            }3 ^. w: g" I( [6 M3 R5 M- A
9 m4 W+ [  L  l; E6 N1 n  L4 }
            if(gvopVersionParams.bIDEDeviceMap > 0)2 a& D4 Q" I4 h
            {
) W: @, g) @* ?% a8 M7 U                // IDE or ATAPI IDENTIFY cmd
: [+ N) _8 G( _7 W6 H) k                BYTE btIDCmd = 0;
$ l) T8 x+ Q1 Y                SENDCMDINPARAMS InParams;. I2 g9 R. T( j! Q6 M! f8 o+ I
                // Now, get the ID sector for all IDE devices in the system.  q. |9 A9 g; o! ?% w
                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
# v( d% l; d. }) W* N                // otherwise use the IDE_ATA_IDENTIFY command
4 O% g9 t- H7 Z) _1 r. }                // 具体所得结果请参考头文件中的说明
: o! u) `5 n3 C% ~                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?) _6 H, p- G) k9 B/ z- E- ?
                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;; w; f# z& g7 b# H2 s
                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));# M5 v8 Q! l" `6 Q" ]
                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
  L: b0 O2 A2 C  x* |. ]3 X# b! V2 @5 m) @; H+ |
                if(DoIdentify(hPhysicalDriveIOCTL,7 b. J% X' F: P: K# N4 w' O  ]" V+ U2 m
                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
  Y8 ]: l+ Z; L; u5 p                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))6 ?5 T% {# \: ~. X8 Y
                {2 x0 |5 c7 _7 E; y* L9 ^6 V/ f
                    DWORD dwDiskData[256];8 ]- o" e) F5 B
                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
, I6 A" w: _/ X8 R; t6 j/ z. _2 _5 g                    char szSerialNumber[21];
- `3 o1 L* X1 Q5 x+ R. S2 {                    char szModelNumber[41];
6 f( P. c. }6 e7 }/ x- k( V0 L- f, x7 l5 X
                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
* r! }- k( ?& Z3 @6 U) E( c; u- ]+ }                    for(int i=0; i < 256; i++). Y6 g1 P4 ^8 p# F2 F- P+ F
                        dwDiskData[i] = pIDSector[i];
* b: R4 S# g! [( c% f                    // 取系列号
! l8 n% H4 K! a9 E( O. R                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
" H6 R, a4 K4 w( f$ o, H% G# y                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));+ C8 h* c: j& \+ P2 D

0 k& N" L+ l" p3 t                    // 取模型号
7 O% r7 k- o+ r) q3 L- f                    ZeroMemory(szModelNumber, sizeof(szModelNumber));  m0 t4 R% N) d& }& @- Y
                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
) U. d* }5 j2 _* q+ E& U! o  h) B  I+ o4 d( {8 B  W9 [! i) H2 j
                    pSerList->Add(szSerialNumber);! X8 x- r6 a  h
                    pModeList->Add(szModelNumber);# Y5 v8 Z  v6 D0 r. Y; N$ I
                }/ }% @* J4 I$ T( R. r1 d
            }
7 f( s: t( ^, z  F            CloseHandle (hPhysicalDriveIOCTL);
$ c" z; X3 _& L' T        }1 w1 \& g6 i5 D1 ]
    }
+ v9 n% F5 J5 X0 r# V4 C& ?, A/ O4 ]}
0 g) W$ P  y% s3 J0 l) c//---------------------------------------------------------------------------) I. }9 h% }0 w  ^0 w
// DoIdentify3 y# U7 {+ p* J5 {! S" |
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,# e/ x! p' g' X2 Y2 v% F
              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,3 F8 ^2 y# X! Y: a: }
              PDWORD pdwBytesReturned)
% U& i9 I) [8 q1 s7 B{$ o- Q7 D/ ~: g! v: |8 P: Z
    // Set up data structures for IDENTIFY command.
5 P! g! y' p4 l. D5 p6 L  y    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;8 _8 ~. O% S; V3 [* A4 o
    pSCIP->irDriveRegs.bFeaturesReg = 0;
# ]% q+ }' y$ @: O! t2 W    pSCIP->irDriveRegs.bSectorCountReg  = 1;1 w5 M& N) x, Y: p* f
    pSCIP->irDriveRegs.bSectorNumberReg = 1;% K( h; |9 v- I: w6 w
    pSCIP->irDriveRegs.bCylLowReg  = 0;' h5 s3 K/ r1 r$ H, J8 P* |) J
    pSCIP->irDriveRegs.bCylHighReg = 0;4 H: O% {! \4 r, P

! `% D4 L! A: U* V5 D$ C    // Compute the drive number.(主盘和从盘所对应的值是不一样的)8 o' J( n1 t4 s! L& Z4 o9 S  c
    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
3 x% j7 R: ?8 l# c" j
' g* O- j: M2 j    // The command can either be IDE identify or ATAPI identify.3 C! T+ U. k, L$ @: m
    pSCIP->irDriveRegs.bCommandReg = btIDCmd;0 W) r8 ^# m) |8 e; Q/ Z4 |
    pSCIP->bDriveNumber = btDriveNum;4 \% X/ Q, q2 H. u+ Q5 L
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;( x3 L! W; }6 T9 A. `7 S2 \. b

$ G% w& e  q" K2 G" \    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
- I* I0 B' ]! [8 j           (LPVOID)pSCIP,* R; v! H9 b1 l2 v8 X0 U3 w" K, }# B
           sizeof(SENDCMDINPARAMS) - 1,$ v3 ~, L( n* S5 _3 }* \
           (LPVOID)pSCOP,
% i* @/ w, {8 f. ?6 s/ H           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
' q4 z8 y% k" {% v           pdwBytesReturned, NULL);$ [4 j9 q: x' r* y7 O
}
' G( J1 c& ^) h8 v+ [- h//---------------------------------------------------------------------------
, i  a( E$ O, M& n// Windows 95/98/ME 代码
2 [, l& I, U% \+ c- j- v5 n//---------------------------------------------------------------------------) M$ \( V" \$ ^5 ?% F0 G
// ReadPhysicalDriveOnW9X
) }# F7 u: A, Qvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)
0 J" ~# K. O7 o{
) _. s' P' S" D4 ], d9 k" F    WORD wOutData[256];
' R1 K1 E0 M4 V/ ^, f* v    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);$ M% \/ P% h! U" ?
' t/ k6 R) ^" F' ~0 Q+ Y4 W( R
    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
5 ?8 \7 ~# c) W; y; _    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以9 _1 K+ h! j) O# ^$ w
    // 避免蓝屏的出现。(期待高人能指出原因)
, G/ A" u2 C/ i$ U    for(int nDrive = 0; nDrive < 8; nDrive++)4 v! X( ], p) ^3 S0 Q# |7 e( ^; A
    {. S! }$ i2 {( n7 |4 I% B( T
        WORD dwBaseAddress;
9 ?& T# ^& d/ ?4 o% F% P9 K; I        BYTE btMasterSlave;         // Master Or Slave
  _6 |2 j# }/ |% Q        bool bIsIDEExist;
/ o, d7 ?) m9 U! o        bool IsDiskExist;+ w, O% K: e5 z$ s  [

$ `; U, E. r3 o4 p        switch(nDrive / 2)9 i2 l+ m( b( _3 i0 H
        {6 x  O: q5 v; Y( H5 I
            case 0: dwBaseAddress = 0x01F0; break;  i; w% C) B' c- O$ R9 I
            case 1: dwBaseAddress = 0x0170; break;
+ x% T3 |1 M* O            case 2: dwBaseAddress = 0x01E8; break;; y2 s: L5 [& I& x, w. M
            case 3: dwBaseAddress = 0x0168; break;4 f: n& o: ^6 M. R0 W( H& F% i
        }; K1 @* B+ ~5 ?

3 Q% t5 D: q' Y) \% K        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);! H* O- l/ O9 ^$ t# U. r, ~7 F

6 d; P5 W2 m" Z8 f        // 进入Ring0
+ W+ a+ B6 x9 P! u& v        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,1 s* W5 \, Q$ m* n& [6 C( [( q
                bIsIDEExist, IsDiskExist, wOutData);
; [% d+ s/ U  g6 {) g) Q    }
) ]. ?( c/ G2 q& R9 I) L) J: b. C- b. x
    // 开始读取3 P4 g6 m8 y, u; p" [. J: ^
    for(int nDrive = 0; nDrive < 8; nDrive++)
) r0 u1 ~. I/ t7 X$ `    {
- ~1 z+ e2 r  Q3 r, C; J  `& l        WORD dwBaseAddress;
$ W& X9 {8 r0 C7 l6 }& Z) h        BYTE btMasterSlave;         // Master Or Slave
# y& [1 W7 q- f+ x9 W4 z% ?5 E& @. f        bool bIsIDEExist;
- I+ L* t( ?9 E& [/ d# J; \        bool bIsDiskExist;
- K' V  s/ o  D        switch(nDrive / 2)' O( S6 }% _7 @
        {; u; Y) `2 }  U% C
            case 0: dwBaseAddress = 0x01F0; break;$ }# W$ v9 |8 o- ?! |9 t
            case 1: dwBaseAddress = 0x0170; break;
$ y; n" @2 j" k+ j$ o1 z            case 2: dwBaseAddress = 0x01E8; break;4 b2 x! v0 p$ t6 \& F  X
            case 3: dwBaseAddress = 0x0168; break;, a  u8 B8 b" Y/ y7 i$ J
        }
' i* @- V5 ~9 b0 J# P# a; o5 I
! w$ M  e  Y1 `$ }; w1 u        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);2 c- X! N8 U0 T5 @' m
+ [1 Z- r3 A' {
        // 进入Ring0
2 h8 S1 f7 j' V# |* G3 h) T        bIsIDEExist  = false;
) I  _/ p% @3 [- Q6 Q6 a- p% G        bIsDiskExist = false;
' F" ], Y8 i5 S) g/ c3 G        ZeroMemory(wOutData, sizeof(wOutData));. t8 A) `% f( |

3 C0 w# Z8 ]1 w6 f* C* v        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
+ i" A# e7 z7 k$ a7 ^% s3 K                bIsIDEExist, bIsDiskExist, wOutData);
/ d# H& r' ^5 `
6 _  \2 M" R& f0 y- J        if(bIsIDEExist && bIsDiskExist)+ E' a, B- m. ~% |8 k" I+ k# i# `
        {
/ V/ m( K2 V' _6 Z: F0 u5 J$ K3 r            DWORD dwDiskData[256];
; l/ [) t( }. M# r            char  szSerialNumber[21];
4 t, p" _3 Z% I7 |1 Q- J            char  szModelNumber[41];& w# X. b6 d" P, t; e

  N: h, B* n& x" Z: X7 d! Y            for(int k=0; k < 256; k++)
! u& l: |: {5 S; Q8 _/ \                dwDiskData[k] = wOutData[k];+ f  E, y7 u# V) l

5 v$ W7 ]! s0 s" {& F/ K            // 取系列号/ u+ s- L) W; k/ Y% `
            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
  [& N9 s( E+ x6 f            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));9 O* f( m8 @" m

, a! a2 k- e3 M, O7 d7 L            // 取模型号: }7 j# Q: `5 F& j0 O' B+ H
            ZeroMemory(szModelNumber, sizeof(szModelNumber));
; C8 D! J5 N/ c; @            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
0 d! n- [3 E" q
# C1 }) x. h  Z. U# q* J2 K! |            pSerList->Add(szSerialNumber);" ~/ }* U1 z* M/ s6 W5 B% ^7 O
            pModeList->Add(szModelNumber);0 p- [% }/ U* n4 p" x
        }6 Z! ]* g8 d! H" |. t/ N6 Z
    }( Y  K7 P# Y  Y9 Q1 G+ A3 p6 Y
    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
0 x% v5 s1 v3 o1 m; i}
9 z: m3 }4 @( y2 v$ f* K6 S. T$ ]. L//---------------------------------------------------------------------------; [+ L* t- B- Q: n9 P: j
// 为防止不负责任的转载者,在此注明原出处信息,请见谅。
& a+ E  w; L- z( X) b// 资料收集整理:ccrun(老妖),欢迎光临C++Builder研究: http://www.ccrun.com
& t" j" {) }9 A//---------------------------------------------------------------------------
; y& b  N# X. K! s// ReadPhysicalDriveOnW9X_Ring0()
. v6 l8 \% _- b3 o1 p: l//2 J; W; i! K/ D& j# J# f, a, P4 R8 [
// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h# r' I' l( g" J# D
// btMasterSlave = Master(0xA0) Or Slave(0xB0)  f1 j" i, t; e# r: k/ e/ `4 E
//---------------------------------------------------------------------------; h! v+ p8 e8 o' l3 h
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,9 e# N, H/ q3 I2 p
        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
7 ?6 x) v; D) H  P/ {7 b% K: D{; c. {9 g; k2 m6 M) A
    BYTE  btIDTR1[6];4 X' v; t1 r/ E4 H2 S( p# }
    DWORD dwOldExceptionHook;: \+ R( ^/ `4 R  w" A
    const int nHookExceptionNo = 5;4 F5 E( q" w$ z0 i% v

4 M( K! C$ R, u. N. d& K    BYTE  btIsIDEExist = 0;
% s( l/ G0 ~6 k3 Y7 A    BYTE  btIsDiskExist = 0;# r- `6 E. v3 {. e
    WORD  wOutDataBuf[256];
0 o# A( d/ `. r# x& w5 W; f# T7 \- s
    BYTE  btIsFirst = (BYTE)bIsFirst;, I0 i/ P+ b# z
, _" o. k6 t4 i2 j
    const BYTE btBit00 = 0x01;  `3 z6 I2 c+ \
    // const BYTE btBit02 = 0x04;
* p" F  ]5 `( a- \. U( n    const BYTE btBit06 = 0x40;7 o9 I) y% E; J2 k" L! D: S5 [1 H) T
    const BYTE btBit07 = 0x80;
, l- A  a) ~: n    // const BYTE btERR  = btBit00;! M! Q* _& A/ W" T
    const BYTE btBusy = btBit07;
4 q/ g0 ^/ [: m1 [7 H2 s    const BYTE btAtaCmd   = 0xEC;
0 y# r2 A& n+ b2 F    const BYTE btAtapiCmd = 0xA1;' v7 g2 l! W" Y' O% u
6 J8 \6 L8 a8 E2 A! g& }4 D( }! B
    __asm6 p9 x- O: N6 Z/ c3 T" n$ e& i
    {% f3 b/ h1 v' I& F+ U& {# u
        // 必须先执行这条语句
: }3 v! n2 f: z6 T        JMP EnterRing0
! Q3 [2 e" z5 q/ f4 [8 I, C  @8 Z6 B. P
        // 定义过程* T7 |: e5 E% W# M. w# r! K3 j( q
        // 等待IDE设备直到其不为忙为止
3 M* r4 h& ~* I- T        WaitWhileBusy proc, P* I4 J, p9 G( z  |) z" n* a

0 t  Y- ]1 ?9 A0 ?. ^        MOV  EBX, 100000$ X, Y4 c- T! J2 i' G
        MOV  DX, dwBaseAddress! O2 q; q' I7 H7 D* X. Y8 ^! g
        ADD  DX, 7* s" ], `% {/ {. T3 p! E

  m0 H6 g5 S, K  H+ `9 u        LoopWhileBusy:
1 @& ^' n' @" D6 H/ l" s- ]! I& _7 {; V+ @. N; D
        DEC  EBX
. X  K# p/ G" F; G4 P+ H8 Q4 R        CMP  EBX, 03 O  }7 l7 F3 q9 ^% z
        JZ   Timeout
* q' @% T5 i, u# f% U' d        in   AL, DX
% I5 X7 f, m# G6 ?/ @2 @        TEST AL, btBusy2 t# q. @' `& E% `$ s  |# n
        JNZ  LoopWhileBusy
1 j. g; K+ d9 n4 [% P        JMP  DriveReady5 v1 z, f! `, q5 R* S
- B5 Y% a8 U% A2 x6 S
        // 超时,直接退出3 D, w, J, L- o" T
        Timeout:
  i7 V/ u( [# t/ F/ r        JMP  LeaveRing0' `9 q* O( y5 b6 b
        DriveReady:8 X- r6 `  \1 P
        RET
- f# F5 v/ J. r! a$ u$ ~) n: W( R        ENDP   // End of WaitWhileBusy Procedure6 ?! U  q; t* @) A5 ^
% K8 S% J7 S6 z! e- V1 g  q
        // 设置主盘和从盘标志
- z( L5 H, X3 W5 M, G% P% I! t$ }        SelectDevice proc
) l4 W0 J, T7 R7 K) [; h
: b# M! N' ]8 v" F/ f* f  Z        MOV  DX, dwBaseAddress) [# O. u) c' p5 \/ b
        ADD  DX, 6
) Z, i% a' T3 e* P        MOV  AL, btMasterSlave
2 B3 a: W3 h8 D1 ^$ \" \1 ~# G* [. m! s+ ]* j3 |& x0 ~
        out  DX, AL
: E  V3 q$ X4 q5 X' Z        RET
3 Q: P& q- o8 w. e) b& i( }: i0 k4 A9 q4 Y; J
        ENDP  // End of SelectDevice Procedure
2 D+ B& ~; W. j2 @  A# l) ~, Y' Y
0 }8 |  d/ P# X7 ?        // 向IDE设备发送存取指令: c/ P7 U8 f& `
        SendCmd proc
. |+ I( ^. S7 x6 Q3 j# j* [  T! W. r! l
        MOV DX, dwBaseAddress
/ W# e+ `1 d8 R# a% G7 B        ADD DX, 7
, w3 D9 {/ [" W  C# @4 F        MOV AL, BL // BL是主从盘标识,在过程外设置
7 I* k' x; `0 J5 N7 I( I        out DX, AL2 m% r1 B; |+ ~1 s7 n9 Y& @" X# t
        RET
, D4 q; k5 w6 F2 d5 f& v, Q        ENDP  // End of SendCmd Procedure/ P3 z% A* @1 r# h9 U; k% p
: B" \- g8 b$ k, K( i3 T
        // Ring0代码
9 c+ W5 ~8 Q$ z        Ring0Proc:) w7 Y5 d# H" v/ Z- R
        PUSHAD
  Z/ A* W! x8 [5 ^5 y  z7 e2 T' `+ A        // 查询IDE设备是否存在
6 V, B2 c: Z, u, p3 n7 d        MOV DX, dwBaseAddress
- D( K& G( {0 l        ADD DX, 7# I3 M2 w% \  a+ {) z5 e6 r+ G
        in  AL,DX2 J# F& u: f1 B2 \
" q: [2 W6 D$ `
        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
" v0 \- u$ h, w" j& K        CMP AL,0xFF4 C" J7 X' d0 Z+ [
        JZ  LeaveRing0
% t# ^" x0 N. F+ \        CMP AL, 0x7F# l1 K0 o2 j1 t
        JZ  LeaveRing0
0 t0 u( G/ H! M1 [/ S  B! D, C
2 d4 A, ^/ r3 i& B9 m; P& L' S        // 设置IDE设备存在标志1 ~# M2 K# Z3 R( v
        MOV btIsIDEExist, 1
* u" Z$ }; I" ^0 t% n' W* C
9 @' V5 x1 s0 ^6 ~" L# l        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)7 q/ O, e+ f8 o: L6 ?4 W, x6 R
        CALL WaitWhileBusy# ?! a; o  o) T/ n7 H& {
        CALL SelectDevice" X! q: ]" X# f. ^! C
; N4 p, h, u: Y
        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏3 N+ U# D. N; K3 n8 r& n
        CMP  btIsFirst, 18 D& d! ~' n( u- \+ b
        JZ   LeaveRing0+ I- b6 z+ L1 f. N8 J  V7 r

- u6 g, Q3 d+ R$ G. c        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
& W# j1 P+ V0 Q  p. r        CALL WaitWhileBusy
, j/ Q7 I) I$ d) R$ P" J
2 U3 z+ v+ B1 b% t; s" p: `9 |% y6 U        // AL的值等于cBit06时,不存在驱动器,直接返回2 N3 D+ e) ^% g2 R  R
        TEST AL, btBit064 ?. y9 w9 g+ v
        JZ   LeaveRing0
6 Z! d7 X& @: ]7 B  C$ \& Q
1 q4 ^/ h; ~% x7 Q; {/ b  H0 v        // 设置驱动器存在标志
$ g" G9 ^3 f) ^& H. l% n  p# i        MOV  btIsDiskExist, 1
  ?) j( H: C' u1 r# }
: X# A. R, m" L        // 发送存取端口命令& }( D/ C8 w9 ~+ Y& g
        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
6 Q& y$ w, W6 @% {* A$ E        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
% Y6 V: V' x1 J4 `1 v        CALL WaitWhileBusy
1 K6 n% p$ z0 E        CALL SelectDevice    // 设置主从盘标识
# t3 ]+ z) ~4 \  C8 e& i) u7 L. c        MOV  BL, btAtaCmd      // 发送读取命令
+ |0 C8 N, k( ^7 `1 ]$ P        CALL SendCmd2 x4 Y) S+ G. d# ?$ ~! r
        CALL WaitWhileBusy
, x# O/ G9 N9 A9 d# s* U. Q9 `  L% R3 o
        // 检查是否出错
% f4 b' ?, S) f, y! {2 z        MOV  DX, dwBaseAddress( s. k" x4 y$ d! w" O' y: V
        ADD  DX, 7
" J9 z  t7 M7 b
* y6 l) u. J/ l( O        in   AL, DX3 \: x4 L/ F' h- a  M4 e
( m0 `# D" m8 K* N5 Q  v
        TEST AL, btBit001 _% ^  }1 r9 l2 s* e
        JZ   RetrieveInfo   // 没有错误时则读数据. G* i2 `7 T+ O- `3 d: X% b( ]( l/ Q3 P

9 f0 F& d* [& _: n6 B        // 如果出错,则进一步尝试使用ATAPI设备命令
, n/ O- r: Q) ?) j        CALL WaitWhileBusy
3 F; z: h, q! z4 |) m6 J        CALL SelectDevice
7 Q2 j  x8 q/ S. Y' w, w4 `, F+ o        MOV  BL, btAtapiCmd" ?1 H+ k+ \* i! x
        CALL SendCmd7 ^( Z- |( s, u: U. Y5 D5 m
        CALL WaitWhileBusy; s5 ?% {- Y7 `  _
1 I1 |7 M7 H8 S: R% w. S
        // 检查是否还出错, j; [: a5 `3 L/ _
        MOV  DX, dwBaseAddress& \; j" W. S7 j0 n* h- r
        ADD  DX, 7
  H8 @4 n5 A1 t: l2 _* W        in   AL, DX8 D9 ~' c6 Q1 i" Z
        TEST AL, btBit00
  ?/ w2 ?) b$ e        JZ   RetrieveInfo   // 没有错误时则读数据
; q- |* V6 `! f  {$ N        JMP  LeaveRing0     // 如果还是出错,直接返回6 G! z" P0 q$ X. R

7 h& B" @& Y9 U8 I, H        // 读取数据
/ l, A! m: |. T0 |        RetrieveInfo:6 Q! \) I+ L1 H1 {+ R( I! z& h

+ ?) ?) E: U; r& T) G        LEA  EDI, wOutDataBuf
( o  n: G( [! o: n; D. O        MOV  ECX, 256
" p8 t+ t$ U; ^$ Y        MOV  DX, dwBaseAddress, O. E$ @# D% {/ o/ G- s7 r6 J6 @
        CLD
7 H3 y# v+ \" f. _* n' ^
- X) J8 p1 b3 j" {+ m& f+ [: @        REP  INSW& |9 O! U# u- f. m0 r
2 u$ k3 z! s1 L7 ]* i, H
        // 退出Ring0代码0 N* j2 j4 U8 ~. m
        LeaveRing0:
1 z# ^4 t3 Y1 S2 r; b# p6 Q+ x2 s& ?; n
        POPAD4 ]! J  a9 j6 F5 H# _
        IRETD# P( G$ ^/ V% w, @$ K2 P1 K8 j7 u

+ O6 b: e& @' i6 W- I5 z& S1 s        // 激活Ring0代码& {3 ?" r$ e3 Y/ H
        EnterRing0:( [: n! \$ `, s8 n7 @8 x, r  `

. E6 Q8 e+ v6 A- Q/ L/ y' D" c! ]/ _        // 修改中断门
5 z4 N* d/ s4 n* X3 x6 }        SIDT FWORD PTR btIDTR1; b% P! J1 m; i/ h  W# X
        MOV EAX, DWORD PTR btIDTR1 + 02h) p( _; Z- F& A3 s0 b7 h. B
        ADD EAX, nHookExceptionNo * 08h + 04h/ B* ~+ ?. N7 k+ M! a
        CLI
+ N& W. f2 K: x0 J) x% N6 K# o$ `( F8 L" C, b: x/ ~( f
        // 保存原异常处理例程入口
. E: B+ Q! M. t  p        MOV ECX, DWORD PTR [EAX]% f  e8 O' V% H" O- ^* [" w, Z
        MOV CX, WORD PTR [EAX-04h]
; z7 z/ ]$ ~7 n' b$ }! T+ Z' P        MOV dwOldExceptionHook, ECX
! d6 _% y1 m3 e5 o( {3 C# D3 P5 n1 O6 I3 Y' D/ K
        // 指定新入口+ @( ^7 O8 ~; o4 z9 l2 j
        LEA EBX, Ring0Proc/ x6 q# ]( }- ]- h9 C  Z
        MOV WORD PTR [EAX-04h],BX
+ f. |5 a3 P( ^( b6 ]- j        SHR EBX, 10h
5 E3 g) z. E# G' z' ?% s        MOV WORD PTR[EAX+02h], BX5 c0 [. I: R2 `

+ g# r6 T( Q- ?/ b. ?0 P( Q. f, Q        // 激活Ring0代码* m7 Y( e2 N' n% ?; R/ {4 Q9 A
        INT nHookExceptionNo
2 O& u' h3 C5 s, g0 z  w( T7 R! |4 j; F2 ~: ]
        // 复原入口* k9 p+ ?4 E/ G% l
        MOV ECX,dwOldExceptionHook
, o& C& m4 a! B/ K1 ?        MOV WORD PTR[EAX-04h], CX
5 ?1 `% g8 d, M: N+ b        SHR ECX,10h
# z! r* W; J. T5 b2 a- x* j6 Y        MOV WORD PTR[EAX+02h], CX
; a$ T% D# B) D" {0 q% h9 T4 Z        STI! ~: J3 S0 W. U* [' w: u( E
    }
5 l' q3 \& j. K; e8 N2 E    if(!bIsFirst), s# R( U6 ?6 ]( [, Q; F
    {
, @7 w% Z3 ]/ w4 X1 u( W        bIsIDEExist  = (bool)btIsIDEExist;$ z6 C6 ]! y% `6 A9 A4 k* y3 e
        bIsDiskExist = (bool)btIsDiskExist;
! e( }5 O7 b3 o$ ]6 Z1 D        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
% L( E- `. `; O    }
0 t- L8 G/ o  [# q; ^9 n}; y% o  `, _4 Z% j- [
//---------------------------------------------------------------------------
( d8 c1 Z* ]0 I4 R% ^# g$ Z// 调用方法:
: W; s+ e: I' A1 B/ x' O3 |) `0 M1 `+ lvoid __fastcall TForm1::Button1Click(TObject *Sender)% \" L9 b8 ]. L) h) U
{
  Z) ^) i6 d8 }8 d    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
* l8 v3 D* m+ Q9 c6 R6 c" X! V}
6 f4 u# B$ Q( E" b, o5 @- a9 N$ J
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-9-30 10:45 , Processed in 0.036945 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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