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

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

[复制链接]
发表于 2008-1-6 19:59:06 | 显示全部楼层 |阅读模式
代码框架,你所要做的仅是修改WQL语句,具体可看MSDN。以下代码为简介起见,一次返回所有的CPUID或硬盘厂商系列号0 s& E( ~! o! C! [) Y0 L

  1. - f3 n% _; f- E) S9 _8 R$ n
  2. #include "StdAfx.h"
    - v4 E$ O8 ]5 x7 R) g
  3. #include ".\puiddisk.h") j+ c8 Y" @' y* M/ S& F$ g
  4. #define _WIN32_DCOM
    4 J3 `) B# k# g
  5. #include <iostream>* n) ^1 r* M9 ]# q7 K; J
  6. using namespace std;; {, j. N- \, h
  7. #include <comdef.h>
    ( `$ {+ [) k* n( Y( o8 h! h1 n2 `
  8. #include <Wbemidl.h>
      T; R5 b8 W7 N1 O9 v5 ?/ g5 Y
  9. " N; k1 Z4 |& k1 t; B2 _- {
  10. # pragma comment(lib, "wbemuuid.lib")
    8 J. H0 Z6 p1 k9 e7 Q& }
  11. CpuIDDisk::CpuIDDisk(void)' O' y! U  o% `; }
  12. {! `& Y0 ^. C3 R0 z7 U/ Q/ Y- f& P
  13.     GetInfomation();% O9 J9 k8 q9 j' e9 w8 d
  14. }" e7 E$ ~# V1 A' v3 Y' i7 E

  15. 2 v$ y3 t% B3 b$ l- ]& i
  16. CpuIDDisk::~CpuIDDisk(void)
    3 D" {  c: p+ _. p6 g% V
  17. {
    4 B- {* {* h% \7 e$ \( g
  18. }
    ' |4 d4 @4 q, v' ?
  19. int CpuIDDisk::GetInfomation(void), d# g( O4 i0 }3 Y9 Q* a
  20. {
    & V+ }# `" G$ k* w- {
  21.     HRESULT hres;! G: j3 ~, Y7 V8 o8 j7 d  }
  22.     //步骤1:不是必须的,COM只须也只能初始化一次
    8 w& W  ?9 ]3 ^  {5 J1 T0 G
  23.      hres =  CoInitializeEx(0, COINIT_MULTITHREADED );
    ) a% Z5 J: W- }& b2 R
  24.     if (FAILED(hres))
    ! H3 f& y) J$ w7 u# Q
  25.     {
    : a* N6 L$ y) B2 V
  26.         return 1; //初始化COM异常:注意,COM只须也只能初始化一次: n: [% }* z3 S3 ~9 o
  27.     }
    6 Z: E0 o" U! y" V
  28.     //步骤2:不是必须的,COM只须也只能设置一次
    ( C$ `* F: x# z  c+ L
  29.     //Set general COM security levels
    1 c( [! n1 Z0 k0 x& h9 x$ R; X0 h" y
  30.     hres =  CoInitializeSecurity(4 u1 f$ n# [5 l2 I! v0 C' s
  31.         NULL, 7 \: q3 ]. o& x$ t
  32.         -1,                          // COM authentication
    8 H- h9 [5 P4 Q" }4 Q
  33.         NULL,                        // Authentication services. t; K9 l* o2 ~" ?) k5 E' @5 e% T  X
  34.         NULL,                        // Reserved
    6 q% R( \4 q' k+ p2 a
  35.         RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication " P- t$ N4 j1 ?! t! d! `; h& t
  36.         RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  2 Z( K9 Z$ ?" \+ x& C
  37.         NULL,                        // Authentication info) s( ~& S* Z) A- l  q
  38.         EOAC_NONE,                   // Additional capabilities + K7 p( N& O* [( ?
  39.         NULL                         // Reserved# f% d+ r& N) \' G0 x
  40.         );
    - T$ p! T7 P# C$ D% A  d
  41.                      
      ]( v" {/ J9 V+ z8 i( U* o
  42.     if (FAILED(hres))
    * a; b5 h+ t" @0 F
  43.     {7 {+ \6 U6 A, U( L: f& u
  44.         CoUninitialize();
    ; B& ]% {. Y# w1 b
  45.         return 1;                    // Program has failed." ?; h! P# h0 F# K' f* ^
  46.     }9 [" h) Z! R# N7 l
  47.    
    3 W3 l( Q3 K0 ~1 F3 w1 ?
  48.     //以上不是必须的,若已有“::COMInit();”,则要跳过' B, a6 @" ^/ N* W/ z: d
  49.     //步骤3: Obtain the initial locator to WMI
    6 M4 D5 Y+ v3 @; _
  50.     IWbemLocator *pLoc = NULL;( |2 }8 |  j$ v- O5 s
  51.     hres = CoCreateInstance(( i. Y3 B/ V9 W( A- t) K- X, J8 b3 K$ B
  52.         CLSID_WbemLocator,            
    + s: z: L4 I  s  T& B/ K( J; l
  53.         0,
    7 s5 R8 m, a4 l7 w
  54.         CLSCTX_INPROC_SERVER,
    " t7 A0 x0 |9 M. x
  55.         IID_IWbemLocator, (LPVOID *) &pLoc);# V8 c8 V; k! @9 g/ [% m

  56. ' U2 a- r$ E, |- C% W/ ]9 K
  57.     if (FAILED(hres))
    & F5 E& [' u/ s/ [" {$ b
  58.     {0 g  D- a5 D9 Z; W3 B: X* S+ A1 N
  59.         CoUninitialize();# g+ ^& M8 G( G- S
  60.         return 1;//Failed to create IWbemLocator object
    ) p1 \% a# B& {0 Q) ?' `- t
  61.     }
    5 ]3 ^! b9 ?! s* h4 o

  62. * A5 u2 V  Y- [# h
  63.     //步骤4:Connect to WMI through the IWbemLocator::ConnectServer method
    ( ^  ?$ U' D: Y6 j
  64.     IWbemServices *pSvc = NULL;
    7 I5 \. ^' X" P: r, J! U
  65.     hres = pLoc->ConnectServer(
    : b& M- |) f% `" Y
  66.          _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace# O! F% V' s( N' k
  67.          NULL,                    // User name. NULL = current user5 x" g7 Q  ~: R+ F) s8 ]0 ]+ O4 s+ }6 o* `
  68.          NULL,                    // User password. NULL = current
    + U% `3 N8 h! N2 e7 l- x
  69.          0,                       // Locale. NULL indicates current$ y" M* R' P. R; h
  70.          NULL,                    // Security flags.
    ( _9 K+ M5 S$ `$ h9 A8 z! W
  71.          0,                       // Authority (e.g. Kerberos)
    5 v4 P% C, F7 w' l1 `
  72.          0,                       // Context object
    1 X  I% y7 {% o
  73.          &pSvc                    // pointer to IWbemServices proxy
    : j+ {1 H8 v1 l9 `1 x
  74.          );
    9 U, Y& b( @$ T; ^
  75.    
    # }$ Q; p* x- m1 K8 a! J4 O3 u; x
  76.     if (FAILED(hres))
    / ]. b9 k. B: e- I. z
  77.     {
    ' A/ ]: ~  S4 j+ A; e7 ~
  78.         pLoc->Release();     
    6 q* f3 i8 Q' x1 C9 ~8 g) z
  79.         CoUninitialize();3 d/ @# Q/ ^5 k8 a
  80.         return 1;                // Program has failed.4 o- g) ]% G( `9 ]4 m! e1 W; }2 t2 [
  81.     }, V& v3 o" O3 {
  82.     // 步骤5: Set security levels on the proxy7 e- g7 G* l% J+ {7 i8 {" H
  83.     hres = CoSetProxyBlanket(
    * G6 _: J, ]2 n! e
  84.        pSvc,                        // Indicates the proxy to set- q& ]7 Y0 D7 E. R! D2 k
  85.        RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx3 J; q$ L2 k( o! D1 x
  86.        RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx  z: a- W; n% }3 w1 F7 n. B
  87.        NULL,                        // Server principal name . R) X4 d; a+ j3 ]
  88.        RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx
    * U9 Y0 @9 H4 N$ Q; N+ c
  89.        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx9 X( A6 ]5 ^# {! f9 V6 D; t
  90.        NULL,                        // client identity0 y  N6 ?6 H3 k/ R9 U8 h
  91.        EOAC_NONE                    // proxy capabilities
    ) r- B1 Z4 v4 i7 K4 r  l+ t( D7 r
  92.     );
    2 @; m, H+ _4 k5 ~3 U

  93. 0 {. L, N! c* I7 R! s, X
  94.     if (FAILED(hres))$ O( K! s5 c7 k2 P3 [9 c. _
  95.     {& C0 R5 ~1 B- ]4 \& M; D
  96.         pSvc->Release();- P4 Q- R9 ?' t1 n* F
  97.         pLoc->Release();     0 J+ f' P, H$ x; t- j
  98.         CoUninitialize();3 Z  X) _: d- x: w% M* E. f
  99.         return 1; ! P' k6 Y& ^5 u- n. ~0 P
  100.     }
    3 |* a- j7 M4 U' B' v- U/ m. }% V
  101. 5 l8 F  n; k  o' Z) H. u: ?
  102.     // 步骤6:Use the IWbemServices pointer to make requests of WMI ----, x1 L8 S7 m; |! V* T& t; d$ y: b
  103.     IEnumWbemClassObject* pEnumerator = NULL;2 S8 u# j. @: K. T
  104.     //计算CPUID
    . {7 b% ~$ d' {2 ~. o( T  X
  105.     hres = pSvc->ExecQuery(
    & w: @$ W2 {- V4 Z& I
  106.         bstr_t("WQL"), 7 n& ?3 G! q5 b# q
  107.         bstr_t("SELECT * FROM Win32_Processor"),//Win32_OperatingSystem
    ; a: C6 v% s" M& H0 S/ Y
  108.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
    ! x" ^6 J8 _7 W* q5 H/ z1 j
  109.         NULL,
    , c4 }  b  {4 u+ a. r
  110.         &pEnumerator);" p# b3 N$ U( `% V
  111.    
    ' u! T5 u6 i3 |1 O7 x# q8 ?" u$ K! T# ?
  112.     if (FAILED(hres)), g7 c8 G" U- C- o
  113.     {4 t! o! e4 ]0 C$ b2 z. P
  114.         pSvc->Release();
    & L; x/ w$ f/ t4 [9 Z/ t& M
  115.         pLoc->Release();% ?4 g/ Q3 T* N; }: P  C
  116.         CoUninitialize();
    # Z6 S8 `& V" Z
  117.         return 1;. y& D8 \' X  j$ _) d0 ^) B; |
  118.     }
    ' H  Y# X- C' E8 y! f  h* F# i/ ^
  119.     // 步骤7:Get the data from the query
    & ?  P( F, A* B; a3 u- O
  120.     IWbemClassObject *pclsObj;
    ! ^: {, q" O& c+ D, B0 a! J$ z* l
  121.     ULONG uReturn = 0;% F" S/ q' K, e8 j$ w
  122.     while (pEnumerator)
    & Y6 D0 X; @8 ?1 ]  ]
  123.     {
    ' r# i: f  w, g# R$ D" y' x
  124.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
    ! I( y8 U0 a6 j& @; U
  125.             &pclsObj, &uReturn);6 U; j0 {" w" C+ F( `# U
  126. 0 X  A( k! P$ \* _/ ?
  127.         if(0 == uReturn)4 {4 ?8 A7 v9 U/ ~
  128.         {
    ! l# h6 |2 g! X  T
  129.             break;
    $ e  F/ {$ \! x* K9 _" }
  130.         }
    ! b1 \0 u* y+ H& n
  131.         VARIANT vtProp;7 ^3 K# E* K9 Q8 W8 v; S8 {. R* Z) z, t
  132.         VariantInit(&vtProp);: F& ?* Z: m6 G
  133.         hr = pclsObj->Get(L"ProcessorId", 0, &vtProp, 0, 0);
    , u( x2 |$ y% U& l! b/ g
  134.         strProcessID=_com_util::ConvertBSTRToString(vtProp.bstrVal);//strProcessID:类级变量
    , s0 }; M( w7 `
  135.     }
    ! G7 v. e! u3 k, Q% {5 u

  136. 9 r$ U& `0 y5 \' n2 P
  137.     //计算硬盘系列号
    - w- O; W  b( a! A1 a# b
  138.     hres = pSvc->ExecQuery(5 ], Z8 |3 C5 t: H$ ~6 V; j0 ?0 P% ?
  139.         bstr_t("WQL"), 9 q  b: _6 v0 ?* T/ c% g
  140.         bstr_t("SELECT * FROM Win32_DiskDrive"),
    4 G3 v4 P! r. e& H
  141.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, % i& G! a2 H4 l2 t: j
  142.         NULL,
    8 b+ k) }2 T# F( |% f& l
  143.         &pEnumerator);
    . f3 k, E( p9 F

  144. % q# |; Z. b+ _6 l2 H6 U6 ^9 W
  145.     if (FAILED(hres))# h  s& d8 D5 p2 \' o
  146.     {
    6 d% ?/ l4 L4 L# \/ _( H8 f
  147.         pSvc->Release();
    ! E9 Q4 G; Y0 X, l$ I, L" ~7 f
  148.         pLoc->Release();
    - {6 k5 u; E; ]
  149.         CoUninitialize();
    " [, p- k0 y! ^' ]/ m, U& r1 m
  150.         return 1;
    3 ]' e- s( I4 g9 Z( |# T4 o2 e
  151.     }
    & k- W. Y2 e  p# ]
  152.     while (pEnumerator)7 B- O" A; S5 V* s0 e( m+ J6 }
  153.     {) I+ c# t) m7 N
  154.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, - q1 ~! d4 I$ [# T
  155.             &pclsObj, &uReturn);
    ! J0 o. z4 y2 T. ?' [7 m) Y

  156. 2 |& i# @) u3 X- ~
  157.         if(0 == uReturn)
    # R0 h9 i2 Z* g, }6 c5 Z8 R+ D8 l
  158.         {$ D0 I$ o4 o7 c$ f1 p6 [
  159.             break;
    9 `  x7 t4 R/ l) j* J  A6 l9 Z
  160.         }4 k5 {  p9 z4 p8 @0 {3 z1 `
  161. ! F( r; x/ p' n) e) M( W
  162.         VARIANT vtProp;( {5 |, z) ]! C! y0 Q2 ], H5 \1 `( e
  163.         VariantInit(&vtProp);' K: _6 H& M" ]" j" G6 |( L% @& F* Z
  164.         hr = pclsObj->Get(L"PNPDeviceID", 0, &vtProp, 0, 0);
    . {3 O3 ~: o6 a6 l" D5 a% @2 H' {, N  y
  165.     strDisk=_com_util::ConvertBSTRToString(vtProp.bstrVal);
    % c- p$ e1 s! L1 v& E
  166.     }
    + j6 }. E  g+ E+ e+ R7 d+ [
  167. $ p( U- s% U" w: U, r# W
  168.     pSvc->Release();$ r$ ~- f$ t: L( @5 [
  169.     pLoc->Release();# A, U: ~! \4 n  h/ c
  170.     pEnumerator->Release();+ E, o( l# j1 k+ r
  171.     pclsObj->Release();- Z6 s' _% A+ n% p3 O/ k% l
  172.     CoUninitialize();9 X3 i' R* Q, R6 }/ e
  173. * r: T8 j5 i! G
  174.     return 0;   ; P! O, U6 ]$ H3 i+ s
  175. }- R) {" ~: }! \. n
复制代码
 楼主| 发表于 2010-10-11 19:21:05 | 显示全部楼层
本文代码经ccrun(老妖)在Win2k下试验成功.
$ o3 _6 |/ H) }' X
! `1 ~* U' {) C1 k#include <WinIOCtl.h>6 A5 k; u& d1 Q: M( _; Y0 V& A
#include <stdio.h>
5 h( K# F1 d6 ?& R; W4 O1 O8 `8 O- t% c# q; X8 Q
#pragma inline' ?; y' L  _' r2 T6 K
//---------------------------------------------------------------------------; ^# e: `3 X# y# j& |
// IDE NT/2000/XP专用变量1 b) D' Y6 N, v. D2 s
#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
6 f* I5 Y' E2 `7 v3 _6 h  p5 P1 v#define DFP_GET_VERSION         SMART_GET_VERSION
3 t* u3 n+ j# ^9 J#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
- ~* v' R0 A9 f; n0 J6 i, z  n$ ?% d#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA1 a! N4 D. p6 q
- R  M0 s- l% O& W* E; s
const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令
4 C$ |! u4 e+ O: b8 lconst WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
% s( ]$ f0 f( `( s4 t# X4 L$ r, l
const int MAX_IDE_DRIVES = 4;. }& u' Z6 Y" B: `0 z5 @; D
/ g0 U" [/ H- D: b
// SCSI专用变量
8 N" s& d$ |. u, H8 uconst DWORD FILE_DEVICE_SCSI             = 0x0000001B;$ \5 w1 Q- e) I7 {0 X6 T+ X
const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
1 C7 n& {/ A4 c0 _8 t* Fconst DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition4 z0 A) ?7 A; @7 L, u- u+ E
const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
, ~2 }; s0 L( V# a9 O
( G8 |  w% Z9 {. F! r  f' \typedef struct _SRB_IO_CONTROL  H2 p" w$ W. U: B' R! \" W" e1 Z  @
{; Q+ y; p; Q8 N' ?
    ULONG HeaderLength;5 d2 k. w5 q0 U( f( v* t
    UCHAR Signature[8];' Y% F! R& l/ D3 E* F! i
    ULONG Timeout;
! L7 k3 v' ^0 {$ I    ULONG ControlCode;
" B: ^8 M& G) b1 o7 Q# o4 y( z! `; |    ULONG ReturnCode;) f& B0 w" H2 h) u
    ULONG Length;3 @& Y3 j7 e8 t& S/ `) d
}SRB_IO_CONTROL, *PSRB_IO_CONTROL;
. I& d. g2 ?/ a7 x9 P) V8 P* C1 W, x) x2 V- B* A9 X5 J0 j
// 读取的主函数
: r* ?: r* {- P' `1 y2 i4 n8 wvoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
/ h9 j2 ]2 c: E8 S% h1 H; N8 D- J/ l' t& T
// 辅助函数
* W" m# \( c( T  Z* |0 f" r$ Hchar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
4 ^0 \: _3 {5 G8 j: ~/ B// NT/2000/XP函数1 W8 m% q+ F* q. G
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
* w  F/ w' k5 A/ P- d: l: f( {bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,3 I/ h% C: M! k0 s
        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,6 U- Y* ?3 l# M# x
        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);4 {; S1 b; c- D/ T' y
// Windows 9X函数% |' @) L/ B7 t% Y
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);/ |' @1 q2 C, x1 _5 D5 g* U6 n% d
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,, C/ S. Q+ o( U$ \3 u( @3 t! d- c
        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);  j4 W4 k; x) w8 w" L  L' ~

) T$ T) t6 q5 F6 m// SCSI读取函数(for NT/2000/XP)
4 F/ f& _* W- p8 Q, R0 XString __fastcall ReadIDEDriveAsScsiDriveOnNT();
9 @2 e, o+ C( C0 ^0 I: o//---------------------------------------------------------------------------3 g4 ^# H: M& y
// ReadPhysicalDrive. e0 v7 d- Q' }0 U
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
! [# m7 N2 t! Q6 `* D{
- G7 U) s* Y5 `( `5 x* J    switch(Win32Platform)
5 l: ?  u# ]& o4 K, C    {$ e2 P3 ?3 m3 X) l
        case VER_PLATFORM_WIN32_WINDOWS:
7 \8 u$ S- B# c- J- I) p* C! S' P0 L            ReadPhysicalDriveOnW9X(pSerList, pModeList);
, V& G/ j- b  w* w" P$ D            break;+ _; E$ v  h/ |! O, n
        case VER_PLATFORM_WIN32_NT:
- s& d% N+ t% Z$ N: `/ ~" H) q0 m$ d1 y            ReadPhysicalDriveOnNT(pSerList, pModeList);; A7 N5 ?: }6 w0 X  Z, O* k
            break;
) A$ v0 G* h& Q1 w" F) A/ k3 M        default:
: O2 _, @6 ^3 J; }/ X            break;7 P/ w0 \0 ~! ?2 Q) n2 V1 q
    }
$ [7 }; M) N2 x* {( Y7 D}
/ E# ~( A+ O1 B5 e5 d//---------------------------------------------------------------------------2 E7 K) p" K0 m3 }6 b
// ConvertToString8 @5 A5 i. f- m& F, E( e  L
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
- T) }1 V' F) E, r; C5 T2 f{: c& i! j  w+ E0 s
    static char szResBuf[1024];1 P" o/ ~1 Q3 H# x. v3 t
    int nIndex = 0;1 m  c8 @5 a( ^% b
    int nPosition = 0;
) F1 ^: X( |6 z2 t$ y5 j' A5 C( w* }# U8 ^" K
    // Each integer has two characters stored in it backwards
. c1 h  M6 U* ]4 [7 l    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)3 J0 o5 A6 a% p, D+ }
    {2 |. Z: v3 y" k
        // Get high BYTE for 1st character9 v7 Q2 [5 S. l( H1 H9 {- H
        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);1 b: U) c1 ~3 ]$ z- X
        nPosition++;
. O- {$ S* n/ H/ M' J. Z/ ^, m+ F% M* ~. h! u
        // Get low BYTE for 2nd character
0 [9 y" l3 b, C( x/ r; z% Q8 A! U' F5 z        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
' I- {$ d" T0 ]+ Q# y$ t- g& e        nPosition++;3 ~( y" w( w: W
    }
% v) I% t) ]; o8 j; }: T* l& ^) Z5 o9 W
    // End the string) e' m6 z7 b, Z& w
    szResBuf[nPosition] = '\0';4 ~2 z& }$ l& ~6 r

( u9 k, l1 A) L8 {) o6 `    // Cut off the trailing blanks
4 x$ d6 l3 A0 f5 X- K5 Z    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)$ D( H* o3 w9 ~$ a1 Z' ?/ \" `( j, P
        szResBuf[nIndex] = '\0';4 O6 T" S7 W) h  h8 i# B# i

% s- R% F, T$ Y! i/ b    return szResBuf;) z& [# a& W1 F! D! }8 q3 B. ?
}
5 o3 X- ?" `# f! o7 q$ m//---------------------------------------------------------------------------
2 I2 O3 G( l, Z3 l% u// Winndows NT4/2000/XP 代码4 h- s- d  G# W* w
//---------------------------------------------------------------------------
9 v) r9 _1 H' b  |" \// ReadPhysicalDriveOnNT' `8 U5 [! |  z5 _0 |6 @) X
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
- M6 L7 z* R/ ]8 J: Y{
7 C& W/ r6 x3 |2 e6 n7 v' C2 N: {    // 输出参数$ T. w& C  D+ B3 v3 F) ?# }. {7 j
    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];+ v2 k& L; {% B6 L0 @  E" W
; ?/ U, Z, F! a
    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
; J' Y, V- \+ O- W" J    {
; Q% _! H4 E5 Q9 I7 C6 f' R0 w        HANDLE hPhysicalDriveIOCTL;
2 F) Z- R$ R7 A' v2 _  k/ \        char szDriveName[32];
2 y( L6 d2 j# `% u- m# J
0 e2 E, M; [) }7 u  C        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);  I/ y; H4 Z1 p$ C( `+ T- U6 z% E
        hPhysicalDriveIOCTL = CreateFile(szDriveName,
% z5 ~! J' M% |- Q' `* k% Y* ~' `# l                        GENERIC_READ | GENERIC_WRITE,
; I) u% R2 c- E) u, q                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,; B1 w; a6 x7 `0 `! x
                        OPEN_EXISTING, 0, NULL);7 x0 [, d1 b" }) b; q3 u# w
( z) C& a0 Q( R1 C9 ]2 h2 m2 `
        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)4 @0 B! [5 m* U
        {  V, x* u- w$ P3 k
            DWORD dwBytesReturned = 0;# Z3 B$ M# H$ l
            GETVERSIONOUTPARAMS gvopVersionParams;* d$ _1 D/ p0 [: i6 R
  b4 [, J; `; H+ N3 J+ ]2 ~
            // Get the version, etc of PhysicalDrive IOCTL6 v/ L' o. f5 X; m" L
            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
1 _7 G+ ^  b" `$ c
# R) n  `9 }: ?4 [3 M" I# }            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
  V* T0 [' H8 k+ |                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
/ Z9 }$ I  C) i8 r$ S                    &dwBytesReturned, NULL))# g4 W6 U# f/ B2 z, T, x  D
            {' `/ W! k7 w& A- [8 j
                continue;
; ^& d+ X9 m! E( I8 i0 g            }+ T7 Z7 `- R+ z- N

7 L1 Y% d1 w* q2 F8 U3 l            if(gvopVersionParams.bIDEDeviceMap > 0), S7 a3 f4 I8 Z2 w' P
            {
& F( ~! |1 n% }. M4 p8 M! x                // IDE or ATAPI IDENTIFY cmd
% j0 H6 V( A) ~! K4 x3 d9 q                BYTE btIDCmd = 0;
1 R+ T! _: T* U. Z                SENDCMDINPARAMS InParams;
0 O, K% x, T# t: l; p8 {                // Now, get the ID sector for all IDE devices in the system.
) y5 ~* t% s* u, e$ R7 w                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
& T3 t( E4 n5 O0 n$ B( D                // otherwise use the IDE_ATA_IDENTIFY command: u5 m- W8 }' D5 X" s6 j
                // 具体所得结果请参考头文件中的说明: }9 i/ q" D9 b
                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
, }1 M- L; J' N                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;  h2 t# w' v  |2 S3 Y1 J% o5 l
                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
! E  j3 D! @- z$ {                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
8 X# }: i1 e4 L$ |
3 @2 V0 F; s& Z$ [) q5 ~0 D# `8 n: g                if(DoIdentify(hPhysicalDriveIOCTL,) M& b: h+ d; R8 b6 h" z6 Y* ~) u
                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
: D. z9 A' ]" Y8 Q                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))5 R: N- U7 O! r( @9 _
                {
! }! x* g, c2 ^                    DWORD dwDiskData[256];
9 T9 m0 l# g. j: C( H% @                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
' J  N8 ]: p3 z4 B8 f& o' O                    char szSerialNumber[21];& G8 d' m: i% S
                    char szModelNumber[41];
& {# G- o6 f' A9 }, t( o- L1 H" \: Z6 \* y' Z
                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
( j7 [$ ^5 {$ E) w. l                    for(int i=0; i < 256; i++)9 C+ u+ C: x1 d7 F' Q) O( Z
                        dwDiskData[i] = pIDSector[i];" C$ V% j% q; {5 M% M
                    // 取系列号/ j' r/ q+ V2 u! _% P6 t
                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));: c) h/ d7 [" W# R% K# ~
                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
) m- b, B1 V2 m, k/ X' f: ~8 c) ~, X6 _$ h& U* v0 X0 ]
                    // 取模型号0 p0 \/ i2 A+ H2 o4 q
                    ZeroMemory(szModelNumber, sizeof(szModelNumber));
+ s) T% }. Q$ \+ O, Q; T2 f0 Y                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
7 r. \. ^' h8 v
+ @7 Q$ D5 x1 d/ y" S$ R, N                    pSerList->Add(szSerialNumber);! A8 u: M, x; Z9 F
                    pModeList->Add(szModelNumber);1 p1 F. U! F1 k: P( _% \. R
                }0 F3 l( q; ^8 v" |1 P8 Y
            }
' y9 u% N  h5 G7 P            CloseHandle (hPhysicalDriveIOCTL);
1 B' \" l6 b/ {4 g- A  ~7 t4 @        }  p  `" Q! ?* Z0 b8 d
    }* N8 A8 v) Z: k7 Z. i# U1 m
}5 p1 Y. ^, w# j' r6 _) x
//---------------------------------------------------------------------------
3 i6 T6 ~" u2 k  r2 c: |// DoIdentify- c& V' C$ l# N/ B# [4 l# |$ H% C
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
" F9 p0 q0 k  l" }/ B# F+ a. J              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
0 c( n1 s. q2 G# j) a- s' C$ N+ ^              PDWORD pdwBytesReturned)
) B9 i4 J0 ?& ~- N{
) U2 ?6 i4 K/ l: E+ ~7 i    // Set up data structures for IDENTIFY command.
8 R0 G4 k. F$ Q+ s& Q7 p9 R0 m+ K: K$ \    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
, O( X4 q: X$ ]1 E    pSCIP->irDriveRegs.bFeaturesReg = 0;
% @- {5 t6 j7 \0 v$ J# @0 {$ H    pSCIP->irDriveRegs.bSectorCountReg  = 1;
( `  N6 ?/ ]- B& F4 }6 K' ?    pSCIP->irDriveRegs.bSectorNumberReg = 1;
0 L; G' ?! o5 C    pSCIP->irDriveRegs.bCylLowReg  = 0;$ g* ]' p, @) r$ `8 T' O
    pSCIP->irDriveRegs.bCylHighReg = 0;1 L! }" o5 A$ E1 Q, l

# G1 Y9 Q! v8 V' X* E6 _+ ^+ o& B    // Compute the drive number.(主盘和从盘所对应的值是不一样的)( B6 u6 |/ i$ G% l! f$ s( a
    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;- n* E- @6 A' E* }
2 j  d& c9 ]  Z% a
    // The command can either be IDE identify or ATAPI identify.
( D3 U, g8 A: i. N    pSCIP->irDriveRegs.bCommandReg = btIDCmd;, ]8 f0 `& b* C% Q$ u
    pSCIP->bDriveNumber = btDriveNum;
" k6 u: e7 W6 o1 V' f) f    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;3 K6 a: L! ?0 z* i2 g

5 Q" e- |# v: x7 _; [    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,9 o; w. i6 j9 r6 [* f" {5 ?
           (LPVOID)pSCIP,
  E6 [: V, y  e4 e% ~2 C& f           sizeof(SENDCMDINPARAMS) - 1,$ ~- P. B9 ^) s' S6 V4 `2 W' P3 P4 `
           (LPVOID)pSCOP,
, N# O$ F  t  y/ C( t           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,4 j. n4 n- _2 t* Y. s3 s
           pdwBytesReturned, NULL);
  B/ s5 I/ v/ A) N' ~4 P}
. B1 u0 q4 T% f' m//---------------------------------------------------------------------------; t- H- A! `1 J" `
// Windows 95/98/ME 代码
$ J! ]- y: w. x4 ^//---------------------------------------------------------------------------4 @; ?) C2 V9 _7 |, a5 A6 K1 d
// ReadPhysicalDriveOnW9X
( b5 D; P: I5 gvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)8 ^0 L3 q/ A5 }$ `' r5 w
{
9 A. W+ G& Q% p1 b3 ~; d. W    WORD wOutData[256];
4 N& f0 \* ]% r( b* O0 {    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);1 h& i# y9 X$ ?
/ ~1 ~0 M" z6 S) t+ r" Y* D
    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
, E$ Y$ F; v: M1 J& F$ o" \8 r    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
1 w/ n. a1 ]* O+ E0 d# M    // 避免蓝屏的出现。(期待高人能指出原因)
. d1 D6 J* R6 D) ?9 E" A( I    for(int nDrive = 0; nDrive < 8; nDrive++)8 b' K2 M# @7 f8 R$ ~
    {- t8 L+ u3 P; s' Z+ a9 j
        WORD dwBaseAddress;* u0 y. V& l: |9 O. @3 q( q  b
        BYTE btMasterSlave;         // Master Or Slave
2 z4 D: k; m7 i$ D/ g: n9 K7 a5 Y        bool bIsIDEExist;
  f" n4 l# ~( a7 U  }! X  A) K8 F        bool IsDiskExist;! N( K- |- C  G  Y

* y" @6 i& S! I/ d& U! x        switch(nDrive / 2)& y: F/ n8 X9 Y- E2 M  m
        {- \4 y! ^# \( U6 c0 t7 X% j
            case 0: dwBaseAddress = 0x01F0; break;
; Q: S8 D1 C! w, L            case 1: dwBaseAddress = 0x0170; break;
/ R! J+ o' S: c. V* D& k            case 2: dwBaseAddress = 0x01E8; break;) Y2 s) F- `: V( o( h3 O4 C$ D9 m5 s
            case 3: dwBaseAddress = 0x0168; break;
# W9 ~& ]$ M% T        }
; v* J. I$ @) }% B; ~7 Y8 I) J8 a# r1 C* b/ h2 y- ]: F
        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
  v+ q4 p" j+ e8 L& M1 O. f
