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

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

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

  1. ; _/ N, V+ w6 a9 W: _5 y
  2. #include "StdAfx.h"
    / \4 U. J" A% S0 n
  3. #include ".\puiddisk.h"& X4 {9 N! s: p) d1 Z, i  ~# ]
  4. #define _WIN32_DCOM" n) G' l8 A* I* [6 x, _# x6 ~8 l
  5. #include <iostream>& s  S; I1 C; W, h& b% L+ u
  6. using namespace std;* }# f8 z* M. o6 Z/ V- ^
  7. #include <comdef.h>) g4 z2 ?3 d! ?: Q
  8. #include <Wbemidl.h>- r' Z, W1 d; z$ q

  9. % }; Z5 G7 ~  [% f
  10. # pragma comment(lib, "wbemuuid.lib")
    , @  G6 z! \$ ?3 g( z
  11. CpuIDDisk::CpuIDDisk(void)7 Y% t4 Y# R# }
  12. {
    ( \5 e6 d  @' F- F% N- |# S
  13.     GetInfomation();5 }" b9 |$ O) X' x, L
  14. }+ u: d4 N7 x  z6 [6 j% x

  15. ' @% {! K9 A& k" Q9 P
  16. CpuIDDisk::~CpuIDDisk(void); w# ~2 p  B# N4 D1 v& V) x
  17. {
    9 g" L, \  D0 i
  18. }
      Y1 Z1 ^* t9 Q# W+ s$ @) B, K
  19. int CpuIDDisk::GetInfomation(void)
    ( ^9 x1 q; M5 S1 X
  20. {
    ( _; j, u% o! H" y- [, Z5 \
  21.     HRESULT hres;) B0 T  w0 L: Z  N+ i9 `$ _
  22.     //步骤1:不是必须的,COM只须也只能初始化一次
    # Z; ^' r) b# }' d8 j% z
  23.      hres =  CoInitializeEx(0, COINIT_MULTITHREADED );0 q6 v% f9 W/ Z) j7 [! {, ~5 t* F& K
  24.     if (FAILED(hres))# `5 p, I: X1 D# ]
  25.     {( R; t# _  Y( N) d, _& n) |6 }
  26.         return 1; //初始化COM异常:注意,COM只须也只能初始化一次0 L( }8 D) j- J: u) ~: K$ r; r
  27.     }$ d* t- m- v, Z
  28.     //步骤2:不是必须的,COM只须也只能设置一次4 F& F3 w1 E2 H# g; m6 `, @: }: v* O
  29.     //Set general COM security levels1 a1 I- \! o% V
  30.     hres =  CoInitializeSecurity(
    1 i: |2 }9 k  D/ b  j( r
  31.         NULL,
    3 P/ g% z6 n; d% }% M
  32.         -1,                          // COM authentication
    9 p; g6 P. r5 `7 R% G( r
  33.         NULL,                        // Authentication services) p( h, f# y+ J% h
  34.         NULL,                        // Reserved4 {7 O9 i5 x" x1 d3 l% G
  35.         RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication / E0 I7 t5 ~' K0 o+ H
  36.         RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  
    * \: N9 I2 j" G4 \
  37.         NULL,                        // Authentication info
    7 t# d. C& W9 {7 F  {
  38.         EOAC_NONE,                   // Additional capabilities
    ' Q8 x7 L" o+ z1 x. Y
  39.         NULL                         // Reserved
    ; }# [4 S8 {8 N
  40.         );
    9 X' c( f7 X  C) f% ]
  41.                      
    & B; ~" Q4 U) W/ E
  42.     if (FAILED(hres))& o1 T6 k! c5 {7 n6 w' ~
  43.     {
    , @) B( b% {1 ^% F3 w! P$ h
  44.         CoUninitialize();9 t% o4 d2 H: p' e
  45.         return 1;                    // Program has failed.; R/ S2 W: K  R
  46.     }
    7 M( [* Q; L: J
  47.     2 h% _& E( |  O& A4 M2 R
  48.     //以上不是必须的,若已有“::COMInit();”,则要跳过
    5 G$ R& n7 C0 G, S
  49.     //步骤3: Obtain the initial locator to WMI ) T7 R& j, k) i+ f9 v
  50.     IWbemLocator *pLoc = NULL;
    ; R* v# C$ P  J/ v- b
  51.     hres = CoCreateInstance(7 k9 J7 y% a9 e# M9 I% u: |" p% ~# l* E
  52.         CLSID_WbemLocator,             . @% W7 Z' i" t- p
  53.         0, % |4 |% k# J8 Q$ y
  54.         CLSCTX_INPROC_SERVER, 6 a* W. m$ t& D. ]" j* r5 v" R1 w* p
  55.         IID_IWbemLocator, (LPVOID *) &pLoc);
    * K' z, \3 V3 w) K

  56. 9 m6 [* x, ^" E& E2 }1 \
  57.     if (FAILED(hres))
    4 G4 N: p8 U3 V' `  P$ s
  58.     {
    " F; P9 @! Z( |" m- V7 b% l2 w$ `
  59.         CoUninitialize();
    7 ?/ G/ g2 |9 ], ~6 @1 q+ K, \
  60.         return 1;//Failed to create IWbemLocator object2 a% z6 |5 c; A$ {# i) G
  61.     }+ P3 J. m5 l1 E, h, q

  62. 8 d* w$ Y9 A8 V  v$ s. ^
  63.     //步骤4:Connect to WMI through the IWbemLocator::ConnectServer method; r: u5 c8 q) X: ]4 H; I6 ?% I  P0 g
  64.     IWbemServices *pSvc = NULL;5 S. r5 T1 Y  m7 N% O' V/ s
  65.     hres = pLoc->ConnectServer(
    # L5 h# \" w" S6 Q
  66.          _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace/ P0 _4 ]0 I0 F. Z2 k3 _
  67.          NULL,                    // User name. NULL = current user) h7 C- ^+ _& h6 w+ L1 M8 q
  68.          NULL,                    // User password. NULL = current
    % [! o0 e0 s! i; Q( [$ S8 g+ g
  69.          0,                       // Locale. NULL indicates current- ~, H+ {$ m( v/ G& ^' {& g! c
  70.          NULL,                    // Security flags.+ c! z" R- P& k0 K5 _
  71.          0,                       // Authority (e.g. Kerberos)6 w% {: v2 _, k$ o5 m3 I
  72.          0,                       // Context object 3 y* T8 m1 y- r) {* o8 Z$ ~# O
  73.          &pSvc                    // pointer to IWbemServices proxy4 X4 o0 A9 U$ X9 H; Q1 Z
  74.          );5 ~7 x* C0 Q6 j( L. }
  75.     7 ]: N8 ?& J+ S
  76.     if (FAILED(hres))
    $ A$ }- w2 D% |+ u
  77.     {) O/ j7 ?! T8 Z4 P7 _+ ~
  78.         pLoc->Release();     
    ) W: J9 K( r$ n
  79.         CoUninitialize();% L- h6 T2 t" e) Y) Y
  80.         return 1;                // Program has failed.% Z" w% {6 D' X( g  s% n) L9 ^
  81.     }
    ' E' X, D& U) e7 Q# G& |) O$ \
  82.     // 步骤5: Set security levels on the proxy+ o6 e8 Y( Y$ a) P# P
  83.     hres = CoSetProxyBlanket(  B  a& }3 G- _1 q- r5 j  ^# Q+ E
  84.        pSvc,                        // Indicates the proxy to set+ L" ^$ H0 p7 _6 j2 ~: \5 R3 @
  85.        RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx
    " r  k" [; r2 G0 l
  86.        RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx
    7 D8 `, Q2 z8 L* u
  87.        NULL,                        // Server principal name
    3 P9 ?+ d, O6 e* g5 s9 d1 r
  88.        RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx
    ( e+ q5 m; \, S2 w, g% @* f4 O
  89.        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
    $ d: H! t& X# q- K6 W
  90.        NULL,                        // client identity
    $ e6 {! X4 G" ?; P5 P- ~, F
  91.        EOAC_NONE                    // proxy capabilities
    ( Z: H  D1 l3 z9 G' F, F
  92.     );
    % @  H/ m( b: b' h# I2 E
  93. - C7 O" ]' r' ?$ K! v4 [
  94.     if (FAILED(hres))
    / n0 @: s, Q/ w, J4 H: J
  95.     {1 i: r: B5 q/ E8 M8 h  G0 |5 E6 C
  96.         pSvc->Release();5 K% D8 k& U- ?6 {
  97.         pLoc->Release();     6 ?% R2 B, @& R8 y: ]! Q
  98.         CoUninitialize();
    & l0 ]' n5 q  H3 H) P& y
  99.         return 1; / O7 H1 x6 i. _* f# Y. z: U" J
  100.     }
    ) O4 i  [# Q* B2 V
  101. - X5 H/ L6 K' ~/ S$ i
  102.     // 步骤6:Use the IWbemServices pointer to make requests of WMI ----3 t# ~/ \9 C7 d) J$ H1 T& p1 o
  103.     IEnumWbemClassObject* pEnumerator = NULL;- x( a- v3 z; z5 }( V$ |8 e( k5 @
  104.     //计算CPUID
    0 f2 q& q. R, Q
  105.     hres = pSvc->ExecQuery(
    $ _+ S" I- G1 s+ ?& k* e# G: p' m4 K
  106.         bstr_t("WQL"),
    & N# W  }" A3 k% k; L
  107.         bstr_t("SELECT * FROM Win32_Processor"),//Win32_OperatingSystem
    % g& p+ P7 ~; c" K
  108.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, - |* o+ Y) h3 k* e: m$ d, _5 e9 F! f0 L
  109.         NULL,( c+ ^0 ?5 e9 b, M, d
  110.         &pEnumerator);9 Y" S& K0 {( d" k/ ^
  111.    
    8 L* G  y; O! B5 F9 ?
  112.     if (FAILED(hres))
    9 j4 G0 L/ q9 T6 S
  113.     {
    / b2 h- V! Y) R$ C/ C
  114.         pSvc->Release();
    ( s7 ^! u/ f6 g0 ~
  115.         pLoc->Release();
    ) `3 e6 X) J% ~2 K4 x/ g, }
  116.         CoUninitialize();' P- n1 {) a+ y! T  F; C" e: N
  117.         return 1;
    7 d4 X: W5 z* x1 H7 h& F
  118.     }
    ! T' o" s3 K: N$ A4 r* i; w2 H- }0 G
  119.     // 步骤7:Get the data from the query 9 h, `! y' m; E  ]( c! \% E* G
  120.     IWbemClassObject *pclsObj;/ S3 C. v" u( ^  l3 o
  121.     ULONG uReturn = 0;2 g2 h" T% G2 j
  122.     while (pEnumerator)
    7 _4 d2 f$ a2 d! C( U# y
  123.     {
    0 Q; w- U/ J& ]6 u5 J3 a
  124.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
    + ^6 F6 I6 d+ q7 T" b3 t
  125.             &pclsObj, &uReturn);
    2 h) o  P: ^) t! b& t" I$ ^7 c5 a

  126. 2 G( V/ P1 d1 O0 }; s: _
  127.         if(0 == uReturn)
    + y! P3 [1 J: k7 K4 {! T
  128.         {
      ^6 O% d4 {& I+ Q. }
  129.             break;
    * m" k2 {: g% z
  130.         }
    ) E# E7 T& L" u0 }2 s% R: v
  131.         VARIANT vtProp;
    % U5 D. e* ]+ @1 S
  132.         VariantInit(&vtProp);0 O% `- Q* p5 C5 z, s0 T* J8 r
  133.         hr = pclsObj->Get(L"ProcessorId", 0, &vtProp, 0, 0);1 c& s8 R" p2 L$ S
  134.         strProcessID=_com_util::ConvertBSTRToString(vtProp.bstrVal);//strProcessID:类级变量
    ' I% T; s- m, B9 S. N
  135.     }
    ) L# E+ r8 {0 P

  136. , F1 c( k0 W/ t2 o8 O
  137.     //计算硬盘系列号
    + O; F% B$ |8 {- `5 z
  138.     hres = pSvc->ExecQuery(* J& _' }6 B3 X- m
  139.         bstr_t("WQL"), ( Y/ _( d  w' [: w7 c* G4 ^
  140.         bstr_t("SELECT * FROM Win32_DiskDrive"),- \3 t+ A* a0 c4 Y; P# x# g
  141.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 1 p4 I7 e5 A3 t7 w# n
  142.         NULL,4 p: v! S) n2 L/ \  J8 _) ]+ e+ P
  143.         &pEnumerator);
    2 o& c3 i0 [) e+ l) X" _5 v* a9 y

  144. 6 w/ b! c, A# ?" D1 Z& ?8 `4 a0 Y
  145.     if (FAILED(hres))
    $ O/ n% P& `5 \7 o* x9 A. ^
  146.     {
    / E9 m, _2 {0 E* ~1 M- S+ L: i$ R+ b
  147.         pSvc->Release();! P3 Y  ]5 W2 L  p# J. I
  148.         pLoc->Release();7 n' Y6 T' |7 J" @
  149.         CoUninitialize();; t4 E+ n0 `3 U. D2 i
  150.         return 1; 3 o) h7 p0 |' k8 e5 f& N
  151.     }1 T1 q* s% n& z3 Z2 W" ?% h: J
  152.     while (pEnumerator)
    , M9 ?2 W( o' V( w, {+ \
  153.     {
    9 M4 l; j2 ~# k, _* Z
  154.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
    2 g2 V4 ?* K0 B0 U! B
  155.             &pclsObj, &uReturn);
    $ q/ d* m. K9 I* d8 h" c$ ]

  156. 1 ]/ [& i9 H2 Z
  157.         if(0 == uReturn)# J. G! G4 `6 p0 S
  158.         {
    ! k2 h) i6 A5 n! E
  159.             break;% H6 f7 \& v! H7 u; W7 N7 K% |
  160.         }' n" K" f, B: E
  161. % `" w4 H3 f# t' ?) T
  162.         VARIANT vtProp;4 b. [. d9 T! U+ L, l1 Z& _* z
  163.         VariantInit(&vtProp);
    / a& H1 ^" u, e+ K! e6 P/ i
  164.         hr = pclsObj->Get(L"PNPDeviceID", 0, &vtProp, 0, 0);
    ! C4 b; u6 K7 H' o! h
  165.     strDisk=_com_util::ConvertBSTRToString(vtProp.bstrVal);9 g7 ?: U  g+ \0 m6 v
  166.     }
    9 U3 n3 }7 q6 Z' q6 k9 q, G
  167. & P( `  k8 ^! ]3 \' ?! O
  168.     pSvc->Release();  n8 v$ k& S" B' q: Z. n0 c* g
  169.     pLoc->Release();
    : {/ r7 }: h  D0 t- ~3 c
  170.     pEnumerator->Release();# i2 n3 F5 C. k3 @- H" V+ P. G
  171.     pclsObj->Release();; x# O5 {& l8 C& f
  172.     CoUninitialize();' x5 C% l7 s4 v! ^
  173. 6 B" y0 ~6 `7 f/ n4 V
  174.     return 0;   
    " l* {4 [* m& E! E1 u6 Y0 ]
  175. }- [5 J1 v* C. h: g/ t1 [) g. ?- ]
复制代码
 楼主| 发表于 2010-10-11 19:21:05 | 显示全部楼层
本文代码经ccrun(老妖)在Win2k下试验成功.
* F, t" u9 y1 X
# o( K+ M% y1 z4 I#include <WinIOCtl.h>
, P2 _; L- S" M- Z#include <stdio.h>
: w5 `2 h$ X3 w9 n
' Y3 U6 Z1 @6 {8 r( x#pragma inline0 Q0 c5 ~3 @1 Q9 r- K( ?
//---------------------------------------------------------------------------" N" y7 u! V$ L( m3 v4 u
// IDE NT/2000/XP专用变量% q7 |' e1 {' f
#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
4 h: R4 ^3 \1 }' z2 Q0 H#define DFP_GET_VERSION         SMART_GET_VERSION5 T* v5 S* d  G4 x3 Q
#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
' {5 z  T/ ]7 X#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA# m) N2 V' L# }+ Z
7 B9 \+ e. n8 v* F3 ]. D
const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令
0 u# A" V4 t, W+ r: kconst WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
& d, t1 v# [0 }$ o& y+ t% k5 t9 I, ]6 [
const int MAX_IDE_DRIVES = 4;
* J$ d6 V3 P0 Z4 O% S0 m
, X2 Q' h/ W/ U6 F8 Y// SCSI专用变量! r# u* j3 h2 J% c, m2 `$ f
const DWORD FILE_DEVICE_SCSI             = 0x0000001B;! n/ p: \* t/ M& K$ @  p, j
const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
8 j5 o8 R1 a) f  Z. {2 F. l5 \const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
: C* ?) y+ U4 ]. b0 d$ S8 cconst DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;) @! y- J5 h6 S0 n( j. \/ ^' R# ~

9 j! a5 j& d! }5 D; G4 `typedef struct _SRB_IO_CONTROL- F! \, R% K/ L
{
: P' Q& j' n% |7 ^    ULONG HeaderLength;
! ?, C8 q. y# ~. \8 o/ i# k, W6 z    UCHAR Signature[8];
: c$ F! a2 _4 y6 l. @    ULONG Timeout;6 v" ?. l  F. g( @+ W; F1 h
    ULONG ControlCode;# I( S8 e, t3 O% ]" T  V$ _
    ULONG ReturnCode;
% t7 C1 j4 \- E2 B    ULONG Length;3 g5 i6 W9 e' X6 G! D7 X
}SRB_IO_CONTROL, *PSRB_IO_CONTROL;
  u0 z# Z1 }8 h2 }. ~% f% _
2 K" Q$ D* w+ C: m( S' L3 g// 读取的主函数
9 g5 U5 P4 j; C& Q# Lvoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);$ s7 Z9 K* w3 c' s

/ h. w" ^# J) q6 b2 U6 {// 辅助函数
" x- M; W" t* _" q+ m  y8 Mchar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
# v( t9 _. o8 i7 ^& K2 J0 ]; j1 z// NT/2000/XP函数. v2 o! U! L1 Z/ M0 I
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);! Y) z+ ~2 f/ R! Z' Q
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,. _* p, x  b: T  V4 A  m" r
        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
; u" e! c+ r) V' p; c6 p        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
" i# }/ v, ^& m% C; b$ M// Windows 9X函数
: w1 F$ C& {5 S& d5 Zvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);
  {% x: w) H$ O- u5 p1 mvoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
. B& l2 D0 j; S; X) x/ @: [        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
" C( ~  ]& u  X, f4 C7 l, a1 v( M4 Z& Z! R
// SCSI读取函数(for NT/2000/XP)/ }, A, g" Q' z" E- ]* x+ z
String __fastcall ReadIDEDriveAsScsiDriveOnNT();$ P! o& z; Y6 A
//---------------------------------------------------------------------------
4 i3 Q$ p2 p0 k$ T& o. q// ReadPhysicalDrive
$ e& O  E5 j# I- J9 ^5 |7 L% ~void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
& ~# \, R& p) f( K; [6 M' _6 V{
9 g5 j! k  `; i, [( _3 a    switch(Win32Platform)" E! W  U; F: d7 _8 E
    {
4 L8 P7 X9 Q1 B5 g5 _0 {7 r( |5 J        case VER_PLATFORM_WIN32_WINDOWS:
/ D, B, e5 W2 H/ \/ _            ReadPhysicalDriveOnW9X(pSerList, pModeList);( n3 @' |* S, ~5 M  S2 G' N
            break;$ n. M" E4 ^2 I1 V; }
        case VER_PLATFORM_WIN32_NT:" F& F( l: |/ p; U
            ReadPhysicalDriveOnNT(pSerList, pModeList);( U; k4 V9 y# {
            break;
1 m( o0 ^3 {5 V" K; v6 d& s3 X        default:$ U$ H$ }, z7 ?1 S6 A5 z
            break;
6 k" j6 a4 E4 H* D! \/ c7 p# X3 Y    }
( h4 A3 U' c! G}
1 V' G/ Q0 v0 p//---------------------------------------------------------------------------6 }$ l( t& C. m6 L5 {: i2 r& i. ~9 V
// ConvertToString
" ^# S) r8 y; f( s2 f7 Gchar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)1 A! Q& q* w! z4 u9 }3 }) B
{
8 X( p; D' V$ O% D    static char szResBuf[1024];
, c6 s1 j+ `1 O; @2 J: e    int nIndex = 0;! s% y) h5 S( e4 W/ n' n( |; e8 D7 O  }
    int nPosition = 0;/ b" b( V7 S- G$ ]! T' ?  I6 ~; P
, t3 I! [0 w# N+ q; V
    // Each integer has two characters stored in it backwards
& `/ ?6 c% ?0 b    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)) T  @5 Q0 V0 l* @% Z0 |* n& ~
    {
, N* W8 T3 J8 Q( U        // Get high BYTE for 1st character6 }2 Z3 |3 I# u' c5 x" k
        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
& r4 t- l* z8 d5 z) g7 z7 b! P        nPosition++;
: N2 J4 q6 ~7 F) |# U$ ~4 }6 \& o( \1 |; c, x4 P0 o* I* F
        // Get low BYTE for 2nd character
( |6 l  \+ e& L8 F; g- Z7 H2 G        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);3 a, G; C2 k# q. n. w
        nPosition++;1 @7 a3 L/ ?8 y3 B
    }
7 _" p% X, Y' D& M1 d
+ \9 c) F2 m% t$ o1 S9 }    // End the string: E9 c. v( U" @3 W
    szResBuf[nPosition] = '\0';* t1 O" G5 |# [% K: E

0 \% z9 |8 H% C' t    // Cut off the trailing blanks( m3 l, `$ A+ L9 L! ~$ E+ ?- z
    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)5 ]$ ~( b% c: U% S# d* L
        szResBuf[nIndex] = '\0';
# }1 m& g) }& G6 I% Y; T6 h8 U& U8 R* O
    return szResBuf;
" w& Y; [" X' k! K, g+ R. \}
2 D+ `' B, k' m# B% P) k2 N//---------------------------------------------------------------------------
0 M- ^5 S6 ]7 X9 W1 c9 \& k// Winndows NT4/2000/XP 代码% ~, G7 p2 a. q& i) ?* p
//---------------------------------------------------------------------------
& y( J5 I/ M3 i" j( I9 r// ReadPhysicalDriveOnNT' H' x3 U5 e+ i, U
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)/ t' c# |  v: t1 {/ v
{1 I4 g) ]1 Q. F; S* c. G
    // 输出参数
4 P  L* u. ^7 d4 F7 }: J8 s    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];5 c: x0 y; O5 u- @- d1 L

) R; y% b1 P( L/ _5 K! I9 O' J* n    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
: H; ^$ P2 `6 m" s; x    {
5 r2 x1 x# G7 G! }+ l        HANDLE hPhysicalDriveIOCTL;6 S7 H* h3 S  i, D' N
        char szDriveName[32];) o* L  x" x3 v5 |: t
: Y! P" m, A8 j# A  @
        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);* R4 s2 G' o, T' N
        hPhysicalDriveIOCTL = CreateFile(szDriveName,
3 b1 ?) p) Y# n/ a: r4 o                        GENERIC_READ | GENERIC_WRITE,7 S. y- M! W# v! d" d
                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,- ]2 v3 ?. |. C5 C2 N7 u
                        OPEN_EXISTING, 0, NULL);, l/ ~( m' j# H
# z. g+ K6 I2 k! H* a
        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)* Z1 m  G- U& V% M2 f6 n
        {
; r) ]2 `+ ]+ G3 N; O+ H; C            DWORD dwBytesReturned = 0;
0 U1 ]+ y$ J, m; r, d            GETVERSIONOUTPARAMS gvopVersionParams;
( n* }. W1 R/ g/ ~6 [" w0 P' {& |
+ V1 E2 H" f" s4 ~            // Get the version, etc of PhysicalDrive IOCTL
+ ^( B- o, F8 M            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
* g4 ]2 G, a( h2 [" r7 e
9 f5 E1 U0 v. H( B, l' a* `; _            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
/ t0 q& `* R, \                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
( |" V  _1 \/ U! q8 m2 h3 X+ g                    &dwBytesReturned, NULL))7 r  N2 ~3 ^. w% `7 [
            {$ y) S, `. v5 A. S8 o
                continue;) s3 y$ s) c5 P+ J* E: ?9 A
            }' R- C# E: \. w% m$ w, S
4 N# n; U6 X1 T9 r  r) I" |
            if(gvopVersionParams.bIDEDeviceMap > 0): Z% v5 P: Y& j2 O6 ~7 Q1 @; d+ @
            {
0 ]# c9 q+ U5 J+ U0 ?" l( x1 e                // IDE or ATAPI IDENTIFY cmd
/ K. l1 W3 w. d$ N! \                BYTE btIDCmd = 0;/ H/ s% ]+ ]' p/ e. s/ J
                SENDCMDINPARAMS InParams;
  s  f( v8 F" V3 M                // Now, get the ID sector for all IDE devices in the system.
* u6 |; J9 ?  }$ I% @                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
: t2 l' \' X  Q                // otherwise use the IDE_ATA_IDENTIFY command
7 {' E+ [+ q( @3 E! q3 G                // 具体所得结果请参考头文件中的说明% x9 t& Q  ^5 i5 P2 W+ X
                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?5 Q% [! L! l$ r/ H: Z) X  O
                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
; i8 d4 U9 R) l' s                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));3 W# w  l1 p. {  E! O
                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
: n; a0 B9 p+ X  Z; p  Q
8 ~! h9 f+ C% k5 W/ {                if(DoIdentify(hPhysicalDriveIOCTL,
* j: [2 m) u; @8 z                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,* O4 \$ `! d! P  w3 y8 V
                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))  t* X- V( p: d% w7 l
                {; e* N& d" J0 m' n
                    DWORD dwDiskData[256];
6 j# ~0 u) o* p                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件" @( Y: J, x* V: v
                    char szSerialNumber[21];
% R# Y0 o  E# D0 G3 T' y5 F                    char szModelNumber[41];
2 m: W4 E5 k2 Y2 ]6 {5 j( t! `/ i. `/ W
                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
* Z, m/ Y- n+ j. [                    for(int i=0; i < 256; i++)# [+ G8 u7 J8 r. V1 l8 c5 T
                        dwDiskData[i] = pIDSector[i];
3 I8 R7 k7 Z( J- r. n" G                    // 取系列号
2 {1 o7 N; ?! r4 Y! F8 x  h, v4 `                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
; ]0 N5 U  Z* F! p2 {- j. T/ L                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));, ?( U; F# v, l9 d

' ?9 H0 ?- q: g% x! T+ w$ e                    // 取模型号
" |& x+ ]( P$ h2 I4 I- X                    ZeroMemory(szModelNumber, sizeof(szModelNumber));
  ~0 t5 _" W" `1 Y! K                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
' \. _1 Q& l9 F, g" z/ J2 K) I! F9 x
. N- a( X3 F% R" _2 e. D# s6 T                    pSerList->Add(szSerialNumber);$ _" M; w! e! D% c
                    pModeList->Add(szModelNumber);
  {& v& M( o; s6 i3 Q                }
) d, E0 G, N8 }2 Q  f! c            }
9 j" _( z' m) ?9 }4 y. Q            CloseHandle (hPhysicalDriveIOCTL);
/ K  [- f& R  T" y0 h4 F        }
- O$ h) ]. O" i' [* _    }/ v6 r+ y) l% P5 c% Y* Q0 }# X2 `
}
# n+ e+ |6 G, g$ M5 \  p' R//---------------------------------------------------------------------------4 @0 I0 J& e1 a) I" H: W, m+ N
// DoIdentify
* b# X) I3 D" ]& r3 M+ }2 `2 mbool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
$ A6 u+ i5 M# r* ^( R3 C              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,0 s$ T8 _- H6 C. k0 R
              PDWORD pdwBytesReturned)7 d* i/ j! ~2 l/ E3 x$ E' i3 X
{1 Q% X8 f. B7 m7 H- ^) X
    // Set up data structures for IDENTIFY command., ]. ~: E; m0 m7 ^# i
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;$ m! A4 L5 G3 k+ _1 y/ c+ m
    pSCIP->irDriveRegs.bFeaturesReg = 0;$ D3 p1 ~5 @, g1 t# {, P
    pSCIP->irDriveRegs.bSectorCountReg  = 1;. t  n/ a  ~1 u: f
    pSCIP->irDriveRegs.bSectorNumberReg = 1;0 f& }* W5 `3 h) A
    pSCIP->irDriveRegs.bCylLowReg  = 0;# m; [$ w& L& Z) d# t7 @
    pSCIP->irDriveRegs.bCylHighReg = 0;
3 n- G$ c. T9 T# a) t" c$ L
6 J% A9 K+ E4 d+ {" x  n. f$ u    // Compute the drive number.(主盘和从盘所对应的值是不一样的)
( w* g2 P* v$ F5 l; b* b* ^6 Z% N# N    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;/ ^4 i# Y$ Q8 _& ~- d
% l7 }# o1 K- h  p( q$ ?6 H
    // The command can either be IDE identify or ATAPI identify.
7 D/ t0 {7 e& j9 V    pSCIP->irDriveRegs.bCommandReg = btIDCmd;( z3 b6 w8 L; H4 `, @, I2 N  f
    pSCIP->bDriveNumber = btDriveNum;6 F: s+ v/ f" X1 c0 `* v7 T5 w! @2 a
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;/ p4 l! L  E1 _! d
, ?9 a  `' F# v- t
    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
' E0 V: g# Z8 n           (LPVOID)pSCIP,5 m$ C" G6 g- Q# q! J; O( g
           sizeof(SENDCMDINPARAMS) - 1,& A4 O: d7 j: H' [/ t8 D. ?
           (LPVOID)pSCOP,) Q( N! E+ r: c- i" ^- M* Z! C
           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
( w% J( V( A: A5 A           pdwBytesReturned, NULL);
/ p' C- o7 b! i' L& y! V}# C. H9 D3 A5 |$ O, v! D0 j
//---------------------------------------------------------------------------
9 M6 s) w8 l2 j8 ?. z% c$ p// Windows 95/98/ME 代码
5 f! V8 c" {6 q! y  Z//---------------------------------------------------------------------------
' M+ L4 r1 {+ q: _8 a+ R, c// ReadPhysicalDriveOnW9X
2 l( b/ p) q( U/ T5 n7 E5 Evoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)) X0 g3 {9 m, i7 M1 o% L
{) O" U3 f! e6 {2 G, U# ^: C! @, \
    WORD wOutData[256];* u& r1 `" r" G. u7 F" A* W4 s4 _  M
    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);& c1 A: e6 C! D

