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

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

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

  1. ( R# L* o, h% K! d. v* k& k4 W
  2. #include "StdAfx.h"0 h  H3 f: [! k* t4 M) {
  3. #include ".\puiddisk.h"
    " [8 u+ A/ H1 T4 h- Q
  4. #define _WIN32_DCOM( l, i3 B3 a$ y7 B  Q$ g1 s* y7 r
  5. #include <iostream>
    7 }+ ~* S+ v( N
  6. using namespace std;. G) s9 u) I- b! p4 {- q; L
  7. #include <comdef.h>
    7 f8 d6 Q8 @4 i
  8. #include <Wbemidl.h>/ s7 C1 _% C+ i& ?

  9. & H9 o1 d  T( f; R6 q, m4 M# |
  10. # pragma comment(lib, "wbemuuid.lib")
    7 p' z6 |3 N% U# \/ J
  11. CpuIDDisk::CpuIDDisk(void)2 g( L5 y( N3 i- o! Y
  12. {+ e& c. q6 W( D; j
  13.     GetInfomation();
    % o; Y% Y) ]2 M2 B) Y- U
  14. }
    + B7 ]& [; P3 n& K' k% p; T/ f, m4 n
  15. ( h5 x, d' O# x" X+ B2 w
  16. CpuIDDisk::~CpuIDDisk(void)
    ! d  c; W7 q- K7 y( M
  17. {; ^' L( F  Y" o% b' {1 H
  18. }
    ' _7 B- }" d, v1 U3 y! c! h
  19. int CpuIDDisk::GetInfomation(void)- p# r/ J3 ~; v; e/ W7 ~
  20. {9 p- j7 F: ]3 p+ ?2 p) A% z. w
  21.     HRESULT hres;; g1 h3 [+ P" p6 T" F
  22.     //步骤1:不是必须的,COM只须也只能初始化一次' @; f' v4 C  v, u3 T- P
  23.      hres =  CoInitializeEx(0, COINIT_MULTITHREADED );
    ! A" x  D0 k7 [6 L7 I* }3 i: |4 P
  24.     if (FAILED(hres))
    ' O. g  z8 S7 s1 e. s5 K
  25.     {. R; _4 ^4 ^7 s3 |& b7 k
  26.         return 1; //初始化COM异常:注意,COM只须也只能初始化一次& f4 |; {) X# P0 a# s8 j' G/ \
  27.     }) L& B0 U# w' s  E2 a% S1 n
  28.     //步骤2:不是必须的,COM只须也只能设置一次9 E$ Z  ]) Y+ h0 O8 `+ y$ N
  29.     //Set general COM security levels
    / {1 C2 u- t) B4 H
  30.     hres =  CoInitializeSecurity(! i) `# U7 V& r7 c; @, _, n
  31.         NULL, * e% q1 s/ j; l8 m& f" M5 I7 T0 w
  32.         -1,                          // COM authentication
    $ |9 v( G) y, X; {8 N% U/ {) [
  33.         NULL,                        // Authentication services
    , x3 e, p: B( j, u# x1 ~4 l# h
  34.         NULL,                        // Reserved# C; p0 o; d9 ?' m  _3 X+ U' l
  35.         RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication
    ( r6 ^; j% g/ R+ V1 D9 Y
  36.         RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  
    8 Q! _; s5 R0 z. o3 V. \+ [- r( Y
  37.         NULL,                        // Authentication info; V4 d& {% Y# c" |' B7 Z
  38.         EOAC_NONE,                   // Additional capabilities $ H; P* t5 i, y; Z9 O, U, Y8 M
  39.         NULL                         // Reserved
    ( |) n" |  P. u$ w
  40.         );! N# [1 @+ o, p1 y/ o
  41.                       9 k0 b# n- t: [& j9 e
  42.     if (FAILED(hres))
    : G: e; [, E. E9 d& i- K+ g
  43.     {0 d3 r) y' F1 |% A' l- V
  44.         CoUninitialize();
    8 x# `2 \$ T* C9 b
  45.         return 1;                    // Program has failed.
    2 g3 Z8 B2 Q- x. O/ M- \
  46.     }
      Y- ?" Y0 ~6 }- G
  47.    
    / n) d' s) {, g" C: x, K1 J- E( q
  48.     //以上不是必须的,若已有“::COMInit();”,则要跳过
    , M& a) n% x  m6 P
  49.     //步骤3: Obtain the initial locator to WMI
    & U9 a" t# x! t" z: D$ E0 G
  50.     IWbemLocator *pLoc = NULL;
    / M: F# P5 f' x: k+ C) W
  51.     hres = CoCreateInstance(
    5 z$ b8 l6 J8 ]( Y7 a; S
  52.         CLSID_WbemLocator,             0 a6 r1 D( i6 r3 |# Q; _4 S7 s
  53.         0, 4 f. j; {% B7 u, _" o3 C5 I& W& z
  54.         CLSCTX_INPROC_SERVER,
    ( \% s3 Z( [* _8 Z) u' w, t
  55.         IID_IWbemLocator, (LPVOID *) &pLoc);% d! r( k$ Y) s# W3 v
  56. 6 _0 \1 N4 g, ?; ~+ r* |2 A1 U% y
  57.     if (FAILED(hres))
    9 s# T7 C: z& ~, J( s' ]
  58.     {% p& m: `' v, }, ]1 z$ r9 W
  59.         CoUninitialize();
    $ a& k6 ], E9 X/ `3 H$ I. ~$ {+ Q
  60.         return 1;//Failed to create IWbemLocator object7 g( u0 {; e. v5 e) l0 b
  61.     }0 o3 F  \; p4 x

  62. 2 n7 d: X9 W, N1 N0 d
  63.     //步骤4:Connect to WMI through the IWbemLocator::ConnectServer method, F+ T8 e7 S3 I1 x) E# w
  64.     IWbemServices *pSvc = NULL;
    : D' f8 a8 t! }# u& x( t" `
  65.     hres = pLoc->ConnectServer(
    * v& D' `0 |3 {0 f
  66.          _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace7 k0 n2 y( Q- h
  67.          NULL,                    // User name. NULL = current user4 q* y( y: j/ N$ R% i1 `7 y
  68.          NULL,                    // User password. NULL = current# ?! H" D& g" z( _$ g# N" G
  69.          0,                       // Locale. NULL indicates current
    : n- d- W; R& Q
  70.          NULL,                    // Security flags.
    , R* d4 x0 W4 M" m* s4 O8 L
  71.          0,                       // Authority (e.g. Kerberos)
    , ]* ^4 o/ y7 h, K3 v* [
  72.          0,                       // Context object - H5 j6 K2 u! Q4 j# T
  73.          &pSvc                    // pointer to IWbemServices proxy9 M+ z; |8 {9 v) L" r
  74.          );
      V( Q0 Q  e0 ^9 E; l
  75.    
    3 g3 m- q; R9 ^5 |
  76.     if (FAILED(hres))
    ! `: p$ V! D: a: s
  77.     {
    ; z; k0 [: H6 N0 `) {4 ?
  78.         pLoc->Release();     
    3 U" ~0 p) [# L# q8 a5 \
  79.         CoUninitialize();) J; B  p3 ~6 O  P* X
  80.         return 1;                // Program has failed.1 x# Q: x" Y+ M) T" G( C* x  y' Q
  81.     }* l' \/ ~+ L: ^8 i9 [
  82.     // 步骤5: Set security levels on the proxy
    $ K( T5 n6 S  Z- j! a( O; f( \
  83.     hres = CoSetProxyBlanket(
    7 ?# m5 @0 g, R& i$ }! O. ]
  84.        pSvc,                        // Indicates the proxy to set+ [- U% L$ g0 A+ q4 b+ {* `
  85.        RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx3 j# F( o! D! o
  86.        RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx
    + _1 j2 V6 o8 |' ^% n3 k
  87.        NULL,                        // Server principal name " q! t# f/ b; Y/ p7 f( r3 v
  88.        RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx   I' ]0 |5 ~, F6 L1 v$ x
  89.        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx( N" B' H" g# I' s
  90.        NULL,                        // client identity4 x  N+ W! g0 Z& x" O% H% Z
  91.        EOAC_NONE                    // proxy capabilities 5 b' m, L/ F- F" F" Y$ T) v' Z9 i+ s, a
  92.     );
    ! i$ e  V# ^7 }' j
  93. / Z( ^) G2 y3 t6 ~! O7 S7 k
  94.     if (FAILED(hres))
    , [6 P% F7 X8 B) y! G$ O/ D0 U/ f  M
  95.     {# k# P" j+ s5 A
  96.         pSvc->Release();
    + w. Q3 Z$ z1 U, c+ @6 E9 T! k( @
  97.         pLoc->Release();     3 q& j/ |! n  _9 \. y
  98.         CoUninitialize();
    ) {# ]3 Q' h8 B  j' m; B1 l
  99.         return 1; 0 e0 V- g1 r" ?1 J; ^( X
  100.     }
    / F7 [( n2 b. b

  101. . d$ c% X( g# g: |
  102.     // 步骤6:Use the IWbemServices pointer to make requests of WMI ----
    # A& `, D1 X6 c, U
  103.     IEnumWbemClassObject* pEnumerator = NULL;. u3 T' I: Y9 f" D! @. s4 u
  104.     //计算CPUID+ F! q5 ^5 c, N# T! W: P" k
  105.     hres = pSvc->ExecQuery(
    ) o0 v1 q) ]0 I
  106.         bstr_t("WQL"),
    , O9 P4 t( n( S1 `1 T
  107.         bstr_t("SELECT * FROM Win32_Processor"),//Win32_OperatingSystem
    , n, b2 n# \( B2 \1 E4 O
  108.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, ( g4 S9 ~. J, A/ m; c
  109.         NULL,
    3 v! z7 `% ?. G1 q7 Y
  110.         &pEnumerator);
    3 r& L) s# V1 U$ H
  111.    
    2 g; y5 q, F3 s4 k% K5 y# s. P
  112.     if (FAILED(hres))
      u& s9 M; t/ T$ Z7 y5 Y
  113.     {
    6 c* M) L$ S7 i) s* L
  114.         pSvc->Release();
    / W/ i6 E/ e+ X6 \
  115.         pLoc->Release();" J6 H: g; C$ m2 G9 S% ]" g
  116.         CoUninitialize();: ~6 W5 H$ S% h1 O5 j
  117.         return 1;
    / g/ R8 I4 b; t7 F6 }
  118.     }
    2 _" \6 M5 i7 p+ |- H3 M) G& i% Z2 ^
  119.     // 步骤7:Get the data from the query " [4 J& e4 [9 R6 Y7 W, e& _
  120.     IWbemClassObject *pclsObj;
    $ ?& t1 T9 u- Y, [6 D3 f' |
  121.     ULONG uReturn = 0;9 m' x; |4 t: i0 e- |) P5 i, d; M& q, U
  122.     while (pEnumerator)5 G* Q5 |; p3 U3 q  u# f4 @1 D
  123.     {
    , z( Z- L7 W3 B! P2 f+ S
  124.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, 5 q# a1 c% [6 Z$ ~9 ]
  125.             &pclsObj, &uReturn);- }( S8 L! x$ g6 ^9 k

  126. + J; A8 G# F1 e. s- w' O$ F
  127.         if(0 == uReturn)
    $ m8 Y! \# w, z$ |
  128.         {! v5 M1 @6 @+ }' R9 }6 r
  129.             break;
    * u, }4 v6 h) ?
  130.         }: w7 A% a. O/ q0 n  u
  131.         VARIANT vtProp;
    ' Z; Z, ~$ j& d  e/ Q
  132.         VariantInit(&vtProp);
    ' \8 P: f7 f6 K# |, ?( X) D
  133.         hr = pclsObj->Get(L"ProcessorId", 0, &vtProp, 0, 0);
    ( H& o" q4 N9 w
  134.         strProcessID=_com_util::ConvertBSTRToString(vtProp.bstrVal);//strProcessID:类级变量
    7 d7 ]9 }: r" Q5 }
  135.     }
    5 u$ c1 z2 r; R5 Z, a
  136. 7 q! f8 y5 m+ o! r) e* Q
  137.     //计算硬盘系列号
    * U5 C* N8 t) u6 t3 n" l
  138.     hres = pSvc->ExecQuery(
    0 Q6 o3 w8 k* J: j
  139.         bstr_t("WQL"), ) ~; B/ M0 o6 X  l
  140.         bstr_t("SELECT * FROM Win32_DiskDrive"),
    ; v2 _; Y+ a" y& c- z/ Z
  141.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, ) s% M+ S! A5 {! j1 E
  142.         NULL,
    7 m% Q, r, }3 K! \6 I
  143.         &pEnumerator);
    6 a. y% z/ M& C% T0 `. r
  144. 3 }3 l* F0 E, L! ?
  145.     if (FAILED(hres))
    + p) R5 L4 o3 G* J' l
  146.     {
    & F  r6 @" }5 Z, L  h
  147.         pSvc->Release();
    7 Y: W: P+ l+ V2 O+ J
  148.         pLoc->Release();
    . ^0 a: u$ a; Z; M- Y4 J$ n
  149.         CoUninitialize();" w1 H$ u" i, e% O% O: o; a4 t
  150.         return 1; ( h" A* f" L) j, K. G2 ^
  151.     }
    * y* f- p% a% K. L- F& g6 E
  152.     while (pEnumerator)
    ; ]+ u/ {" z8 L) u% d7 P
  153.     {  _2 ?6 g* b- t) Q' l
  154.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
    ) v' O2 r& ~# D- F% U
  155.             &pclsObj, &uReturn);8 U- u( \9 l) ?7 ^: [" [( G4 W

  156. ; e! p  w% F+ z
  157.         if(0 == uReturn)$ h' V% ?+ S1 f! @9 l7 m: K" _
  158.         {
    * a2 W9 P6 |1 l
  159.             break;( a: v2 r$ y5 I; w7 j
  160.         }
    6 F+ |( s2 P$ R- k; X3 P* ]& _* ^
  161. 0 Y( K3 \0 G" J6 u9 Y5 {
  162.         VARIANT vtProp;  h, r$ u: Z& Q; R
  163.         VariantInit(&vtProp);) a, u* _  M7 Z
  164.         hr = pclsObj->Get(L"PNPDeviceID", 0, &vtProp, 0, 0);$ K6 w' N7 t# k4 }( h3 A" A! e
  165.     strDisk=_com_util::ConvertBSTRToString(vtProp.bstrVal);
    5 O' e# f2 Y+ {$ z
  166.     }
    . _' G$ C3 {5 T; h
  167. 6 H, t9 ?* |& t' `! U  ]9 |
  168.     pSvc->Release();
    6 B, A3 q& m0 r" G
  169.     pLoc->Release();
    0 ]# u9 d( Q9 ~5 C5 ]
  170.     pEnumerator->Release();2 q9 U5 g, w# i0 T
  171.     pclsObj->Release();
    ; |; e' N, _' x) }# t& c7 W0 v! _
  172.     CoUninitialize();$ Z# h4 d. T! A  m( t5 b+ u

  173. 6 x* Q4 O8 E  H8 @; j
  174.     return 0;   
    6 [, G8 K" {% _
  175. }; y( ^3 a+ G! o, J. F
复制代码
 楼主| 发表于 2010-10-11 19:21:05 | 显示全部楼层
本文代码经ccrun(老妖)在Win2k下试验成功.
* w9 {) G: f% y3 |5 n& J4 n7 _7 Q0 q% Z/ D$ f% [7 K
#include <WinIOCtl.h>& _7 `, p4 a* p
#include <stdio.h>
8 h1 X4 \* ]! b
7 |4 l; s4 F3 V* L% z" }4 p#pragma inline
( E4 `# `, @) `7 L% [9 v  |0 S//---------------------------------------------------------------------------2 H. `: M# p' X# _" G. J8 q
// IDE NT/2000/XP专用变量3 m, o% q+ F* {! f2 P1 E' _
#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS; _: o9 x; G, |. K& ?& i: u
#define DFP_GET_VERSION         SMART_GET_VERSION9 p: `; k5 D# b/ W$ X& A
#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND4 ?7 Z7 Q, ~; v! O& H. z
#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA5 N2 T( _* C5 W: ^$ D
# k. _/ Q1 N1 a, Y
const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令& Z  N- n7 X, l# a  G
const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令% @+ Y- {  i& B

; _% V( a' P3 x1 z4 N( x3 sconst int MAX_IDE_DRIVES = 4;' O7 o4 Q1 r: T0 g1 M! W

3 @4 F- c) J* B" f" R// SCSI专用变量
6 N) J/ p: ^. |% @; l3 Oconst DWORD FILE_DEVICE_SCSI             = 0x0000001B;0 H" J& P2 K2 Y! |- P. d
const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);8 Q0 F8 y. s) K* @
const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition6 U  n- a* x( k- n
const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;5 a7 q( A" t/ k  l1 R, `2 o: g1 r
" |$ Q5 W3 d/ t0 Y
typedef struct _SRB_IO_CONTROL0 s+ E) `7 e; v1 a9 V  p4 }
{
8 s5 o! E" y) e/ g    ULONG HeaderLength;: Z( }! n4 b- C  Y" w
    UCHAR Signature[8];
# o8 J6 D) K" J: V: h3 ]6 Q    ULONG Timeout;
* Z, t7 }( z0 [+ h9 ]    ULONG ControlCode;3 N2 F: v8 ]2 W1 P- \! {
    ULONG ReturnCode;
0 J6 U6 G- y- \5 z( x* Y    ULONG Length;2 e5 e. P) l1 j4 h; r3 I
}SRB_IO_CONTROL, *PSRB_IO_CONTROL;
3 ~7 y6 z" J0 l, B8 p! n. m2 J; m0 D9 c8 I% a. x5 f
// 读取的主函数  t* J3 c9 I4 V  P- f
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
7 Z% N5 x, s, k- w- w) j
/ Z1 A# U3 W- {& p: ~: Q4 X) I8 F7 X// 辅助函数! ~8 J& h( R' E% T0 R7 U
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
7 C5 S/ H# \! t8 S8 ]: x// NT/2000/XP函数
" C. K6 T4 O/ r5 {/ wvoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);- O4 x8 C* O- @& O
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,1 q, e& r" H% T/ N/ N
        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
& e% ?' ^9 |: q8 e! C( Y3 L: h        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
' D  j+ L7 o, a1 C! S// Windows 9X函数
- `7 v  T- ]* T4 Rvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);, T1 }! |1 u4 l! u
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,$ d( X; T$ h" H9 r2 W; |
        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
8 a5 n6 s6 Q( N. a( u0 q# b0 `. N
& @* I1 @4 L  @7 c// SCSI读取函数(for NT/2000/XP)/ E7 M. i0 V  C/ K+ p/ b6 B# O8 A
String __fastcall ReadIDEDriveAsScsiDriveOnNT();5 S/ }3 e1 t) \
//---------------------------------------------------------------------------
- W; r. P/ D/ O// ReadPhysicalDrive+ z0 H: a6 C* q$ C7 O6 R/ |# n7 H
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
) U* @( q+ ]8 ^' Y{5 q8 m  g8 L6 z/ d
    switch(Win32Platform)
  V$ f# B3 J- w4 L1 h" ?    {
