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

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

[复制链接]
发表于 2008-1-6 19:59:06 | 显示全部楼层 |阅读模式
代码框架,你所要做的仅是修改WQL语句,具体可看MSDN。以下代码为简介起见,一次返回所有的CPUID或硬盘厂商系列号; P+ S8 b0 o3 E# _" }+ |9 N
  1. 8 K% y" ^' f; D7 Z/ A
  2. #include "StdAfx.h"6 A2 z2 I! W6 H2 K& [: v
  3. #include ".\puiddisk.h"
    # }; Q5 L; k! [5 V7 n: k$ ^
  4. #define _WIN32_DCOM
    4 M  O0 u5 ?3 n1 ]7 P% x
  5. #include <iostream>
    . B- C# |) y4 h) e
  6. using namespace std;
    3 z' ]/ {& ~! [) O: X, z2 |7 R
  7. #include <comdef.h>' r5 k' Z! A& L+ }( o* F
  8. #include <Wbemidl.h>5 h, T& T. n- Q/ B5 ?2 W7 g
  9. ; V: W: R7 _' t; l
  10. # pragma comment(lib, "wbemuuid.lib")
    5 l; p' _2 V- \" D9 ^4 m6 \3 w2 x
  11. CpuIDDisk::CpuIDDisk(void)* X, s; Z4 u* v9 s! R
  12. {8 P8 H/ Z( p' v0 b8 a
  13.     GetInfomation();
    - e0 @- A7 e: _; \# k
  14. }
    , \& C8 S4 G: N5 b, y
  15. $ n& Z" R: l, ?- k7 ~9 p
  16. CpuIDDisk::~CpuIDDisk(void)
      k" [- m9 V5 Z% P$ q# V0 ~- [- S! J
  17. {
    3 [$ u0 |/ n8 w; t% f
  18. }0 W& P7 ~1 t% q7 Y. S
  19. int CpuIDDisk::GetInfomation(void)
    ( h, Q0 |+ v' ~# N
  20. {1 t. c& w6 e* e9 u& v, `
  21.     HRESULT hres;6 V' G  H  s4 w4 A4 H; N8 P. A
  22.     //步骤1:不是必须的,COM只须也只能初始化一次
    1 t7 f) D0 @: q. P4 k" V
  23.      hres =  CoInitializeEx(0, COINIT_MULTITHREADED );
    % v" H  E/ v" ?, z" |5 F) @: O2 T
  24.     if (FAILED(hres))
    5 D9 E: j/ @' s7 ^
  25.     {4 X) ^* u; F  ^2 z" X( f+ c
  26.         return 1; //初始化COM异常:注意,COM只须也只能初始化一次! r) G1 l3 u3 x% G0 _! I
  27.     }- M, c8 }1 r% E
  28.     //步骤2:不是必须的,COM只须也只能设置一次' D. b1 M; m1 i6 w# ^
  29.     //Set general COM security levels
    $ G0 f2 d  A* E: f0 _  l
  30.     hres =  CoInitializeSecurity(
    2 e7 [, K# n- w& \% }
  31.         NULL,
    ( l8 W6 p. v9 y8 v9 `7 t) E4 l1 |- x
  32.         -1,                          // COM authentication: T+ v  }" ?: E
  33.         NULL,                        // Authentication services
    2 s$ ?6 ?; L& g' K& M5 d' X
  34.         NULL,                        // Reserved) j( S% K9 k+ [, Z$ u( |# b! X5 _
  35.         RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication
    % L) R& J# `8 j
  36.         RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  3 D- t( |4 j, g& w: [
  37.         NULL,                        // Authentication info
    8 \( u8 T: q+ s1 o7 S; V
  38.         EOAC_NONE,                   // Additional capabilities " A2 [  L& {' A* @5 L* ]1 Q
  39.         NULL                         // Reserved
    # P5 |+ ]5 E6 b; r9 v0 B
  40.         );
    0 u# T# T+ g7 m; T
  41.                       ' i6 r1 y) w9 I# z9 A$ h
  42.     if (FAILED(hres))
    . t- t2 C9 |! f; i! q
  43.     {/ r$ V( l* C& V1 q% q& E( D
  44.         CoUninitialize();
    & v5 ^3 Z6 y3 j2 m- J/ v: |( |
  45.         return 1;                    // Program has failed.
    ; J$ V! N" h0 U; Q* w6 f/ V7 y
  46.     }& m2 C9 m& R* {. ]! t
  47.     3 J2 I, Y- i* E! n" B" Z- N0 e4 f
  48.     //以上不是必须的,若已有“::COMInit();”,则要跳过
    " z0 A8 p' Q" c2 m: O- n( h$ P
  49.     //步骤3: Obtain the initial locator to WMI $ M' v8 F" B" J
  50.     IWbemLocator *pLoc = NULL;
    3 \* X* G& {" _- ^2 X. C
  51.     hres = CoCreateInstance(
    * L) ^$ h/ `7 v& v+ L3 O, o: U
  52.         CLSID_WbemLocator,            
    * _8 X4 ?* b8 U
  53.         0, * a8 d" Y/ R8 I* B+ |
  54.         CLSCTX_INPROC_SERVER, 6 u1 @* e8 \) a6 h4 u
  55.         IID_IWbemLocator, (LPVOID *) &pLoc);6 n9 s' w. z7 m5 W4 H# I
  56.   x4 Q) w% M; [; F9 d6 ^" l
  57.     if (FAILED(hres))  H6 u; k8 B8 }# Y, t" p
  58.     {
    : Y1 s4 B. p% P& |. F+ @, L
  59.         CoUninitialize();
    1 [9 y3 c$ k; }6 V7 h; L& `
  60.         return 1;//Failed to create IWbemLocator object
      H; w' ]; F& k5 V. I" w
  61.     }1 J- `% ]) z2 p4 w5 }8 h) {4 B4 ]! @7 k. B
  62. ! F1 m# W( s( E( n* D) H$ `; _
  63.     //步骤4:Connect to WMI through the IWbemLocator::ConnectServer method3 u6 [1 J, ?$ E: k3 M
  64.     IWbemServices *pSvc = NULL;
    ) `, S0 D+ |8 b; c: A
  65.     hres = pLoc->ConnectServer(
    / ^/ D1 ]% z0 D3 g6 }
  66.          _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace7 b7 W) W( L0 K  l9 _- p" B
  67.          NULL,                    // User name. NULL = current user
    $ N( ^8 a( o6 N. a
  68.          NULL,                    // User password. NULL = current
    ) c9 @% S( d8 ^% ^
  69.          0,                       // Locale. NULL indicates current) \" B6 }9 A& n
  70.          NULL,                    // Security flags.
      F" W+ y  I( I, P
  71.          0,                       // Authority (e.g. Kerberos)8 L( D  B4 f, p, _/ i
  72.          0,                       // Context object / A; `( \8 l& b% W, }
  73.          &pSvc                    // pointer to IWbemServices proxy; V+ C% H  Y# B. i: F4 R
  74.          );
    6 Z( s- t* e. K' A2 A
  75.     - F8 X5 {1 C4 W/ N9 L& N1 W) S, Z
  76.     if (FAILED(hres))% C. o* l, ^) n0 n+ ~) R& i
  77.     {
    7 a  ?5 Q) u& @
  78.         pLoc->Release();     ) B$ X# {$ ~  s4 ]
  79.         CoUninitialize();! i2 n" m0 k( s9 @" f! v2 q3 @
  80.         return 1;                // Program has failed.
    ' P2 o  Z. L% S/ \* m6 o1 P
  81.     }
    3 U- J# \9 g( d8 H& q
  82.     // 步骤5: Set security levels on the proxy  n2 R% E+ L) B, }0 d  j9 J" `* v+ z
  83.     hres = CoSetProxyBlanket(
    1 `0 [2 |+ f! k- X3 O+ A
  84.        pSvc,                        // Indicates the proxy to set
    + r- [0 p. N  |
  85.        RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx* k' w) m' a6 R1 k+ Z+ X5 ]
  86.        RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx
      Y; q9 E) W6 m$ J0 f1 h* p
  87.        NULL,                        // Server principal name . d3 O' d& O/ H3 H' @3 {
  88.        RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx 5 {+ v/ ?3 {9 V' C  B+ @" I
  89.        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
    9 O/ U$ [! F7 V
  90.        NULL,                        // client identity
    ( j, d' v4 A( ]# u; a
  91.        EOAC_NONE                    // proxy capabilities + c1 E% D0 W: D* |9 k
  92.     );7 ^2 |0 @: U4 B. u0 d

  93. 1 O0 J* m2 j% U* y0 `  U- o
  94.     if (FAILED(hres))' S1 ?9 ^, P" J/ a
  95.     {
    3 J7 v0 R. `. g$ M- G8 z+ l
  96.         pSvc->Release();: K* m/ T: L, Y4 S. A
  97.         pLoc->Release();     
    * j. P) V# {& w# ^
  98.         CoUninitialize();
    * _( P6 d5 Q$ v3 R  h
  99.         return 1; " b8 h$ \  h+ ]
  100.     }( ~' u( a* S: r& S3 ^. R
  101. & ^) M1 j' u$ o* y, P/ [* t; }
  102.     // 步骤6:Use the IWbemServices pointer to make requests of WMI ----9 k/ \5 A1 v: u" M/ ]" t6 A
  103.     IEnumWbemClassObject* pEnumerator = NULL;. j  O: `) k$ T& v/ e1 Y
  104.     //计算CPUID
      ^! f* H. N; B; |% @
  105.     hres = pSvc->ExecQuery(
    & w. M* O6 b5 P( m3 v* m9 m
  106.         bstr_t("WQL"), & o8 T& i' P) v) K5 _% P
  107.         bstr_t("SELECT * FROM Win32_Processor"),//Win32_OperatingSystem9 S; W6 k. T& U- C2 B
  108.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
    / M0 s; C: q$ |& ?0 n# P2 e
  109.         NULL,
    5 u0 Z4 \7 u8 f+ W# c
  110.         &pEnumerator);7 q: J, `. @# [* g7 r$ e3 E
  111.    
    9 R- C' B+ U: q( o+ o
  112.     if (FAILED(hres))
    5 Y% [' f1 r, h+ m
  113.     {
    4 J5 G# z: @. D; }+ K
  114.         pSvc->Release();
    # u9 p5 [& X% c8 ]7 G# H
  115.         pLoc->Release();& y3 V: q, E) |! F: R
  116.         CoUninitialize();
      l( `- X2 M9 |+ \; K1 b$ `$ d& U' d
  117.         return 1;2 |' ~8 A9 `; ^6 v( L, w' k
  118.     }
    ! S& b% m3 w4 T3 u7 j
  119.     // 步骤7:Get the data from the query * W/ {6 Y6 g# g; a0 T8 K
  120.     IWbemClassObject *pclsObj;2 B( R) X. c" v# c2 o- w: D
  121.     ULONG uReturn = 0;0 r/ x/ P4 e" R8 ~: I/ g0 m
  122.     while (pEnumerator)+ M8 R. Z; {# o9 D! V8 m
  123.     {
    4 E, G" R  X: s% w, T
  124.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, , `% n: ^. D. {
  125.             &pclsObj, &uReturn);
    3 |+ G% }9 C5 G& p3 h
  126. ' L5 I( P( u& F* J( U% F
  127.         if(0 == uReturn)) I9 r3 N% T7 s
  128.         {
    # {- _( C: W; h6 q: ?  Y" |* R- r
  129.             break;1 ~0 N2 A% n. X4 {" a
  130.         }1 ]' w  b2 W( F
  131.         VARIANT vtProp;
    + @1 a4 T$ P/ l
  132.         VariantInit(&vtProp);
    ; x) C0 p3 A( y$ {. l
  133.         hr = pclsObj->Get(L"ProcessorId", 0, &vtProp, 0, 0);5 A$ P5 K0 d% m$ R* U
  134.         strProcessID=_com_util::ConvertBSTRToString(vtProp.bstrVal);//strProcessID:类级变量! P: j$ ?- [" J6 T
  135.     }+ e# b3 D5 Q, d$ D9 y4 A" E
  136. ) D1 }1 M& X: P7 M) G& V5 l1 A
  137.     //计算硬盘系列号* A; G2 m9 a: B. z4 [. k( V
  138.     hres = pSvc->ExecQuery(
    , N3 I9 t7 W- p: ^, D
  139.         bstr_t("WQL"),
    * p6 @# {) G, h1 T) |
  140.         bstr_t("SELECT * FROM Win32_DiskDrive"),3 w# ^' b/ y- x. G0 j4 o; t2 Z, X
  141.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
    ) t9 h$ O! e9 N$ U! H
  142.         NULL,
    ! e4 t" q$ ~- W5 _- g
  143.         &pEnumerator);
    5 w5 r' m3 M! ]; a% h

  144. 5 \+ y1 E0 b7 w6 W) d% j1 G
  145.     if (FAILED(hres))
    1 h0 S0 e) @: J7 o/ j
  146.     {! i/ u; S, i5 c6 K" A, f
  147.         pSvc->Release();. m6 h% n7 r3 v3 V, T% U
  148.         pLoc->Release();
    5 O- x, Z' c$ _6 m+ v
  149.         CoUninitialize();# K; P2 x* E+ ?$ `' I
  150.         return 1; - ]6 W  @6 D2 m& M  D, s
  151.     }
    0 j8 B1 _8 |( g$ K
  152.     while (pEnumerator)
    ( a. |3 N% h, q) g/ R- _
  153.     {
    2 F& O( t) r6 F$ Q3 b+ p
  154.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, # n/ i/ w3 E  ~
  155.             &pclsObj, &uReturn);
    1 v: i8 x3 H2 [  E

  156. $ }$ `2 V. `6 B: @
  157.         if(0 == uReturn). o! Q+ q: g% C0 V2 Q6 ]
  158.         {' A4 C; |- z9 L: |% Q. G5 F
  159.             break;
    * m! D- J; P  ]& i
  160.         }
      J% g% Y. o' @& v/ n3 o' i8 Y
  161. 9 s- G( Z) X3 ?  M  I
  162.         VARIANT vtProp;; }+ w1 Z" N: K5 S
  163.         VariantInit(&vtProp);
    6 N$ N' v2 \9 t$ a7 I7 ~4 x  O
  164.         hr = pclsObj->Get(L"PNPDeviceID", 0, &vtProp, 0, 0);
    . ]- I9 x! F# j- B4 b) I! ^7 h
  165.     strDisk=_com_util::ConvertBSTRToString(vtProp.bstrVal);5 o2 H+ ^/ v7 z( D5 o8 [+ _
  166.     }; ~% _7 b) x5 @/ Y( N1 n+ c4 n: {
  167. , W9 q. O. n" l. d) U
  168.     pSvc->Release();: x- ^6 W: |2 l* ?8 Y
  169.     pLoc->Release();, t6 [1 [0 K, r; W" @0 k% n% e( F
  170.     pEnumerator->Release();
    - }! t" q: c; O2 x1 p' @* W
  171.     pclsObj->Release();
      u1 Y6 F1 Z3 I; W
  172.     CoUninitialize();
    1 Q# K# @( d/ ^% k

  173. ! h8 G" s4 W+ G2 X- @0 Z3 d
  174.     return 0;   
    & u7 M! g1 C1 ]" N. R6 V, A, }
  175. }
    7 x* B7 q5 q1 B- e, |, c: I
复制代码
 楼主| 发表于 2010-10-11 19:21:05 | 显示全部楼层
本文代码经ccrun(老妖)在Win2k下试验成功.
0 P0 l% r5 O4 g8 b% {& P2 d0 |
$ L: E6 f1 K1 Q$ v/ c& K( M" \#include <WinIOCtl.h>' ?3 Y8 F% v8 I2 u& {
#include <stdio.h>1 }+ |: |4 n' G9 X, j

$ S" ]4 u3 b% }( |/ W' M2 ^#pragma inline
+ w( }" F+ c. ~+ N//---------------------------------------------------------------------------+ n0 n. V, D$ X- ?! f  U
// IDE NT/2000/XP专用变量! Q. X  ^) `1 _* |, ^" Z/ a2 n7 Z
#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
' ^8 g2 u; N8 z/ X0 z+ d#define DFP_GET_VERSION         SMART_GET_VERSION
0 Q2 j7 w9 G& B+ J6 B& \6 z0 _#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND" U! M8 B9 e. v# @
#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA3 O3 J( U- N! ]% {: l$ n

7 B6 ~' C8 w  u5 [. ?% aconst WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令
' {4 P5 I2 o; b5 S4 u0 W" jconst WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令6 w/ G4 J9 T. c) t$ u
! H) H* B- x; n% a
const int MAX_IDE_DRIVES = 4;7 c4 w; s" o7 B  n, O; d2 o
/ Q5 y, u; `# u  V8 }4 j
// SCSI专用变量; i! k! z4 ]0 h4 f
const DWORD FILE_DEVICE_SCSI             = 0x0000001B;
: ~# F0 }* l7 n  E$ w7 L9 d6 {const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);1 J- O) R5 |, ]# F5 k
const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition8 g' n8 i9 M. D/ F2 S
const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;3 I6 K" t) b7 f& A9 {
0 b: s+ o0 @# C/ x! @5 H! r
typedef struct _SRB_IO_CONTROL
' i. M6 z, U" ?; I2 [/ H! G$ R{
$ w3 ]/ Q0 v8 ~    ULONG HeaderLength;' n. L! @5 F5 E/ X  E$ i3 n" \
    UCHAR Signature[8];
# |1 [1 N: j2 i' ]; t: N; p1 J5 d    ULONG Timeout;
# Z: q$ p- H$ E( \4 `    ULONG ControlCode;
1 M8 ^+ s& Q/ W0 |( j    ULONG ReturnCode;. N9 g) T$ p5 I/ |7 \
    ULONG Length;$ t1 |+ g! Q7 ?
}SRB_IO_CONTROL, *PSRB_IO_CONTROL;  g8 D$ S4 n# q/ p1 F7 U

0 {7 j- ~2 y2 R  A1 l: ~5 x// 读取的主函数% J' q2 z8 a' X& O/ {- e
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
0 @( k( u: s+ m0 w- }
3 }5 S; R/ y4 K) I2 t// 辅助函数
7 k# `  \4 s+ i; o' achar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);1 g3 H4 w) `& ?$ ^# v0 C/ R
// NT/2000/XP函数
% g  d4 l: q) r, Kvoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);8 g' h2 @2 ]) j  T5 g
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
8 a0 P& E) @+ B4 J8 a        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
6 E" I' e  p1 ?: V/ r: `4 Y        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
+ {1 t4 Y' K' D9 Y/ |// Windows 9X函数
, b8 ~/ z( i! K( G( U$ z+ m& j5 dvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);
  t/ q  ?* D5 [1 o3 [/ jvoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
0 L- `3 x. z/ j' z8 P& T        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);5 ]* x8 ^7 g8 _: c) K3 g2 B
' V& d& m: J1 z
// SCSI读取函数(for NT/2000/XP)1 V  K- C1 l6 i/ Y: Q$ g( ~" A6 B
String __fastcall ReadIDEDriveAsScsiDriveOnNT();
! ~: b8 K& E7 L- I4 ]- U//---------------------------------------------------------------------------  t/ U% F8 ?) b4 \2 E  k
// ReadPhysicalDrive
' z( f" G5 _( c7 e9 Lvoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
+ ^; J5 a1 u9 t  P: ~9 F  N- v1 s{
. R( v- n$ H+ _5 G6 H    switch(Win32Platform)9 `7 S, w* Y8 q8 j/ s( A8 l% z; x
    {
0 Z; D1 T) m  U' J5 {2 x# F        case VER_PLATFORM_WIN32_WINDOWS:
* c, h3 S/ k9 l* t4 H* l            ReadPhysicalDriveOnW9X(pSerList, pModeList);
' [; R9 ^. U' }6 m            break;
  E2 @$ P& ^( Z! v% l& U! g. i9 `) \        case VER_PLATFORM_WIN32_NT:& K  z0 i; K( r
            ReadPhysicalDriveOnNT(pSerList, pModeList);
4 [; U+ l$ ^, @/ m            break;
' O5 ^( v5 D$ V* ?- c        default:
. [" X0 ]4 |  ^" s            break;
7 H5 v, X9 k$ N: |    }+ d. r! g1 F$ b: K
}
- s4 s  J0 }' u/ u* j//---------------------------------------------------------------------------& ~, c, u4 v0 x& k
// ConvertToString
  s! f( X) }1 Z- x5 Rchar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)# Z! Z4 N( u3 j3 h' R
{' b: }8 |2 D4 f
    static char szResBuf[1024];
& _' T5 x( F; n2 @, ]    int nIndex = 0;* q, A4 ^3 y8 i2 m; B- K
    int nPosition = 0;% R7 a& Y, |+ x" B5 \$ S
2 {  L6 U8 Y2 d. ?  c
    // Each integer has two characters stored in it backwards4 N+ U' K+ q: E# W9 J: D
    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
8 m6 H7 g9 j8 o1 ]. D' n    {
2 A; k( i- i7 K% {        // Get high BYTE for 1st character
8 P* U5 s# O* C: @5 j        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);. E5 ?& V% r8 N/ i$ F7 h% c6 Z
        nPosition++;* o; t! p# ?( j; D

: G- |! J0 |- h# R5 ~        // Get low BYTE for 2nd character5 F, r) c( N4 @) ]. u( W' X
        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
6 w. G8 T% H" ~/ N        nPosition++;
# p5 Q9 ?# B- P! y    }
; k+ a  ^5 h1 W2 @# }6 G; _  K
4 i/ \1 i! p: n6 ?9 e5 m$ g) W    // End the string
9 z& J, z3 S+ `- ]* C, D    szResBuf[nPosition] = '\0';
& L5 s; ^0 I7 u; g- C( e
2 `. X2 M$ P! w& f1 F; M  Q    // Cut off the trailing blanks5 o  S% {( y. K2 k( ]. d  E: v4 ]
    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
. m8 _( _" J. T2 i2 o9 ]        szResBuf[nIndex] = '\0';) e) w% h' G5 l% D" t2 W

1 ]( @, u( x9 N, R    return szResBuf;
! q& ]; z( G  [; c" ?}
( a- ~2 ~; j. @: I: a9 {% o0 K3 {0 h# o//---------------------------------------------------------------------------' v4 @6 G2 s; D1 b7 V
// Winndows NT4/2000/XP 代码
! e! Q% D6 H5 [6 @# E2 V//---------------------------------------------------------------------------
$ b5 F2 T+ u% w3 T; V# s$ h// ReadPhysicalDriveOnNT" Q9 I0 }1 X0 i- N9 P; R& i0 V
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
9 j! R# k$ O% A8 q6 f{1 j: b( r+ [+ R1 ]! C7 M4 L" F- K- v2 L
    // 输出参数8 D9 x% w+ }& G0 X- ?
    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];% n6 g! L% y4 Y+ ~+ \! W7 C
* m# F) b( n1 w& q$ t# `$ n
    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
/ F) D$ O6 T& F* Z    {! t- L, Q% J& }
        HANDLE hPhysicalDriveIOCTL;
% U2 z0 ^7 K  Z) i        char szDriveName[32];$ h. ^  S) O/ K' k3 g7 E" ]4 {$ e
9 p' \9 v5 j, b+ m8 U& X
        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
% ^# w- G# a# @- S) @( U1 z1 J0 n        hPhysicalDriveIOCTL = CreateFile(szDriveName,
: }- v' u9 b( _8 o) B& @                        GENERIC_READ | GENERIC_WRITE,
3 O& P1 t+ [. E. U/ X" \; i! ^                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
) K5 }9 P5 r4 ^% l) ]/ t                        OPEN_EXISTING, 0, NULL);
3 L2 Z- W% \; M
2 ?$ T3 T' l' y# A- c4 U9 A" _        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)  Z( M( g- z* |$ ]' T6 l
        {6 ?! m7 |  F8 s! I
            DWORD dwBytesReturned = 0;3 M. F" U, h1 z) G4 m: _
            GETVERSIONOUTPARAMS gvopVersionParams;# d8 u1 p- @5 }
  \, x& f0 E1 i# l5 p
            // Get the version, etc of PhysicalDrive IOCTL
( Y9 Y/ U0 B0 e- q; ~( N            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
1 W: ?1 O7 q$ O; ?
1 e( B0 g7 [; k0 y; @- h  c, F  P            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
+ Y# p4 l. m; }3 `7 m" w5 }1 y; U                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),3 ]. V0 A3 }# c! \7 M
                    &dwBytesReturned, NULL))
2 ^6 P5 Y! Q5 |0 Y2 J            {
- V. h3 c& u/ f: ?$ a                continue;
0 T  U/ o1 ~% A/ V  y            }/ F, y  _' X* A9 ~3 g$ s6 l5 W! l
+ c7 h' c$ D6 [# L; e( O
            if(gvopVersionParams.bIDEDeviceMap > 0)
& p  a/ j5 D$ u: }- D            {
. T( X0 R! `1 T5 {                // IDE or ATAPI IDENTIFY cmd  J, ^7 |, K  ~( u1 Z
                BYTE btIDCmd = 0;9 J) V0 r1 I9 h) r3 u9 W  J. l" \4 ?
                SENDCMDINPARAMS InParams;' O/ d4 C6 ]% Q
                // Now, get the ID sector for all IDE devices in the system.7 P' j; C/ w! m
                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,) l- Q3 V: o- K& C4 J
                // otherwise use the IDE_ATA_IDENTIFY command2 s, h- V: ]  N5 ]% n
                // 具体所得结果请参考头文件中的说明9 Y& V4 Q% U& i3 @  w/ h5 o
                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?. \7 s3 j* [: Y. A+ D' \+ j" G
                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;: L. {- m0 `6 p; z. h" N
                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
! y3 @9 t( g, A# {  E) G                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));0 [% x5 c8 g& U( N# ~% L! l! E8 C" m# x
5 N' L4 H7 I: a& K! m! E
                if(DoIdentify(hPhysicalDriveIOCTL,
7 ~' \0 m) J. z8 J# ?                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,' K* S% L; M1 [1 N
                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
  n; @) B1 c7 X1 @/ \. P. C                {
/ S1 p' R4 E+ I; l                    DWORD dwDiskData[256];
. v) k6 D" F5 \- E! ^                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
' L. M6 n0 H% ~                    char szSerialNumber[21];
4 ]( @- f( `1 p. |                    char szModelNumber[41];4 T6 `4 ^" x3 }6 A6 c

  A$ V7 c8 Q; r, U; t                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;' I6 _2 R7 m% c8 f1 H
                    for(int i=0; i < 256; i++)0 s8 k% E* D2 v; Q
                        dwDiskData[i] = pIDSector[i];0 g* f- @3 w9 C; z4 j. j9 n
                    // 取系列号$ V( {5 M/ p6 l. {; E
                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));* h2 g. Y5 q, R5 I
                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));+ Z5 h! o. e3 D( p2 X! Z% _: j. x2 f
3 Y. k# L1 j" M2 V" ^; H
                    // 取模型号% z0 X" z  b) X
                    ZeroMemory(szModelNumber, sizeof(szModelNumber));
7 d' `0 H; L; w2 g9 j: C) s                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
' n8 R0 [. i8 L& Q1 D- h2 R" t6 d
9 ^7 V. ?4 V) c8 t                    pSerList->Add(szSerialNumber);
1 d9 e; d# I# j                    pModeList->Add(szModelNumber);5 T+ {6 G# q% o; K5 F
                }8 k# c0 V* q9 |. x  n
            }
( T% t4 ]! q8 {& ~            CloseHandle (hPhysicalDriveIOCTL);
# p5 r8 P* Y$ U5 i  I" \        }( A6 y7 x6 v; G: @; G8 W; w
    }
3 W* s  R8 K* P+ U}
& L6 @8 D! i1 x$ x  F//---------------------------------------------------------------------------
+ U! m1 S8 Y. h* ^- }. B// DoIdentify! x8 D/ [' ~  `8 k8 }7 F
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,; |1 m8 Q/ U6 r3 P; Y( n# O
              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,% a7 C( t# h4 r
              PDWORD pdwBytesReturned)6 Z# H/ Q4 N0 f: ]  h
{8 P* }! y4 J, V3 I, H9 A9 k6 D0 J% I
    // Set up data structures for IDENTIFY command." k, O* k0 h, b0 F
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
' w0 k6 h8 O; N. E! K% T# b* a    pSCIP->irDriveRegs.bFeaturesReg = 0;# Z$ e; J' e; c! m5 a
    pSCIP->irDriveRegs.bSectorCountReg  = 1;4 k* t! j6 \% x0 I5 i3 q
    pSCIP->irDriveRegs.bSectorNumberReg = 1;
, V( c, z  b3 Q" {    pSCIP->irDriveRegs.bCylLowReg  = 0;
: O7 w3 j# c3 z    pSCIP->irDriveRegs.bCylHighReg = 0;
& }: J" q6 p5 c& F- C, y# w- U) K$ {2 `1 c6 I3 |
    // Compute the drive number.(主盘和从盘所对应的值是不一样的)
) R/ b" W3 S% ]7 z8 h+ f    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;/ q4 v2 q) p( R3 B
; |" c1 o7 L6 t. k+ u* f. S( ?& K# U
    // The command can either be IDE identify or ATAPI identify.3 X7 C/ _) n- [. `# V
    pSCIP->irDriveRegs.bCommandReg = btIDCmd;