0 |+ q' r7 D- H" c        // 进入Ring0
! T- A! i+ D5 l& A+ c        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,- @7 p0 Q# U" ]
                bIsIDEExist, IsDiskExist, wOutData);
# i) {% ~: k* m# v1 @    }  I) X. f( {- Z/ U$ v; W) W  U

" B8 q& v' p; _+ k    // 开始读取7 {" M% \* L8 `$ h
    for(int nDrive = 0; nDrive < 8; nDrive++), v( V" V! v" t& ?% |* z
    {
5 j" X: B  l' l0 `8 X# `        WORD dwBaseAddress;
5 c1 C# x$ \& d4 h) a/ \        BYTE btMasterSlave;         // Master Or Slave
5 j0 b6 ?" M, T        bool bIsIDEExist;
* S8 O, `* S) T9 p% r        bool bIsDiskExist;
4 [  @. c4 b% ~  n: M  v        switch(nDrive / 2); q, ?. A5 U0 i# O* n" x5 E! O5 i
        {' B6 \8 P7 e5 X: w, K) D* Q
            case 0: dwBaseAddress = 0x01F0; break;( \: `( V! R0 ^2 s  U, k
            case 1: dwBaseAddress = 0x0170; break;
0 D6 x, t. R+ |            case 2: dwBaseAddress = 0x01E8; break;; C- H  Q5 {+ X, u' ^' h
            case 3: dwBaseAddress = 0x0168; break;2 M4 h2 ^5 n+ b3 ^
        }
0 Z% k$ z& O: w$ }
# n5 l) I# i' D& w) y; M0 _. ^        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);. w- a! D- p8 C0 q( ?) `
# t" D3 F- F( C2 F7 }; @  V
        // 进入Ring0
