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

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

[复制链接]
发表于 2008-1-6 19:59:06 | 显示全部楼层 |阅读模式
代码框架,你所要做的仅是修改WQL语句,具体可看MSDN。以下代码为简介起见,一次返回所有的CPUID或硬盘厂商系列号: V+ f/ _' I) ]8 W% z

  1. : ^- Y7 J# d+ ~& s, |3 j
  2. #include "StdAfx.h"
    ) Y7 x2 m/ J, R+ j
  3. #include ".\puiddisk.h"
    ! f- S' e" w5 N; h/ z$ O0 p' Z1 k
  4. #define _WIN32_DCOM) b' i$ l: z) h7 s8 v# j+ y
  5. #include <iostream>
    5 p6 H  N% y/ P% f
  6. using namespace std;
    ) S/ ~+ L% H# e' d7 ^* K
  7. #include <comdef.h>9 R3 t3 P/ i6 y: K: z
  8. #include <Wbemidl.h>
    5 L$ A. h6 x0 @0 v. Q0 I+ C' z
  9. + J2 ^& O/ Z8 q8 L2 y
  10. # pragma comment(lib, "wbemuuid.lib")
    2 O2 H* g$ k+ v) P) T
  11. CpuIDDisk::CpuIDDisk(void)
    * \- |' b2 l& Q
  12. {( a: w, ~: g; |& C0 j8 E7 Y4 s
  13.     GetInfomation();
    5 W6 Z) p! L0 o
  14. }
    , e9 A" C  I+ |3 d& r
  15. 6 q0 u  A5 Q/ ]6 M2 a% y
  16. CpuIDDisk::~CpuIDDisk(void)
    ' }9 S  [4 i, s9 M5 T/ K
  17. {
    ( n+ _1 N9 @% m; J, r
  18. }
    ! S. p% q: G5 r% \
  19. int CpuIDDisk::GetInfomation(void)/ B8 ]: s2 T& S7 z) |( C9 |
  20. {) z+ _/ b/ m; G4 ]6 q% R
  21.     HRESULT hres;5 J# g- u4 k) j/ w: C
  22.     //步骤1:不是必须的,COM只须也只能初始化一次
    # G) W# S; H! d
  23.      hres =  CoInitializeEx(0, COINIT_MULTITHREADED );& q0 p) `* q$ M; [, q' k( H
  24.     if (FAILED(hres))
    7 @% {1 f. D) B, ^3 b% o2 n' h
  25.     {
    ; q2 X0 b& Z: w! X$ W
  26.         return 1; //初始化COM异常:注意,COM只须也只能初始化一次
    7 ]- S9 z0 H  Q
  27.     }! ]# O' D* C' l$ P5 I+ ~6 M
  28.     //步骤2:不是必须的,COM只须也只能设置一次# N) t; ]3 D7 t
  29.     //Set general COM security levels0 ?* R" d  L  I5 g( V
  30.     hres =  CoInitializeSecurity(
    ; |1 G! G! I; A5 t$ G* }( S1 |( @
  31.         NULL, 6 Z% @7 p# ?' k4 @2 W
  32.         -1,                          // COM authentication# y1 Y; w6 a7 q2 u5 Z, }. |2 }
  33.         NULL,                        // Authentication services
    ! a- i0 u4 `. @5 C8 y
  34.         NULL,                        // Reserved- N7 \+ V2 z) \% E2 Y' S
  35.         RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication
    4 o( x* c6 j  h8 A
  36.         RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  
    " z1 O4 c6 z: x6 |  L
  37.         NULL,                        // Authentication info
    . ]$ y8 V. l/ c9 |3 c  W1 d
  38.         EOAC_NONE,                   // Additional capabilities
    # k! j$ v& P7 S: b4 G. x# o
  39.         NULL                         // Reserved
    % A: u* {8 Q' B
  40.         );* H6 X' ~5 g  R- b6 j, i
  41.                      
    - p, @0 m: s1 A. ~# T% S
  42.     if (FAILED(hres))
    * r/ @1 I! y6 n' Y
  43.     {; W" Y9 }5 h& J9 v0 A5 R9 r7 V, V+ q
  44.         CoUninitialize();
    % z6 g  M" R8 }! v2 U
  45.         return 1;                    // Program has failed.
    6 X0 @" n/ b0 a( t1 ]
  46.     }7 `% z1 Y' \7 Q/ B& r
  47.     0 y" f9 q8 U% A0 V
  48.     //以上不是必须的,若已有“::COMInit();”,则要跳过* Z1 }/ N( H0 z9 X
  49.     //步骤3: Obtain the initial locator to WMI ; k/ l7 q+ _" x( _  H: u4 u
  50.     IWbemLocator *pLoc = NULL;: C, j5 n5 N6 K6 {- _. q
  51.     hres = CoCreateInstance(
    5 d: x9 ^0 B. F) i3 L
  52.         CLSID_WbemLocator,             3 O( j# M) t3 W2 j. y
  53.         0, 1 m4 ~6 c3 O7 V' [0 f# Z
  54.         CLSCTX_INPROC_SERVER, $ o; C9 ]0 D9 D
  55.         IID_IWbemLocator, (LPVOID *) &pLoc);- b" |  D. P! C5 d! |! q
  56. : y$ V) l5 s# R/ u( d, F8 u
  57.     if (FAILED(hres))
    ) K) O0 y$ Z6 X9 [7 g+ x8 D7 j
  58.     {
    . `$ y1 V: |. }9 t5 k
  59.         CoUninitialize();
    2 O: u) H' \# x& \, r( H  v/ ~# q
  60.         return 1;//Failed to create IWbemLocator object
    $ {2 c3 Y5 a7 M, n2 k) O* x, C
  61.     }  J; a  o( ?: L6 r
  62. ; U( R* B& d; i1 D/ D
  63.     //步骤4:Connect to WMI through the IWbemLocator::ConnectServer method. R0 Q/ M( b$ B. w
  64.     IWbemServices *pSvc = NULL;
    4 r9 z5 w' c6 r5 \) f: T. \1 Y
  65.     hres = pLoc->ConnectServer(
    3 M1 i5 T7 ]0 A, h& ~
  66.          _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace
    ' Z, v! \, s4 U
  67.          NULL,                    // User name. NULL = current user) U& J5 i5 S0 C8 T, W) I; V' P
  68.          NULL,                    // User password. NULL = current& c: Q6 }/ x; C" }  u( U  w
  69.          0,                       // Locale. NULL indicates current
    7 {, H: c1 {* C* I2 i2 `3 c% ~6 B2 I
  70.          NULL,                    // Security flags.
      N' D( e/ N7 B) V
  71.          0,                       // Authority (e.g. Kerberos)
    / |6 X0 I* m. l# M, L' o1 ~. H
  72.          0,                       // Context object 7 ]3 t7 z5 }& `( @5 I$ D. I+ E
  73.          &pSvc                    // pointer to IWbemServices proxy( T& d* H  Y; r) c* I
  74.          );
    - d$ X/ }$ _, t% X9 I* D! D6 p
  75.     , N0 }; \* x; Y* D" {
  76.     if (FAILED(hres))$ l# i' j" m9 t' ~3 W. Q
  77.     {$ r0 q3 u6 X8 {4 G* ]$ d# E0 s( v
  78.         pLoc->Release();     - U/ m; p9 C* b! a7 X
  79.         CoUninitialize();
    : _/ F6 d! r! F+ l8 M; {
  80.         return 1;                // Program has failed./ ?" C/ _5 H* x+ J
  81.     }, G) \$ T% w5 q+ Q
  82.     // 步骤5: Set security levels on the proxy
    / H0 x  E0 q5 r8 M( G! n. c; s  T
  83.     hres = CoSetProxyBlanket(+ G& j. j% {; ~  U% ?  K+ |7 W1 K8 k1 ]
  84.        pSvc,                        // Indicates the proxy to set5 r( \9 \7 l6 t3 g3 P( q
  85.        RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx
      U# x' [9 p5 `2 Y7 \
  86.        RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx* O. Z4 \: ~4 @
  87.        NULL,                        // Server principal name
    / N& `$ q8 j4 ]$ M7 e( W
  88.        RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx
    & C& p4 C( V+ K. B$ S% h' m/ V; [
  89.        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
    ! t. a# l5 b- ~5 ^: C* ~4 `
  90.        NULL,                        // client identity
    4 y1 D9 T; f% Q+ _7 P2 b8 l. H2 ]
  91.        EOAC_NONE                    // proxy capabilities 4 P' b, o& v  h5 X# ]) s
  92.     );
    ) A1 ?+ Q. |% N2 a( l& f5 ]

  93. ) i. |% M# V% M5 {
  94.     if (FAILED(hres))+ ^8 U* z! h+ E1 I
  95.     {" E* }% t$ I4 ]- Z" {
  96.         pSvc->Release();8 i$ O, \$ ~) h; I  Y6 {6 C6 H
  97.         pLoc->Release();     6 M5 T+ ^: t/ S' W4 A3 n
  98.         CoUninitialize();
    ' k9 o+ m& g% R; t. Z
  99.         return 1; , m+ d7 s" R0 _* h0 }$ u, O5 Z- J
  100.     }
    ) n! f: F& R2 [

  101. : M+ A0 o* d; h/ y
  102.     // 步骤6:Use the IWbemServices pointer to make requests of WMI ----
    ; d6 H1 f( R0 Q; l% x
  103.     IEnumWbemClassObject* pEnumerator = NULL;
    6 l% E7 x" Q* [# s2 w6 k
  104.     //计算CPUID
      }6 a0 h; F& h# H9 c' V! b& s
  105.     hres = pSvc->ExecQuery(4 u8 i6 K4 c: H
  106.         bstr_t("WQL"),
    + b9 E, u4 x$ H9 [
  107.         bstr_t("SELECT * FROM Win32_Processor"),//Win32_OperatingSystem
    4 j" e" q% l- R. ~: \2 w4 ]
  108.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, ; v4 X% k! B% o" P
  109.         NULL,# Q" h" f0 [" _* G  N$ g' N( C( i
  110.         &pEnumerator);
    & Z2 x0 _: k, g2 B! v7 V5 H9 x% U
  111.     ! i/ w2 `3 K: D: t. O0 \
  112.     if (FAILED(hres))
    9 O; W  a) j; @. ~
  113.     {
    3 ~- t7 p+ s; ~9 ^5 @' q, \
  114.         pSvc->Release();
    ! v# V, x0 |$ Z4 R+ v7 c: V3 c
  115.         pLoc->Release();+ s& d  a6 o7 {1 c' c& B1 m& {
  116.         CoUninitialize();6 _7 m- m& B. i* V$ e
  117.         return 1;$ j) A) J& _9 {4 X2 _
  118.     }
    . B3 [- J3 p% G; J% _& |& k: L
  119.     // 步骤7:Get the data from the query ) ~8 b) e2 |8 w
  120.     IWbemClassObject *pclsObj;
    ' O6 [# d8 r/ z7 y
  121.     ULONG uReturn = 0;
    ( d0 ]5 ?5 t7 S  `- J
  122.     while (pEnumerator)
    , v+ L8 W" l+ E4 o3 R4 M
  123.     {9 W1 d! b1 f, b1 f# ^
  124.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
    : g- U9 y, E, N
  125.             &pclsObj, &uReturn);, s/ B! z4 v% z( a' h% M

  126. ) D- M+ B) R( z0 X4 [* I* g
  127.         if(0 == uReturn)( Q, J, x8 f) T% Q6 A# z( b3 Q
  128.         {
    + U# i2 U( x: {9 w  i1 @
  129.             break;
    ; R, C2 V& R8 p1 y
  130.         }
    ! X  F" V& ?0 c8 k! E% X- q2 R
  131.         VARIANT vtProp;
    3 F5 g3 j- m/ H6 e$ c0 b- U
  132.         VariantInit(&vtProp);& _. B, i# K! j" ^4 S# Q2 |
  133.         hr = pclsObj->Get(L"ProcessorId", 0, &vtProp, 0, 0);) `" ^* w2 L9 d' [
  134.         strProcessID=_com_util::ConvertBSTRToString(vtProp.bstrVal);//strProcessID:类级变量
    & b8 u' R6 E  `+ n! c9 P) z
  135.     }" ~* O  Q7 I* m0 g: `+ {! a
  136. 3 w: E4 W& i+ k3 \! p" D; F, L- b
  137.     //计算硬盘系列号
    6 A4 D$ g7 w! A, j7 E
  138.     hres = pSvc->ExecQuery(5 L, Y6 y, ?7 y* p
  139.         bstr_t("WQL"),
    7 i$ p' R9 O8 B
  140.         bstr_t("SELECT * FROM Win32_DiskDrive"),
    2 Q- o: u4 s$ u
  141.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
    6 d. |& J& m" G; J
  142.         NULL,: }( l. C2 x: I
  143.         &pEnumerator);
    + [0 h0 c9 ]& F2 ^9 p# ~

  144. ; D5 V; o* ?' `; I3 F0 v, U
  145.     if (FAILED(hres))8 b. c8 W, W/ H2 Z5 ~7 U
  146.     {
    - ?1 O1 F4 [: A( ~2 W$ }7 J
  147.         pSvc->Release();- U# j) S4 N( n- p
  148.         pLoc->Release();
    % G: [7 X: R" P, C; U" O
  149.         CoUninitialize();" s, `* A$ |3 V, b1 g
  150.         return 1;
    ( R2 q  a- A$ U4 i8 ^- J& |4 r6 P2 w
  151.     }
    6 `; [0 }1 W; Q  f2 c; G7 Q
  152.     while (pEnumerator)2 P( [7 P9 e$ `$ P$ i2 a* T
  153.     {
    2 s; v$ T& z2 ]( X
  154.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, . w/ F! V$ b# p" j2 L
  155.             &pclsObj, &uReturn);
    $ F+ n1 \7 r) A* l  r, `
  156. 8 m; U; F$ T, X1 _0 K
  157.         if(0 == uReturn)! W' H1 e- _; j: [! B' X
  158.         {
      j7 f1 ]6 R4 F+ {5 e
  159.             break;
    & S& u1 w7 k% Z
  160.         }
    5 z8 M1 ?7 |- S( a( T; y) d+ `5 q

  161. ; ]2 T" l& D' }) J$ d
  162.         VARIANT vtProp;, y& |7 g' X% s, q* l( w
  163.         VariantInit(&vtProp);
    5 W5 U& z3 ?, Y4 x  I, O( N
  164.         hr = pclsObj->Get(L"PNPDeviceID", 0, &vtProp, 0, 0);) \  n. B* S$ g/ N- c
  165.     strDisk=_com_util::ConvertBSTRToString(vtProp.bstrVal);- z; e+ \/ _& T! f% Z6 T* l
  166.     }+ w2 s! b0 k5 t; v# N' Y0 n9 M* }

  167. 2 Y. ~! o) A2 r
  168.     pSvc->Release();
    2 [4 u: b; v, h  `2 q; Z
  169.     pLoc->Release();1 i' c4 N- {3 M2 k
  170.     pEnumerator->Release();# ~* Y7 r+ i% O  g/ A! Q& P1 P
  171.     pclsObj->Release();
    ' O1 \, T5 N7 m: g& z4 N
  172.     CoUninitialize();" Z+ U8 R" B, e2 v' b* G6 Z% U
  173. 7 y6 R" K0 y( _1 S1 R7 m
  174.     return 0;   " Y7 \/ g# B& ^% J! y6 T
  175. }
    # H8 Q9 C; B, L3 h* Z8 m
复制代码
 楼主| 发表于 2010-10-11 19:21:05 | 显示全部楼层
本文代码经ccrun(老妖)在Win2k下试验成功.5 r5 R2 G- q9 ]8 D3 Z8 I' r

$ D0 I4 ?) d  p7 h: B. e#include <WinIOCtl.h>
* I! ?0 W; z$ ]& b* J5 e#include <stdio.h>8 l0 J" |* ^6 ~) A
) Q) b; M, E8 H5 P; t& h
#pragma inline
5 \( i$ s# d# A% E: i8 s//---------------------------------------------------------------------------
- C+ C' I! Y+ H# x/ F/ E// IDE NT/2000/XP专用变量  j& u8 [7 d* f5 o8 i6 W% q- w
#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS. a1 `5 j9 L) F
#define DFP_GET_VERSION         SMART_GET_VERSION
* h; L4 T0 P" s; P9 G; w#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
) s- o8 r+ G8 {' l& K: @$ \#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA: d2 t# q2 k0 I- B
$ Q+ \- K) N1 L. m+ C+ `4 i
const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令5 K: j; E8 w" _7 S, \$ u
const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
; e, W' Y( `" ^" H1 i! Y. x5 w, i4 K+ l/ P0 J1 U
const int MAX_IDE_DRIVES = 4;
6 F  Z$ _$ X$ z7 M5 B# A6 d# o* c$ {( }  T4 Y
// SCSI专用变量
1 n0 Y+ N* X. j+ s3 I: |* w8 xconst DWORD FILE_DEVICE_SCSI             = 0x0000001B;! d0 o# j7 k4 e6 u
const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);: f9 V' D* i/ T+ g6 K: t
const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
) ~8 H% E" F' Nconst DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;3 Y) T; |' @7 l& e) ?/ b; o0 f