# v. {/ C6 A% b4 N! _        case VER_PLATFORM_WIN32_WINDOWS:
5 l3 L8 `) l. a* ^; d            ReadPhysicalDriveOnW9X(pSerList, pModeList);
) J4 E1 S+ u( [! H, U& L            break;
* R* ?1 y+ y# r: K0 f* P2 m4 g6 c+ z        case VER_PLATFORM_WIN32_NT:& E: X- v: E8 N- J7 g% e2 Q
            ReadPhysicalDriveOnNT(pSerList, pModeList);" m: w0 |9 @5 ^1 L6 V' H: [# o
            break;
5 R) u4 q  O5 K        default:
0 g2 |" g) X/ d* C5 H: a            break;& m! s( X9 r. y: g
    }
# ^8 ?# i# b8 X# y}6 r& t. s' t* I6 b) e5 X
//---------------------------------------------------------------------------2 e" H; a* Y. \9 \
// ConvertToString/ g; Q* j0 _8 ^. n" c
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex), u5 b( T% E; h9 S0 M3 _/ i9 `
{. _: [$ ]1 ^5 @' h2 f* H+ `9 T
    static char szResBuf[1024];
6 G) x: Y2 V  Z' g" X7 a: w# S6 F    int nIndex = 0;
+ S6 @% |$ A  ^! d9 ?    int nPosition = 0;
- ?, m  o# u- ~) t8 o7 v
8 o  y; i# C7 }/ M$ N- a    // Each integer has two characters stored in it backwards2 w0 b$ D! q2 p5 E( y
    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)# A* P* w1 f6 j, Y1 H$ F
    {; x5 X3 I! X5 T7 o3 @
        // Get high BYTE for 1st character
- |) C& @3 w* ?/ o4 ^        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);0 v0 z- D0 N  t. f' C0 V
        nPosition++;