/ d% |% g) e! @! M        bIsIDEExist  = false;% N2 r# f+ U$ b
        bIsDiskExist = false;% [: V; K7 N3 l# o4 @
        ZeroMemory(wOutData, sizeof(wOutData));
/ {2 Y2 Y2 e. x) ^( z
8 G1 I$ R8 ^* P* F- t        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
7 p* f. Q' s* J2 d4 T4 b                bIsIDEExist, bIsDiskExist, wOutData);
$ q1 _- B! \7 d8 A7 K3 x
% Z6 P$ b: e1 }2 {! W$ W        if(bIsIDEExist && bIsDiskExist)
' x% r6 e) |0 G: f: m        {
& I$ k; u) F: F' {) j; P- Y  l3 `% W            DWORD dwDiskData[256];
! {$ W: ^- ~, s            char  szSerialNumber[21];
# H" ~: ]8 [/ b            char  szModelNumber[41];# |  ?! `& R$ w- I% K
4 D7 `- R0 `& [! ^2 d
            for(int k=0; k < 256; k++)  [9 B# v! T) Z+ K. m
                dwDiskData[k] = wOutData[k];1 V  {- Z4 V& h

$ W4 k- V* S: b3 R! k# L( X9 |            // 取系列号' C3 Z7 n. q% b& p7 j
            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));1 u# u, ]+ |" W, o6 |2 \3 `  _
            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));5 W$ O, I: U* m3 j3 a; P( d1 E
5 s6 f' V+ l: }; q
            // 取模型号8 g0 [- o, E" ?$ x3 `3 i6 P/ O
            ZeroMemory(szModelNumber, sizeof(szModelNumber));# |' O" ^2 u3 }& a7 o" R
            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
$ G$ m$ r9 |6 [2 J( b
1 E2 s& z# X: x6 M) N* E+ N3 ~            pSerList->Add(szSerialNumber);- s& i7 U1 K5 J3 r
            pModeList->Add(szModelNumber);
2 x  w  K2 m" K/ m' u% y2 ~        }8 w( J, k5 k! D; k- @' D/ X
    }
4 Y2 R' |: b5 R8 c- B  G$ u1 z    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);4 e1 l/ M$ z. `
}/ H) b5 Y" f4 M8 i' S7 Y4 `# ^
//---------------------------------------------------------------------------
) O5 J  H4 v- @7 s) L// 为防止不负责任的转载者,在此注明原出处信息,请见谅。
  S% F3 I% U) w* Q// 资料收集整理:ccrun(老妖),欢迎光临C++Builder研究: http://www.ccrun.com2 j$ l* K. e% C- I1 ~: v. r
