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

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

[复制链接]
发表于 2008-1-6 19:59:06 | 显示全部楼层 |阅读模式
代码框架,你所要做的仅是修改WQL语句,具体可看MSDN。以下代码为简介起见,一次返回所有的CPUID或硬盘厂商系列号$ L3 o+ }9 _3 a8 y' S2 @8 g5 f
  1. 8 h1 B  _5 Q( {) @, {' z8 g0 z& H
  2. #include "StdAfx.h"
    ( k+ \' e5 R$ l9 I9 O! j5 l& w
  3. #include ".\puiddisk.h"
    6 M+ I) }3 J$ z
  4. #define _WIN32_DCOM* O2 g- C7 f* A9 U- g3 }
  5. #include <iostream>
    7 x$ G, P3 i$ n! r3 U. P# W
  6. using namespace std;' c- M" N* ]9 D. G- T, }3 L! ^
  7. #include <comdef.h>, T# {3 g9 O1 F. v' f# @
  8. #include <Wbemidl.h>
    6 x9 N0 H7 J9 `7 C% A
  9.   U; f( \2 R' M( }8 n- U
  10. # pragma comment(lib, "wbemuuid.lib")
    1 C$ E$ ]) v9 v; k
  11. CpuIDDisk::CpuIDDisk(void)
    ! w; l; O- m9 Z: P
  12. {- M: g* q2 U  o
  13.     GetInfomation();
    ; P  ~9 M0 e& [- Y" b* f5 Q7 T
  14. }5 T* I* z9 l' K
  15. 0 t' X" G. ?3 V
  16. CpuIDDisk::~CpuIDDisk(void)
    . `2 ]+ z1 w1 f% U4 M6 R
  17. {
    # ]# t$ {0 e# V
  18. }, [3 I1 O/ V* u( Z8 S, a" @
  19. int CpuIDDisk::GetInfomation(void)% _( b5 Z6 h/ P# I
  20. {
    9 @) A1 [1 ?- X
  21.     HRESULT hres;) s* W2 \. }$ E5 E3 h
  22.     //步骤1:不是必须的,COM只须也只能初始化一次
    ' _: D! v, X# r  L
  23.      hres =  CoInitializeEx(0, COINIT_MULTITHREADED );6 t& F3 ]1 i. ~6 j# U
  24.     if (FAILED(hres))# M' _3 k$ k2 Y- t; e. H9 j9 U( }: Q
  25.     {
    ) p" O7 {# l$ G# A1 |, `' _0 L1 f
  26.         return 1; //初始化COM异常:注意,COM只须也只能初始化一次
    - G, L. x1 d: V7 t: B2 m
  27.     }
    ' J* G/ d0 o; j! B4 a( k3 a4 ]
  28.     //步骤2:不是必须的,COM只须也只能设置一次) m; I  m( E, |' T& ?
  29.     //Set general COM security levels
    6 G. `; c! M) u1 o" D0 S
  30.     hres =  CoInitializeSecurity(7 R7 S0 g5 W+ z- i1 i! {9 |
  31.         NULL,
    + U  M# X! D6 G5 F; v& `: k
  32.         -1,                          // COM authentication
    0 o% {- C4 V4 U6 T0 @$ {
  33.         NULL,                        // Authentication services5 E! ]8 M0 f% g
  34.         NULL,                        // Reserved( ?: P4 s9 ^9 K/ r$ o# {2 X: ^
  35.         RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication
    8 a$ J- `: U2 y: U
  36.         RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  9 l6 X* t* ^) Z0 s$ h
  37.         NULL,                        // Authentication info4 Z1 L0 c( P. T5 b
  38.         EOAC_NONE,                   // Additional capabilities / [$ v; T- s0 R  u; b/ C  M
  39.         NULL                         // Reserved
    6 @4 [+ D! \2 E
  40.         );; L8 x; `1 ^- P) T
  41.                      
    6 l/ F* z, H; |( e+ g; E! o
  42.     if (FAILED(hres))* Z* O* ?5 B% A1 w9 s6 b- m" C
  43.     {. X0 r) t" H+ K
  44.         CoUninitialize();
    , x# ?* F% F7 \' X
  45.         return 1;                    // Program has failed.
      h" _5 l6 I5 `3 B+ l/ T  {4 N
  46.     }; m# k! m) ]& \, [. x0 {, H
  47.     2 u: d4 R+ C# I6 m' \1 ?: X
  48.     //以上不是必须的,若已有“::COMInit();”,则要跳过
    2 ~5 G( o$ }6 k) U5 R
  49.     //步骤3: Obtain the initial locator to WMI
      B% z  D) o3 G; l6 ^
  50.     IWbemLocator *pLoc = NULL;
    8 y! D- D- i5 k4 _" @# P
  51.     hres = CoCreateInstance(
    ! \1 J; i) i$ x, F
  52.         CLSID_WbemLocator,            
    ) b2 z5 f( L9 j' X; o7 {0 g
  53.         0, * n, Q, b6 H& ~8 A( L. M
  54.         CLSCTX_INPROC_SERVER,
    % F: S  z1 V; l. M% Q0 b
  55.         IID_IWbemLocator, (LPVOID *) &pLoc);
    : @) N- s4 _0 ]+ A6 u( j, q

  56. $ U* o) }: G6 ~! A3 N
  57.     if (FAILED(hres))7 \9 g) b4 Y7 u
  58.     {1 r$ `: {2 j) N3 k( I) R; F7 `
  59.         CoUninitialize();- b9 M0 z+ T+ e4 v+ F+ C
  60.         return 1;//Failed to create IWbemLocator object3 J) x- L4 ~9 P  G5 H: U
  61.     }7 s( ]( G6 i0 V0 {2 J/ r, K# N

  62. & s4 B+ o. S4 v6 o
  63.     //步骤4:Connect to WMI through the IWbemLocator::ConnectServer method
    , o% L; p  [: B# f6 Y+ `
  64.     IWbemServices *pSvc = NULL;& G9 P) ]& s1 ~  n& \2 T
  65.     hres = pLoc->ConnectServer(2 ~  E# \2 A2 S" l% x! \* v& R
  66.          _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace" i1 m4 Y! a8 r/ ~
  67.          NULL,                    // User name. NULL = current user0 [! Y1 E1 S5 V7 ^. X
  68.          NULL,                    // User password. NULL = current  t& F6 L7 {3 S; c4 X' O
  69.          0,                       // Locale. NULL indicates current
    7 l. z( [+ L2 p
  70.          NULL,                    // Security flags.1 }: ~; M+ U" d  K7 m3 L0 r/ n
  71.          0,                       // Authority (e.g. Kerberos)
    ! Y% Z; J. D7 e1 c0 i6 h4 y
  72.          0,                       // Context object
    $ E/ w+ G% V3 A6 o/ N0 ^  _
  73.          &pSvc                    // pointer to IWbemServices proxy# I: ]( D+ n8 u' v* F
  74.          );
    % P$ `' q- H& ]& E; `/ D: [
  75.     ! {1 ~* O6 v) e. x
  76.     if (FAILED(hres))" X" O9 A; f7 C* g! g9 m
  77.     {$ n0 ~, T3 \  I
  78.         pLoc->Release();     , |& A; K* G+ K& j* R! T4 a3 a* K2 ^
  79.         CoUninitialize();* t8 E) d9 V$ j7 [2 j' B' }
  80.         return 1;                // Program has failed.
    ' H& x2 ]# M' Z$ e
  81.     }# ?* h- x% X! W5 U3 |8 q- Z
  82.     // 步骤5: Set security levels on the proxy
    ! `' H3 W6 G0 A. b% k% l' G
  83.     hres = CoSetProxyBlanket(
    2 ]% c; m) @7 i9 P2 p
  84.        pSvc,                        // Indicates the proxy to set
    6 E. O! O2 w; _% n3 w( K( |( U9 u
  85.        RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx
    5 @0 }7 K0 X3 ]& Z3 d6 b
  86.        RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx
    : c1 Z1 ?# M# E# n" k
  87.        NULL,                        // Server principal name
    1 h  h2 t5 p! V& G) l& I/ F0 |) F) J
  88.        RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx ( {2 V, ~- f2 j- l: f8 `
  89.        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx& |. \1 [- t" K: L4 l$ o' X
  90.        NULL,                        // client identity
    4 |/ A  M& c8 u& M6 n
  91.        EOAC_NONE                    // proxy capabilities
    % P4 f: o: n3 G. }. M, Y
  92.     );5 }* G' `6 e' Z) ]+ ~3 L# P9 ]
  93. 8 `, F, \2 w+ M% B9 x( F* F
  94.     if (FAILED(hres)). W8 i& F1 U2 Q; i( I# i: O# b3 n  }# P! g% Q
  95.     {8 A; K- o! g; \, E8 R* M+ u
  96.         pSvc->Release();0 L" P; @- Q" p& _8 j
  97.         pLoc->Release();     ' O: c" {% Q; I
  98.         CoUninitialize();2 F; \( Z8 U1 V, `4 d6 B
  99.         return 1;
    ' u# s* v2 D  J: @$ @
  100.     }
    / B7 c! x& y3 p) d1 k
  101. # \) ]1 M5 N7 S
  102.     // 步骤6:Use the IWbemServices pointer to make requests of WMI ----
    4 h4 w1 a% L5 I" c% Q. {" |* U
  103.     IEnumWbemClassObject* pEnumerator = NULL;
    * t$ _( t$ W5 l% b3 T
  104.     //计算CPUID* y4 G7 v0 W8 x  ^6 n( ~7 |
  105.     hres = pSvc->ExecQuery(
    $ ]' n3 y/ `  z6 _3 E9 c' C7 V9 Y
  106.         bstr_t("WQL"),
    ; Q; ?- _! Z/ h& `
  107.         bstr_t("SELECT * FROM Win32_Processor"),//Win32_OperatingSystem
    - l; ]- C$ {; q4 ^( h
  108.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
    4 \9 B5 e6 i( ~
  109.         NULL,
    ! Q* @; G( _9 Y+ z$ F- a8 v0 D
  110.         &pEnumerator);
    1 G, R2 Q* O+ E) p( X8 n
  111.    
    . L3 d6 H- M4 J/ ?
  112.     if (FAILED(hres))4 B- j5 y% F2 I2 v. x! ~
  113.     {9 ]9 V' g, }$ i! }8 Z, G, Y0 Q* B
  114.         pSvc->Release();
    + q5 |/ e& n) u: Z! ^: ~
  115.         pLoc->Release();* Z8 i! X. u6 v4 K. T# f
  116.         CoUninitialize();9 J6 K5 l# Z( n, m6 ~5 W: ]
  117.         return 1;, U6 O5 x/ T, c3 J
  118.     }2 q! ]3 [! n3 `, v
  119.     // 步骤7:Get the data from the query
    9 ?- I$ J3 t$ M3 w( [  c* o8 P; j
  120.     IWbemClassObject *pclsObj;  Y# E: Q9 p+ s! g' S
  121.     ULONG uReturn = 0;' e/ U2 U# y" d  m- d6 T, q/ }) t
  122.     while (pEnumerator)
    % D4 p8 u3 R* R6 y% V6 }
  123.     {
    + B* }' |2 R- |0 r+ i# F9 v* P
  124.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
    " e' x" r: u) q: C3 R
  125.             &pclsObj, &uReturn);. g4 X" u: e! w9 I% X; q' Y

  126. , O6 U2 A. _# ^' E7 Y* ?
  127.         if(0 == uReturn)
    % H" W; C" _0 R" I
  128.         {: m* _$ t" A' j3 d% @3 a, [7 {
  129.             break;
    $ n7 Y6 w5 z6 @/ f5 [
  130.         }- g4 c2 g% \2 |. |
  131.         VARIANT vtProp;
    ! Q  m7 y% a* F4 m/ y, |
  132.         VariantInit(&vtProp);. C3 v+ l; U+ m8 ^% \& U
  133.         hr = pclsObj->Get(L"ProcessorId", 0, &vtProp, 0, 0);  Z( W. x) Z( j. p/ v
  134.         strProcessID=_com_util::ConvertBSTRToString(vtProp.bstrVal);//strProcessID:类级变量
    + q+ l: [1 Y- q& V! _! d$ c$ P2 j
  135.     }
    0 Y# a) o0 i- e8 N
  136. * N: g$ |$ J3 v4 v
  137.     //计算硬盘系列号
    $ j! C' p$ E* \& c- G6 S
  138.     hres = pSvc->ExecQuery(7 U% }! f. s1 H+ m7 Z
  139.         bstr_t("WQL"), ( U7 _0 Q& W. K5 J/ l$ w
  140.         bstr_t("SELECT * FROM Win32_DiskDrive"),
    5 y2 A- o$ ~  h$ a7 ~  Q- _
  141.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
    ) l' ?- I; M" E2 U$ W& \6 E9 n
  142.         NULL,
    / D' Z' H; v+ i  p
  143.         &pEnumerator);- }, z* C3 Y6 Q8 G' g0 l6 H
  144. * q! |: `3 v  u/ N1 _; x3 e5 ]) i
  145.     if (FAILED(hres))0 T0 y, A" P& M4 l! A' k
  146.     {
    2 N( E( {* \0 n) U4 ?
  147.         pSvc->Release();3 ^% q2 L" z: }. k9 w
  148.         pLoc->Release();+ U4 l+ Z2 i0 |  `! q
  149.         CoUninitialize();
    $ A; _, w* J) c  `$ O* e4 c
  150.         return 1; $ l6 I3 a: ~: q4 }# t
  151.     }9 z: \8 _: L$ o7 a8 u; r
  152.     while (pEnumerator)' A7 y0 A$ z. k* k
  153.     {
    8 f! w# v9 b0 F4 L
  154.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, 2 e: z* u# R! q. N
  155.             &pclsObj, &uReturn);! c6 g6 b. J& X+ {4 ]3 s9 l9 m' K3 u
  156. 7 a2 U6 \1 b/ C7 X. g: l
  157.         if(0 == uReturn)
    9 y* \  J3 b$ t) G. _9 U! A  l
  158.         {0 [1 L( N' v- p2 W# S5 n3 B
  159.             break;
    & }" x/ |4 p! c% N) E$ k+ O/ r
  160.         }2 Z# e$ [5 p9 ?0 |2 h/ m% F
  161. : P# f' q6 J1 l$ u/ v
  162.         VARIANT vtProp;# F' R1 ^4 H+ r5 P, z( v
  163.         VariantInit(&vtProp);4 @0 N( H1 s7 n5 i( H
  164.         hr = pclsObj->Get(L"PNPDeviceID", 0, &vtProp, 0, 0);
    2 b) a: ]' I# M1 V
  165.     strDisk=_com_util::ConvertBSTRToString(vtProp.bstrVal);
    7 A! a( Q$ I* A/ n
  166.     }* ?4 ~( E4 a7 _9 l8 ?/ X+ S2 p
  167. ) L4 Y9 B6 f( X* S$ T9 `' K# h" C
  168.     pSvc->Release();
    3 }, W: _* H; ?. r9 Q/ Q9 C3 |
  169.     pLoc->Release();# A( z: ^% A6 Q" b* Z
  170.     pEnumerator->Release();
    ( G" F$ A2 l+ x7 Y1 |
  171.     pclsObj->Release();
    8 ?0 c, u- H5 @% C8 a% D1 ?/ x$ c
  172.     CoUninitialize();- P0 k: J* H+ z$ M# y

  173. 0 U: ^1 h# H) i- |  k5 V
  174.     return 0;   4 I1 u$ l% j; o3 R
  175. }
    0 f! q. D. l! k