( M/ w, M* k% V- d4 o/ m: B7 d( F" W. b' u: w3 X5 M
        // Get low BYTE for 2nd character
0 T6 ~. |% ]# @9 G4 v) h        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
' o0 Q. d0 ^  ^3 `+ n2 _2 M  `) \        nPosition++;
' C) W$ j5 I* R5 u    }
! D3 @6 Z9 i. h7 Y$ Y
# N1 b# v) k! _: g, u    // End the string" f7 S1 d) K+ k( ~7 D- S
    szResBuf[nPosition] = '\0';7 a/ X0 E# W9 v. T
1 ?3 V! T' j3 W* r) w
    // Cut off the trailing blanks
, Q6 `+ \3 A  @' o2 S7 U7 h% u    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
1 J+ D( ?3 s' H) B% F        szResBuf[nIndex] = '\0';
6 H3 i# r' n1 P% A# \2 G0 v6 [
) ~! s; @! G/ C5 E" Y3 Y    return szResBuf;8 f, k, ?7 Y" j, ]) }
}+ ~. b& f5 d! A
//---------------------------------------------------------------------------; ]' h$ e/ _6 p3 x
// Winndows NT4/2000/XP 代码
' E2 l' A% B5 S9 a/ }9 P; P//---------------------------------------------------------------------------# u) K$ r9 p4 Y
// ReadPhysicalDriveOnNT
; \) C. H5 U! c8 X# p# Z  Evoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)/ r% v+ K- ~" ]5 Y, I3 y( _
{! x5 J7 U1 P# e% Z& e
    // 输出参数, J& `& G% C- o6 y( ~5 Z" N" ~
    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
5 C9 z( Q6 A; G% T8 z
5 k, Z0 a/ f/ ^    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
% P, C, h. U5 ]: |0 X) p4 t  p    {; ]: U) _: r. ~
        HANDLE hPhysicalDriveIOCTL;: |2 M' T. v5 O
        char szDriveName[32];
