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

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

[复制链接]
发表于 2008-1-6 19:59:06 | 显示全部楼层 |阅读模式
代码框架,你所要做的仅是修改WQL语句,具体可看MSDN。以下代码为简介起见,一次返回所有的CPUID或硬盘厂商系列号
' `& [. u# Q1 a2 f7 _! x9 X- _
  1. ; H& ?/ R) b, S4 B; H
  2. #include "StdAfx.h"4 a6 `& ^6 Y1 _3 k$ q& L+ V0 m* O
  3. #include ".\puiddisk.h"6 X& [0 _& ~8 f' I: I# t$ m5 w
  4. #define _WIN32_DCOM
    ; u$ y" l6 ?) g8 Q+ l% G
  5. #include <iostream>
    / r. O$ g  {/ z6 ]! R
  6. using namespace std;( r4 a0 c/ f  v5 |" x/ ?3 o
  7. #include <comdef.h>
    4 |/ z5 E. V$ N7 W; @
  8. #include <Wbemidl.h>
    5 x4 n8 o# C. Z0 g
  9. : ]) ]+ `# J+ z" d! v/ }! a: S0 D
  10. # pragma comment(lib, "wbemuuid.lib")
    2 @' S2 u* D3 P! j# w* t/ l
  11. CpuIDDisk::CpuIDDisk(void)
    8 p6 p! Z% g5 v) B
  12. {9 O4 J1 ?: O& S7 N% g; ~
  13.     GetInfomation();6 q2 B  R4 z+ o% C& o
  14. }
    ( o; v5 L: ~# v# g9 @1 Q
  15. + k6 g0 z8 v+ e' I
  16. CpuIDDisk::~CpuIDDisk(void)3 [8 Y/ P8 x6 T0 F
  17. {
    " Z. ~2 [. e* z
  18. }4 r4 Z, A1 o2 u/ G5 g( x
  19. int CpuIDDisk::GetInfomation(void)
    . \; |* _% ]" i/ [8 c1 J- t
  20. {, c) g4 \/ F' M  M0 m
  21.     HRESULT hres;" t4 M9 Y# S1 _1 ]( b( v6 s% t7 d3 }
  22.     //步骤1:不是必须的,COM只须也只能初始化一次# y; |9 o) h! \: K+ B) J' t- q
  23.      hres =  CoInitializeEx(0, COINIT_MULTITHREADED );9 g! l. F( P+ y3 Y
  24.     if (FAILED(hres))
    : |# w( K& m4 A
  25.     {
    ; A1 @1 t3 h' O# c! j2 `
  26.         return 1; //初始化COM异常:注意,COM只须也只能初始化一次
    7 i6 p: P$ L! ]* Q- r6 f. R
  27.     }+ |" y6 W1 l$ k
  28.     //步骤2:不是必须的,COM只须也只能设置一次
    % V' `& u* o6 i; B( T# Y
  29.     //Set general COM security levels. V( a4 F' o' D/ u9 F3 g
  30.     hres =  CoInitializeSecurity(" R3 N% t- u, r1 c
  31.         NULL,
    . V4 g4 u8 R2 P4 V$ @! j9 Z
  32.         -1,                          // COM authentication
    , i8 N3 Q) o1 f7 X1 l/ Z# ]
  33.         NULL,                        // Authentication services
    " L( s' ]; Q) |' O7 E. g# d' [, J$ d
  34.         NULL,                        // Reserved
    ! }$ P7 x! E3 W$ |' H) Y# @! o' N
  35.         RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication
    + V- }8 e) {" Z4 a& I8 I$ T
  36.         RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  + c( D1 x( C; U0 v5 X) M
  37.         NULL,                        // Authentication info
    ; p/ p9 X8 Q: j  c# W
  38.         EOAC_NONE,                   // Additional capabilities ) V* X: r/ ?0 ?9 y' h  W5 ]
  39.         NULL                         // Reserved
    ( w, n: q4 ?, j
  40.         );' s0 f3 p7 b, W
  41.                      
      E6 m( x4 {. m2 I" t5 w
  42.     if (FAILED(hres))
    4 W' D. O) B( z: ?4 t. q
  43.     {. a7 A3 R* L- g/ H* J
  44.         CoUninitialize();2 U8 [4 P8 W- Y7 f
  45.         return 1;                    // Program has failed.9 H; Y! t5 e1 G7 F/ X0 S
  46.     }7 @. @- V$ G/ ~, O0 Q
  47.    
    - {9 t/ m6 s2 B2 d4 R- k3 f; P( S
  48.     //以上不是必须的,若已有“::COMInit();”,则要跳过7 `: f2 o: y, m# Y
  49.     //步骤3: Obtain the initial locator to WMI
    ' u: `- b2 u1 a2 }% t6 ~
  50.     IWbemLocator *pLoc = NULL;
    % v% c# e' x3 i4 e* G1 m% N
  51.     hres = CoCreateInstance(
    7 y; w" C* f$ P6 v1 R! b
  52.         CLSID_WbemLocator,             0 R; N; Y9 I3 O, y, s+ T8 g
  53.         0, ' h; o/ }7 T' L# p5 ]
  54.         CLSCTX_INPROC_SERVER,
    - _0 r0 ^' H& N! ?( [$ W( D
  55.         IID_IWbemLocator, (LPVOID *) &pLoc);
    / |3 n8 Q+ z! q: |* l# G3 B( H

  56. # s1 E+ B" V  p0 r0 w6 C2 l
  57.     if (FAILED(hres))
    4 u1 z5 A3 G/ `$ _8 S
  58.     {
    . J; N; W& q2 s, U, g; v. h( C
  59.         CoUninitialize();
    3 T- P9 V( }. [% F8 ]
  60.         return 1;//Failed to create IWbemLocator object
    * [7 L! S+ u( O0 f7 {8 `
  61.     }
    3 _; E% J- O5 s: L- I- m; X5 B- S
  62. $ C2 U/ V$ {8 }1 W$ R8 q
  63.     //步骤4:Connect to WMI through the IWbemLocator::ConnectServer method# D9 ^3 [0 q- J1 s$ I) {+ o2 t! X
  64.     IWbemServices *pSvc = NULL;
    " Q5 |- ^+ \- A1 s) r
  65.     hres = pLoc->ConnectServer(
    . E! O& u- I1 [% j0 N3 R8 S4 A
  66.          _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace
    . V9 n6 q$ x' N) r* g2 S1 |* M
  67.          NULL,                    // User name. NULL = current user
    , T$ F+ W9 k* I
  68.          NULL,                    // User password. NULL = current/ y1 ?2 M; ]8 `8 U- ^: F5 }/ n3 V
  69.          0,                       // Locale. NULL indicates current- w3 |- X* d7 X9 D$ J4 M& Z9 Y
  70.          NULL,                    // Security flags.
    # l5 N. s& ?; o' D
  71.          0,                       // Authority (e.g. Kerberos)
    4 j! T+ z' Z2 W
  72.          0,                       // Context object ' w* s# N" w$ r& N! i! s8 l
  73.          &pSvc                    // pointer to IWbemServices proxy
    , L$ [! M4 l0 _, }4 \) f
  74.          );1 e: e4 ~3 x4 x8 \
  75.       @8 C! h" i; `4 g1 U. Z
  76.     if (FAILED(hres))' Q: K) N- n4 \; T8 ]
  77.     {
    1 Z" U" J5 v1 B" W+ o# ~. X) G
  78.         pLoc->Release();     9 u6 e4 P- |$ Z- y7 q$ W  u
  79.         CoUninitialize();
    - |0 q' t3 r) Z# C* S* V
  80.         return 1;                // Program has failed.* P/ e+ p. G* O% l: U" U" B3 J  w9 w
  81.     }* Z2 B7 g% S# L: E0 e; N- b8 R& e  P# Q# s
  82.     // 步骤5: Set security levels on the proxy+ L" h5 j% u) Z" D, `
  83.     hres = CoSetProxyBlanket() z' b# ?$ i9 ~) _1 X" y' ~
  84.        pSvc,                        // Indicates the proxy to set4 H* b4 Y; w( E- L$ w/ g* x2 s' W% x
  85.        RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx+ [! {: L- E3 k0 K/ K: r( [' H$ U, \
  86.        RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx( B/ Y, _% |" z3 P! D1 L6 O
  87.        NULL,                        // Server principal name   P" e3 ^; S' Q/ z2 t- J* C
  88.        RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx ( b* M5 {! H8 s4 Y: d# M0 t
  89.        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
    9 M& v2 u7 b( C1 I9 R" c
  90.        NULL,                        // client identity; M- ^4 U) }9 }, N% |3 `
  91.        EOAC_NONE                    // proxy capabilities 1 |3 _6 i/ s1 E* \) n
  92.     );1 {, C: l4 m5 H% h4 w' C& x# w
  93. 7 E, t  Q2 W6 X
  94.     if (FAILED(hres))) ^( v* i; A- [# L( g: `
  95.     {: j$ r/ a( X1 Y
  96.         pSvc->Release();& f) S5 t5 o3 a
  97.         pLoc->Release();     
    . N7 W6 e  L. n# E
  98.         CoUninitialize();9 ?/ u) B/ K# U. M7 w
  99.         return 1;
    7 p" g1 a) {8 `' z6 U, ?6 ?! l
  100.     }& C& X! j$ K% H
  101. $ {- v+ ~$ D3 T; `& h& T* W# c
  102.     // 步骤6:Use the IWbemServices pointer to make requests of WMI ----, }, p' b- {& c2 f6 I
  103.     IEnumWbemClassObject* pEnumerator = NULL;) @( Z, P* R0 s7 G- U
  104.     //计算CPUID
      V' P) K0 `1 P; Z8 [1 j
  105.     hres = pSvc->ExecQuery(* U/ j* p3 h, ^/ ~6 L
  106.         bstr_t("WQL"),
    0 W; |: S+ K; I* m/ H( F# g
  107.         bstr_t("SELECT * FROM Win32_Processor"),//Win32_OperatingSystem& b9 ?% |( B. o9 D
  108.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, . K+ s6 @5 ]8 |8 R- a
  109.         NULL,  W2 ^! V! W7 \. x; I7 H7 i
  110.         &pEnumerator);
    0 ^. ^9 t7 K/ `# ^+ ^
  111.     : C% d: z! Z7 P& R* o# U; d: |
  112.     if (FAILED(hres))
    # _% Y0 e, o( b3 O4 a& |; t2 ?; U
  113.     {  o2 B+ e8 m5 F% t* t( w- j: O& C8 h
  114.         pSvc->Release();
      \% G& i/ Z/ i- s
  115.         pLoc->Release();
    4 t" |7 d( L9 `% G$ a) Q
  116.         CoUninitialize();
    $ N% D; j1 Y" j
  117.         return 1;
    ' p$ D- Y/ J' u( i
  118.     }" k% A" P6 }& Q% {0 P
  119.     // 步骤7:Get the data from the query
    ' D+ N! y5 R2 T- p5 Y) M! y
  120.     IWbemClassObject *pclsObj;
    9 E+ m8 x' O' M" o
  121.     ULONG uReturn = 0;3 \0 o% L% q/ J# E1 o% g. {
  122.     while (pEnumerator)( m, E+ T. e) @  W% m  K
  123.     {. Z# r! `1 E/ i, Y1 |7 X
  124.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, 9 N8 _& [% `- N. y& F" ~* n
  125.             &pclsObj, &uReturn);0 ~7 I4 Z7 s! `
  126. + n& H% {0 c1 K
  127.         if(0 == uReturn)& \+ e8 |6 b. r4 k. a9 L& G
  128.         {
    ' S+ {4 [% X* z. u2 c$ I. @, I1 y( E; U
  129.             break;9 B9 G) U: f5 Z" @6 F  R
  130.         }  G9 S6 K0 i) A- w4 u, N1 c2 T# `3 e
  131.         VARIANT vtProp;0 F2 i; [$ C0 b8 D2 T
  132.         VariantInit(&vtProp);
    ) Z; d2 {  b7 G2 i! f$ R
  133.         hr = pclsObj->Get(L"ProcessorId", 0, &vtProp, 0, 0);
    9 V( j" U1 ]7 q  T7 D
  134.         strProcessID=_com_util::ConvertBSTRToString(vtProp.bstrVal);//strProcessID:类级变量5 a7 Z8 u6 t8 E
  135.     }# w6 i+ L, \! K
  136. , ]. f1 s) v- |: P
  137.     //计算硬盘系列号/ e! h% W  ?" r9 A
  138.     hres = pSvc->ExecQuery(0 r1 F% _  {- E3 l! V
  139.         bstr_t("WQL"),
    % ?; J' i, e; y4 I+ H  D
  140.         bstr_t("SELECT * FROM Win32_DiskDrive"),! {  G" y) T% j
  141.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 5 f1 w* B1 {) @7 Y2 S
  142.         NULL,# y# l& q$ _9 G- _% z1 ?
  143.         &pEnumerator);
    ( ~: K, v: S$ |8 `% i; F

  144. , o' i, j- D, v( c! j7 M9 D
  145.     if (FAILED(hres))
    ' r* R/ _/ N, X3 r9 i* `/ E5 I
  146.     {0 F% j' [9 R/ Z; ~; `: [* d
  147.         pSvc->Release();7 [" _  n# W, `5 S4 E6 C3 N& y
  148.         pLoc->Release();( ?9 b5 ]# I2 S: o- E) k
  149.         CoUninitialize();5 r2 w- ]/ }+ e) m1 v8 R( i6 D( l: G
  150.         return 1;
    7 r0 x9 Y1 ^: [3 d  [2 o& y
  151.     }
    . y' v- b4 m2 P  E
  152.     while (pEnumerator)
    : \, [' P0 H) P6 K; ]
  153.     {0 U- _; {( L, e* Q8 f& J
  154.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, ; r0 y; ]9 H8 F& d7 R* w! {
  155.             &pclsObj, &uReturn);
    * j6 L; V: Q5 v( e) R* \; z' P
  156. 5 s. N/ }  N2 g. G, Y2 p6 I/ r; ^4 q
  157.         if(0 == uReturn)
    3 y4 ?6 _' U: s: `, u
  158.         {1 n; _! B) E: x1 q0 p* o0 N) u% l
  159.             break;- R$ h3 [* G* M0 s, J: Q
  160.         }
    $ p# O# |1 ^' h7 q+ ~

  161. , [) F; x0 r' u# _
  162.         VARIANT vtProp;
    # y  n% Y) p. o
  163.         VariantInit(&vtProp);. q9 h. c: ^- e1 e
  164.         hr = pclsObj->Get(L"PNPDeviceID", 0, &vtProp, 0, 0);
    % y. C7 j% M' a0 Z/ m$ C7 t
  165.     strDisk=_com_util::ConvertBSTRToString(vtProp.bstrVal);
    . m, G; J+ ~3 X$ h
  166.     }4 c. a) ^2 }0 E" E- _

  167. 6 |6 i2 n' H4 b. N- C3 H
  168.     pSvc->Release();
    % X; p, d9 B+ ^
  169.     pLoc->Release();0 i, p% q( w9 k. u3 H* ?
  170.     pEnumerator->Release();& t8 j8 {# v8 u0 \1 ?
  171.     pclsObj->Release();
    9 M/ G5 }. L0 x+ W, {) u
  172.     CoUninitialize();
    ) S' p% p. d5 T- ]& q3 ^" e5 l) }
  173.   u( V1 \, h7 t, w
  174.     return 0;   
    , m" H9 r* o, j# b8 f
  175. }
    4 N5 f; Q( X5 Y. u- Z+ {+ ]
复制代码
 楼主| 发表于 2010-10-11 19:21:05 | 显示全部楼层
本文代码经ccrun(老妖)在Win2k下试验成功.
  k+ S5 N: s" q$ L% H. ]2 c" B0 Z
: I5 _7 `# K4 l6 v. f  p1 d5 \3 i% m#include <WinIOCtl.h>
* R2 g: Z0 B* c# q8 ~3 s6 O#include <stdio.h>2 o* P/ g+ T- P" L

4 |! o  w' z: d#pragma inline
3 y4 z7 E+ t! l//---------------------------------------------------------------------------
+ @9 h, e" G( t# o. @* u- c// IDE NT/2000/XP专用变量# |+ I, p$ n- k* S
#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS! W- m8 b, {: F8 U3 c+ {1 e. y3 R9 C
#define DFP_GET_VERSION         SMART_GET_VERSION1 z  z1 R) a, _
#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND9 u% G- x+ R! i% [% M+ a9 @# @
#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
) n( a  L* E0 ^, o! [2 [: F. ?$ L/ B9 r$ P/ r
const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令
4 S. Q2 j( B2 {) ]3 f% ~1 |const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
) w( m) |0 S6 z1 x5 Y* @7 s, J3 G' G+ r( t* U
const int MAX_IDE_DRIVES = 4;. P  m6 f# g* i. `

! k3 M; ~  L: D5 e// SCSI专用变量
  w$ a; R" K- }const DWORD FILE_DEVICE_SCSI             = 0x0000001B;8 W& C3 r2 E: E5 n( N2 E( p
const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
) w5 X) U; f6 C  H( Aconst DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition6 n0 O0 n. O! B% n* D9 k
const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
- z% E$ c# V, l$ |7 A! p3 p
5 x  g0 w0 }& f# q* Itypedef struct _SRB_IO_CONTROL
, P) }8 n1 E4 y0 d- N6 N8 g{& w; F4 ~% B, V1 g6 o" ]
    ULONG HeaderLength;
9 Z( c: f/ ?9 o5 T9 R    UCHAR Signature[8];, }6 J5 Q" ^5 k# ^
    ULONG Timeout;
% E+ s# }$ W0 E, A# D0 T# e3 x    ULONG ControlCode;3 C% o/ G% G1 p. M1 {
    ULONG ReturnCode;" X" [* N0 M, N$ A3 `0 N9 \8 y) v
    ULONG Length;$ Z8 w- k# ^3 `1 y+ o- f" U# L: y
}SRB_IO_CONTROL, *PSRB_IO_CONTROL;* D+ Z  L" ?" Q" W$ b( C
. b% h' l( ^2 h4 I8 J( W8 k
// 读取的主函数
0 I3 i" _& R. dvoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);3 i7 ?* t+ G9 L0 i0 z! Z/ E+ @
4 t' c3 d1 }) u9 H) p, F
// 辅助函数
+ ?, T$ J* S6 B3 a. }  W: echar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
/ v8 J$ l" g2 \3 o+ p1 y1 E4 F. {7 ~// NT/2000/XP函数2 V; G& V( z4 g
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);# `" U) }$ }5 ^
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
: @2 `. O8 F: E4 v" J        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
7 Z) g& J$ ]" R0 G" k; R        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);! F. p& j8 w' p. B8 |! `# J
// Windows 9X函数
- _" [9 r% d3 h6 |) Y+ G/ q2 yvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);6 _6 Z- f( c' ^* W/ G
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,; V2 c5 W  n' a1 l! `9 a" j
        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);. ]6 q* f6 O4 N% n
9 V, Y/ s4 w/ W: u, R
// SCSI读取函数(for NT/2000/XP)
2 t1 p6 u6 r$ A! K+ w& q$ V" D4 zString __fastcall ReadIDEDriveAsScsiDriveOnNT();+ u+ ]9 h8 q0 x$ J
//---------------------------------------------------------------------------/ _: x# c, _& \% g: q' c
// ReadPhysicalDrive
8 s1 ]/ B, ?2 P0 S' Q2 h7 F# l: `void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)( d! O" ^  P* }7 ]# v7 j
{% Z  b! ]2 w+ [& U, ~' r% r* O0 ?0 P
    switch(Win32Platform)4 Z+ Q+ \6 B( ~: G/ s, o% c* J
    {3 a- Z+ J, S3 b* I3 b
        case VER_PLATFORM_WIN32_WINDOWS:
; s1 D) w0 ~+ x            ReadPhysicalDriveOnW9X(pSerList, pModeList);
- K5 o. G1 v1 O1 H1 T* O, b% B            break;5 T8 H- O' w4 e- c0 ?
        case VER_PLATFORM_WIN32_NT:: ]; [: a3 O# R! o+ x
            ReadPhysicalDriveOnNT(pSerList, pModeList);$ e  J! l$ M! K, V! @( e% g0 D9 F
            break;
* |2 P( P+ y, t+ A7 `        default:7 l: ?$ r: k! E2 d# o9 T6 E
            break;* X2 S. B$ a: U; v% g* ?. Z
    }
$ r3 Q& ^8 K. }# j7 D}
& _) G' h% [. b, J! U//---------------------------------------------------------------------------+ O4 E( `+ _* H" {& D- p
// ConvertToString
: z" l0 H2 v; D$ c3 g0 Echar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)6 q2 z3 l" m9 b+ R3 h7 ^2 Q. q  p
{: M/ k) {' l# p( h* x6 ~& @
    static char szResBuf[1024];
* M  c2 B* u. d% l7 ?    int nIndex = 0;
2 Q2 q) P1 r) s3 k    int nPosition = 0;$ l5 X% ?/ f6 a3 D% T
  y# h  h# R. _# b8 I1 E
    // Each integer has two characters stored in it backwards
- c- E7 f' d& |) A4 t4 \7 Q    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)' F5 f" `2 Q- r$ a9 [+ U1 T
    {7 ?9 r+ x$ x! n; r0 h; Q# c
        // Get high BYTE for 1st character
( P2 y( m2 m& H        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);4 I. b. E7 h7 G4 \+ k6 J; ^
        nPosition++;
" X2 l% {6 r. [1 x; ]) a- n* T" B2 _# u
        // Get low BYTE for 2nd character! A  M" n0 N0 ~" Q1 M8 Y7 F0 v
        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);: ]' v; X9 A- i4 f; k/ {
        nPosition++;/ e' J8 q- C9 e2 p, Y0 l
    }
/ B0 I4 c7 `, [2 q* j
7 J9 g: N2 r# p3 A5 W1 w4 l5 X: }    // End the string
+ G" g; V) q7 c; J' H5 e( a) c    szResBuf[nPosition] = '\0';0 ?7 p% Z5 w# ?- ]) O
) s/ m, V. X: Z2 n
    // Cut off the trailing blanks
9 r( \0 A1 }2 [8 A    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
" N8 D+ b/ m6 {- [        szResBuf[nIndex] = '\0';
( p* F# H3 j3 f' z" O0 Z
( N2 r; E7 A. U    return szResBuf;9 Y+ D7 [3 _) Z# f3 I: e7 T/ S
}; W7 I! t; M$ I
//---------------------------------------------------------------------------$ z7 k; ^' r1 d! {
// Winndows NT4/2000/XP 代码
5 M' O8 m" V6 K% {: E* I7 o4 M//---------------------------------------------------------------------------( ~8 h, V, h) c6 H+ t
// ReadPhysicalDriveOnNT" J1 N" j$ w4 m
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)% R" q3 y! w0 A5 ?( S. Z# b
{
- B& Y+ L# U; u- V  L( ^2 {    // 输出参数. A; e$ [0 B5 m6 e
    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];3 M3 P5 r) K2 ]0 l

3 ^3 J# m( i& R% z# d5 S    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
# M* O; \" }. s' h6 l; N    {, f; f8 D' k) V; B" B
        HANDLE hPhysicalDriveIOCTL;
9 d0 \- p. ^9 Z6 a  x  ~, w; Y        char szDriveName[32];
8 {' G+ ]$ k$ C& W+ I  K$ r1 j  H. l0 g- N2 d' g7 P
        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
; Q6 l- I$ i" E; z+ g  A0 X# |        hPhysicalDriveIOCTL = CreateFile(szDriveName,
2 i8 v3 r/ k4 B# Q7 h9 J" w7 ?7 z                        GENERIC_READ | GENERIC_WRITE,
' N1 x/ n$ m( }3 [+ U                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
0 v# s+ {0 D' U1 F                        OPEN_EXISTING, 0, NULL);
$ M" Q& ^8 H- W8 V  v
2 U* d2 d! B7 N% V8 @7 R7 O        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)3 G. U3 n' K/ W7 v, [
        {
5 ~1 A- U9 R4 q/ z            DWORD dwBytesReturned = 0;
2 o0 W: v$ A0 f/ @$ ~            GETVERSIONOUTPARAMS gvopVersionParams;7 B( N# c% n# ^/ s: [

: E- h0 K8 @5 u% X4 [: o9 L            // Get the version, etc of PhysicalDrive IOCTL$ g" {! d; q! g( p  n3 q
            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
$ r. E0 H: p, Y7 t% ]
6 x; x9 M3 G# y; B            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
  a0 f( G) {( J3 Y; c                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
; g9 {8 n' ]# T; j8 W                    &dwBytesReturned, NULL))
+ y" `- D7 d+ Z" |$ R4 S3 Q2 n/ N            {, B# O* x0 z( m7 A
                continue;4 C, J3 @7 C, }, S
            }
; r2 c9 k  h; x3 h. v
2 U% [5 D' n8 F7 W9 e7 ?& n- T3 ^( d            if(gvopVersionParams.bIDEDeviceMap > 0); x; p" O+ K; q5 z4 i
            {
6 P1 O# w) }8 M3 t; O# n                // IDE or ATAPI IDENTIFY cmd
7 A* t: p- _0 z7 i                BYTE btIDCmd = 0;
( h# m3 a+ m& o8 V3 k  {- s) H                SENDCMDINPARAMS InParams;
, ]  c" E: z+ T0 E3 b# B' `3 Q                // Now, get the ID sector for all IDE devices in the system.* r4 r+ Z  e2 S4 g$ d3 V
                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
+ D* B$ S5 ?7 ^                // otherwise use the IDE_ATA_IDENTIFY command
; Q0 A+ b7 J1 J- A/ P                // 具体所得结果请参考头文件中的说明
2 E- L7 W, r- [; d6 [                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?6 D- X1 c0 v8 e6 Q: m# E1 c3 S) Z
                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
' v; X) ^: ?! R- ?, g# _. o, c7 [                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
* V3 M& A# h: K6 Z7 M1 |                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
( m/ B  I( f8 |1 s! B) |& W" K5 Y, g2 d$ v
                if(DoIdentify(hPhysicalDriveIOCTL,' e0 e2 M" D. s" i5 w. g! _( |
                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
) L8 i$ |  M4 N3 }( q) k3 X                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))0 k* y4 C1 Q: W  v6 B
                {
6 L$ E5 T9 u7 Q& b$ C/ u4 _$ u2 t7 J                    DWORD dwDiskData[256];
4 X9 u4 ^9 ~/ w* Q( g& ]                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
# @  X; I% h# Y, w9 s8 j6 i                    char szSerialNumber[21];0 m( t; \5 L  c0 C: U) m, v
                    char szModelNumber[41];3 k9 f; Y+ \4 Z
2 }/ U- j& m( [  J$ Q; l
                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;9 k* N3 o$ I. S* n( r3 @0 t5 R
                    for(int i=0; i < 256; i++)
# A# ^# m: h- V' P% G                        dwDiskData[i] = pIDSector[i];
! B4 u! W! M! v0 T/ w7 h                    // 取系列号
1 ~; w; }3 s6 f5 k                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
! r* Q* J& M4 e0 d% @% _' [: w0 p                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));  W& |  J0 j* t0 ]- l# O
5 P1 b) O/ \8 U" {1 f, \! g4 @; u( O
                    // 取模型号$ s, X9 j9 t6 W: ?* U% [
                    ZeroMemory(szModelNumber, sizeof(szModelNumber));: h  }% x" \" e0 W+ D$ r! I# ?
                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));" h% v0 t( y" F8 J" l

/ g+ l2 B" |0 Z7 t: n, g                    pSerList->Add(szSerialNumber);  f2 X% K6 [, x0 h$ k
                    pModeList->Add(szModelNumber);
/ o$ K) n2 m& Q/ g1 V+ v/ p                }
8 ^4 F% r, ]! \! r. h& b  B            }
4 w) ]4 L: T/ s9 C3 x& h. `            CloseHandle (hPhysicalDriveIOCTL);6 \6 ?- @4 J& M- p) }
        }
7 U  ^% b# W1 ?& q    }
3 V5 X2 D0 t/ X+ @}
5 o' P7 x7 U# s$ S0 U$ v//---------------------------------------------------------------------------
/ N) y& l6 g/ R// DoIdentify
7 Q7 ^/ x& w* H5 y  p: X) lbool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
. R6 ?( `0 @% l4 p" ]              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
' R' x5 p0 t3 W1 L  M              PDWORD pdwBytesReturned)
$ ^3 j1 W9 E5 W, F  Y0 k{
1 t1 _6 S( ]1 l1 J6 H6 ?+ i4 s+ x& b7 p    // Set up data structures for IDENTIFY command.* ~3 b0 j7 [! D4 O
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
9 ^/ E3 p* V2 s  l  A, \6 I3 |    pSCIP->irDriveRegs.bFeaturesReg = 0;2 |# X# ^3 v9 o  D+ m
    pSCIP->irDriveRegs.bSectorCountReg  = 1;3 ^* R# o; B: Y6 Q  h
    pSCIP->irDriveRegs.bSectorNumberReg = 1;8 G0 D4 k" j( d1 E' E
    pSCIP->irDriveRegs.bCylLowReg  = 0;% F  g# G- e- P
    pSCIP->irDriveRegs.bCylHighReg = 0;  Q, _: S* M) f' m/ h5 M3 x

% T& K1 ], \9 n& W* `8 D    // Compute the drive number.(主盘和从盘所对应的值是不一样的)$ H" E0 Q6 N! t8 ~+ S9 e
    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;- \* G' ^9 }0 H: K1 z# z

- Y5 s; V1 Z$ s& ?# ~    // The command can either be IDE identify or ATAPI identify.
) d) \! l/ r0 x! A- e2 j    pSCIP->irDriveRegs.bCommandReg = btIDCmd;" L1 n: ?, t7 d4 X5 n
    pSCIP->bDriveNumber = btDriveNum;
- v1 G& l5 U$ B, P6 s    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;* @! \0 f& q: t
% p( e1 l) W) _: o: x! ?
    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,) v6 g/ ~. w7 D7 h* H% O
           (LPVOID)pSCIP,- @" q, d& D& z* m# y
           sizeof(SENDCMDINPARAMS) - 1,
9 t9 I' [; `. P; u+ t5 R           (LPVOID)pSCOP,; k! e; r- g" a9 Z2 e
           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,1 U' T: N, {" r5 m5 g6 h7 \+ v. G
           pdwBytesReturned, NULL);  B/ r4 m) d- D3 p) e- @# L# F
}% n) E) d7 o! ~8 m
//---------------------------------------------------------------------------8 F9 H5 m7 W* p' T$ ~% S' I
// Windows 95/98/ME 代码2 `* |3 e& N  R2 R
//---------------------------------------------------------------------------/ @7 Y' G- P' F! k* c& k
// ReadPhysicalDriveOnW9X% J2 b+ e% n2 }0 W9 ]& {4 ^
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)
+ W; f! N+ r3 E) W. \{3 d* {8 t0 `/ q- c: p/ C
    WORD wOutData[256];
% H; k( L9 M3 ?, n    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
: m1 ?; l0 ^( Y3 C/ j( b& J
  p" J/ `% ^1 J5 ~2 b; w. P# u    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。7 {( z. O$ X& m( M0 l6 d
    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
2 H# U( j0 M: o0 ?1 z    // 避免蓝屏的出现。(期待高人能指出原因); C0 H1 [8 ?; L+ _
    for(int nDrive = 0; nDrive < 8; nDrive++)) ?" d& Z) F8 j* O( k, Z
    {+ E7 P1 S$ T$ T4 x* r4 l# a
        WORD dwBaseAddress;
5 C5 l, G- j+ |        BYTE btMasterSlave;         // Master Or Slave
3 g6 {/ q  g* Z+ I        bool bIsIDEExist;
" ]! j' Z( l4 R4 K' N0 M. q( j        bool IsDiskExist;9 q4 d& \# A  Z2 u

! Z9 w% H, W# j" O% P; h        switch(nDrive / 2)/ K1 M% v2 a  b6 l! d
        {* e( D; H1 m3 h  ^) }: g0 N
            case 0: dwBaseAddress = 0x01F0; break;8 O3 X) @) R; ^6 V1 p+ c
            case 1: dwBaseAddress = 0x0170; break;
( X2 W# {; Q# W1 H            case 2: dwBaseAddress = 0x01E8; break;
5 h+ T& s1 z  x9 b; E( O            case 3: dwBaseAddress = 0x0168; break;2 b# Q6 L: E( R
        }; O: e, \9 a, [% M" N0 \# f

5 x. H" n( y/ C" k        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
/ P( A; V# m% J; B% Y" O0 x
: Q) _: M% d. {0 }+ Y        // 进入Ring06 Z' Q* _# R" D! ^4 p$ L
        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
* B# B6 Q6 c. n                bIsIDEExist, IsDiskExist, wOutData);
1 k1 M2 q( z' p  ~/ M4 S    }* K) d/ v1 i# L% T% k7 [, [* {& w
, D# D8 X% R( i4 f4 a- l
    // 开始读取
3 J" M" p1 i' Y* T" F- ]    for(int nDrive = 0; nDrive < 8; nDrive++)! H2 J5 r4 x! B, C) ]1 i4 {
    {
, x0 g4 B( u3 N+ k5 L& O        WORD dwBaseAddress;
! R( ]7 Z5 S% n9 R        BYTE btMasterSlave;         // Master Or Slave
5 P6 `' c+ [) ?        bool bIsIDEExist;
7 C4 K' D3 `6 ?  ^1 C6 [) W) ?' I        bool bIsDiskExist;' r3 L9 T9 r) F% K4 o
        switch(nDrive / 2)
  k6 _, Z3 r' ?        {/ F) Q* v, M$ X+ O6 |0 f! q3 \
            case 0: dwBaseAddress = 0x01F0; break;- f8 U6 L  p# T1 x( ?% x
            case 1: dwBaseAddress = 0x0170; break;; L$ u2 t( P9 V0 U7 z! v, V9 m
            case 2: dwBaseAddress = 0x01E8; break;
3 p8 F* m. H# f$ `* `3 q            case 3: dwBaseAddress = 0x0168; break;9 \4 _  l- e& H4 l, g
        }+ X9 S- b6 S8 D: n  E: ]9 c
8 ?' _( E$ a5 \8 F
        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);; [  }1 W2 C' @; E
! H, J: C' b) i
        // 进入Ring0# V1 I* K* h- R% W. B8 Y7 a4 v
        bIsIDEExist  = false;. ^# R& E! W" r( Z3 a
        bIsDiskExist = false;  i% l$ c, _1 G% F! G5 {) t
        ZeroMemory(wOutData, sizeof(wOutData));
) A( \7 g, Q. k( s, f4 u  d* R: W. N5 i$ a* |9 @" u+ J4 v6 t
        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
! I- ]9 [) {& ^* H* H6 Y! T                bIsIDEExist, bIsDiskExist, wOutData);
- `' d0 Z' r8 r, p( W; M, s+ w' S
( t) c  ]2 i; t4 o% ?8 u0 X        if(bIsIDEExist && bIsDiskExist)
7 b& j+ R- E0 I        {# k* M# a, v% y/ U
            DWORD dwDiskData[256];
" G" y' }; w1 G# A! L# A8 k  l            char  szSerialNumber[21];
% I' `0 w* `' i) y& e- U! X! j            char  szModelNumber[41];
% T/ M. m+ k  T, b. V6 A: h; a2 x
( A6 k' }( q6 `, c            for(int k=0; k < 256; k++)+ W9 w! I, Y$ a& j5 F
                dwDiskData[k] = wOutData[k];% ?% s2 F$ H* q

% D7 J7 E* p+ ^% y$ B            // 取系列号
" a4 ?& x% A6 d! o( W/ h            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));0 u0 H; \5 B. g" C' D- n  N) Y
            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
. Z3 N, c5 {) G1 T5 {) H3 Q9 U; H( ^: |2 C) L
            // 取模型号
+ o6 u# W: t; x4 L            ZeroMemory(szModelNumber, sizeof(szModelNumber));
$ e3 W  V4 l' |            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));6 R5 X$ d/ O4 |0 s1 v* J; q+ O
% H; g+ h# O2 L
            pSerList->Add(szSerialNumber);- P1 A3 |3 k% ?' m; D$ P0 }
            pModeList->Add(szModelNumber);& y+ h% I' A1 M7 k+ d2 U
        }3 `& b/ z5 k$ I$ N% b
    }( `4 |, o6 S! ^* I0 a
    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);, N% T! }9 B4 }$ Q+ u4 R! A) a
}
! R8 C; c" \& W9 p  u( S7 V//---------------------------------------------------------------------------& Q8 T/ }; m4 p, ~, i: p7 r, b
// 为防止不负责任的转载者,在此注明原出处信息,请见谅。
" }, \& A4 Z, b// 资料收集整理:ccrun(老妖),欢迎光临C++Builder研究: http://www.ccrun.com
% U- U# T  \0 A; i' R# ]. Y  m//---------------------------------------------------------------------------, e$ n$ D. i) {
// ReadPhysicalDriveOnW9X_Ring0()8 r9 S7 w* t; J5 b  f
//7 O. k1 \, P  W0 n1 H4 v( o
// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
5 ^5 r' C  i  ?  o* d// btMasterSlave = Master(0xA0) Or Slave(0xB0)' m; H/ p( v" v- P: u/ h( x
//---------------------------------------------------------------------------
: G9 g( D1 H2 N/ zvoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
  h8 n$ ]& u' q2 r' s        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
1 m" S# H; |, @. ~4 T. b{
8 S. q: ~  D5 ~* \2 u7 Z# V( l    BYTE  btIDTR1[6];: H7 u, l0 ]1 T# F5 g+ K
    DWORD dwOldExceptionHook;
% R, D6 b8 f2 ]: F/ h    const int nHookExceptionNo = 5;# j) R3 x0 ?8 ]- f# C
/ ]* `! m: h5 y, c" ?- R
    BYTE  btIsIDEExist = 0;9 d# ~+ d1 ~" t; R, x' U& G
    BYTE  btIsDiskExist = 0;
6 q! K! W, B) k$ T    WORD  wOutDataBuf[256];/ d8 D1 W* \8 W1 Q  w* [

/ M) E) E8 r' S+ X4 Z    BYTE  btIsFirst = (BYTE)bIsFirst;
! O  P4 O+ x- t  l* F1 F% f2 u0 C/ G. S
    const BYTE btBit00 = 0x01;
8 I  d# S  D  r  k    // const BYTE btBit02 = 0x04;/ J' x! n# e2 O# k& R
    const BYTE btBit06 = 0x40;
# e/ M" I  e5 y0 S1 p" V4 [    const BYTE btBit07 = 0x80;
" A% p6 t3 A1 I+ B7 ~% Y1 T8 T    // const BYTE btERR  = btBit00;
1 _3 T8 n' W6 Q# m    const BYTE btBusy = btBit07;4 U0 ~6 q% T; Y" q, J: G( }9 C# `
    const BYTE btAtaCmd   = 0xEC;  r( F5 R2 ?' }, a
    const BYTE btAtapiCmd = 0xA1;
" T' G$ i% Z+ Z2 @5 `7 K9 O! B2 _0 g0 w
    __asm
* [6 d9 k: i8 c; e# b" `    {
$ t+ m/ i/ }4 c* k4 s        // 必须先执行这条语句
( E0 W2 a/ E) l( f# }+ V7 ]$ o( X        JMP EnterRing0! i/ `6 z; ~/ a2 r6 x" V' ]

3 V( {8 U, a3 `2 _) n) I! R1 x1 f3 }        // 定义过程9 S% d0 g: r% }: C/ ?% B
        // 等待IDE设备直到其不为忙为止4 s" V5 v. _! Y% w
        WaitWhileBusy proc& z% l7 C( d5 c& u+ B5 M7 B+ l

5 l* S, d) d( P9 U$ d        MOV  EBX, 100000
" @- i3 [" w  I& \        MOV  DX, dwBaseAddress
7 B+ `4 k% K0 V, j        ADD  DX, 7
2 K' F; o5 S3 N, O) W3 e& e
0 g  C! G* ?) U        LoopWhileBusy:0 i1 r" g! t  m% t% H" {
1 J* ]: O4 K+ O( U- r+ P
        DEC  EBX+ @1 g) ~9 M+ \+ ^1 r9 C# l" g7 h
        CMP  EBX, 0
/ x& B! R( Z2 N1 X7 R( c* N# @        JZ   Timeout" P1 V" I/ }  i* [5 a5 _0 N
        in   AL, DX" h2 _- t3 ^5 |9 j% x" K% d% r7 J
        TEST AL, btBusy
8 ?$ V1 p9 B$ F7 H        JNZ  LoopWhileBusy9 p# f; |& ]2 {
        JMP  DriveReady
- ?0 |7 z- ]. {0 x$ H. \) M1 Y3 ~7 V0 T* k# i
        // 超时,直接退出7 z# Q( G4 a  h6 C
        Timeout:
! y0 S1 c7 G- r5 A        JMP  LeaveRing0
9 k  R% e  `5 l        DriveReady:
" s# F4 [, z- X7 \2 ~; o        RET: p; Z* J  I; s
        ENDP   // End of WaitWhileBusy Procedure
8 P+ Y9 Q3 I% o1 a
3 w; F, ]+ @4 t3 M! s$ E; n: _        // 设置主盘和从盘标志4 U# e. F  {9 }4 m& ?$ Q& R8 Q
        SelectDevice proc
* x6 K" D/ @* c7 C1 F  C6 \
/ O& u" N9 l; p        MOV  DX, dwBaseAddress+ l6 ~/ Q) q8 i- W) z
        ADD  DX, 6
( r* Y- }& A6 u7 M* j5 j4 f: {/ W        MOV  AL, btMasterSlave
9 C0 U& H( J  \. j  d$ r/ p1 E6 O, R* c: x
        out  DX, AL2 a$ X& `: U$ M% Z( l5 d
        RET% d3 l2 c+ F- {7 K$ B$ F  g' N
; l; i: Q! H) q( C: t
        ENDP  // End of SelectDevice Procedure/ N: h! F1 F" d+ G( f# P7 Q" U
0 K5 l8 v3 t: R
        // 向IDE设备发送存取指令
2 V- ^5 D. z4 Y- L& W5 K; C        SendCmd proc% i7 J5 T4 C! H7 b! }  d
8 H# Y9 J7 Q! K
        MOV DX, dwBaseAddress& a' |6 O& A! Z/ |5 i& ]
        ADD DX, 7
  U+ W2 |. s2 W+ s3 W0 g/ y        MOV AL, BL // BL是主从盘标识,在过程外设置6 @8 ^' a8 U- j* ~
        out DX, AL4 U0 d- _2 g2 j( Q9 R# _% |- j
        RET' H6 _, a1 e& a1 H$ `
        ENDP  // End of SendCmd Procedure
, b6 v6 [3 o' O. w  }, ~2 m5 C' N* R' y
        // Ring0代码
/ W3 _% p& H5 e5 j+ x$ j3 t& P, A/ b        Ring0Proc:
% L* j4 C; d. k  ]+ o        PUSHAD  i) O- @& C, n3 K1 }
        // 查询IDE设备是否存在1 f& ~4 p! a$ T" }# F, f
        MOV DX, dwBaseAddress
" E" \. N1 U) |5 y        ADD DX, 7! u: q% _! K! r& a* \3 V9 [3 A
        in  AL,DX( `3 D/ E& Z3 J$ Y7 U9 g' P
7 m; z; x7 h, v$ I4 `8 w! u* B
        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回& g9 N- k; a. }  H' V6 f, d3 O
        CMP AL,0xFF
8 S; u  D& f; T: E* w4 ~        JZ  LeaveRing0
" w- b5 _2 |  [; J. h1 i2 ?        CMP AL, 0x7F
: G7 @( a0 l! S. l/ e& t+ t+ J        JZ  LeaveRing0! T/ B! a& L- Y. b0 w

( J  B3 ~, ~) r& j9 d        // 设置IDE设备存在标志
" ^! i# u* A4 {6 B        MOV btIsIDEExist, 1
& k6 H9 S& F* B1 ~) p
) p9 s* u/ x# V! c/ h0 v1 T" \, s        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
/ H- \1 M( H* h        CALL WaitWhileBusy& I/ S9 X- }  {1 L) G% P2 y0 ]7 S
        CALL SelectDevice) A  M& ^) R" l