: ~) K' m1 }  J. U5 s0 etypedef struct _SRB_IO_CONTROL
  k1 m7 T( N& K! H2 o2 y! F8 w; D  V{
( [3 y* t& L8 ?2 G+ l" [1 j2 f    ULONG HeaderLength;
  u5 k. P+ s% Q7 b    UCHAR Signature[8];8 l9 D: c2 [/ ]2 j& P  d6 {3 Z, w9 \7 t
    ULONG Timeout;  n; \/ M: H( G; t5 w
    ULONG ControlCode;% @+ ?: g+ S: U& {4 n8 t1 G, w( }
    ULONG ReturnCode;: q: j- M$ a" K; V2 y
    ULONG Length;' t0 [( T! Q1 m# z2 O
}SRB_IO_CONTROL, *PSRB_IO_CONTROL;
6 X' U+ l  N# q' D" J9 c; N9 l4 h# R  K
// 读取的主函数- @; _% y; x6 ]; x
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
! a8 ~- t1 v- g% G/ L8 \7 ^$ G2 O* F, z( R- }+ {
// 辅助函数
& s  C. F) S* m, k% R. d; Tchar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);% h, B) |; n) ~$ _
// NT/2000/XP函数, M/ F) q( \6 P7 v' i' p
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
5 k9 c# ^8 z4 n6 w. qbool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
( x2 I: a! O0 a# J        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,. u  ^  C( p( H) y
        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
9 m, _# x+ B: A/ j) h, b// Windows 9X函数" W1 X9 X4 T. o3 M
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);, ^' o# q- C0 j2 `" q1 F5 v1 l5 C
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
; @. @; T$ \3 t+ O4 _6 O        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);2 h0 c+ s, @5 w4 R0 U, _5 R, O: I
( h2 i  q( j+ V8 n/ y. n( k
// SCSI读取函数(for NT/2000/XP)
7 ^1 J+ Y. ~' @- B! W( a+ U4 KString __fastcall ReadIDEDriveAsScsiDriveOnNT();
9 Y7 X: O. {1 n+ V# E//---------------------------------------------------------------------------. G) f$ K; s: Z# f% A: s
// ReadPhysicalDrive
% E' K7 l7 |' {% |# Ivoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
2 i/ I2 k  q% \5 X{
. L) `: r9 J) H3 U& l    switch(Win32Platform)
/ y% V+ V  A" A5 {6 z$ o    {
# M- ^3 }  O4 P1 c6 Q        case VER_PLATFORM_WIN32_WINDOWS:
2 s# Y5 m8 G2 @4 e2 g            ReadPhysicalDriveOnW9X(pSerList, pModeList);$ |) u- n' T3 J4 y
            break;
, N' \4 m! m3 V3 h4 w% R        case VER_PLATFORM_WIN32_NT:* x3 Y) ~% Y+ A1 H
            ReadPhysicalDriveOnNT(pSerList, pModeList);
+ d! V8 r* E( J6 [7 u* {+ _            break;
  H; R$ p- @( @! g4 \. W7 ~        default:- a* S% N& }2 f% y
            break;
. a- |( c# e7 R4 S- G    }* [6 g& g( j3 }  R
}1 V* u6 X/ `, y* E# i
//---------------------------------------------------------------------------5 v$ Y* r" K+ ?+ e: U
// ConvertToString
% [) _/ s+ b. y( H, [& C! s* ochar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)' Z# E1 i( j+ n4 M7 t
{
* w0 b. j  j3 X. P7 W7 ~    static char szResBuf[1024];
8 }0 ?5 @' {5 C# o% g    int nIndex = 0;2 m. M4 q5 U4 y+ E7 I* K9 P5 D
    int nPosition = 0;
) u6 F( l5 q9 @- _8 {% r! \# q4 B: K7 E' O
    // Each integer has two characters stored in it backwards
% Q: U( u7 [; L' F  w3 B8 v    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
6 c1 q2 e$ j' {2 S/ V    {
7 N: k9 Y$ C3 [% [        // Get high BYTE for 1st character8 f; W5 {3 \5 ?9 A
        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);4 x( N7 U: n# U5 ^+ U
        nPosition++;: b5 I- f. W3 y6 M1 H) Q
) p/ H; B. F+ D$ C' C% u& f
        // Get low BYTE for 2nd character
5 y- I) m" K8 v; h5 k4 G        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);- @. X! O+ a1 Y: K# v  v
        nPosition++;
- P" e6 N# V' D9 D- ~    }. {& \: j, w) P: B, {7 o3 F8 J
& n  e& v6 e9 I  M7 J( w: U
    // End the string, F) C! [; o, w8 e. {+ i" [" u
    szResBuf[nPosition] = '\0';" B- p) T2 {4 N! c9 t

, ^" Y4 `* S( S" p& c) M( K& ]    // Cut off the trailing blanks$ |0 p5 A, C, q" y3 ~
    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
  s2 \  }. j7 _7 j        szResBuf[nIndex] = '\0';1 q! K' A2 h* [4 Z. S

$ t  N. A8 i' M( F7 S' r1 V+ ?    return szResBuf;" D+ `/ r  v! q) M
}
' S/ P/ Z. Q0 V9 u5 Y2 Z# ^" L//---------------------------------------------------------------------------! k# {3 L0 [& b! V. Z% O6 J) e
// Winndows NT4/2000/XP 代码
% Q+ z( M6 d7 u9 }4 [' I//---------------------------------------------------------------------------
$ g& }6 G; \6 m6 y: O// ReadPhysicalDriveOnNT( G/ e7 ]# q( ^/ O
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
, U: ]* g& r- Z* B. E{1 J% z6 }4 ?" G$ e
    // 输出参数
% |# V7 A* ^+ ~) o    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];7 f, t+ S! b: e& v9 F- p

4 k6 N, a/ P( z, }9 _4 i4 \' D    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++). h8 T4 B$ ?" ^1 F9 ~+ [6 C+ T
    {
$ y0 s. x1 |' D$ j9 m; F        HANDLE hPhysicalDriveIOCTL;
0 G' j1 C7 `  ^3 F7 F! a6 P9 H        char szDriveName[32];
/ N5 }  o8 C0 n4 ]" B- I4 o2 }
8 |2 J! N2 Z- l( A* S        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
- N  a6 }# t" R        hPhysicalDriveIOCTL = CreateFile(szDriveName,
- J6 {6 H0 @9 N' R7 D: i                        GENERIC_READ | GENERIC_WRITE,4 w6 S: T# g; R+ J
                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,9 t+ _! I% g" @3 N
                        OPEN_EXISTING, 0, NULL);
& ]/ U6 Y4 p% N% @; e$ ^9 `
3 O) A; c/ H* `        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)0 I5 M$ _+ u" {' k
        {
" y( m2 d! H+ _* `) j2 @8 P            DWORD dwBytesReturned = 0;
/ M1 W" c& m6 ^            GETVERSIONOUTPARAMS gvopVersionParams;" T5 }) v6 L9 F, }4 Z) ]( n

3 S1 H/ W* W, K            // Get the version, etc of PhysicalDrive IOCTL
. _; {% m% ~/ N9 K0 ?& y$ y            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
; g0 b/ s3 x. J0 f& D
) t0 L8 w* \1 T3 S& }            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,/ t; o/ G2 H8 Z8 K8 e8 W& C7 N
                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),8 a: B1 _2 \  Y/ V5 y
                    &dwBytesReturned, NULL))1 L' j7 m9 n6 L% T
            {8 o/ r& @. u8 H, k' ~
                continue;
& j1 K7 A: g- C+ c* U. e4 ^! [            }! g$ S' A; F% c! Q

# |: V/ }' X2 I8 r* u            if(gvopVersionParams.bIDEDeviceMap > 0)
! n+ O* {8 B/ t6 A2 B1 e            {
/ C. R0 S( H6 U( X8 N2 Q& W- H                // IDE or ATAPI IDENTIFY cmd
7 t  e7 l  \" T( s5 i& V0 z                BYTE btIDCmd = 0;3 F1 K6 y4 {+ Y/ ]7 a
                SENDCMDINPARAMS InParams;
( V( r: i$ o2 l. V/ u                // Now, get the ID sector for all IDE devices in the system.
" E  W2 _/ e% h9 s; `- [                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,# M/ R# Y/ I# s% V- @$ N& V
                // otherwise use the IDE_ATA_IDENTIFY command
% J! W4 _+ e8 F$ N                // 具体所得结果请参考头文件中的说明
; O8 ^$ f1 V: I+ u6 }                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?* }2 v6 @, p  P+ R8 H6 u8 Q
                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
- e/ W, a4 R. G9 h# z- T                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
! @, r: K: W% t* }                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));  t5 I6 U# O2 b% z) e) F

- b% b( a8 }& L5 Y5 N                if(DoIdentify(hPhysicalDriveIOCTL,& W, P- [- |6 C& Y8 p; V
                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
. Y2 P; `2 v( {! k- n! s+ ~! W) |                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
1 b5 J  x- e  r: N4 V                {
+ X2 Z* ]& Y. i3 A7 F                    DWORD dwDiskData[256];: K. I; J2 `2 o4 l4 y9 t9 N$ f
                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件- S- L( w' v) n5 ?$ [' y
                    char szSerialNumber[21];6 {$ R# c" N1 S% b$ _% o
                    char szModelNumber[41];' }/ A, ?# `5 C* ^$ \8 v. S) r$ P
7 f8 d2 x/ F) u: h6 F
                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
& Z; T/ Z5 P& Z; U  f. K                    for(int i=0; i < 256; i++)1 h; ^, ^  N: J8 Q6 A
                        dwDiskData[i] = pIDSector[i];" _7 s  I2 c7 G5 G+ I9 a- @
                    // 取系列号
- A) M, S# m+ Q+ ?# N                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
; m9 l( I3 q4 W  J( ^7 i4 E                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));  E- O6 i7 K& f6 p5 s

% v5 y% Q: V+ }9 F: q$ I4 v5 i                    // 取模型号: r% o/ D) F% v% h+ {( H
                    ZeroMemory(szModelNumber, sizeof(szModelNumber));5 F, Y2 ~- X6 ~+ [" t2 K
                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
* {0 Q: i) q. h: _6 p3 f4 w; f8 I/ D. D/ K
                    pSerList->Add(szSerialNumber);! ?  r5 o1 I* N- n0 R
                    pModeList->Add(szModelNumber);/ z; }# g: `: R# r) C* l" k  T
                }
: w4 J: V- K  E5 d" u: M            }4 a* v6 e4 b6 l  M
            CloseHandle (hPhysicalDriveIOCTL);$ b( W0 @- i; X, q7 Q
        }
% }+ d% `& R% r; s3 B+ G    }
/ m& ^; {3 E9 t# {}
  _% p! R+ ]6 t+ `$ @) r//---------------------------------------------------------------------------' G  g! G7 M& H* {" E' C1 X8 S' @
// DoIdentify
2 z3 a6 ]' @( g. {( _3 f$ Vbool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
1 h& p* m" P, J; q& W# I% q" F. e              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
) G/ a' ]% a3 d% N              PDWORD pdwBytesReturned)
; p* W+ Z) u7 l" o$ Z+ q{
- U1 T% M' r( W# ]2 `4 `3 T- X1 n    // Set up data structures for IDENTIFY command.
7 f, M4 c: B5 s8 `' v5 w    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
- W9 c+ y. K/ c; D- K9 U$ z    pSCIP->irDriveRegs.bFeaturesReg = 0;
( [$ F3 S8 V1 C$ p- N    pSCIP->irDriveRegs.bSectorCountReg  = 1;$ Y3 Y0 Y; m5 L  n4 l) }  g7 v
    pSCIP->irDriveRegs.bSectorNumberReg = 1;9 O0 v0 D. ]1 @  l! `
    pSCIP->irDriveRegs.bCylLowReg  = 0;
