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

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

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

  1. 9 B( f  c+ @* o
  2. #include "StdAfx.h"
      L4 n# `8 `  ?! K) S  a, [
  3. #include ".\puiddisk.h"
    9 B: n2 f( |- R; k
  4. #define _WIN32_DCOM
    8 [, H! n6 J" F' ?8 U
  5. #include <iostream>2 U9 x, t8 y* U+ v  Y
  6. using namespace std;. l* k5 |- r# u8 `- r' \& R
  7. #include <comdef.h>/ {- i& s* Y8 A8 p6 x5 B; o
  8. #include <Wbemidl.h>- u, u: {8 {" h  {7 H' T
  9. % c# B- @/ N& ]2 e( X* G) v
  10. # pragma comment(lib, "wbemuuid.lib")
    * x+ U, e8 }/ F% j& O* A
  11. CpuIDDisk::CpuIDDisk(void)
    4 n/ w6 G7 A  x0 C$ r( K! L5 ]
  12. {9 h; x- j; f5 K  P
  13.     GetInfomation();
    2 |7 N  S$ w# P6 ~% i
  14. }& Q8 B( {4 w' R& w

  15. ! g+ O. U7 m3 [" d  O$ k
  16. CpuIDDisk::~CpuIDDisk(void)
    9 q# d" ~% q5 T! Z" K1 X; o
  17. {
    5 c) A1 f1 }5 N1 Z
  18. }
    & Z( e% }* y$ K3 l7 S/ j
  19. int CpuIDDisk::GetInfomation(void)6 u& T7 S5 u' G& r6 G: n, Y4 L8 j
  20. {
    % }$ |/ Q4 P( V6 C* O, l. V/ e5 E
  21.     HRESULT hres;
    & u5 k# P0 ^$ ?* A
  22.     //步骤1:不是必须的,COM只须也只能初始化一次
    0 I$ Z) v% q  E1 r3 {1 l
  23.      hres =  CoInitializeEx(0, COINIT_MULTITHREADED );
    / t& _: p& A! H' Q, b3 z
  24.     if (FAILED(hres))/ a$ o+ Q1 c* Q! d/ x9 N
  25.     {
    9 j/ C7 r( [, p* u' s
  26.         return 1; //初始化COM异常:注意,COM只须也只能初始化一次
    ' Y5 R9 ~% }' m; v, ~" n7 U$ Q9 |
  27.     }7 \1 s8 a# T3 S1 l
  28.     //步骤2:不是必须的,COM只须也只能设置一次
    * E! D# u6 O( p& O+ O
  29.     //Set general COM security levels- p. T2 s$ D3 e5 }! |& f% I
  30.     hres =  CoInitializeSecurity(
    : i* k! l# G! C5 d/ w. b" Y5 l$ \
  31.         NULL, # _' m- v  F" q( M
  32.         -1,                          // COM authentication
    ' M6 I' K& I2 s( Q+ J; B
  33.         NULL,                        // Authentication services! K8 r: Y9 B# A+ H$ W
  34.         NULL,                        // Reserved5 V$ I- l1 r# p. \
  35.         RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication
    5 n6 [/ ?* |& @$ S
  36.         RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  $ v$ C. _" M: \, H3 x/ {0 U* J! f
  37.         NULL,                        // Authentication info
    ; K0 {- p. f5 X( T1 v
  38.         EOAC_NONE,                   // Additional capabilities
    # L; ?2 m: ~5 x& A
  39.         NULL                         // Reserved
    2 b" X4 S4 Z/ |. q. {; S' P
  40.         );
    ' W( B. S5 a- G; ~! _/ Z' B
  41.                      
    - w, W% }# H" ?. C4 X1 ^
  42.     if (FAILED(hres))
    $ |" x; T2 w7 C* v5 o! S. e+ P$ d, l
  43.     {& t! J- ?, u4 M) e7 i
  44.         CoUninitialize();5 }7 v* Y1 @& M# I3 f
  45.         return 1;                    // Program has failed.
    4 r. \" k9 }& B7 D5 c5 |8 M
  46.     }( H5 d1 m( v. |8 _& p
  47.     4 g" ~8 d. n0 k
  48.     //以上不是必须的,若已有“::COMInit();”,则要跳过
    + u, _0 l2 U' w6 S) e
  49.     //步骤3: Obtain the initial locator to WMI 3 I2 Z  Q/ Z" I0 ~! `& y; t" M- J
  50.     IWbemLocator *pLoc = NULL;
    1 I8 H( v# ?3 A& b! w- y5 x0 l
  51.     hres = CoCreateInstance(
    2 G5 \# Y0 \- S
  52.         CLSID_WbemLocator,            
    . Q  |8 z4 K( S! I1 l/ B% X7 \+ ^
  53.         0, 1 @2 X/ J, r  A; S% F
  54.         CLSCTX_INPROC_SERVER,
    8 |# ]% o1 o/ p7 D2 H" ]
  55.         IID_IWbemLocator, (LPVOID *) &pLoc);+ F4 ^. |7 x3 i
  56.   }- j+ ?/ B& B# X; i! X% i0 t* K
  57.     if (FAILED(hres))
    ' f9 w* i5 u- m7 H! N3 e
  58.     {
    ; H* o0 }; H8 j, y0 ]' H; [
  59.         CoUninitialize();
    " \' G( Y% a9 X
  60.         return 1;//Failed to create IWbemLocator object
    $ v5 U  N3 @% e$ v: G7 S% P
  61.     }
    7 \) s8 d! i) z  {2 \5 t3 G; B
  62. . u7 W! s+ R! t/ R* M  Q+ Y
  63.     //步骤4:Connect to WMI through the IWbemLocator::ConnectServer method
    - n5 E: J+ p& X  S4 t2 B0 s
  64.     IWbemServices *pSvc = NULL;
      U3 b% I: X3 H
  65.     hres = pLoc->ConnectServer(
      [6 T  _# m: K  d# f
  66.          _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace$ m; ?* p$ q* Y" z( U
  67.          NULL,                    // User name. NULL = current user" \, h% |6 d+ Z& I
  68.          NULL,                    // User password. NULL = current+ _4 f+ a! {/ d0 T  X; {8 l
  69.          0,                       // Locale. NULL indicates current0 _" x8 {9 c+ w7 s* m. s) _
  70.          NULL,                    // Security flags.
    . n' q# l4 e6 [6 D' c
  71.          0,                       // Authority (e.g. Kerberos)
    1 H8 k$ `/ i. g5 ^5 P. ?8 R
  72.          0,                       // Context object
    " F4 h8 D0 B: N8 T7 A( {9 U8 t  H
  73.          &pSvc                    // pointer to IWbemServices proxy
    8 I5 g' A. o; L' ?) ^1 c9 E
  74.          );9 c+ V# }8 u, l9 z
  75.     4 |7 O! f+ Y( p' a# V7 J. b4 B
  76.     if (FAILED(hres)), v: b, ]2 ^( Q: h' I
  77.     {4 a8 l. @7 ^+ x* A# Q/ Q5 w
  78.         pLoc->Release();     % |: T0 {" }7 W2 a' B& t
  79.         CoUninitialize();8 x2 I! B9 g* k/ e& N
  80.         return 1;                // Program has failed.
    : O! C2 P" e4 d3 N  M
  81.     }
    / W$ |" }6 m1 N; E6 N
  82.     // 步骤5: Set security levels on the proxy
    5 D( W+ Y' Y. C" X
  83.     hres = CoSetProxyBlanket(/ @3 Q" D) f8 i4 n
  84.        pSvc,                        // Indicates the proxy to set( X0 Y1 e( y$ ~4 d
  85.        RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx
    ; l. u( k; A7 O4 @$ Q  H
  86.        RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx
    # S. }7 r% {6 n6 i. o. @
  87.        NULL,                        // Server principal name
    5 }/ K! z1 l3 m/ Z2 s
  88.        RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx
    2 m; S3 z& z: @) O$ A+ X6 W
  89.        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
      H3 K6 m- d) Q0 a( C* ~( T8 P. _
  90.        NULL,                        // client identity
    ' @2 M# {# ?$ P- S2 W8 N$ }
  91.        EOAC_NONE                    // proxy capabilities 3 g4 [# F# u" ~* x' J. R- q
  92.     );
    0 `, r: t: D* t: ^' }: O( M

  93. ! ?8 p. Z% x; e, G6 S( F3 j
  94.     if (FAILED(hres))
    ) G( P" T+ S$ X0 D! u
  95.     {
      M' x& q8 `" C' ?
  96.         pSvc->Release();; N" D9 \. V" }. \' W4 X5 B) m( s% W
  97.         pLoc->Release();       T% ~/ [* c. q! I: j  j3 R8 [
  98.         CoUninitialize();# W% l9 m1 T4 X+ I
  99.         return 1; - x  P; V6 g. r" p6 y9 t: I
  100.     }5 h' K6 ?- I* |; ]7 ^3 x
  101. 7 _6 G: j1 M. S4 d0 x+ v
  102.     // 步骤6:Use the IWbemServices pointer to make requests of WMI ----
    ; o8 G. T3 G; f$ D3 e
  103.     IEnumWbemClassObject* pEnumerator = NULL;
    9 r/ t) a, r* Z9 R; c/ Q2 `4 i
  104.     //计算CPUID
    7 x4 [/ b# t2 Q9 `
  105.     hres = pSvc->ExecQuery(( f6 K: c; T( |* O
  106.         bstr_t("WQL"), ) G9 |3 t3 J+ W& _) z, ~
  107.         bstr_t("SELECT * FROM Win32_Processor"),//Win32_OperatingSystem
    9 X' R" I0 h- @4 M
  108.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
    $ {8 z' ?% S5 f9 D  M" h6 I
  109.         NULL,
    ! F8 n% ^! H, c- }+ N  ]
  110.         &pEnumerator);
    : f# b+ H& T: e6 J0 w! x
  111.     , @8 I- z! h8 u1 @
  112.     if (FAILED(hres))
    . [  Z$ Z/ j) L( G9 ~) x( k
  113.     {$ L' Z1 n2 G/ |4 P) v
  114.         pSvc->Release();
    5 K# N& o7 G  F  B# U
  115.         pLoc->Release();% {. o! W; @& ?0 ]  k3 c
  116.         CoUninitialize();
    9 v. m9 J" }) p+ P) Z
  117.         return 1;
    $ e( H* a% A. j8 y. b
  118.     }
    ! v$ u$ J! h5 H1 `% F2 ]
  119.     // 步骤7:Get the data from the query ! ?  J" E  T2 B6 k5 T! k# C! _
  120.     IWbemClassObject *pclsObj;
    4 D- F, l% K3 g1 _8 h' F2 Q' q
  121.     ULONG uReturn = 0;
    ) j- F0 F: W+ w4 H; }
  122.     while (pEnumerator)
    & G! L, n1 a: ~  v# J- j. U7 V
  123.     {$ L6 S( R1 \- n: k
  124.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
    ; b1 f3 V) Y! @  n8 d
  125.             &pclsObj, &uReturn);. @) v1 ?( m# b1 H5 x8 R
  126. / s$ f: i# r% T
  127.         if(0 == uReturn)* j, ^0 V# i. S
  128.         {5 t  }7 e4 a3 ]2 V: X
  129.             break;
    , v  X$ [, k, S& J( R
  130.         }9 ^( M' }3 ?: a: [8 o3 M
  131.         VARIANT vtProp;: h$ @) C! g8 V% N: D1 N  h% t0 w
  132.         VariantInit(&vtProp);
    7 [6 i$ B9 j( d) k! b
  133.         hr = pclsObj->Get(L"ProcessorId", 0, &vtProp, 0, 0);: n3 @( ~: u/ g# w: E, V
  134.         strProcessID=_com_util::ConvertBSTRToString(vtProp.bstrVal);//strProcessID:类级变量
    , h! }! [& z. d) |. o/ x
  135.     }6 h. B! v2 p  D2 ]( {. o

  136. 7 g! ^* u1 D' _' T+ r
  137.     //计算硬盘系列号7 l2 f+ Q, k( B7 C
  138.     hres = pSvc->ExecQuery(% `6 `) H+ ~) l  Z+ i' o1 m
  139.         bstr_t("WQL"), ( X# k# ?5 a( D
  140.         bstr_t("SELECT * FROM Win32_DiskDrive"),0 s, B' @- a4 U( h- Y# }
  141.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, & v9 n8 L7 D) K% U% Q6 v1 f6 ^% ~
  142.         NULL,
    $ w. E5 {$ j1 T' A: P) T2 x* Z( n
  143.         &pEnumerator);
    3 e, c! [  b" @1 c/ G1 d
  144. - k5 ?% u0 H8 h: v. B# y+ h
  145.     if (FAILED(hres)); n$ ^) c1 C- _7 U
  146.     {. A0 I6 L4 y/ M0 G, W
  147.         pSvc->Release();
    7 ~- L- C7 O! H1 X! b9 ?6 d% B% J
  148.         pLoc->Release();0 v0 y' W! L  {/ o3 u) q% g
  149.         CoUninitialize();. Y; J4 A. R3 X1 p
  150.         return 1;
    8 h/ |" `; r+ _/ {3 {, Z* |
  151.     }1 j. X& ?+ r3 F8 B
  152.     while (pEnumerator)
    , U# a8 z  [' a; _; S( s
  153.     {7 u- e0 f. |8 Q# }& R  P
  154.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, * i- c' O- n1 u" B
  155.             &pclsObj, &uReturn);
    / Z& p7 D# }# D

  156. : l% u( \2 ~" f, O
  157.         if(0 == uReturn)/ V3 V. [+ d2 ?2 X+ q
  158.         {
    " m" @% `3 _; s$ ?/ K
  159.             break;
    7 l& ~! z) N5 l8 R' A7 \, G7 L
  160.         }- A( K/ r; A1 K& Z% _, f

  161. , O& c- r. C7 A( D; W- k) w
  162.         VARIANT vtProp;
    * {% v5 d6 k9 u% d# M" e3 t" Z) t
  163.         VariantInit(&vtProp);
    ; v0 C: W, F6 D& ]
  164.         hr = pclsObj->Get(L"PNPDeviceID", 0, &vtProp, 0, 0);
    6 ^4 m9 F$ s. N% |! e3 z
  165.     strDisk=_com_util::ConvertBSTRToString(vtProp.bstrVal);6 ?7 {9 k$ i$ o+ Q2 Y/ |
  166.     }
    1 @) z0 K& D0 ~, _, ^
  167. 4 ]- l) ?$ G3 b
  168.     pSvc->Release();) Z0 q& T& ~: d5 }: L& m
  169.     pLoc->Release();! Q2 Q# S9 |! m4 H* _, K/ \* s$ Z
  170.     pEnumerator->Release();
    6 Q/ L$ ^. `' |7 S/ I
  171.     pclsObj->Release();
    . q1 `1 J* @, J
  172.     CoUninitialize();
    + R0 R# ]4 u) m9 w: g  N. w7 M
  173. + j1 b" A6 t1 i9 x/ ^0 O
  174.     return 0;   
    - u8 [/ v7 |/ ~, i! e( F0 n
  175. }
    " p( x8 o6 q9 m* A% r" h
复制代码
 楼主| 发表于 2010-10-11 19:21:05 | 显示全部楼层
本文代码经ccrun(老妖)在Win2k下试验成功.
: E# ?' T6 c! Z* X0 p" O; P. L# U% T
8 l) ^6 N! `( [2 z/ k4 v#include <WinIOCtl.h>
3 t5 x$ g/ A( H#include <stdio.h>
5 L- C! X) z0 I$ K- k4 h) [# B0 s5 Z. Z4 y% t
#pragma inline$ |) y5 j- t( S) T9 P+ j( [% N: B
//---------------------------------------------------------------------------8 I/ e( U0 X* K1 r, M8 u
// IDE NT/2000/XP专用变量
2 ?" e( n. P* y, Y; T. \" b#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS1 d& v6 {+ o+ c* F+ @# {
#define DFP_GET_VERSION         SMART_GET_VERSION+ x2 u# z/ m5 E1 v, g
#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND8 O) X# g- l" F& s0 ~
#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
' i5 i+ G. i  R( l8 A2 t  e! `* _* ~4 k" F0 o/ D: d* a
const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令# n7 a4 m, k& x6 W- y$ o& E: u2 D
const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令# h) Y4 o! U# P! g# \1 y/ q
9 ~: \5 b1 r  q1 s
const int MAX_IDE_DRIVES = 4;
5 H* V/ }, U5 [; G" c8 i* d. }! J% Z0 l! Q# E4 G# ^7 B$ ^3 y
// SCSI专用变量1 c" e/ [* N2 y! F! C& t5 P
const DWORD FILE_DEVICE_SCSI             = 0x0000001B;6 S+ g" D5 S; G+ _/ D+ W
const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);. H' w- I+ b+ ~( f. Z6 l( m
const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
# X- J( w7 g9 M5 k* ]: Y! \const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
* L% F6 ?0 I. X2 m- k2 S' k) z! W. Z$ q9 v  x* g
typedef struct _SRB_IO_CONTROL4 k" H8 P$ k/ g
{& H3 }4 y0 h% d% i* w& H
    ULONG HeaderLength;0 j! t' I% |4 b/ z
    UCHAR Signature[8];8 u1 [# M0 c( K) `4 {2 M$ ^/ m0 _
    ULONG Timeout;4 w" g: z' Y. n
    ULONG ControlCode;% V" C, a  [" j4 b0 Y1 K3 [( y
    ULONG ReturnCode;$ n; l' A" Z' }9 f4 X
    ULONG Length;
  c' W4 z0 e% G: k8 ]; m" f& g}SRB_IO_CONTROL, *PSRB_IO_CONTROL;. Q( w! u: D3 k- k& q+ [3 O
; U( Z9 B1 @4 J/ c8 i6 q
// 读取的主函数1 _, M; J& Z( s( L" ?6 }
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
7 q. g3 l% M6 M
8 K8 Q! c5 [* v* W* t" q, ?// 辅助函数
- a* J5 F% o8 b0 Nchar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
/ H0 N0 e+ l( H! B- A! L9 Q1 [// NT/2000/XP函数- l+ l9 z6 [& \; K! L! T
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);% G0 U" U5 h. F5 _/ }2 }0 v( r
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
" U6 H: E. |- p7 J9 G0 V" j- [5 n        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
; W6 ~) k5 \& s5 y        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);) G: t* Y! M( @
// Windows 9X函数
' `7 p+ f# q+ A  ovoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);
8 o1 i1 {+ _4 V0 b, i( T7 K) tvoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
, [& r! _1 N) O+ v        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
, L* _" a8 Q% z: V' C! K( k9 ]3 x4 C7 f5 @& |, Y
// SCSI读取函数(for NT/2000/XP); t: z; x( n' m) F% G5 z" F
String __fastcall ReadIDEDriveAsScsiDriveOnNT();4 L: @  F9 Q* E' S3 t
//---------------------------------------------------------------------------
; b) D- d  O, C4 F: U3 y# W8 ?( h, L// ReadPhysicalDrive
: m$ Y$ E. E! Y% nvoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
) b# T4 ~9 _' k* F, y& U" ^{
& ?- B% L! E6 ]0 B- [7 _' l2 i. ]    switch(Win32Platform)/ e, H3 b# m& ^/ ~% [. q+ d
    {. v1 p+ i5 k4 G
        case VER_PLATFORM_WIN32_WINDOWS:
6 }" P' r- g  N2 v            ReadPhysicalDriveOnW9X(pSerList, pModeList);
9 G+ ]' p9 q) S$ ~/ S5 u            break;
; b" M' Q+ q0 G        case VER_PLATFORM_WIN32_NT:
: r* ]6 o& T: u7 O/ l& ?( l            ReadPhysicalDriveOnNT(pSerList, pModeList);
- U. }- c- M2 j$ F& B            break;& L! q" J5 a  `
        default:6 G' J3 n9 [7 A, Y8 t3 M
            break;) l2 q0 P( u" a/ R0 \
    }9 m! s7 i" ?  \' S8 ?: v* y
}. j. [( M/ o# C3 z- d% i0 h
//---------------------------------------------------------------------------$ g9 H% w4 M  p: @6 k4 l+ c7 r
// ConvertToString
) ]' ~+ a$ D0 A: n9 m! Ichar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex). l5 V7 Y, C  }
{
# C7 r% T5 Q; E/ E/ P    static char szResBuf[1024];/ F* z( b2 h8 R4 C- {
    int nIndex = 0;6 S6 ~6 w8 B  r
    int nPosition = 0;2 z$ L4 x/ k! P: z8 W5 b6 E$ B- V+ T

4 n/ |8 u2 `( U+ ^3 [6 W( L    // Each integer has two characters stored in it backwards
6 F! |5 n8 f9 z3 K0 e    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
& h- h6 W) a' t" [5 e    {
  S( s# H! O/ e& J4 Q/ |' _! [        // Get high BYTE for 1st character3 n/ ]* U; x; g& B# L- |# J
        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
1 F- t# y' i2 Z( U/ m2 f        nPosition++;
/ ^% J* B1 u( U9 F5 G" W8 n# g9 C* V, {
        // Get low BYTE for 2nd character
; ~' l4 X* q) Z$ Z4 D; j: V2 m! n        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
& K  f( G  q- @2 E, D& R        nPosition++;! W& _/ A) A9 t. y! y4 A1 p, I
    }
$ V8 u* O' O, t( Z- H
' ?. c) {7 k' F, f* w6 N    // End the string
* j& R; m; ^4 k7 i    szResBuf[nPosition] = '\0';
+ ]4 S% W- y5 {- z3 O& E4 D
) ^3 Y) @  G( O+ u+ \4 ^/ h    // Cut off the trailing blanks2 T- Z( U/ a3 A  F- g' X! N
    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
4 P4 R( \5 _! i8 \. U/ D        szResBuf[nIndex] = '\0';( O) B  ~5 q  w9 S
8 A( L! M. @0 l1 S% {+ C
    return szResBuf;
$ d4 a* L& `7 T}0 U0 W/ q/ ]) I2 W( N  d+ S
//---------------------------------------------------------------------------
7 c2 ~2 Z2 a' B  w3 |4 D) s// Winndows NT4/2000/XP 代码
. x* D! j- }1 _0 P# B6 b' V//---------------------------------------------------------------------------5 f# ^$ q2 d, m  I
// ReadPhysicalDriveOnNT4 x. v( g* g" S' S
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
0 q& A5 {2 D$ t' R! @9 a{
6 b9 m1 C& n; L  a; ^    // 输出参数
; f2 F7 _7 e' l+ M: I9 ?# ?  {    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
- x! s. J+ X. W: B7 ]  U3 f
5 j/ f' f+ W, d. j! ?6 U2 K7 X6 d    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)- [; w, ]7 H$ ?  X2 K2 I3 w
    {6 T0 u3 L" g4 D! v( h2 T8 k2 W1 o
        HANDLE hPhysicalDriveIOCTL;
/ ]3 i# C' C. O/ |        char szDriveName[32];
* ]# K4 E6 e. v7 t8 z
7 i2 E. N& F) c% I7 A1 a/ S        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
, c. f) x& [. G- z        hPhysicalDriveIOCTL = CreateFile(szDriveName,9 L2 p3 B' D7 T3 B7 n, g2 U5 T
                        GENERIC_READ | GENERIC_WRITE,1 `# _; Y* K$ g2 J! j
                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,- K3 N0 s0 t, O; C# e1 ]% O
                        OPEN_EXISTING, 0, NULL);# ]1 u6 a5 z& A* }

# o) T6 Y  u6 \8 c- }3 G        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
/ H* z7 a' c& m" x        {2 C9 R: f' O# H
            DWORD dwBytesReturned = 0;( C9 X. l: [. b* p6 r: l
            GETVERSIONOUTPARAMS gvopVersionParams;. ?! F" V8 V8 O9 p$ ^6 Q# s
+ j" ]$ v- ]' ^" }4 d3 F
            // Get the version, etc of PhysicalDrive IOCTL
% e' W  s3 ^% a9 `, w; e2 U            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));' b! ?( Q; W2 ~+ m. ^" t
1 s% u0 |$ T' ^) k& `" c
            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
- c( ?9 p  L: `  d$ G                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),8 y# Q1 v4 _5 M' ^, L
                    &dwBytesReturned, NULL))$ ~$ G; B) g9 s% F, M0 K
            {
- o& V8 J, P$ T; k- P% ]7 X: C                continue;3 A8 C  P# _" W3 v2 Z# T
            }
; w0 h- c) H, L. C" j$ w2 {2 l: N7 E0 ^+ X0 ~5 J
            if(gvopVersionParams.bIDEDeviceMap > 0)! B; |6 @7 V0 {; a1 y4 Q9 S
            {+ `- ], s- B! C0 o( S/ j3 I/ z
                // IDE or ATAPI IDENTIFY cmd
) d6 ?8 q& ]7 `# t: w3 j  M                BYTE btIDCmd = 0;
% n6 l( P5 l6 r2 y/ H& D5 C2 n                SENDCMDINPARAMS InParams;
( \$ H: l% g- [. I  |& Z                // Now, get the ID sector for all IDE devices in the system.
+ V# C5 u8 m3 m; O                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
/ Z8 n6 G- B5 u/ N                // otherwise use the IDE_ATA_IDENTIFY command8 |  ]& z4 Q" ~
                // 具体所得结果请参考头文件中的说明
, A' {3 B) `* H' V                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
4 C/ T# {" ?$ E# c, {                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;% C3 k6 g) C3 j: [  y' S3 X5 G, h' {
                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));# D7 s  S2 |- z+ N: p
                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
) h; y6 }! @0 ]/ Z3 s
; q0 [( K& `+ j; S& ]                if(DoIdentify(hPhysicalDriveIOCTL,
( q0 A3 F  T0 P1 a                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
2 \3 X3 c6 k# N  x                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
1 R1 k+ s5 i- U% x& h                {: {7 L8 o) k" y
                    DWORD dwDiskData[256];. {- L$ V1 ^( o5 a* f! @
                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件' v( d9 G; G$ I2 w* K
                    char szSerialNumber[21];
2 n. I: d# `# v: U                    char szModelNumber[41];
7 O/ j/ i& Q! m) b2 W9 f  ]0 j9 q& Q
" c$ H6 Z7 |# ^5 x' G; c                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
! j( c0 ?: L3 @. U                    for(int i=0; i < 256; i++). p7 b( D7 @5 E( l' o( R
                        dwDiskData[i] = pIDSector[i];6 ]- B3 Q0 i, c* _( N# e
                    // 取系列号8 e: w' X" V' j* h
                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));( N- P: U  Q, q2 W; V
                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));8 T+ a: f6 o1 C/ J
2 x- W, y" D; c2 ^
                    // 取模型号
' P) G  M( n5 P* ?                    ZeroMemory(szModelNumber, sizeof(szModelNumber));) Q" R0 |) A+ P0 `
                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));" t) `7 m2 x6 G

1 A1 k6 U4 w! ?9 q) |- K                    pSerList->Add(szSerialNumber);
" N6 ~( n, ?! ^% V( A                    pModeList->Add(szModelNumber);+ d0 w, U' C' i6 j8 R
                }+ B' x2 F* R# y# f; a) y
            }6 v( k" B& C/ k& W5 S
            CloseHandle (hPhysicalDriveIOCTL);7 h- |$ W! h3 B% @
        }
