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

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

[复制链接]
发表于 2008-1-6 19:59:06 | 显示全部楼层 |阅读模式
代码框架,你所要做的仅是修改WQL语句,具体可看MSDN。以下代码为简介起见,一次返回所有的CPUID或硬盘厂商系列号
$ n" j% U0 D, S6 W: d
  1. 5 |' H8 c: k' k8 D  e# d3 n
  2. #include "StdAfx.h"
    ) ~2 C& U$ _/ b+ U/ C: B
  3. #include ".\puiddisk.h"1 R/ j+ ^! n) ?1 G& _
  4. #define _WIN32_DCOM
    $ ]  l! H/ N1 D* e
  5. #include <iostream># a1 u- _6 }$ \- Y) |. ]" Q
  6. using namespace std;
    * c) x  z. r! ]' x) [" L! v
  7. #include <comdef.h>
    ! I! D4 s2 h2 j9 _* o. g' ]& R
  8. #include <Wbemidl.h>6 k1 X4 W5 a8 g7 q
  9. * s* k( O9 w; S; r* x+ A0 Y
  10. # pragma comment(lib, "wbemuuid.lib")
    - z8 V' f" z+ Z7 [0 c/ Q3 h
  11. CpuIDDisk::CpuIDDisk(void)
    9 F$ e4 x# r8 A) \2 C4 `
  12. {$ T# T7 P# `2 B; V3 f9 v" U3 L1 s
  13.     GetInfomation();
    ; S- }" e  C3 N% i& V  t# \  J6 }8 p  _
  14. }
    , P7 c: t3 r- w6 F, r) S6 z

  15. 6 T1 M3 d1 ?% b# i  }. Q
  16. CpuIDDisk::~CpuIDDisk(void)
    ' m6 n9 \; m, @/ I
  17. {
    : `7 N) r. A& _9 `
  18. }
    & H' C0 I, ^  l, n) t; ~# m  N
  19. int CpuIDDisk::GetInfomation(void)
    " X$ L$ l. m7 b0 K5 _
  20. {, Q) _# L  o/ m& m1 g! N
  21.     HRESULT hres;7 T  c( V9 E; i, f' g: M6 O: F' a
  22.     //步骤1:不是必须的,COM只须也只能初始化一次
    4 t% ?+ r, v& x& x7 l
  23.      hres =  CoInitializeEx(0, COINIT_MULTITHREADED );! s. b3 z+ o$ g
  24.     if (FAILED(hres))
    - A2 i5 D( ~- g8 X
  25.     {
    % H. H$ b4 w3 y
  26.         return 1; //初始化COM异常:注意,COM只须也只能初始化一次
    ) D0 p8 ?  N( e: U- ^
  27.     }
    ( K0 M* z4 g) `3 A5 y
  28.     //步骤2:不是必须的,COM只须也只能设置一次/ \& Q- q1 ]0 `! ~7 I# }1 A) ?& I: Y: t
  29.     //Set general COM security levels# C$ T  j1 H# y+ f, y3 V4 X
  30.     hres =  CoInitializeSecurity(* D: i' l( ?+ S9 E2 C4 X- p
  31.         NULL,
    2 P- `+ U; K% }9 ~; w
  32.         -1,                          // COM authentication( d# D; r" {& x5 ~- |% J8 U
  33.         NULL,                        // Authentication services" _/ _0 |5 i: D) a, K+ s$ H5 X
  34.         NULL,                        // Reserved
    6 F6 d7 n& }' r% a& ~
  35.         RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication ) m. f& ~0 p7 C( |, d7 d
  36.         RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  ! l, D. b8 u2 X6 w7 ~
  37.         NULL,                        // Authentication info0 G  `" J, D4 s7 X4 O3 H7 _
  38.         EOAC_NONE,                   // Additional capabilities
    6 x& c& ~) r! X
  39.         NULL                         // Reserved
    " D( Y) x" b' [( j( ^$ O
  40.         );4 f% {7 k# ~' N5 {
  41.                      
    4 q- N& a7 N4 L1 D! y/ R! |
  42.     if (FAILED(hres))2 x2 E$ G* A3 E# d( ]8 t- d6 @
  43.     {+ [1 o. }  e4 ^0 P
  44.         CoUninitialize();
    # W" ]5 V; i  X) c5 q( O1 c
  45.         return 1;                    // Program has failed.
    5 @( D# P  H/ z
  46.     }
    ! |. r- \, C* k! j) n
  47.     : D6 I" S3 N2 S* A1 b
  48.     //以上不是必须的,若已有“::COMInit();”,则要跳过: {7 n* c/ S5 U4 [/ q* ^
  49.     //步骤3: Obtain the initial locator to WMI
    + p" d, u' c5 z" Y. r5 Z  q
  50.     IWbemLocator *pLoc = NULL;
    / J/ ~7 H6 \9 g  Z
  51.     hres = CoCreateInstance(# p3 \& s& j) Y9 _
  52.         CLSID_WbemLocator,            
    $ U8 Z! k# G5 O7 H% B
  53.         0, ( V/ f0 A( z* v: K( j. A
  54.         CLSCTX_INPROC_SERVER, ; O1 ]2 r. x( k! C# O# y. c/ [0 Y
  55.         IID_IWbemLocator, (LPVOID *) &pLoc);$ Z2 `+ a0 |( X7 ?. e
  56.   m' w5 A2 X/ z" k, i, t
  57.     if (FAILED(hres)): ^9 r9 y) J+ i) r- P( \  k2 j$ y
  58.     {- c& D9 D( @, p
  59.         CoUninitialize();+ A9 W7 Q' Q9 v# `+ J+ \. `
  60.         return 1;//Failed to create IWbemLocator object  p' y; Y8 c  S% K6 C
  61.     }& X" }. N: J8 W5 m0 l' z; r" C

  62. . Z/ t7 H6 l+ K. U' P4 d6 l
  63.     //步骤4:Connect to WMI through the IWbemLocator::ConnectServer method  C  Q& |  B9 q3 n9 z) O' a1 ^1 u
  64.     IWbemServices *pSvc = NULL;: L% x% x) }4 ^; V3 r
  65.     hres = pLoc->ConnectServer(
    : c8 j1 [8 m) A, W  y( ~% G
  66.          _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace
    . t  l. Q8 Y/ i( j* J
  67.          NULL,                    // User name. NULL = current user1 {- V7 \) i7 q; n; T3 I
  68.          NULL,                    // User password. NULL = current
    3 P* \) w; {" R( ]
  69.          0,                       // Locale. NULL indicates current
    0 e$ T. B' {4 o) N1 I
  70.          NULL,                    // Security flags.
    , D) D4 e3 v% G& P8 U( y2 k
  71.          0,                       // Authority (e.g. Kerberos)- q& P$ h5 c; Z, H
  72.          0,                       // Context object
    8 `+ |& O, D! |5 G: j
  73.          &pSvc                    // pointer to IWbemServices proxy$ x9 ~6 E, m: k  O* w+ p# S
  74.          );
    , `4 {2 x7 A& @4 G
  75.    
    : z; M: T* R# B) O1 m
  76.     if (FAILED(hres))
    % c1 D. q* L; d5 c* b  D, s4 {0 n2 |
  77.     {& o6 h+ Q( |/ U
  78.         pLoc->Release();     
    7 p. u- F; q* p  E  H
  79.         CoUninitialize();( g- P  P5 [' i$ x7 h
  80.         return 1;                // Program has failed.
    3 M' ^1 C8 P; E" K% C0 S( ]
  81.     }, V# g) s+ k* a% a( v, w! l
  82.     // 步骤5: Set security levels on the proxy
    7 N, @7 a; ?* j# M  T) K
  83.     hres = CoSetProxyBlanket(; R3 B6 M3 f( F
  84.        pSvc,                        // Indicates the proxy to set" |( j* \& l* y+ s9 S/ T+ H7 c9 x
  85.        RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx
    ) ?: |# f) U* A9 e
  86.        RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx9 v. k3 |: B/ c$ T1 i( T
  87.        NULL,                        // Server principal name 7 ]2 G' ]/ g+ X$ M/ A4 z6 L. B
  88.        RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx ; B9 s8 n  P/ v4 _9 w
  89.        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
    , F9 C. C' ?: g  n
  90.        NULL,                        // client identity
    ) u7 r( Z$ z3 t7 X2 k
  91.        EOAC_NONE                    // proxy capabilities % b, H/ ]( _  a! _9 Z) C( o- W
  92.     );  C& v" D) N/ r2 {- F2 P/ ~9 O

  93. . a/ n& z7 G; z# a0 `7 L  b  w# y
  94.     if (FAILED(hres))
    4 v& ~! V) c4 f0 w' b3 K
  95.     {
    7 y$ U* A) V! x2 S: T, U$ `5 F
  96.         pSvc->Release();& ~3 I6 E+ Z. Z9 n7 D3 y
  97.         pLoc->Release();     8 Y$ Q$ U4 F2 P- v0 S* X+ g5 s
  98.         CoUninitialize();
    0 h0 ~2 P7 g  Y2 |! q3 _
  99.         return 1; 2 K- }$ t& s* M
  100.     }
    0 t2 V( @! ^; g7 r& i# p

  101. ! G" N' J# k! _4 m  L1 \& @
  102.     // 步骤6:Use the IWbemServices pointer to make requests of WMI ----! L: E" B* k; }6 K& v9 {" d7 [3 @
  103.     IEnumWbemClassObject* pEnumerator = NULL;
    8 v1 k6 x. G" d& i6 [( d
  104.     //计算CPUID: V. x, B6 d, h2 T# b: Y: w8 o; c( ?
  105.     hres = pSvc->ExecQuery(
    0 t0 B& C4 L) f$ I0 v
  106.         bstr_t("WQL"), - E5 H4 D* g  c' _% {$ f7 `
  107.         bstr_t("SELECT * FROM Win32_Processor"),//Win32_OperatingSystem
    ! |/ L4 A$ V+ j
  108.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
    + z& n- W& {3 P. ?( M% B7 q
  109.         NULL,4 v/ E. A9 z; d& {
  110.         &pEnumerator);
    % u3 |1 H) R% f, |) p. j' [0 S, n
  111.     ( ]( @. c4 o+ m5 [% R
  112.     if (FAILED(hres))8 m% s  h8 `+ j2 M" n
  113.     {
    ( o4 Y/ k! }+ B* y
  114.         pSvc->Release();
    " U6 ^- Y: ?$ x. A4 i
  115.         pLoc->Release();
    $ g* Q% y5 f$ d; z8 l
  116.         CoUninitialize();
    ! `+ E4 X/ S! s, O" ]" M+ w4 d
  117.         return 1;4 ^* q$ W0 ]* n  ~$ `# c
  118.     }' }5 r, y+ P, o1 s8 E$ o" S. g
  119.     // 步骤7:Get the data from the query
    ' n; C: d1 M% ~* s+ S/ N3 r
  120.     IWbemClassObject *pclsObj;; u9 q$ a4 I; }. P  \
  121.     ULONG uReturn = 0;) `6 E% v# k. K, B" m
  122.     while (pEnumerator)
    ; D$ X1 Z5 A& l2 h, C$ W) m
  123.     {: [& @3 w8 C. P% o  @7 q
  124.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
      N( z# O0 {& e4 W
  125.             &pclsObj, &uReturn);
    8 t, A. J$ L, I. c
  126. : |/ i; n+ T; `& T
  127.         if(0 == uReturn)3 r. V% W2 ~6 d& {9 C1 {
  128.         {
    1 m7 Q5 m$ n6 ~5 d0 l7 ]( R( o2 V2 s2 o
  129.             break;/ P6 @- v. T+ v
  130.         }0 \, m& M# |  X3 J: ?1 [
  131.         VARIANT vtProp;
    / r& }3 C+ {5 B# {; M0 P4 E
  132.         VariantInit(&vtProp);
    1 J4 P( {9 |1 e3 h
  133.         hr = pclsObj->Get(L"ProcessorId", 0, &vtProp, 0, 0);6 p" k9 U( @# g7 h
  134.         strProcessID=_com_util::ConvertBSTRToString(vtProp.bstrVal);//strProcessID:类级变量
    9 Q# Q* m5 q" t  E. }0 l  b2 h
  135.     }
    8 T8 r7 w0 A% k' y. p. e

  136. 8 `3 C1 }# {* }, O0 H2 N
  137.     //计算硬盘系列号$ P$ {1 G+ F7 [) @; j2 l1 h5 ^
  138.     hres = pSvc->ExecQuery(* ^, ~9 ]0 R, z( x2 v8 L- @+ Z
  139.         bstr_t("WQL"), * e5 _6 _5 _; N# K$ A
  140.         bstr_t("SELECT * FROM Win32_DiskDrive"),0 ~7 f9 o  {3 [, M* F
  141.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 3 v2 _. i- T6 f8 t& b  P# N
  142.         NULL,. @9 S; b- t! i0 Q" l& I: Q, P
  143.         &pEnumerator);
    4 l, E. |7 d7 U/ w" ?4 |, D/ Q# G. X; Y
  144. / E: a3 R8 H+ P  I
  145.     if (FAILED(hres))1 V. d2 a, {( y  [& ]/ o
  146.     {
    6 c4 D: `6 v/ l  d/ A5 ^0 A
  147.         pSvc->Release();* [. @/ @( z$ u0 F6 Y
  148.         pLoc->Release();
    & m7 k4 v+ L4 h% a9 T/ b
  149.         CoUninitialize();9 `5 v6 ?% F3 w/ K8 j+ ~
  150.         return 1; # c8 C( E5 m0 p5 Y# K- k# h
  151.     }) R! i0 @) g% j2 B( f6 c
  152.     while (pEnumerator)3 g, e9 C2 G' g: M
  153.     {$ H9 k0 \5 [' f% Q& Z
  154.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
    + M* q( [- j; ^5 L
  155.             &pclsObj, &uReturn);
    " v, i+ I0 J/ E
  156. 7 y5 B1 U, d5 }& \4 g# J
  157.         if(0 == uReturn)0 L, h9 z4 G* f9 s" C5 b
  158.         {$ T& S6 n2 n  e6 y
  159.             break;
    # v% ]6 _- w3 q! r# B  g
  160.         }
    & ~! }9 }* ~) z8 L: E! ?, U
  161. 5 [# t6 e* h. ~5 |0 a
  162.         VARIANT vtProp;
    $ o+ I' L- j  a" C: P* v6 Y
  163.         VariantInit(&vtProp);0 c, C' U$ c- z5 @$ A
  164.         hr = pclsObj->Get(L"PNPDeviceID", 0, &vtProp, 0, 0);
    6 ^+ i) N- _  X
  165.     strDisk=_com_util::ConvertBSTRToString(vtProp.bstrVal);
    " R% K3 E% U* n, y2 h6 v1 ^
  166.     }
    5 `) r& Z) J. `- O
  167. : K8 H/ l3 Q" I* l; J
  168.     pSvc->Release();+ v1 L5 F( n- ^( E( N/ W
  169.     pLoc->Release();$ H( G' w) I6 d8 T. d" ]$ P. r
  170.     pEnumerator->Release();
    3 d0 ^, K/ I; {3 h3 v/ C- Q1 x% u
  171.     pclsObj->Release();
    , y' L4 V( M- P6 q6 m. P* A
  172.     CoUninitialize();: A+ g( Y0 q3 j6 `

  173. / n* M. v9 ~, j/ C8 {3 l* g
  174.     return 0;   
    + O! p- ~$ v* x. p
  175. }
    ) T: w* z: m7 ^$ R2 k
复制代码
 楼主| 发表于 2010-10-11 19:21:05 | 显示全部楼层
本文代码经ccrun(老妖)在Win2k下试验成功.9 O: K* m' h* Z& G7 q
1 W5 v' G3 ^4 N5 k4 y2 q3 G
#include <WinIOCtl.h>
0 y8 W! F4 @) h#include <stdio.h>
1 `6 ~2 ~* O1 Z: ]& b  F' b" }
* w: v- M, p- n. w2 t' p6 j" }* n0 C#pragma inline
3 \. ~. k6 F: g% X3 V& z//---------------------------------------------------------------------------) j; X, J5 Y* ?6 X; F
// IDE NT/2000/XP专用变量( `+ d! v' ~( f4 l
#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS0 _' d" U: f$ ]6 J3 K' {# a
#define DFP_GET_VERSION         SMART_GET_VERSION
/ z+ g' {5 I5 B/ K( E  W#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
, i% i$ O0 Q9 r' q& ~" X#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA! P; W+ l) i3 P
$ W* I6 {1 h* I( K- |/ J
const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令( H/ c2 a, t9 h/ K
const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令+ d& @6 l- H& G  h0 c4 U2 x4 e
) ]& n9 c! d# M. M* H: Z
const int MAX_IDE_DRIVES = 4;
' M3 R9 O! z9 `( ^/ |6 P4 I% c' `  j2 y6 c% v
// SCSI专用变量
* X  J8 l; v- s( d4 \4 |const DWORD FILE_DEVICE_SCSI             = 0x0000001B;
) \5 g! n1 E) `3 G' y! xconst DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);/ ]. K# O; `8 R
const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
" K2 O/ |- l7 E9 K2 O' Rconst DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;3 b0 M$ I) ^1 w0 z0 z6 y* J

  I7 f! O3 U0 z: S1 Stypedef struct _SRB_IO_CONTROL
# S# n1 S( f9 K{
$ t6 }0 K+ {- p* F& Q; q" S    ULONG HeaderLength;
/ O4 ?/ @, F" C5 E3 k    UCHAR Signature[8];! g9 p5 P2 P: P# K' T
    ULONG Timeout;, k: N8 L% a* _. p
    ULONG ControlCode;
' v2 d5 n  p4 c. w- t) Z0 R    ULONG ReturnCode;( @& v3 B6 ]7 q* B2 `
    ULONG Length;
: A1 J3 I& h  U: I+ d}SRB_IO_CONTROL, *PSRB_IO_CONTROL;
+ v% X4 f$ ~- J3 W1 i5 Y3 L; {* e# M! `$ I0 [+ p; y# ~5 b
// 读取的主函数$ A, k: O: X) s' M( X5 o
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);5 c( |  R+ z' R# i* D
' b  c* Q& ^8 u$ l+ `( |
// 辅助函数2 L( j& h  h9 W8 e9 |
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
; M2 h2 S% N- C; C// NT/2000/XP函数
9 b# Y/ Y7 k7 c, cvoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
( t5 a& F; Z& `bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,; R, u8 _0 e  V
        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
9 U; y) E* {" y/ m7 I        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
) K3 x( `' m% T9 L+ T6 z; J7 ?// Windows 9X函数- g+ S& P) S, H, M; T
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);
. A: N. w3 P( V* nvoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
9 f, n  k0 Q$ ?# {& S        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
* R6 {( l& Q: e0 \# J, O* F' ]5 o9 v. w8 }9 v8 ~1 n0 g7 F6 a
// SCSI读取函数(for NT/2000/XP)
( |$ C. f% X9 j8 \8 v5 iString __fastcall ReadIDEDriveAsScsiDriveOnNT();
) w) v5 Z) c' O% y7 C8 J+ j5 v$ y//---------------------------------------------------------------------------
. N3 t  F, \- U' q- g! Y7 e// ReadPhysicalDrive. w% @1 A% M+ ^! A
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
# y& H% T' N; k9 y5 r* u{7 D7 _" a) d4 T+ W5 i2 C% J6 x0 C
    switch(Win32Platform)
& u- X  ~9 n+ m- {  Y7 C    {2 P, h* E# {2 b' h) H& d( n
        case VER_PLATFORM_WIN32_WINDOWS:
3 P3 D4 K5 f! M' L' ]8 `6 m            ReadPhysicalDriveOnW9X(pSerList, pModeList);
& d( Y( v  \" w( B            break;+ d, \2 X5 H9 \/ h% D
        case VER_PLATFORM_WIN32_NT:
# {: M9 y7 Z, E# v            ReadPhysicalDriveOnNT(pSerList, pModeList);
+ {3 C' v9 K' \            break;; l4 P: q3 l: o
        default:) S, {) @' u0 J) Q, i; X
            break;
1 i8 L: \9 u2 i0 p. Y4 A6 K6 N    }$ G5 `3 e# C) {# b! U1 _
}! e( C( a9 p* C6 U
//---------------------------------------------------------------------------
5 H+ |" Y& W; Q6 |// ConvertToString* l/ [' @# W/ P0 ?2 c" B$ ~( o
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
& T) \! c6 ]& R" [; ~{$ e4 R3 Y* i! p3 c/ T0 O1 E( [, V5 s
    static char szResBuf[1024];6 E) F' V( u. y! i& p$ K$ ?
    int nIndex = 0;
! F4 u* v4 S) `9 n" `    int nPosition = 0;
3 E+ F/ Q4 x  h7 }) G- N: G/ E+ v" J. E( W) i4 u: h' c
    // Each integer has two characters stored in it backwards8 }; D. f; c  a* X
    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
% I/ U; e# D4 ^) ~    {
7 B  N. I6 c4 @, A5 l        // Get high BYTE for 1st character
8 L" I. ~) q. e* C0 `' V$ t        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
: j' a9 [4 P5 A5 t        nPosition++;
1 B* N. Q: g& t
2 B* f3 x$ L- ]. K& C" }0 K% l        // Get low BYTE for 2nd character
9 {2 m  Y3 ]; p* t5 ]- Q        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);% @1 Q& A/ A" n" S$ ~! R( a+ A
        nPosition++;
# J; T- O' h7 f+ h/ f: t! m2 ^    }
4 r. h. X6 J- f4 y2 R
7 b% P5 g; K/ s4 t    // End the string
, t) ~  t0 T( D& ]    szResBuf[nPosition] = '\0';3 q7 ~+ Y6 `# N/ U
9 u: ?8 r2 |- u8 K% q1 ^/ @0 c
    // Cut off the trailing blanks0 H) L4 R" M7 E3 H0 J
    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)* v' x4 _: T: H! T# @; x
        szResBuf[nIndex] = '\0';
0 F- `6 q3 o' ^: i& w
3 C! F+ J7 L; ~7 e/ W) a0 c    return szResBuf;
. g" b# c% E! V2 U9 ~}
& C1 g1 @, ~& R7 _9 P" I6 v% B' t/ B//---------------------------------------------------------------------------
3 G4 P2 E8 ]  ^// Winndows NT4/2000/XP 代码
. E5 M3 ~$ _/ w, U//---------------------------------------------------------------------------
6 |" K! h5 O  e8 j+ H4 j9 ~  z// ReadPhysicalDriveOnNT% F: c8 _4 R" n7 b% `
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
+ q. y  h) |" u3 p! m2 e; C9 z{4 k5 \  J; H# |
    // 输出参数, |- q1 w  M; }% @, m6 `2 R
    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];. Y% p3 [+ p5 l2 I! O( y

7 [* p$ F' r7 U* x0 m- e, N% o    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
; o. i! y. S. Q9 c) L* F) f    {! ?1 m8 U: D* X& l- D
        HANDLE hPhysicalDriveIOCTL;
$ N4 t6 t5 _* @# }        char szDriveName[32];
) c+ Q* P1 T9 p- M8 F
. H# d& q% t9 Y  K) c/ _        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
; S- I* D/ [( Y( `1 K+ a. J        hPhysicalDriveIOCTL = CreateFile(szDriveName,4 Y7 Q/ ?; N5 [+ k' C. X8 Y) f9 G
                        GENERIC_READ | GENERIC_WRITE,
* y! G; _, o7 O+ _" R                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,0 H8 H+ a5 }3 L9 F8 Z( t
                        OPEN_EXISTING, 0, NULL);. }3 Q1 k& E- R/ b# Q4 u
# o0 C: v$ O" M$ _! M/ D) W
        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
2 d9 {# A+ w  `2 y. e; J: g: G- W7 `+ z        {0 k$ G' I' T0 s" l; ^9 i" e% ]" b- {
            DWORD dwBytesReturned = 0;) E/ F* Y6 h+ i: V
            GETVERSIONOUTPARAMS gvopVersionParams;
! }0 a( e$ s6 o4 G# P$ d$ Y4 p% t/ p5 B9 h! L
            // Get the version, etc of PhysicalDrive IOCTL. b8 d1 m3 E3 F& p' U# E# e
            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));3 {' r9 ^* _" `

+ V+ J6 B/ k' |# L            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
9 g+ A* z% Z" Z( X                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
& V5 l  N1 x: P7 I  B3 l8 p                    &dwBytesReturned, NULL))
6 \. |, k( H6 G: ^            {/ k9 v6 S6 E7 N2 u& l) w
                continue;
$ G: o$ k/ Y# ?( |" t            }: Q7 H) i! o3 s$ k4 B" ~* _* M
8 {1 O) _3 k, y  P6 e
            if(gvopVersionParams.bIDEDeviceMap > 0)
% c1 T3 G: g; h            {7 l9 T2 l* G% ?% q$ Q8 \& I% m1 S: x
                // IDE or ATAPI IDENTIFY cmd& u8 f9 O- _4 H( v) V1 v5 @4 [1 \0 O
                BYTE btIDCmd = 0;
! H* T7 L+ f& T1 B. M: O9 q                SENDCMDINPARAMS InParams;8 z. v5 _* `5 T' U% e' ^, L
                // Now, get the ID sector for all IDE devices in the system.
% R4 B, Y" `8 D9 g! b: t4 L$ V                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
" J) D+ ^: W8 x. u2 I- B8 ]                // otherwise use the IDE_ATA_IDENTIFY command$ V% D6 _, w# k& ]# p+ c# d" e2 Y
                // 具体所得结果请参考头文件中的说明
5 s! k; I$ g0 q: |: c( F                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
9 |( z- N  \+ d, n3 Y                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
) z# k* y6 v) K+ @, E8 r                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
5 w! G* r  A9 w# ]                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));, p1 L/ q# `) p8 Z! V
7 A3 ~. X& x. C5 W+ C, y
                if(DoIdentify(hPhysicalDriveIOCTL," M- F+ v" b0 g2 I
                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,$ h/ U0 v8 M: p* `% R5 \6 C
                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
2 C+ t9 i. ?/ `1 Q& [1 t* w+ N  N9 `                {
* v& Q/ V+ _! c4 u' r" I( E" R                    DWORD dwDiskData[256];$ I( L4 b/ V$ D
                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
4 k5 m& g) b% m- N" R                    char szSerialNumber[21];  d- E% q3 H5 \* T
                    char szModelNumber[41];. R% [4 f! h4 p$ l; Y

+ X; N/ f6 K  i                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
% O: D+ m4 d% g  A8 A- c' M; S                    for(int i=0; i < 256; i++)
; v' U6 S, k/ O/ E2 c                        dwDiskData[i] = pIDSector[i];, [4 Z2 t. p; E4 ^, r" G1 k
                    // 取系列号* ?9 X' x) q! p* ~- x
                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));) Z! J; N6 |  n+ P# s( ^
                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));  z% _+ e8 O* G  F. }) g

+ n( q' Y" |0 b% G! }                    // 取模型号! ~( Z9 s% N; G: w
                    ZeroMemory(szModelNumber, sizeof(szModelNumber));
  Q) E' g1 M) g, ^2 H; y' o3 ]                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));$ d' y9 M  k: f* j

9 H+ @6 F, d! q1 D                    pSerList->Add(szSerialNumber);
1 Y/ y2 W4 o' `4 B/ D                    pModeList->Add(szModelNumber);
* V  `) M7 f; g                }
- {" J2 r0 I, [% R0 B& M5 ^            }
5 f* h0 F1 A9 w' k. d$ C' E2 \            CloseHandle (hPhysicalDriveIOCTL);" [" o. c: `0 b
        }
4 s8 z. a: }! Q! [( ]8 {' x    }4 A) o/ i( [% _# C2 K
}) ]2 S& j$ g. N; k( Z+ n- n
//---------------------------------------------------------------------------& H: B2 L2 n( S* H4 A& \
// DoIdentify
8 M7 F( v$ Z, q% u0 Y0 W6 P: Lbool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
. N2 A* l$ b: r# o" k# Z              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
9 |6 C" G; J* P& z/ v7 i# g: E              PDWORD pdwBytesReturned)' i7 L9 K$ g3 g3 e6 z
{
' b# o- J" o5 u. V! m9 u& k    // Set up data structures for IDENTIFY command." L7 q3 G+ Q" B' _$ D: \
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
. ]1 Q1 c. a( _8 u7 A    pSCIP->irDriveRegs.bFeaturesReg = 0;
9 B! C+ C1 n. s- u$ j    pSCIP->irDriveRegs.bSectorCountReg  = 1;
  w/ r8 W7 B# ^    pSCIP->irDriveRegs.bSectorNumberReg = 1;7 p, v7 |9 r& F9 Z3 r3 H
    pSCIP->irDriveRegs.bCylLowReg  = 0;) h8 \. ?  A2 [
    pSCIP->irDriveRegs.bCylHighReg = 0;; p2 L5 ~6 ~" t) B1 r' R

  E/ c. t9 V( l! F* d' O+ J2 G    // Compute the drive number.(主盘和从盘所对应的值是不一样的)
7 U4 _/ t" d2 y) w    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
$ M" e+ R! i. e# T
% H* l, L/ b1 k9 v% P) v    // The command can either be IDE identify or ATAPI identify.
6 i1 e1 P" R: s& ?    pSCIP->irDriveRegs.bCommandReg = btIDCmd;& i) [. [' p/ v; ?
    pSCIP->bDriveNumber = btDriveNum;4 ~+ t( _  E+ R2 X
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
3 p  B* b& i! G% E8 A/ @5 H6 Y- n/ f4 t3 ~( B5 |0 m: u8 L: Q( `
    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,4 i% E+ [6 r) g' S
           (LPVOID)pSCIP,: @1 G- |$ [$ u' N3 Y; v
           sizeof(SENDCMDINPARAMS) - 1," ^8 x) ?  T: {2 _
           (LPVOID)pSCOP,
( z  V3 z. {9 q& ?: _1 y( f' _           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
4 b; T7 C$ H6 }3 b. ?           pdwBytesReturned, NULL);
7 B8 D1 [  o/ W  b" {}2 E; T9 ~5 M2 E$ Q2 B
//---------------------------------------------------------------------------
9 y2 W  H# c. I# b* G1 ?) ?// Windows 95/98/ME 代码
* C, D2 m: F7 P- e# O0 e' D//---------------------------------------------------------------------------. ^3 f1 r  ~$ X* c: g: V
// ReadPhysicalDriveOnW9X
/ t! u+ U" F: n7 k. @# V3 Jvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)! A* U* J5 t! g9 [( i# S% X9 [
{
5 h0 k+ p; v0 \( y9 d' l0 L    WORD wOutData[256];8 D: O" H+ Q, o% y& _
    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);4 b' R6 L% E2 P: o

3 g9 l4 @. e" {# z3 N    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
. v; p  a+ ]' e    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
' ]' P# E: [" g5 Y    // 避免蓝屏的出现。(期待高人能指出原因)
% e6 n; ~# e! n7 a) n9 x    for(int nDrive = 0; nDrive < 8; nDrive++)
* I5 n# l# B8 ~    {
6 C8 ~. c3 W# [9 J7 y        WORD dwBaseAddress;& Z6 x! p/ }, X( T7 o4 n( J* B
        BYTE btMasterSlave;         // Master Or Slave8 F0 ^/ M" i2 p" A, j/ D+ K$ l6 [
        bool bIsIDEExist;
% X3 z, K! O" ?        bool IsDiskExist;
% q4 Y" l! o! z* e" X! C
/ ~! x" d3 q1 s5 Q" c6 o! M% `3 L        switch(nDrive / 2)
6 a# x0 f5 `+ i3 R9 W, {        {
7 W6 X% i# X1 X) \4 d. Q            case 0: dwBaseAddress = 0x01F0; break;1 y, B  N. Y) |
            case 1: dwBaseAddress = 0x0170; break;
. u, {' v- m2 [# u7 @- g* x& l. V+ R4 [            case 2: dwBaseAddress = 0x01E8; break;8 @/ a" M' C7 H: C/ v) f+ [
            case 3: dwBaseAddress = 0x0168; break;
, R1 G0 C1 ]$ ~* ?1 I; X! c        }
$ C0 w9 W' H7 y/ x% o+ `8 H' n  R) F( x% a7 Z8 t: z
        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
# Z: ]) m( \; O  u2 o
/ V2 w: H' c' u4 m        // 进入Ring0- z& B' k. {* ]5 A* f( Y
        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
6 T- [; B' g# t( h) E' z  ^* P                bIsIDEExist, IsDiskExist, wOutData);9 H, |  ?3 U$ j1 G
    }
' F' \$ }, A; j$ y3 y$ K* ?  E: v0 W: K  v1 j% V$ D
    // 开始读取
; z3 m7 A/ f3 c, h' w    for(int nDrive = 0; nDrive < 8; nDrive++)( @5 M9 h3 Y) k1 d
    {
$ s; l! _' E$ E0 I        WORD dwBaseAddress;9 m: d& b& H; m/ v
        BYTE btMasterSlave;         // Master Or Slave
. n' E# ?1 G9 z5 Y9 T- q7 J        bool bIsIDEExist;( g/ B& M( b! H7 c
        bool bIsDiskExist;
# t' f# o3 n$ Z! u5 ~- j        switch(nDrive / 2); n  m0 \% n! P% f! p
        {
) A) i6 V/ a9 {; F9 g            case 0: dwBaseAddress = 0x01F0; break;
) \3 ^# @& t$ [; G/ G) p6 h, a            case 1: dwBaseAddress = 0x0170; break;/ Y2 G6 \, l! Y) ]$ r# H2 ^8 k
            case 2: dwBaseAddress = 0x01E8; break;( h2 T/ U1 ?$ D/ n
            case 3: dwBaseAddress = 0x0168; break;! _+ R* g9 Z4 F/ w) R
        }& {2 d2 c5 w; ~5 A
8 ^$ J8 T, |+ ?, o
        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
2 D+ r/ P: m- |$ c. [8 p( ], p" _  j  p& s) m% A7 S% V9 F
        // 进入Ring0& n4 B% D$ W& U" g; o$ G$ q
        bIsIDEExist  = false;. E( F  ]! Q  p- f9 _6 I
        bIsDiskExist = false;
& s" V5 |" |7 S# M/ s1 I$ @5 u        ZeroMemory(wOutData, sizeof(wOutData));& c8 e- V8 m+ c0 Y2 o+ f

! U$ [3 u7 A' n7 q2 ~7 \        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
- G) F! i) b) h                bIsIDEExist, bIsDiskExist, wOutData);
% a6 o7 \$ B- k! P; V. L2 d5 V4 c5 S- x1 n7 i: k
        if(bIsIDEExist && bIsDiskExist)
- r3 I2 H  _9 I9 X        {1 o( N6 p& D5 \" M( K  A7 V, o
            DWORD dwDiskData[256];4 y6 A4 t  }8 P  d8 T# T9 }
            char  szSerialNumber[21];' M$ I' R0 E1 W7 `/ G  o3 J  {
            char  szModelNumber[41];
! l. G& X+ o' Q+ r7 m
5 V! d$ Y4 @0 B; u: }+ Q            for(int k=0; k < 256; k++)% h; W/ S* I; W1 a: B: l
                dwDiskData[k] = wOutData[k];
* ]5 T1 b) w: E1 l* x) k& [& K- r( N  l' Y
            // 取系列号
, \/ F( z, V8 P7 V9 n0 L  O) q( _& E            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));- S9 G5 f9 A- f
            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));% b- R% u2 A3 l% ?$ B7 o

3 Q' m5 A, x% i9 f) A            // 取模型号
7 Z/ e6 Y% l+ p4 B+ P& \; P- r8 s            ZeroMemory(szModelNumber, sizeof(szModelNumber));. |% a$ S! R1 k$ A" f8 F
            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));( @6 l* O. ?4 u& }" O- D5 |
- u. t' \) \$ h& G# [  x) @
            pSerList->Add(szSerialNumber);
' A2 u$ E; g6 h8 x6 c            pModeList->Add(szModelNumber);0 a/ b2 f/ Y% \5 F) J1 S) Y
        }- M( I9 V% h0 d6 x; n/ F
    }. @1 j6 J  c" a; Z
    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
7 G+ `4 k! K% u" B$ U}
% V% j! f* k/ N8 A  Z1 \//---------------------------------------------------------------------------/ V* }9 r0 r7 d/ ^, g
// 为防止不负责任的转载者,在此注明原出处信息,请见谅。; Z  `- w$ S5 E. g* G3 B3 Y
// 资料收集整理:ccrun(老妖),欢迎光临C++Builder研究: http://www.ccrun.com( e) x% K$ c0 G; d7 s% L
//---------------------------------------------------------------------------
2 v/ T% M2 _1 k( J! K* W7 V// ReadPhysicalDriveOnW9X_Ring0(): `1 i# b: U9 [  t9 P8 p
//" Z7 y$ h" ~5 V
// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
3 O" l  v4 S6 N! i2 I# ~! L6 x// btMasterSlave = Master(0xA0) Or Slave(0xB0)
: Z- U# r+ _& j//---------------------------------------------------------------------------
; O1 Q7 O7 o3 I4 E& ovoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
, h* F8 P; s( I* ^, B# O        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)8 y  ^# S! S7 w
{4 j/ u: d7 G+ k. \8 g" k' @7 s, o- `- w
    BYTE  btIDTR1[6];
1 R8 c! U, a  N& L/ ?0 ^    DWORD dwOldExceptionHook;# a- H- ^- X8 s! E+ _
    const int nHookExceptionNo = 5;! {0 F( O9 s$ o# T. O
* v! f$ H: H( Y
    BYTE  btIsIDEExist = 0;3 m5 a: ^* K8 f/ J; i: T! s+ R  X3 C
    BYTE  btIsDiskExist = 0;
/ y4 s- v# S, s! E( P    WORD  wOutDataBuf[256];  c+ U& U: Z: m6 a7 u
+ N/ i* r% A4 G3 S. f
    BYTE  btIsFirst = (BYTE)bIsFirst;" S' t2 q0 u6 E; D

" f8 O* {/ f* j    const BYTE btBit00 = 0x01;7 u7 c3 X: S& q
    // const BYTE btBit02 = 0x04;" c2 ^$ z9 K3 O, ?8 z, S; K# e
    const BYTE btBit06 = 0x40;1 @7 Q% m" x) @+ E  o) q
    const BYTE btBit07 = 0x80;) n5 Y; J6 c( n( {0 Q/ B
    // const BYTE btERR  = btBit00;3 W( A3 I1 a' W) H& v
    const BYTE btBusy = btBit07;0 U; x) D6 Z1 G$ V
    const BYTE btAtaCmd   = 0xEC;# b/ @/ I& n, ]4 K! H$ p3 C+ i% g5 J
    const BYTE btAtapiCmd = 0xA1;
3 f, ^# j% J1 h$ B8 Z
5 L- Q  R) z  l6 [# l8 J' U    __asm
' w# b2 K# v0 ~1 q9 ~# E    {- c' s8 q- O3 H3 x' U( j% f
        // 必须先执行这条语句
( i# ?, t" g# t4 I1 |$ [        JMP EnterRing0
) X1 d/ M7 J2 G" V' P! |& l7 j, H) i" i) v9 J" R
        // 定义过程, J2 k* F$ K5 o* m. I" t5 U
        // 等待IDE设备直到其不为忙为止2 j0 k7 n  d' S6 ^
        WaitWhileBusy proc2 P5 c! _8 p" a. {/ W3 K5 @

! f5 B% u# h1 l$ H! E- x        MOV  EBX, 100000: i7 {; h$ b  \, J& }; B, R
        MOV  DX, dwBaseAddress. e. l9 s9 A0 u4 N8 w9 X: o
        ADD  DX, 7
+ b, [5 d+ B7 M: L/ y4 H$ h
! x, w' D( Y& r$ q  X1 Q        LoopWhileBusy:0 F- ?& i/ E, h5 @2 x1 D, {3 l
* `( j4 `# f, Z6 z; W+ L, Q  P
        DEC  EBX7 O+ e/ Q- W" ?) `
        CMP  EBX, 00 ~6 V" M. ], ?/ p; X) k
        JZ   Timeout1 T+ I, S8 [3 m) x/ A
        in   AL, DX$ D! m# [) U) z
        TEST AL, btBusy# x) q' r# U  I! m
        JNZ  LoopWhileBusy
2 M, ]& o. J7 k6 Q, C        JMP  DriveReady! R; p) |* O+ M2 j

9 @! Z/ v" S" E; h6 ~; }$ v+ Y        // 超时,直接退出
- w! u! |$ R8 P6 T        Timeout:. ~3 W  f; k5 ]0 E0 `
        JMP  LeaveRing0; @5 }  r! w6 B8 [
        DriveReady:# O9 I( y& Y) Y& p( h' a
        RET9 C3 C6 a1 t# c  S/ m$ L
        ENDP   // End of WaitWhileBusy Procedure
2 q- {7 Q  X, ^# Z  X8 Y4 x8 t& H
) s4 d% ^5 `4 R9 i4 d; D( @8 V        // 设置主盘和从盘标志9 Z' n3 }& @2 M4 M
        SelectDevice proc' n0 B$ C' V( {* g  @* |
& |& F5 f' [3 w' E" G
        MOV  DX, dwBaseAddress: ]# x" U2 [# b) Z9 t5 B+ m; ?; x
        ADD  DX, 6
! m8 Z! f/ J8 a! k$ W$ r- D) L        MOV  AL, btMasterSlave
$ c) d, t; q- N; c) \  a* v* R7 p; B$ K! y' M
        out  DX, AL- w& P0 T% I( j$ t0 d( b
        RET2 B. K% o0 c" X! C
) Q2 }3 }$ H* Z7 C
        ENDP  // End of SelectDevice Procedure
% i6 R. M$ `  w; q- o4 R& O9 @! _* Z  ~1 A* I7 ]3 n
        // 向IDE设备发送存取指令1 p- G$ b& I7 F8 t0 q
        SendCmd proc  M1 w6 x) Q- Z& i
% C! t0 Q* l9 [; G# c
        MOV DX, dwBaseAddress2 q$ ^; g* ]4 E: ^) r
        ADD DX, 7/ o& v8 j# \3 K0 j
        MOV AL, BL // BL是主从盘标识,在过程外设置
% H6 c; P- M3 R        out DX, AL) D- v2 Z/ ]& p7 s) u' K& y
        RET
. O2 q9 N/ j' x; P' M        ENDP  // End of SendCmd Procedure
6 p+ s* E$ H, v3 p6 L- p& F8 e
4 e4 G$ R3 d* E8 j5 ^8 a1 `0 T  q        // Ring0代码( T" P( h& Z, O  m
        Ring0Proc:
( b! l! h  U1 r6 V        PUSHAD
. ]) d+ z, e1 r& Z3 S3 \* I        // 查询IDE设备是否存在
$ g) c6 _+ Z7 v0 G1 ], ], k- P        MOV DX, dwBaseAddress
, n7 c4 b9 y1 s9 W7 R' N        ADD DX, 7
8 `+ z9 G, U! N( z( d3 O& f. {        in  AL,DX3 @0 z! G6 i" b* Y' P0 t* `
3 I( T: V# `8 }- x
        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回& E2 n* l) j* J1 V. g, c! }
        CMP AL,0xFF
9 n7 f* o8 \6 e, D- G! `) h6 S% J6 p+ I1 @        JZ  LeaveRing0/ a2 [+ D# K8 _
        CMP AL, 0x7F8 {0 k4 |! d) Z5 l; {. V* e8 i& e
        JZ  LeaveRing0
0 j& j7 V( ^% c' Q9 l7 C
+ N9 c8 S0 v0 p* }, G7 V+ U/ N        // 设置IDE设备存在标志
" r. i: {6 O) ?* y! I  A        MOV btIsIDEExist, 1- R5 Z/ ~: X% i8 U
3 ]5 B# H6 u' \1 ~( [* v$ ^# l; r4 w/ r* y# {
        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
0 I" j8 j/ U- A' ~" i7 ~: U: ^        CALL WaitWhileBusy6 m1 T8 Z' Z- r2 |3 m
        CALL SelectDevice9 [1 Q# l: @- |& k

. A5 K2 H5 J9 b  z0 s) J        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
5 g) h, u0 r2 O6 [  y8 n        CMP  btIsFirst, 1/ E4 `- F! t9 S6 H3 Q/ n
        JZ   LeaveRing0
- _: }. F' j8 d- D. x+ Y$ t
- o3 R5 k9 d& j+ C& _+ l" G" r        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???3 z2 y" r+ |8 V' b( [
        CALL WaitWhileBusy
9 T$ o8 \* J( e* X1 ^- r* H  k  F' X' }  a
        // AL的值等于cBit06时,不存在驱动器,直接返回
$ b( H* T# v  `, ?- d        TEST AL, btBit062 u" H/ I. q$ S. J0 h) L, |
        JZ   LeaveRing0
* j; _9 h+ m" T4 f6 t
8 L. u9 X6 e5 c# P  ?$ v, h        // 设置驱动器存在标志
" R, z7 a; c9 E$ J4 I) g+ W8 e* h0 R        MOV  btIsDiskExist, 13 x2 p9 T# P( A* H. H9 L

! O5 N/ ?  p- f        // 发送存取端口命令! k7 x1 H" j% ~. \$ q* q% N
        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
( j3 U- V2 H3 I7 V        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令! f, ]0 a5 i$ K( i
        CALL WaitWhileBusy
! s3 R- ?5 ~0 C0 O        CALL SelectDevice    // 设置主从盘标识
7 F1 S2 w( Z" T4 E        MOV  BL, btAtaCmd      // 发送读取命令
" N, w+ |8 F* O* @        CALL SendCmd
0 n' A, z) I1 x  P        CALL WaitWhileBusy
! ~& ~, {6 k4 I" D* q
/ \" b# {) _5 m, u2 l4 R        // 检查是否出错$ O, K1 M. P2 o  s  t0 m: x( s
        MOV  DX, dwBaseAddress5 A- g/ M3 u& N: O
        ADD  DX, 7
# L# K! C3 e( @5 G3 H2 W
/ z; _% g- _* W/ q8 k+ s        in   AL, DX; f4 J3 v: Z. U) \! n1 c" O
# b$ y4 Z- G. r
        TEST AL, btBit00
  j5 {1 D/ G  g' k' p        JZ   RetrieveInfo   // 没有错误时则读数据8 j& V7 q4 z8 W0 R. f
1 b. A1 e" J( |) t  v* D0 S
        // 如果出错,则进一步尝试使用ATAPI设备命令
8 I( s+ S" l  Q0 S, c        CALL WaitWhileBusy
  Y' A; t( C: N% C( C4 A; g! C        CALL SelectDevice
. t0 O$ P7 U% w3 B; [        MOV  BL, btAtapiCmd
- `& b% S! k( Z1 k6 R- ?, B        CALL SendCmd1 U, j7 ]$ j0 w1 ]
        CALL WaitWhileBusy
/ D  L& ?, X# a4 C* U4 z4 O) H8 _- k0 ?* G. J
        // 检查是否还出错) ]  ~# Q2 C9 ]. T; Q% \
        MOV  DX, dwBaseAddress! N9 H* a. D% S
        ADD  DX, 73 i. G( u9 ~. \5 f3 |
        in   AL, DX
6 L/ n- X/ k* g2 W% B        TEST AL, btBit008 O: Q5 `# H5 Z! M8 B8 n4 R; f
        JZ   RetrieveInfo   // 没有错误时则读数据
$ I! `- t) ?, r! _4 n        JMP  LeaveRing0     // 如果还是出错,直接返回! c0 k# t7 f6 b

) y" R$ l! c  {& s& Z3 i- M        // 读取数据/ Y: B& K9 U* e5 D( f+ C
        RetrieveInfo:
3 I0 j# i( Y* f3 j  R' `
+ v/ d9 [5 ?" [2 y( u        LEA  EDI, wOutDataBuf
5 s  m6 |/ |% T' K# Y- x: A. c        MOV  ECX, 2562 `1 J" K7 I0 O. c5 U* X  p* N( d) @
        MOV  DX, dwBaseAddress# v/ s1 j( g1 W0 y0 \6 M6 v' g/ e# l
        CLD
; u# o. |0 k) n+ z- E4 E2 K$ O. [
        REP  INSW
/ c- f  Y( b* C, z0 k5 y/ \) n+ M. [3 h- Q; ?/ t0 R
        // 退出Ring0代码
7 t1 h  J5 q6 G* b+ [        LeaveRing0:" t# J5 F" L2 F

. j7 D  ?$ R; I' P7 @        POPAD1 _% `1 M2 h3 ]" q6 F+ K
        IRETD
) Z: c: J% U" C6 g" ~6 b, |
/ M" a6 B4 }! f        // 激活Ring0代码5 {! d6 j; m. ?# u/ n+ r6 f
        EnterRing0:; r# Q+ x4 v9 L7 x
/ |) c1 W9 i( E; w3 D" ~6 I, g
        // 修改中断门" X2 q9 r$ L' K! P5 V
        SIDT FWORD PTR btIDTR17 _; L3 B& ?, P
        MOV EAX, DWORD PTR btIDTR1 + 02h/ H+ B! |1 P) C! k9 j4 C$ k
        ADD EAX, nHookExceptionNo * 08h + 04h
& u7 F7 }/ P' K) J        CLI% D. l: q" T$ ^6 {3 Y. k' J
; u/ j+ v( a4 Z
        // 保存原异常处理例程入口
9 b9 V8 f0 F9 u6 ?1 N+ n! F9 p        MOV ECX, DWORD PTR [EAX]* n! P0 d% z7 y3 _, k% J3 z
        MOV CX, WORD PTR [EAX-04h]
% y2 l1 `7 Z% @9 j' N) A) I8 x        MOV dwOldExceptionHook, ECX
( B. k6 }  f9 s/ X( R. V# h8 I
. [. m5 r! a5 v/ Z        // 指定新入口5 `2 P" c  P  D0 Q3 s" G4 H
        LEA EBX, Ring0Proc
' ^0 a8 n& c8 k        MOV WORD PTR [EAX-04h],BX
" a% B9 I% V- H; q/ |2 |        SHR EBX, 10h
9 p6 r' @7 g+ m& x& J8 M* @" X/ h        MOV WORD PTR[EAX+02h], BX
$ g2 g* s# Y2 s9 g5 {7 K
; o2 N$ z1 l$ G+ }% P! P( j0 W        // 激活Ring0代码
. Y- L0 f# A" J1 L' q' W) u+ Q7 `- p        INT nHookExceptionNo
/ j0 s) u" W# V. h" l! P  f# Q( f* d1 t; [( m' e) q
        // 复原入口( L$ B8 a  n/ W) [3 w& P7 }
        MOV ECX,dwOldExceptionHook
0 C9 E: u% ]2 E" y* P        MOV WORD PTR[EAX-04h], CX
, c) ~0 s% E& p" {9 _9 F        SHR ECX,10h" r. T+ d: ]$ ^  D6 N; R: O
        MOV WORD PTR[EAX+02h], CX
1 }1 X2 J8 Y1 _) w        STI3 K7 t1 Z# [9 \6 A! e
    }
4 x3 V8 H+ ^$ [' r8 ?9 r    if(!bIsFirst)7 V; Y* `; {  q) [
    {; b$ X9 P6 ~8 N6 _( c. i- J
        bIsIDEExist  = (bool)btIsIDEExist;
) s& |% @( J" V8 Z; f        bIsDiskExist = (bool)btIsDiskExist;
' r0 `1 l' e: r$ a. u0 [        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));( ~; a: b+ g  y4 d/ K$ O" a
    }
/ j. i+ C3 |) @. G2 C}
# L8 Q4 ]2 O5 o: z  u% h* y//---------------------------------------------------------------------------
4 P4 P( P8 D  _$ F// 调用方法:& i, W* k- P& L5 `. G
void __fastcall TForm1::Button1Click(TObject *Sender)
1 A2 h/ I- _0 M  Y. ^8 Q' e+ b) V  P, g{* t* D2 }6 j& I% f# k( `
    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);% ?* k' K' C3 A4 b5 J; u4 L
}) e' d8 S% _3 ?8 @, v3 `4 z
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-6-19 17:47 , Processed in 0.038188 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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