7 @. b  F  F7 F; t! p* V2 S8 A! y! ]0 N
        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
. c# n8 ?: t; g7 k        hPhysicalDriveIOCTL = CreateFile(szDriveName,
6 l" [: \0 v" o. o                        GENERIC_READ | GENERIC_WRITE,
) o! z6 F) R0 G4 x8 l                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
% w$ K6 X$ m6 ]5 R* n' T                        OPEN_EXISTING, 0, NULL);
" a( u* V3 p+ W: s- i; C% J9 d: N  v1 _
        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE); c7 y7 q* M! M+ ~# {4 g
        {% ]; M: t: [1 `4 D% j
            DWORD dwBytesReturned = 0;
) K9 Z, c/ u- n1 O+ x1 o4 k( n$ t0 B            GETVERSIONOUTPARAMS gvopVersionParams;% J9 I: ?. l$ f4 w& q$ C
% M& l3 r- M, ~* ^5 {  i$ ?9 d/ U
            // Get the version, etc of PhysicalDrive IOCTL$ K& a+ ^. [  `6 T/ }0 @
            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
  }* l, {6 h. H4 ]
# I: g2 X0 a5 l9 Z9 Q            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
8 F; w) r3 H7 b3 h3 \# n2 a, L1 {                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
& a: P; b8 Y3 X( e  W                    &dwBytesReturned, NULL))( a# ~: e! Y2 K- n6 ~" w
            {
7 @& P9 w  ?6 Z5 ~! W2 A  l' P) ~                continue;
  |2 t3 l2 G7 M7 z8 t  j            }+ _8 p  d. |! w4 g  F/ t( u

1 M  b, o( A. X  v$ k            if(gvopVersionParams.bIDEDeviceMap > 0)( K# ?+ f, T* ~$ I0 W2 p
            {2 o/ N! d9 p6 {) Q% V% M9 R
                // IDE or ATAPI IDENTIFY cmd
1 S% s3 h; r$ W# T+ A9 x: P& n                BYTE btIDCmd = 0;8 O$ d& K) N; V# M7 [7 k: F6 b: I, _
                SENDCMDINPARAMS InParams;
. W  R7 D* e8 ~                // Now, get the ID sector for all IDE devices in the system.
1 [9 g% u9 x! g$ |                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,& ?$ @( X: d/ G
                // otherwise use the IDE_ATA_IDENTIFY command' ^2 a$ u  y0 @- s3 `" }
                // 具体所得结果请参考头文件中的说明
  V3 @) e+ m0 F3 ~                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
0 E2 |- j/ G- ]                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;' T5 }2 g6 y1 p. H3 n
                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
: _# P8 T" H0 E& P5 G% b" k                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
$ O1 K# a# l- h8 g' o( T+ |6 m# ^. V* Z  J8 [
                if(DoIdentify(hPhysicalDriveIOCTL,  D) Z8 d3 ?9 E/ E5 W6 R
                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,' L* i- p; W* Y8 Q
                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
& V" Y+ P9 d. }8 v+ ?                {. Y) p, _0 \+ g7 f; K2 b
                    DWORD dwDiskData[256];
- a. b& [: |4 V; o                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
8 O. w. d; d" m1 s. o. F# f                    char szSerialNumber[21];  X( @' y4 E" }8 y8 I6 U. W# c- n5 W
                    char szModelNumber[41];# F+ i5 N1 ]& d" N
( f  E% d2 M- F6 f* C, @1 Z
                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
' P. z4 x# E9 J# H                    for(int i=0; i < 256; i++): V  Y. k0 ^1 b' Y# y
                        dwDiskData[i] = pIDSector[i];
& b& I2 w% `9 `$ {/ I0 Q                    // 取系列号0 T1 e. [5 L8 x# b5 `
                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
4 A0 G  ^! P# k+ {+ _/ @                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
6 ^: I, K# v/ i1 w9 G  q0 S& }, r+ M
                    // 取模型号  e# Z# B/ J5 @3 Z
                    ZeroMemory(szModelNumber, sizeof(szModelNumber));) {. e2 ?2 m( t5 ]" o
                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
9 p5 W3 e$ d  e0 ]0 Q5 a% m) M$ y+ m$ h2 M
                    pSerList->Add(szSerialNumber);
3 T' u4 i& P, A  Q                    pModeList->Add(szModelNumber);4 E1 R1 O3 o, o
                }. L7 d! H; H0 f( g( `* }4 s
            }
/ i) |1 U# N* N: X5 [; s, E            CloseHandle (hPhysicalDriveIOCTL);' f0 y# _2 Y! ]0 j2 I$ |' u2 P
        }% o5 C1 O6 @) e3 j6 B% K0 X
    }
6 ^1 x9 V& W8 J) p+ J9 F+ ^}
0 i( Y. n7 X+ y, J  _2 U  ?//---------------------------------------------------------------------------
, g4 R% f0 F  Y) b// DoIdentify
  Y9 G' P+ N3 K2 i& Q1 _bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,3 v( }) U! l+ |. }2 C
              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
; r2 @+ t5 b6 K: E$ A/ @              PDWORD pdwBytesReturned)
  h7 G' y  O$ V% B  d8 T{  F- b# [. R9 w) o: q3 h) E0 T% i+ D
    // Set up data structures for IDENTIFY command.3 z, J' L; W9 `: c  p( T  X3 F
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
. I/ V5 I) G) `    pSCIP->irDriveRegs.bFeaturesReg = 0;! z3 m4 D6 F' @# V! h
    pSCIP->irDriveRegs.bSectorCountReg  = 1;
: k4 j2 }6 E! g* t    pSCIP->irDriveRegs.bSectorNumberReg = 1;
' _* B8 _: f- d% w3 M1 a# {7 b    pSCIP->irDriveRegs.bCylLowReg  = 0;
/ q9 I' c( ?1 l+ i  G% o7 F( t    pSCIP->irDriveRegs.bCylHighReg = 0;% F' i/ m6 z# ~' M

8 T3 `! b0 z! I. z    // Compute the drive number.(主盘和从盘所对应的值是不一样的)
) V. C9 I/ J1 A" m    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;# t, c6 d. b& }* y0 S& W+ i0 B6 `
$ i' x! g& D" e+ h7 s, S( M
    // The command can either be IDE identify or ATAPI identify.
/ F6 l) z0 \8 o' }/ c    pSCIP->irDriveRegs.bCommandReg = btIDCmd;
. t" H) G: `: s9 J) a# H* |  d8 K    pSCIP->bDriveNumber = btDriveNum;* N" E: _' Y  }) S/ z
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;6 L3 A& V, D0 A. G. A

$ L* i' w7 O$ I    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
+ e4 F2 r0 t7 b           (LPVOID)pSCIP,
- {9 a! f( p/ `0 f5 E           sizeof(SENDCMDINPARAMS) - 1,
  |. B" S; I. N" o           (LPVOID)pSCOP,
/ G$ X# t3 I& P) y, S7 M           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
2 T9 @6 a" {6 n# R+ B           pdwBytesReturned, NULL);/ Y  Y# o# y5 R! Q3 u; x( M0 R
}3 F6 y1 Q+ I0 g7 @; {  p
//---------------------------------------------------------------------------- ^0 T  u7 H' h  @- W( Z% k
// Windows 95/98/ME 代码. f1 ]1 a' ]3 d8 ^0 @3 z
//---------------------------------------------------------------------------
  X- y7 p5 d- L+ R// ReadPhysicalDriveOnW9X5 b  K6 k4 p7 Q% c& E
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)- ^% W+ X& ^# G1 }9 {6 ^* _
{
/ F) Y5 f- z9 ~9 [$ J    WORD wOutData[256];
  q8 h+ ^- c8 I    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
  u9 z2 W" g) ?$ v1 ^& u" s/ K
+ f6 c. R4 y. @# v4 j( o! m" t    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。# M0 Q) X& M0 i
    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以' k* E# m- W0 X% H, E& R3 m, |
    // 避免蓝屏的出现。(期待高人能指出原因)) {. ^0 }1 G& y# V/ ?# a9 j
    for(int nDrive = 0; nDrive < 8; nDrive++)  }6 t2 s8 H4 S
    {( a9 \( ^2 ^+ \/ z
        WORD dwBaseAddress;/ l' m9 x) d1 H; m% M  z- |; o% v
        BYTE btMasterSlave;         // Master Or Slave# S' D+ t2 q  q& g! L+ R8 Z; f
        bool bIsIDEExist;" h7 }1 x7 A; b+ b+ m3 h
        bool IsDiskExist;
, g  t* i5 ?5 V) T! Q9 h
+ w) K! z) ^" O) Z5 S. p" ]1 _! @        switch(nDrive / 2)
8 }# {6 |3 S$ w7 M: d; u! R        {
2 `3 P  P8 v5 v            case 0: dwBaseAddress = 0x01F0; break;
; q* w/ M5 j; _: @  f            case 1: dwBaseAddress = 0x0170; break;6 e3 ~3 {7 a; U) `8 F& E* t
            case 2: dwBaseAddress = 0x01E8; break;2 r7 F9 H7 B0 |1 c* f' p
            case 3: dwBaseAddress = 0x0168; break;7 ^( _0 G' E' |9 \. I/ W* Y
        }9 ?0 G/ `: r2 v" r# I
5 v7 V+ x! _1 p+ A# B3 q
        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
; A) T5 y7 Q2 {. S9 j: l+ h4 h, B
9 j: p  \8 z4 V  ^: _        // 进入Ring06 ~' R! j9 r& {
        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
, K5 h2 r/ u4 v. r( r( f1 k. l                bIsIDEExist, IsDiskExist, wOutData);9 g4 k2 T9 @$ ?$ `3 u& W6 b
    }. i6 C$ {% L/ U% g/ Q( @
  H2 [, w+ L8 k% W/ _7 u& v* s( ~7 P
    // 开始读取, p& X1 f/ P2 C' n0 T( C/ _
    for(int nDrive = 0; nDrive < 8; nDrive++)
( A& K" o* I* i* Y0 ~    {
6 a. Q  O  K" k! Y) s: x        WORD dwBaseAddress;
2 F! e+ M/ q) Z. M        BYTE btMasterSlave;         // Master Or Slave
; E0 b3 I3 u! b& w        bool bIsIDEExist;/ O$ N( x* p- R' p9 U* ?- }
        bool bIsDiskExist;: [- }1 {$ A- c" o$ i( S% t
        switch(nDrive / 2)4 P" S7 }2 V1 \# T+ s: h, D
        {
2 y  w1 [9 \$ ?! e  L            case 0: dwBaseAddress = 0x01F0; break;/ {$ z' `: p3 b8 S
            case 1: dwBaseAddress = 0x0170; break;
6 h) w7 ]( G1 {: {4 |$ }! u            case 2: dwBaseAddress = 0x01E8; break;) j- }5 I* D/ N: U  _% k
            case 3: dwBaseAddress = 0x0168; break;' h. u- B3 F* l9 e" h* g$ n; O8 t
        }# f" f# U% c& N* r# n! v% U1 m, I5 O

) U6 D. c& c8 ]. _, u/ k        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);+ G+ F" t  K* U( l" y: h

2 Q' f0 M, r- q5 {) I        // 进入Ring0
$ `5 J* B; I7 [& y  M        bIsIDEExist  = false;
- g" ^0 ?. y* p; m" k4 D+ }* c( m        bIsDiskExist = false;) D; T' c$ A! U0 Y  D7 G0 i/ z$ H4 e
        ZeroMemory(wOutData, sizeof(wOutData));
. S- a3 d8 ?, e# L; q0 Q8 s4 M
/ H$ |! P" Q, r4 G        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
$ @$ O7 p) y# V) `                bIsIDEExist, bIsDiskExist, wOutData);
+ j- r, i/ v6 B+ {% j0 S+ R7 {
! I" Y6 I* |# a2 j& A& s# `        if(bIsIDEExist && bIsDiskExist)" h0 F6 [7 I7 L5 _( S
        {
& w5 H7 r! B- _- [            DWORD dwDiskData[256];
6 l: K2 g. S' H- S( f( d, p            char  szSerialNumber[21];
0 h2 y! i! e1 k6 i            char  szModelNumber[41];
1 n) q# U+ g9 ?( O3 B9 v
6 O" V" |. O! p1 X% g- U            for(int k=0; k < 256; k++)8 X3 \' I& _2 a8 ~* ?- T! c" p
                dwDiskData[k] = wOutData[k];
# `0 L1 _! l6 w; }/ K
+ R7 ^; L& f4 F3 R( Z            // 取系列号( m0 k1 I- r' ^% P4 s
            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));, u2 y2 n+ l9 @9 m$ h
            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));# u8 b/ |8 m6 `# T' |
0 V4 @7 o6 _* S- R
            // 取模型号
. ^8 ]5 ]6 e# _! W            ZeroMemory(szModelNumber, sizeof(szModelNumber));' n* X* }( \  {( S+ e
            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));7 v% S% A. z% r$ e8 B0 I- K4 l

