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

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

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

  1. 2 n3 h7 A' v1 q7 ]! ]
  2. #include "StdAfx.h"" g/ e( f; n/ L/ M7 _
  3. #include ".\puiddisk.h"
    4 a( l0 Z3 e* [8 I
  4. #define _WIN32_DCOM
    1 K* \) _+ c4 H" d4 P% ?% ^
  5. #include <iostream>9 B$ M( {" \1 p: N
  6. using namespace std;6 Z& m6 F7 v, N/ V3 l- Y& P+ H
  7. #include <comdef.h>
    8 Q$ v6 M; q# [/ c8 O* \# a, k2 W
  8. #include <Wbemidl.h>1 @5 |4 Z4 `0 F! d5 T

  9. ! n0 z  y# ~8 [* }
  10. # pragma comment(lib, "wbemuuid.lib")) ~" s2 o) I, B% E! e# _) }
  11. CpuIDDisk::CpuIDDisk(void)7 _2 e( x( R% k" W" l" `0 Z
  12. {/ Y+ |- g- ~  {6 h& Q2 p( ?
  13.     GetInfomation();
    & x  \" }( F9 u) Y5 Y5 \
  14. }7 S* A6 P1 M# p  h, j

  15. 1 T3 t. C( N# s2 ^, L# T8 Q# Z
  16. CpuIDDisk::~CpuIDDisk(void)
    . [, b' D% P! u. v6 o
  17. {5 j) c) g4 U, A, {/ S# ?
  18. }! a9 U5 |  |* A8 Z
  19. int CpuIDDisk::GetInfomation(void)
    ( F0 O* v' X0 M' ], z7 F
  20. {! y  {! h2 l& j6 i% _
  21.     HRESULT hres;. `1 K3 O; c/ B+ Y
  22.     //步骤1:不是必须的,COM只须也只能初始化一次- Q/ {2 `9 m; {* [8 z7 j/ }: ^9 G
  23.      hres =  CoInitializeEx(0, COINIT_MULTITHREADED );
    7 G/ A6 R5 l8 X. b% o
  24.     if (FAILED(hres))
    , a0 f0 f6 j9 o) V2 N: V
  25.     {: H) c! H; i: p2 |1 B3 d
  26.         return 1; //初始化COM异常:注意,COM只须也只能初始化一次
    0 v- ?! P. g* S4 ]# I) A4 [
  27.     }
    # b. d" X; {$ I
  28.     //步骤2:不是必须的,COM只须也只能设置一次
      r, f; [+ e! y" k' `
  29.     //Set general COM security levels7 e2 n* ?- x7 N% O9 s9 k9 W- V
  30.     hres =  CoInitializeSecurity(
    $ t0 ?8 H, M, _" L- l7 h8 o
  31.         NULL, 2 i- P& T) y' O! K& K9 Z3 m
  32.         -1,                          // COM authentication
    " I: e- E: q3 O. \! O6 a9 J
  33.         NULL,                        // Authentication services
    ! d6 q' X: I, @2 u
  34.         NULL,                        // Reserved0 V) P1 w+ ]3 I6 g5 t2 `6 M
  35.         RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication ' ?' A" {% j2 T( K* x- s  C1 S
  36.         RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  
      ^) R. q" L8 r' h# S* N
  37.         NULL,                        // Authentication info6 p" ^* k. t- }) M( ~0 X
  38.         EOAC_NONE,                   // Additional capabilities
    7 k+ n4 o' ^0 s+ H& d& ^) n" U
  39.         NULL                         // Reserved3 o; o7 L' W* O% A  R) n' y
  40.         );8 c3 Z( I1 c7 M5 I; _3 z
  41.                       0 ]1 M; }' B+ _- a
  42.     if (FAILED(hres))
    % B1 [# ~! J# b+ n( R
  43.     {- d% G/ Q# i. U+ ?) D) Y
  44.         CoUninitialize();
    / s- R! p' s: H6 }' m
  45.         return 1;                    // Program has failed." Y4 b: x1 V# Z5 \, B6 d- n; ?
  46.     }+ R3 `( |* u3 q
  47.    
    " Y# A5 R4 z5 i/ t+ c2 T
  48.     //以上不是必须的,若已有“::COMInit();”,则要跳过
    2 z& y0 N' ?! ?! j2 Y3 C
  49.     //步骤3: Obtain the initial locator to WMI # ?9 S; b( N* j9 [7 O9 R; f' }
  50.     IWbemLocator *pLoc = NULL;
    ' c7 [4 s4 Q6 l; c" M
  51.     hres = CoCreateInstance(
    1 M7 M4 X& h  n5 N( h
  52.         CLSID_WbemLocator,             5 M0 L: l- C# \2 v& B
  53.         0,
    4 ]+ ?4 V  ^. I6 U% A2 `& I
  54.         CLSCTX_INPROC_SERVER,
    4 C( F* j4 b( u0 L' N9 i6 m
  55.         IID_IWbemLocator, (LPVOID *) &pLoc);5 k: g9 W& E* F3 O7 P. [

  56. ( ]+ J; Y* Y6 q! L4 u+ c
  57.     if (FAILED(hres))
    3 _/ A" c! l$ l) p& @: k
  58.     {- z  P% R/ r- H4 S
  59.         CoUninitialize();0 P& A5 |; r8 |+ }( F& }6 D
  60.         return 1;//Failed to create IWbemLocator object0 \- g( r$ j2 `9 |# D
  61.     }8 B9 w: y9 ^7 s$ S
  62. " a0 Z) N. ?, ?2 A
  63.     //步骤4:Connect to WMI through the IWbemLocator::ConnectServer method) S- i8 ^/ n6 _- t9 q' ~. X% a
  64.     IWbemServices *pSvc = NULL;! u5 P: l: @7 b# _' z0 ~% `: x  x
  65.     hres = pLoc->ConnectServer(
    4 ~; a0 Z9 p9 ~0 k1 q+ O
  66.          _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace
    0 v; v  I  I$ z# p) h" X
  67.          NULL,                    // User name. NULL = current user
    3 e  V( F; h9 D: c9 J+ x
  68.          NULL,                    // User password. NULL = current
    # s8 o: ?+ ]7 V( @' l# y
  69.          0,                       // Locale. NULL indicates current
    ; l' p; L  n7 F) D6 R
  70.          NULL,                    // Security flags.
    3 H, N4 k/ c1 ?4 `& Z$ t5 D
  71.          0,                       // Authority (e.g. Kerberos)
    $ `4 r3 T' @8 j
  72.          0,                       // Context object 6 O, y( C- n- B
  73.          &pSvc                    // pointer to IWbemServices proxy& u6 u" L. B' z- k, E# p: \% s
  74.          );  C) f1 k, ~5 J4 f- A
  75.    
    ! w0 O4 @% G9 [+ h) g9 r5 ^
  76.     if (FAILED(hres))
    * {  C: B. j( E! O, Y6 ?1 l
  77.     {
    : b; @- Q5 l6 l( D& @" A
  78.         pLoc->Release();     
    0 {' m8 ~/ r/ \( T
  79.         CoUninitialize();
    1 F2 }$ \0 \8 @  G% F: X6 c
  80.         return 1;                // Program has failed.4 z- i& A' m! [' W% Y
  81.     }, y# P$ n0 w4 O5 g- K3 D+ z
  82.     // 步骤5: Set security levels on the proxy% E- h9 F6 _; l+ U% Q: v9 h
  83.     hres = CoSetProxyBlanket($ g& n' Z( P$ J5 J
  84.        pSvc,                        // Indicates the proxy to set
    8 F9 R8 ~9 h: _$ R6 R9 \3 c
  85.        RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx
    3 F1 D! X1 }" n$ C2 @# P. N
  86.        RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx
    , K4 w5 H5 m* n9 E% U& t
  87.        NULL,                        // Server principal name 4 J" s" ?1 E% w6 a& B8 F
  88.        RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx
    # |* e" r; n- R: |
  89.        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx. Z$ m! V) Q% e2 {+ e
  90.        NULL,                        // client identity
    - E# J; d8 n# n( |( o, |" Q. u! f2 n% q
  91.        EOAC_NONE                    // proxy capabilities / l7 R- `# K3 H0 p
  92.     );4 ~8 C) f) r) _$ s

  93. ; d0 x+ _" U6 e6 \  E3 B. r9 J4 Z
  94.     if (FAILED(hres))& \' ^2 G/ F% N7 o. K  |$ T
  95.     {
    . V# r8 o( ^& ~0 c, C1 n
  96.         pSvc->Release();  z6 M# P7 b2 b  }. x) d
  97.         pLoc->Release();     
    ' m6 [- ?- L9 v- s8 Z9 h
  98.         CoUninitialize();* V8 k& S- t& Q' \) R* ~. y
  99.         return 1; 9 n  B9 K/ w0 K/ @" K) R0 [, u8 G
  100.     }4 ?! c0 I- L! P, D
  101. 8 k/ g3 t6 ?! q5 x+ z9 N. `0 v) ^
  102.     // 步骤6:Use the IWbemServices pointer to make requests of WMI ----
    & k8 M& T3 Y* K9 O2 C
  103.     IEnumWbemClassObject* pEnumerator = NULL;7 |4 w4 \# ]+ Q$ V; h/ S
  104.     //计算CPUID2 U& D7 F3 q% x$ b  }" x5 Y- o) Z' e' R
  105.     hres = pSvc->ExecQuery(
    5 |6 g% ]1 Q( G  H9 x6 q
  106.         bstr_t("WQL"), ' M) _) b" e8 `9 ~, j" h. m7 p
  107.         bstr_t("SELECT * FROM Win32_Processor"),//Win32_OperatingSystem
    ( N- J9 @" V) k9 ?
  108.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, ) K4 e# y( _3 I
  109.         NULL,
    & [( H# {# W& w5 c, u2 p
  110.         &pEnumerator);
    + l& W) U; @% |) U
  111.     % ^# d. z" u, O5 m8 t6 e# o
  112.     if (FAILED(hres)). n% U' Z4 T; V: n/ o& B, ^! H0 o
  113.     {/ Y* |3 n2 ?+ W4 a8 p
  114.         pSvc->Release();+ {) d. \; I( z
  115.         pLoc->Release();, @7 F6 g8 |% ~0 f4 }  S
  116.         CoUninitialize();
    ) O( S6 U! |5 w9 a/ ?
  117.         return 1;
    ! O" D- O- l6 @- `6 f, [
  118.     }
    * g! u/ ?: B0 B2 Q" ]! {2 ~
  119.     // 步骤7:Get the data from the query ) f7 K, b' [5 T$ x  J) \
  120.     IWbemClassObject *pclsObj;- N3 M4 b/ P0 f% M9 D% Q$ p
  121.     ULONG uReturn = 0;& b8 m: U/ ]2 b9 {+ D% Q; `3 S/ N
  122.     while (pEnumerator)6 r' ^8 w. x! [( ~8 S1 l3 _# z
  123.     {9 }+ e8 l; G' V  E5 f+ a
  124.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
    * N0 ?2 Y# v3 D) ?/ o% G) \- K
  125.             &pclsObj, &uReturn);
    6 H3 K" m+ T5 A' j8 U

  126. + _1 J3 ]: d( m  f
  127.         if(0 == uReturn)
    , r2 x8 W; H# {- m( n
  128.         {
    $ O2 G& O' q. g) w, t* ]
  129.             break;
    2 X% X6 e7 Z- ?- @* |' _
  130.         }
    : x$ m& V; S4 D7 c- E! P! H- h
  131.         VARIANT vtProp;+ |' ?7 W4 o' s2 V
  132.         VariantInit(&vtProp);% b1 X/ T" n  W6 L# y
  133.         hr = pclsObj->Get(L"ProcessorId", 0, &vtProp, 0, 0);4 V" r4 n6 |" X9 o
  134.         strProcessID=_com_util::ConvertBSTRToString(vtProp.bstrVal);//strProcessID:类级变量* U: H8 g6 \- R8 K
  135.     }
    & p2 m( f% u) A  M1 b' m
  136. # L- X0 d  P4 `$ y6 i1 M8 k
  137.     //计算硬盘系列号9 K1 h5 d8 }5 t8 P; Q& Y/ f
  138.     hres = pSvc->ExecQuery(
      W, y6 p' \7 ]- ~* E! x
  139.         bstr_t("WQL"), ! Z) K4 T7 g8 Z7 Z1 J
  140.         bstr_t("SELECT * FROM Win32_DiskDrive"),
    % J% g0 E7 X' N
  141.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, ( v6 i: k6 ?8 x* x. P7 _3 i5 r% C
  142.         NULL,
    # o' S9 s8 M2 B# q( X8 f1 C# t% g
  143.         &pEnumerator);
    7 `5 U+ w5 d1 q; j. Z9 g
  144. 1 ]9 b4 n, U/ u6 ^' A* l4 H! i! O
  145.     if (FAILED(hres))2 G5 \; ~! l# h* ]
  146.     {- Z4 X$ V2 N  r7 }
  147.         pSvc->Release();
    1 E5 @! r! p0 f! E. \4 X
  148.         pLoc->Release();
    0 ~8 N: J" k: U
  149.         CoUninitialize();8 c1 K/ R# D$ B! i5 A5 S3 G
  150.         return 1; ( f, N1 b3 G) W% [/ C1 k/ [* d
  151.     }
    3 `$ t$ b! m* S; M1 s
  152.     while (pEnumerator)
    6 D0 O& F4 f9 P6 K& v6 ]+ e
  153.     {. }6 e7 s! K$ R  T' r6 g
  154.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
    ) u- a) T7 I7 c& ?, U( p, t
  155.             &pclsObj, &uReturn);
    1 ~* X$ Z& J' N+ V5 ]" t0 P+ f

  156. ! r4 v' S) J& l$ b" K5 d* [2 h! f; n
  157.         if(0 == uReturn)7 J3 j1 h" h. T9 g6 i
  158.         {( l& Y& p1 o3 N( l
  159.             break;1 g6 ]+ C2 L* ^6 M
  160.         }
    ) k: G/ i0 l3 x9 L$ E! G1 k
  161. " `) O% w) i6 |# V2 B
  162.         VARIANT vtProp;9 b  G  x( i: u4 z
  163.         VariantInit(&vtProp);
    2 {6 x! Z6 q4 b* ^" ~$ K; P
  164.         hr = pclsObj->Get(L"PNPDeviceID", 0, &vtProp, 0, 0);
    * p; j- C. ^$ K1 B1 v0 D, |
  165.     strDisk=_com_util::ConvertBSTRToString(vtProp.bstrVal);
    - H2 e. m8 y; U# {. ^
  166.     }
    5 F1 c3 ]/ f4 ]/ k- W& ^1 T
  167. ( S+ K+ }+ y. n, w( ~& C# e0 Z
  168.     pSvc->Release();
    , N/ _; p$ ]+ Q* [9 t
  169.     pLoc->Release();6 E0 b' i: S' q$ x; q7 x* z
  170.     pEnumerator->Release();% \6 V$ t8 k; H
  171.     pclsObj->Release();- s! I) X$ F4 \, q9 E
  172.     CoUninitialize();
    0 q; q' D) M2 e* K: E* ]) [# j
  173. ' E$ y1 [& H7 G& A' ?0 ~
  174.     return 0;   4 ?3 l9 N. n: B- N! q
  175. }: ]6 r8 O9 t4 H  o! W