9 _, {+ i: Q, |    }) k' x. j0 `! M
}
9 q% T) i& v& |# [* ?+ d' s//---------------------------------------------------------------------------( j% U+ ]6 j- k2 p) j1 [6 b9 A
// DoIdentify0 Z0 g* _" l: O
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
# J! V- p+ q' W. C# |  P              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
  r5 {: d+ {$ j( j9 r              PDWORD pdwBytesReturned)! B$ m. ]4 _2 ~3 u
{
+ f! ~' w. t+ g0 b1 z    // Set up data structures for IDENTIFY command.8 ^3 D. H% K" M) q8 o
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
0 [1 N9 Q$ g7 |# a9 F8 I    pSCIP->irDriveRegs.bFeaturesReg = 0;3 L, Z, l+ P0 B) e- d" L8 J0 C
    pSCIP->irDriveRegs.bSectorCountReg  = 1;
, n1 N* N3 K5 K+ {; e, U    pSCIP->irDriveRegs.bSectorNumberReg = 1;2 Y% k$ h& Y* t. u0 i
    pSCIP->irDriveRegs.bCylLowReg  = 0;1 Z) x: j. W+ K9 U9 z
    pSCIP->irDriveRegs.bCylHighReg = 0;. G* m0 I1 w5 v0 m! `

$ d( t0 {& P+ q: f6 G    // Compute the drive number.(主盘和从盘所对应的值是不一样的), u& s. A# V+ z( T! R
    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;- s# S8 I$ p/ J- S& a8 |, g

7 e7 h4 ~2 w6 O( u$ h+ R  {    // The command can either be IDE identify or ATAPI identify.7 c* \6 H+ T( H' L- ^3 K
    pSCIP->irDriveRegs.bCommandReg = btIDCmd;
2 Y/ j- U5 o, _' w0 W    pSCIP->bDriveNumber = btDriveNum;7 `. r. Z" m0 W4 e- ?  @
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
* a+ }+ h$ Q/ B" R  M
4 c3 y/ n! B& z2 @2 c: c    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,+ b" J$ ~8 x5 z  e# W+ [! B& e5 E9 A
           (LPVOID)pSCIP,5 q# m4 ]% [) X8 B2 ]$ L& ^
           sizeof(SENDCMDINPARAMS) - 1,! l) u/ A3 p; I) n! I/ ]
           (LPVOID)pSCOP,+ L* g/ D0 ~4 R7 x
           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,. I4 a! W. C4 H2 {
           pdwBytesReturned, NULL);