8 z- Z, m$ z# ~- b            pSerList->Add(szSerialNumber);
) X; r  V% R. W$ s            pModeList->Add(szModelNumber);
8 n! ~' R2 B+ F" x; B7 ^        }7 \& ^/ `0 Q3 j4 v- E+ {( M
    }
  _$ v% n  O, G# C5 S    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
& M7 t: T: l8 e7 ?- n. |( r) r}& m& D3 f5 B8 Y- C, ?
//---------------------------------------------------------------------------3 {; q! N$ k! v$ |
// 为防止不负责任的转载者,在此注明原出处信息,请见谅。3 [: a7 S3 q$ U& E+ D6 b5 S+ @
// 资料收集整理:ccrun(老妖),欢迎光临C++Builder研究: http://www.ccrun.com
& |2 ]. _* [* c' Z8 g' M! Y) y//---------------------------------------------------------------------------. v. ?) X2 ?+ P
// ReadPhysicalDriveOnW9X_Ring0()3 [4 A* [' d$ U& _4 r4 p: O
//
3 P6 n/ W$ l% H4 k7 A: ^// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
+ ^" z* O6 i7 }# \" [// btMasterSlave = Master(0xA0) Or Slave(0xB0); G/ J/ x8 l4 \) L
//---------------------------------------------------------------------------
+ T  ]( e" o* M2 z  zvoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,% \" \( L/ Z; g9 u; h( m
        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
) i* v% h% S; [! R! ~$ M{- C2 H0 ]; S  F
    BYTE  btIDTR1[6];
8 M# _6 i8 t+ a$ Z    DWORD dwOldExceptionHook;9 I! C* G# x- L/ F9 G. R' `
    const int nHookExceptionNo = 5;4 t$ y; P  w: p

4 @' ]+ y8 D& z2 X2 W8 k    BYTE  btIsIDEExist = 0;
5 g% l+ T+ {! L, Z9 s& `" a    BYTE  btIsDiskExist = 0;3 ^  Z/ l$ ~6 s$ O7 _7 x
    WORD  wOutDataBuf[256];
1 M. ]1 f: h- h: N: i' W
4 t; O: Z% _9 z! r    BYTE  btIsFirst = (BYTE)bIsFirst;/ b8 R& F$ w% X! ^: g, S3 X

: r# Q- R8 _& O# V8 x+ S- p1 t    const BYTE btBit00 = 0x01;5 \: f7 X. y4 X0 C! v, h2 Z
    // const BYTE btBit02 = 0x04;
2 p4 R: n! T# g7 F. g# z    const BYTE btBit06 = 0x40;9 \3 Y" x/ I4 H# ^
    const BYTE btBit07 = 0x80;$ J7 j3 ?$ P, R2 J/ z" i) g
    // const BYTE btERR  = btBit00;
7 h8 R+ b/ C$ Y- J5 A% H# B, {    const BYTE btBusy = btBit07;# ?. c8 C& x  x* v, b  t
    const BYTE btAtaCmd   = 0xEC;& l# n) j8 z7 n  J- }
    const BYTE btAtapiCmd = 0xA1;. L( @0 ?+ J9 u4 @& q* U
0 j/ l3 u7 }+ e" [; {8 f$ f1 i- r4 \
    __asm4 `5 ]9 e+ r7 D+ t3 H
    {
0 j  O1 Z9 B" i$ p& B1 M        // 必须先执行这条语句. y0 H, o( O. f7 v. l
        JMP EnterRing0
8 n" d! i1 Q8 n1 G& \( ?' x/ }9 [) n
/ ~9 `, r7 c+ }0 {( d. J# r        // 定义过程( r) @$ b  J9 a  F- K& h; Y
        // 等待IDE设备直到其不为忙为止
* y+ J+ m) p; i& D4 O* L        WaitWhileBusy proc
. T, Q+ h3 {/ T: R4 s+ \2 j3 p+ i6 {
        MOV  EBX, 1000001 P1 C3 f) y  d
        MOV  DX, dwBaseAddress3 i, k# m) D* c1 U. _( ?
        ADD  DX, 75 v0 f/ _6 k( V, a6 s
- X* y5 c+ {4 x# @
        LoopWhileBusy:* Q9 P. c; m& q) M- w  K& f) B! g
5 H, C& U: r! @1 h3 K
        DEC  EBX! H* M! \" x9 w+ F. x1 t
        CMP  EBX, 0. f* M; r2 Z! z, Z, j( M
        JZ   Timeout9 R7 Q5 C7 s) D; c6 L, K9 J$ v
        in   AL, DX) y) m1 V% W& U( T( Q, @& d* ?
        TEST AL, btBusy
9 Q  ~' ]0 \4 r6 B1 V0 T        JNZ  LoopWhileBusy
! m' H! S- r$ ?4 Q2 F; |  a0 z        JMP  DriveReady
, j# E& C4 a% x3 t$ W9 B  c, p, t: p2 I; C. r7 n
        // 超时,直接退出8 V4 ?  h* e' P3 Z- \- h8 a
        Timeout:
' B( ^/ }7 D; g! q4 c        JMP  LeaveRing0
- n( N  K8 K: C; T        DriveReady:! f+ u" H: `0 q2 ~5 n$ y  W  K/ W
        RET
! `3 p& j6 x! g+ H! [  X) U: g        ENDP   // End of WaitWhileBusy Procedure
" _! \! }6 d5 I
2 h) ]: G' d  C/ h7 e/ M2 q        // 设置主盘和从盘标志! y! c- S$ E/ @4 V
        SelectDevice proc3 w. u$ E- k8 _8 l

) G' ~, Q/ u0 Y0 @2 H$ L9 M        MOV  DX, dwBaseAddress
- ?6 I/ U; s- w* L        ADD  DX, 6
" U4 F9 F* `8 p  b- t        MOV  AL, btMasterSlave1 D! k) f# T* Z# A; |3 a
1 O. g  o" i* X$ q( C9 y8 K8 Q
        out  DX, AL" o! V/ W, ^" V
        RET5 Y* I9 J2 b' @6 S  F

5 A; y" |* R' i6 x/ K1 A        ENDP  // End of SelectDevice Procedure
  F4 A" Q' W  r% X$ E) c( A* v/ R8 L
        // 向IDE设备发送存取指令
0 R, \/ i5 p5 U: j8 B6 G/ ]        SendCmd proc4 A/ w7 X% ~# `5 A0 a  G