//---------------------------------------------------------------------------1 @- x9 J: k4 x. s. w, c0 \
// ReadPhysicalDriveOnW9X_Ring0()
0 J7 k0 s. k% S+ W! ]: l! ^//
1 L4 H$ K4 p" L; s// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
! |9 ?- a! J2 X4 z: u// btMasterSlave = Master(0xA0) Or Slave(0xB0)
% K. C/ x, {: o//---------------------------------------------------------------------------: t- j7 j: C5 v+ {' w; {; H
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,! D  c* k6 t. s# \( m
        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
: r% B% J' \: [9 f+ ^1 s0 C{
" r/ ]. b. b8 Y. X    BYTE  btIDTR1[6];
/ a1 r; D1 P9 d4 x, W0 S. S) K    DWORD dwOldExceptionHook;
; `) o" Y8 A9 N& e7 t2 y2 c    const int nHookExceptionNo = 5;
- b8 u9 Q  d/ S# c2 E' s2 @
4 [0 |! m) A' p, h+ w    BYTE  btIsIDEExist = 0;
( Z1 y+ u" m2 k1 J    BYTE  btIsDiskExist = 0;
# Q" @2 i* L& G, e4 [    WORD  wOutDataBuf[256];
- D% t( G1 _9 ~+ q4 X5 s; Z) [. j' \# f! T- ~# w# j
    BYTE  btIsFirst = (BYTE)bIsFirst;
& U8 Z7 z$ M" d; s  C9 V
- K/ {; j8 E- w, Q* ?  {) m    const BYTE btBit00 = 0x01;
8 l" [9 U2 w* X$ J9 n9 \. R5 D    // const BYTE btBit02 = 0x04;6 Y# M8 n( m* i# q) K
    const BYTE btBit06 = 0x40;
& A* O8 o) |0 I: V0 v: T1 H    const BYTE btBit07 = 0x80;4 o+ H. F( [" f5 q* T; c  B+ B
    // const BYTE btERR  = btBit00;- o. Z3 C9 Q7 m! B2 D
    const BYTE btBusy = btBit07;
8 c6 S' ^# n2 Q0 L, G$ s; `) I5 G    const BYTE btAtaCmd   = 0xEC;
( c- b4 B4 B( x$ ~8 r) l    const BYTE btAtapiCmd = 0xA1;
. z9 M" @7 M0 o; \9 c# H; q) Z6 x9 A# \; ?2 m  W$ j" O
    __asm
% D+ i' X  Z9 _5 N# d3 ^; k" C    {
4 k/ |  M4 }+ i( U- d' e        // 必须先执行这条语句. n- ^% K$ r" M) E& g2 A5 O
        JMP EnterRing0/ u" F# R7 c/ F  r' P
' A0 J. Q2 g- [7 `: w
        // 定义过程
- }. l5 W4 W* {) r' f        // 等待IDE设备直到其不为忙为止
( ^! ]6 L/ t3 f, m3 c3 }  C        WaitWhileBusy proc' S5 j; ?8 W5 j: J3 S# }