1 k  E' s: H& m+ `1 g2 R5 p/ N}
$ i, s' D, T) _9 g) ?//---------------------------------------------------------------------------7 K6 K% F: {8 q# ?9 `$ ]
// Windows 95/98/ME 代码- l/ V4 c5 [4 b9 N; L  r
//---------------------------------------------------------------------------7 X6 K6 Z9 v. Y
// ReadPhysicalDriveOnW9X
& ?2 g- ?6 |$ j9 W+ M5 Svoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)% [; [' o8 [+ L5 g8 a) b
{
6 \2 x3 f8 E( r$ q    WORD wOutData[256];
* @, y' p; e- \; m7 }5 ]    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
/ B& L) g8 K) f, ^9 z+ {" F4 q; A/ `$ b  b' z6 ~, o4 u2 P
    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。  J6 b7 F5 a! C& I5 v! {% I, L+ {
    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
, \9 ]2 S  X3 \7 t* t' h8 ]    // 避免蓝屏的出现。(期待高人能指出原因)$ `7 J  S. g; O0 D' b/ b
    for(int nDrive = 0; nDrive < 8; nDrive++)/ P5 J5 O4 c  s. x4 {
    {7 q/ K# B% @0 Q* `8 Y
        WORD dwBaseAddress;% Y4 v  S: a: ]9 D3 s. b% s' W- U
        BYTE btMasterSlave;         // Master Or Slave6 n' Y+ \$ I" S7 J9 Z% Y, }
        bool bIsIDEExist;
$ j( H- L* v% b. L3 j" w0 }        bool IsDiskExist;% |0 _9 s! h9 X; V* d, L

7 N, r, V$ P7 D+ _) \4 T        switch(nDrive / 2)
2 Z& J4 s& e3 I& L        {' w+ r" L: b7 V% c
            case 0: dwBaseAddress = 0x01F0; break;
$ S! l2 U8 Y. _. I8 t5 E# |" z            case 1: dwBaseAddress = 0x0170; break;* a" x/ v( @2 M& E
            case 2: dwBaseAddress = 0x01E8; break;
- S* x% g  V  ]1 D/ b* D: ?            case 3: dwBaseAddress = 0x0168; break;; P1 J' i/ @  W4 |' v: u; A+ t
        }1 j" o2 ]6 O# O) M! D

6 |1 V+ g3 g( ~  l6 w1 R        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
4 E' h: O+ P* l) x1 j% @/ l+ O( R% K) l9 u9 u( V4 m  L, g+ q
        // 进入Ring0/ k$ T' [- M4 M. I. g! U
        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
, [7 O( A9 G5 n1 M/ V                bIsIDEExist, IsDiskExist, wOutData);8 F; u- I: h6 S
    }  f! q/ T( C! `, z' T  m

8 H. r' R9 W" |/ B    // 开始读取' d( E7 m1 b" s8 }5 h! i
    for(int nDrive = 0; nDrive < 8; nDrive++)' E9 W: @; v5 m: N* P
    {) ~0 \( Q9 o9 M9 X3 d6 e" Y6 \$ p
        WORD dwBaseAddress;. u/ [4 S/ _# \# |: \
        BYTE btMasterSlave;         // Master Or Slave
- D5 L# K, K6 V        bool bIsIDEExist;
3 x2 W& w. ^  k; F        bool bIsDiskExist;
% ?2 h- d7 n# m4 ^& z2 k& y        switch(nDrive / 2)
, n. \8 _4 O% X' F: P( b        {
  i& O. f5 n0 B" V& p) T% j& D            case 0: dwBaseAddress = 0x01F0; break;5 J/ M0 k# a+ O# q$ f& {" K
            case 1: dwBaseAddress = 0x0170; break;
6 m4 Q! A/ j  d            case 2: dwBaseAddress = 0x01E8; break;
$ U3 F# I/ k) [# o, R            case 3: dwBaseAddress = 0x0168; break;# f4 K8 i; a9 D4 w5 @
        }+ W. `) C  \; h1 a$ U" P: n

0 s- q7 i! H! _; H& @* [6 v- l        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
" m# l( {% m, q0 H0 {* Y; T
0 e* q* ~2 N7 O: T0 D% X; O, \        // 进入Ring0
3 Y* A( n% v  A+ Y. K        bIsIDEExist  = false;& n+ A/ }! r: o# Y- }4 t
        bIsDiskExist = false;
7 ?, c6 T/ ^& j        ZeroMemory(wOutData, sizeof(wOutData));! }1 @7 a2 c% J
8 A' e* m9 V, P" t) `% _; C9 Q
        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,& G6 c) X7 D! u; ~- d, W* O
                bIsIDEExist, bIsDiskExist, wOutData);, p: u6 l0 \( {2 w1 H2 N$ ]
! N3 f6 ^0 N' _: ?- b
        if(bIsIDEExist && bIsDiskExist)
3 S( m4 |7 a% f' d        {
6 b* O1 I) J7 t% }7 j3 l8 v* H            DWORD dwDiskData[256];
; e0 p9 }2 ]3 Y/ X            char  szSerialNumber[21];
' D; W$ m" F4 g8 y( s+ }  @7 @            char  szModelNumber[41];& D" Y/ C' n+ a' Y. C

$ l* E2 W! {: b  C& k, |            for(int k=0; k < 256; k++)# F0 ^) ?% f( h+ M0 u. W! e4 u
                dwDiskData[k] = wOutData[k];
4 c; D: e) ~/ z4 m+ W
! M1 s0 ^: l0 F* a! r. J2 B            // 取系列号
3 b) D( n' I* d+ @, c            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
5 d$ w% g. a; f/ k+ B. o4 L' [6 W- ]            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));0 C& z7 v, d5 M+ ^4 [* ~

  m3 d% t  b$ [! j! m            // 取模型号* l" m: U/ v8 b, p2 J. g3 S6 w
            ZeroMemory(szModelNumber, sizeof(szModelNumber));9 o+ J& s# a* p7 \5 t8 j6 p2 P
            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
' k9 s1 l& N+ S& t0 A( Y
7 ]  L7 d- I/ R8 S% u5 M6 [            pSerList->Add(szSerialNumber);( M2 [0 s  h7 W8 P
            pModeList->Add(szModelNumber);: F0 H6 e4 {# n5 W6 X
        }
5 x0 f: G' ]- M7 f. S$ X% R, x! i    }* K/ ?/ D$ w  k* J; m4 H2 D: V
    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
3 b1 e1 g  q* D2 M" `* ~; N* \- H}9 l+ E' E; k( Q
//---------------------------------------------------------------------------; W! j  ~9 c/ A1 B' a( l( w' d. G
// 为防止不负责任的转载者,在此注明原出处信息,请见谅。3 t1 v8 T& X4 G( M
// 资料收集整理:ccrun(老妖),欢迎光临C++Builder研究: http://www.ccrun.com2 R2 r0 B' I. I; C
//---------------------------------------------------------------------------0 [7 T; G- Z: L- ^7 |% T; j  @+ ~
// ReadPhysicalDriveOnW9X_Ring0()& D& i8 C3 a0 p% x0 [
//
" d/ M+ X. Q# m+ Q4 J& l// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h$ b0 |& P4 N, C' s8 i2 ^* `' a
// btMasterSlave = Master(0xA0) Or Slave(0xB0)
# d3 m( ^! j6 g$ I4 P//---------------------------------------------------------------------------
. t3 ^9 d8 V' X9 ~3 zvoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
' d1 e8 u, T, M! T2 ]8 D) ?* a        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
$ u, l# X5 k/ G8 p1 A5 s{
$ X$ l+ {& j. h! i: b% a7 u2 v    BYTE  btIDTR1[6];
; I+ V% y' J- D$ Z    DWORD dwOldExceptionHook;
+ p' B9 d5 e2 u5 x1 l$ f) q: j4 r    const int nHookExceptionNo = 5;
5 E" F" G! Q7 b, \5 \3 o9 V7 o0 w" R) y. y2 f
    BYTE  btIsIDEExist = 0;2 F5 r( A# y7 \/ ]/ D
    BYTE  btIsDiskExist = 0;# _7 l) D- A) A# B0 ^& N' F8 J
    WORD  wOutDataBuf[256];
  Y/ F4 q1 b& R/ ^! u8 |- Y) ]! k; z
    BYTE  btIsFirst = (BYTE)bIsFirst;
5 i, D1 g9 W+ G
" U6 d2 J5 [' w% F3 k9 z4 W8 s    const BYTE btBit00 = 0x01;* j; k0 Z0 ^+ T" S
    // const BYTE btBit02 = 0x04;
# }7 ^5 [0 g+ G% |    const BYTE btBit06 = 0x40;/ w# A9 f7 l; G8 j/ O
    const BYTE btBit07 = 0x80;  l5 o: O3 S7 ~4 ]* n* u
    // const BYTE btERR  = btBit00;
1 V7 i( s/ b1 N; D    const BYTE btBusy = btBit07;
& l# ?: \6 _' z& g    const BYTE btAtaCmd   = 0xEC;
+ i5 |7 N! c0 G    const BYTE btAtapiCmd = 0xA1;
2 x* e$ [. T9 k; T0 K: O0 p# k' U  H& B! Z; @) v9 z, C/ o
    __asm
/ ^5 K" R- f* o+ h7 e; _- h    {
6 F9 U+ a) [* s" u# f+ ?5 Y( A        // 必须先执行这条语句
& j+ k5 [& U' g        JMP EnterRing0
1 E, J) X! M, N9 @' W
! |; I" z5 ~2 T) Z9 h+ b4 L9 X% ^        // 定义过程
4 W0 G* T: D1 _0 ~6 h: i( x+ Y        // 等待IDE设备直到其不为忙为止8 ]  O- M5 z( X- _/ H3 j
        WaitWhileBusy proc
" h# B) a4 \9 \$ x2 F! R: o/ X! t4 H# L% g9 D( N% K4 h$ o
        MOV  EBX, 100000: w% M9 b: e8 x! h: o# _
        MOV  DX, dwBaseAddress
& M% O: ]! _3 J- }1 h        ADD  DX, 7
4 P; `/ p; o* ^( I+ W* a( L& a
4 K% e3 R& E; K1 n4 `        LoopWhileBusy:6 m& K( ?; q) O0 B
# d1 Z4 A' x" b% n5 }8 L
        DEC  EBX
/ s1 E. q: k1 u( P/ E        CMP  EBX, 0. r5 ?7 q( f4 O# ^; f# y/ q
        JZ   Timeout! t' l2 v" n2 Q# H% X' ^/ h
        in   AL, DX
5 X: K+ A# f# r! ~& X7 M7 _8 Y        TEST AL, btBusy: L& W! c5 U3 ^+ c
        JNZ  LoopWhileBusy
$ C2 q* H5 N( h        JMP  DriveReady
5 k$ q0 K) \: K0 p. `2 ]4 i  P. r$ v3 R! M
        // 超时,直接退出
7 y/ ^9 g& \: k! d' K) G7 J6 _        Timeout:% C7 o- y: f1 [1 D
        JMP  LeaveRing0
+ T, N. y1 ]; C- n        DriveReady:, D) o4 ~( m% y8 E
        RET9 v# q" e' r1 q
        ENDP   // End of WaitWhileBusy Procedure. d: X  v  G8 K$ k2 U  E
/ V& t& K  k* l- s' l
        // 设置主盘和从盘标志2 U" l1 s- H7 K* T7 W, Q; E' Y4 X1 A/ k
        SelectDevice proc
) X0 Z8 e) e. c! r. y. s
) I& Z0 N8 k! `7 Z        MOV  DX, dwBaseAddress
1 N0 e$ U4 l9 U        ADD  DX, 6
' m8 w2 _7 @! t$ Q) J0 K        MOV  AL, btMasterSlave0 W! v" X  y9 [- S4 p/ N

8 B1 q7 u2 c- x" x' n( q+ a3 y        out  DX, AL, A$ j) b9 G  V1 E6 W
        RET
5 K9 P2 c3 |8 b* b- E2 [! C3 R* O- f4 i( w" W, O
        ENDP  // End of SelectDevice Procedure
$ @2 `+ x3 Q: Z) v, C' V( Z- R
8 a: L9 N6 |  i3 j9 T. u" K        // 向IDE设备发送存取指令
; `# q& E+ U  |& j) P0 U        SendCmd proc3 z. m$ l4 o: n1 K+ L( G' r
% Q4 l( R: }( _4 }8 s+ r7 L
        MOV DX, dwBaseAddress
4 N! S$ [% z; k9 y! P8 e        ADD DX, 7% S  k  x0 a3 b$ u4 A) ]- K
        MOV AL, BL // BL是主从盘标识,在过程外设置
" z5 u/ |* T8 |% x        out DX, AL
' _! w) T/ k; m  h        RET
* J8 ^7 l- X' G! i        ENDP  // End of SendCmd Procedure
) |0 Y  ~: V% v* s2 q
5 I& i$ h. I% I) U3 T; B& g        // Ring0代码: y  O! F: d2 s8 U
        Ring0Proc:
5 }; C* O& U4 i$ b        PUSHAD2 y) l0 w! A/ M8 g1 m8 d# f
        // 查询IDE设备是否存在- ?' f  f6 R, p* U- b
        MOV DX, dwBaseAddress
' t: W1 }& B: k5 b7 E        ADD DX, 7' u3 G* j$ ?/ E( Q
        in  AL,DX3 V" h) x9 }9 {: |; n" f* d
: v: r' G6 O) ~" c4 p4 p; U
        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回% P* g" B7 x" `& N
        CMP AL,0xFF9 X9 \- v, g4 ~+ d4 v! b3 `
        JZ  LeaveRing0
. ]* B7 @! I/ x( u1 G5 \7 ]        CMP AL, 0x7F2 G$ m4 P5 c+ b% a* g+ H/ K
        JZ  LeaveRing0& }) s  R7 \. [/ z$ M0 z# D
6 }- c: J% D; _/ }
        // 设置IDE设备存在标志  f7 Q1 ]3 H' a1 k! d- z
        MOV btIsIDEExist, 1" w% w6 T& }  H