复制代码
 楼主| 发表于 2010-10-11 19:21:05 | 显示全部楼层
本文代码经ccrun(老妖)在Win2k下试验成功.! T  A2 U) g( l
) B$ S( `; X& x) \, M
#include <WinIOCtl.h>
& a9 l5 [- W- m" s" O#include <stdio.h>5 e3 s* h. L7 K0 t
+ t* c5 }# j$ u" z
#pragma inline
! A; \( l% {1 n/ z/ `$ T//---------------------------------------------------------------------------% X) O5 ~2 `2 V! E( o$ f
// IDE NT/2000/XP专用变量+ j/ V: B7 O! c- k+ s" k1 _3 T
#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
6 j: ~! t2 L+ E6 B# A! g#define DFP_GET_VERSION         SMART_GET_VERSION
- f. V8 y  y/ u. a#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
/ J/ W+ D4 H$ H#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
3 J: Q; d7 |) s) x+ D
* n5 ^, q' t+ @" n- p( K! [const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令; s5 D4 N. J2 J1 I8 s+ i- T
const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
1 s* e% u9 u- B( o/ N
" ]: v) B; k: o: u5 c  D. oconst int MAX_IDE_DRIVES = 4;
" w7 s7 H/ l& ], P
6 }) l8 H3 ?- ?/ I// SCSI专用变量
1 n- E  s) S; |5 iconst DWORD FILE_DEVICE_SCSI             = 0x0000001B;: J1 z) Z5 H7 a
const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
7 ?/ b/ i5 k' x$ j% Z. ^6 \# h5 gconst DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
% e6 m, S7 c% X; i: dconst DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
+ |6 c8 }: w5 A1 `* i! ^, k# A5 w  Z9 }6 d6 |! L  U( P+ Q6 w( N
typedef struct _SRB_IO_CONTROL
' s7 ~# p" C! D: u* A  v{; V. n9 d4 m2 }: m: X& @
    ULONG HeaderLength;, a6 x/ }/ S' @
    UCHAR Signature[8];; c" C! U1 I+ \% C( O, z
    ULONG Timeout;
# a; @' H& D  q5 k    ULONG ControlCode;  A. N/ D. H; p! q- r
    ULONG ReturnCode;: g. R4 i0 x% f7 W3 p% B1 x, F
    ULONG Length;
7 a; h5 }" T, c& g}SRB_IO_CONTROL, *PSRB_IO_CONTROL;3 D6 q* |! W$ v# j& x6 ]" E$ L
  X3 U' ]) y, c
// 读取的主函数+ i( k+ j( {2 X# f1 g% w. U
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);' e% n8 J! Z% m- C- b' F: e2 G

* M( F* R6 x! l+ M% V// 辅助函数
, P# K1 m. L$ `6 j7 n7 zchar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);9 K) Q. G; v7 f8 I; v& U/ n# w
// NT/2000/XP函数$ [6 O& r0 ~1 ~
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);6 ]! T7 b$ J0 P
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
2 Y+ U3 I8 A! }& q3 M$ X        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,2 _5 l  l+ k4 Z2 ]6 F
        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);" ?7 j# A+ f/ i: R. C