: R6 Y$ O: v% ~8 n( A        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
1 `, x! `9 Y5 T; y8 O# W        CMP  btIsFirst, 18 H. l; J' ]0 f9 @
        JZ   LeaveRing0
" ^; z& b  K9 V$ s" S8 S1 p* ~2 a! S
        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
, [: O. |' w. ^        CALL WaitWhileBusy
* M9 i( q4 z* V+ n7 u3 Z. z- h% S5 w% p2 ]
        // AL的值等于cBit06时,不存在驱动器,直接返回% ~7 |  L: P/ h. N$ N. V
        TEST AL, btBit06* J( o% P5 ~0 |
        JZ   LeaveRing0
; T+ R& t$ l, ~: ~# T! x* {1 s* g% z6 p! M" w' `' c
        // 设置驱动器存在标志
: Z$ I4 x4 [5 J& X" o+ X4 r1 m        MOV  btIsDiskExist, 18 Y! i3 o( V9 x* s6 e7 R6 \
0 I  e) ?" W+ H+ g5 Q; C' w
        // 发送存取端口命令% z, H7 D/ f; G& T
        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
1 K  e3 I, o+ x        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
/ B' g: O/ h: r        CALL WaitWhileBusy
- @- i1 X& L- @" M1 S0 Q% b7 P8 _        CALL SelectDevice    // 设置主从盘标识
- s! Q1 U" K  U: q        MOV  BL, btAtaCmd      // 发送读取命令
' m+ O6 H$ Z' T, d  j" A# w3 l        CALL SendCmd* k+ |$ w8 Y% Q7 b& t5 t- _6 p! O. a
        CALL WaitWhileBusy
, a0 x$ W9 }! |8 p# P5 p/ Q; K9 e4 ]5 d1 X/ X
        // 检查是否出错
; m/ w! i, q$ \8 ]6 S& J        MOV  DX, dwBaseAddress
% S# n! g5 M' m        ADD  DX, 76 Z/ g# t4 M2 U$ s
# }# T3 V5 t! x7 V! y
        in   AL, DX+ s: y% v# ]( y0 d% O5 {

4 m9 P$ c: t% Z7 y9 d, o+ x        TEST AL, btBit00
6 v9 _% W6 U: [& T& K; C- _        JZ   RetrieveInfo   // 没有错误时则读数据6 H: o+ v8 ~$ B0 V
. a& b. C: ~3 r1 V
        // 如果出错,则进一步尝试使用ATAPI设备命令
! v' o$ w  F! i, r5 P( e7 J5 h: U        CALL WaitWhileBusy) U/ `, h; Q8 c
        CALL SelectDevice
" q% x' Q( q  r' E        MOV  BL, btAtapiCmd: n% {- m: d# l+ j
        CALL SendCmd
' n2 g# U$ }+ S' P0 V2 s$ U        CALL WaitWhileBusy
+ n; q6 ]! a3 O2 v% q3 d  O+ M: M3 ~! l
        // 检查是否还出错
+ X2 I+ T0 B3 p3 s& @. I        MOV  DX, dwBaseAddress* k) b  p* P+ @& g
        ADD  DX, 7
: [) U4 L9 K0 g7 V) z        in   AL, DX
! o9 L5 Q, l( r6 F        TEST AL, btBit00
5 C, F4 ~9 h- w1 m3 [3 @6 A' C9 ^5 u        JZ   RetrieveInfo   // 没有错误时则读数据
; D. R; v+ w7 I7 {$ R        JMP  LeaveRing0     // 如果还是出错,直接返回  S" e* [5 s% C* j1 i& W% {% i2 [3 V
- J7 w& L# e& L8 i. D4 u
        // 读取数据1 ?+ n7 ^2 X% V
        RetrieveInfo:
% `" b3 v% F3 N8 P5 ]2 O/ |) w: \& `! T. X& @2 K" X
        LEA  EDI, wOutDataBuf9 \" D) z  V6 q8 n4 j) G
        MOV  ECX, 2564 i. d" ]. |0 b7 I2 \" T) u
        MOV  DX, dwBaseAddress
& E3 a0 ~. A4 ^/ I$ V        CLD
) W% Y4 m5 [2 p* i
% Y+ W8 ^7 b3 k; a        REP  INSW' M8 m6 |; W9 Z) [+ d+ I

! p. `, \4 X, V( E0 W3 r/ X, x1 D+ S        // 退出Ring0代码
# o( L: u4 Q( G+ @        LeaveRing0:4 ]# p" V& H; X' c

5 x5 H8 W- l. k4 x6 a6 {0 q; V4 m5 \        POPAD
: @' t0 q! W# I! X7 S6 j        IRETD/ p3 ~) Z2 H' E  b! |, Z6 a

' q* m5 P& q" A        // 激活Ring0代码
* [8 p! Q7 E/ M; P$ g- }        EnterRing0:
2 x4 |* h& c5 u. R, Z5 H! F6 ]( v! A- ]. e
        // 修改中断门
2 ]* M* P/ d* z        SIDT FWORD PTR btIDTR15 f' S1 p1 S3 i2 f+ k; R$ g6 n
        MOV EAX, DWORD PTR btIDTR1 + 02h1 T) h; W' j! [0 ~; X2 Z
        ADD EAX, nHookExceptionNo * 08h + 04h1 m+ u$ {) b) r" k3 H6 }- N. M9 S
        CLI3 E2 A" u& @" b% L  o% G, ]

! k) b7 x: j3 |4 Q  t) ~        // 保存原异常处理例程入口9 c1 \. F+ I! @2 f" W: Z" P) V
        MOV ECX, DWORD PTR [EAX]4 m/ ?$ ~& S1 v0 q3 e; O5 V5 j
        MOV CX, WORD PTR [EAX-04h]8 C1 p9 d1 r+ I: ^( E, o
        MOV dwOldExceptionHook, ECX$ g/ P: Z: A1 y* a6 K% _
% Y% r' u" B/ A8 q5 J
        // 指定新入口( ]" M; Y2 o1 P
        LEA EBX, Ring0Proc
" \% M  W- g) r# R+ q* `        MOV WORD PTR [EAX-04h],BX5 }# ?9 e* {1 i% d5 h! W
        SHR EBX, 10h
% X) C  @3 |$ ?        MOV WORD PTR[EAX+02h], BX
& D5 h4 Q- z8 R! i8 Q% X; z; w9 _3 ]3 O0 b& i$ A2 W1 h# |- K! K
        // 激活Ring0代码4 r2 ~3 o% q% Z4 U: I
        INT nHookExceptionNo