- M$ V+ q8 a5 R# a% s        MOV DX, dwBaseAddress0 s5 C: [2 M& M% S  Z! L7 S
        ADD DX, 7
6 _) x2 }$ W* I0 l5 i% ]        MOV AL, BL // BL是主从盘标识,在过程外设置
6 x+ Q' b. K( F9 c9 g        out DX, AL; F" C3 @3 c" U1 U8 P3 R( S
        RET
' ^* W' l. ^2 ~        ENDP  // End of SendCmd Procedure7 Y- g* \5 w* H3 b# P: f5 h0 e

; M5 r" \5 n! P- r; H# c        // Ring0代码$ k3 ]) S0 m1 Z8 D8 B2 {9 D# M1 O
        Ring0Proc:; r/ _0 R6 V! n) r$ N7 L4 o, _4 h) k
        PUSHAD9 P1 f* G, q! e3 D/ I% b
        // 查询IDE设备是否存在+ v$ C3 q* y) V; K$ @  T
        MOV DX, dwBaseAddress
. F/ `$ g1 J8 X( P& o' C- {' R        ADD DX, 7- x! \5 r& h3 \+ C
        in  AL,DX
+ S$ c% O# ]: {; T9 A+ h3 ^6 F: Y9 p: D2 ^7 T1 o7 Y
        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
3 }: V0 A2 m6 H' F1 L        CMP AL,0xFF
2 Z7 ?; L9 b, b+ I9 t* j        JZ  LeaveRing0/ G. y1 E, n. B9 `/ a: U) l
        CMP AL, 0x7F