7 |; H3 z; s1 V+ `* z- ]$ F    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
8 J7 w$ w+ ~5 O    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
2 `  o( n' y+ O% A2 K; d    // 避免蓝屏的出现。(期待高人能指出原因)( Y) C/ E9 _- O- {
    for(int nDrive = 0; nDrive < 8; nDrive++)* {+ A2 @) P2 P
    {( o" U" B, w% n$ ]( ~6 v
        WORD dwBaseAddress;
1 Z. l& i5 a7 u8 H6 R1 R6 m2 Y, H        BYTE btMasterSlave;         // Master Or Slave
8 w0 _8 V, M9 j        bool bIsIDEExist;
1 F$ F1 w) C; J/ L# j. j& h        bool IsDiskExist;! [" ^1 A) K: `
2 C- t/ @% m7 f( t4 c. `. j
        switch(nDrive / 2)+ h- L' C: r2 n3 X" s) Z  G
        {- v, e. h5 B4 x" [  W& k
            case 0: dwBaseAddress = 0x01F0; break;( i; I$ o5 _. j2 ]4 A" B" E
            case 1: dwBaseAddress = 0x0170; break;/ _' V0 X0 j3 c$ ?, Q3 L
            case 2: dwBaseAddress = 0x01E8; break;) r) }/ f' x  c+ o* J$ x/ j6 Q
            case 3: dwBaseAddress = 0x0168; break;
1 [( o* a2 @- o        }
4 ?5 n) u7 H* M
" v  S* G- i9 X2 J        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
  P  D5 \  D1 J# y+ q  _3 J3 N1 J! @' b
        // 进入Ring0& ~: m1 c5 P( E$ r3 x( d
        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,4 c: U% Y0 q( J# [8 K3 s% i
                bIsIDEExist, IsDiskExist, wOutData);4 c, O+ |$ J1 ^6 S5 C/ T6 h
    }' r' Q, o+ N; V/ b! u
9 d* W, J6 b9 q1 V% Z0 W6 C% e/ P
    // 开始读取
  E- L0 n6 m+ [: c, M    for(int nDrive = 0; nDrive < 8; nDrive++)
1 [1 G, ^. k8 [    {
# d; m0 k3 s/ a; r        WORD dwBaseAddress;3 X, `7 |0 r9 |  B" U0 ~
        BYTE btMasterSlave;         // Master Or Slave
0 M, G' X. v8 s( o& g' I. o        bool bIsIDEExist;7 {4 s$ e! z3 C/ _8 T! [
        bool bIsDiskExist;6 P2 p( R) _( E& c3 L3 r
        switch(nDrive / 2)( Z7 }3 {& g; A. e) X
        {
; y- f/ ^1 |/ _6 U7 s            case 0: dwBaseAddress = 0x01F0; break;) H( Q/ p0 \# c3 E# {# e
            case 1: dwBaseAddress = 0x0170; break;/ Z4 ]8 K3 H' T  ^& {4 ]
            case 2: dwBaseAddress = 0x01E8; break;
" {' u. h* M" K9 A6 K; @% M9 \3 A            case 3: dwBaseAddress = 0x0168; break;
0 u1 l4 o$ l+ B; v' P. k        }3 k% A* }# g/ n4 t
  {% S# Q& [- j* ~
        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);% x0 u; c3 N/ h# N: p9 s& w
0 b& w+ h* z$ ?% w, b
        // 进入Ring0: @# h0 R$ \" g- x" V
        bIsIDEExist  = false;" X/ Q( K0 }- e: N
        bIsDiskExist = false;& ^9 ?  H; c1 U* Q, i# {8 l2 k% z
        ZeroMemory(wOutData, sizeof(wOutData));! q6 T9 K9 I% i  o4 B

& T' D" r/ B* @/ E6 c3 F7 C( O+ p/ U  p9 T        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,3 p6 W$ t2 q8 t0 A6 C6 f( s/ G
                bIsIDEExist, bIsDiskExist, wOutData);
$ P% V1 W: Q" D# ?4 D
; s1 t* Y) k  A! M- \  {) `: ]        if(bIsIDEExist && bIsDiskExist)
# m( g# h& v' p& n6 f3 f8 ~- U        {5 e0 a$ e* q) T" G+ I- h
            DWORD dwDiskData[256];
. y+ r' L9 p  i            char  szSerialNumber[21];2 Y$ c' c9 r8 N4 K/ o8 W! p
            char  szModelNumber[41];' ?; y0 |+ f& m/ o
* p2 S# o  j5 \! d- \) i+ T; `
            for(int k=0; k < 256; k++)
# G# i: @3 z' F6 Y                dwDiskData[k] = wOutData[k];
# S8 T; q6 O1 ~+ c& q! c0 Y+ u6 U2 K
            // 取系列号* |7 {) M5 B2 [" y2 u  Z
            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
( L* a  m0 g* l" c& w            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
# W6 _9 P: `5 o; @1 `+ `! {' ^) U5 d, F2 ~7 S8 G5 F0 Z; i
            // 取模型号( m2 |3 `, B7 [2 G; F6 k2 C2 o3 x7 g
            ZeroMemory(szModelNumber, sizeof(szModelNumber));
9 s' P* w1 C' x3 e6 X            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
* g' H) ~4 X- R. k- h" ^. C' B1 u, v
            pSerList->Add(szSerialNumber);% Q1 ^, z  k: O/ B0 l
            pModeList->Add(szModelNumber);$ F8 g" r  f3 D0 U
        }; h$ D; Q8 L$ b9 `
    }
& _% p5 `  H% x3 c" B/ d* ?    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
0 m3 Q! S& n* z' n& q}3 M4 C+ t/ i! k# `1 P, \4 o
//---------------------------------------------------------------------------; ?/ {# D( H& \
// 为防止不负责任的转载者,在此注明原出处信息,请见谅。" [  y2 R; Y  I  A8 k
// 资料收集整理:ccrun(老妖),欢迎光临C++Builder研究: http://www.ccrun.com+ h0 H+ A  D4 P8 C" y  P* a
//---------------------------------------------------------------------------$ z% e8 ^0 @$ Y
// ReadPhysicalDriveOnW9X_Ring0()
# O" B. l  _. x% B//3 q( a/ _6 X6 D9 w
// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
% I4 {- ^4 j) w- Y' ~) m: U// btMasterSlave = Master(0xA0) Or Slave(0xB0)
" ^) E" Q# d% H; e& Z8 @//---------------------------------------------------------------------------6 y; C6 s, G( K  v) x
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
. L, ]$ ]2 O- v) C0 k        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
1 [1 i/ b. J5 ~3 V* {5 @. C{) ^4 |- h; z2 v' ?2 T
    BYTE  btIDTR1[6];
- W2 O- v+ T; p; K( `+ S    DWORD dwOldExceptionHook;1 Q+ N1 j' b& g
    const int nHookExceptionNo = 5;
4 t7 ?: x2 L7 a/ Q& M* U, x. Z  U! u7 t& d' m! m" ~9 ]+ W  _
    BYTE  btIsIDEExist = 0;
/ H4 \. v$ m  L    BYTE  btIsDiskExist = 0;  }" D$ X- O# U. ~& g6 f. P& j% @
    WORD  wOutDataBuf[256];) b* o5 V! Y" S8 I6 P( j

! |" w2 ]1 S  W    BYTE  btIsFirst = (BYTE)bIsFirst;" U# z- f' V% o$ x' U; J

! D- `' T7 W) q    const BYTE btBit00 = 0x01;% X9 X, J/ ^& e. A2 j5 h$ A
    // const BYTE btBit02 = 0x04;
! b) Z3 j) L& s8 }    const BYTE btBit06 = 0x40;
3 I) [  H/ `4 z8 \* j    const BYTE btBit07 = 0x80;
* j, |* A' q: D' K" A    // const BYTE btERR  = btBit00;
  Y+ w) }. S$ j    const BYTE btBusy = btBit07;
; w% b- |) ^9 W* j; C; v& x6 J    const BYTE btAtaCmd   = 0xEC;; Z/ o* j% B5 q  C
    const BYTE btAtapiCmd = 0xA1;3 Q+ T# t& s8 o* K7 H

/ K+ a- t; @6 O& Z    __asm' O6 B1 n+ v& g  J, ]9 j
    {/ B/ E) m. X& y
        // 必须先执行这条语句
. I" \  P2 r5 n# Q& u, L! E        JMP EnterRing0
/ E( u* L9 g" d4 K, }- ]6 N4 z- e( U. k2 X" N/ o, ?8 Z
        // 定义过程, x- M5 z& {, A# E
        // 等待IDE设备直到其不为忙为止4 O& M- o$ r1 k% A5 R8 g8 j! `
        WaitWhileBusy proc( _  E% G0 `% a* o

% u* l# p7 v: Z; ]: A% O; H$ S" ]' ~: d        MOV  EBX, 1000004 U- Q. w2 d, k8 q
        MOV  DX, dwBaseAddress3 P6 @8 D" _4 t/ _7 N
        ADD  DX, 7
" E7 X. I3 _  b
3 r& g+ q/ D1 D# A$ D        LoopWhileBusy:3 `. n: M, ~: b% S& k, A# v

) u; b' n9 f& a' J& S8 F8 Q        DEC  EBX
( x/ Q; \  \- m* j  _3 N- U        CMP  EBX, 0
9 `6 a' Q# _( c7 S# ]- h  x        JZ   Timeout
8 }6 P* C7 T$ D9 g        in   AL, DX
0 G0 @: k/ J. ~1 |# k, _# D        TEST AL, btBusy
( i3 N6 J% R- Q+ o  X" I6 Z6 L6 d0 ^        JNZ  LoopWhileBusy& N- y  T. _- [
        JMP  DriveReady- z2 x' ]# x5 z: G6 Q

0 t7 n; P3 ]$ n        // 超时,直接退出
6 V* D7 K) Z! A+ s! }) A5 O! y: O5 H        Timeout:* S+ z# `& \% {/ O  }3 d$ L
        JMP  LeaveRing0
6 J$ [, k& [; c$ E7 E* b2 @1 S9 k        DriveReady:
) I2 P+ Z3 _  K5 H' |) K        RET
" ]) A% M5 e+ R+ N2 K) O8 R        ENDP   // End of WaitWhileBusy Procedure
, P; a) {9 {- j9 O# U: z9 u2 f: T/ y1 r
/ @; [5 U7 J- W  d) i        // 设置主盘和从盘标志( e! I% M, Y" h5 T) n
        SelectDevice proc
4 D" N; `! Q, `4 s0 K
  Y2 q' U- o* T8 C; T9 x5 V, m4 F        MOV  DX, dwBaseAddress8 K- ]# _. L. H1 Y) W$ t4 M& k; y
        ADD  DX, 6: z( [* X2 b" z1 @3 m. D
        MOV  AL, btMasterSlave
6 d6 J1 c/ S& K  Q+ O
- Y* S2 x$ X  W( D+ u/ y& Z        out  DX, AL, Z/ F9 {) ~- f) p3 L8 ]( n
        RET6 E9 }( S! a" n3 [0 a, I1 v7 m4 W, }* |

/ ]+ d9 `0 l; \1 q" r, w% U        ENDP  // End of SelectDevice Procedure
8 I. R# b2 `2 y  J/ e1 F- K7 s* k! s4 h% F* l, l
        // 向IDE设备发送存取指令* K; b# ~6 \, P, s- [
        SendCmd proc9 ^. P5 x  `. E2 u$ A
7 W# ^! i( d9 H7 |+ T" {& c
        MOV DX, dwBaseAddress
7 l/ U7 y! j1 w: e0 k6 J- f4 E7 z- u        ADD DX, 7
' c& F2 b( \' k7 Y5 C7 l6 c        MOV AL, BL // BL是主从盘标识,在过程外设置, s' {3 ?: g& e5 t- M) I; X
        out DX, AL
/ Q  c/ e- b% m+ q9 L        RET- c- b6 D. e8 @+ E7 g: g" Y
        ENDP  // End of SendCmd Procedure
& n) v, s0 L$ k" y! R2 [' E% U9 g9 g, B) }8 _! U
        // Ring0代码
' f* d5 W4 A* |: i$ q( T$ ^, l        Ring0Proc:
. R+ X& J/ m$ d6 c, e( e        PUSHAD
; T( b6 o  l1 ?+ n+ G. T  m        // 查询IDE设备是否存在/ v. C7 k8 Y# Z/ G
        MOV DX, dwBaseAddress
3 k! @+ Y9 H) a7 z0 U1 U7 c0 q8 r        ADD DX, 7" B9 B: P+ e: B* B* H! R
        in  AL,DX0 ~+ t) B# P( m; u  z; u1 G) T$ k
/ B0 |- P" o. X: r8 u+ s
        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
& @5 L& ]5 m* W" `0 o) U        CMP AL,0xFF( g( }! ?2 @, u
        JZ  LeaveRing0
( z: k& L# }1 z& _7 h* B3 }        CMP AL, 0x7F8 n- N9 h- j6 F0 k; Z& a$ D/ P' D
        JZ  LeaveRing0
+ j+ i% v5 A% l7 U* p. h6 \; O
4 \4 ~( w: o, M. E1 B7 F* Q        // 设置IDE设备存在标志
1 \4 i! c8 g8 n        MOV btIsIDEExist, 1
% p( r5 s$ o, @( {6 K& u3 }( p3 |) `! A
        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
9 W- n8 A" n/ _7 M3 i& a        CALL WaitWhileBusy
* `1 K% u) u- U& J$ L; H4 ^8 g, N' R        CALL SelectDevice
6 n! z( Y1 Y3 P9 q+ r
: I# u$ J( [# {$ a5 H* Z        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏( d& U: z0 m/ Z$ _9 K. `) [! ]
        CMP  btIsFirst, 1
' G8 ?; b2 J3 N& r3 z        JZ   LeaveRing0+ j- c# ^( V$ N/ g

9 t: O4 U2 H7 h& x( I        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
  w, w7 X- t5 z7 k' @        CALL WaitWhileBusy
# `7 }4 w9 {! A; ]( R& S
% W5 ^$ Y5 p1 m        // AL的值等于cBit06时,不存在驱动器,直接返回5 Q) l1 C6 w5 K" J- `+ B
        TEST AL, btBit065 G$ |) [2 _7 }! r& ]1 S2 ~' p
        JZ   LeaveRing0. t  l, ~1 t: @. z- x/ \/ N% L

* |# \6 t( a* g) ^" u6 N. E; x% L        // 设置驱动器存在标志
- q3 A2 R- {; H        MOV  btIsDiskExist, 1
' E" v" c% x7 ~( |- F
. |7 k9 U6 Z; A: ^( i4 i        // 发送存取端口命令
9 o: {' d! N* y, x3 d7 {/ T( ]5 h        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
2 S6 P4 q' Q* i5 `3 z! C/ n, \        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令& ~5 R& R  `6 U2 Z
        CALL WaitWhileBusy8 G7 ~5 {$ ~4 s- f
        CALL SelectDevice    // 设置主从盘标识
2 n% M: _5 P) D% {: Z' I        MOV  BL, btAtaCmd      // 发送读取命令% ~% ]* l. @0 C% `6 P( e
        CALL SendCmd
% N% Q. r7 d) q) f        CALL WaitWhileBusy0 K. _: k1 I1 J. ?5 n$ B+ Z
! W: s9 Q  h* T' @& L* ~! B
        // 检查是否出错
; h6 n) |* }2 y2 t        MOV  DX, dwBaseAddress+ V, z5 S: g9 l& ]" B  e  q
        ADD  DX, 70 x' o" w6 j: j4 ~  h  L: E
" v1 U7 X9 m' e7 }8 s% N
        in   AL, DX
/ C- U- N0 V' y* V6 o8 Y
- O6 u+ y5 m$ l6 i, X  J' l* K/ N! E        TEST AL, btBit00' p/ \2 K* Y. B* t" H. N2 b
        JZ   RetrieveInfo   // 没有错误时则读数据/ R1 S" A  O  O0 L) A3 K7 {

- {2 u+ G- ?) Y1 p; z) T1 L        // 如果出错,则进一步尝试使用ATAPI设备命令
( T; @% r9 g9 G. I0 d" C        CALL WaitWhileBusy
; Q) ]5 V2 ]3 H9 v1 R        CALL SelectDevice+ P  L( b' }0 r& X, B1 _7 v( A
        MOV  BL, btAtapiCmd
6 X7 k4 F0 k( ~& j5 h        CALL SendCmd8 l5 E) I  n5 f5 a$ q8 k
        CALL WaitWhileBusy
1 b. G8 N3 P' n1 I% B
) I$ `& ~/ _8 ~' p! H! `/ R        // 检查是否还出错
9 O4 @# y- v, S* `/ g  g        MOV  DX, dwBaseAddress
# M- y+ O9 V6 L- B        ADD  DX, 7
- P8 O" t6 a, q+ S, X        in   AL, DX
2 K- v- [$ j1 k6 C+ J/ i6 j        TEST AL, btBit00' n! V5 C; q5 V) D4 V! t* t
        JZ   RetrieveInfo   // 没有错误时则读数据- e9 w2 d8 n, Q( ?2 [8 s) O
        JMP  LeaveRing0     // 如果还是出错,直接返回
& y  Y+ h+ Z" e) U  S1 |
+ r9 Z7 C) ?, n/ A: Q- w        // 读取数据) o' [$ F6 P8 x
        RetrieveInfo:
/ Y: b8 J6 S; C" `& e
6 n* I7 x  ?: q$ t+ G6 ^        LEA  EDI, wOutDataBuf
& F& H. z* q0 a" N: d$ J1 {/ M        MOV  ECX, 256! e$ R1 M* X! y" k8 ]5 n
        MOV  DX, dwBaseAddress# O6 y. b* n0 b: {/ m
        CLD6 n% D6 E" |& H( Q- U5 V5 x' \0 l
8 t; p$ |5 N6 a& V' k) ^' a4 s) e
        REP  INSW6 I" \' C; [$ Z8 s# B( j) t. W

& E4 Q$ E6 u; i5 e) Y        // 退出Ring0代码
$ Y. O5 a$ J' ?9 L: |" k% v        LeaveRing0:5 t5 u5 @3 F+ m5 q" N* I
  h1 M0 ~/ ~! v, p6 G6 N
        POPAD; o9 g+ D2 d/ J# S
        IRETD
* c7 x+ I7 v) C9 k2 k4 ?2 M
4 P/ x# O8 B: d1 k1 X        // 激活Ring0代码! V1 x* w1 Q! q1 N5 v$ i
        EnterRing0:
- \. }/ Y& c- p! A1 |: g( |. K/ F( E
        // 修改中断门
+ j, ]8 W2 @. F4 w        SIDT FWORD PTR btIDTR16 m" N* N1 L7 k6 c; G" I# h" r
        MOV EAX, DWORD PTR btIDTR1 + 02h3 r- C4 C+ |5 e; U; I( }
        ADD EAX, nHookExceptionNo * 08h + 04h8 Q% L5 L, ~* g9 Y0 A6 k
        CLI' n: w, ]1 v. q# ?# B$ Q

- ?! @* i6 ^* q4 ~        // 保存原异常处理例程入口
6 D4 `+ b+ e6 I1 \6 K        MOV ECX, DWORD PTR [EAX]! i# e) Y6 d' d; n
        MOV CX, WORD PTR [EAX-04h]% D! }# q+ m: c8 m4 c% ^
        MOV dwOldExceptionHook, ECX
- X9 W+ R. N0 ~/ ~0 r! v0 W- e& j% H' V! c+ s
        // 指定新入口4 O) Z7 C0 y* f; Y9 x! {! K
        LEA EBX, Ring0Proc
+ {7 Z" ]( g4 f& f0 ?! N( P        MOV WORD PTR [EAX-04h],BX
! b# Z" J% P* @- v4 g        SHR EBX, 10h6 p2 c8 d) W* j0 {( `! R6 u" S
        MOV WORD PTR[EAX+02h], BX0 h: u; [& q7 L; ?  n, v
7 p3 F1 e+ }5 {  k  h  Z
        // 激活Ring0代码
' H9 p* f1 e- n6 o5 g: @3 e( K        INT nHookExceptionNo4 F) k/ Q0 w9 B8 Y- `

6 q( o3 E9 I! i7 K8 r& i1 P4 M        // 复原入口7 h& }6 U1 L! Q4 K) |: K* L  w- |
        MOV ECX,dwOldExceptionHook
$ e( s! }+ J( H4 Z; q        MOV WORD PTR[EAX-04h], CX+ R" C4 t! K& R
        SHR ECX,10h4 R$ q. N1 B' h
        MOV WORD PTR[EAX+02h], CX
7 L- \# K- ]* }/ B        STI9 f% k# s' b+ V
    }, ~+ E  S9 N2 V( D' Q9 b( T
    if(!bIsFirst)0 N2 W5 q% H& J9 L+ ?( H  C
    {
- A9 x, K* A" G        bIsIDEExist  = (bool)btIsIDEExist;8 ^$ d5 k1 n$ P0 H& [8 n, j( v
        bIsDiskExist = (bool)btIsDiskExist;
, d) c0 B! A0 o1 y# w; O        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));/ K" j* k' J3 Q+ o: n6 g
    }
' Y9 _' C5 Q9 d4 a}- m+ f$ X/ z1 ~* t
//---------------------------------------------------------------------------
) k8 O5 b: M% `' F3 L// 调用方法:" Q( }! D2 Z4 o
void __fastcall TForm1::Button1Click(TObject *Sender)4 W8 I" _" ~' m5 g- [& `
{' J# w2 h6 j% U( g
    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
0 S; m! v7 `7 i+ n}
! B7 {$ q4 [" H6 C
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-8-14 00:54 , Processed in 0.043053 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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