// Windows 9X函数
: L7 U8 G/ @& R2 Vvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);
2 b6 c4 S- ~$ a8 V& V8 hvoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,8 B) ]0 B  C& A: F
        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);) b: k7 W6 D! J& C4 g
9 ?1 R. u9 e! X2 V8 t
// SCSI读取函数(for NT/2000/XP)
/ H$ i6 z% A! v+ BString __fastcall ReadIDEDriveAsScsiDriveOnNT();
0 w# Q# r  X; z/ K/ K( a//---------------------------------------------------------------------------" a7 @) a: z3 x) u& K6 f
// ReadPhysicalDrive# `; i. c, V/ |2 s
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
; q* k9 `: |2 C' |9 G{+ s* q: ^6 j# x: E% }: O
    switch(Win32Platform)
% |+ I- B( q+ ?. i9 K& R    {
  \/ `+ V0 g$ p        case VER_PLATFORM_WIN32_WINDOWS:8 \/ Y: ^3 C) W+ _! T1 [6 T' d- l1 @
            ReadPhysicalDriveOnW9X(pSerList, pModeList);) `, s5 N* w4 E8 T, x" B! V8 G
            break;. F: P! u& @5 M3 A. d
        case VER_PLATFORM_WIN32_NT:
" B+ O) U* Y  ~# w            ReadPhysicalDriveOnNT(pSerList, pModeList);
5 r0 p4 q1 E$ K. M( \, j            break;
6 p0 o9 U+ W7 }: m3 W  L  y, P        default:
8 M# B- Z' y; t! X            break;: A$ Q6 d. C$ _& H: i& P4 w8 C
    }8 j) {: {$ h$ H; P$ A7 d3 M0 {$ q
}8 S! |, l0 `% H; N+ N  J6 y0 q
//---------------------------------------------------------------------------8 c: T( q* b9 b* z2 c0 u9 G/ I( N
// ConvertToString' R7 L6 F- Q: z7 E5 C# N
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
& c  Q* P3 u; `8 }8 I* ~{+ i" {. R! j* M! h
    static char szResBuf[1024];7 m5 V' B% c7 V
    int nIndex = 0;
% Y- _: g3 z; q9 j& K  |    int nPosition = 0;4 k7 X1 D0 A% @; x; M8 M
' @( L' ~9 Y, a. q
    // Each integer has two characters stored in it backwards
0 H' C5 [8 z2 n/ p( a+ I! H' V    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
+ O$ K) D' f9 S3 `    {" X4 M* [, m5 s- |; e2 P
        // Get high BYTE for 1st character
) r6 `% ?8 p: n- g1 y        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
$ U% V+ X$ y  ?7 u        nPosition++;
. S, L- [5 d% B$ j  C- h, E' |# [7 K
        // Get low BYTE for 2nd character* i- E  O! Z  Y0 E  f8 E- t4 o
        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
( T; J8 C0 k9 T" q% Y+ q- Y        nPosition++;
6 ^  e) E$ j! O! Q: [- `1 b    }
" ~) K  k% \+ h$ Z7 L' ~9 R7 K) I3 S2 a5 P
    // End the string