复制代码
 楼主| 发表于 2010-10-11 19:21:05 | 显示全部楼层
本文代码经ccrun(老妖)在Win2k下试验成功.# H, X# \  k% z

' t2 ^' I+ V# [% R#include <WinIOCtl.h>: F. d. H1 y+ F3 Q5 I2 \4 w
#include <stdio.h>
3 h9 M* C7 T% a) E+ j1 f# V$ f. n  z$ r/ `# w2 e) ~9 X
#pragma inline
  a" P8 p2 \0 J' I  X//---------------------------------------------------------------------------
& Y3 K2 ]; q4 j// IDE NT/2000/XP专用变量
. g$ b" f/ ~; w4 ]2 I: k2 z#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS$ S5 x0 Q3 x  e' q
#define DFP_GET_VERSION         SMART_GET_VERSION
" M* U" C, ]2 G7 P$ ^#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND$ m+ C0 A$ F. j2 w" K
#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA3 g( ~/ I9 _5 r
: d; @, `' ?- p  i9 [& W- v
const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令4 W6 p3 u  z9 u' J& U  ^
const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令7 q8 v+ Q, M+ O. ~1 k; Y& l( U# ~6 x; a

. h# H7 V: c- T" D- Z, Y% Cconst int MAX_IDE_DRIVES = 4;) Q# ]4 P" {- p/ t

' ^$ g/ J- ~* m5 |% k0 g5 I7 w  \9 z// SCSI专用变量5 p) X7 O2 N( m$ A  V! J
const DWORD FILE_DEVICE_SCSI             = 0x0000001B;
+ i  e; u' O4 z  Q+ N' O0 yconst DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);$ P4 Q" b  I# i! C: p, i% P3 H/ `2 P
const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition' R  y9 ^, H( s9 m4 R3 u$ @
const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
% j& @; x& q% C+ v# F! L6 d# x: L- @) S
, z; Z  r3 w1 v# Gtypedef struct _SRB_IO_CONTROL
7 y2 d7 O, U" j8 Q{
: D' H5 y" u& Z1 `" M% @    ULONG HeaderLength;
' c% d! e/ ^8 f" V    UCHAR Signature[8];
2 U2 C: }5 p. J  X2 w    ULONG Timeout;
% Y5 U: W# N+ b( T    ULONG ControlCode;7 {0 r) w1 Z) }5 |
    ULONG ReturnCode;. ]- }; w" E2 V$ Y; M. {
    ULONG Length;