1 k) b% G" Q: v$ S2 t! R    pSCIP->bDriveNumber = btDriveNum;* L4 i6 j& O5 L
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;# ~$ x! E; z2 k! Z/ R) g. d
  ]7 p+ I( r! b! d. E
    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,- o4 N! X, T% w+ Y8 i
           (LPVOID)pSCIP,
# M! f8 C& W, o- U- ~9 [. L           sizeof(SENDCMDINPARAMS) - 1,
' E) |2 g& j3 b# S           (LPVOID)pSCOP,, j8 ^8 e5 s$ l5 M" q  J
           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,0 r2 X: n" g9 ]1 Z* F6 l% Y- `
           pdwBytesReturned, NULL);+ j* W( t" [9 R: B
}
8 ?* L* T3 c% `# G5 e//---------------------------------------------------------------------------3 K: [6 K& L% A1 V7 A8 z
// Windows 95/98/ME 代码: x; i' v$ \" d* k- l+ ~, I1 b5 T4 m4 j
//---------------------------------------------------------------------------
1 a% j; H+ f, Y& s  T8 X) _// ReadPhysicalDriveOnW9X
5 Q2 R/ y$ P5 j7 Dvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)' |0 L, D. e# o! ]; z% g
{
% f9 k- l, v! ?) C    WORD wOutData[256];
5 t4 ]. Q( e; G  m/ O* p3 d5 c    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
0 j3 j: _1 d1 r! K, A4 S& d% b* p$ i  R
    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
# ~# \* ?/ V* e$ m4 ?& m    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以7 A. U( T. ?8 F1 j' D
    // 避免蓝屏的出现。(期待高人能指出原因)2 |& A2 |" y: i7 @# C7 i
    for(int nDrive = 0; nDrive < 8; nDrive++)
$ a8 t. i; [: B8 B. P5 ~    {
, L( u" a2 |% z- q' h* R5 X        WORD dwBaseAddress;
9 K1 _3 O/ E2 ]2 }( v7 V; K        BYTE btMasterSlave;         // Master Or Slave
; L7 {5 T/ k% i" a* c, \        bool bIsIDEExist;0 B' U% p: b6 @# t/ H
        bool IsDiskExist;
8 C2 ?+ ]' y* q. H- `! s8 j
% ~: x. O$ A5 C8 c) f/ G1 n% o        switch(nDrive / 2), \% m& j5 a5 C9 `5 j0 k" r
        {
# j3 v/ }% [! x3 V$ Y1 W9 {, I  V; y3 v            case 0: dwBaseAddress = 0x01F0; break;/ b% Y  Z& w4 a5 M" |& o
            case 1: dwBaseAddress = 0x0170; break;
* G/ q% a; O) I            case 2: dwBaseAddress = 0x01E8; break;
+ J: ]4 q" J6 i- n/ I' r4 {( v$ P, {            case 3: dwBaseAddress = 0x0168; break;3 S) ^8 b: v2 j
        }
9 @3 y5 o$ N# H; ?
# o- p& ]  `  @# T# r+ I% `9 H        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);3 l0 e& v' }3 ]

  g- ?3 T) ?5 {: J+ X        // 进入Ring0
: r1 ?3 e( |- b9 @        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
2 c, L, m. V: Y3 F" q. j                bIsIDEExist, IsDiskExist, wOutData);2 s* Q5 i5 Q. U) C/ ?
    }
7 c. m4 t! I. K; W. l1 j: H
$ I6 t& ~* @8 q8 E; ~+ O    // 开始读取
0 J' p* ]# ^" J+ B. o    for(int nDrive = 0; nDrive < 8; nDrive++); [( \5 s1 @+ ^* U( r
    {; f6 w: q# p! K! P$ s; `) C
        WORD dwBaseAddress;! Y! T5 x- B% h- |
        BYTE btMasterSlave;         // Master Or Slave
2 |  R  v$ L0 c: u. Q' d        bool bIsIDEExist;
6 c. a! t2 `0 D* P+ H% W5 ]2 c        bool bIsDiskExist;
: N* a( D1 Y* ], i5 Z: e( W8 Z        switch(nDrive / 2)$ D7 c0 \, e/ \% _* S4 N  N/ v* ?
        {
& B# [5 q  H$ z+ S: C6 M            case 0: dwBaseAddress = 0x01F0; break;) R7 Z# e1 \3 r! c+ O
            case 1: dwBaseAddress = 0x0170; break;
8 t0 S' v! A/ T  {            case 2: dwBaseAddress = 0x01E8; break;
+ {4 n  n+ O0 T7 V7 p            case 3: dwBaseAddress = 0x0168; break;& u: D' j' {5 m& O: t7 r
        }
; y9 `) ~; q: F) }* ~6 D! Q2 P
' R8 `$ x. Z' V: Y: F        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);5 t$ ]9 j! q8 s8 |4 G7 v" f4 f