& u- F' T0 k1 A$ `    szResBuf[nPosition] = '\0';
6 X: v: v& A2 c0 A" }3 a$ Y' l5 F' l; U9 m
    // Cut off the trailing blanks
5 l# Z4 j) ~; _) O: {    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--): e  X* ]  Z8 X, r# Y
        szResBuf[nIndex] = '\0';
2 A. D$ T& t& `
; `% U- R4 G. E* o' U& B: W    return szResBuf;
( F% p  v4 K# {, h' f: b}' |1 r0 f" |& M# N$ L
//---------------------------------------------------------------------------0 F! v# c9 x% e; z) m% o) u
// Winndows NT4/2000/XP 代码
) @- {: N) J7 l* U7 C( {//---------------------------------------------------------------------------; t3 c0 d% I' E( U0 [; p
// ReadPhysicalDriveOnNT
" M/ b# p; ^. `# K. z; H5 |void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)  G) z3 X  q* b& ?/ P9 u* O% I
{
* W0 e( b* {$ X: N' `    // 输出参数
# \+ U! _0 c- [. [, K+ x! E    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];0 [# F- ~& ^) c! h( _- S) W
4 f. {+ {% v' q; A/ h) E( B
    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)# e7 z, E. P) S% m
    {7 V' |3 d' H; [) i( c
        HANDLE hPhysicalDriveIOCTL;4 w; {: }0 E9 g3 K$ }
        char szDriveName[32];
' b( B: i; l& u' b6 j
) Y0 r( a$ q7 V8 A3 o+ i! |8 d  Q        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
8 R! C( u: p* ^* }1 R# f; R        hPhysicalDriveIOCTL = CreateFile(szDriveName,
. Y4 k( k% V) `/ d2 N# @                        GENERIC_READ | GENERIC_WRITE,
% l" ?4 N0 a. \% W                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,6 r' b9 e% q/ a* e- i
                        OPEN_EXISTING, 0, NULL);
; i0 J$ M0 W) c1 T4 P) j( [8 r# j. u7 I8 F  Z
        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
0 k( D6 j* ?/ I0 j; ^( B5 ^        {: h2 X" Z2 Z$ O# \  t9 {6 M
            DWORD dwBytesReturned = 0;/ l; [. W2 k6 c' H$ l
            GETVERSIONOUTPARAMS gvopVersionParams;; @9 ?& K1 D4 |* S5 I3 ]

" _9 m& y4 l' B! l' j8 u( Z7 E            // Get the version, etc of PhysicalDrive IOCTL7 P1 H! m: V8 T0 G, I- f. m
            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));5 I+ A2 |1 |" X9 n, b1 ^4 A' _

: C, k! h( v9 a; C6 l) X4 Q- Y            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
% e- ?% o; U, O: V0 \5 J; ~! e                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),4 X- X0 }( p8 K1 \3 K
                    &dwBytesReturned, NULL))
4 y1 _9 |. ]1 ]0 u0 \( h            {
! S( x7 _3 p* a  E. m, J& R                continue;
9 o9 D' J" |' Z; ~, h            }6 Q) T, z- h7 y* ]
* i/ H2 F. X  a( S, Q, J6 ?
            if(gvopVersionParams.bIDEDeviceMap > 0)
# n( s* n% v% `            {
$ c- R6 C$ O& O' }" T& v6 d                // IDE or ATAPI IDENTIFY cmd: r1 z/ F/ Q3 V9 v# @) O* E( T
                BYTE btIDCmd = 0;1 B' S! h7 X0 x. j# Z
                SENDCMDINPARAMS InParams;1 ]7 p6 e! e$ T: a/ g
                // Now, get the ID sector for all IDE devices in the system.  i% |8 T& P0 v
                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
. j" C# X$ ^  P2 u- F0 b                // otherwise use the IDE_ATA_IDENTIFY command
/ |: Y1 S% d" y3 t% R6 V                // 具体所得结果请参考头文件中的说明
" @3 _9 _0 P' W- ^; B) ]3 K                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
5 A. }3 ^% H  l6 v; A  S. `                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
8 J: Y* H7 u0 y                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
9 S# u8 D% Q/ w                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));6 I, S2 u9 W  l, @. E# c. P" i

4 @3 |- Q) q, s) W2 i; e                if(DoIdentify(hPhysicalDriveIOCTL," ]. W7 T: O2 O
                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
1 c1 r+ n4 E# i1 O- V/ r                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))- Y4 k* U: [6 K- k% }* }# q
                {+ w) T5 I% o7 H6 ]5 D: i
                    DWORD dwDiskData[256];
  y2 r: A; X* N$ s: I7 G- J' A                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件5 d+ U9 f: W  q/ `+ ?9 U. n! M
                    char szSerialNumber[21];
+ L% u+ M+ K% A7 g' S3 _8 t. \; t                    char szModelNumber[41];% B* b* z* ^9 G

. \5 W2 N. D: y# n: h                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;' u& _* j- D9 V4 x; Y$ b1 a
                    for(int i=0; i < 256; i++)8 V& j" ]+ [" O( t4 g. f; k/ ~
                        dwDiskData[i] = pIDSector[i];' n# N. \  d1 ^* \$ S
                    // 取系列号
) B9 W3 |2 a' Z+ t* _                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));& [& T4 M) {3 v0 J3 m
                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
7 D0 J7 M5 a5 z, A9 j0 [- h" A6 D1 ^9 k, t
                    // 取模型号7 W( P/ b6 D  B( S3 U
                    ZeroMemory(szModelNumber, sizeof(szModelNumber));
5 w3 y& o  p6 r* c! S/ G3 E/ p" @. x                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
4 p% U( I1 X: R9 b% B
/ Z% l" t$ N6 Z% W                    pSerList->Add(szSerialNumber);3 O" d2 A9 ]; d! x. C" |7 F+ I
                    pModeList->Add(szModelNumber);1 g/ E/ ]' N4 y3 x6 |1 G) s8 N/ x
                }6 x- S- `1 q9 R
            }
& G8 x) @8 o& m+ h            CloseHandle (hPhysicalDriveIOCTL);
- w( {2 E2 F. S8 K" `. O1 K        }
( _8 r7 p' I1 c. j) g' v+ b1 @. G    }
  [" S2 N! S, P) d. H/ y# Z2 s5 U}7 @. E% p6 I; C! `
//---------------------------------------------------------------------------
; f3 d0 B& L6 |/ o// DoIdentify
6 T8 _: E* h0 l2 c: o- Xbool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,- V( L, |- A  |. V+ h" [" F9 P6 T. Y' d
              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,& u, n" k' v" h
              PDWORD pdwBytesReturned)
! f4 Q% A6 W& T4 {{
6 y, R+ P0 s3 P8 N    // Set up data structures for IDENTIFY command.. R5 ~* k/ g6 X- i- b+ C- t& L
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
* h$ C+ g2 K6 ?1 d# G    pSCIP->irDriveRegs.bFeaturesReg = 0;
& ~0 F) s# w! |( B4 g; e    pSCIP->irDriveRegs.bSectorCountReg  = 1;
' _! t# W5 v7 i$ M2 e    pSCIP->irDriveRegs.bSectorNumberReg = 1;  f, L) Z" v. O
    pSCIP->irDriveRegs.bCylLowReg  = 0;
' _' k* r; a' n" Z3 }/ ^    pSCIP->irDriveRegs.bCylHighReg = 0;
- `* y# a. w  d' h6 r
  N; d1 Y  U  S+ x    // Compute the drive number.(主盘和从盘所对应的值是不一样的)
3 T4 W8 r; s% [0 x4 o/ V9 ]* M) `5 @4 d    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;6 |' q. v9 s8 W) c. e: O, ~) f5 L
# i! s' f) q( `' @
    // The command can either be IDE identify or ATAPI identify.8 \* w- m" c% F( I7 t# ~
    pSCIP->irDriveRegs.bCommandReg = btIDCmd;
& L" X* O( r/ O& K" ]5 _    pSCIP->bDriveNumber = btDriveNum;
- w0 f# K0 p; I! B( p    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;4 r& J. L4 w, z0 s+ Z
" R1 k, S/ |$ j. k7 U- ^
    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,: H' P8 @: F$ W$ _- B
           (LPVOID)pSCIP,
5 I1 n! A- X1 g1 K0 \           sizeof(SENDCMDINPARAMS) - 1,
" f4 g# P) D) _* w# n  s! D           (LPVOID)pSCOP,( `. k5 `% O1 e4 I; t
           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1," o- b1 Y5 |1 p1 E8 Z" B4 {
           pdwBytesReturned, NULL);
( U. G% K3 b% {}4 n$ _4 G5 A8 ~( Y
//---------------------------------------------------------------------------# j+ y, u+ h/ i6 ]+ U# p4 h7 U, P
// Windows 95/98/ME 代码' J. q; I  P, E$ a5 u
//---------------------------------------------------------------------------
7 {9 Q/ e& ^+ q4 M// ReadPhysicalDriveOnW9X
9 N: P  w: @$ S6 n. Kvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList): M( p: Y; \* q+ A1 \
{
0 y6 s- j' q2 ?" }8 V. ?    WORD wOutData[256];
  C; U8 V4 m3 T) n/ g  x! H    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);; Q; r3 P% G' t7 ^
0 u, Y+ r4 p" b; ~  x6 H/ K
    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。& Y5 a/ s3 I/ O' r& m
    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以- \9 a) I3 d( Q( G
    // 避免蓝屏的出现。(期待高人能指出原因)4 J) p+ o; `' I+ ^, u6 U# |5 n
    for(int nDrive = 0; nDrive < 8; nDrive++)
$ q% f7 _+ {6 e5 `- o6 ]    {" z& Z9 R" S% y% O
        WORD dwBaseAddress;$ b! _) O4 n( }! T5 E
        BYTE btMasterSlave;         // Master Or Slave
+ Q& |" p7 \2 S4 x1 v' a4 Z        bool bIsIDEExist;
$ J( d% y- A$ f! W$ H        bool IsDiskExist;
/ o" C1 y0 H# R* \2 F3 Z
7 J/ i  c5 z. y/ Y) I; M9 G        switch(nDrive / 2)
* }5 F* D0 {) {8 q8 F        {- A0 H" R( j1 O6 {8 I5 j+ ^
            case 0: dwBaseAddress = 0x01F0; break;  |  \4 i% L: a( M1 l! a. m6 U
            case 1: dwBaseAddress = 0x0170; break;, h" b" G) T# d! O7 g& p# `
            case 2: dwBaseAddress = 0x01E8; break;' [3 S1 E& L2 L8 I: N7 v* @4 V
            case 3: dwBaseAddress = 0x0168; break;% z$ L0 e+ _7 X  [, S
        }- j- e1 L' [0 Z: _5 B* V5 b

$ G2 E  q3 @2 f, l5 `% h- ]        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
! `% M( R) ?$ J
. d0 p/ r4 {* C        // 进入Ring0
! L8 v& ^5 [* @8 r! D% i6 l        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
- r3 }$ T: i6 J% [                bIsIDEExist, IsDiskExist, wOutData);$ \& D# y$ P/ N7 E8 |" r1 e# j
    }7 n, G1 L4 A% J: ?: r5 r
3 p) N# C) ^8 u& E' S9 j
    // 开始读取3 k5 u5 Z5 Q* F( a+ ^
    for(int nDrive = 0; nDrive < 8; nDrive++)3 X% {' x2 l; L- F" j& z5 l# T
    {2 B4 J7 l' w- w$ l
        WORD dwBaseAddress;
% B2 X3 q+ g) R$ L8 W        BYTE btMasterSlave;         // Master Or Slave
% c  S5 {8 }1 k* T) u        bool bIsIDEExist;1 e" S+ J0 `% Z, U
        bool bIsDiskExist;
1 h/ W+ I1 Y; @( _8 n; C/ F8 q        switch(nDrive / 2)
, r  S& ~  I0 F4 q" n8 o        {
5 V* n/ \% v+ h, K; c            case 0: dwBaseAddress = 0x01F0; break;- M4 Q/ a: _# f; k( L
            case 1: dwBaseAddress = 0x0170; break;
( K3 l1 x' V# j4 v* K% t2 l            case 2: dwBaseAddress = 0x01E8; break;
: ^% n5 z. F& K: s# a# ~5 d! o4 ]            case 3: dwBaseAddress = 0x0168; break;/ [8 s2 n# M' z7 f) z8 k6 \) _
        }
& q6 ^! Y. e8 ?8 c; J- m
, H& x0 E7 V/ ]3 c. P; A; ]8 c: X3 P        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);, a5 D! P2 W2 D& y( e% ~3 Q

0 V' i" ]9 V; B9 a7 ^        // 进入Ring0
1 N+ r6 m6 e  e1 a' z6 W) }) ^        bIsIDEExist  = false;( E9 }4 q- j. m& k4 q' Q9 h
        bIsDiskExist = false;
2 b6 U/ C! A. s: H, p, f        ZeroMemory(wOutData, sizeof(wOutData));
% P5 U+ @/ w. K# L# |
$ w+ C( M" [2 r$ i        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
% E# a+ a5 b/ y% p% q                bIsIDEExist, bIsDiskExist, wOutData);0 x" Y) Q8 y3 C
  W+ q/ H5 G8 N' ^$ I9 E
        if(bIsIDEExist && bIsDiskExist)5 r8 j) Q' S3 v; M  D% k1 j
        {. l% q( h, R# L  [( J$ a
            DWORD dwDiskData[256];
" R6 c) p# r, t- l6 w: a7 Z5 E5 a            char  szSerialNumber[21];
- g; M6 }# O2 t! f& x, L* N            char  szModelNumber[41];
, \0 H4 ]( t- a. j
! k* }7 [' P3 o; L: S            for(int k=0; k < 256; k++)( Q9 M# F& [2 n' k
                dwDiskData[k] = wOutData[k];
9 L+ z' b0 A! s3 T0 }3 B! D! J& @% N! U9 ^3 d
            // 取系列号4 }  r; M! _) x$ o7 U  }
            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));% w. Y0 T0 b# E- {0 }( r5 A, c
            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));2 F, [4 I3 o' F2 C% z( I

0 L: E5 j$ o& ], H: [, o            // 取模型号
! D9 k* q, E# n' j' s- c: A- P            ZeroMemory(szModelNumber, sizeof(szModelNumber));
9 E2 S! C: P/ b            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
. y" O0 l& r. d- H  W% ]; G2 u3 J( n0 o
            pSerList->Add(szSerialNumber);
. s+ H" C) H7 ]! v5 Z            pModeList->Add(szModelNumber);
' U4 H5 j& E9 c; O        }6 E+ t- {! J8 k% v5 P, D8 [, T
    }) d: B& x+ n! \% w
    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);9 p& s* k) @# _2 d* V
}
$ Y$ f% O1 i3 J( _+ n0 ]! Q* c//---------------------------------------------------------------------------
& R% x1 F$ k8 Q8 A" J, L- S// 为防止不负责任的转载者,在此注明原出处信息,请见谅。
- _; r9 z8 E! N& K  T// 资料收集整理:ccrun(老妖),欢迎光临C++Builder研究: http://www.ccrun.com& q" ?8 j% j) O3 U
//---------------------------------------------------------------------------
7 w+ M4 S( u% T. V2 t1 @// ReadPhysicalDriveOnW9X_Ring0()
4 m4 \/ @. |! h! T- c; J//1 C  Z0 R6 n" D* ?5 K4 |9 K5 s
// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
# f+ J7 S2 A  j+ f* D4 G8 h" W) y// btMasterSlave = Master(0xA0) Or Slave(0xB0)
- X- _' ^  ^1 c//---------------------------------------------------------------------------
8 G8 I5 k# E& \/ B$ ~void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,% L& F& M# I0 O: L- V7 n- i' z+ V& g1 y$ o
        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)1 b" b# ?7 Q: W! f3 J: x% _& W. x# P
{  H$ H. O; |7 O4 h! ]: C/ Q
    BYTE  btIDTR1[6];; F9 Z8 |% ?6 |  W
    DWORD dwOldExceptionHook;