* s/ z, b% i9 H/ e% X        JZ  LeaveRing0
" j$ h' e( M8 u* E: g# @2 d5 w  i' E, p7 |! c
        // 设置IDE设备存在标志9 }+ I! x4 C, _  Q8 K
        MOV btIsIDEExist, 1
9 d& ^1 b0 y) Q9 {4 S( s/ A$ y7 }/ s
        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)8 E( V0 V+ [- k7 t" @* r0 t4 G
        CALL WaitWhileBusy  F* e" z$ J, [9 R* i; b1 a" O
        CALL SelectDevice
. ~0 c, Y$ T; v% J( F4 ^3 Q. L. F- U# [, Y
        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏" g$ ]5 `/ `* a% s- s( e2 D' k! G
        CMP  btIsFirst, 1. V9 S& Q7 m( B" H2 s
        JZ   LeaveRing0
: O' Z7 G" C# {# V% `
5 g, p) [# x! {1 u: A+ ~2 A1 f! O: ~        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
  f  s1 a$ @' ~7 U& w        CALL WaitWhileBusy: I& E) ]6 f) a1 A

$ I; W4 s* I; ^        // AL的值等于cBit06时,不存在驱动器,直接返回) u$ F$ a9 @1 {/ V1 O* a2 P
        TEST AL, btBit06. n* W' j* s- t  K; i3 @! d
        JZ   LeaveRing0
3 u3 p% ?0 ?. J% g  l# V1 R7 w; h/ j9 l
        // 设置驱动器存在标志1 [& s5 d2 v7 d' a1 h& J8 s) ^3 J
        MOV  btIsDiskExist, 1% @4 L( p- U! e
, y3 h' H2 \1 w
        // 发送存取端口命令5 T2 \7 q+ g. Z4 L* k
        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,/ r2 n& k! m. ~. J, ?, C% Q) y
        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令( N" ^6 G4 S& o7 @1 J1 @3 g  ^1 H
        CALL WaitWhileBusy$ a9 _  Y. ^1 f1 r! V
        CALL SelectDevice    // 设置主从盘标识
8 W. z: T+ c& a9 @; {2 p0 [* r        MOV  BL, btAtaCmd      // 发送读取命令8 ], G5 ?0 Y; C" N. i# n0 {5 S
        CALL SendCmd
& q% a# N/ t7 v0 [  H: I        CALL WaitWhileBusy% O5 [, ^5 {+ S+ q% N, T. y$ a1 ~2 ~
* Y7 \: I; n$ f& b' u4 a
        // 检查是否出错# a4 V3 ~% o4 `7 p2 d% @
        MOV  DX, dwBaseAddress  O5 P5 _, Y5 @8 F' V. T0 d
        ADD  DX, 7
" b; o9 p" K+ y9 O/ K/ t" d. E1 s, P; M/ ]
        in   AL, DX
* }) A, I7 w3 e
5 @* C6 J. V/ Y; K6 D" c        TEST AL, btBit00
% r0 M" Q% q0 T! k( t$ q; l        JZ   RetrieveInfo   // 没有错误时则读数据0 T+ r$ t5 _, ^2 Y  {
7 f6 f, ^: i3 y3 @
        // 如果出错,则进一步尝试使用ATAPI设备命令
; @3 R4 W/ f! l) h- n4 n# N4 W0 h3 [        CALL WaitWhileBusy
0 ]: _; l! P8 E1 m3 s4 k6 L        CALL SelectDevice
$ t9 {- v( _7 u2 f; i        MOV  BL, btAtapiCmd
+ L3 s. F$ w& U1 O2 d3 C        CALL SendCmd
5 p- Z. y5 ]3 T1 p        CALL WaitWhileBusy
( j+ x, l  M# ?8 E; J! n& G% S# {, x. F: o
        // 检查是否还出错6 z! j, L1 u$ H+ _  o- {' ?+ I
        MOV  DX, dwBaseAddress
- t7 B3 u. v6 w" ~& y1 o        ADD  DX, 7
, ?% b/ G+ x7 a4 ?        in   AL, DX
, j" H8 s& z6 @/ Q- `9 R9 p        TEST AL, btBit00
# g& {6 d% G0 Y3 p) ^        JZ   RetrieveInfo   // 没有错误时则读数据
/ a2 f8 T8 W1 Q# B. X+ A& r9 l        JMP  LeaveRing0     // 如果还是出错,直接返回" L% L9 E, `3 L( B9 |9 p

& Q  h9 t5 i3 z7 |' l        // 读取数据
9 Q- z4 Y$ p# S1 M; F        RetrieveInfo:
2 v( e3 E5 S% _" j
& ]3 }, z) |, s" o        LEA  EDI, wOutDataBuf
# M& O8 G9 H. g        MOV  ECX, 2566 z8 h7 |9 m( J2 P7 B, v
        MOV  DX, dwBaseAddress
' h3 A$ m6 S2 N* H+ q+ a        CLD
6 \: u5 N  c  |) X8 r
. j/ K3 u6 j4 s& p. x        REP  INSW0 k2 ]7 G+ D2 s! I" F5 n; N
8 U- ^( `) _6 w! k" t
        // 退出Ring0代码) e* m  |% W4 S  P8 F2 u: Y
        LeaveRing0:5 @' {& y! \/ U, U
5 x) X; x% d. j3 X3 L$ {( b' V
        POPAD1 V% {  ?* G2 s1 S- y4 N# N
        IRETD
% W/ B$ l: e% F; y8 h' R
  m% w- b1 r, j        // 激活Ring0代码
* J, V/ \* m3 P. x1 w+ F        EnterRing0:4 }+ \. ?' J& r1 j- d
. T, b& D# H$ c( h/ I
        // 修改中断门7 B1 z; |/ G( \7 F/ A2 M% K6 V
        SIDT FWORD PTR btIDTR19 s4 K' Q( I' M9 T6 q$ U
        MOV EAX, DWORD PTR btIDTR1 + 02h
4 b+ A8 J6 Z$ p, I/ H8 ]! W5 g. u        ADD EAX, nHookExceptionNo * 08h + 04h
. d8 F2 T4 j( J: R! R        CLI4 x% {4 T5 {$ h9 ^

) U- o5 N6 @+ R4 e. @        // 保存原异常处理例程入口
- M2 @% B( z6 x) D1 C( W; s        MOV ECX, DWORD PTR [EAX], t. n: J( ^* |( W$ X
        MOV CX, WORD PTR [EAX-04h]5 K3 ^+ x% P7 S! i
        MOV dwOldExceptionHook, ECX
0 g+ }1 h3 S1 O; M
8 E2 {4 p" X) Q% x+ w) p% y+ h3 u        // 指定新入口3 m0 R2 a  {8 S2 ?
        LEA EBX, Ring0Proc7 P# M9 V1 d  w' j
        MOV WORD PTR [EAX-04h],BX
* S$ O  g. J/ `8 O# t# Q) H        SHR EBX, 10h9 K4 m' @3 L* B2 W$ J8 u2 V' k
        MOV WORD PTR[EAX+02h], BX
7 C+ ~( v% y% K$ ]# c9 A; J3 j7 j( @$ @% @& ~* W
        // 激活Ring0代码
! p6 W3 c# g9 u3 j* S; m5 G        INT nHookExceptionNo; ^( O3 R* \! C

( t' ]+ k' v* N' Z6 X! P        // 复原入口
5 W& x" ]! N7 f! Z" z        MOV ECX,dwOldExceptionHook
* k3 J! O' i' C/ m; L        MOV WORD PTR[EAX-04h], CX
6 f" [. C: f  ^, s2 N        SHR ECX,10h* f( N; Z& M0 g6 b: T
        MOV WORD PTR[EAX+02h], CX4 J6 e: B/ [7 P6 X' I# z) z
        STI4 j& ~8 |1 [) ^8 V
    }
( k# n  f( J8 a9 e  E& t0 I    if(!bIsFirst)
8 A# B9 K4 a: O& b- @. M    {% ]! x. h- {4 T" O  P% H+ F6 C
        bIsIDEExist  = (bool)btIsIDEExist;
2 B. g1 h" _2 P; c' M& {        bIsDiskExist = (bool)btIsDiskExist;
' n: f" n4 y/ b        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
, [; T# M1 S2 B    }
6 B/ q7 v. S5 u  S* Z' h( X7 Z}
1 {1 e6 I, \. j5 }. J2 z//---------------------------------------------------------------------------
, F4 p/ C2 m5 I& A; g7 Y// 调用方法:
; ^$ Q$ f2 Q4 U. w  m5 Y, Mvoid __fastcall TForm1::Button1Click(TObject *Sender)8 C5 A* c8 T1 C, d
{
  ~. O' p. d" W    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
3 b' J' \& K8 R6 x% v0 B/ |% }9 W+ {  I; M}
( B. n+ F7 L) ]/ |
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-9-30 08:52 , Processed in 0.047536 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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