7 @& v, G3 L; m2 G        // 进入Ring0
2 C' e1 ~' }) u7 E% H        bIsIDEExist  = false;
! F( n7 z$ w/ W! T5 p        bIsDiskExist = false;: l0 |) F- r' ~5 w3 W0 R; S
        ZeroMemory(wOutData, sizeof(wOutData));
: {" W; @. i% K* i5 B# o
, F( V, p/ L* A0 F' T        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,+ t- Z/ F! `6 E2 n! I
                bIsIDEExist, bIsDiskExist, wOutData);5 a+ F5 x: E7 D0 G0 W5 K
. P8 d: P, u1 L; m
        if(bIsIDEExist && bIsDiskExist)+ G8 b! `" ^7 `0 W
        {! ^& X7 y! Q& F: d5 W. }
            DWORD dwDiskData[256];
* J6 d4 `6 @1 I! \7 @            char  szSerialNumber[21];
8 R  F) m) |% y; P- p$ \            char  szModelNumber[41];4 P4 j+ v% M; s  {- [
4 x6 B3 O8 K$ n$ x
            for(int k=0; k < 256; k++)! u1 P4 L. |2 \' p8 j- H) @5 ~
                dwDiskData[k] = wOutData[k];9 ?' B! B3 `& o  n
: X- k4 X$ P% S: [+ n
            // 取系列号; K7 k# ]3 F0 C2 O- P& g# y
            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));  u$ H" X4 @( j, J4 @! E# d: {- N1 [
            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