/ H: D# Y7 e$ @% q        MOV  EBX, 100000" }* p( V4 T- w" A2 \. S1 f$ l
        MOV  DX, dwBaseAddress
6 s9 _) T6 a, t        ADD  DX, 7
8 M, U' F" x7 Q+ R3 N3 v2 v$ g; a7 j9 O, O! B) u
        LoopWhileBusy:: W2 A" E6 I* e/ `& c) K& t& {" V

) I8 n# j* q3 F9 F& H        DEC  EBX3 P% x5 f( H, X* y( ^2 p
        CMP  EBX, 0
% M8 M2 E# a$ ^7 U3 j        JZ   Timeout/ N# u- {9 ~$ g
        in   AL, DX, U$ f- x( g  I: Y2 K" G2 o5 ?
        TEST AL, btBusy: R& d. \+ y4 A* }' V4 O
        JNZ  LoopWhileBusy
9 n5 @1 k' l. U- d% x4 d8 G        JMP  DriveReady) V. r' {* F# N
. o4 l5 ]) T  y% q
        // 超时,直接退出" t7 n+ ]# n. t3 h/ S( u
        Timeout:" A* e# b4 K; e8 p0 k+ P
        JMP  LeaveRing0; F$ y7 a- Y. f8 q* A4 v
        DriveReady:
* l0 M3 V6 N, v! R, x: h        RET
. o& n7 d+ e- a. Q4 H& I        ENDP   // End of WaitWhileBusy Procedure7 R; ?! _7 E0 z2 p8 ?0 x3 R+ i( ~

7 p! L; v- a: z- w7 e6 }        // 设置主盘和从盘标志; N, _0 N1 L8 S2 [# f
        SelectDevice proc
/ @; h0 c5 r* @! t+ x8 V
6 @9 D1 l. r$ {6 O        MOV  DX, dwBaseAddress' P- W4 v1 w8 f
        ADD  DX, 6
2 w) A) Q0 E% r4 L4 g        MOV  AL, btMasterSlave
" |7 L1 f- w3 x) O0 D
- ~# \' V$ Y( V/ G3 Z" C        out  DX, AL$ f2 G0 }/ B; W! o6 O
        RET. v; n2 {0 ?% [2 J

% `. f) [& T# Y. c8 I8 p        ENDP  // End of SelectDevice Procedure
2 t8 S2 F$ u7 B( C; ?' z/ |# |4 d. A& _/ T
        // 向IDE设备发送存取指令
: W; f0 \3 t! X: W5 a        SendCmd proc+ Y, Y9 [5 g: P, S! `; T1 Z8 d' ~/ t
& O8 v- e# |  Y1 Y3 P) P
        MOV DX, dwBaseAddress
) ^& ~* V6 k9 R$ h5 K( ]        ADD DX, 79 ?5 k) s  G0 d2 t$ q8 u1 ~
        MOV AL, BL // BL是主从盘标识,在过程外设置
