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

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

[复制链接]
发表于 2008-1-6 19:59:06 | 显示全部楼层 |阅读模式
代码框架,你所要做的仅是修改WQL语句,具体可看MSDN。以下代码为简介起见,一次返回所有的CPUID或硬盘厂商系列号1 j1 J" H% f0 h( y" ~( r3 P, g9 L
  1. % D+ P) H5 l/ t, F2 Z
  2. #include "StdAfx.h"
    + ^* a8 }# K* t7 X8 f
  3. #include ".\puiddisk.h"( A" M$ p2 J* z6 k
  4. #define _WIN32_DCOM
    $ \3 U) y  F* i% ^( Z1 P
  5. #include <iostream>
    ! y' j) G- x' N8 M! U
  6. using namespace std;, r" r: F8 x" w2 i7 X4 q* W
  7. #include <comdef.h>
    0 j4 Y8 `6 h# C
  8. #include <Wbemidl.h>) c4 P$ t! E+ y: i

  9.   ~1 d7 x& @2 \; y+ Y
  10. # pragma comment(lib, "wbemuuid.lib")) F: Q7 _0 c3 {
  11. CpuIDDisk::CpuIDDisk(void)
    / U/ R0 f: A/ a( E
  12. {
    % f4 g' {9 ~) C1 R3 v5 h
  13.     GetInfomation();
    / H/ P# J# x5 U/ ?1 i
  14. }
    5 O, f& W% f& i% {

  15. - B$ _; u0 \$ Y4 S% n5 y, F
  16. CpuIDDisk::~CpuIDDisk(void)1 ?3 \) j! B% [% @9 ^% M% @
  17. {
    ' j7 b0 T3 Z" i
  18. }
    " t0 w- M) a( j
  19. int CpuIDDisk::GetInfomation(void)+ B0 T- I/ r% M
  20. {
    , v6 _2 m- ~2 h' B5 q1 @: |
  21.     HRESULT hres;
    : A, L& c# _% s$ j, S& H
  22.     //步骤1:不是必须的,COM只须也只能初始化一次
    9 V4 z7 @* p# T( c. o* {# p
  23.      hres =  CoInitializeEx(0, COINIT_MULTITHREADED );) N& p9 N. u; U* Z7 j( a3 r
  24.     if (FAILED(hres))% o' c* a' s% y$ p3 s/ \! v5 q
  25.     {
    * }& Z. D8 y/ D% t7 M" x
  26.         return 1; //初始化COM异常:注意,COM只须也只能初始化一次2 D2 d  m$ w& @: n
  27.     }% c' w# ^: A9 T" u  c/ T; n
  28.     //步骤2:不是必须的,COM只须也只能设置一次( ^. {( [8 Q  p* x/ F
  29.     //Set general COM security levels
    - J5 {5 W  L- `* o( d) h
  30.     hres =  CoInitializeSecurity(9 R$ K- g% W/ F7 W' a- X; j! U6 B
  31.         NULL, ! M9 d2 K7 @7 U0 j
  32.         -1,                          // COM authentication
    3 g+ |  I6 N( Z/ g# `+ p1 M5 k: p
  33.         NULL,                        // Authentication services7 }( p8 _, x6 P3 o- q& L* i: M
  34.         NULL,                        // Reserved
    # R2 q% N% ]4 M4 H; `' h
  35.         RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication
    & o  |" H4 W7 k8 H% ~1 [
  36.         RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  
    7 f! }% m6 Z& \4 w! c
  37.         NULL,                        // Authentication info  q2 V* y$ J" I9 b
  38.         EOAC_NONE,                   // Additional capabilities
    0 H% Y$ s, l0 W5 X% b
  39.         NULL                         // Reserved( j4 X# Y6 o1 B5 ?  x
  40.         );+ z; v. {" O$ _( Z/ Z% W
  41.                      
    9 U) i9 i0 L3 z) Y
  42.     if (FAILED(hres))
    8 Z, c9 B! |" n8 C
  43.     {
    ; ?( l+ S3 C5 @& _: K$ S
  44.         CoUninitialize();
    , p( S/ k5 r" [3 a$ F
  45.         return 1;                    // Program has failed.6 L* Y9 S+ P* m& `) O! |
  46.     }
    7 h% |9 K  p7 w  [  w( I
  47.     - r4 O5 s( N5 s* C% Z3 Z) m7 S
  48.     //以上不是必须的,若已有“::COMInit();”,则要跳过9 c. k9 M2 g8 V  I! q
  49.     //步骤3: Obtain the initial locator to WMI 6 `! e, C  \8 _% y
  50.     IWbemLocator *pLoc = NULL;
    # c  J4 I4 N# |" |
  51.     hres = CoCreateInstance(
    " k. f+ u9 k: A0 t+ E
  52.         CLSID_WbemLocator,            
    : a( k" m, _9 r0 F0 K" k, G$ x5 u
  53.         0,
    & y, f. b# S! n/ A
  54.         CLSCTX_INPROC_SERVER, " h& `  u  q4 g' k- d  I
  55.         IID_IWbemLocator, (LPVOID *) &pLoc);
    ) M& q; S' O7 T% B% L
  56. ( [" x, f; R: R
  57.     if (FAILED(hres))+ Z# N/ P1 A) C. Q5 ~
  58.     {# J% u5 n. z" c/ w* T8 r& }
  59.         CoUninitialize();: Z4 @" j: [/ r; U  E
  60.         return 1;//Failed to create IWbemLocator object
    9 Y$ K0 w6 x+ n9 ]7 X% l+ f
  61.     }. S' C. B2 Q) m/ j$ r

  62. * g/ t  V4 N9 ~$ o4 H, I, A
  63.     //步骤4:Connect to WMI through the IWbemLocator::ConnectServer method7 ?9 k& w. \2 J3 f
  64.     IWbemServices *pSvc = NULL;! B8 j7 w8 i/ w0 m6 }7 x
  65.     hres = pLoc->ConnectServer(
    * c! y5 r' G1 y. y
  66.          _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace
    : e" x) \' r) u: q/ Y# p
  67.          NULL,                    // User name. NULL = current user* c6 F  c, T# `7 q
  68.          NULL,                    // User password. NULL = current8 E' |# B& |! w+ A/ U* s, n* a* m) f
  69.          0,                       // Locale. NULL indicates current1 X/ q' a; B5 ^# B" R& m/ I
  70.          NULL,                    // Security flags.( k5 i3 U$ b5 G) E# |" k
  71.          0,                       // Authority (e.g. Kerberos)3 {! Q  i& A5 m
  72.          0,                       // Context object
    5 J: W' \$ F$ u0 y- m- M/ \3 g, U
  73.          &pSvc                    // pointer to IWbemServices proxy
    " L# J) r/ ]& g
  74.          );; D. H- C* X2 M7 `9 x$ A
  75.     9 H. k- \+ ~7 ?
  76.     if (FAILED(hres))6 E3 e0 P. M! L& U. p! i6 H
  77.     {
    ( ?/ Z0 Q2 V5 S$ i4 H! G( H
  78.         pLoc->Release();     
    7 r; H4 c5 C# A# ?# ]9 ^& i% U6 M
  79.         CoUninitialize();7 a; s, l( O8 [
  80.         return 1;                // Program has failed.
    / `9 C% Z' R* Q# r. c  F. ?
  81.     }
    , O" ]) b3 Y: T
  82.     // 步骤5: Set security levels on the proxy
    ( `) \2 ?4 V2 E/ T
  83.     hres = CoSetProxyBlanket(
    . V$ o& V, S: Y! o7 y( k9 a; g
  84.        pSvc,                        // Indicates the proxy to set' B* h! L( c& p$ }8 r
  85.        RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx
    : [! E: w, k% S
  86.        RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx
    * ]2 U; o, ], c6 k: J) p
  87.        NULL,                        // Server principal name 5 u; ]. `1 @) D
  88.        RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx
    3 i1 |  Q! |2 G  \2 a2 a& x: E
  89.        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
    / D$ t4 H/ Y- F. i2 O+ X
  90.        NULL,                        // client identity  @5 [! R. T3 S- p" I! D: K5 _
  91.        EOAC_NONE                    // proxy capabilities 1 Y5 n/ Y9 h7 n% ]0 c7 O
  92.     );5 I0 {7 A, Y4 C2 C  j1 h) S

  93. 9 Z0 j0 F* b. ~
  94.     if (FAILED(hres))0 t6 q& N8 N) e- |% {& Z$ l- t
  95.     {
    ; A4 S" k! W( X/ t9 B/ g' o/ j5 }% B
  96.         pSvc->Release();$ f" y# N  c2 w: h3 T# H% o- O  L
  97.         pLoc->Release();     
    , @* R8 I4 B/ ~- I* s4 e; }; f; @0 S! H
  98.         CoUninitialize();  p6 y4 }7 J" P8 W
  99.         return 1; 7 ^$ C8 D4 z" O# N9 K) G0 i
  100.     }' R+ E, P& q8 h4 z. q
  101. : z1 r" \& a- E& x, z" y) O
  102.     // 步骤6:Use the IWbemServices pointer to make requests of WMI ----
    ! k1 Q' p% C' S; `  W6 {, o: m
  103.     IEnumWbemClassObject* pEnumerator = NULL;
    5 k: Q  j3 X5 D2 o! j
  104.     //计算CPUID
    2 Y* U5 h' l/ Y) I& t
  105.     hres = pSvc->ExecQuery(
    & F7 Y# }) E3 e/ g& Z
  106.         bstr_t("WQL"),
    - D" I7 H0 r) b9 y& j7 R# x2 \# t$ Z
  107.         bstr_t("SELECT * FROM Win32_Processor"),//Win32_OperatingSystem4 ~9 P/ ]% n& R% o( t7 I7 S
  108.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 4 r: ?6 F& W  Y5 b0 l
  109.         NULL,# o+ g! }3 k, z3 u; [
  110.         &pEnumerator);4 ]  O2 I8 q9 }# |
  111.     6 [0 z" q4 M. M
  112.     if (FAILED(hres))# j% e' k9 Q7 Q' ]
  113.     {
    ' k/ U- y6 G' W# ^% S, P
  114.         pSvc->Release();
    + l2 g$ V. y( a" \# B
  115.         pLoc->Release();
    0 c& ?# S1 U' I$ e* ~' f5 R2 W! F
  116.         CoUninitialize();
    % u9 G# b+ z) t6 W3 z1 d
  117.         return 1;  A7 ~5 J3 ]* g, d+ ^) Y0 T3 P
  118.     }
    9 c7 W1 R  g8 w9 e) K: Z4 q
  119.     // 步骤7:Get the data from the query
    ; o/ L( d$ s4 S1 S  _! `1 q
  120.     IWbemClassObject *pclsObj;+ o5 G9 @5 J' x) ^
  121.     ULONG uReturn = 0;! ~$ ]7 K1 y/ V9 D, e# Q2 G; Q
  122.     while (pEnumerator)& k& ^' O, F) F# _1 _
  123.     {
    0 [6 h: u+ P* [: t/ ?
  124.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, ! |! ?6 |7 Y6 ?" ~( f' Q
  125.             &pclsObj, &uReturn);8 ?, L+ P- K" j, s/ ~2 y; M
  126. . k7 e1 \  v4 S1 ~& q. }
  127.         if(0 == uReturn)& ~9 @0 v. ^$ u
  128.         {
    ; z. }; T$ l8 S$ Y; T% J
  129.             break;! m% G% D6 T' o; D
  130.         }
    5 N# T) m! Q; I: b- r# g9 ^! _
  131.         VARIANT vtProp;
    ( g+ a8 R2 ^5 N
  132.         VariantInit(&vtProp);# k4 {; d- T5 `
  133.         hr = pclsObj->Get(L"ProcessorId", 0, &vtProp, 0, 0);
    0 W# W4 h) _+ x. [
  134.         strProcessID=_com_util::ConvertBSTRToString(vtProp.bstrVal);//strProcessID:类级变量0 K) p( ^& m# L
  135.     }
    7 ~$ U# @, m+ m
  136. 9 m1 T! w1 m( a4 h
  137.     //计算硬盘系列号
    7 m$ _' O. m2 i+ Q
  138.     hres = pSvc->ExecQuery(9 ^& y* h: a7 R( k0 ]
  139.         bstr_t("WQL"),
    $ C3 u$ ]5 \! G$ b9 p1 V  c' Q. w
  140.         bstr_t("SELECT * FROM Win32_DiskDrive"),
    4 E; {) w& I& r5 q! Y8 Q; ~
  141.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
    1 B$ j& C5 M4 O9 L1 B; W
  142.         NULL,! ]5 `. |3 Y2 t3 l# K
  143.         &pEnumerator);) e+ C2 x' F  j' h: {  g0 m

  144. 5 T' r' q0 ]4 D
  145.     if (FAILED(hres))0 U; ~$ b  F& g6 T& t
  146.     {
    ! c) m; s6 W' C" m
  147.         pSvc->Release();3 T+ ], v* Y& I% \( \+ h& `' K2 ~
  148.         pLoc->Release();
    & m) N7 W; T  T$ o  H& o
  149.         CoUninitialize();
    0 O% T! |& t3 }: `# l" F
  150.         return 1;
    6 Z& V) F3 y5 ?0 C
  151.     }$ ]( d! |0 c) M  q0 |2 g
  152.     while (pEnumerator)
    ) ?$ z, }& p& F* }
  153.     {7 M. n+ U5 `& v4 I8 M
  154.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
    ' L8 C2 w  r+ F! \4 z
  155.             &pclsObj, &uReturn);8 A7 P* N) A/ ]
  156. 8 v( r+ q9 c# F+ B% e
  157.         if(0 == uReturn)/ ?' \1 D  E$ _& u$ z, S- t
  158.         {7 K; _4 I2 @. m8 [# T' g# }
  159.             break;
    7 T1 b; @5 a# J! u) u, j# `9 ]3 w3 X
  160.         }+ L# q, ~, S& b1 T# @
  161.   b4 E+ e& g3 y& q
  162.         VARIANT vtProp;
    5 |$ F$ N6 v& _+ M/ |2 w
  163.         VariantInit(&vtProp);8 z% k8 ^* d3 D* D) i
  164.         hr = pclsObj->Get(L"PNPDeviceID", 0, &vtProp, 0, 0);( q" p* }* ~0 f" P& ~
  165.     strDisk=_com_util::ConvertBSTRToString(vtProp.bstrVal);& K3 E+ A4 b8 F1 p+ [2 m' }
  166.     }- K6 Q2 U4 W8 G6 B3 l
  167. 0 h, O5 @+ `+ I
  168.     pSvc->Release();
    - J8 h0 \0 g8 U/ w8 g0 d
  169.     pLoc->Release();
    1 `& x) [1 L) z. |) B/ I5 @
  170.     pEnumerator->Release();7 R1 ]" X5 x5 p8 O4 ~) q
  171.     pclsObj->Release();
    ; w% M& n0 _/ b8 D/ c* y
  172.     CoUninitialize();/ q6 ]% y8 w; }/ B- H

  173. ; ?8 |" q% M4 y
  174.     return 0;   
    ; ]% N! l% g, O( M5 y; q
  175. }
    ; y! q% {' ?: E- V' f! R
复制代码
 楼主| 发表于 2010-10-11 19:21:05 | 显示全部楼层
本文代码经ccrun(老妖)在Win2k下试验成功.
; S0 v, d  R( L5 c# H/ _: Z
8 i5 t* U5 Y. H) q' g#include <WinIOCtl.h>
) K5 x' i" }" A2 n) T4 [& F9 g% ~#include <stdio.h>, R0 p9 M  r% g. K+ i& ]  u
! `2 d+ m; }- A4 W
#pragma inline7 q9 g5 Y, k3 _1 u$ H3 h
//---------------------------------------------------------------------------, Y  o& i% I2 ]( ]4 o1 R
// IDE NT/2000/XP专用变量
9 d1 b/ R- \: o* ]+ K2 K3 A7 L0 `#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
. q5 q/ i9 K1 w8 g; x% f#define DFP_GET_VERSION         SMART_GET_VERSION
: ?1 t: @5 y# p. h4 S, n#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
9 b* O4 v8 f: `2 ^4 T#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
# L+ ?: ?2 {# f; V* o7 v1 ^$ ^/ q6 p2 q6 m7 M4 R2 y) X
const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令1 r8 [- x& k5 r, e
const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
; r, Q# D3 x6 \9 u  L. R2 U, R" C* ~6 v! b. b1 H6 W! o" u2 V
const int MAX_IDE_DRIVES = 4;
/ J4 `/ d, n" i3 t( V0 l2 v6 W5 v- H" N9 V5 M2 a
// SCSI专用变量' z0 u* O9 C3 G4 P2 D' e
const DWORD FILE_DEVICE_SCSI             = 0x0000001B;
% a; b: t$ A2 H9 V9 o' ?7 lconst DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
+ m3 T1 `- X2 X( l! T) Jconst DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
" |$ G( R6 L  c- \7 fconst DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
; g5 H. r6 y$ k3 R
; ^7 O9 ^6 F- h$ Ptypedef struct _SRB_IO_CONTROL
; |* u. Y7 `1 D( J{
4 p  ?  m% ~$ V8 Y2 g    ULONG HeaderLength;8 w: E; Z3 _" O* T7 `4 t
    UCHAR Signature[8];% m6 w8 Q7 H4 s, S+ T
    ULONG Timeout;  z$ @3 R& U5 F9 C: g$ }
    ULONG ControlCode;- N' u3 M6 \6 `/ o' c: i
    ULONG ReturnCode;
& H( E: p  r. y* q3 g( }- x6 @    ULONG Length;7 y0 T0 k( X. }0 W# S6 z! X
}SRB_IO_CONTROL, *PSRB_IO_CONTROL;
: B( [2 A/ N: u+ J4 {  [
! m; v5 ]. d' {. _// 读取的主函数
6 s# J& \& I0 X% F; H! R# T0 q2 f+ dvoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
1 N. H4 G$ Z5 s, \3 w0 J) G& x! n, F& n- S2 o+ P5 I
// 辅助函数8 p) H: T6 R0 E8 U& d1 J# f6 f
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);- w6 s' W9 G" S6 _5 E- M
// NT/2000/XP函数
  @7 b* W# D9 X) Kvoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);. J  X% e+ X5 o* x
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
" L8 \) T) `9 c# _! x7 D/ j        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
: h; m% Q  X& b& G- A. Q        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);- P5 d! x* \2 m5 ]0 I9 P
// Windows 9X函数
  p5 K- |, Y  m1 e  bvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);- G4 l' G' R& y4 T: O; k
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,+ G8 [. v8 U, ?$ A& C3 t
        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);$ o( W% Z7 N) e* S* T* M& c" |) R* u