2 D- H9 G; F# X9 k1 n2 Z  r6 b: z8 @, d/ }
            // 取模型号# t& h4 [9 U7 |0 s2 i, R
            ZeroMemory(szModelNumber, sizeof(szModelNumber));  P. h6 @5 ]- c4 _+ u" o  ?: S
            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
) s; r- G' p( z$ \
3 O  ^6 N) P( s            pSerList->Add(szSerialNumber);* Y3 @4 B' g4 T- E/ s/ }5 i  ?
            pModeList->Add(szModelNumber);; _1 [# r& ^4 V5 r- j$ F7 \
        }
' O! `5 D. o& Z7 @5 T& G    }2 Z! W- X! U5 v! q
    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
; T. \" m4 s- L' |* `$ V}2 }8 N' M0 m& n& N& d8 F) j. @! n. ^
//---------------------------------------------------------------------------
: ^6 H6 C' }5 j" T" Q// 为防止不负责任的转载者,在此注明原出处信息,请见谅。
+ J3 T+ T2 E% R4 ^// 资料收集整理:ccrun(老妖),欢迎光临C++Builder研究: http://www.ccrun.com& s0 W# b1 N; Y9 f0 ]$ n( S3 T% L
//---------------------------------------------------------------------------# m4 V: {" ]$ }+ z/ }
// ReadPhysicalDriveOnW9X_Ring0()
8 j  U, c+ M7 J3 o1 M//
7 x4 `4 x7 ]( W5 W. N3 v: Y( B! c// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h" S3 s. u( D# r1 s" E
// btMasterSlave = Master(0xA0) Or Slave(0xB0)
$ D# K& |0 I5 E//---------------------------------------------------------------------------
; Y8 t5 k' \6 G' `. v# vvoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,4 s! W3 O3 x& w: P
        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)& s9 Y/ i4 h0 c& i0 Z4 X
{
( }8 p! X4 U4 B# C    BYTE  btIDTR1[6];
3 v5 R* l0 a5 q- p2 A    DWORD dwOldExceptionHook;
- x! `) b! X5 x  P; m    const int nHookExceptionNo = 5;# u# O2 C& h9 p) r: o

4 F: z& }  w. P) Z# j* z& Y& A    BYTE  btIsIDEExist = 0;) {  ]# T! n; R6 }3 N! i/ ]
    BYTE  btIsDiskExist = 0;1 U6 z9 p* L8 }3 y4 }% w
    WORD  wOutDataBuf[256];3 D+ |% q/ {4 t- V' D

! ^: x% E. a) S. @+ F- q    BYTE  btIsFirst = (BYTE)bIsFirst;. J! U9 I5 P! G  F7 I* s
* G$ e1 g, I/ K9 ~
    const BYTE btBit00 = 0x01;
* ^7 B1 O+ L7 E9 g    // const BYTE btBit02 = 0x04;% V8 O& E$ B1 m" ~
    const BYTE btBit06 = 0x40;
& [( v: [/ H3 y1 C    const BYTE btBit07 = 0x80;- I/ @. t1 Q  j0 g: O5 y1 g( r
    // const BYTE btERR  = btBit00;/ S1 Y0 S+ E) T
    const BYTE btBusy = btBit07;
2 o: t$ L7 T( \. T    const BYTE btAtaCmd   = 0xEC;8 b3 ^2 _7 P+ q
    const BYTE btAtapiCmd = 0xA1;. P$ n, h% ^$ J5 n! d
' T, E( d" c, u( w8 [* M2 ]
    __asm* ^, [6 R' \* }2 o$ Z. ^: V
    {5 d2 p4 P9 J% V9 |* C
        // 必须先执行这条语句
, t$ M+ O: @- U! m1 V% x' _* d6 l( f+ y        JMP EnterRing0/ R0 r8 L9 _4 h, P

3 }+ a+ J) f$ T! j7 c# J        // 定义过程
6 k+ g- \: Y% |2 u        // 等待IDE设备直到其不为忙为止
- n% r4 K) ~; z# M0 f        WaitWhileBusy proc
' f2 R  ^1 d: Y) C: j; A5 n2 i: |. _- D( q
        MOV  EBX, 100000( [$ b/ j2 E' H9 N. y. `4 }
        MOV  DX, dwBaseAddress: F9 Z  p. b' p! N- _9 X" F
        ADD  DX, 7