' G* W+ D; S1 c, L3 E9 _        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
6 H  Y+ ]5 p2 y* T6 `) p        CALL WaitWhileBusy
( C' @* Y3 [, {; l+ r        CALL SelectDevice8 w6 j7 K6 t) E9 f, w

* e; h. J3 y3 g4 _# h! V; v        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
" O: N4 L' j# C  ^! o1 e4 I        CMP  btIsFirst, 1
/ i, m( y4 |% i" a- Z" O        JZ   LeaveRing0. Y( K- q1 B1 C: Q
& }8 T* a, g8 i; ~
        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???$ v* C) @1 d# J5 N$ {
        CALL WaitWhileBusy2 W+ O0 Y6 [. W: A  {. z6 D9 Z+ ?
* D% i  v% s: C5 J/ N( y& |
        // AL的值等于cBit06时,不存在驱动器,直接返回
" Q4 q. S+ _4 o) p' `" G        TEST AL, btBit06
- \+ L! Z1 d/ _% L' Z        JZ   LeaveRing0' h+ c* Y7 V+ Y+ Y, E

7 O- G6 f! d. t' t        // 设置驱动器存在标志4 F+ ~  v( k3 @! U# i4 }
        MOV  btIsDiskExist, 1
  X4 U$ {' [5 a  C8 @! f, G% X# J1 H5 f- o
        // 发送存取端口命令" e5 Z6 B4 A, L! s9 Z8 P
        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
: z- h7 H8 `- p% a' l  M% J        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
2 ^8 O1 y# i' s: R9 J+ |2 G, X        CALL WaitWhileBusy( [8 F( ]" q. i) g  L
        CALL SelectDevice    // 设置主从盘标识8 a2 b8 ^7 v6 T$ @
        MOV  BL, btAtaCmd      // 发送读取命令
+ G/ i! b+ G! k* C' v        CALL SendCmd
0 m. ]  i' M  j2 ]/ C. o        CALL WaitWhileBusy. T; z1 ]9 h7 p& c1 L
, r" m$ I& J4 \( P" y$ K
        // 检查是否出错
( ~/ F  W1 W0 v" j$ `        MOV  DX, dwBaseAddress
- z& c; f& L- z) i        ADD  DX, 7
2 u  N# Z. ?- Y7 I. R* w. E" E* x$ m0 ~, G3 L! s
        in   AL, DX2 |0 f& y( g6 q) P6 e# ]