$ h# z$ Z/ K6 l: s- j2 o2 F        out DX, AL  Q/ Z0 A9 p" ^
        RET- _* V- _, y7 ]' D) i3 A/ D
        ENDP  // End of SendCmd Procedure9 k* g# L1 y) b2 g, h

) t4 n, z% Q8 W8 Z- \" a        // Ring0代码  J8 ^( u+ E/ [0 R. c5 A! F* @
        Ring0Proc:
' N! Z! r* S; k9 e        PUSHAD" I4 U2 m6 }5 n* C& `% B
        // 查询IDE设备是否存在
8 b! o( L' o, R0 a        MOV DX, dwBaseAddress! `( x8 i# q0 Z1 ^4 A2 {
        ADD DX, 7
' o; n1 U& U+ ^) C4 j  c        in  AL,DX& ~" h9 L0 T8 l2 [8 ]' K& f7 `
8 K2 \) s; E: ?: q$ _) S; _
        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回6 W# Y) a* U" |! c/ ^
        CMP AL,0xFF1 G$ q+ e; }3 x& ^- {
        JZ  LeaveRing0
% V8 {) _$ B6 Y: x6 q8 G: Q        CMP AL, 0x7F
8 g! ]. b. [3 @2 g3 a        JZ  LeaveRing0
0 b* r0 e2 \2 W) h9 U5 a/ c! H. t8 f
% E5 \4 i/ Z1 F) x" f2 Y        // 设置IDE设备存在标志
" o# L7 [) ]) B4 ?        MOV btIsIDEExist, 11 [4 n! l3 P$ F8 [9 v& U& v3 Z' c
3 \9 y* r' h( m1 r
        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)9 Z: y4 q" z% Y/ r
        CALL WaitWhileBusy& y& v! Q3 T+ K. n7 S  w9 {' k; C
        CALL SelectDevice
! j- I0 [+ _! c  V. r5 k- p% |
: [5 B/ @" U  n/ \        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏' s# ]. x) w* r/ e8 e  Q" y
        CMP  btIsFirst, 1
; A6 Q- |$ Z+ M7 V& F        JZ   LeaveRing0
; d9 a5 M3 t5 q8 G% S
& H) d  z1 n7 }7 _        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???; `5 V( t$ G; @* a
        CALL WaitWhileBusy, x5 f6 `  ~8 q* S
# Z5 \5 [- ~, ?  i/ p
        // AL的值等于cBit06时,不存在驱动器,直接返回
' ^) B3 \( K) x$ b5 w        TEST AL, btBit06, h$ N& f8 ]9 S( x2 `- A. @' P
        JZ   LeaveRing02 y; n/ B2 ]  T) q) v0 h