+ ?. i0 E0 O/ I  b# z: C% y# y
4 W1 }2 F0 r: p6 I1 G        LoopWhileBusy:) p$ O$ r1 z* z! Z: f6 E0 `
" H- _1 U, E. y  W6 n5 M$ C
        DEC  EBX
3 Q- D" u8 p, J. K& f9 J' ?        CMP  EBX, 02 [4 c" P8 l- k: U: `# q
        JZ   Timeout
- M7 Z$ T4 g% S& T+ d7 J        in   AL, DX
% x8 |$ n6 Q" c  X/ V; y$ _* E        TEST AL, btBusy2 M* s/ Z2 n% V
        JNZ  LoopWhileBusy
0 O4 r7 w" }* l8 V7 _        JMP  DriveReady3 O8 e. P* A( V) d2 J

1 z# _* ~4 P$ k) _        // 超时,直接退出7 y& f* E. N0 A, {: V( [' Q
        Timeout:
  ]; M$ N, u- Q; N6 ]5 l8 P        JMP  LeaveRing0
. j( k2 j& l7 j+ z" P        DriveReady:9 H5 G7 J( p+ i2 e1 @) T4 W' E
        RET% C2 p! o: M8 w0 c/ |1 B
        ENDP   // End of WaitWhileBusy Procedure" ^) \. V" u. x# f2 O* g1 q; N
/ T9 P# B, j& I0 E( z$ n4 D: j8 B2 O
        // 设置主盘和从盘标志% p4 V; f  }! P+ p
        SelectDevice proc
9 _/ F  t, W/ }0 ^2 |: h& u
) v, o8 o+ e: u+ k5 e4 \/ K. W        MOV  DX, dwBaseAddress
3 s# k( ]+ t$ X: ~2 s- B- [        ADD  DX, 6
2 w' J; w# E5 n# }( ]1 n        MOV  AL, btMasterSlave% b2 ~4 b) G3 V  F( x2 k