3 ~! n$ n! J2 T}SRB_IO_CONTROL, *PSRB_IO_CONTROL;7 I% ^; J1 Y! r" t3 R: I( ?

# t; [* \5 P! Y) i// 读取的主函数% E& ]+ W5 {9 @; h4 X& A. `
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
9 A" J4 f: }3 h, M) B2 ?' H2 Q% z. q
// 辅助函数  m3 f# a% V3 P; U1 s
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
" P5 H4 i. e5 T- \1 Q% i// NT/2000/XP函数; J7 P. r' ]4 |& J0 q8 |. ^
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);6 ?" v6 I1 t. y4 a$ _
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP," ~: [4 i, N4 X
        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,/ g7 Q4 {) x5 ]' W- V4 W
        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);2 r: F8 H& r+ }- k1 w
// Windows 9X函数/ c2 I* r+ g9 _) o. E' B
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);8 m9 s" q8 u, d1 G2 ?
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,% A+ D/ _3 U" L+ u2 u/ }' Q
        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);. L; N/ ^" \( k

2 J" C/ {6 U$ `+ R& X' C// SCSI读取函数(for NT/2000/XP)
5 E2 U' t( s- Y! {String __fastcall ReadIDEDriveAsScsiDriveOnNT();
1 g% f7 v& L$ D1 a2 j' p//---------------------------------------------------------------------------, z$ R& T4 O) X+ I
// ReadPhysicalDrive
, I- v; y7 W* hvoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)( V( z! v# F4 f; V  `, L
{
( L! [6 S# H- c& ^, Q. m0 ~( R    switch(Win32Platform)
' n& b9 C6 E7 M0 k( L2 s- u7 d$ \    {' a- l: O0 Y- N  F5 `* {
        case VER_PLATFORM_WIN32_WINDOWS:6 K7 t% a7 W5 H" P5 Z, F
            ReadPhysicalDriveOnW9X(pSerList, pModeList);
1 a" o; J& b: J/ s8 D5 O6 B- H: X            break;5 X9 _6 a2 d7 u7 |
        case VER_PLATFORM_WIN32_NT:( J: L0 a! i; Q- \) Y# u
            ReadPhysicalDriveOnNT(pSerList, pModeList);
  f! D9 z" ^1 |. d/ X  ^! O            break;
* |7 k5 P1 B3 x& F        default:' N1 v1 s4 G, [$ o. Z' Q
            break;0 y: D+ L4 O0 K9 S
    }" G- Z* [, p& Q/ _
}' P* n& f* d4 t& Z
//---------------------------------------------------------------------------
  E- g2 a2 j, }2 R4 u// ConvertToString
* C. X8 [- U$ P& k# l  {# _char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
) B! ?7 S5 N  ?9 C2 Q- Z& v{
; B6 ]3 a  h7 V    static char szResBuf[1024];
+ y, W, B' b7 |) \, s    int nIndex = 0;
/ \* `; u9 g! D2 L; A( u/ I    int nPosition = 0;  L9 m+ R0 l' Q, }* @( r
( {1 \8 N4 t; ?. d& o# r+ z  U
    // Each integer has two characters stored in it backwards- |# ?/ \; `  k! y7 |
    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
/ [2 X  R9 B+ \( Y' W    {+ E: w% N9 L0 z
        // Get high BYTE for 1st character
+ \7 s, b/ }" e; ]        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);# X8 V% g' X* h( H& ]) y
        nPosition++;
" u9 x  n: K; z+ m3 }3 J
8 \! f- X& B$ n        // Get low BYTE for 2nd character
& V7 L% M. z' P        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
4 d' Q0 V9 `+ z# @        nPosition++;
2 x- ~& Z2 x" t2 h4 D    }' h0 }0 A! ?' J$ Q5 j$ v$ Y; W
" R- ?% V/ |7 N8 \' g
    // End the string. f+ U: T3 S; @$ m5 u
    szResBuf[nPosition] = '\0';
: z9 C; u! j3 `0 g' t; \2 @( N! H# a
    // Cut off the trailing blanks
, L! A4 H& m9 k4 o' B    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
& R, F* W5 e1 g        szResBuf[nIndex] = '\0';
  U' U6 x& S7 x$ l9 g' d, d- w
& ~: l: s' [5 V, v6 Q* @. A  P    return szResBuf;
" c; D+ w8 _+ x' F/ _( W}' x) C+ [& m. |0 \) }
//---------------------------------------------------------------------------
( M! j9 S8 d- r  F// Winndows NT4/2000/XP 代码  M! `( }- p5 S
//---------------------------------------------------------------------------
# o  m4 _; c+ {$ {- T0 }// ReadPhysicalDriveOnNT' S6 c, Z. M6 ~4 O8 a
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
4 ~5 w( B9 J" g8 g( [& c{
) i1 S* @" b) B; e% n7 \    // 输出参数
* b( ?& K8 f; I* d/ p    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
% l1 I1 q& O2 b5 O8 s! m& P! o3 K( @
! Q5 i) v& e2 i4 v! H2 U    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
" k0 g$ X) R" l6 G* t( J: k6 x    {4 k* Z. Q, j" F( E
        HANDLE hPhysicalDriveIOCTL;
8 d4 o' [% ]6 D, y+ `$ ~        char szDriveName[32];
! s5 h5 T/ L2 W0 ]
- n4 N* M' C/ r8 O3 c        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
+ s; V+ B- Z  w; k* W, e5 d        hPhysicalDriveIOCTL = CreateFile(szDriveName,1 h. S8 \. R2 d8 C% q& E' Z
                        GENERIC_READ | GENERIC_WRITE,
# h3 j8 T) W7 u" B/ Q1 V6 f                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
. A+ P. I; P4 k8 y" {- Q, x* J                        OPEN_EXISTING, 0, NULL);
2 X# P: h  p" q2 q9 a+ ^$ j0 K1 c* P
        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
/ D& Q, r4 W* z# A) }  b! w        {! m4 |& \0 H: _) R2 F
            DWORD dwBytesReturned = 0;0 k- `/ K  s' G$ [9 T% o
            GETVERSIONOUTPARAMS gvopVersionParams;+ f  u1 ~3 a5 ^( n* d
4 }/ _% A7 T7 i. t$ k" M5 @
            // Get the version, etc of PhysicalDrive IOCTL' E1 D: X  }+ Q3 x2 B
            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
* K0 x' B5 t, C% U- e3 I/ \# X2 X
            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,2 Q. I9 @* n, {& h& [& s3 q
                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),+ Q: F" x* I/ [( l) E; |' O
                    &dwBytesReturned, NULL))
% Q) I- c" I6 b3 p; S' ?6 J            {
! c0 v; t" I! C2 d                continue;
2 O3 |  F$ Q- l  t; f            }0 Y  U1 v1 U' o8 F

) T, i5 F/ Y- a: h. y3 R            if(gvopVersionParams.bIDEDeviceMap > 0)( C. Q- P' y! D. {4 o* X7 J  U0 q6 Y( Y
            {# J/ z" @. _  n2 F/ d& j
                // IDE or ATAPI IDENTIFY cmd( O# i! B- A) D' n' U" M
                BYTE btIDCmd = 0;
. L- Z+ C. Y3 t# q! y2 B                SENDCMDINPARAMS InParams;
7 S. r& N" G3 }% [" m! b                // Now, get the ID sector for all IDE devices in the system.
; |4 j! E8 l& |                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,: w% @$ Q/ p0 `' x5 l
                // otherwise use the IDE_ATA_IDENTIFY command
8 d% X) }$ f1 m" |                // 具体所得结果请参考头文件中的说明: ]+ [: O7 \. i/ E( S) [7 y- N0 s
                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?9 s0 @4 R; o2 w, E; P- m
                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;1 `* y4 }4 E! b- S' F& K' P
                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));" r" _  Z6 y: ]6 K
                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
1 k6 X, d' q: W( X. J' s
( a( |% [# f+ Y* x) f( ?# H                if(DoIdentify(hPhysicalDriveIOCTL,9 [+ C) N4 ]% H" A0 a- W( W8 m
                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
& M1 t4 ]) M6 h( L                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
+ X% S) n# s. v5 l  x+ F                {' E8 _3 z2 k4 R4 A; J, W
                    DWORD dwDiskData[256];
+ p1 G% `0 W3 l& N( _# q                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
8 ?! n$ b) V  o, M/ M                    char szSerialNumber[21];* s6 n, f6 J2 @% l- a) z5 D6 Z
                    char szModelNumber[41];6 _7 s& _; ?1 H& R7 K6 U

) u$ H6 u. K+ |5 [7 m0 T% g3 o                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
+ ^( V7 h3 m- b: B4 c% i                    for(int i=0; i < 256; i++); S$ K1 B4 n7 c" w
                        dwDiskData[i] = pIDSector[i];
9 x; Y9 o9 m% h% I' L                    // 取系列号
" E; m7 R3 v$ O3 ]( o# z                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
, A7 b8 x6 \" l5 L  C                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
  Q1 t) r3 d5 S% C( t' B$ _/ M. v% o  }
                    // 取模型号, j8 p2 L" K  v# U
                    ZeroMemory(szModelNumber, sizeof(szModelNumber));
1 N8 \. I2 `7 q1 J" N/ U. f                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));4 y# c7 F$ Q( }6 x1 t6 x  _! q' k
( }0 G4 E0 B/ ]# q
                    pSerList->Add(szSerialNumber);, `* `/ y! L' D
                    pModeList->Add(szModelNumber);
) s/ p$ ^& h5 n" ]4 y# B$ y; t( _# N                }
2 w; t1 `$ `# U3 K. x+ Z  Z7 }            }6 u7 k; D. T8 |& U
            CloseHandle (hPhysicalDriveIOCTL);. e: x3 ]" ], v3 H0 b  F4 F
        }* T) M3 Y$ R, ~# P0 \5 X! c) f* P
    }
5 @9 S+ _! i. I3 p1 L! \/ g}, _. e1 X7 o0 x7 s* O) r
//---------------------------------------------------------------------------
. D8 h6 m( H  S6 u; p* W  E. r// DoIdentify
1 x8 C- {  m% L% \$ @4 }  t6 Y" gbool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,; {4 d/ K8 O! e* Q  T
              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
  X4 U1 g! _5 f0 N              PDWORD pdwBytesReturned)/ G2 ]3 C/ p. c. j% X$ T* r) H8 X
{
/ N7 @0 b. s% x" o$ w2 g8 \    // Set up data structures for IDENTIFY command.* O% [- ]* B( f# _# b) i
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;1 \6 F7 Z/ ~: H
    pSCIP->irDriveRegs.bFeaturesReg = 0;: c0 z. ], Z, Y$ Y
    pSCIP->irDriveRegs.bSectorCountReg  = 1;# k, N! Q0 w2 W! Y8 D( I: F
    pSCIP->irDriveRegs.bSectorNumberReg = 1;
3 D9 n7 E+ X: m4 V  L+ D( ^8 l8 }    pSCIP->irDriveRegs.bCylLowReg  = 0;
. M' L9 |& c8 g7 l) R3 o, }    pSCIP->irDriveRegs.bCylHighReg = 0;2 g$ c; o1 S3 G* q  E
0 |* G. J9 I# }+ a, u: `) L. X
    // Compute the drive number.(主盘和从盘所对应的值是不一样的)( ?( q8 Z3 K+ o7 b! P
    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;( l: e" x1 Q9 u& K! N) t3 O: w
8 }9 T" S6 E: c) C
    // The command can either be IDE identify or ATAPI identify.
/ @6 h, k) x/ w1 e' B! m$ O+ \5 x    pSCIP->irDriveRegs.bCommandReg = btIDCmd;6 ~; ]. S8 [3 o, u+ l# |
    pSCIP->bDriveNumber = btDriveNum;
( t# x- t  `, x/ f    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
  z  y& W8 @6 P  M8 [! ~. a! X4 t, h8 o
    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
! D( K+ ]/ {& d: [, v# V           (LPVOID)pSCIP,7 Z! @$ n+ W, w" P$ I) K$ m
           sizeof(SENDCMDINPARAMS) - 1,
2 f3 A$ l+ D+ I. {7 R           (LPVOID)pSCOP,2 h# ~; U- x0 _3 h6 t) D
           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,: A, t2 ]5 W2 f; e8 K; q
           pdwBytesReturned, NULL);
6 C0 Y. T7 j+ ^1 T4 z2 A7 G0 }}
" _; \5 C/ T( n2 h//---------------------------------------------------------------------------6 s! S6 _! m" H/ ?2 [
// Windows 95/98/ME 代码6 f1 @3 s' {) V5 h
//---------------------------------------------------------------------------
8 h$ k. V( b% Q0 [- d1 d// ReadPhysicalDriveOnW9X
* P& n  x' ?( @9 S4 f4 ^" \, Xvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)) w) C8 t% a5 Q" ?# B. f6 k
{
% V1 h% G  b: u" G5 Z5 h    WORD wOutData[256];
  \/ k! G3 m/ {0 {4 E% c( h$ O    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
7 V" a& c5 V* r. d! A' h+ O& c* W: ?8 W# y5 j$ t% c3 g
    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。. F) {" }" E4 {' `& Z
    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
5 f  S5 u) H' {0 u! R    // 避免蓝屏的出现。(期待高人能指出原因)9 Z' _( i) t3 `" O: F% s, b- h
    for(int nDrive = 0; nDrive < 8; nDrive++)
, _* E2 ~4 }0 P' P% Q    {
; l3 u$ B/ i% c+ W$ c% s        WORD dwBaseAddress;
  E3 V+ S0 W+ |/ j        BYTE btMasterSlave;         // Master Or Slave
# _8 S% e3 b' Z9 v# {        bool bIsIDEExist;5 [' |& a7 z& E9 n! e( a# S/ ]
        bool IsDiskExist;) m* _2 y1 `* q0 }. b% ], d# N  g$ x

1 ?% [8 d; J. n$ t' _        switch(nDrive / 2)
  w# D. W+ e: u$ h: u: f        {
! F+ H0 B! ~6 f, r) ]            case 0: dwBaseAddress = 0x01F0; break;# f* ]+ I) C& v, V' K; |# a- }
            case 1: dwBaseAddress = 0x0170; break;2 Y3 J4 n* K- ^% x
            case 2: dwBaseAddress = 0x01E8; break;( ^& C+ v+ j: n
            case 3: dwBaseAddress = 0x0168; break;
$ P1 Y2 s3 F# P3 h4 v6 G+ N9 R        }
+ N$ _( f) c/ d8 \5 S
" q6 ]7 Y( y9 |1 B" E        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);7 B8 m0 [) u# K' F: w8 D
7 o+ Z2 g: y+ S5 @3 G6 c0 a: b
        // 进入Ring0* x7 P3 R7 \( K3 _% [+ R
        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,1 ~" w1 U3 f7 ^: `7 U3 n
                bIsIDEExist, IsDiskExist, wOutData);
) B; Y& I5 i6 m, t    }% w: b. _  a+ V+ Y

) y  P! u: }/ m% }* ~    // 开始读取
9 X7 O# d: l1 w9 f. `    for(int nDrive = 0; nDrive < 8; nDrive++)8 ~" X% |7 E& V2 C; J& U# f$ i
    {; q& V9 l3 e4 Z
        WORD dwBaseAddress;
7 D( p1 ]) e: n+ D, T        BYTE btMasterSlave;         // Master Or Slave
0 k4 d) L5 X/ |: O! F; u        bool bIsIDEExist;9 W% I( P4 b( y3 C3 _7 O! y
        bool bIsDiskExist;4 m# G, o6 A$ A- W5 }
        switch(nDrive / 2)
8 g7 h/ i) i+ M3 R& U+ _) e7 |( q        {4 r9 w5 p' v/ {( D2 N. \: _! \* y9 s' K
            case 0: dwBaseAddress = 0x01F0; break;' L# o5 b9 Z: e! V# T" W+ ~' x
            case 1: dwBaseAddress = 0x0170; break;4 t5 a! `9 J8 w' i+ {  k
            case 2: dwBaseAddress = 0x01E8; break;3 ^( z7 I- g+ m% n1 X, K% o6 B" R
            case 3: dwBaseAddress = 0x0168; break;
( Y$ }& D& v7 u: {) {, B9 a        }
; p/ V: S$ w- g, S, f& J4 L0 U, t; t7 c" l- d' b
        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
$ j" h' t3 z* u" N$ f( D/ N
4 X" V! j8 p3 i& Y        // 进入Ring0
2 M4 ?  B; W; Y6 ?# z1 L  g        bIsIDEExist  = false;- r8 y5 j* F1 p# `  x
        bIsDiskExist = false;7 e+ R5 f! L  r) ~/ {6 {
        ZeroMemory(wOutData, sizeof(wOutData));
; K/ }! E9 H' s+ R( c, F" A) B
2 p& f+ D9 g5 F7 c        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
6 n) |! f# H2 @! N5 B. _                bIsIDEExist, bIsDiskExist, wOutData);+ u+ X& r2 H- u: r3 s
6 s) n# V' u- a$ |
        if(bIsIDEExist && bIsDiskExist)+ g% K% h  }" X
        {
, z* y0 S6 O( d! K) U) D8 s7 ?, v# D4 @            DWORD dwDiskData[256];: z$ k4 S$ m  w! M7 N/ k
            char  szSerialNumber[21];
$ ~$ q& c! w: W+ h, `$ Q! q            char  szModelNumber[41];: T. n6 I  X. }* W- h

$ p0 R( ^# Y3 U; m  Z7 F  w            for(int k=0; k < 256; k++)
+ T' P% [/ t) m( z2 R3 X" H                dwDiskData[k] = wOutData[k];% T  P! \/ F8 n; f  V$ Y( k* B- L2 w
5 X. g0 D1 g7 a+ R+ ]. b1 V
            // 取系列号
2 w2 P- x  o- S' K            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));: ^, h4 X* M* X. i  [  Z
            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
. U  j! a" u1 m' g- c
7 d  U) u0 J& R' B            // 取模型号& L: ~1 c0 a3 e4 S6 J
            ZeroMemory(szModelNumber, sizeof(szModelNumber));% m  \* K% `; f! U- y2 s) _
            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));0 Z5 ]" f1 Z5 H2 @
3 v2 C6 u3 ?& I% k* j' Q' N
            pSerList->Add(szSerialNumber);9 k+ @# i4 d4 l# d0 n9 ?1 s
            pModeList->Add(szModelNumber);
+ y7 q9 Z& T2 Y& e5 S2 v  ?( \% Z; l  J        }
" G9 b, i9 Y  h    }
9 W# u6 D! M' }# V( Z* A    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
4 _  j% q' j  x6 @9 ]}8 o! x' Z3 L' O, f1 t2 o
//---------------------------------------------------------------------------
& W& Y' {4 A: f7 Y0 q! e// 为防止不负责任的转载者,在此注明原出处信息,请见谅。
1 `7 k+ A+ g1 t/ a: I7 p// 资料收集整理:ccrun(老妖),欢迎光临C++Builder研究: http://www.ccrun.com
) D: z3 e3 o- q: `* R% D//---------------------------------------------------------------------------  ]0 O3 ]: `7 ^' K
// ReadPhysicalDriveOnW9X_Ring0()
, a1 C% y$ ^/ [/ _, G$ s! [& D//9 b, I+ |9 S( b0 m! V2 {+ m
// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h! p" t, D, D5 v0 k
// btMasterSlave = Master(0xA0) Or Slave(0xB0)
# C6 _# m. P. N) ^& A1 n, J6 N% v//---------------------------------------------------------------------------
( O, w. Y8 k& E" Z# k# rvoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
( O0 z2 W1 I% U& Y6 S$ P        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)" ~3 M* g1 ~* J
{
# T5 Y8 f5 \8 o    BYTE  btIDTR1[6];
9 W0 p3 a8 ]/ x" h1 i    DWORD dwOldExceptionHook;
( I/ Y4 Q0 ~6 l" h) R9 E* i2 u    const int nHookExceptionNo = 5;
) ^4 m# k4 \) }- l! I7 R8 _! B
9 S1 g4 O  d1 [* m: W8 A8 n    BYTE  btIsIDEExist = 0;
6 W$ O1 ?# R: n8 l8 M8 V- {8 |    BYTE  btIsDiskExist = 0;# F  N* U% G) V8 d# R+ c; R( U0 ^4 I
    WORD  wOutDataBuf[256];
. Z$ }- P, `7 U: T( h! ~7 W, s5 M$ w, t' O5 b7 w: D
    BYTE  btIsFirst = (BYTE)bIsFirst;+ L; j5 F7 V6 V7 K+ w6 k7 m

1 Y$ f  P' Y( R( ^* j    const BYTE btBit00 = 0x01;
! O, L4 w6 C: f/ a2 p9 m* k    // const BYTE btBit02 = 0x04;* n8 L+ V* p, q3 J) j* H
    const BYTE btBit06 = 0x40;5 M2 E: B; f9 Q& A( D) T( O9 C
    const BYTE btBit07 = 0x80;
: h7 a3 r, ]6 _" l    // const BYTE btERR  = btBit00;
3 i& N$ f2 j; O6 P; r, X, J    const BYTE btBusy = btBit07;
/ }* Q) _3 L! w. x5 n: A, Q3 |    const BYTE btAtaCmd   = 0xEC;
! e6 L" H" p3 A. ?4 ~    const BYTE btAtapiCmd = 0xA1;
6 R: Z, R$ u4 \; Q. t' ~+ j
5 C  ]: p0 D  X( Y  q    __asm+ I% A) M" f6 C4 M$ I( [- U
    {
& Z( S8 ]! S2 D8 K0 v        // 必须先执行这条语句3 `  B5 Q2 A" f6 y
        JMP EnterRing0
( H; D. C/ ~+ k" {  J
( S3 G# i) Y8 s+ K1 A# C: [6 r        // 定义过程6 [; j( b% B/ |8 p
        // 等待IDE设备直到其不为忙为止
4 W+ E0 J$ \/ ?# s1 ^$ p: B( I        WaitWhileBusy proc8 X# V" I0 R2 y- ]- [( g9 x

2 `% d9 q! O6 h        MOV  EBX, 1000000 p7 E' a# r5 l' ~% a
        MOV  DX, dwBaseAddress
' O% H4 N) q9 y/ R$ Z6 Z        ADD  DX, 7
2 Y  z  D( U. G6 _0 C( V
' i: I; h" B! E1 Y7 J4 B$ Y9 G        LoopWhileBusy:
% Z4 z& a% [, G, h2 E% N) w0 w. O. ~( f8 M
        DEC  EBX
- }+ M  W& x7 Q+ r        CMP  EBX, 03 V8 H: w9 J6 {' `+ ?# `$ t( E
        JZ   Timeout3 T  T( D3 z# A
        in   AL, DX
1 s" B. {7 \" g, `) U5 T        TEST AL, btBusy
% |. S) Z& m: m  ^4 t) C8 G$ V. x        JNZ  LoopWhileBusy
: G5 f7 J' m& E1 S0 Y1 g        JMP  DriveReady+ `$ k! L1 K, I7 Z6 g. T- y

  z1 d$ ]. ?( @0 \( T        // 超时,直接退出! L+ @7 Z; I2 f% _0 e$ t8 t
        Timeout:3 W( q/ m; T( c0 d
        JMP  LeaveRing0
1 K5 i0 u- b8 h  f. f- N        DriveReady:2 {: U' b0 q4 ?/ L& W# v
        RET
* B# v4 x4 \0 q  Y* U        ENDP   // End of WaitWhileBusy Procedure
5 z" a: S$ o: b  K. F  v: ], t% h2 _
        // 设置主盘和从盘标志5 i0 z/ \5 s+ k$ x' `+ N
        SelectDevice proc
; l/ l/ [5 H- f$ v# ~& j$ i+ X
        MOV  DX, dwBaseAddress) B$ `% `$ Y0 a; I! _, Q7 v# ^0 Y' D
        ADD  DX, 6; C- L/ Q5 A# g, W5 p; Y- k
        MOV  AL, btMasterSlave
+ s+ n- N9 ^: V3 ?8 L( d$ G; X
0 @: y  z* n# O: x* Z" t" d2 q8 z7 y0 H        out  DX, AL
1 M% T1 b1 E1 J( k0 |# W5 o        RET7 R# I5 [$ l0 b. X  p! {

. m; Z3 A! y5 V. J& B2 w' v. l        ENDP  // End of SelectDevice Procedure
# J& V& L" O7 ]. ^( d  O9 x8 G* U$ V( E1 {' W" C( O9 X
        // 向IDE设备发送存取指令) |; Z! f6 u' r2 U
        SendCmd proc
( x! Z; l' x6 Q1 v" c3 {
& R  t4 V5 y  w/ v4 y        MOV DX, dwBaseAddress
/ A; X% g. x9 D3 x( Q+ W        ADD DX, 7+ G" K- r  j; F3 V
        MOV AL, BL // BL是主从盘标识,在过程外设置
: e6 x9 o* k$ Q) v. H& R        out DX, AL
) q1 o( ~! V* y  \+ F, x$ D0 U1 d        RET/ B8 n7 }1 Q% ^/ R! ?. _2 i2 |* N
        ENDP  // End of SendCmd Procedure
# S4 T9 q8 N" K1 x$ Q, ~& J" ^, g" A5 ^+ b1 X0 y
        // Ring0代码
" t5 c: \2 A7 b& {% N/ u$ i; R        Ring0Proc:
, s( S6 {, C, A# {! y6 c        PUSHAD
2 e& l; U& l' l5 Z, S, ]7 S  ~! h        // 查询IDE设备是否存在
3 [2 z9 ]! W9 O  S        MOV DX, dwBaseAddress& q, \9 U! B- v# `/ [; E0 D) N
        ADD DX, 7
# |* E/ a# n6 A2 y( P9 d( _0 z        in  AL,DX
9 E8 [! P" n" d. R5 a0 ~
" P5 L9 @' u/ H; N" F$ u& z5 V        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回5 d% z3 Q$ h. F5 i& M, p! o
        CMP AL,0xFF
1 c: T; D# z2 s4 h        JZ  LeaveRing0$ r% c& a8 d5 X$ X
        CMP AL, 0x7F
$ K( s) L1 I: t. E! S, L- C6 O        JZ  LeaveRing0  Y( Q; R  u; V; f3 j# l

0 g6 H# d/ y( H# n        // 设置IDE设备存在标志: l# I& K2 y# I- S% f$ ]8 ?: G! M
        MOV btIsIDEExist, 1
. [4 r# q; R: q1 T7 H2 Q
* O1 I! n5 j8 d/ E# D% N8 i! |        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
/ a; L% o( h) o4 o# P1 N        CALL WaitWhileBusy
- k* A* y1 F: o4 `. A1 L3 F: u6 x& U- L        CALL SelectDevice
( S5 a3 i/ ?% b3 G. k* \* f$ D8 D1 D
        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏# e) w( U6 S" @- ]1 _  I
        CMP  btIsFirst, 1( z$ _8 l- M3 s2 d$ Q# c
        JZ   LeaveRing0' k3 M8 t3 C; R4 k& }

4 T( b$ a$ L8 P( k        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
7 I" M1 Y- V1 \5 ^        CALL WaitWhileBusy
8 f4 u! X0 F% z5 R# ^; _& N2 K" n$ A5 M- S) g9 D/ A; {% X
        // AL的值等于cBit06时,不存在驱动器,直接返回
) @" L9 n6 c: m# p5 X: z4 c0 i        TEST AL, btBit06$ ?3 v5 C6 `2 Y" a0 U4 {1 |1 r
        JZ   LeaveRing0- B7 p; o# s  I

# i5 \2 \2 `: {7 \$ B! c3 D; [; F        // 设置驱动器存在标志+ O0 }" Q% l* A0 F
        MOV  btIsDiskExist, 1  C  h) t7 M/ O1 S# J% M
& _' N/ d+ a2 W. j& ?# w. O6 f( [
        // 发送存取端口命令
( Q3 h3 d% n+ h9 R4 H        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,. U, t1 @8 S6 b) V  ]" x0 L/ m% o( e
        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令/ G7 k5 K4 S3 |4 h, c7 L, `# A
        CALL WaitWhileBusy
- Z/ S0 w% V% ?! L1 H        CALL SelectDevice    // 设置主从盘标识. V  `( S$ t% U
        MOV  BL, btAtaCmd      // 发送读取命令
6 R& `7 r- H/ p/ B8 p# p# ^        CALL SendCmd
  ?9 A8 S& Q; t# |6 `# I        CALL WaitWhileBusy
& b) J' a6 B  ?7 @' ?8 _7 q6 _' M6 X% m! U- l2 d8 z
        // 检查是否出错
. t! X( w+ O6 s/ Y        MOV  DX, dwBaseAddress% x- b! _5 o0 V7 w
        ADD  DX, 7, d! O- R' H  }- O7 `- J8 v8 Y

5 A( p$ K; U2 u; c3 l+ z        in   AL, DX/ Y* \6 _+ w; r; n$ k

- l+ m* ?  ]$ O. q( S' M        TEST AL, btBit00! D& `  Z; N, Z: s5 F6 T6 J% g
        JZ   RetrieveInfo   // 没有错误时则读数据
' W1 M7 r( ^& B
7 g$ B! W4 R' t7 z& K        // 如果出错,则进一步尝试使用ATAPI设备命令8 Y5 Q6 R& r( x3 E( O3 E
        CALL WaitWhileBusy( T0 X4 b, N' P8 P% B# B; @( a
        CALL SelectDevice, o2 S! E& q! w" h
        MOV  BL, btAtapiCmd
7 {, U) y$ d' L7 I        CALL SendCmd% Z% m9 C  o+ S! ?, _9 J
        CALL WaitWhileBusy# \% Y2 p2 A: A# h; h# y2 J

1 J9 i1 Q: i% b* E        // 检查是否还出错0 z4 \: u% B( V5 N: s9 |; Y/ I/ d
        MOV  DX, dwBaseAddress
3 |! |- p, t. ~: M4 \) u- m+ P( Y        ADD  DX, 7
) C7 A. d# A2 k) Y! t        in   AL, DX
9 c6 K7 o; Y. [9 S        TEST AL, btBit001 t5 u! l1 M! O# T6 `, k8 u6 ?
        JZ   RetrieveInfo   // 没有错误时则读数据% J" t$ e- @5 r1 E0 s9 ?6 j) b
        JMP  LeaveRing0     // 如果还是出错,直接返回
* \. \% W3 e7 a
3 n# }$ s1 j/ g, a. C        // 读取数据
$ Z. N. d- m9 l( i2 C" w        RetrieveInfo:7 b6 G% c" y3 ~6 Z' Z1 t# a
& `9 _. T2 i/ A3 U4 c2 c4 X
        LEA  EDI, wOutDataBuf2 M$ a+ k$ ?- j: d4 @8 Z  c! J9 D
        MOV  ECX, 2569 Y" E5 \% ]! [, A
        MOV  DX, dwBaseAddress
+ R  o* R( H/ B$ `; P        CLD% E% L6 C) }- a$ C% Z
5 x7 t7 B' U, `
        REP  INSW0 [" d# V$ T9 Z! b, x

, h/ U$ O8 A1 f  y0 T# a( H        // 退出Ring0代码2 w; S' ~& `8 n9 w
        LeaveRing0:# a. }% o" T0 }0 L7 \+ [/ Z

0 B( E2 i' Q* r0 c5 h5 F        POPAD
" ~& d; ]) v1 g  V# y        IRETD+ M9 Q( r: E8 u' n  p
& Q2 x- \  a) T- J5 H
        // 激活Ring0代码
3 D# e" E3 H8 n* f" s- t9 q        EnterRing0:
/ g& H/ d/ @( Z9 D( U
& u% ~5 Q, Z2 D        // 修改中断门
- r. o3 e. {3 h* N        SIDT FWORD PTR btIDTR1/ {9 m, R- k& X8 P# P. a
        MOV EAX, DWORD PTR btIDTR1 + 02h5 a2 ^7 H! ]0 K: ^  n/ ~& M8 [
        ADD EAX, nHookExceptionNo * 08h + 04h
0 x5 K; a3 k3 ?+ @3 P& B# K9 Y        CLI6 T* R2 h! U8 d5 v" K" s: m
  u  v0 j" w: {. a
        // 保存原异常处理例程入口# _& p8 c0 }7 \- H; s% o
        MOV ECX, DWORD PTR [EAX]1 R* C3 z2 d: \( l; ]) f/ l: N) s
        MOV CX, WORD PTR [EAX-04h]* Q0 U3 R' |$ S+ \: l
        MOV dwOldExceptionHook, ECX% O9 ?% u, I2 E$ u* ^& W1 ]
+ h4 m# F, ^4 q! F
        // 指定新入口$ O& G4 o4 A% p$ O  m
        LEA EBX, Ring0Proc
  V. h8 ~3 P$ O; p  L0 F5 r        MOV WORD PTR [EAX-04h],BX* ]' h! D1 f- `7 K" L, d
        SHR EBX, 10h. N" o1 K& U6 z4 h/ g/ B! G) P
        MOV WORD PTR[EAX+02h], BX
: F3 `3 f2 j1 k$ k, M* v& K$ C; T& o! |1 R
        // 激活Ring0代码9 t, S1 g, |* O$ v2 L- S
        INT nHookExceptionNo2 [9 i. e- `% k# s

& C3 N9 O9 J7 N" y/ h        // 复原入口- E- t3 Y% K. V, J: e
        MOV ECX,dwOldExceptionHook* K% K4 h' C/ h" f4 S( b' a9 _+ W
        MOV WORD PTR[EAX-04h], CX1 f$ a* G0 R, u; H1 l0 ]
        SHR ECX,10h/ P' a: q6 O+ p; i0 y- j2 }2 ^
        MOV WORD PTR[EAX+02h], CX
- s4 \$ h) I" [2 \6 m" C; t) a* p9 \        STI  l% q4 p% w1 u; \0 o
    }
/ U0 i6 H! n8 t) H% o$ }    if(!bIsFirst)
5 i: X+ a( }9 k3 g( V5 M    {# V0 s" x  M% L7 D* k1 u. O1 p
        bIsIDEExist  = (bool)btIsIDEExist;' O- T8 C( r$ K8 l. W$ }
        bIsDiskExist = (bool)btIsDiskExist;
7 @9 g5 J9 F7 a6 D$ e4 G        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));# D$ Q  I1 C; O6 ?
    }- t6 O8 ~5 M4 l  Q& X8 h4 f% M+ E" y
}
8 z: B! F! v" v, x% N3 k  H2 @//---------------------------------------------------------------------------* m8 t- M# a. L6 [0 _
// 调用方法:. M4 Z9 @$ Z; f9 W/ [
void __fastcall TForm1::Button1Click(TObject *Sender)2 H" K2 C" P4 ]7 m. E/ j, |7 |
{
7 s# _7 @  X6 j; ~1 U    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);$ w# ]  J, [! X* Q' a: V
}" \$ j4 N; g- f' g0 Z# @
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-9-30 08:51 , Processed in 0.040052 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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