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

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

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

  1. 5 [! P. U- u2 Q; f. N8 A4 r
  2. #include "StdAfx.h"
    - ^9 U5 t% X5 O2 ^
  3. #include ".\puiddisk.h"
    + i6 {2 S% f: S& [  ~! ]
  4. #define _WIN32_DCOM9 B4 b- K& O+ ?6 j% v  ^
  5. #include <iostream>/ y6 X/ Q! d% S* V- x! p" P  w, s
  6. using namespace std;8 m& w9 `* k$ s+ i/ I: f% Z
  7. #include <comdef.h>
    5 L' p9 n. c' \* A5 y! v; h
  8. #include <Wbemidl.h>5 f5 P# r" E% b1 {4 Q9 N
  9. 5 h( b. R0 h+ {& R4 \2 B: X
  10. # pragma comment(lib, "wbemuuid.lib")
    - w# q# ?8 Y( m) G; y
  11. CpuIDDisk::CpuIDDisk(void)
    / h- A' D2 ^; t* Q/ v. W' Y. H6 B
  12. {
    . m4 P1 K3 T. m+ r3 f9 ?4 D
  13.     GetInfomation();. A. P& K: ?2 ~. c1 C# _6 e# F
  14. }; `; a! Q/ i' `) r" b

  15. 8 U" F4 F- K5 U$ k% s0 H
  16. CpuIDDisk::~CpuIDDisk(void)
    7 @5 S, U3 g1 P1 F; r
  17. {( u7 {- k; f6 S+ I! E" x
  18. }1 ~. n' M( V; Y  t- ^( H
  19. int CpuIDDisk::GetInfomation(void)
    4 o# B5 H7 y7 R* w/ w
  20. {' ~+ }- L# Y3 i
  21.     HRESULT hres;
    * e$ ]' P, |) s; X; o, S
  22.     //步骤1:不是必须的,COM只须也只能初始化一次
    ! P% f% D, w) r& w  r4 a
  23.      hres =  CoInitializeEx(0, COINIT_MULTITHREADED );
    * d4 [' ?# \' D$ j
  24.     if (FAILED(hres))% Z. k2 j  @1 M+ I0 `
  25.     {
    " _6 Y; p. ~% Q6 B/ B/ d
  26.         return 1; //初始化COM异常:注意,COM只须也只能初始化一次* Z: L" H- T$ u5 N; w" Q9 q
  27.     }
    % O' N5 F* D$ v3 u) }
  28.     //步骤2:不是必须的,COM只须也只能设置一次5 ~7 D) K" x% z0 X4 c) b$ C' Z
  29.     //Set general COM security levels
    : E( l9 t# C+ Q4 U7 o# }
  30.     hres =  CoInitializeSecurity(/ W: P) S6 `' n2 y. K9 p5 I
  31.         NULL, , S4 g; @9 h9 ?7 F/ U
  32.         -1,                          // COM authentication9 o# a' T" B( ~, T
  33.         NULL,                        // Authentication services7 x/ p. Z3 ?' D5 ^" O, u1 A& A
  34.         NULL,                        // Reserved
    ! Y% m3 W9 C* m, [- d
  35.         RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication
    3 e1 e/ N" U( d% f+ I  x8 v# ^5 H; A
  36.         RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  
    ; l8 c. X2 M! Q* b% F
  37.         NULL,                        // Authentication info
    1 o% v: p; N6 g, ~; `
  38.         EOAC_NONE,                   // Additional capabilities
    + u* |3 H) L( P5 ]$ t0 I, r
  39.         NULL                         // Reserved! O! J2 [# |  v/ }8 x7 Q, s
  40.         );
    2 R9 n$ }- j. Y' L: _6 q" ^
  41.                      
    / E4 r% p, }; K$ g  P, W) J4 B+ m4 k
  42.     if (FAILED(hres))6 f6 [0 u6 L: R- ~1 f. e
  43.     {
    ; O/ H9 P6 }- F  Q  D
  44.         CoUninitialize();
    * M' D+ M- R5 a; i& I1 |
  45.         return 1;                    // Program has failed.1 E# ?1 F$ k0 u: R+ n+ M8 ^- D
  46.     }
    6 b. s, N; m/ M, o
  47.     " W; z/ R3 \. p
  48.     //以上不是必须的,若已有“::COMInit();”,则要跳过
    / ?4 R0 ]. z9 z% V/ ]! e0 ~
  49.     //步骤3: Obtain the initial locator to WMI
    : e2 D/ N+ K9 `, [: z% s
  50.     IWbemLocator *pLoc = NULL;
    1 O2 k# ?4 C% f3 _3 M$ l
  51.     hres = CoCreateInstance(! M1 O) \+ b; f1 S, H
  52.         CLSID_WbemLocator,             2 ^0 _' U1 S; R3 {5 _
  53.         0,
    & T( T: j. T5 T; ^7 ~. z: H
  54.         CLSCTX_INPROC_SERVER,   h7 O& M4 s) t1 q* W, h
  55.         IID_IWbemLocator, (LPVOID *) &pLoc);6 a/ c6 f" e$ N' R9 G6 U' ?; l

  56. " O# z  v# u% ]) C, K+ W
  57.     if (FAILED(hres))/ b2 P  v0 g: x& W- R+ X
  58.     {$ M$ v' v& ^& V  A5 L5 p
  59.         CoUninitialize();; ?' O3 F) d, \$ I- y
  60.         return 1;//Failed to create IWbemLocator object" R5 R5 I  D  }# S" t
  61.     }
    ! ^2 d. R- a' _; f

  62. & v# Z. Q5 E3 W* i& D; ?( y( \
  63.     //步骤4:Connect to WMI through the IWbemLocator::ConnectServer method
    / [9 V4 s; q$ i7 f/ ?. \/ l
  64.     IWbemServices *pSvc = NULL;
    ! j& v1 U% N! J* D# R. M( H
  65.     hres = pLoc->ConnectServer(
    ! F8 v5 j( ~4 s$ Q' S. V. S, b
  66.          _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace
    ( @. A3 @: a6 l  ?! }! J' s' X8 D% V
  67.          NULL,                    // User name. NULL = current user
    ! l( |+ Z2 h. q8 n7 K3 r5 Z
  68.          NULL,                    // User password. NULL = current' g( `4 v; i/ l+ y+ p8 B
  69.          0,                       // Locale. NULL indicates current
    ( [& e4 J$ d( c
  70.          NULL,                    // Security flags.
    ( d$ X9 Y6 U% g  J8 u' t
  71.          0,                       // Authority (e.g. Kerberos)
    . k& a& b5 @! y& @0 Z
  72.          0,                       // Context object * U; S1 p% T  D. t
  73.          &pSvc                    // pointer to IWbemServices proxy
    1 t, B; m, x5 O
  74.          );$ Z+ Z. ?% o6 C' }/ _
  75.    
    ( V* z5 |! s5 C+ L- h
  76.     if (FAILED(hres))
    0 f. u& m1 u2 Y) J
  77.     {( L+ m9 O3 I6 ^0 Q8 D7 b9 l
  78.         pLoc->Release();     % v$ \; c" x) s2 J
  79.         CoUninitialize();* Y* g1 s9 g6 `( F& k" X
  80.         return 1;                // Program has failed.1 W1 [2 O! n3 Q' v
  81.     }8 |' J, i$ G3 e8 Q; e
  82.     // 步骤5: Set security levels on the proxy
    # u% k! j3 R; R5 }
  83.     hres = CoSetProxyBlanket(8 F9 N7 E8 B6 T; X
  84.        pSvc,                        // Indicates the proxy to set
    + h( z8 i! S" {5 j( [
  85.        RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx0 v: F4 q# U4 c  R
  86.        RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx
    1 b, ^) }7 _1 p0 q
  87.        NULL,                        // Server principal name
    ! F5 x+ z) I. E3 v* i8 o$ x# y
  88.        RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx
    9 B. M9 D1 x8 S) ]
  89.        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx! ^  x' V( O$ P1 S5 }
  90.        NULL,                        // client identity
    . Q5 V1 N; Q  T) T  S4 c
  91.        EOAC_NONE                    // proxy capabilities
    , z3 _' J" Y8 b
  92.     );8 Y3 c5 g9 |' f5 L/ H" p: a6 h
  93. & \9 t1 P, l$ r0 J, [3 ]; j8 R4 D
  94.     if (FAILED(hres))3 O( C- R! q- s6 P2 t. S
  95.     {
    ( p* F( U4 D, ^2 R3 A" k- l# ^$ a" n
  96.         pSvc->Release();
    1 J2 Z. H4 U1 d8 v+ _$ P
  97.         pLoc->Release();     ) g: V" g$ m0 s
  98.         CoUninitialize();
    6 s( T3 O/ _8 |& z3 K7 l
  99.         return 1;
    + g8 ^' V' R) @7 V" f0 k
  100.     }
    1 \) |6 e6 H! S4 I$ u' u
  101. 8 S; I1 L' |3 U! @2 z+ p
  102.     // 步骤6:Use the IWbemServices pointer to make requests of WMI ----
    7 K4 L6 t2 H. C' U" M$ Z
  103.     IEnumWbemClassObject* pEnumerator = NULL;
    1 D( H/ ]5 G2 V2 m6 [% S+ h
  104.     //计算CPUID4 e1 |4 y0 n9 X# ^' h) p# M
  105.     hres = pSvc->ExecQuery(
    : L! Q: {6 G/ n. n
  106.         bstr_t("WQL"),
    ; {5 a) ~3 u+ l2 e; g7 r
  107.         bstr_t("SELECT * FROM Win32_Processor"),//Win32_OperatingSystem
    / c( G8 X2 a3 ^! R
  108.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
    * s/ p( u7 i3 h$ K. N, `- _
  109.         NULL,! w  ~: d* X$ i9 K* I4 q
  110.         &pEnumerator);5 o/ A" Y( j% e8 Q
  111.    
    . Y' L8 v( n0 B# X
  112.     if (FAILED(hres))
    : Q! n: R: R& x1 x: i
  113.     {
    - Y! g0 Z4 e: l) r
  114.         pSvc->Release();" n! z; b# W: s* G" J
  115.         pLoc->Release();2 S3 R4 k/ n: [' i  P* u0 r3 E% |+ B
  116.         CoUninitialize();
    $ h4 m2 C; Z6 J4 J; l1 F
  117.         return 1;3 d' Q3 B, c& z% U: s! j, J0 z
  118.     }" w! [0 ]8 g; O8 q2 l& C
  119.     // 步骤7:Get the data from the query ! s: E6 M8 D+ Q* Z$ F7 A& c- t/ f+ j
  120.     IWbemClassObject *pclsObj;5 Q% i- c2 d1 |8 V0 b
  121.     ULONG uReturn = 0;9 ?% E+ z) x! x, [/ X
  122.     while (pEnumerator)
    2 f" d% O& {8 s
  123.     {
    1 N) J4 }1 r. c- j
  124.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
    0 z9 u# t7 i! X
  125.             &pclsObj, &uReturn);
    1 j5 E  Z8 B+ W

  126. # H3 I  \& D& |5 t4 u% P# g
  127.         if(0 == uReturn)
    ! x7 s7 R- t, G$ S- ?+ [' E, C. n) L4 @
  128.         {
    * P& w4 i4 o6 |; ]* R
  129.             break;* A8 v8 K( U1 w- _- t% W1 w' T  I
  130.         }
    0 B4 i+ ]3 D4 n4 E" ~2 M' ^
  131.         VARIANT vtProp;
    + q5 M2 P- \9 v
  132.         VariantInit(&vtProp);
    1 w& f* e* Y' N4 S
  133.         hr = pclsObj->Get(L"ProcessorId", 0, &vtProp, 0, 0);2 C- e$ ^% q# [+ v: v# }7 h
  134.         strProcessID=_com_util::ConvertBSTRToString(vtProp.bstrVal);//strProcessID:类级变量* u# ^' W) Y& L% e* c. D. |* g
  135.     }
    $ l( h' x; r7 y  r. e  {

  136. 9 o; n! \( b" V, X4 z% B/ W
  137.     //计算硬盘系列号! m! g4 O; b! j2 ]
  138.     hres = pSvc->ExecQuery(4 _! E6 {( b- a4 X4 }
  139.         bstr_t("WQL"),
    : J( k* }$ ]- u8 w+ I+ C6 {
  140.         bstr_t("SELECT * FROM Win32_DiskDrive"),2 L- ^! O! I3 H0 B0 m2 v
  141.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, ; i/ ~$ \! H& ^+ \8 R, [7 F
  142.         NULL,( \" C/ g( ^1 s6 y$ h: X
  143.         &pEnumerator);/ Y* @; K' t! y  C
  144. 1 U; J8 w0 y/ b  D2 V
  145.     if (FAILED(hres))( a) K9 K8 y9 I. o+ T
  146.     {
    $ E8 g: e# ~0 ~; B5 a8 t6 t
  147.         pSvc->Release();7 C/ N$ ~; A: X. Y: f9 _
  148.         pLoc->Release();
    % b6 S4 g* {1 M. W4 d* R( @" D
  149.         CoUninitialize();& Z+ l, Z9 K/ M6 e
  150.         return 1; " Z7 g3 M$ D$ f  _( w. q
  151.     }
    1 v: ~9 |; l& p$ N2 @; n
  152.     while (pEnumerator)( l+ U3 a! ^1 R4 L: u9 _8 q5 x
  153.     {
    ) H. q$ R. Z4 K. U5 F, D% [
  154.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
    ; a9 ?3 }/ Y  N! N9 Z
  155.             &pclsObj, &uReturn);
    2 K& m' I' U6 U1 U
  156. : L4 c% ^: z& T
  157.         if(0 == uReturn)
    1 l* z' n; e% T
  158.         {9 o7 G  V% [: e/ e) Y+ v$ L5 w6 R
  159.             break;
    9 r; z( F+ ~. d$ G% q- g
  160.         }/ W9 f6 M( O0 N) ?3 a% j
  161.   m: a" I; z6 o0 D" h2 T
  162.         VARIANT vtProp;
    # `4 N9 N5 E/ m( U: K# l- P
  163.         VariantInit(&vtProp);
    ; T" H1 Y# a1 k+ X* X5 ?
  164.         hr = pclsObj->Get(L"PNPDeviceID", 0, &vtProp, 0, 0);
    0 o; L9 o  ]1 b+ L3 @: p5 j
  165.     strDisk=_com_util::ConvertBSTRToString(vtProp.bstrVal);6 t0 d. p8 K# C* C2 I' r+ V: I
  166.     }
    * P2 A$ h6 G& m5 I0 d1 o9 r, m* \7 x

  167. $ N3 M  A9 @% V4 i2 G2 j8 o
  168.     pSvc->Release();
    & k+ o6 r% h% U' l& o
  169.     pLoc->Release();1 B" r3 R3 f" S$ T( S. p9 t. B
  170.     pEnumerator->Release();
    ! [: [  J8 c# U6 ?' A
  171.     pclsObj->Release();
    2 L3 S; }; l; [, C1 Q0 i
  172.     CoUninitialize();
    . ]+ t  s( P9 S  m+ E$ x
  173. 4 x; ~6 s, J' e' T& A  E# e
  174.     return 0;   
    ! P8 O) L& t  _6 g) R9 ~
  175. }
    & x' `6 x2 Q4 c9 u
复制代码
 楼主| 发表于 2010-10-11 19:21:05 | 显示全部楼层
本文代码经ccrun(老妖)在Win2k下试验成功.' `& O4 T) m( P

8 k, t% s; y' j5 s" }9 U4 ]. D! x#include <WinIOCtl.h>8 S$ {$ d# U4 `8 {* }" g
#include <stdio.h>
$ S; M6 q1 T" W
! n" W4 T, l8 y; G; ^  s#pragma inline* f& A: v4 b+ d1 p6 G2 w
//---------------------------------------------------------------------------9 M6 Y( o% Q% {2 J& h* t0 r. P/ g
// IDE NT/2000/XP专用变量
5 x8 c+ y0 N7 N$ Z, \2 t#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
( y! }( p* x' K#define DFP_GET_VERSION         SMART_GET_VERSION
( b3 c- q: N, g) ?4 C- @& }#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND' }: C& I( Y: N. L0 H) W0 ^
#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA1 j+ |! O9 q6 {# S3 g! ]7 ~- y- ~: c
7 O* C. P0 i3 O- L
const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令. D( {& ^  J4 s
const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令" }% ?. N7 a% k$ G

2 z  z# w; x1 E0 Zconst int MAX_IDE_DRIVES = 4;7 `. a/ |0 r) \0 x  `( `0 O

* T, r2 l2 w0 @3 c. a) _! d& x/ I8 O* y8 w// SCSI专用变量' A! B. U/ [/ a% Y: F
const DWORD FILE_DEVICE_SCSI             = 0x0000001B;8 N: [( ]9 a! d7 H6 w
const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);, n3 J' c# Y, \8 r; z/ J/ o
const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition7 z) z' ]" `8 i3 E, i# q( {
const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;* i1 |5 J& |2 \* s2 Y3 f$ q3 }( ], N6 Q
5 x. T% Z: X9 }3 g  F
typedef struct _SRB_IO_CONTROL
- n3 y, B. W; x{3 V; s  D4 _9 X! [% ?+ o- }1 K
    ULONG HeaderLength;
+ S  Z& y% C- q1 K) B/ w. W0 S    UCHAR Signature[8];
$ x' i/ H8 b6 v& \  h    ULONG Timeout;
- l, U; z; v# }. U3 K- {* E    ULONG ControlCode;. g& R% I% ~5 S: C% {# }
    ULONG ReturnCode;
- e. f) v; E/ `" o2 i+ r    ULONG Length;5 Z  [& t3 F/ V5 `0 I6 q
}SRB_IO_CONTROL, *PSRB_IO_CONTROL;5 b2 X2 T/ `5 `  X

6 A5 R7 T7 e- K3 k// 读取的主函数1 I7 f: e0 e5 y+ M7 j1 @
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
, R; F! O7 ~6 g- _( [" V6 O+ w9 F- A. w( d
// 辅助函数0 W" W6 f+ e) w, D+ }. V7 G% n7 S
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);' q1 I+ [; K3 X: T
// NT/2000/XP函数
1 l7 T4 v+ V2 @void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
8 r- O- D8 X9 T, e4 K! ?' k1 ^bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,4 s- Z( W% I! r! j/ Q+ s( A) ?
        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
# c* m, `- E4 m# E  E& K        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
$ H; R! v' ?3 H4 W// Windows 9X函数
2 H3 c: r' N9 e; e0 R8 Qvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);1 l( P, h. q$ u
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,$ c& C8 K7 m2 Y
        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);) |" H7 ~/ J2 _' |2 H3 q

+ \/ o9 t* C" {5 I// SCSI读取函数(for NT/2000/XP)  x: e5 q' x2 D" k: o9 q
String __fastcall ReadIDEDriveAsScsiDriveOnNT();, }6 q! B% H) o& @4 {" x0 J& y
//---------------------------------------------------------------------------
1 |/ R4 x6 t5 W2 s  ?) `  e// ReadPhysicalDrive
% V; \% ~( f+ _* o; P" p, kvoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
* D* [3 F) I0 H{1 i6 \/ W. @2 }+ L% `0 H! w
    switch(Win32Platform)  e7 q/ _" O. F4 M* s; |9 I% q
    {
1 T% t: B0 ]& l' {! s  k        case VER_PLATFORM_WIN32_WINDOWS:
% U6 w5 q# }5 h0 s            ReadPhysicalDriveOnW9X(pSerList, pModeList);, x9 @" m( H$ Q$ i2 d7 Z
            break;
) \1 u- [1 c) O+ D2 A" _, s2 T        case VER_PLATFORM_WIN32_NT:4 M& m4 v1 L; e: ?$ ~
            ReadPhysicalDriveOnNT(pSerList, pModeList);( X. \3 p# ]( H$ W8 e# T
            break;! e. a- {4 W1 i) ]# }# h
        default:* @4 f1 n) ^( J: M
            break;
  c' |# [& _  _8 f8 q    }- ]( ?3 N8 S3 \
}
' [% n4 Z" N' D  U9 u  D2 T//---------------------------------------------------------------------------
0 N. b4 o" C5 n+ e* K; X! s( s0 N4 q// ConvertToString
' q' }% G4 ]& X* R1 M" Dchar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)' s7 D4 z7 s6 C
{! _5 Q  D8 ^1 X
    static char szResBuf[1024];" T- u9 W7 `5 e6 I" V: Z% j& G
    int nIndex = 0;
/ {/ l$ x8 T, N; U' i2 w    int nPosition = 0;" Y4 ^3 `6 f; \, R+ X3 ]
, y) V; I. D2 C- `0 p" o
    // Each integer has two characters stored in it backwards& v8 Z) m' ?' b4 D+ k+ Z5 G
    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
0 g* W! P/ }9 O* T    {$ I! e# h- N. V* L) ]6 Y0 k
        // Get high BYTE for 1st character
5 u" a( E/ I4 C# o  H) @        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);8 L6 j' L8 K- K" I6 r, u
        nPosition++;
/ z" l; p! R3 j4 @
6 l9 W. P6 g% V' L  c6 Q        // Get low BYTE for 2nd character! u4 g# f9 w1 D! N9 r5 G! K- Q
        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
5 ~  d  O3 \# B2 n& p2 e9 K$ U        nPosition++;5 P8 k: J8 l0 q7 c" K8 q
    }
5 s' {1 r4 Q3 ^, `/ J1 K; N$ F" {! C- h$ R( I2 m0 S5 `: i0 _
    // End the string! Z3 Y4 S0 I  W! \( [! m; e* U8 F
    szResBuf[nPosition] = '\0';
7 r2 b" m& y' l+ t( g- U2 H# f7 D+ Q! O4 R0 O" Y- B8 z
    // Cut off the trailing blanks
  `! T  m+ q0 A    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
' P7 P7 F7 Q- U! T' b% ]$ e# u        szResBuf[nIndex] = '\0';0 @; L) M1 {: }- L
1 ?/ s% F! [, X/ K5 {
    return szResBuf;
6 p' Y  e; E! M; y}: ^$ {1 y% A- j! q
//---------------------------------------------------------------------------
5 ?" n) u% |$ Z1 R; \// Winndows NT4/2000/XP 代码) ~! C( {: v/ J7 M; s
//---------------------------------------------------------------------------
  j; C/ _) M% u1 E3 p) n8 G- C( w& l// ReadPhysicalDriveOnNT4 v2 f" O! J4 s) V
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList). V6 U1 @2 B: }# `8 t
{
. }. l' I4 D2 X. r/ J    // 输出参数: J; x8 r: I* a  x) f
    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
# w3 B, b; ~4 Y& d( K2 k) i5 c, E2 f  @" y! Z( }
    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)* @7 ^  }3 Z, ?* j
    {
  V7 |: _" E0 L& M        HANDLE hPhysicalDriveIOCTL;" T: u% T# I0 H/ h& V- h+ a
        char szDriveName[32];, }9 x" T0 v8 m' N6 e+ w( d  F9 h
4 I' r7 w- j" F
        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
! `" D& p# n% ~: v; `+ ~& ~3 f        hPhysicalDriveIOCTL = CreateFile(szDriveName,( Y1 w: o- F- j8 t
                        GENERIC_READ | GENERIC_WRITE,
' @5 {& E) l: b2 a) Y6 Y, V9 ~                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL," J. P+ i5 |# a4 |# {
                        OPEN_EXISTING, 0, NULL);
5 c# I3 }. O% C& {* l2 A4 w
  P: T3 _* M) F, g, P' I        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)0 [, t' t2 W1 X: ?# A7 i& K$ r$ t0 ?
        {
% u5 H+ s# F+ E            DWORD dwBytesReturned = 0;1 m1 N( O! C6 U3 P" i) g2 @3 k
            GETVERSIONOUTPARAMS gvopVersionParams;
4 u# C+ S: H0 \4 U& H3 Y5 h5 w/ M3 o, {* D) q' {0 `, F
            // Get the version, etc of PhysicalDrive IOCTL* l5 F: M8 T: b1 ~' f1 `8 J% r
            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));- K+ k9 J8 D( @7 N/ y

: g# _1 P. Q- M            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,4 J; H2 t9 I& K3 p1 J* Q
                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
7 N  `1 U# ^+ a+ Y+ e/ G5 J                    &dwBytesReturned, NULL)), g# y1 d; ~# v- m& e% I$ |( e9 j
            {
7 R' `5 m" N2 A" Z4 N                continue;
! s- W* x# B# |3 h/ m7 j            }
& [- l  z* @* z1 e
* D* ?, w& F+ O: H; p            if(gvopVersionParams.bIDEDeviceMap > 0). F4 s  [5 E8 }+ s) k* _3 `! e
            {
( c9 {$ b5 B% f* g$ i                // IDE or ATAPI IDENTIFY cmd
8 i, X1 v, N( ~5 Q* k: X0 C$ K                BYTE btIDCmd = 0;
0 L# P  q, R& [+ P" |                SENDCMDINPARAMS InParams;
5 S" S$ T$ P2 d                // Now, get the ID sector for all IDE devices in the system.
! j* G5 r7 M' H" @+ I                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
+ I+ Y# }1 m/ |4 p* e# u5 ~# q7 M                // otherwise use the IDE_ATA_IDENTIFY command
7 b  B" S" v" H0 W; p  A/ I" L/ g                // 具体所得结果请参考头文件中的说明% [$ E) y$ w  ~. M$ ^
                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?/ I5 H' @- u# K. J' o! O+ z% N0 }
                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
4 ?- k2 I- |9 W2 E- `$ y                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
$ m$ P+ z& p, K                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
+ ^  }8 C+ l, I* p5 ]9 |* Y1 K9 I% W
                if(DoIdentify(hPhysicalDriveIOCTL,
* o6 S/ z! x& _$ a                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
# Y) y8 N* M9 S( ^/ @                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
/ U/ b4 p6 H1 g2 Q6 W* R  h4 z                {
( O: k5 F- Q& t9 P: e& W                    DWORD dwDiskData[256];
5 y$ y  q& S4 D, B- ^0 W                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件. S* m) ?8 W7 W: R5 K+ G1 N: D
                    char szSerialNumber[21];$ a; m2 t0 y. n. ]4 ^
                    char szModelNumber[41];% S1 E: R# g/ d9 G
5 {7 z/ e  L( T9 r/ T! x
                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
- H' W+ {; J% q) @# u                    for(int i=0; i < 256; i++)
' L. T5 J! t2 H; k' H. J                        dwDiskData[i] = pIDSector[i];2 I' ~7 C! ~7 M) d& ~7 m
                    // 取系列号
2 f, Z" J9 K4 J3 h9 d: \5 ^                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));1 h+ T, q+ K8 @" X$ q4 C" T
                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
6 f- s5 o- ~) u8 v: A& l$ q: {2 D4 e8 R; v( e
                    // 取模型号1 o, a  k& H/ i* R; J
                    ZeroMemory(szModelNumber, sizeof(szModelNumber));; S- _8 x$ Z" p$ n, d
                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));" W# f; k" F5 h9 j

* N, R; C* J$ z$ _& g                    pSerList->Add(szSerialNumber);
) c7 O% w$ s3 b, n3 |                    pModeList->Add(szModelNumber);2 F# c4 s: [! a
                }$ _" D$ b7 M+ x7 a- m$ W
            }
! i$ f" t, a% O4 [9 ], I: p( y- Q            CloseHandle (hPhysicalDriveIOCTL);
, Q, r* \- y2 n6 G1 X        }2 Q6 Q. E: e7 ?
    }
: H- N" v8 H# Z  [# h! K9 G1 @}
# d2 r4 t" E; A1 o$ G5 f6 V//---------------------------------------------------------------------------
& r  u( a0 Z5 w  b; c// DoIdentify
. j4 E( J$ f6 t! {bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,* A0 {+ k( M7 \! O% H
              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,9 r. w% u+ r/ D
              PDWORD pdwBytesReturned)9 N9 t  E/ b, a, K( P
{1 Z; t2 N8 S' c, W+ K2 [9 l$ b3 y
    // Set up data structures for IDENTIFY command.
' w0 g6 G3 k5 H) N3 N* d    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
$ c; @4 R0 B3 a1 K4 n3 M8 j, a+ C    pSCIP->irDriveRegs.bFeaturesReg = 0;
, @* d" m( P) c2 |    pSCIP->irDriveRegs.bSectorCountReg  = 1;
* k+ T2 p8 `) ]9 _    pSCIP->irDriveRegs.bSectorNumberReg = 1;
" q' |+ ]0 o: Q1 p" T- }    pSCIP->irDriveRegs.bCylLowReg  = 0;
- t: c! }5 c' p" V; C/ ~- d% |    pSCIP->irDriveRegs.bCylHighReg = 0;
8 i$ a+ m, ~) A* Z
+ _! ~8 E: ^7 E    // Compute the drive number.(主盘和从盘所对应的值是不一样的)
+ K% ~8 C1 l! J" d; y    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
9 z* |' q; N$ Q" j. d' @
8 Z! W- _$ n& ?) Z2 y    // The command can either be IDE identify or ATAPI identify.
% x$ u5 v" P* w+ P) C* _( J. C9 u# K    pSCIP->irDriveRegs.bCommandReg = btIDCmd;# {+ {5 I8 f- d1 e  s' h
    pSCIP->bDriveNumber = btDriveNum;
8 K2 \# D4 ]- u2 j' Y$ V2 e- ~" J    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
: ^! E0 x# ^7 u/ X' K& |0 i  `6 \! K: S6 l1 J% ]9 o
    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,0 U. c; W% w. A+ T* U% F
           (LPVOID)pSCIP,( D1 M3 o2 r8 g+ S; r* {9 _
           sizeof(SENDCMDINPARAMS) - 1,
! b" O0 |. D1 A+ I( q) l           (LPVOID)pSCOP,
) y- N# D  K. }9 b7 r3 S. Y& A           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,: Z$ F1 k* R* n; R1 t
           pdwBytesReturned, NULL);" g( S2 n2 v/ i: P) I0 R2 ]; ?* x
}
: F! s( D5 ?/ d4 n7 V( }//---------------------------------------------------------------------------6 C5 O+ h& W3 P: Z- y
// Windows 95/98/ME 代码
+ ~! g/ t5 K: V: `8 M7 H//---------------------------------------------------------------------------
3 D+ w$ F4 g. q1 ]$ G; u  Q// ReadPhysicalDriveOnW9X/ W( T2 w3 Y3 ~6 b0 d* ^1 P0 M
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)& ~" m* F/ V* j: R0 }
{
2 x$ G( [' }  i+ a; {# ^    WORD wOutData[256];
7 n. j* }' ^4 t    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
. J# c$ p2 @: T* u% a9 Y# ?& Y4 Y3 m: a7 ?. ~
    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。% [& j/ q/ w) X- M; ?6 J
    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以6 g3 W) Y* t4 r, p+ X
    // 避免蓝屏的出现。(期待高人能指出原因)
/ a. V+ E1 h" s- B- R8 p8 [    for(int nDrive = 0; nDrive < 8; nDrive++)( Y5 {; l/ G  Q: b/ p7 k
    {. g' c1 F0 A8 u: ~4 u
        WORD dwBaseAddress;( b; q7 M) z1 _0 q5 J% W8 {% u
        BYTE btMasterSlave;         // Master Or Slave  M1 ]2 \- l6 \
        bool bIsIDEExist;& [, J# m' m+ F$ ^9 X- Q/ G
        bool IsDiskExist;
/ p2 B& L( ?$ r5 K' |
. `0 j) _. s- Z8 N        switch(nDrive / 2)
% @2 [0 U4 o  z        {
; n5 \% _6 H/ A            case 0: dwBaseAddress = 0x01F0; break;
5 a! L8 v% T7 ?4 j            case 1: dwBaseAddress = 0x0170; break;
/ k1 _# r1 j6 L            case 2: dwBaseAddress = 0x01E8; break;
" w. O5 j8 Z  c( f: `            case 3: dwBaseAddress = 0x0168; break;
6 b" X! w3 x2 @" n' e4 Y% H& l( l% c4 I        }
; W. S/ o8 o& [( d$ B, D, r8 L$ p6 `7 Z
        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);% V# _9 h9 v9 F% V: U
2 _* |" N' l0 K- J
        // 进入Ring0
& k3 a; a; i# P8 L4 ^        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
& i6 z" H1 ^2 Q$ I                bIsIDEExist, IsDiskExist, wOutData);
5 B$ F( S% F+ s  _    }, D* J2 O: d& [1 F

2 W. {- H/ s$ g4 e7 Y9 V7 Q    // 开始读取
- W/ X0 [/ Q+ T' ?    for(int nDrive = 0; nDrive < 8; nDrive++)) M# L$ Z" C1 R
    {
; S5 b4 M: O3 B6 W9 E        WORD dwBaseAddress;
4 k2 C. [, C4 A; }8 Y1 G        BYTE btMasterSlave;         // Master Or Slave
$ G6 U  @, A2 [0 c        bool bIsIDEExist;
2 y# v% G2 n0 y4 j        bool bIsDiskExist;
6 ~$ V3 @1 e9 j. ]( k9 J. {/ y) @5 Y- A        switch(nDrive / 2)3 s; y6 f& A" b* R
        {
( L0 ~) @: P  ~( _2 S            case 0: dwBaseAddress = 0x01F0; break;' l+ N3 ]; e, d( C+ q8 {" |0 V2 P
            case 1: dwBaseAddress = 0x0170; break;
; }4 M, C$ X9 i2 U& A' y            case 2: dwBaseAddress = 0x01E8; break;2 f- Q* r$ i+ s. R8 O7 ?. Q# ?8 M
            case 3: dwBaseAddress = 0x0168; break;
! `# g2 q: v$ B3 p0 w* U& [* ~        }/ U7 W  Z4 E6 V
  J3 R2 I5 f5 G0 a0 T/ y, U
        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
  {, A3 h8 @. L' y3 u4 h0 V0 P
& G3 m8 q' b. K$ x. L! P! P+ m; B        // 进入Ring0
2 R! f9 w# M3 E( n5 u1 L/ {        bIsIDEExist  = false;3 N% G. ~! J6 ?# ^2 s0 k4 ?& c# u
        bIsDiskExist = false;) b# X; V  q" j1 i1 T( @. W1 I
        ZeroMemory(wOutData, sizeof(wOutData));
, `/ H! G' \& f6 J1 }4 U
  {; z6 o' C6 l        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
; y7 F" l& j/ t( [' ~  L                bIsIDEExist, bIsDiskExist, wOutData);
% F. E  U! G  H# Q* Z5 b* T
3 p. k, m. _9 S* }        if(bIsIDEExist && bIsDiskExist). c+ t* e2 ~+ r2 l1 [+ i
        {
5 r: U. R$ _6 k5 W# t% j2 u            DWORD dwDiskData[256];
9 f) H+ e; s* _5 i1 a) C            char  szSerialNumber[21];
' m, L5 H% Q) A5 G* {            char  szModelNumber[41];( H6 c5 e0 _! a& Z* p9 {4 d$ ^, ^- X" v

8 m, R! }+ J8 d' J1 b' F            for(int k=0; k < 256; k++)
4 K# W. C; M- i+ [: u# z6 p                dwDiskData[k] = wOutData[k];1 f# j3 s: k* s
4 k# o* P6 a/ E. B: {
            // 取系列号8 L3 C. c4 u+ V; C: p
            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
0 Q1 o6 x- }" ?; f            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));, x+ P& H4 w. Q# i
9 w8 a* g1 G- e- a5 }3 n; z
            // 取模型号
4 A5 i3 o6 F: s) l% C            ZeroMemory(szModelNumber, sizeof(szModelNumber));
: |2 ?5 |9 D/ q            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));6 F* z; q$ m: }! n/ k6 q

: ~  A# c1 m3 ?7 w1 |0 z- Y% t& w            pSerList->Add(szSerialNumber);  @# Z! j; Y2 Y& L7 T3 b8 t
            pModeList->Add(szModelNumber);
2 g+ i/ f% T! r$ C        }
' W; W0 }& \% J) Q: b, M5 ?5 g+ _    }+ o/ B0 \. D% s3 D5 _0 a. m0 Z: S
    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);! l+ o+ z6 e/ v' Z3 O
}
1 T  G$ L  c  y* X//---------------------------------------------------------------------------7 d6 ?; j1 O: T$ a1 x
// 为防止不负责任的转载者,在此注明原出处信息,请见谅。
2 k; }3 X& l: G: A// 资料收集整理:ccrun(老妖),欢迎光临C++Builder研究: http://www.ccrun.com
1 j; P: r# T. B# ~/ z//---------------------------------------------------------------------------. R# @" D2 D. \2 y7 z  K
// ReadPhysicalDriveOnW9X_Ring0(): L' \4 @! I' W$ U5 z7 Z
//
* H2 d  O$ m) T/ i+ l$ e7 a) g5 C// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h" a  n& H2 k7 @$ C8 D. l
// btMasterSlave = Master(0xA0) Or Slave(0xB0)
2 g2 H) l$ }! v7 F( M) x//---------------------------------------------------------------------------
  v( n2 F$ T, w9 zvoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
$ _9 o1 h0 u( v        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)! O8 x0 h! e3 ~# q$ X! J
{
: x* {. A4 j) V) T6 S    BYTE  btIDTR1[6];8 s3 c/ Y# N; T6 ?+ ]
    DWORD dwOldExceptionHook;
4 X) k) O* k* I3 u! X" Z    const int nHookExceptionNo = 5;
* @3 L; h' s3 m6 V' r2 ~+ Y
6 u; o8 y2 q5 Q# T" d0 Z7 A0 X    BYTE  btIsIDEExist = 0;
1 U+ g" x3 |7 A) s7 k    BYTE  btIsDiskExist = 0;4 n7 U$ G2 I+ D# T  V# u* C1 X
    WORD  wOutDataBuf[256];* R/ F( |& s% {( P

1 M5 e- y' B7 r! g- y* j/ {* R    BYTE  btIsFirst = (BYTE)bIsFirst;
; r, [# q& [% R/ \6 A: v# E8 D; \5 e
8 D$ W+ u" c* Y  m  ]; k    const BYTE btBit00 = 0x01;
5 R& r4 m7 s1 ]; ?    // const BYTE btBit02 = 0x04;
5 r) w( ]- t& F( G- O    const BYTE btBit06 = 0x40;
" a" k: O# c! W6 O    const BYTE btBit07 = 0x80;
6 }; }8 ]/ ]) o    // const BYTE btERR  = btBit00;$ D1 y3 v/ i, U! t2 m3 H* Y
    const BYTE btBusy = btBit07;
5 ]) |( ^4 U7 r; B    const BYTE btAtaCmd   = 0xEC;
( E: l( k: T/ c3 M& O    const BYTE btAtapiCmd = 0xA1;
/ Y& J) s- X: Z
7 p2 W6 v  t- a    __asm/ L; F, N( M! {5 o$ G
    {/ H# Y3 S4 r- y, @0 x
        // 必须先执行这条语句
9 {6 q0 \% C# ]% ?        JMP EnterRing0- O: K8 u" R% Y3 m" S! h
, t& g  J; W. V/ y2 H
        // 定义过程2 t' I; \* G; f  m5 y1 p
        // 等待IDE设备直到其不为忙为止
$ ^# ?/ T* ?, H        WaitWhileBusy proc; ~* i3 P  ?/ c* l9 o8 \% ~7 e. S
" U9 O9 M8 C  W
        MOV  EBX, 100000
) s  L) i: T- U* F* m        MOV  DX, dwBaseAddress7 B" R9 f2 l: n) z, H8 }
        ADD  DX, 7
7 V2 d5 B5 y; O7 j$ O# U9 {2 ?9 e
' g, H* a% [6 u5 d% N        LoopWhileBusy:3 G. p# _9 ^& r# k- h

1 f" B% s# o; Z4 X' I        DEC  EBX
& B+ C) C! G$ [& v9 Y/ y  ^) s        CMP  EBX, 0" y$ l) C' p  f7 P& |- }
        JZ   Timeout
, \; V" F2 D( a3 y, k1 C3 _        in   AL, DX
7 L) C- `  B. L! w( v5 c6 P( Y6 ^3 X        TEST AL, btBusy
- }4 l2 b& W" D5 ]" f        JNZ  LoopWhileBusy
. E8 S& Z& r! a5 n7 n        JMP  DriveReady
1 X% K; b8 Z% B; n$ N/ E' I
1 L3 M( ?4 c( _" Y. q        // 超时,直接退出
* N  p2 h1 [* Z+ p* m' N! t        Timeout:
$ f5 _( I) t3 e* p        JMP  LeaveRing0) r( z4 w: `9 X; l* E( A
        DriveReady:
. T: a* ?) i% n9 l0 o        RET. B: c6 f: I2 p; M# B: J! Y( v9 x0 c
        ENDP   // End of WaitWhileBusy Procedure' G7 r9 t  }" v' n9 R) l, H

  b8 R% Y% @2 I! N" ]" {0 _+ O8 s$ |$ E        // 设置主盘和从盘标志
6 u4 H; e- p5 N/ B- f        SelectDevice proc+ q, J) L' N6 ~, ~
$ l" H; |2 B7 z
        MOV  DX, dwBaseAddress0 Y/ f, o  _8 K, a- I5 I
        ADD  DX, 6. w; ^  H/ u  P+ i( d7 f) h
        MOV  AL, btMasterSlave
8 i8 N2 h* f0 }" ?- @
( x5 {5 u  x& [1 V5 B2 _& ]8 H# e        out  DX, AL2 s$ Y. \* c3 P0 ^5 o
        RET2 ~) F% S; s5 J! I1 U
# d5 L9 j# c0 E8 F+ p
        ENDP  // End of SelectDevice Procedure
7 A3 A8 d' C, e. G+ S$ z3 y: ?: |. {: |
        // 向IDE设备发送存取指令: k/ m" P! u* q, m% r- L+ ]9 @6 f
        SendCmd proc* H/ C9 C; c/ F$ R3 F

. l# _, T8 J" I) g        MOV DX, dwBaseAddress
/ o/ B6 q7 p9 r" k5 u- N8 F" ]        ADD DX, 7* l/ N4 ?6 I* r
        MOV AL, BL // BL是主从盘标识,在过程外设置: U* B! t' K! u, |- G% @+ d6 w/ j
        out DX, AL
- }' q+ a) y1 Y! F7 w8 `& y0 M        RET8 @+ g* U7 ]4 \& X; j
        ENDP  // End of SendCmd Procedure  ^# v! D# \" l6 A3 U5 }+ V1 {
% @0 O3 c" B* [) O4 j# K
        // Ring0代码
- A+ T# o- b& t; D" n+ _        Ring0Proc:
) Y/ W2 ?& M/ a" Y+ A" }( I/ n        PUSHAD
5 a; L# D+ q2 ~' u5 Z% g, R0 P        // 查询IDE设备是否存在9 C- _' T" ]1 B9 [' f3 H
        MOV DX, dwBaseAddress
6 Y5 J1 U$ [4 d+ c: U1 T        ADD DX, 76 g; j% i1 ^+ w) B! ~: s1 m
        in  AL,DX
- `) |, ?5 Y# u9 i7 v' q: R  E9 Q- ~# p( z
        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
0 i6 }5 H8 D7 f( G2 O        CMP AL,0xFF
" V1 p* M" U; }0 D# }3 X( Y2 I% Y9 T        JZ  LeaveRing0& z; M3 ^) j* O
        CMP AL, 0x7F
% Y2 x) V0 \1 z/ Z% E$ |& v        JZ  LeaveRing0# c8 R# ^+ B! o$ e

7 e2 f; N3 j# i) ~) s        // 设置IDE设备存在标志
3 L) x  ^: I3 ?4 O# p- s        MOV btIsIDEExist, 1# y% E' Q; a9 s$ c4 b
4 F; ^* i" A' S- t% V# @6 G' V3 o
        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
- t6 u. I9 y# r0 b        CALL WaitWhileBusy
& T! U8 P+ k) M* O. I4 q        CALL SelectDevice1 j6 }) c% Y" m8 J  V0 m. B9 K4 u/ y

# G* \. q' D/ q* K/ \0 V        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏* c+ n6 v$ W& a* `' N! h5 P6 y8 A
        CMP  btIsFirst, 1
4 ^- S0 ]! e; c        JZ   LeaveRing02 o" Z% ?; `$ E, E! T& a+ A, |: v/ x
! A1 C2 [& w& m; D0 W
        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
- U0 W% F$ m# J' @( R3 `9 z2 y        CALL WaitWhileBusy
, a% N8 ~' K3 A8 X2 J! Q2 Z2 p: B& ?  {* T% C1 ]
        // AL的值等于cBit06时,不存在驱动器,直接返回
  t; p' I- R: F( f4 j4 r3 q        TEST AL, btBit06
! T( |& S5 }8 Y& V! e' |5 P        JZ   LeaveRing0" j/ \3 @# f9 m- f2 A& J

% H' y1 I# b0 k$ j        // 设置驱动器存在标志
# u% g0 J2 P* k& v% _4 Z        MOV  btIsDiskExist, 1* L# A# }/ f  W. b; n
& h$ V( ?  b' Y, U
        // 发送存取端口命令
9 q6 b* X; s8 z1 Q3 p3 Q( X        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,3 m* }+ ?+ c/ L# M' O# a
        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
2 F% I1 l6 h& x* g7 o) \$ J: z+ j        CALL WaitWhileBusy
) E: e; O& n& u) y        CALL SelectDevice    // 设置主从盘标识9 f; {: ?- x1 c2 D$ U
        MOV  BL, btAtaCmd      // 发送读取命令4 b: ~/ d3 x& Q# F5 C  {
        CALL SendCmd6 I: I) |; J: \0 Z  F+ R2 I
        CALL WaitWhileBusy
, f" @0 m" Q( y3 b9 f# W- m% Q, r7 u& L' {8 n1 \
        // 检查是否出错+ @' x, b  E/ e9 T) a4 h
        MOV  DX, dwBaseAddress
$ \5 u- u+ S0 m9 I        ADD  DX, 7
, ?/ N. Z  h, ^/ c& E* c7 p: i, i( L( `( Q( O
        in   AL, DX
9 S  `; C0 ~, W) }" F/ C: |  l3 r8 O
        TEST AL, btBit00
( Z: ^7 |% p8 X2 a  `        JZ   RetrieveInfo   // 没有错误时则读数据
+ N3 {" z5 q6 i% x* S  r
1 K+ u* x3 O0 y( }, x6 W        // 如果出错,则进一步尝试使用ATAPI设备命令
6 @: g; r8 Y8 @( y5 h* l; u- r2 C/ Y        CALL WaitWhileBusy
! \3 J" A5 M" D& [% K) ^        CALL SelectDevice% W% g2 l/ d2 ]0 R- {0 i
        MOV  BL, btAtapiCmd4 F4 ?4 i4 N8 P# t. m: j) G
        CALL SendCmd7 z7 N: m& b1 Z# Q/ J# }
        CALL WaitWhileBusy$ r2 f, ]7 M  I( R$ l

- x9 @9 S% Q; ]# X8 D( X        // 检查是否还出错+ `0 [1 m% Z% x  c- o. L
        MOV  DX, dwBaseAddress* }' @- Q% ~9 I- C9 y% ~7 o
        ADD  DX, 7. s& b* @5 M) s- @# r5 D- ~
        in   AL, DX
) r  [5 S; w8 K9 i5 t7 q2 F        TEST AL, btBit00
6 S% E1 {! z/ Q; K3 @1 [9 E- |        JZ   RetrieveInfo   // 没有错误时则读数据
- w8 X; \4 h5 w# `        JMP  LeaveRing0     // 如果还是出错,直接返回! D% U6 s, r& p, v+ _: a
3 c2 [& _+ g. ^7 s6 p
        // 读取数据
2 O; n$ d4 b% D2 @! C5 i        RetrieveInfo:' y" p( r" K) m7 z. R# t

: @/ x9 h( f  O2 u; o        LEA  EDI, wOutDataBuf
/ F; s3 ]; V9 n3 \        MOV  ECX, 256; y0 @$ K: Z8 B
        MOV  DX, dwBaseAddress* \$ P$ e% V; ]7 u5 C
        CLD8 |+ c1 R1 x  w7 p
; u( ?; ?' W9 \2 V' ^
        REP  INSW4 s) T7 O) f! x# d% i
/ t5 _4 i: |3 T$ C
        // 退出Ring0代码
# r5 A! L7 g0 s1 N7 r        LeaveRing0:
& d0 W; }2 @& ~) ~2 W) p+ J
* n. I7 D% j1 U9 ^9 u" g        POPAD
8 C' e5 H# n6 i# n        IRETD
) \3 f. l( l7 G9 F) K. F! Q9 |+ `1 U8 L: [
        // 激活Ring0代码
, @/ f( k$ H# R1 X5 M        EnterRing0:
% ^8 J. h. @8 b, R7 G: r
: [' ?: d  l3 U' {        // 修改中断门
- Y" R& q: z" [3 g- @# ?6 ]+ x6 f        SIDT FWORD PTR btIDTR1
( U; N/ Z# q- v: K        MOV EAX, DWORD PTR btIDTR1 + 02h
! _' U( D- ?' q9 W% G* K        ADD EAX, nHookExceptionNo * 08h + 04h
, a6 U" C/ D% s, f" {& {( S6 i9 w* [        CLI4 p, O! y9 Z- ]7 U4 ?

5 E  \' ~7 W$ y6 B, _        // 保存原异常处理例程入口6 R$ B7 v- i0 j& ]
        MOV ECX, DWORD PTR [EAX]- [2 c- J+ Y/ Y9 A
        MOV CX, WORD PTR [EAX-04h]; j# ?% ~5 H# O$ L# N# B3 H
        MOV dwOldExceptionHook, ECX$ \" s9 L8 l3 f5 n

' R5 z5 |! j$ J% @2 {8 X        // 指定新入口
1 c% A8 b' X* ~6 Z        LEA EBX, Ring0Proc
" N" r" g" v/ w2 _! I8 O        MOV WORD PTR [EAX-04h],BX
( V9 d; D2 [! B. m; j; }$ u3 N        SHR EBX, 10h/ U8 T" y8 ?( w2 Y! M# L" Y5 {) p
        MOV WORD PTR[EAX+02h], BX
% m, g# a2 J/ a  T3 g
( K' M2 E) K- I6 M" O) X# i        // 激活Ring0代码
2 J' j8 e6 K9 L8 x. p, l3 K1 Z        INT nHookExceptionNo
. {; U! V/ E% S4 {
7 C( Y) q. n( _  g) a9 @8 Q        // 复原入口% v  _! J0 n! @! n6 f
        MOV ECX,dwOldExceptionHook- z" P/ A  U: e) \# F9 S& [
        MOV WORD PTR[EAX-04h], CX
0 {+ @8 R  h/ T+ s. q        SHR ECX,10h
3 c4 I$ ~+ D/ a        MOV WORD PTR[EAX+02h], CX; e* ?" o$ t+ Y& i: l' D4 E
        STI5 j2 x& h4 t! o' ?
    }
7 c! u' c' i$ G) W5 h& J  o8 f4 u8 o( e    if(!bIsFirst)
$ j& m* o) ~  ^+ [    {0 Z' `" x1 @" c2 m( r6 I6 B( x( ]7 z
        bIsIDEExist  = (bool)btIsIDEExist;
7 w9 O( e6 G% Q        bIsDiskExist = (bool)btIsDiskExist;
4 j$ m1 ~2 s1 W7 _6 F' p        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
% ~* A7 L# x% k! Q! n) H+ z$ T    }/ ^+ {& k2 u; J) M
}
5 L" C0 P- E" M% s9 ]//---------------------------------------------------------------------------
4 k+ F/ w5 ]7 ^2 }// 调用方法:
7 Q5 U3 u. r( Q" avoid __fastcall TForm1::Button1Click(TObject *Sender)
  a/ C- Q" T; J9 ?/ [& [( N{
& Q- q& F3 f$ ]    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);$ a3 X9 s- E# F6 C, A
}! o' V3 G% E3 Y9 p+ K
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-6-18 08:02 , Processed in 0.019773 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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