' `2 P% W" t2 d// SCSI读取函数(for NT/2000/XP)
6 Z6 G) Q. {( ^$ c; R$ GString __fastcall ReadIDEDriveAsScsiDriveOnNT();* Y6 ~, y9 t2 Y6 T+ T
//---------------------------------------------------------------------------5 O/ I) o; s9 n+ _, {0 l/ V) {
// ReadPhysicalDrive
' g, h( q2 t8 V! ovoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)! j! b* X# W; B7 a
{/ \+ O2 o# Y/ \
    switch(Win32Platform). g% V* A( q, q/ q- a
    {
, y$ l+ U$ s  D* s/ d        case VER_PLATFORM_WIN32_WINDOWS:3 N4 A5 Q- P8 `
            ReadPhysicalDriveOnW9X(pSerList, pModeList);
* A6 F- E; Q/ Y- E- F            break;3 r$ v8 C( Q$ C4 w3 p' S
        case VER_PLATFORM_WIN32_NT:1 z7 x# V) y1 i6 i
            ReadPhysicalDriveOnNT(pSerList, pModeList);
* f; w! Z9 X0 ~, S, ?            break;
8 l7 _; e1 [9 x        default:2 s# C6 H/ Z9 |; x2 J4 ]* P- r
            break;
4 g- m8 v. I* _/ R( e    }
' F. h3 @! a; X- g: L1 w}
& W( L" H0 u% ]  A5 A//---------------------------------------------------------------------------
/ Q' v3 O0 \0 i9 C# c: i// ConvertToString
( B' K" s8 `+ `char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)- w, r8 Y. Z, j6 [+ @  v; L
{+ [/ [3 X& \: I2 _& d
    static char szResBuf[1024];( B! Q, L; V( r. _! I
    int nIndex = 0;: q  G4 n% f' ^1 U
    int nPosition = 0;
. y# m+ l0 f. K( T
  M1 T/ @: C% v3 W* G" g% c    // Each integer has two characters stored in it backwards# ^6 a" W6 i3 b8 m# H2 [5 z
    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
+ U+ f9 b/ Q3 a# L    {
6 c. P, m  ?& J+ h) f        // Get high BYTE for 1st character+ @7 d5 e0 O' D- t
        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);1 V, L( O" S3 ?4 A9 ^* o. _
        nPosition++;0 u  H- I2 [% i  P9 e6 M! m
! R3 g6 n( Z6 A& ]
        // Get low BYTE for 2nd character. I" W. |; N- }2 g* I  y
        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);. q( ^  L6 O6 h' x, Q# {0 H! _
        nPosition++;2 r2 Q4 T& q8 B5 h% V$ S
    }
: o1 t. y) T7 F% R4 g* ^, J
* q7 ]" o- q' d& w5 B+ s    // End the string" e0 t! ?$ {5 \* P! |
    szResBuf[nPosition] = '\0';! H) \2 o0 C1 I/ t  Y9 `, q( ^. V

5 h) b5 q; V) U) R    // Cut off the trailing blanks
3 a' Q6 V' f; r9 C3 p8 L. n    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)1 c9 N3 {1 \( m# ^
        szResBuf[nIndex] = '\0';
5 H( m+ x1 {! }4 s) h; |
! H7 `& ]' n4 [6 Q    return szResBuf;
1 ~% }( q  B- a: h& u8 i4 k}7 n# T* E" z3 V- U8 t6 r
//---------------------------------------------------------------------------6 H3 T6 M3 {5 w3 S, G" O1 U
// Winndows NT4/2000/XP 代码2 A- b* O9 m1 g; U. }& I. B
//---------------------------------------------------------------------------
4 `4 \, J6 c  u$ o# R$ b( G# S// ReadPhysicalDriveOnNT
: d+ {/ o! x  z/ E7 T! f# u* N7 vvoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
0 }! ~+ Y9 e. K- }6 f{
1 S. X4 a9 T1 ]4 p' M/ R3 D    // 输出参数0 M3 N/ o- v9 H& Z% W6 J3 v
    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
; S+ t" Q6 _, i; r% ~; O
! I4 {! M- h% l    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
4 I6 k1 V$ `! v9 t    {
( D' E  C' E9 m0 W5 K+ q: A        HANDLE hPhysicalDriveIOCTL;
9 e' S% v) Y, E% F% F7 a( s0 w        char szDriveName[32];
- Q! X2 s1 W' I0 W
4 Z4 f7 P- r$ q$ m) W) g  n        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);0 h& O& f) e! O7 O# `7 d
        hPhysicalDriveIOCTL = CreateFile(szDriveName,
) l+ Y2 G% r6 s# ^8 M  i+ n                        GENERIC_READ | GENERIC_WRITE,8 w6 X8 J: F& F( V; o
                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
# }5 G5 d/ X' U. d  r, [8 ^                        OPEN_EXISTING, 0, NULL);% g7 f, f9 ^/ P; Y* F3 i; {9 \
: W8 ?; a9 a+ L/ a- d
        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
2 t$ q+ ?. B. Y  L  L2 L& t3 w        {
- s" c4 k7 w" a( Y            DWORD dwBytesReturned = 0;; e% G  f3 F5 {9 D
            GETVERSIONOUTPARAMS gvopVersionParams;* E8 E+ E9 Y) R& y
/ j: J8 [3 W8 W$ I" Q
            // Get the version, etc of PhysicalDrive IOCTL
: u( }+ R' i4 k: f7 t            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));+ _0 M/ s/ S# @9 O# P9 ]; G" u
4 u8 n: u0 Y; d2 e# _) F
            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
+ K# J9 E+ L1 ^' j8 r                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
/ S. h1 y/ X3 P2 G4 f                    &dwBytesReturned, NULL))
3 j9 Y1 C, f) \) O1 _            {
% G3 @. d, @" R0 y, T& V                continue;& b: U+ D5 H+ P0 W) t: s
            }) A- P6 h$ J# L% {3 }6 _$ M
- S. A* C2 L8 z5 Y  R
            if(gvopVersionParams.bIDEDeviceMap > 0)5 b/ K. O, R, N
            {. N* K3 l1 _! ]8 N# s( {! X; @
                // IDE or ATAPI IDENTIFY cmd  c# Q- Q8 z# l# O+ x- ~: b# ]
                BYTE btIDCmd = 0;
; X. T7 m. Z9 G6 g: E% {, @                SENDCMDINPARAMS InParams;
6 H$ V0 d. ~& l& S9 t4 J                // Now, get the ID sector for all IDE devices in the system.
. {8 m7 y% L  L' ^. {& q# ?# s                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,  v; Y- m4 P9 |" `0 Z
                // otherwise use the IDE_ATA_IDENTIFY command% i( c9 ^' f+ B: j4 F. @9 M, ]" X
                // 具体所得结果请参考头文件中的说明
3 u' j: u1 C- w: w$ `4 l                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
. Z: t6 @8 U5 q! f+ d- q- P                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
- O8 C. D/ l. b% r: C                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));9 C, W$ z, {1 Y4 `, H5 D
                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
4 |* {1 A: E' C7 j- M) ^. N5 W! b; I# F+ l
                if(DoIdentify(hPhysicalDriveIOCTL,! D7 D  x. N) X- _9 ?
                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
! R! ?7 h* i0 P8 O" M4 a# T; l5 y                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
- `4 T- {# A  p( C                {- q5 l3 ?! {6 V. o
                    DWORD dwDiskData[256];
8 j6 T1 W: R% C+ x0 T                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
1 B* N4 Y- p9 `" k$ K                    char szSerialNumber[21];
* C0 ^4 c& X& M1 L6 k* m                    char szModelNumber[41];
3 z9 U/ h9 J' D- i9 B- X/ m# N
5 k. G/ G6 s) Q5 m  O; P' L                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;: p+ C* o" Y0 n/ ~, }4 J9 K( Q
                    for(int i=0; i < 256; i++), n* \, U3 E' s% W# t
                        dwDiskData[i] = pIDSector[i];
- g. W7 _0 L9 k5 k, n; B! I                    // 取系列号
5 ?4 i! L( n" ]% {( B                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
/ P! S2 N9 E" S                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
  F4 t9 _. M: W2 c: Q5 P
! h, P5 l2 f0 M; F& E% N5 ~( N                    // 取模型号
2 x  p# M+ [/ w8 E3 [# I5 a) M8 @                    ZeroMemory(szModelNumber, sizeof(szModelNumber));
9 l0 l8 M' B. p; t. ]. U/ h% h                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
; X# J% r. |. ~' Y5 T" k/ g9 c' @0 D/ E- _7 F% [) x4 A4 o
                    pSerList->Add(szSerialNumber);
+ ]5 K" P+ r% `* J/ m. a) p                    pModeList->Add(szModelNumber);; R: b  v5 z, H8 [( w
                }
- ^1 m( h5 O9 e0 I/ b1 s8 y0 P2 C            }
/ ]/ o5 m& ^0 _1 O            CloseHandle (hPhysicalDriveIOCTL);
0 v3 P. E* J3 s- t# o        }, j$ J/ w4 d. X. E- }% F% D
    }! d; G% h4 x- v* @' K1 \
}$ ]' `( H( g! K6 R; u
//---------------------------------------------------------------------------; m6 e2 g1 W+ [4 \+ M7 q  L
// DoIdentify
4 j$ i* W# X; R* I. T, Ubool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
/ w1 L" e# n. j              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,7 h) s, n- ]7 E" Z+ s7 @% g
              PDWORD pdwBytesReturned); [& f, d) v5 `# c
{
" q* \* g" ]) ]" h* B5 J    // Set up data structures for IDENTIFY command.
8 t4 V" l7 I( P; l) }4 v# Y    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
5 G& B1 |9 z9 P! G    pSCIP->irDriveRegs.bFeaturesReg = 0;
+ S. y& K& _8 o    pSCIP->irDriveRegs.bSectorCountReg  = 1;; |+ m% z+ r9 v& U
    pSCIP->irDriveRegs.bSectorNumberReg = 1;