: H4 v2 ?' r+ E6 R2 S( h# T: ~! p5 W% K- m
        // 复原入口
5 I: V: F7 j( t' [* V2 u        MOV ECX,dwOldExceptionHook
% O5 I6 V3 R8 i, W% V. [5 B( o  p        MOV WORD PTR[EAX-04h], CX
# {' V& g. k6 W* T        SHR ECX,10h( v' D6 b2 @: T' b
        MOV WORD PTR[EAX+02h], CX, ]; o" b  A4 d6 u# O" y0 A$ O
        STI
+ l% d8 d  n3 n, h8 ^% V! ?  B    }
( t8 B) x$ N' R! Y0 ~9 N    if(!bIsFirst)& v9 T; S0 R  G
    {& \1 l% Q$ M5 Y/ s) T! F# o
        bIsIDEExist  = (bool)btIsIDEExist;
) i8 R& X) B4 H: g" @        bIsDiskExist = (bool)btIsDiskExist;* ~0 s; A$ }: |% l5 V7 C% ?
        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
; T. [; @, E* w8 w    }/ c  n% T; ~7 p+ q# {
}) `/ T. R# M+ T* R
//---------------------------------------------------------------------------
9 W8 q0 ^9 l( b3 \: K0 E2 u) K& p// 调用方法:
% V& t+ e1 s( Avoid __fastcall TForm1::Button1Click(TObject *Sender)
  x! l) ?6 E$ Q4 y; `8 Y/ \3 w{
$ e9 h8 n3 U6 n    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
. e( e. I$ N- f3 b. \; z! s7 @}) n9 o5 \) t6 G# A& |- T% y
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-6-18 06:07 , Processed in 0.020667 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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