* e  o# y' p3 W# v7 }8 q
        TEST AL, btBit00
; F% y( H3 q1 g: e$ ^        JZ   RetrieveInfo   // 没有错误时则读数据
  t: x. F7 S" n2 I
0 K5 w" e1 u  p9 d        // 如果出错,则进一步尝试使用ATAPI设备命令, @7 ~4 ?, `" ~0 Z' O
        CALL WaitWhileBusy
# j0 h! F- ]/ ~& }; O, B7 j        CALL SelectDevice
7 h) e1 }' z; `  L        MOV  BL, btAtapiCmd
2 x+ ]) K- R- @$ T" A        CALL SendCmd) j3 D. i, G) _- n0 @- C
        CALL WaitWhileBusy
  S5 @2 H) L/ F- w  J) T
( h  g- `4 b) C6 z0 J9 E        // 检查是否还出错
/ n% O4 @/ |+ n$ M  T* K' Q9 p1 E        MOV  DX, dwBaseAddress
4 O" s% h; ^/ @; ^        ADD  DX, 7* J* S* E1 ~+ U! Y  @3 v" O
        in   AL, DX
0 J) X$ n! B: z3 U3 d4 u9 O        TEST AL, btBit00
% h6 A. z: o7 `2 M- B* R* @        JZ   RetrieveInfo   // 没有错误时则读数据% t9 W& p, _0 r5 d5 E
        JMP  LeaveRing0     // 如果还是出错,直接返回' O' K2 `- Z, p$ `

  `! X8 h- T. K: }. D9 Q* }0 N; R        // 读取数据
7 \$ _; U9 N7 U        RetrieveInfo:
+ W( f2 g  K  P2 u* L6 f* M
; d: F- V: {6 \2 S& l  d4 f8 J        LEA  EDI, wOutDataBuf  o) K% k2 h( x- }# `3 o& M
        MOV  ECX, 256
6 V# }7 C! W& d4 n: \) e4 Q% z        MOV  DX, dwBaseAddress
$ b0 |: a. @8 S9 h9 F; c- b) W        CLD4 E0 c  V* s+ S) M* m1 e- `7 E, _

& V0 n, k. [5 B* }" h        REP  INSW: S4 ^3 V+ r; s
7 S) s- z4 f6 a) w9 X# x, @5 W
        // 退出Ring0代码6 v1 P6 V8 o( g' U" }
        LeaveRing0:
! o7 C3 J8 o7 T9 X8 d$ Q8 j" ~' W) V- F1 y5 q5 M" I
        POPAD! V- g/ j" O" \# x! X/ c
        IRETD
( H* E2 v. n7 W7 s7 V: k, u6 e/ e: m* L9 Z3 Z
        // 激活Ring0代码
( n- U" \; U- S$ D9 b' m$ Z        EnterRing0:' `3 i9 K8 s1 e
- U& F# `% I3 v3 g9 _1 W6 b
        // 修改中断门