/ K9 o3 M# L" I    pSCIP->irDriveRegs.bCylLowReg  = 0;
3 P( {5 W' L! T$ |6 ^7 C  W& F    pSCIP->irDriveRegs.bCylHighReg = 0;
9 {3 M1 ]# P2 G/ d7 r! S7 J
  x, W5 |( F7 S* [* o    // Compute the drive number.(主盘和从盘所对应的值是不一样的)
" M) T8 g3 @3 S! ?9 V/ J    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;& B9 M7 e- u" w4 ~6 a1 N# S& U% r

. e6 {+ V' n; [! L$ u. q    // The command can either be IDE identify or ATAPI identify.* p3 f7 a( O% e0 E
    pSCIP->irDriveRegs.bCommandReg = btIDCmd;2 F; Z/ K8 T  d6 u4 w
    pSCIP->bDriveNumber = btDriveNum;9 U, |. z% n# Z3 P9 |/ ?7 I
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
1 K0 f9 E% v" B- P- B6 u+ x9 z: a/ L4 m$ d6 M4 R' u- ?
    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,: }' V8 U. _# n; B/ m
           (LPVOID)pSCIP,% _0 m  G& U8 C( i0 K9 R
           sizeof(SENDCMDINPARAMS) - 1,
0 R: W" g& Y7 q2 P% F8 _2 ]/ q# _           (LPVOID)pSCOP,
* [4 q) l$ t. Z+ l. ]7 G           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
) U# ^# L8 O* ^# u7 `( U- g: a           pdwBytesReturned, NULL);
' a! U& I6 `- ~0 L! q# f}
: k( S: O* T2 J4 ^" o//---------------------------------------------------------------------------. ]  O% Z5 p. p( h' I
// Windows 95/98/ME 代码9 o: _* w  c' p" o
//---------------------------------------------------------------------------
7 [6 n" A4 E: Q// ReadPhysicalDriveOnW9X
" `% Q; X  i: F& F0 V' q8 Lvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)# D2 y4 f/ L+ a8 N
{
8 K2 K* _3 F% N    WORD wOutData[256];
/ a$ E& ~% y% p) o    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
: `6 Z6 k8 U3 O4 r* f+ T% v% \7 I
    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
6 z  z1 Y* ^5 s5 H    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
' @& E% u8 o- O- g2 I& H4 i4 h' D    // 避免蓝屏的出现。(期待高人能指出原因)
4 U; Q- `  _; G! J    for(int nDrive = 0; nDrive < 8; nDrive++)
& b& \9 p6 ?& t% C1 \0 _7 i    {0 O7 Y1 |( Y6 n. x: k9 V8 i- [; H. I
        WORD dwBaseAddress;
+ G$ t* V) R" f( @, N+ |        BYTE btMasterSlave;         // Master Or Slave
" K) t" c8 J( _3 O, w        bool bIsIDEExist;
% S+ i- l3 c0 y2 Z0 [: ], F        bool IsDiskExist;8 J% ?& ?- b% ]6 M% F2 n1 V

5 r6 G* d! S+ n( m) _  U1 v        switch(nDrive / 2)
# u& w4 \: c3 u3 S        {: D1 Q4 j" p# M% I1 d0 \( X
            case 0: dwBaseAddress = 0x01F0; break;
0 o% x; p# L7 T8 [            case 1: dwBaseAddress = 0x0170; break;
1 I. i2 s( t2 T1 m# z3 E            case 2: dwBaseAddress = 0x01E8; break;
( q/ ]' E) c4 `7 p- G            case 3: dwBaseAddress = 0x0168; break;
9 G1 Z$ X+ K5 Y5 I0 W& r6 M& O: I        }
- ]: e+ z) N: ^- Y0 |
$ O3 t: j/ A  `: e2 t. M        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);& x3 |2 G1 [/ K; B* c

% B, T2 a( z2 a: Z; r        // 进入Ring0
* z" V& x$ U. }  R5 g. a+ H        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,5 g4 c8 s3 H) s& `, @" ~: r4 \: D
                bIsIDEExist, IsDiskExist, wOutData);# q' H# e  a4 T6 _) X
    }% {# O) R' T- G5 d

- j9 I9 [$ b7 L! q6 f# B! S) f    // 开始读取
  _6 C7 i5 z/ A/ m- C0 f6 ~% B    for(int nDrive = 0; nDrive < 8; nDrive++)% u7 a) j  R3 w; ?
    {9 Y  \! b  t0 w) {) q4 T& j
        WORD dwBaseAddress;
) x  J5 z$ C0 t& m% Z        BYTE btMasterSlave;         // Master Or Slave5 `) h2 v$ Q, }6 F& C) E; W7 L: N
        bool bIsIDEExist;
5 o: E+ H9 i5 z- F, \& T  R6 g        bool bIsDiskExist;
$ F6 P7 O1 k6 M* M        switch(nDrive / 2)7 D* Q( [. X+ G" N
        {: K- k" {. U0 ]* g. V3 ]2 k; U
            case 0: dwBaseAddress = 0x01F0; break;
! u$ X) I  j4 L1 b5 X2 r            case 1: dwBaseAddress = 0x0170; break;
3 {% `( f: s* M. ?$ y: }4 t            case 2: dwBaseAddress = 0x01E8; break;
- l5 N6 r8 o3 x            case 3: dwBaseAddress = 0x0168; break;' e4 A) Z: I  B* [1 ?/ T
        }
2 }# a2 E9 Z. J: J5 D1 D, R. J, ]" X8 x! @- E6 Z! w* o
        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
& z% ?% P' h7 Y' v+ D
- z- ]7 Z# M! K+ ^        // 进入Ring0
7 c" A: L: C& e3 T* |        bIsIDEExist  = false;
4 r) P$ J$ V! O( U/ X7 b' E* O( r' _        bIsDiskExist = false;% V& e( x* q; @( R! }! u
        ZeroMemory(wOutData, sizeof(wOutData));
( j- m3 g/ @( {* X* K. u
2 w6 I4 j* J  b        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
% j$ B6 M  j+ g9 q3 w: ^                bIsIDEExist, bIsDiskExist, wOutData);
" `4 F6 z- D; G) p5 K! _* m/ K1 f5 s/ r# u2 ?% n/ D
        if(bIsIDEExist && bIsDiskExist)
/ y9 u7 t; r9 ]$ Y# i        {' |6 ~5 L, I5 {9 f/ Z1 P& d, y5 q
            DWORD dwDiskData[256];7 r% S# L: \& W# H% c
            char  szSerialNumber[21];1 b1 \4 I( j1 L1 n; E- q* ?; D) n
            char  szModelNumber[41];% Z. f" S8 p  p  e, p
- b' ]+ \5 S7 d2 c' N, M
            for(int k=0; k < 256; k++)
7 _6 ^# T* I0 \% E2 [% K, A                dwDiskData[k] = wOutData[k];
. U9 W2 ?9 `. z7 E# P7 w$ U3 @, i! ?! d0 z6 u
            // 取系列号! l6 t2 E" {" _0 U# q" K+ G
            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
! D. \& O, u3 ]: Q& u/ G! F            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
! g* r( K0 R. J: `- j) n% g) U* J# c
            // 取模型号
5 Z3 C5 K: B: U) H4 E( V3 u            ZeroMemory(szModelNumber, sizeof(szModelNumber));2 b6 ?, l0 r; Q1 |0 D
            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
" v5 S( }# o( r8 X+ u: F6 W2 ~* P2 \9 X9 M  s4 x& u% i
            pSerList->Add(szSerialNumber);
2 o5 h1 Q# d( E: `5 _2 k. E# ~            pModeList->Add(szModelNumber);
3 u8 ~% ~; G; d& M% o1 Z        }
: O1 h# J6 I6 ^& C1 Q+ a+ P9 w# K    }) ]! X4 \5 c* ^5 ]) K) v+ l5 b' f
    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
. @( r5 @/ l* J/ s8 e}
% I8 X# C% \8 W. ]2 j# f# V* b4 q//---------------------------------------------------------------------------4 b, ~% g1 B+ L+ O
// 为防止不负责任的转载者,在此注明原出处信息,请见谅。  W$ }7 W* O0 z4 Z
// 资料收集整理:ccrun(老妖),欢迎光临C++Builder研究: http://www.ccrun.com
/ G( P5 B0 H2 b//---------------------------------------------------------------------------$ ~9 Q- u2 A  A; s$ L; h  b) w% Z7 p& B
// ReadPhysicalDriveOnW9X_Ring0()' }. i: ]3 c  ~6 M
//
8 q' B, A+ ]' q8 f9 e  G// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h" H% p" n3 l. d/ D
// btMasterSlave = Master(0xA0) Or Slave(0xB0)
1 I9 i- V% ]% \! C6 P//---------------------------------------------------------------------------
( I: S* X; z( p5 evoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,6 C+ E; _0 B; K, l
        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
+ c' I, G$ \: O" r( q; L: a' K{( U" @3 p4 ^( w6 i0 ?; u$ e
    BYTE  btIDTR1[6];
+ b8 A1 L/ |% J. G' I    DWORD dwOldExceptionHook;$ R1 k5 r7 m5 x6 ?2 v5 t
    const int nHookExceptionNo = 5;  E3 l* K8 C* l7 m4 ?9 g6 A/ D

3 P6 G/ @& S( u# {0 y9 T  F. {: i    BYTE  btIsIDEExist = 0;& A' i' s& K+ S% ]2 U6 y& d2 q
    BYTE  btIsDiskExist = 0;4 g( B& I  Q9 L. _6 }6 [1 j! s
    WORD  wOutDataBuf[256];
# I8 g$ g/ L& T- U4 f8 `' X7 w% O) s# c+ Z  u7 L5 s" _
    BYTE  btIsFirst = (BYTE)bIsFirst;
7 i; C9 n1 h9 _# r# g& s
# a7 _' u9 G  H, {) P% ~1 A; G2 S    const BYTE btBit00 = 0x01;
5 h  _& ~( n+ {5 X5 P- u    // const BYTE btBit02 = 0x04;8 C: k' u: M+ t  `+ h
    const BYTE btBit06 = 0x40;' ?5 ^& z4 m4 c, X6 I, j
    const BYTE btBit07 = 0x80;
% N8 H  T4 Z) |    // const BYTE btERR  = btBit00;
5 u$ \6 @) J' F) V" X) I* @% F    const BYTE btBusy = btBit07;
4 X' J# O8 K/ F9 T) T' d' I    const BYTE btAtaCmd   = 0xEC;
( s, q* M  D, q. H    const BYTE btAtapiCmd = 0xA1;2 x9 i; K3 K! n. e' R6 C. @
5 v5 `' J5 Y* E3 X( D
    __asm
8 j  N" u& V3 n! s5 J    {) @  U. T# L! i5 b# `) a; j
        // 必须先执行这条语句
: m' v! ?3 Q( U8 n2 l8 n; ~9 h        JMP EnterRing0
7 K- v: A' Z) O8 l- M8 m! s( E
" f7 p( z% F  L: _8 t, R( S* \) ^        // 定义过程
" E, I- k6 R! o! N9 j        // 等待IDE设备直到其不为忙为止
5 }$ v  w% y) w, c  t: G        WaitWhileBusy proc
- N0 h/ S7 z- A) a; o
9 A( X7 j& a3 X' a- s; ?        MOV  EBX, 100000
  b, N+ t% _( c  G        MOV  DX, dwBaseAddress
5 B" W' b5 P2 L8 p6 l+ L9 b        ADD  DX, 7" X+ H5 y0 O8 z  z
- }, b1 R) `4 c2 t" v
        LoopWhileBusy:& G  {& j8 n$ n7 F

) g, J" P# @7 Z7 B+ I        DEC  EBX
( @  Y" P; k# F5 v        CMP  EBX, 02 S$ J6 d& L3 N  ^# R# n1 \
        JZ   Timeout
  ]6 z4 t* N, x5 _( A        in   AL, DX
2 q$ i- b# v8 V% p/ A/ R        TEST AL, btBusy1 n6 w) j6 R# z# s
        JNZ  LoopWhileBusy: }0 b8 |$ Z  A7 J3 x7 d  `
        JMP  DriveReady
1 Q8 {9 m  b8 n, X: S1 W5 V4 `8 M+ P  U8 A. |0 E% v' O
        // 超时,直接退出4 G* }5 f3 Y& c. R2 P
        Timeout:
- O- j& q7 a1 v        JMP  LeaveRing0
/ G" f7 D. i, B+ y. z( K        DriveReady:0 G0 q9 c: f: k1 v' f. m+ j" J4 B! f
        RET
# b2 J9 Y" g( }) A# G8 Z/ V" W        ENDP   // End of WaitWhileBusy Procedure
; }  T: f$ i' a7 c4 i" J* d9 q$ I) Y: a/ z$ O/ E5 i/ _9 `# I6 s, [% O
        // 设置主盘和从盘标志+ p' h* S9 O7 @, r/ C& X: j
        SelectDevice proc
3 l' k$ ]/ G* j8 }
5 v8 r% f1 X/ f        MOV  DX, dwBaseAddress
# q1 ]) |$ j- p% g8 _        ADD  DX, 6* y- K% M  S9 I1 B% c/ J
        MOV  AL, btMasterSlave% ^; {/ _5 a0 i7 C6 m+ j
% X: ?! n, s7 L' H' D# @0 {
        out  DX, AL3 L) ^+ \! s' A2 X7 h
        RET
4 V8 X9 g% {  r/ U! X  b' N
3 E" `- z  M! ^3 A8 p: o        ENDP  // End of SelectDevice Procedure) l% k! D; D7 T8 [& F7 u

7 Y! j0 A4 ?' [! F! x" g+ p        // 向IDE设备发送存取指令: [! \1 I5 U; G% j& f, d
        SendCmd proc, L, y1 s) D& m2 }9 r* K

1 h2 y+ E; Q$ ~, y# T        MOV DX, dwBaseAddress7 `( {) y% M1 u8 P1 z  L" s
        ADD DX, 7( c$ ]% }+ D/ n4 }7 F4 T: V% x( u2 \
        MOV AL, BL // BL是主从盘标识,在过程外设置
+ P- B  Q& c1 A. x        out DX, AL6 a( O7 ~4 B( e  |; S; d
        RET; V5 ^" K1 r- J! h& X5 z4 H( C
        ENDP  // End of SendCmd Procedure- g+ n' U8 X7 y1 w0 J
+ W* T- Q. i/ R3 _6 ]
        // Ring0代码! a6 H* p6 |0 |$ v, E/ X
        Ring0Proc:
- {4 D9 l0 d0 B# h: N! L$ z2 v        PUSHAD& @3 K( z  `+ r$ s" G
        // 查询IDE设备是否存在  m6 `7 d% u4 E' a- q5 R) J
        MOV DX, dwBaseAddress
9 n, Q0 ^. R& A& A        ADD DX, 7# l! e" c1 n; ^5 e/ s0 o* M
        in  AL,DX) l! C& R( ?! _7 R' j: l
8 \, m6 o+ f# |
        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
& A  ~& Z7 w0 h8 d) r/ e        CMP AL,0xFF' s$ X; E: L9 S, y8 p1 U
        JZ  LeaveRing0' p. _/ L& q& }. J% i" p1 T
        CMP AL, 0x7F
2 V2 v9 C- |( ~        JZ  LeaveRing03 D7 }; f5 H2 r" x
* d/ O3 D, Q6 _7 ^& t
        // 设置IDE设备存在标志: n1 m! }# q; K8 E1 \
        MOV btIsIDEExist, 1
( ?/ o/ O- b& r& \$ q
: D6 o+ Y' a6 z; Z" k$ O9 g8 t1 ]        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
% C, N! L+ [' M3 S4 O        CALL WaitWhileBusy
" y3 o/ ?# U, y: H        CALL SelectDevice
+ l5 Q- I6 i' j) j3 L2 t2 f* x) p; x( f+ i& u
        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
2 J& F0 ]4 E+ A" A        CMP  btIsFirst, 1  _! {3 f% i1 A1 Q, a9 W; r
        JZ   LeaveRing0
4 v; w4 Z# n% G; e3 M2 K
* Y6 Y0 n4 O& r, s8 r        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
  O" l& J- M# W        CALL WaitWhileBusy; c/ y% J; z# T9 D2 l/ [! C2 R

% F& c1 B& \; ]5 U& m  f' n        // AL的值等于cBit06时,不存在驱动器,直接返回
! `( F5 G  H. P8 r8 ~        TEST AL, btBit06" N8 x4 d# \* J8 {' [# n% s$ V
        JZ   LeaveRing0
  @9 P, L. y$ |# _* ~% G# A
" U+ |0 t9 A9 W- }; e; l) Q        // 设置驱动器存在标志
$ _( E9 O: A' K* r! A3 j        MOV  btIsDiskExist, 1; ^$ e0 ]7 B9 r% C

: z8 I4 B* v5 \5 G2 y        // 发送存取端口命令8 V" e( |7 e. ~
        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
( U. P2 {' P* d0 t. `2 @7 M, n        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
9 y8 z( b7 g* @* Q5 a        CALL WaitWhileBusy7 N% q) ^. }2 n+ v' m; b- @
        CALL SelectDevice    // 设置主从盘标识
, J* p! N6 O5 [$ @4 A; [        MOV  BL, btAtaCmd      // 发送读取命令& O$ b2 k3 Y9 L2 ^0 H
        CALL SendCmd/ M8 M: m6 i3 f% @6 E% C" _
        CALL WaitWhileBusy
" t/ \: M( ~& H& x' E+ t- @! S, |/ {( u
        // 检查是否出错
7 ?. ^- }+ g. ], U" y) Y        MOV  DX, dwBaseAddress( C( i  w0 H1 H! [2 [+ C( f; }
        ADD  DX, 7# m5 y! S; R3 H  x# n

5 }' U4 t# N8 R2 N) n. Y/ }* [' @        in   AL, DX
* E% a) l. {! N3 I  S3 {" N# v" E' W' Z: F7 x: h% M
        TEST AL, btBit00
3 u# A5 o( _/ p2 k/ c: Z) `        JZ   RetrieveInfo   // 没有错误时则读数据5 C+ g+ h2 G" i& J1 k1 T3 ~

1 N! H$ G; z. X* a" `* g, ~+ s        // 如果出错,则进一步尝试使用ATAPI设备命令/ h1 C: x* Q/ v5 m0 Q7 s/ Q7 Q
        CALL WaitWhileBusy
& R9 r, `" G' {/ M2 l9 i        CALL SelectDevice# S- J. z- P! r+ ~. t' D# L& T/ D
        MOV  BL, btAtapiCmd
) r" K; ]* t! `5 t4 v        CALL SendCmd$ x5 \& F5 z2 J  L9 h( M8 @
        CALL WaitWhileBusy7 d: {' x5 |9 P2 r
( v5 Z% s1 C, |9 b: G4 V- h+ R
        // 检查是否还出错$ S; K1 l. b- P; m
        MOV  DX, dwBaseAddress" G; Z3 D# N5 h6 k
        ADD  DX, 7- ~+ D& e' B/ T. p7 a5 N1 ]
        in   AL, DX
# w7 s5 L- \1 b; u9 Q+ W        TEST AL, btBit00( K8 u' o" _2 t2 \' r1 X9 m  [$ h; P
        JZ   RetrieveInfo   // 没有错误时则读数据  n) w  s, ^% t1 _1 k: C9 d( l
        JMP  LeaveRing0     // 如果还是出错,直接返回
3 Q# f6 L5 t. r& p
" d, X0 F% x- u  {5 X9 |8 H0 ~) j6 K        // 读取数据! J6 }$ K$ P8 J  o/ V. x, }
        RetrieveInfo:
# {4 Y; e: i2 A# Q- t; b9 w+ z# `' N
        LEA  EDI, wOutDataBuf. W; r4 ~2 J1 k0 z5 W0 s0 _% H
        MOV  ECX, 2567 b+ ^2 X0 f' p. [  N
        MOV  DX, dwBaseAddress
) c$ F9 k; M/ i+ B% M        CLD- W% @8 E8 K& B$ L+ R. `+ g  T6 }
1 w0 _6 L+ Z3 x- d- y2 \5 t6 q: q/ y
        REP  INSW
4 |/ I& p- U9 Q9 q  |& O8 n' Z7 n* j) V. B
        // 退出Ring0代码
" f+ Y1 v4 }% z( ]' ^9 Y        LeaveRing0:
' {! c) ~. b& K" x
# f5 X" q" O1 t# _; X0 I2 P$ }$ U        POPAD
' l9 t/ e/ c6 f4 E/ P) W! }        IRETD
: R. c+ E- C/ K+ L( W
+ B& o; V/ o' D& E4 L: l2 `        // 激活Ring0代码
. I6 U( O: ]4 X" s        EnterRing0:/ k- z% E- _4 E* E. e

( [8 I6 K* n+ V8 D        // 修改中断门
* _# d: {8 \/ ]4 c( c+ Y' M$ P. T' I, a        SIDT FWORD PTR btIDTR1/ j* O. ~$ i! B
        MOV EAX, DWORD PTR btIDTR1 + 02h( Y6 h4 j5 x+ s/ w7 G5 Y0 o. S
        ADD EAX, nHookExceptionNo * 08h + 04h
/ o0 [& u% h- ^        CLI& ~  c7 g+ t* f& v; L
, ~) E3 _: C6 N& ^- ], s' c
        // 保存原异常处理例程入口
5 d" W- x: w# J: Z        MOV ECX, DWORD PTR [EAX]
; @9 ?5 h5 e& F0 g* A* I( o        MOV CX, WORD PTR [EAX-04h]
3 c! Q) ~7 J4 S, T        MOV dwOldExceptionHook, ECX
; |8 L9 L. Z) f& l8 G5 s
. u" _" ^2 G( m- Y  T* P        // 指定新入口
8 F) y: N6 k. r4 ]: r: D) q        LEA EBX, Ring0Proc
9 ?% z% E3 R: K+ U, ]- W" j. t% x' ]        MOV WORD PTR [EAX-04h],BX  H1 D* J" \( ~, Q+ U1 A( P
        SHR EBX, 10h
3 U( I! I5 X5 Y6 V& S/ n& Y        MOV WORD PTR[EAX+02h], BX# g9 B- d2 V4 w' @% c4 k

& d6 i* Q8 D, `( U" M- ]' i        // 激活Ring0代码
' j. E- g3 i% _2 \: K3 r' y! @        INT nHookExceptionNo
# x3 ]( u. S+ |) |3 w, C2 E1 @6 N/ Q$ ~2 k$ ^( x
        // 复原入口
, X; X4 C" L% B/ w7 X6 K+ ~        MOV ECX,dwOldExceptionHook5 D/ K4 i& Y, w0 y6 d
        MOV WORD PTR[EAX-04h], CX
2 }, O" C2 N5 J; o( h% d$ l        SHR ECX,10h
! ~, a: Z/ u/ h. u6 r$ c& v2 t        MOV WORD PTR[EAX+02h], CX; P3 a! j+ I. L7 F
        STI
/ j8 }) q7 R5 t1 A2 e/ o. {    }% _. ?- F; k* x% `4 K* d- z% Z: I
    if(!bIsFirst)4 m4 U) o3 L# y- t0 f- C
    {0 f7 L0 }" e# G
        bIsIDEExist  = (bool)btIsIDEExist;
- _, n* j- G& {; }        bIsDiskExist = (bool)btIsDiskExist;
" ~+ H+ C9 T9 q* r) b7 l        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));" G6 J9 E5 A4 {, b
    }# |7 K( l6 a6 y
}
3 C8 H% W0 \1 t2 {//---------------------------------------------------------------------------: A+ }: x5 E/ u4 C: Q. d
// 调用方法:
1 n. h" W+ v( zvoid __fastcall TForm1::Button1Click(TObject *Sender); h# c" O' {& ]: f( `: V
{6 _( a- y6 F  B' Z8 u& g. l
    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);, ~( @/ s$ F! G$ E' p1 w$ E
}; k( B' Q5 A* o9 U' Z) K# j
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-8-14 02:10 , Processed in 0.020654 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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