6 n1 ?( w" l! ^1 Q! ~        out  DX, AL' {8 x6 b2 i, r- b4 P
        RET
' s9 f5 j* c  k( z  X7 m
* y0 d2 E4 p9 l5 ]2 q$ m4 S0 z        ENDP  // End of SelectDevice Procedure5 ]3 J- @! Y" W7 ~" n3 X2 O* b# M
3 _8 P$ h3 n) z* _
        // 向IDE设备发送存取指令; C( O) r5 X; t+ n* K  Y6 Y/ }7 W
        SendCmd proc, Q$ M' A9 D  R9 {% u: B
: ?, H9 j" h  H
        MOV DX, dwBaseAddress
, d" Q4 U5 d6 K; j8 ^- i        ADD DX, 7
: M% `% B7 k9 U! F$ Y4 k        MOV AL, BL // BL是主从盘标识,在过程外设置
% B  [8 x) `1 j% }        out DX, AL
& ?, _" L9 z3 n% `; I        RET
4 x$ s. j; N8 a5 k5 r+ a        ENDP  // End of SendCmd Procedure, ]: z! @! v$ f# I; u- ^2 O
# T) t8 h& g# U9 p; a8 L! E- a* b
        // Ring0代码* L2 ]6 E1 U7 j: j& ?) n# c
        Ring0Proc:) Q0 t& f9 y) R$ b
        PUSHAD. U1 D4 h+ ?3 h8 I9 O! r
        // 查询IDE设备是否存在