, W% L8 X' }! ], i! G7 f$ p* y4 N    pSCIP->irDriveRegs.bCylHighReg = 0;' X- `9 N# j( Z" }# N+ z

: A1 J* z) p) J( A) j    // Compute the drive number.(主盘和从盘所对应的值是不一样的)
: O1 x3 Y% ^0 `( U  h    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;& B2 o. `9 w7 V2 k, Z; G3 x) u& R

1 A3 B+ m; ~; ^/ s/ F; s    // The command can either be IDE identify or ATAPI identify.' X5 T+ K* [4 m
    pSCIP->irDriveRegs.bCommandReg = btIDCmd;
) m! M1 [& `+ M6 @1 a    pSCIP->bDriveNumber = btDriveNum;( H( a& n5 j& ~
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;: f% R. ~8 _6 d. c  x

2 t+ r2 C/ f* n. R% @    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,; N, M0 a3 u" C9 w
           (LPVOID)pSCIP,
( O* c9 W' b& s           sizeof(SENDCMDINPARAMS) - 1,
: T$ _  ~  [; o           (LPVOID)pSCOP,
/ d# k  |" J& g6 B$ S           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,5 Z$ ~) T# s7 O
           pdwBytesReturned, NULL);
* s) y8 G  O3 ?3 k5 v* }4 l7 `}+ s5 m0 Y4 o/ w  S3 C
//---------------------------------------------------------------------------6 o) ]9 V& T+ |- Z$ K0 t% J
// Windows 95/98/ME 代码( B) |# U2 w7 t5 O/ d
//---------------------------------------------------------------------------
& G# F, r  V% _! e5 R" B) |, g// ReadPhysicalDriveOnW9X
  f5 o+ k# X' z( y; o2 l8 Lvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)9 P9 |$ f, P3 M7 S0 n# z1 F
{) t  s! X* O, c2 [3 g9 F
    WORD wOutData[256];4 i4 G3 w# X$ ]
    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);3 B5 f  f' b3 J7 P( j+ y

  I' X  U! V2 x8 |, {- O    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
% k- D+ \8 w' _6 Z8 ]* X    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以+ i9 P8 c' }, R1 w9 M* B: e! D! V
    // 避免蓝屏的出现。(期待高人能指出原因)
7 X2 `( D# Z* i3 t' k) W! u    for(int nDrive = 0; nDrive < 8; nDrive++)/ {( \7 j7 `, F2 V# V
    {
1 v- r# `# v0 s/ i! u+ G  N        WORD dwBaseAddress;7 n* r" d+ ?8 v; v  t$ Z! E$ e6 c
        BYTE btMasterSlave;         // Master Or Slave
; E: r% G) {, \! C4 _        bool bIsIDEExist;
9 w- r, `4 r: Z        bool IsDiskExist;
, I7 s! c3 Z5 u. C9 G+ O7 D) {, V; q& v0 @
        switch(nDrive / 2)
& d  r- R% N* |) r        {# c- X$ H3 s4 y7 D* ]3 o4 ?
            case 0: dwBaseAddress = 0x01F0; break;
. k: m% L2 i4 ]" s            case 1: dwBaseAddress = 0x0170; break;1 G+ |; E! h! V2 h3 e
            case 2: dwBaseAddress = 0x01E8; break;7 a- Z  S4 J$ A+ e& y
            case 3: dwBaseAddress = 0x0168; break;
5 J0 l3 k9 I! K) Q        }* a! c5 w" j* \% I

+ i2 U" ]' X: k        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);0 m( N( w! b; z# D
) ?5 u8 \* d' v" M% q9 g" H
        // 进入Ring0
6 \( Q! i! U8 X) j7 H6 R        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,; _! l. L6 u4 v! c2 Z* j8 E1 c
                bIsIDEExist, IsDiskExist, wOutData);/ A* n9 g  Z+ i1 w0 k; z
    }1 w: ?/ _/ C1 P; h7 p  }* M
8 d; n3 M( z& w* E. T
    // 开始读取% }3 ?& a# _$ X5 T. F
    for(int nDrive = 0; nDrive < 8; nDrive++)
6 ~2 j/ _# G4 g; g$ k4 V' o! a    {6 p, ]9 s" [6 H( T
        WORD dwBaseAddress;
1 _0 v3 B( ~: j+ L9 U        BYTE btMasterSlave;         // Master Or Slave
' S& v* X. x' d        bool bIsIDEExist;8 {) ~. f5 h6 i7 v2 F, i
        bool bIsDiskExist;  @2 {7 d6 I. p2 M
        switch(nDrive / 2)  [0 V; W2 C* D1 r: P4 m
        {3 C( f2 `0 @( J1 g2 f! x8 U7 d! X9 y
            case 0: dwBaseAddress = 0x01F0; break;
9 ^( @% _( }- h            case 1: dwBaseAddress = 0x0170; break;
( }! D  V+ u' H! e  h( a/ A            case 2: dwBaseAddress = 0x01E8; break;
5 G. Q0 a* o) ~' ^            case 3: dwBaseAddress = 0x0168; break;1 S5 M2 ]4 S5 w, y6 e- d
        }! j* A" [2 [( k9 \
4 H3 u+ u' M7 A' f, N- f
        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
1 w( A1 O+ I5 I  @+ q# q$ \, a+ E& C% u* t6 Y% A
        // 进入Ring0+ a9 t1 U9 |# z* O: Q! c
        bIsIDEExist  = false;$ {2 k* C. k, i- u9 F3 E" @$ v% z
        bIsDiskExist = false;
, M: _/ m9 w1 |        ZeroMemory(wOutData, sizeof(wOutData));
! K* h  t0 i. X' e' P
$ J  @( ~; b) r4 c9 C1 C) j; [        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
# y- T4 p- X8 X! U4 i4 ?: [                bIsIDEExist, bIsDiskExist, wOutData);5 D7 J4 f2 U* R

/ \7 M! e# H5 N2 c        if(bIsIDEExist && bIsDiskExist)
3 E  s. o: O; D        {# t; g( d! o4 i6 L0 W9 H
            DWORD dwDiskData[256];  B" S" g' b/ I' c' Y+ n  q
            char  szSerialNumber[21];
$ n- P, y, d0 e; s; ]2 X            char  szModelNumber[41];
' M) P( }$ E2 q1 e1 s, b+ j6 Z0 `7 _$ q& V/ N! T6 h% w5 L8 K2 _; ]
            for(int k=0; k < 256; k++)
% W( x1 A' S& I5 w6 M                dwDiskData[k] = wOutData[k];
7 ~2 e% @2 ~0 S8 \
8 U- |0 a; \0 M" v3 v6 |6 F( }            // 取系列号
; j% g2 q4 ^3 U: T8 c            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));! S" C3 W7 B* s/ e
            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
9 Q2 |, C. K! @: v' M2 @$ x
$ L# E: Z0 a$ C, l# C3 F4 r            // 取模型号
/ L4 h; @0 t6 Z7 v& m            ZeroMemory(szModelNumber, sizeof(szModelNumber));
' T+ E" H  s; P9 g3 a" i, `            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));: M( [; I! j, o1 I* s
' P7 u% G& g0 g' i
            pSerList->Add(szSerialNumber);
1 C2 o- [' s2 F* f( W            pModeList->Add(szModelNumber);
# k+ t; m% s2 e" @! b5 w        }
2 t8 Y& ^  y+ g% n+ Q8 t, T    }
" i9 H6 v: b; y) l    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);/ B$ j0 r) E% L2 j7 A. O2 y
}, w' d- \* ]1 i" p. F1 i
//---------------------------------------------------------------------------
7 {3 X3 K9 B5 ^4 d/ ^// 为防止不负责任的转载者,在此注明原出处信息,请见谅。
7 i( W$ [; O6 P2 M5 l// 资料收集整理:ccrun(老妖),欢迎光临C++Builder研究: http://www.ccrun.com
6 x: v# C7 Y6 K7 \/ j7 M( e7 W//---------------------------------------------------------------------------
2 ?0 s. B- W+ X' ~: t: {// ReadPhysicalDriveOnW9X_Ring0()6 O, i- o0 S; y' I. t4 g3 ^
//3 J8 L. B% @" a2 ]$ C
// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
# o& k% ~: k0 v6 \' S0 X1 g1 g// btMasterSlave = Master(0xA0) Or Slave(0xB0)  c0 O5 _! ]' x& @1 E: N  K
//---------------------------------------------------------------------------$ k# Y; I8 U* X) Q1 T
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,3 x+ s; O- N( T. Z8 L: y2 Z
        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)2 Q& Y; P5 m9 `) i5 w
{$ t  v* c) O: S8 d/ [2 Y2 \
    BYTE  btIDTR1[6];* s; V% ?# P2 n. T
    DWORD dwOldExceptionHook;
) P1 {6 e' C2 R/ K1 h% W$ ]    const int nHookExceptionNo = 5;( C4 F. q$ _7 s& ^6 @1 {' {
) `4 k% n5 y" ^9 x5 m2 a
    BYTE  btIsIDEExist = 0;  \* d& x9 l; J( i0 O& N
    BYTE  btIsDiskExist = 0;$ S0 K/ e0 G, Z3 R% O6 U3 }
    WORD  wOutDataBuf[256];7 [2 C0 n& E  F$ ^
: p" F/ _1 b5 X/ x! ^
    BYTE  btIsFirst = (BYTE)bIsFirst;
! y; X" F; z9 G( M; ^+ J' P- u! @/ F
4 u# d( J0 T  o3 v( @    const BYTE btBit00 = 0x01;$ ]: X" T4 U, I, A
    // const BYTE btBit02 = 0x04;
& p% I* c0 q, K    const BYTE btBit06 = 0x40;7 R& `# S; D! p; w* l
    const BYTE btBit07 = 0x80;
$ U0 N/ T% ^% v9 [+ K    // const BYTE btERR  = btBit00;4 G/ \! R9 T6 V6 N8 |
    const BYTE btBusy = btBit07;6 E. i* B1 p+ |5 `2 H3 \# M& _
    const BYTE btAtaCmd   = 0xEC;- V3 g# ?( A1 j+ W$ V/ H8 r
    const BYTE btAtapiCmd = 0xA1;
2 V3 R! P; r: Y6 T/ o% e7 A
. x' A% E" z! U- U# E    __asm
; n# e0 b7 E5 ]4 m4 L    {
. A: `# \* a  F  B! l- m7 s6 Q( p) b  q        // 必须先执行这条语句
- c. M0 K8 k4 L0 @8 w0 D+ S0 T        JMP EnterRing06 E, M0 @* ^+ }% c

2 b& V+ y4 y9 v7 T        // 定义过程6 _8 w- d5 @5 p0 L* {
        // 等待IDE设备直到其不为忙为止6 o8 N/ J+ t  x7 {* v1 d
        WaitWhileBusy proc: E0 h7 M4 \- \, x

! ?+ I" L0 U6 a9 ^# k" z* T7 {        MOV  EBX, 1000007 R6 C* x7 h! Z' q" L6 f7 ?+ U
        MOV  DX, dwBaseAddress' r8 I) ^6 I  D2 k
        ADD  DX, 7
( U9 P% P2 L* ~0 S! v/ D2 T% S
5 g, ]" t, y" h- f+ T" X& K) F) x        LoopWhileBusy:0 E3 J3 s: w, k8 R* S0 i
& i' e! z( V. s5 s. T  m
        DEC  EBX4 }7 i" x# {' v
        CMP  EBX, 0# `5 ]# L. j+ T, R
        JZ   Timeout
5 `5 ]5 g. Z7 e) h* N* `        in   AL, DX
  A) v) x+ t( [8 y6 G        TEST AL, btBusy
  C0 n. D2 e: B) Y0 m4 |        JNZ  LoopWhileBusy4 k4 q; W" p( a4 Q- R* C
        JMP  DriveReady
1 o4 t6 Z* C% u  T7 [# C; |9 n0 d1 c) }7 d
        // 超时,直接退出
' F# z$ B* P6 u; s" M. \' |: W        Timeout:0 {5 x7 n% |2 K( ~2 ?
        JMP  LeaveRing0+ x4 A0 A: X5 `7 v. c) ~* {
        DriveReady:1 \+ E; `- t* r& S  w4 @0 N
        RET8 Q0 h: b4 o$ a9 H0 b7 M% D
        ENDP   // End of WaitWhileBusy Procedure
5 e" v1 p- n1 K. M) n+ y4 R. C+ _
        // 设置主盘和从盘标志
' @2 n, A  J. N$ r# e4 e8 }& ]' F6 O        SelectDevice proc4 X/ v; i9 Z+ V' S; M- A% D0 B% d

5 g3 b! s1 y) X$ }8 A, V% L/ ]% M        MOV  DX, dwBaseAddress9 [. n  s" A. m1 Y7 \# s7 X. _. C
        ADD  DX, 64 n  C1 P3 [6 J& G) T, m
        MOV  AL, btMasterSlave; }+ u9 p% L8 \3 Z
( A  f# M! z9 X8 }( f
        out  DX, AL
3 e% e1 ?( Z, ]$ K) w" `        RET
( i2 J$ {" ~! b1 @5 R+ @
( t: o+ H: m3 X0 ~  c, ?        ENDP  // End of SelectDevice Procedure
9 B- n, R0 Z; f" Y( _$ i. Q
5 L' Y9 \1 Q  g' R# M7 D        // 向IDE设备发送存取指令, b  O% ?' `. R
        SendCmd proc( _* b% T9 l; X: \
- E, X2 i  m) D5 p
        MOV DX, dwBaseAddress
: B: N' {+ _7 |        ADD DX, 7
1 I! p& ?+ d, _6 F        MOV AL, BL // BL是主从盘标识,在过程外设置
8 @% ^& H8 o8 G        out DX, AL, ~4 y# r9 ]/ O0 s
        RET; K7 W! c" {. Q/ O1 F
        ENDP  // End of SendCmd Procedure
" C7 R* J* K& C4 R: [+ X, |; h2 \5 t% Q5 ^) M
        // Ring0代码
3 q8 z: X/ E- X" i        Ring0Proc:4 u5 q% G' r# M) ~- J* _" M/ M
        PUSHAD
) t8 l) Q( N, w        // 查询IDE设备是否存在. r$ Q( P3 b4 F" ]+ T1 `2 _
        MOV DX, dwBaseAddress' s  }, f. Q4 t' P
        ADD DX, 75 Z# a. c% \2 r! U. R
        in  AL,DX
8 ^4 a) J' u! f; t9 ^8 i' ^8 ^
- W/ ~; a4 _; Q- F        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回* S' ^; H4 c' p, Q. a: A
        CMP AL,0xFF
3 U5 k+ |2 r8 p6 G( `        JZ  LeaveRing0" S1 @' `( a: h- f. E  P# N
        CMP AL, 0x7F
. I6 ]: l) f: G: ]: E        JZ  LeaveRing0" H5 \0 a! i6 A+ [4 K- U: g) b

8 s- I* S; ?5 T3 E: J5 P+ K- E5 S* J        // 设置IDE设备存在标志. [$ L7 D# R, k; U. X: z
        MOV btIsIDEExist, 1: {+ m: ]8 q: V: [: M. Z+ u
0 M3 t, T/ E  l( X7 P, z, ?) \
        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)2 y1 U5 c( ~+ A6 }: L( `2 _" R
        CALL WaitWhileBusy
- B8 t7 E7 a* Q        CALL SelectDevice
- u) W! g: H- i" g7 m2 U- P1 o. H# E! S- {- y
        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏% x' V5 c  J- M5 [" X& C
        CMP  btIsFirst, 1
1 h; Q# d0 w7 H' d( J" Q        JZ   LeaveRing0
- Y" W0 r6 s7 a9 C% j7 w; p2 t9 W$ W: x% p# ~% ]9 @
        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???. U/ }% Q6 U5 c1 {! }( v
        CALL WaitWhileBusy
2 v  @1 ^8 [  d) A8 s9 X7 s. Y5 j8 g, I- L5 N" n$ w
        // AL的值等于cBit06时,不存在驱动器,直接返回
% X/ N3 J3 G, `7 d        TEST AL, btBit06
0 h  x& V* h# k4 p+ I2 G8 i6 K9 K        JZ   LeaveRing0  h% t- r7 ~6 }* P4 x' `
" Z1 A9 c. h' x! n; @
        // 设置驱动器存在标志+ L) T1 x1 l2 m. a3 s1 b8 ~. @: q1 I
        MOV  btIsDiskExist, 13 u! g1 l8 n: [5 `" y" {

$ g& m# v7 F5 a+ x9 r! I# Q        // 发送存取端口命令: b0 S7 a1 K. A: i4 S) |
        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
, {9 p- F! H5 b/ L; t( N        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令* X9 C& Y% v% s$ V
        CALL WaitWhileBusy. Y8 }# N7 y1 A& P& p8 d" d
        CALL SelectDevice    // 设置主从盘标识) X; R2 A/ O: m0 T$ N5 i+ m$ [
        MOV  BL, btAtaCmd      // 发送读取命令
- M: Z% `6 d& K, [& J        CALL SendCmd
/ P& x/ ^7 J; c+ Q        CALL WaitWhileBusy9 {1 F) N* R5 j/ Z2 A: r
! @2 R6 j+ J2 G! ?
        // 检查是否出错$ J; g0 {( k- {$ C2 {' T% K- J
        MOV  DX, dwBaseAddress
# b: }) t6 E4 R5 g- v  d* e        ADD  DX, 7
4 c% @) {6 N; d9 U& P2 F6 W! `( [% R8 l" \- r5 \2 J( f8 c) d
        in   AL, DX
" h9 S3 c" f9 q% p5 f
; V7 s4 ~# `+ I6 \        TEST AL, btBit00
5 u( B1 n3 n6 Z/ x$ N2 E& Y. ~        JZ   RetrieveInfo   // 没有错误时则读数据
; }0 [$ a: i0 N7 `8 A
& s  I/ O8 b1 o) z0 q        // 如果出错,则进一步尝试使用ATAPI设备命令- U3 Q0 N  ~4 |6 x+ u' L
        CALL WaitWhileBusy
& _5 w! G; J6 Q1 Y. v        CALL SelectDevice8 N0 W/ z3 }* f. j# M
        MOV  BL, btAtapiCmd% M* _" ^/ |2 I8 Q7 e9 i) r
        CALL SendCmd
, b# g# F9 x# K+ R7 k: B6 z4 r; p        CALL WaitWhileBusy
, k) `: `# \: T7 {' [/ S. t" k2 E4 ~4 r
3 A- n2 X6 ~. y4 n        // 检查是否还出错
, a0 h7 {& j+ D+ l! i        MOV  DX, dwBaseAddress
" T7 [) S' B( A: R        ADD  DX, 76 a( }( ?: D( W/ G/ ?
        in   AL, DX
) t' s( @  b  \" H        TEST AL, btBit00, H* h* a* w4 @# H( s
        JZ   RetrieveInfo   // 没有错误时则读数据
- z# S: \/ y  k3 K+ ?, R& C! @+ g        JMP  LeaveRing0     // 如果还是出错,直接返回- Q7 k( {6 Y1 P# U( J

* V6 v8 r" t- T, {2 j* u) L/ \1 Y        // 读取数据
% B+ E3 D: F3 {1 q* [2 k        RetrieveInfo:: q# y9 J4 L' M9 D) |

8 t9 G6 g7 }1 q: M; N' o  e        LEA  EDI, wOutDataBuf
/ W8 T/ P7 z' d$ @        MOV  ECX, 256/ O4 x2 ?/ o% M1 q! e2 W
        MOV  DX, dwBaseAddress
6 O) X1 n# E9 F+ O$ J) D7 _+ ^* F        CLD
0 H2 ]3 [$ L& Y4 S+ k$ y
4 ]% s9 |! J; z9 `        REP  INSW
. C# N& L8 g. D2 f6 z) W5 P  R# r
& R$ U6 a: b$ k* j8 o        // 退出Ring0代码/ n8 h8 L, K: I) P8 p1 E) N
        LeaveRing0:
& w: A/ [4 J* X  n& w# I$ Q1 T3 q5 Q- H
2 w* K0 ~1 ?6 k. l7 R2 E        POPAD
6 o5 \! |9 g6 C1 Q6 a3 d* ^0 _3 D        IRETD3 m9 O( M: f* H

1 H+ s9 E1 M- d1 e  Y/ S        // 激活Ring0代码8 Y9 L5 i2 k  B4 H0 C
        EnterRing0:8 m2 R# A2 \) s6 j1 W7 R

3 e" C. c: r7 ?2 |& e# R/ K! {1 D        // 修改中断门/ u* E; s1 b5 f' W1 @3 t
        SIDT FWORD PTR btIDTR1
7 ?+ l  T) z8 L' X; m9 e        MOV EAX, DWORD PTR btIDTR1 + 02h
* L8 Q& |  _( k: c$ s        ADD EAX, nHookExceptionNo * 08h + 04h
5 ~3 S* j- ?' y7 H5 K# ]+ T4 Z        CLI( F, }# ^' I) p4 T) B
& ?- E, f  R+ ~1 @1 l' T
        // 保存原异常处理例程入口/ i, h, n6 U1 d8 G
        MOV ECX, DWORD PTR [EAX]
3 W# L# l+ H0 s4 o: N* ~        MOV CX, WORD PTR [EAX-04h]7 c& |6 j1 v+ q. H
        MOV dwOldExceptionHook, ECX6 x) p& u; S: L4 Z# r1 x

8 M0 p- G' z" L6 }        // 指定新入口2 u4 }5 g6 d/ {& b4 ?6 i8 X
        LEA EBX, Ring0Proc
. I8 n; T6 ?8 f        MOV WORD PTR [EAX-04h],BX
- _* U# _  P+ x8 l) m        SHR EBX, 10h
+ J8 O3 s0 D/ R1 C        MOV WORD PTR[EAX+02h], BX
7 ^# l# z( ]! c! u4 z2 h7 |, F3 W/ w" K; {
        // 激活Ring0代码& ~3 a% ]  \3 F
        INT nHookExceptionNo1 j5 L, i3 l: u( m7 g/ d
* u4 t2 V6 x  s$ F  W
        // 复原入口
2 e8 f' D2 C0 O, f4 ~5 h/ w        MOV ECX,dwOldExceptionHook
. y( D: P# H, G' l        MOV WORD PTR[EAX-04h], CX6 j- G9 T5 Y. k7 L4 w) ^
        SHR ECX,10h
5 m+ s; G! r; h6 V7 L: u1 }6 g        MOV WORD PTR[EAX+02h], CX9 ?5 L; X- c* ~- k1 k& q
        STI- X' N' y$ G( z/ X8 `& I. i" n
    }# s$ R! z- G: A4 I$ h  C7 P8 e# S; m
    if(!bIsFirst)
. X7 w; H$ T2 ^! E+ h    {
  }1 c: C1 x3 l1 C        bIsIDEExist  = (bool)btIsIDEExist;& N6 O+ H- A' U
        bIsDiskExist = (bool)btIsDiskExist;
1 ?& J0 V' \( X$ c* w* S, s        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));  O4 @* e+ ?  d3 h
    }
! t5 f: w/ m+ ^0 e: {}
7 m: z' t, g+ Z2 }//---------------------------------------------------------------------------
7 H' u9 l. c/ s' N2 c/ O// 调用方法:
+ Y' {$ ?6 h1 z1 R3 qvoid __fastcall TForm1::Button1Click(TObject *Sender)
( J( i5 n$ B- D. ]{
8 C  I% _9 O" g3 {0 Q& y  e    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);) c% c+ A# v7 F
}1 P7 F: t# l4 l; O" N
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-11-14 14:45 , Processed in 0.019077 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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