, M9 c# t* j. o9 j: m: Y        // 设置驱动器存在标志
2 r9 T# j0 b! b! S        MOV  btIsDiskExist, 1
  |8 |& A9 f6 _5 u$ i" p# F! Z! T6 M; {0 r( g( Z8 G, B; F5 W
        // 发送存取端口命令
  K1 ?8 E9 m( D$ H( `        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,/ `) L, t1 i8 ^2 [1 U  I
        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
0 I2 B# _( p5 R% N/ Y0 h5 C2 I        CALL WaitWhileBusy
% n% B+ ^. [; a# Q- ^        CALL SelectDevice    // 设置主从盘标识- O; Z/ {; y' [/ H! @
        MOV  BL, btAtaCmd      // 发送读取命令
, q0 [$ P* y4 o        CALL SendCmd  N+ q4 [, w; Q; {
        CALL WaitWhileBusy
/ ~  k2 [. ~' s: B- G4 X% X, T$ a: g# Q& j8 P# g
        // 检查是否出错7 t' [8 D3 s9 h. {
        MOV  DX, dwBaseAddress( d$ ^" f8 B. r* y
        ADD  DX, 7
2 w0 ^# ~" `1 X6 F3 m- s" ~. Z4 |
  U; a8 o) T) a: u& ?; a        in   AL, DX
1 w: `) Z5 n6 A( V/ F) `) s* p/ ]
* z# e& t) M9 \  J* @5 k+ S+ F; N: a        TEST AL, btBit00
( J0 o0 g4 f# m; m+ |3 X; Z/ L        JZ   RetrieveInfo   // 没有错误时则读数据
$ t+ E, |1 a, p, y" |( y9 f- T& D0 Q9 h. R5 L: w* V# H. y7 a  k
        // 如果出错,则进一步尝试使用ATAPI设备命令
: `: f* c5 P  Q        CALL WaitWhileBusy
1 w1 U" m. T* u  ]1 {7 L' p# e7 n        CALL SelectDevice* w% d9 p* C8 ]0 s1 Q2 H2 ?/ J
        MOV  BL, btAtapiCmd
2 S. S7 R% G9 q3 G        CALL SendCmd1 |& b! |. A8 f. Y9 S
        CALL WaitWhileBusy' B! M# k+ {0 T

7 k, n* ^$ Z& o- f        // 检查是否还出错
" F# @  R! g' y        MOV  DX, dwBaseAddress+ X7 b$ k: s( T
        ADD  DX, 7
3 [/ t4 V8 {: A+ {. j        in   AL, DX8 Z0 q1 o% z# i. j1 \2 Q( t
        TEST AL, btBit008 W+ E/ y9 [( m$ {1 E2 N4 Q
        JZ   RetrieveInfo   // 没有错误时则读数据
9 y7 M: L$ V( C# W) u        JMP  LeaveRing0     // 如果还是出错,直接返回
7 l% q# m5 X7 ^, y: }
- i( x1 |: w; y        // 读取数据# s, Z! L% E& N% y- M, B3 v. }1 c$ I
        RetrieveInfo:
4 f) Z- {: Y- {; [4 d9 H; v6 n
# z! v/ {$ T- N& n0 W0 p$ P        LEA  EDI, wOutDataBuf& q, ~; l6 Q( f% a' i
        MOV  ECX, 256( h1 f8 b8 V" V# D. R6 V  i
        MOV  DX, dwBaseAddress
; _7 {" D+ G/ P        CLD: @/ D. K% P" z/ V/ B( ]. O6 ]

( G8 V, I4 Y5 n, [# v3 c        REP  INSW
# W& Y& m  h- u5 J: f$ D7 Q4 }7 I- M7 \5 _! M4 m- l+ D
        // 退出Ring0代码# A& H$ t3 Q( z: U1 c0 |
        LeaveRing0:5 m% o! R5 Y; Z4 m3 {! c9 G1 y" Y

* l% b1 G. E! R        POPAD
! R2 B9 }* @2 [# l        IRETD
! N5 c  \9 t2 h9 {
3 _6 [- d$ e0 C        // 激活Ring0代码
4 \" d" I* k( \. ]0 p        EnterRing0:
! X1 m% _1 _1 e0 D  b) L. k9 {: z
        // 修改中断门
# g8 q2 b9 b2 _        SIDT FWORD PTR btIDTR1
: [2 G4 N6 l$ p/ r% U        MOV EAX, DWORD PTR btIDTR1 + 02h
9 ?8 B3 M0 M$ C3 f        ADD EAX, nHookExceptionNo * 08h + 04h) ]( U5 r# L1 j
        CLI& D% K4 `3 T3 n1 e* c" o; R; n

% F6 c# v5 n9 x% |- b        // 保存原异常处理例程入口
& o* _! P4 p  {        MOV ECX, DWORD PTR [EAX]
2 |: }8 f0 E8 f        MOV CX, WORD PTR [EAX-04h]- y6 ^3 ~9 n7 Y! p3 i
        MOV dwOldExceptionHook, ECX" ~/ L# K6 K+ Q' a
" F7 b; w. T. I& Q
        // 指定新入口
8 X9 F: h7 P  s- d! H! v. \9 p        LEA EBX, Ring0Proc
2 A6 t5 S0 w8 J, M        MOV WORD PTR [EAX-04h],BX
* A" z* i* Z' M  B4 U1 d        SHR EBX, 10h4 ]+ d6 c! }1 h6 ^  b
        MOV WORD PTR[EAX+02h], BX
5 H, [' \/ Y+ a$ f/ n$ \* O- q  ]/ ~
        // 激活Ring0代码" u% K3 _; c( ~2 ^2 L5 x
        INT nHookExceptionNo4 ~  g7 M7 K- _, b( W" i
$ b( J9 l6 x9 H# p
        // 复原入口
! L& L; W5 `. H/ Z* R) D" r        MOV ECX,dwOldExceptionHook
- U  N, |7 F) I8 x: {' }5 `        MOV WORD PTR[EAX-04h], CX
4 h/ W) a$ ?; l% G1 _        SHR ECX,10h9 J- p* r  n  R7 x) |+ P
        MOV WORD PTR[EAX+02h], CX
( `9 |3 q. L( h# o. f+ E- {        STI/ y. P  J" c) Z# v. R
    }
( E0 g/ M, K/ D" y    if(!bIsFirst)- v0 Z/ W  U$ P- m2 {8 K
    {
6 R/ B9 p- w( i( z        bIsIDEExist  = (bool)btIsIDEExist;8 b( ~3 V; v& F% i7 L) Q
        bIsDiskExist = (bool)btIsDiskExist;
) X+ E9 P4 a' ~- O3 a, l        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));, a& c; u) t$ y5 B; |* M+ c' y
    }
+ |: \$ ~% x3 H}' @7 B: S. n4 n1 V, i
//---------------------------------------------------------------------------
0 C- t+ s! K5 u) I+ \! N// 调用方法:! D; t, }$ _1 r
void __fastcall TForm1::Button1Click(TObject *Sender)
1 D$ Q& q. q4 d4 [" Y1 d{" z7 t8 z. Q2 ^! L3 k- W: z
    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
5 y* p) Y+ c  a6 @7 L8 v+ |}
  A+ b$ ~0 q+ U6 Y. u- f
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-10-20 20:45 , Processed in 0.049825 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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