" R& v0 m' `9 |% e; S    const int nHookExceptionNo = 5;
$ Y3 k- \5 D+ [5 s- ^! `" W; z5 N. m8 L& S$ P4 I+ D
    BYTE  btIsIDEExist = 0;
* i. {, Y, a2 I: R7 ~' c, v    BYTE  btIsDiskExist = 0;  i2 P7 z6 L4 N
    WORD  wOutDataBuf[256];# L* v1 L. I. v! m4 C2 {& I1 @4 x
: E8 t$ f. y1 H7 \0 N
    BYTE  btIsFirst = (BYTE)bIsFirst;
* O% X3 b5 d3 U, `
$ x: c& u( }: h& F( ?. [3 C/ O4 Z    const BYTE btBit00 = 0x01;
  k$ Q0 ?, d' J, p' Z' |  Q' w    // const BYTE btBit02 = 0x04;
$ Q5 o5 g" w( [9 m    const BYTE btBit06 = 0x40;2 `$ C7 B& m0 h5 X/ e
    const BYTE btBit07 = 0x80;" z' \/ s+ p$ x/ V, P
    // const BYTE btERR  = btBit00;
) C/ P0 a7 S/ [$ {( o! \, m    const BYTE btBusy = btBit07;
0 l1 ^9 d+ l0 m- \3 }    const BYTE btAtaCmd   = 0xEC;
( v  L' U& ~% ]9 y! K( I    const BYTE btAtapiCmd = 0xA1;* U/ g( M8 _* x4 N' N
2 i1 z% U" }- d4 ]+ Z: J
    __asm
0 c& S  U7 `* \$ k: m8 \: U9 `    {
; @, Y8 e- _0 C1 t$ w        // 必须先执行这条语句
4 W1 r; d/ K* [$ K" q        JMP EnterRing0
7 M+ Q/ G% {- w5 A& C9 t8 g7 p6 j  y7 f4 [4 Y6 X0 `
        // 定义过程
7 N) Q% ]+ }0 j2 b1 V( @: F        // 等待IDE设备直到其不为忙为止
. e# J# S* X0 |3 u8 Y. A4 v3 }' i        WaitWhileBusy proc
+ O+ S" u# ~1 F# E+ T% k) R' {5 b) Q  s1 p5 [3 x8 f* Q4 l
        MOV  EBX, 100000- g+ e/ Z: {+ W
        MOV  DX, dwBaseAddress6 @6 q& @+ [3 s  L$ R5 @4 j- T4 f
        ADD  DX, 7( f. l/ y0 H" [& \' f/ \2 P( U% v

$ _, t8 C3 n, P1 W! f4 O        LoopWhileBusy:" T0 X5 X! f  ^8 j" O

) y) V/ `# V2 k& W+ f        DEC  EBX0 B3 a5 O1 x5 T/ v+ w, S9 \- ^; x
        CMP  EBX, 0; D: ~' E7 z* O1 v
        JZ   Timeout$ |, x! G4 [3 t$ s+ ~
        in   AL, DX
4 e) b; a2 J7 s  o        TEST AL, btBusy
( h' _# l/ P" W$ m        JNZ  LoopWhileBusy2 P% L' A+ n0 V2 L6 n, O; g% {' ]
        JMP  DriveReady
8 Y) y/ s) z, D
7 u5 s0 X% x/ }" {        // 超时,直接退出
& d8 N+ `- v) I5 X* b        Timeout:( f1 \& T2 r4 X. z/ a
        JMP  LeaveRing0
. ^0 l; I) `" A/ R, G$ P- J! K        DriveReady:4 s, a  ~3 u; @& \0 i
        RET8 f8 p: G! Z1 N, R
        ENDP   // End of WaitWhileBusy Procedure
* d4 @+ M, B) ^5 Z8 a, ^* X8 V& {( @9 A8 j
        // 设置主盘和从盘标志9 S! o# k$ K, ?! `% H) f& R4 v* }
        SelectDevice proc
4 C& w! f& e0 m+ ^# Q5 F. u' y. s6 w6 Y- ~$ n
        MOV  DX, dwBaseAddress9 B/ p6 ^; V9 G. u0 Z
        ADD  DX, 6
2 q/ u2 f$ y' h, i4 e0 w        MOV  AL, btMasterSlave" L2 j' a/ k. J; k, Y3 j+ p
4 b) a) t# W) C4 x  x" j: U
        out  DX, AL. o3 t( h; @  J& r+ u( ], v' M# E0 e
        RET- W  D; k- C# S1 X4 W: `
* d% g. h9 i" ]; E  [
        ENDP  // End of SelectDevice Procedure
9 Q0 k& }  c5 J6 v# y: t2 P( h6 V$ C
9 {' B' Q6 P$ r& B1 M' a        // 向IDE设备发送存取指令4 [8 ~: u0 P3 I$ Q6 U
        SendCmd proc
: B+ }$ @4 f1 e+ f3 d( w# t( a  I& {' R7 {8 T
        MOV DX, dwBaseAddress! s4 D) \" J% U! |; n" [/ Y, i1 s" X$ a
        ADD DX, 7
! d& I6 N3 U: m: m/ G) ?        MOV AL, BL // BL是主从盘标识,在过程外设置
9 i" d+ W8 \4 Y; F5 L* _! O- K        out DX, AL# A. m- h! o" s$ f! ]
        RET, R' {8 }4 x# D5 }2 u
        ENDP  // End of SendCmd Procedure+ _4 Z# h9 k& g$ C8 B

5 l5 z7 A, g% k. q. M' H9 K        // Ring0代码
8 h! }) j, `  H0 {' f# }        Ring0Proc:
2 M3 _6 L* h& D8 D2 O; O6 _        PUSHAD
8 `7 u5 D6 O6 j# `1 z2 W& i        // 查询IDE设备是否存在) t' Y, {$ Q: U: r2 m; U8 K% M
        MOV DX, dwBaseAddress
: ^& U  c( |( Y/ K8 c, Q        ADD DX, 7
1 f  K# V  L$ ?3 G        in  AL,DX2 z% d# ~% D7 U9 @( |& F* n# M0 i

7 t/ U+ M3 O0 C- m" G7 @7 H        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回! p* e& @6 D5 d8 M
        CMP AL,0xFF
$ O+ a6 D& Q9 i$ M9 u( r        JZ  LeaveRing0. j: B2 W! [! p* p( p
        CMP AL, 0x7F
* O" p: l, \! Q1 H/ c        JZ  LeaveRing0% c/ g8 o1 e5 E
1 d3 ]$ w& [1 j* |. W
        // 设置IDE设备存在标志) h# [, F. L, h" d9 u' m
        MOV btIsIDEExist, 1
/ }; V; _# R+ B! y8 T' j$ |/ S1 R/ ^, F
        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)$ _% R' B& H6 v5 G+ I- R! f0 L
        CALL WaitWhileBusy
$ x' w1 z$ s  a# l        CALL SelectDevice) z$ i) Y$ ]4 y

* V8 _4 L. t4 E* m        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
* s% m" c" D0 v& S) H, X        CMP  btIsFirst, 1
' R5 t( c! K: B" W5 d6 i5 r; V        JZ   LeaveRing05 t, T8 {2 M  P7 K, L7 R" Y! i

: z$ E$ d! s( V' `        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???+ M. ?; \1 V# p& R5 ~
        CALL WaitWhileBusy' C# j, M# I% F% @  J
  A: T5 O1 J" H# w7 Y# D& z2 c
        // AL的值等于cBit06时,不存在驱动器,直接返回& N' S0 x" p: e
        TEST AL, btBit06
! I. A7 I+ @" Y9 p+ Z        JZ   LeaveRing0
. H" ?' N& i; l. ~+ K5 u  X1 Z2 w8 C  |, E
        // 设置驱动器存在标志
) S9 T3 D9 q8 i; v6 a        MOV  btIsDiskExist, 1
3 l- {9 ?2 P3 V# o9 @& ~
1 i6 h% B1 \1 f        // 发送存取端口命令+ s8 _. {2 C0 u
        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,; N% g! G" o1 H4 `5 \. L. @1 S: {
        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令1 B( ?  F( T/ t3 m' ?9 x
        CALL WaitWhileBusy2 _( [; c7 m0 ]
        CALL SelectDevice    // 设置主从盘标识
' G4 h" }; o- J9 E0 v5 d        MOV  BL, btAtaCmd      // 发送读取命令2 V+ D( @% M7 f0 C+ ?0 n! N
        CALL SendCmd1 K! O4 E9 r) t5 W2 \
        CALL WaitWhileBusy
6 `7 c( M- A  b5 T3 [  {2 x
5 i: o& j  D+ ]% q5 P+ ~) j6 J        // 检查是否出错
7 N) n+ X3 c/ o8 Z1 G        MOV  DX, dwBaseAddress
: \! g7 w1 H; W1 g7 @# e        ADD  DX, 7% A# a9 ~" D/ l. v( ]
7 r2 W. ~  Q  z- M% g0 H
        in   AL, DX
/ R: P( S, Z" M; r9 C# `
9 a: j/ T, B3 l! I        TEST AL, btBit00. T. A6 S( v1 D' t4 ~0 |
        JZ   RetrieveInfo   // 没有错误时则读数据, L$ b! \- D" I4 _1 i) Z

% b, G. g& Z+ `1 k        // 如果出错,则进一步尝试使用ATAPI设备命令
, P& G4 b; Y: q7 P6 ]7 L) F% D  P2 @4 q        CALL WaitWhileBusy
1 Z2 z) ^8 a( {  l) G7 g        CALL SelectDevice
! j; Q3 V+ E4 e1 h3 C6 u! C1 ]& e        MOV  BL, btAtapiCmd+ h! v' C5 ?4 m
        CALL SendCmd
  S3 _# m  k, R' C# F8 G3 s        CALL WaitWhileBusy
" o- n4 e; k- f* I/ Q( H$ X
6 M' U5 {) M2 D/ q$ L        // 检查是否还出错
; u, q: k- K7 ^" L        MOV  DX, dwBaseAddress
; |" z8 D$ b$ u: A3 |4 a- [1 I        ADD  DX, 7
7 w0 w- i1 L$ \        in   AL, DX
+ i# }. o. n$ T6 L% X3 E5 n! F1 @        TEST AL, btBit00
/ F* g" g9 N( l% o        JZ   RetrieveInfo   // 没有错误时则读数据
; ]0 x7 J) f8 k0 {( U1 q9 q( B        JMP  LeaveRing0     // 如果还是出错,直接返回( w+ m3 M" w2 h
; W' \- ^8 D% C  s* B+ z. u
        // 读取数据
( [- _. y" v+ E" ?' {" K        RetrieveInfo:) [& [, A7 L3 j9 y

' p: {; f* ]% \" a# V        LEA  EDI, wOutDataBuf) R2 I; V! M$ J+ h6 E( f& x
        MOV  ECX, 256
4 }% ?7 I' @: u( }        MOV  DX, dwBaseAddress! A7 E8 v: C) K$ [  S
        CLD
; Q2 n8 V6 w7 ^' ?' y( a. S$ Z8 e* q) Z. ?, R' q5 o  X4 Z  Q) F
        REP  INSW( U% |: I9 S- r4 F, I  @8 z" u8 ?
+ b& w: b. ?7 [" E
        // 退出Ring0代码& m* L3 P: `( n7 z4 Y
        LeaveRing0:. S. U! D5 w1 P% W% Z/ M! Q- a3 b

- E7 W0 @( [; `( J' l" z        POPAD& d' b7 W+ p  Y4 O5 b" U
        IRETD  P+ f% y! h' l: A* _& u

# q8 Y! l3 ?! C7 v' \$ E        // 激活Ring0代码" i' _) H: V! G" Z) q
        EnterRing0:
' a- D" m5 A/ U; p' t& o* m9 b- q8 E) _$ c' `9 `6 s0 N0 F% e9 t
        // 修改中断门
; a0 ^0 H2 j4 ?  e6 z        SIDT FWORD PTR btIDTR1
. |; d0 i# s% F  K+ P        MOV EAX, DWORD PTR btIDTR1 + 02h3 s1 F! v. J% k# }
        ADD EAX, nHookExceptionNo * 08h + 04h6 F& q0 _8 }4 f7 O# q
        CLI
* e8 P4 T& `3 E$ C0 Q1 U' h0 X3 \) Y* B) j% }  C1 y) I
        // 保存原异常处理例程入口8 i1 _/ _+ ~2 j$ {& S" q
        MOV ECX, DWORD PTR [EAX]
7 X% Z' ~4 c1 i" h$ J% e/ \        MOV CX, WORD PTR [EAX-04h]
0 d+ R* d( s3 w# Y! o8 z  j3 {        MOV dwOldExceptionHook, ECX& ]0 y) {8 Z  \% F+ @" r$ f
! `; }2 i; y7 w( f7 X2 S$ B( a% }
        // 指定新入口
: |! W8 ], W# F$ t* y        LEA EBX, Ring0Proc4 A9 }# A- P8 @: D( M1 C& I2 K
        MOV WORD PTR [EAX-04h],BX
6 a5 x1 U0 R) V3 C/ e        SHR EBX, 10h
5 h1 l; ]! V) x& B' q6 V        MOV WORD PTR[EAX+02h], BX' H* F+ r% f+ L* o" F# X8 P

' t# x+ x$ }' P: E7 d9 Q' q5 k        // 激活Ring0代码
3 F3 b. M$ P, b+ J        INT nHookExceptionNo
+ G0 q; k- F( W
8 v- y5 E0 c. J. I        // 复原入口3 u* l% o3 {: u6 h
        MOV ECX,dwOldExceptionHook
- t% x' J0 H7 F& X) r& X        MOV WORD PTR[EAX-04h], CX, t9 I( l  [# x% S" x, E
        SHR ECX,10h
. H/ \; S! ^. i& }1 e7 s6 r        MOV WORD PTR[EAX+02h], CX
1 G8 r. _0 n2 [; H5 T        STI( W: l. J  H- y  X2 t7 s: W1 j
    }8 S6 [0 j- s" _& k9 b. M% {/ H3 u# L
    if(!bIsFirst)
5 J7 X0 G/ `7 [5 _    {2 [( J: T0 B# i5 W( r6 P* }
        bIsIDEExist  = (bool)btIsIDEExist;
" n8 G* \. I1 K, p; B8 U        bIsDiskExist = (bool)btIsDiskExist;& v7 p9 o8 A" S1 S
        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));/ W8 p  M5 G( i4 c" c% I8 G9 X
    }' v, s" N% b; `+ {+ ^: ^1 r
}
4 s, w, B& L3 I% r8 A; [7 Z//---------------------------------------------------------------------------2 L; i; a! A( s1 ?6 Q
// 调用方法:/ ^1 z. Q! l4 |4 [
void __fastcall TForm1::Button1Click(TObject *Sender)' s: w  w' u% {. Q( }! l. l3 n
{& E% \& `- o6 w, O0 _  M/ M
    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
9 {9 L. T, D! F5 Z, t3 P7 a3 ^}" C( a% `* x; F) [
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-12-29 17:44 , Processed in 0.021886 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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