+ ?* d* g! O6 ~' g% U* X8 p        SIDT FWORD PTR btIDTR13 b! w5 y# V) r: p2 k8 ]( e+ P  I
        MOV EAX, DWORD PTR btIDTR1 + 02h
5 p# ~0 y$ k# T% y! q8 t        ADD EAX, nHookExceptionNo * 08h + 04h
* j2 O; m- a3 K% D4 E* Q        CLI
: Y6 T0 I7 J8 l0 ?  d* r$ L( |  j0 S* L( W6 s, I
        // 保存原异常处理例程入口
2 E. R2 D  }2 n" t: e! P/ `# |& K4 Q        MOV ECX, DWORD PTR [EAX]" c6 T2 E% n2 A( g
        MOV CX, WORD PTR [EAX-04h]" U) o" t. ]9 A7 y6 \+ ^
        MOV dwOldExceptionHook, ECX
9 G+ ~1 X7 L$ F7 y; s3 R
+ F" n1 D0 u: ^" U2 Z2 r        // 指定新入口% E2 @- d$ ?) f6 H, a: B0 y
        LEA EBX, Ring0Proc
( k% l% J  F! K( d        MOV WORD PTR [EAX-04h],BX
9 l; {# [4 B- l& N9 j        SHR EBX, 10h
6 l) N, c8 C% }        MOV WORD PTR[EAX+02h], BX! M9 ~- k7 j' J. @+ g0 z& w
. x* t7 Q- M! q
        // 激活Ring0代码# j. R7 n: ]# w% D
        INT nHookExceptionNo
9 `! ?/ C9 T# e' [* U
, u0 p! s: @6 ^        // 复原入口
$ ?1 B# p- I3 F+ S9 p        MOV ECX,dwOldExceptionHook
( a6 O4 M$ l( F5 j2 I        MOV WORD PTR[EAX-04h], CX* p: [: M' D# s1 d9 w
        SHR ECX,10h/ r; ?+ T- f& R5 A
        MOV WORD PTR[EAX+02h], CX7 p- M5 @! T) L! g* K3 w& o
        STI; a: w) S, ~6 b, o+ R
    }
/ H3 o7 u- f1 h- T7 U    if(!bIsFirst)
- T  t8 v: \' K. k    {, N! p( t0 h( A, O
        bIsIDEExist  = (bool)btIsIDEExist;
6 Z7 V. T, I) L6 q        bIsDiskExist = (bool)btIsDiskExist;6 m( I# L/ s0 a- r6 D
        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
9 \  m! r5 h' K" X( [/ Y, c    }$ m" I/ W7 I- z% a
}: o8 I* ~% u& Y3 K4 L
//---------------------------------------------------------------------------
) F! e  W" x4 W& ~+ U' S# l// 调用方法:
* E3 Q6 ]: G6 g+ ]; Jvoid __fastcall TForm1::Button1Click(TObject *Sender)3 k' e1 S6 X! m# {* Y
{
5 [. j* `, m" X' o+ W8 ]) u% F# J    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
% J" U$ ^! y3 c# a* u4 X" T+ l4 s}
/ u5 O3 [. U& F, b
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-8-17 10:46 , Processed in 0.024413 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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