- L; @0 Y0 a% m9 |0 w        MOV DX, dwBaseAddress2 ^- l- _7 S" f1 c' m, p, A
        ADD DX, 7" t( R  A& v7 \$ V+ r" ?
        in  AL,DX
' q- a  M8 D- [. ], Y6 K% ^- G& i, g8 k+ U( W5 F6 }3 Y6 ~
        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
- t, k$ \+ [( W* R$ h        CMP AL,0xFF
1 Q5 n# t) j5 X        JZ  LeaveRing09 ]9 r) }- S7 |* q/ a
        CMP AL, 0x7F
( d, a( V" l7 f8 R) k  e0 c2 }" m        JZ  LeaveRing02 u) Q- U; C0 W- [7 d2 T9 a. e
% s  k5 n" [& g1 z4 J/ l
        // 设置IDE设备存在标志4 H0 ?4 L) p! [5 e
        MOV btIsIDEExist, 1
' {+ ^" g1 O$ Q& \, H; a5 b& f, Z1 u' b) w1 o6 O3 L1 n
        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)8 z! @$ Y0 J7 f+ ~( N0 ]$ r9 d6 B! c
        CALL WaitWhileBusy+ T" N5 @, K; s  D
        CALL SelectDevice% n( M! `5 [2 V% u

# G: D1 w: X* _        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
, n% v1 @, H- p  ]; W, D        CMP  btIsFirst, 17 R; `$ p# ^( `
        JZ   LeaveRing0
3 B5 W. ~2 K: ?) q) ~; \4 g( _( l# q4 D* _# ~9 e- @% R9 V
        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???& h! O8 Z/ m3 k3 u6 n' s9 ~7 Y
        CALL WaitWhileBusy
4 l9 S3 ~, k% j8 ^- I% f
5 ^4 ?( k3 E* K/ ~; Z1 N1 L        // AL的值等于cBit06时,不存在驱动器,直接返回
) X. `( m0 P$ y# D        TEST AL, btBit06
4 W& n+ @2 n, r9 e        JZ   LeaveRing09 E' H9 g6 Y! P

4 T* N+ e* @4 N        // 设置驱动器存在标志& X4 H9 Z! ]* [
        MOV  btIsDiskExist, 1+ k0 J& ]+ u0 a2 j
% l( |+ M6 H- l, I
        // 发送存取端口命令
0 n& c& V* w0 V$ N" d! j3 m        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,4 B7 J* S9 o9 A/ @, \
        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令8 N; |& ^3 w" W) s. X
        CALL WaitWhileBusy
8 }8 ]2 @5 d/ F& W" `* _5 T& y& I        CALL SelectDevice    // 设置主从盘标识$ T* B8 q& [% [( M8 h& ?
        MOV  BL, btAtaCmd      // 发送读取命令
6 ~( _* E; w+ u0 _7 u- d5 @        CALL SendCmd
6 Z9 A2 S" z% m9 M3 g# f0 z        CALL WaitWhileBusy5 [9 O+ p: L  H% f! G2 j5 Z3 m/ t
9 c, }: [, l* Q7 x3 G
        // 检查是否出错
/ O+ z. P/ y0 x5 g6 O: p6 }        MOV  DX, dwBaseAddress
5 p4 _* S3 k! ~% J3 k        ADD  DX, 7& p9 p! c7 g5 H
0 y4 T( I/ U# k! e( D, A
        in   AL, DX
9 L0 G$ L6 _6 o6 y0 U, q* S# X& Y7 @0 J2 t# K
        TEST AL, btBit00
4 g6 m" p# ^% Y7 }7 y" W  ^        JZ   RetrieveInfo   // 没有错误时则读数据. Q1 c( T: l$ [* @/ r" |
' D+ h. }: {9 J( i% o
        // 如果出错,则进一步尝试使用ATAPI设备命令
; M! o' s8 T" O! \! u        CALL WaitWhileBusy
. [  j! ~! x7 W  }( {: \+ E7 ?        CALL SelectDevice' P  V+ _4 e; q
        MOV  BL, btAtapiCmd
; ^( @7 D4 z. `) C4 `        CALL SendCmd
  D. p' d, |4 H        CALL WaitWhileBusy
  d; B, S: a* f! ?. `( a6 r3 u6 s$ ~9 i1 d
        // 检查是否还出错
1 `7 K5 q, g! q, N, i        MOV  DX, dwBaseAddress; z5 z/ M% `  i! ]/ s' e% O
        ADD  DX, 71 g- z, g7 O- L) a0 N
        in   AL, DX
8 L  b% }' f% b: o0 P3 Q        TEST AL, btBit00$ b- q9 ~3 n4 q7 M- E! Q* O
        JZ   RetrieveInfo   // 没有错误时则读数据! g8 {! }' O6 A( d) _8 _
        JMP  LeaveRing0     // 如果还是出错,直接返回) }' p( o" h" z, ]5 w

" N0 D7 Q/ k. T# W" p. ^) S        // 读取数据
1 r4 b/ a4 b  S% O        RetrieveInfo:6 g' \: ^: K# g" d/ n1 e

% G; c6 X$ N6 g8 E        LEA  EDI, wOutDataBuf
8 q5 e- B1 Q! k. ?2 ?' @        MOV  ECX, 256
! B3 t1 `# Y( p6 K: T        MOV  DX, dwBaseAddress+ M% b; A0 x9 Y' K- v* ~5 R" H
        CLD2 l6 J8 x) f0 v/ D+ J. s* [, o

. l/ ^; W0 J( U' I  u* n        REP  INSW5 v6 _, [5 z! {- G. k7 k7 e
/ g! _) z6 B8 O# |) L" e
        // 退出Ring0代码
) G& x/ ]8 s' c. \) E        LeaveRing0:1 ]. \/ W* L, g' a3 `% T$ |" A* y

, F8 _1 g3 L3 ?! U# i6 m        POPAD1 `% `- g/ _9 N' E: n
        IRETD# T7 l/ d1 D! h; y

6 Z" I$ g% B& Y# E9 T        // 激活Ring0代码
" ]8 d; g( t. ^8 [  K" _        EnterRing0:$ P, \- o0 F6 D0 ~2 W$ h( v) q: u
: P* I8 |2 o; x+ j3 \
        // 修改中断门
& z$ D' J; R9 c7 S4 i        SIDT FWORD PTR btIDTR1
; H' K9 [+ `- n$ o# ^        MOV EAX, DWORD PTR btIDTR1 + 02h$ O8 O& I0 K7 \# J
        ADD EAX, nHookExceptionNo * 08h + 04h: h& m, @, L- ?) P/ x
        CLI
( r+ f* b4 `/ W( {* c% C8 u" E  [6 S/ j$ ]- |4 p, E: H8 R
        // 保存原异常处理例程入口5 M+ A' g  n* m1 J
        MOV ECX, DWORD PTR [EAX]$ p. A! d0 j. @% y
        MOV CX, WORD PTR [EAX-04h]7 ~" C+ h! ~+ i2 A  ~6 J& x
        MOV dwOldExceptionHook, ECX
: g+ w% C  X5 m* B* R0 t' j" J( P3 c
        // 指定新入口
$ ^7 p  y# w: U% S+ S9 n        LEA EBX, Ring0Proc+ [4 o) [* h9 C' o0 E8 z1 M7 g
        MOV WORD PTR [EAX-04h],BX
4 w( b0 r2 p  \        SHR EBX, 10h3 m$ T; i% y, Z( s% G5 z* W% J
        MOV WORD PTR[EAX+02h], BX
4 ~. L, U  ]5 A1 C" N1 ^2 q! q- q; ]( V8 Q8 q* r$ }
        // 激活Ring0代码6 w# n* N; a9 D' S5 C! `# L
        INT nHookExceptionNo6 _6 y1 E  p; o% c8 f6 V$ M

" q9 d( J5 ~" Q# w- D4 l2 g        // 复原入口
$ h3 i  ]; N: E4 e5 y' E        MOV ECX,dwOldExceptionHook
9 j% d) y7 c' y7 w$ f. U% }( e        MOV WORD PTR[EAX-04h], CX/ T) @4 Y8 H- \$ C1 q
        SHR ECX,10h9 M/ g( \/ [' b" u
        MOV WORD PTR[EAX+02h], CX
4 Y( S9 E5 X8 J7 P: }        STI
- h$ {. u  A3 J5 \' n- H    }
2 y5 b9 ?4 ?* J) D' k! y    if(!bIsFirst), [5 f  G7 W# T5 `& ^+ o- F
    {
$ Q# s- `1 Z* Q, B. @        bIsIDEExist  = (bool)btIsIDEExist;9 ]0 j3 e4 W0 u
        bIsDiskExist = (bool)btIsDiskExist;$ P8 B" p3 b. d
        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
, |: H* J8 U7 Y3 l' I! m    }& w& ]8 D2 J4 N& }9 w
}6 h$ ^) m- y- W7 L# ?
//---------------------------------------------------------------------------
( e! O+ q. B- q4 y# J3 ~% u// 调用方法:
* X- I) {2 t7 G, [/ j# B' r( ^. S) Xvoid __fastcall TForm1::Button1Click(TObject *Sender)4 V1 ?+ W1 A8 W# b( j& ^5 O0 n' i
{2 i* H# O1 K4 ~. g$ S' @8 q8 h
    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
& g) j" D  ~8 j% n7 m$ n/ F( G7 I) [}- P" m2 E+ L# D: b" ^& y9 i1 l8 Z
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-6-19 04:24 , Processed in 0.018831 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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