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

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

[复制链接]
发表于 2008-1-6 19:59:06 | 显示全部楼层 |阅读模式
代码框架,你所要做的仅是修改WQL语句,具体可看MSDN。以下代码为简介起见,一次返回所有的CPUID或硬盘厂商系列号. B& ~  w+ f3 D1 a$ n1 m
  1. : L7 n( X- z! K+ @# K8 R& d
  2. #include "StdAfx.h"
    " A5 ?% E. R8 i
  3. #include ".\puiddisk.h", J, Y5 }: f8 A+ M/ W  o8 ~( v
  4. #define _WIN32_DCOM/ q) o% s6 _/ ?
  5. #include <iostream>& P  e( b& _5 N. C5 d9 m9 Q" ]
  6. using namespace std;
    & X- e  c$ [3 ]7 D
  7. #include <comdef.h>
      S/ ?3 N, C/ @/ v, H+ E0 F1 ?
  8. #include <Wbemidl.h>9 u: ]. }: `* F& @: r6 o
  9. ( ?. C: C; {+ t! z( H
  10. # pragma comment(lib, "wbemuuid.lib")  f. S+ V7 L" Z! @( ?& a
  11. CpuIDDisk::CpuIDDisk(void)/ q7 @2 u& Q# x  }
  12. {
    . p" [- T) ^' n" c8 p
  13.     GetInfomation();
      O3 ?$ r# r2 x8 j3 v- k
  14. }" z8 u6 k# X6 @+ R" L4 Z$ X) H* l

  15. ; X" e: w5 D( V" K" G
  16. CpuIDDisk::~CpuIDDisk(void)$ z/ l: Z# z  u' l2 o
  17. {( t) o6 Q+ h6 `# R
  18. }. i/ h! Q! Q: Q* Z& E
  19. int CpuIDDisk::GetInfomation(void)1 R& r" ]4 y# s: K
  20. {* I- Z) Z( U- h( L) l4 V( {7 }
  21.     HRESULT hres;
    ! r& @% ~$ h& P/ S
  22.     //步骤1:不是必须的,COM只须也只能初始化一次: y4 A) M1 b7 [# l- z
  23.      hres =  CoInitializeEx(0, COINIT_MULTITHREADED );( s9 ~9 i5 R7 v5 P5 p
  24.     if (FAILED(hres))8 W- E4 }' u% K0 R1 {0 t
  25.     {' c- H9 e6 O1 W% q! p# @  {& W
  26.         return 1; //初始化COM异常:注意,COM只须也只能初始化一次7 C  |, N7 T' k2 v
  27.     }) h; L& h( I; T; s9 {8 t% m
  28.     //步骤2:不是必须的,COM只须也只能设置一次
    7 x8 i7 M$ c; g. Q/ A4 i' q8 ^
  29.     //Set general COM security levels  W# d! A0 F7 U. p- H
  30.     hres =  CoInitializeSecurity(
    3 b7 `5 h2 ~" Y3 b
  31.         NULL,
    % k) N5 w5 W. ]& A
  32.         -1,                          // COM authentication
    + ], ^$ Z* q2 e; R  o% k2 j
  33.         NULL,                        // Authentication services+ H. L8 l% \5 `
  34.         NULL,                        // Reserved& b4 D- C# U' h6 D6 x% B& |
  35.         RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication
    ( G- }* ^, U4 w) g7 I& `& R6 u
  36.         RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  
    5 W- s' v; G3 ^) \% B, r
  37.         NULL,                        // Authentication info
    2 i) O7 u3 G  R5 @6 ^& f& {
  38.         EOAC_NONE,                   // Additional capabilities $ h$ R: p7 H1 `/ o
  39.         NULL                         // Reserved6 U; m( n+ C6 k6 }* d! ]  J
  40.         );. i9 M8 s3 r+ |* R
  41.                      
    ; m* w3 W" _* e+ k% a( J. I$ F
  42.     if (FAILED(hres))8 @: [, E& \5 ^
  43.     {6 Y& u7 J- ~# a
  44.         CoUninitialize();3 k8 ]! q. z  P9 E6 y% P1 y- e
  45.         return 1;                    // Program has failed.
    % ?& {: u& V2 f7 U0 e/ d3 M. \; q
  46.     }2 `  g7 J9 l1 H! a0 |& Q8 ~2 v  d
  47.     3 h" p7 v0 g' g% w
  48.     //以上不是必须的,若已有“::COMInit();”,则要跳过
    . h  j  H+ D6 C7 \
  49.     //步骤3: Obtain the initial locator to WMI 9 U, k' E; Z! j8 \$ o* O
  50.     IWbemLocator *pLoc = NULL;; q5 a6 k7 Q8 ^" g3 U
  51.     hres = CoCreateInstance() z4 D1 R1 \4 T$ H- x: v
  52.         CLSID_WbemLocator,             ( p% y. v( n+ y! ~' P  }
  53.         0, & i2 x2 D; `( M: T$ K5 v! r
  54.         CLSCTX_INPROC_SERVER, ; q1 r' O5 u* W1 v( }
  55.         IID_IWbemLocator, (LPVOID *) &pLoc);
    4 U3 Z0 U8 v) j9 M. s& L0 T+ Z
  56. 5 U/ E; a! N- w, a  F4 ]
  57.     if (FAILED(hres))# u9 [( S2 O  v# D
  58.     {, [. v8 `- `2 @/ v5 M7 `
  59.         CoUninitialize();6 E/ s; `! N) P
  60.         return 1;//Failed to create IWbemLocator object& a2 E7 `  D/ j" ]3 A" ?; u* s
  61.     }, U2 H' ~4 h6 p0 T
  62. ) e& b% \( a$ o
  63.     //步骤4:Connect to WMI through the IWbemLocator::ConnectServer method, F/ P6 T1 i, n. d  g7 l+ @% X- }7 Y2 r1 k
  64.     IWbemServices *pSvc = NULL;( x' C8 u; k% Z/ J" M
  65.     hres = pLoc->ConnectServer(7 ?' `1 K. l& Y9 J9 |6 O
  66.          _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace
    " n2 i- L9 h" a* e  n8 j
  67.          NULL,                    // User name. NULL = current user
    & u7 P. V, |4 x9 n) [4 s2 ^1 b! f
  68.          NULL,                    // User password. NULL = current; J8 N) e: X5 K" W: \# H
  69.          0,                       // Locale. NULL indicates current
    , Q  @0 a/ O$ X9 s5 \; ^# C
  70.          NULL,                    // Security flags.
    2 g- e% l* E. v
  71.          0,                       // Authority (e.g. Kerberos)2 X* d& n/ e6 v4 c, K1 l0 F
  72.          0,                       // Context object & I$ e- T" i9 x, Q* w$ I7 ?
  73.          &pSvc                    // pointer to IWbemServices proxy
    1 c- O% X4 h; C9 f
  74.          );6 q$ ^) t& e* v5 J
  75.     3 F* a  h4 k% O% n
  76.     if (FAILED(hres))
    * _) h6 H% Q2 P6 i8 y  P7 K
  77.     {
    $ C$ j: j4 g2 V$ h6 p, y
  78.         pLoc->Release();     " `; `4 s- R/ L) R
  79.         CoUninitialize();2 v4 i- A8 e, O) W) ?
  80.         return 1;                // Program has failed.
    , t) ^' L  X. p# L( E
  81.     }+ n% S: S# J5 F: r
  82.     // 步骤5: Set security levels on the proxy$ ~, j1 X- M4 x8 Q$ a
  83.     hres = CoSetProxyBlanket(
    5 q9 u, r+ f8 ]1 B) X
  84.        pSvc,                        // Indicates the proxy to set/ A: M! @) t. @1 Q. r* p
  85.        RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx0 m# U8 Z1 Y8 J6 e
  86.        RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx, v/ B) m1 D7 h2 E. f0 ~: I9 z
  87.        NULL,                        // Server principal name 7 T7 C/ h7 I3 j0 u( U
  88.        RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx
    2 S' q/ m; J- ~5 M8 w& X
  89.        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
    : T8 x, m  R$ [/ a2 z6 h
  90.        NULL,                        // client identity3 D- w( _0 G" R% H) A/ O4 M6 s" V
  91.        EOAC_NONE                    // proxy capabilities 7 D! y" A1 t) n" r8 y: N6 T" g
  92.     );
    7 l; `( [4 ^" G4 g  U
  93. + H! [/ X( G4 \9 S" V
  94.     if (FAILED(hres))7 q) a3 c! G3 ?, W4 N1 z
  95.     {
    . _9 v! }: }0 \5 Z
  96.         pSvc->Release();5 R. z/ ^4 j  d$ ^5 s+ i
  97.         pLoc->Release();     3 c! T( P  ?% _9 X% a
  98.         CoUninitialize();
    2 l  H' @2 `9 C- ^, k
  99.         return 1; * ]  a# i* o5 x. B8 I6 k) g
  100.     }
    * J; Y5 T: @! H1 T
  101.   I/ ]0 w! j1 r. N0 n
  102.     // 步骤6:Use the IWbemServices pointer to make requests of WMI ----8 h% l" D/ u# ^/ G, W/ R* Q
  103.     IEnumWbemClassObject* pEnumerator = NULL;
    ; _8 K7 c7 a1 K% l( N3 f. c
  104.     //计算CPUID
    5 S& @5 U+ Y3 J- ~
  105.     hres = pSvc->ExecQuery(
    9 |6 \' L+ ?  \! G6 V4 S
  106.         bstr_t("WQL"), * _2 `* x2 b7 m" S1 e% K  }9 @
  107.         bstr_t("SELECT * FROM Win32_Processor"),//Win32_OperatingSystem
    1 `6 L0 j$ d! `0 c, B
  108.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
    8 m7 [! ^6 e) F6 s
  109.         NULL,
    7 _! W7 Y; M% L+ y: |# S9 o/ j
  110.         &pEnumerator);
    8 `, M0 m! U7 P8 N3 ]# ^8 v
  111.     : i5 f# J" g4 B5 _( Z, E4 u
  112.     if (FAILED(hres)), F: A$ j( T: c: x
  113.     {" Z" r: _% s" U
  114.         pSvc->Release();
    * R# K) s+ |5 ?" q" L' C
  115.         pLoc->Release();
    5 Z% l  I+ a) J3 i% f
  116.         CoUninitialize();; g, t: D7 R' h9 i6 ~; o, s
  117.         return 1;5 S' t% Y- [! X: m/ K
  118.     }
    0 x* y; N0 n5 B2 O: _& z5 w* F
  119.     // 步骤7:Get the data from the query
    5 ]% ]  K, Y- Z9 `  x' ]7 H
  120.     IWbemClassObject *pclsObj;
    ' r! D& a$ \; s
  121.     ULONG uReturn = 0;
    ( S9 N. y5 M7 z* L- q
  122.     while (pEnumerator)
    ( }& Z5 A7 N+ ]4 a$ G5 u1 V* \2 z
  123.     {: `. f0 p" x7 F& G
  124.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
    6 F0 N& A* h" e  {% c4 r+ ?8 T* ?7 k
  125.             &pclsObj, &uReturn);# U* l* B; u. Q7 d+ t

  126. 3 I$ q" @. |8 I; Y0 i# u; Y9 t, M
  127.         if(0 == uReturn)' G- y6 \/ G& Q$ {- N
  128.         {
    4 i, v% W, z: H& Z: h
  129.             break;4 L9 X2 I: O8 f+ h$ a3 Y
  130.         }
    8 R8 E: a5 y+ U
  131.         VARIANT vtProp;3 @- k/ P7 z# e* _
  132.         VariantInit(&vtProp);
    + y2 w+ d6 T5 i  K4 o
  133.         hr = pclsObj->Get(L"ProcessorId", 0, &vtProp, 0, 0);- q6 N0 F( g' z( R! i! f
  134.         strProcessID=_com_util::ConvertBSTRToString(vtProp.bstrVal);//strProcessID:类级变量' x' _* [7 {/ q8 R$ ~
  135.     }
    5 ^1 p! M" t' Y# L+ D

  136. # D, O2 T3 e7 N- w  E, `; [
  137.     //计算硬盘系列号
    8 g* O2 u0 O" j: U
  138.     hres = pSvc->ExecQuery(
    8 n" ]' A4 t# c, a1 Z
  139.         bstr_t("WQL"), ) I  K2 B% i" `. ]% c' H
  140.         bstr_t("SELECT * FROM Win32_DiskDrive"),
    7 \% |6 x) ?  }
  141.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
    : W' p8 x, c: _$ n" j" e$ M. Q
  142.         NULL,- G* e% |; F$ S. O
  143.         &pEnumerator);8 k) w( X# Q$ h! g" u; z

  144. 6 {: [7 ~6 S) P
  145.     if (FAILED(hres))5 s! x2 k) Q0 M$ d* e8 `
  146.     {
    1 v3 f- w& @. P5 w' H' O* G+ s1 v9 a( A
  147.         pSvc->Release();8 m* D- O$ M9 q( Z0 ^, J
  148.         pLoc->Release();2 D, H" J: |. ?9 P0 w. O8 n- R
  149.         CoUninitialize();# C4 A; _1 y1 s. {
  150.         return 1; # e) L+ v$ F: {  ~! R1 r+ w
  151.     }
    4 O! |( [3 ~  a, J# N
  152.     while (pEnumerator). l$ k: i  v7 K# k7 d' X" U
  153.     {; ~# C' f" T. }3 t, w
  154.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
    : K- s  B; r& j4 u! ~/ q% u2 w
  155.             &pclsObj, &uReturn);4 z5 {. b; u+ q
  156. 9 V& t0 j9 ^) E" v5 c# F
  157.         if(0 == uReturn), e+ l- X3 h+ x) [7 F
  158.         {
    * m) `: ^) u# H$ j
  159.             break;
    5 ?( Q9 @' A, {) j6 t- F# v
  160.         }
    & L+ P5 S8 q( J: m6 \# Y$ y  {7 G
  161. 6 T2 \+ M- {9 R8 ~0 D: A6 Q
  162.         VARIANT vtProp;, b% m" ?4 C7 c2 ^3 G
  163.         VariantInit(&vtProp);1 r% d0 t& t& e" u* O4 p
  164.         hr = pclsObj->Get(L"PNPDeviceID", 0, &vtProp, 0, 0);8 A" Q5 ]# g1 z1 q* N% y- n, q
  165.     strDisk=_com_util::ConvertBSTRToString(vtProp.bstrVal);  @7 W. R% T4 h/ E3 G5 c* o
  166.     }# i5 I7 t6 m! F

  167. " k1 b' T- q0 L3 e
  168.     pSvc->Release();. z2 F* p7 w" q; J8 L9 g
  169.     pLoc->Release();
    ( r0 c' z( [1 T
  170.     pEnumerator->Release();
    ; U* ]( ~1 [: o6 g2 x- H! x
  171.     pclsObj->Release();1 u# `* h3 i- L+ `. ?% i, y
  172.     CoUninitialize();# x# o* a: [' \) f6 j- z

  173. ! r' M' T8 u, S9 I% h: b
  174.     return 0;   & l" W; Q: m, R; Y5 a
  175. }
    6 O& W' q' ?3 Y' x, h# H5 z5 b1 g/ L! T
复制代码
 楼主| 发表于 2010-10-11 19:21:05 | 显示全部楼层
本文代码经ccrun(老妖)在Win2k下试验成功.7 }6 S, Z0 z  i" Q% T
' B. y" H% P0 y# L4 ~
#include <WinIOCtl.h>. `* |, o$ B/ d
#include <stdio.h>
& [, b2 f' u6 s0 O$ u2 S3 M; c0 x0 E9 S/ @! t
#pragma inline0 b) X) }2 ~; S7 S# X
//---------------------------------------------------------------------------# J. d: j  K8 I- y* b
// IDE NT/2000/XP专用变量
4 B, ]+ k7 }1 C; ?#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS' ~  |1 q+ N1 U5 S- D* h& ?
#define DFP_GET_VERSION         SMART_GET_VERSION% I0 A0 T' Y+ ]( R1 O; @2 X5 u
#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND( U. b+ h# ?% y
#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA& C* d! _: |/ w6 I& Y3 K) V
. [, [- J+ T- f/ ]0 v
const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令" D4 T; @' g6 t3 N! ~
const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
* i+ w) K6 T+ u7 w  {/ J
5 R  V5 O: a! `/ hconst int MAX_IDE_DRIVES = 4;
& e" e# ?! ~. q/ N/ r3 s
9 \% h% Y& e/ |3 o// SCSI专用变量% U, T. u) Y2 n1 _  p) V; Y9 X8 N1 g
const DWORD FILE_DEVICE_SCSI             = 0x0000001B;
* h8 f. w! c% E( e7 sconst DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
0 E! L5 s9 x4 [const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition) l/ r1 L' v7 Q. J
const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
/ X. u4 w0 ~( W, S
* B" j3 l6 W# }9 M" B+ S% _typedef struct _SRB_IO_CONTROL
4 y7 [+ n, [9 ^, F" _{
0 n7 H6 O* |( L    ULONG HeaderLength;5 D5 F5 d5 Q8 x" g3 g) C
    UCHAR Signature[8];
2 [$ U3 N0 N+ O( P" f    ULONG Timeout;
' ?2 I2 v# s' q    ULONG ControlCode;
- ]$ z1 t4 E$ h7 Z# f8 y. b" `$ S    ULONG ReturnCode;
3 p7 B, Z3 H$ W6 e    ULONG Length;
, ?6 _/ v' ~; K" I' O1 z}SRB_IO_CONTROL, *PSRB_IO_CONTROL;
! [0 u) j3 N7 Y6 k  H- G, L' Q6 ?% W& q: G$ C! Z
// 读取的主函数. d( I9 y, q+ F) D* y
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
4 t9 j: F0 P1 E
" k% X& V* d7 d7 M' a9 c& z// 辅助函数! j; C6 U; J1 y* M
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
2 L7 y$ V' ~) K# e// NT/2000/XP函数) H6 T# v. |, I+ \2 O
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);4 \- b& E' ]. M
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
2 W, l6 Y7 Z" `6 z3 Z  e5 P% h) x5 ^        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,# d4 g8 ?, X, |; [+ H2 [) k$ S  x
        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);1 U8 g* ^" ?9 d& n4 q
// Windows 9X函数  H4 L( ^8 Q9 i2 u  j1 X
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);
7 n5 D2 a# R% C3 @* K7 S) {void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,. J: o! [9 o$ c- q2 [* V* S
        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
) ]  ]" c+ J/ G" r! z
$ q- W% W* |7 s2 H& [// SCSI读取函数(for NT/2000/XP)0 T$ g6 l0 m) C, R$ l- ]+ l; h. C, N3 Z
String __fastcall ReadIDEDriveAsScsiDriveOnNT();/ r8 B$ ^  i) E& t# G' z
//---------------------------------------------------------------------------. {, ?! L' U" B
// ReadPhysicalDrive
& \8 |4 y" ~4 Q2 P0 qvoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
( d% X9 `& m  U: j( Y6 l+ v9 n{
. w# h6 d4 u1 v( W; o. q9 f; g    switch(Win32Platform)$ m. v9 I4 s- X* Y
    {
7 \8 K4 K9 `# J/ O7 h9 ?/ x        case VER_PLATFORM_WIN32_WINDOWS:
4 j, ]- i$ g& ~1 }4 ?& N9 k* D: Z) h            ReadPhysicalDriveOnW9X(pSerList, pModeList);
! {5 d) h2 \7 O: [+ O+ I) w* T            break;+ y! d" P) y# Y$ }- C" p4 Z+ `
        case VER_PLATFORM_WIN32_NT:& Y! s9 a- E5 n' E, K
            ReadPhysicalDriveOnNT(pSerList, pModeList);
) Q# t& x& I+ O& Z; t0 e2 I            break;
- m' x; F% `' j$ [" s        default:9 S8 ~  x' t5 o, O% e& O: M& S( d  K
            break;
1 J2 V9 i# K1 _    }8 @$ ]5 F; O) W2 q
}
7 ?+ [: O' Z5 Y//---------------------------------------------------------------------------
# J5 z, i  D+ N- g5 C8 e// ConvertToString
6 O4 h7 `9 |1 a# \6 Y( D! D% mchar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
2 [7 k0 i! I& @4 y- j4 w: H* @) F{
; y% T: z; r, p/ g# M! c6 @1 |: `2 K% e    static char szResBuf[1024];
" J1 V5 Z4 i/ M0 i    int nIndex = 0;) b0 V  \: a; L6 T
    int nPosition = 0;7 j; y; N; ]3 J5 i) H- V

! G6 h5 G  _/ r, o! u4 V. ^    // Each integer has two characters stored in it backwards
$ G3 X! `3 ?9 k- X4 r- h' l/ R    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
/ ?$ r* s% F* A- U, K! C0 K    {
/ c2 `/ _& `0 V        // Get high BYTE for 1st character8 y; w$ O! B' _5 c5 N& `, m
        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
. h$ N/ ~# O- q) n1 E        nPosition++;
, P; H+ L$ P6 Q6 i( f3 t0 r
( K8 n, T5 ^% A# g8 K6 L        // Get low BYTE for 2nd character
6 _8 B# n+ r, d        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);& T6 L: }' r, ?; b& d* G
        nPosition++;/ I& d, g- m8 V3 {! n8 Z. I
    }  t; I1 p5 m% Q- c# T3 v
1 Y# e$ q2 o! V1 s: W: S+ M
    // End the string
$ p4 o9 ^- l. Z4 l  U* C) ]. w1 W    szResBuf[nPosition] = '\0';% W3 ]( P$ X9 Z& o2 }9 U
. h6 ~. a* W" N" b; X& u  o7 i
    // Cut off the trailing blanks
- H: D. H/ w9 U    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
) L3 E, }; l5 }  X        szResBuf[nIndex] = '\0';
9 _- a  ~+ g0 R+ u1 }# F+ S9 W5 B+ f: L$ Z) k( d) s
    return szResBuf;
3 P# y# y9 \# Z8 y* l4 @% q}- @, d( H- r  ^( E
//---------------------------------------------------------------------------
3 O7 A5 N/ o, b// Winndows NT4/2000/XP 代码
: V- {0 O" x5 F, m9 m4 @! E: k//---------------------------------------------------------------------------
: [6 s4 |; |1 j- p5 m& J! Y// ReadPhysicalDriveOnNT
* J' t" l2 A( m- L: r& q: [: g) _void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)0 L5 m5 ~3 _1 x; c
{4 Q" b( l5 O4 ?. ?' q# x& X
    // 输出参数) S" }$ [# J$ E/ o" U* I. b8 W) m
    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];7 ^1 Q8 t/ ?# o* J# Y3 x

; T/ G/ X" D- U% ^) X$ _    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++); w  r5 L3 P/ {9 Q8 \
    {- ?# x& U& b& L& i; C3 f8 R3 O$ w% d
        HANDLE hPhysicalDriveIOCTL;
* s- K/ @0 K7 g, Z. u        char szDriveName[32];
0 K# v5 J, o8 Q- D$ o9 M
8 m. v# Q7 O$ q        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
! O6 L) p! ?" M9 K& t7 |9 v0 f        hPhysicalDriveIOCTL = CreateFile(szDriveName,3 R* e8 Q( Z8 x2 `" o
                        GENERIC_READ | GENERIC_WRITE,6 M( n4 C; m) [, h; z
                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,& S  l! ~7 H# c3 E
                        OPEN_EXISTING, 0, NULL);
9 p/ q' `: s. I0 H& G! L$ n, H9 d1 H% a2 @1 u
        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
& r/ z7 b0 [' n) A4 E9 b2 l% ]6 P        {
8 S7 ~; x5 i8 r3 |            DWORD dwBytesReturned = 0;
5 h& o3 M* Q: y7 E4 R            GETVERSIONOUTPARAMS gvopVersionParams;
2 f6 I- X( @( B$ k9 u# R
. g1 i3 V, ]% ~            // Get the version, etc of PhysicalDrive IOCTL5 M/ f  L/ k: A. |$ Q! y/ G
            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
- Q! N7 @" ~* d+ P9 p
. x  L. u' N( F            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
! n' }! |& H  m, d% U' T% V                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),9 p8 p) }* f' I
                    &dwBytesReturned, NULL))  l2 E2 I0 [! c. m" r, n- {( n
            {: G8 \+ ^$ b8 ?2 D
                continue;
$ [9 {3 ]$ i6 x$ q" G            }' {" C* Y$ h# ]
1 V5 U( U4 @" I! m8 V4 q
            if(gvopVersionParams.bIDEDeviceMap > 0)& M1 u2 R9 |" e2 h/ i
            {. n7 D3 o9 T# D2 d! q8 Z8 z
                // IDE or ATAPI IDENTIFY cmd1 ?/ t: Y/ n% w6 p9 p  y
                BYTE btIDCmd = 0;
2 F/ B# P3 d+ e$ Y2 x0 J# W                SENDCMDINPARAMS InParams;5 c/ k1 i. U2 N- D( g8 `
                // Now, get the ID sector for all IDE devices in the system.
' z. Q* w5 j: I& {                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command," i/ S" A4 B* {
                // otherwise use the IDE_ATA_IDENTIFY command' g, E0 H' `$ c3 N0 Y- J4 k
                // 具体所得结果请参考头文件中的说明
( f# V" A$ Z9 {( @+ h- d* V                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
6 t5 C- \& _! K3 w) k( ~                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;9 S+ V, |1 N* ^3 J$ o) n1 H
                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));+ y; v4 K% E3 ]3 U+ J# ~" Y
                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
! ^( T% Z! E0 s$ I/ H. _5 e$ C
% G* Z2 C$ Z9 ?4 Q# L5 L                if(DoIdentify(hPhysicalDriveIOCTL,
; M# C- ^) S( q* P0 ~                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,8 ?; T9 p( `  ^" H/ ^: {# j$ E
                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
% G- w' V; V5 g) g0 d1 S$ D                {
) N* o" X  O; W8 }                    DWORD dwDiskData[256];1 _' S# V7 _7 b  Q0 O9 M; ^! y
                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件# u% H7 |& ]' P$ w1 D
                    char szSerialNumber[21];( H5 W$ a, Q" p, S
                    char szModelNumber[41];
* Y0 x% `  w* w1 k, Y$ S& s( @% o2 Y
6 W3 Z, U' s8 }0 F& @# _4 D! i                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
0 X6 f8 s/ b) [% u: r7 ^9 `                    for(int i=0; i < 256; i++)/ P3 y8 i2 L6 y% @1 Z
                        dwDiskData[i] = pIDSector[i];
0 g. W2 n4 ~" m                    // 取系列号- _3 \# R0 P* x7 m+ i
                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));( i6 `" C0 E* \( G1 Z
                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
: M4 v" h: X  H; Y6 Q# g" a/ X. J
1 f1 b% j: l& s* {9 J                    // 取模型号
- Z. G" p1 a% L& V  m3 v                    ZeroMemory(szModelNumber, sizeof(szModelNumber));
$ E% C' I4 a- Z7 Z3 ^                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));/ y% K2 I4 i8 |

* O' u' S1 t+ x; a$ ]- Z                    pSerList->Add(szSerialNumber);4 y, F+ h8 ]  ~- }5 u
                    pModeList->Add(szModelNumber);! {' ]& W) l* |, B. P; a+ S7 j% ?
                }" [/ H9 ^" _. R% A
            }
- t6 Y  B' m9 d1 i% v- e: l6 @6 g            CloseHandle (hPhysicalDriveIOCTL);
# z% z. e! k5 J; n        }
) g4 E# G4 ?8 c5 s  O    }
' y) c. n! ?% U  R}
. j9 t+ }9 U1 X* f//---------------------------------------------------------------------------
$ J$ f" A0 W; o) l: Z// DoIdentify! x( g/ W( ]9 S" _$ y  m9 {
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,6 t: X8 f- m1 h3 r8 q
              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,/ n0 ^- R0 E$ w
              PDWORD pdwBytesReturned)3 w5 C5 p2 z( ~. V, c( R7 s
{! n! H6 U8 |  }' a: e# S; s6 m; J
    // Set up data structures for IDENTIFY command.0 H; O" V0 y( G2 M# ^
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;- i- C" F0 j2 x$ ?
    pSCIP->irDriveRegs.bFeaturesReg = 0;
4 z+ F$ ~# }, n  z' \$ U/ ]0 c+ }    pSCIP->irDriveRegs.bSectorCountReg  = 1;/ b' w0 ?0 w2 R2 N# M
    pSCIP->irDriveRegs.bSectorNumberReg = 1;
* x# {$ O' `: W5 V1 a    pSCIP->irDriveRegs.bCylLowReg  = 0;8 a" M! u+ `8 y7 d: M! i
    pSCIP->irDriveRegs.bCylHighReg = 0;
( J+ o: W/ s5 y! d, m; O3 R
- W* b# ^2 |1 i$ x" g    // Compute the drive number.(主盘和从盘所对应的值是不一样的)
; ]/ R, N5 q2 c$ v4 T. \# P- H, X6 o    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;. Y2 }1 ~9 g' ?  h

- ]8 Q+ ~8 K8 `+ v& S3 k    // The command can either be IDE identify or ATAPI identify.+ K! q/ @9 Q7 _* B" `- H* W1 f! X  v
    pSCIP->irDriveRegs.bCommandReg = btIDCmd;# {9 x; A: B: r3 ?+ ^- y
    pSCIP->bDriveNumber = btDriveNum;
& M. I+ D" F9 I: z+ H2 K. J    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
* D( i% m6 i: P6 l# Y8 e. t$ G: n2 ~
    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
* b/ }1 E3 P9 K5 Z           (LPVOID)pSCIP,( z3 C/ E8 p4 u& ?6 T
           sizeof(SENDCMDINPARAMS) - 1,2 d9 g' C) ?7 ^5 F  c
           (LPVOID)pSCOP,
, s" {! e* d1 G4 ^           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,6 M4 O- `, H% z, |, H5 x
           pdwBytesReturned, NULL);8 s- u! u+ `' H1 u# C
}; `1 U. O8 o1 G2 j/ V( {6 d
//---------------------------------------------------------------------------5 X4 A" A. s4 S% b8 U9 f" [
// Windows 95/98/ME 代码1 ^6 a$ ~5 H! p- \2 K$ H0 b  i6 X( I
//---------------------------------------------------------------------------# i3 k4 n5 o- m1 G/ C6 I3 S, X
// ReadPhysicalDriveOnW9X- x) @2 g" x: I
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)% m9 `  f: K5 b7 F
{
. u. y  A' \4 T( H7 \: ?: y    WORD wOutData[256];2 C( W4 d- r6 O. g' c, p
    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
3 J! Y, a! y) g1 k1 g# f
! W6 O, v/ X4 _: w    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
* I' ?7 H" O% i5 Y" G+ Z! E    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
# p/ G! f  O4 C4 W% X! G" @# M    // 避免蓝屏的出现。(期待高人能指出原因). n; K% S& C" ?/ m* X
    for(int nDrive = 0; nDrive < 8; nDrive++)
) @. L( l8 S' o. e. j: M, z    {# p6 {% W* G( J* L8 f
        WORD dwBaseAddress;: R' w$ E. S- p3 w3 g7 M
        BYTE btMasterSlave;         // Master Or Slave
/ h5 Z8 ?4 i! ]        bool bIsIDEExist;
0 f' ]- Q- R7 u$ U# Z( a  Q        bool IsDiskExist;
4 z' o* W' e% d
7 ^+ q( m5 I  W$ r! S" L% s        switch(nDrive / 2)
" E: y" e; q' F& ~- S        {' |& X' l$ O2 l* u- ^( L- z
            case 0: dwBaseAddress = 0x01F0; break;* o+ i( }8 b9 }% t7 R
            case 1: dwBaseAddress = 0x0170; break;
# B5 J% O+ e* U- I( a            case 2: dwBaseAddress = 0x01E8; break;
; ]9 x4 D7 r% ^( ~            case 3: dwBaseAddress = 0x0168; break;
& ?$ e: W  C, j) B9 k        }
# v; E# m3 h$ b2 p% c% x8 G# A  C7 L( [4 C* O% X+ v# L
        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);* W2 S) g- \9 D
6 A. v' A8 m5 ?' y. r! U" k
        // 进入Ring0
8 ~# E% a$ d" Q- {, k8 ?' s        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
9 L2 b* ]9 c( Q$ f9 g                bIsIDEExist, IsDiskExist, wOutData);
, b, d9 X- ?1 y- \, k- {    }
% N6 K; @1 ^0 S- t- w. _9 {, d, E& }0 u& v* K3 B
    // 开始读取' M; o5 k$ p5 P* @1 a8 N
    for(int nDrive = 0; nDrive < 8; nDrive++)$ S" M& P& b- U) U1 `3 M: x
    {. K8 t( F5 [+ R1 F) _
        WORD dwBaseAddress;. @6 F' g# }  P% e1 u4 E
        BYTE btMasterSlave;         // Master Or Slave8 b" d0 a0 a3 w& T
        bool bIsIDEExist;
) x. f4 V* y. C+ l0 G( U        bool bIsDiskExist;
3 j) l& {4 U4 A- l+ |& s! C4 I        switch(nDrive / 2)
  L% R3 u8 ?+ F: E        {
! N- k1 v% j# D2 o9 F7 _  u6 B            case 0: dwBaseAddress = 0x01F0; break;
' A1 ]. s. k2 ?' O! }            case 1: dwBaseAddress = 0x0170; break;
3 F" d$ y- ]1 r6 w( ?- w! |            case 2: dwBaseAddress = 0x01E8; break;; {% Z5 ^: X) m7 T( s* b) B
            case 3: dwBaseAddress = 0x0168; break;' Z# D0 k+ k/ I5 k$ S
        }
' I0 P$ P, y5 h" A8 [; z9 o) B3 ^7 _2 E. M( ]6 k; R
        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
3 p* M( p( C- e: H8 X# e
3 Y5 A1 a' ]/ o" v0 B        // 进入Ring0
) n/ G7 g( I' p- O  G        bIsIDEExist  = false;3 c" ]; Q) ?. C8 a8 T4 }
        bIsDiskExist = false;
2 c, j: Q6 B% q) m. I        ZeroMemory(wOutData, sizeof(wOutData));
! k$ S4 ~+ k5 v" i  y0 k, Z% L+ R
# Z  v) J0 z' o* k$ T+ O        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,$ W8 {, @+ D3 \/ }; d
                bIsIDEExist, bIsDiskExist, wOutData);4 S* A3 z: v$ j

! T6 m% L% q7 H        if(bIsIDEExist && bIsDiskExist)
! u2 T  G/ q% |5 t: H* z0 o" J/ A        {- ^& x) {  e1 U! h) h  G
            DWORD dwDiskData[256];; ^* r5 i& p0 ]9 Y" A& w
            char  szSerialNumber[21];
: K# ?# `, V6 ~% |            char  szModelNumber[41];; h6 ~8 E, f5 T/ o' N/ M

" U6 \: G6 b/ G& G" }1 s  O            for(int k=0; k < 256; k++)
; W7 Q& `/ z/ b; @                dwDiskData[k] = wOutData[k];
2 H7 c8 [! u4 }# A" _0 O' d% T- f1 x# W3 y
            // 取系列号6 f: V: r/ e, P- P
            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
% m0 a! a* G) y  L3 v            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));% `; r% |# T& \

- s) J) M* d5 u  ~            // 取模型号
  \% J  O& M) A' i& ~; ^/ r            ZeroMemory(szModelNumber, sizeof(szModelNumber));
# Q( S8 v* i: D* H" K# O$ t            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
, T2 F9 v& a; e- a; l" q7 i
2 i. N$ ~& f" ~) a& E2 u5 L            pSerList->Add(szSerialNumber);2 E! z. ?5 I  j
            pModeList->Add(szModelNumber);
* m; B6 q- f. |+ h* `9 K- b4 v        }
3 Q& I- I. }2 V( N. h$ u5 |* M$ E  a    }
  q# M& H  I# v# K+ w    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);* F3 i) u" n7 S3 @4 N: `) ]
}# t$ Y- |- I. u) G
//---------------------------------------------------------------------------8 P( ~2 i( {6 Q  m( w# b) \0 @
// 为防止不负责任的转载者,在此注明原出处信息,请见谅。
/ r1 T' o, w3 r* f5 r$ R// 资料收集整理:ccrun(老妖),欢迎光临C++Builder研究: http://www.ccrun.com( f! n& q( Y' F# b
//---------------------------------------------------------------------------" P, R6 N+ Q/ }7 d0 ?/ v% v
// ReadPhysicalDriveOnW9X_Ring0()0 g  o3 L; {- U0 h. s) l
//6 `3 u$ P3 Y3 s
// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h, m, S2 Z0 z+ a( B% Q
// btMasterSlave = Master(0xA0) Or Slave(0xB0)
* ]9 @) N# C4 G  \5 N/ b//---------------------------------------------------------------------------
# j. Q6 R: V8 A8 {9 Hvoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
- Q. L9 m6 u4 y4 S. W        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)- p* [" Y' U# c, I
{4 N: o7 v  I  h8 f* W
    BYTE  btIDTR1[6];
- u8 d4 x+ ^4 Z    DWORD dwOldExceptionHook;
* I1 \7 _+ ]! X' j6 i; p/ U8 }    const int nHookExceptionNo = 5;
1 A6 e% i% G( j" v4 E; f4 o
. p1 k$ u, [, j; r/ k    BYTE  btIsIDEExist = 0;
% {  P5 }3 h! h% j    BYTE  btIsDiskExist = 0;: b) {( D$ i. @# Y
    WORD  wOutDataBuf[256];
+ E+ o- k3 j; w/ e2 U: P. y- d1 a' g& t: I
    BYTE  btIsFirst = (BYTE)bIsFirst;$ G& a; }+ H. N4 s, U3 f

4 W: u8 T. F9 o( r, u# q' S  v) {) q    const BYTE btBit00 = 0x01;
! o4 c( x9 {  X9 w* C' F4 q    // const BYTE btBit02 = 0x04;
0 ?8 x1 K6 Y, r: p. Z9 ]    const BYTE btBit06 = 0x40;8 u& E9 Q' t/ z! s: ^+ H
    const BYTE btBit07 = 0x80;6 T1 \, L- D, E- e6 G: j# G# @
    // const BYTE btERR  = btBit00;
) X4 T! [( _. c9 t    const BYTE btBusy = btBit07;
* y; }% Y* y( U    const BYTE btAtaCmd   = 0xEC;
3 y+ L- y6 l! o* f    const BYTE btAtapiCmd = 0xA1;
" V! E: G5 |: A1 F3 p
) j% C5 \& ~  h/ G) j; I/ ~    __asm6 b; ~( v$ A- H( b) {
    {9 o9 D& j- Z5 P
        // 必须先执行这条语句
# |: B+ X1 t; [        JMP EnterRing0
+ m4 v6 A/ u9 [1 |5 N: E8 s: S- e( E! R( y& f# X1 h, u
        // 定义过程  U9 e, v9 e  d0 e
        // 等待IDE设备直到其不为忙为止/ u8 t" n/ }2 S5 j* R, e  ^
        WaitWhileBusy proc3 D' v: @- _0 M

7 Y4 l8 q. c. y        MOV  EBX, 100000$ b) Z$ {: l9 H2 [5 o/ r) }2 A1 h
        MOV  DX, dwBaseAddress1 L# U3 E- N% x4 u. h
        ADD  DX, 77 A1 [( n. K# L! w: D

- R* Z) y/ f5 X! t2 A% H4 v! o! v        LoopWhileBusy:
" Y7 E5 n+ Y" c$ c* \
/ n4 {# B5 s/ t  z        DEC  EBX
1 Z. H; V; Z* A  Q1 M& e        CMP  EBX, 0* ?% H4 k9 D1 L+ m1 D
        JZ   Timeout
/ B, V. I  i8 u) `: s5 m  ^: g        in   AL, DX7 n2 C' T# h0 M/ I/ Y7 l
        TEST AL, btBusy
+ w" l# V& c+ u: w        JNZ  LoopWhileBusy
" f$ @" R# _. w, A. h4 d+ I: F& `$ g        JMP  DriveReady4 u5 z, L" p  a2 [$ h' e* N: G

6 |' ^8 s7 ^5 f) R8 s9 F% {( {        // 超时,直接退出
; h/ n7 i! r9 z4 @9 k2 H        Timeout:
1 g/ c, B1 O% M7 H        JMP  LeaveRing0
/ f- b' F/ W+ R5 h$ k$ g) c# b, ?, E: ?        DriveReady:
$ {! x1 j3 t- L. Q: Y# U5 e% L  c        RET
( ^8 G; ]- s" ]5 _& b3 c8 T        ENDP   // End of WaitWhileBusy Procedure( P9 g4 E: Z+ z. F- R' v

( K9 \0 T  ]1 g2 G        // 设置主盘和从盘标志
5 K  o# z* R  h        SelectDevice proc
. o+ H; t; [4 d
! o( w' j; F( K  ~        MOV  DX, dwBaseAddress
- h1 S" a5 o7 b0 d        ADD  DX, 63 \6 ]8 m- ~9 f( k
        MOV  AL, btMasterSlave, }  W2 s) @! a/ d0 M

1 l1 Y' o; @  w8 C! y        out  DX, AL$ Z0 M4 i3 P! G9 W( j. K. j
        RET+ R% r3 ~/ T9 m8 K' \0 }
& P* J0 _: f  J) V6 F! b
        ENDP  // End of SelectDevice Procedure
1 b7 d5 {) ~% ~4 t7 G3 B! L& ^# K5 w
        // 向IDE设备发送存取指令
7 f% D9 `/ \0 n9 W! E# o' q        SendCmd proc
% z$ x& `! G" u  S
1 R+ A+ z: i* r( U/ {        MOV DX, dwBaseAddress
" t9 t& {+ j9 W) t  R1 v        ADD DX, 7, j) s' _5 }( A3 p
        MOV AL, BL // BL是主从盘标识,在过程外设置
8 j7 T$ ^# n0 f" o% b3 j        out DX, AL
, C% J) G! z. n/ I, k% p* M$ Q        RET
% M4 J9 P4 t1 a6 z% S! Z6 U& Q# l5 C        ENDP  // End of SendCmd Procedure
$ h8 z5 S/ P. k2 u- K5 g3 h
+ J3 B: D. R1 a. [        // Ring0代码
% j. v% ^' N$ o, }" ?; V        Ring0Proc:- u* S3 Y/ @0 z9 x) t& I' b1 ~
        PUSHAD
9 c. B/ I; f2 Z/ T5 [# e$ V% k2 u3 b        // 查询IDE设备是否存在
1 P0 ~  ?4 E; n  `        MOV DX, dwBaseAddress
& s( i% a* }# U- _% O- o& }6 g! p        ADD DX, 73 V/ l8 ^2 g0 s  Y, }: b2 C
        in  AL,DX
) ^/ S" P& U* R! _+ L( U7 f2 R# s4 A2 T" t% {$ x
        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回% O8 J" `/ d/ `0 J
        CMP AL,0xFF0 `8 c) Q; s" |  {. s. K2 T& D
        JZ  LeaveRing0
) ^4 q; k" S! D+ i& e4 G4 S* |        CMP AL, 0x7F6 I) D% `( j% G9 h  @
        JZ  LeaveRing0" o) Y; e" D7 V

& g& n: p2 Z6 T        // 设置IDE设备存在标志
6 J: i* v( w' s9 P5 @5 P        MOV btIsIDEExist, 1
6 x8 {8 Y/ Z' M% g* g2 B' k9 c) J! B
' f3 h# y* X" R+ j  v        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
& Y: x( T( t; i, k* T" i        CALL WaitWhileBusy) t5 ?3 f" j1 J
        CALL SelectDevice
3 r9 o0 o% n2 Z9 o% e: ^, n8 g, H; G6 h  Z5 e$ q$ O6 B
        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏4 d! q- ~( n, u; A0 a7 j# B, v
        CMP  btIsFirst, 17 ]/ O) g) d3 e& U3 f" r4 \1 R
        JZ   LeaveRing04 J2 e# a# M1 a
2 A# W' F: R* V) R" @
        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???+ m" ~* U2 i# {7 [5 C/ {5 E
        CALL WaitWhileBusy
9 R6 H# z; u8 o7 Q
4 }, g& H7 O8 n        // AL的值等于cBit06时,不存在驱动器,直接返回
/ D) l3 I4 ^8 B* C        TEST AL, btBit06
! U0 r! D- i9 j% l' V8 @5 _        JZ   LeaveRing0' f& B% P, N$ X% t- \

( J' }2 l. i8 w( {        // 设置驱动器存在标志
" c$ `& V& U$ [        MOV  btIsDiskExist, 1! {3 N; X+ O* D" o" v
2 N( [6 e6 J$ ]$ g1 W5 ]: G
        // 发送存取端口命令3 O: R- N4 P% d* }# m8 W* d
        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,2 D# N1 S$ p7 ^0 V
        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
4 T# ^3 S" `# Y( u7 k        CALL WaitWhileBusy
+ S3 x4 d/ V: G! v1 Q; \) V6 F        CALL SelectDevice    // 设置主从盘标识8 {1 o4 C. G3 k% V# G
        MOV  BL, btAtaCmd      // 发送读取命令2 z: G3 x8 E2 H- X  `# ~
        CALL SendCmd
4 u) w" `. r+ [  b; O- s1 g' j" k- `        CALL WaitWhileBusy
$ v$ m* q  {9 v6 a& N8 u* D  c2 Z) g) t! h5 Z" ^4 B  s8 Q
        // 检查是否出错
$ c; d1 X* j; J, p        MOV  DX, dwBaseAddress
+ ?7 o( ^! U0 W7 ?+ d" H1 w; @        ADD  DX, 7
* J' @( A0 x" i; @! u" Z  M$ v6 C9 g8 ~  f7 i! z
        in   AL, DX
5 d& {' e6 P  Z
' ?7 ], m7 _) _; N        TEST AL, btBit00& X" V+ V& X3 Q) A4 s; a8 Y/ _
        JZ   RetrieveInfo   // 没有错误时则读数据$ Y3 ^. q1 _6 c' i7 |. q$ Z9 e" Y

5 h# w: T9 y8 S  h1 E4 I+ ^* A        // 如果出错,则进一步尝试使用ATAPI设备命令. t" ^* X: t. P3 V; W- y
        CALL WaitWhileBusy6 |" i! ~7 U0 X, \' w  y
        CALL SelectDevice* P1 _3 F- U! L" ]* a
        MOV  BL, btAtapiCmd
, e) ?" ^1 R* m. b        CALL SendCmd
- I  I  z! A$ k/ y        CALL WaitWhileBusy8 [" p, M/ i, O, E7 t$ [
- D+ P5 f* J- W9 I. b
        // 检查是否还出错
0 R- z' C$ f9 v2 ?  R2 u        MOV  DX, dwBaseAddress
3 y, [6 Q7 L8 d& S        ADD  DX, 7- l5 ]% |* A' R8 k0 k
        in   AL, DX
  p) e0 v" C; w; [6 M+ {        TEST AL, btBit00/ R  d+ x7 @1 [' P
        JZ   RetrieveInfo   // 没有错误时则读数据/ s. z( q- [( d3 F( j7 K5 \% u! m1 t
        JMP  LeaveRing0     // 如果还是出错,直接返回% K$ J7 O; N( `- ^6 M

2 }% o. J1 j. T        // 读取数据6 @. T4 R) a6 E. b$ i
        RetrieveInfo:, \, U1 a$ s" v  i; O

' ^" I( {* V' p2 m2 F! g% k        LEA  EDI, wOutDataBuf9 q3 T1 ?8 J* [. C4 t6 D, U
        MOV  ECX, 256- J1 U/ e+ T" ?
        MOV  DX, dwBaseAddress: e( ~5 S' ]* w$ y. A8 \
        CLD+ W/ E" j3 w7 L; ]/ C" T9 v8 k4 Z3 j
5 F, n9 c+ l: \) X  q
        REP  INSW( z, ]  n; q5 n: Y( U
* E$ x' L5 p, W4 {+ g4 X, T" l
        // 退出Ring0代码/ D  F: I3 ~) x+ X0 Z3 ]! {/ u0 U  v& O
        LeaveRing0:
5 s2 Z+ C; n2 M0 d
# U; i# k1 x/ L; Q7 J        POPAD  O+ I, E/ o" G% z) h
        IRETD. U7 T& `( u$ A% r% R9 [, P* u
; x- \! ^" S( d" }+ ?
        // 激活Ring0代码
) \# Z- q% C2 R8 E$ C        EnterRing0:
& n7 Y5 b7 H$ O% ?( p' D& p0 w6 Z
( _8 E7 L+ N- Y0 F        // 修改中断门- M$ o* h: i0 W4 g' N& W, O
        SIDT FWORD PTR btIDTR1+ m3 j! {. H* u' y
        MOV EAX, DWORD PTR btIDTR1 + 02h
3 X' t. n$ _; o8 c; O        ADD EAX, nHookExceptionNo * 08h + 04h
/ e/ S9 D/ ~/ s$ g        CLI8 g6 Y# U1 s: o5 n( v

% t( c, \) l' B        // 保存原异常处理例程入口5 K$ D) c8 F# B
        MOV ECX, DWORD PTR [EAX]; i  X- H& r/ \
        MOV CX, WORD PTR [EAX-04h]9 V! f) b: I9 @3 y: }% p
        MOV dwOldExceptionHook, ECX
8 `8 S7 x3 g- [: i) u, O3 c8 E: Y+ d* Z; n& u7 n9 b
        // 指定新入口
0 Z* W& M- l; g8 t8 m: x        LEA EBX, Ring0Proc& ^" K3 p% X6 D2 ~; F3 ~# _, G
        MOV WORD PTR [EAX-04h],BX
" s. U" Z) l1 z/ j; j$ I- R; E        SHR EBX, 10h
( `3 Y) _0 y1 M) D% [        MOV WORD PTR[EAX+02h], BX
  E0 `3 t5 a2 M, ?/ t) B% o+ a  C8 p5 j1 `
        // 激活Ring0代码
! y' g# X; ~6 x        INT nHookExceptionNo2 |9 H/ W$ [$ X! }

" K6 F( d5 N9 J5 S        // 复原入口% j4 \2 f% [9 N6 b
        MOV ECX,dwOldExceptionHook
! @( ]+ \! l1 W) \1 s9 {        MOV WORD PTR[EAX-04h], CX" y. g2 F; C+ t
        SHR ECX,10h6 L( n* M0 \0 j( Z6 |
        MOV WORD PTR[EAX+02h], CX' D* z1 |9 Q& b5 y( X! ]
        STI
; z5 w5 r# C8 C2 Q4 L    }- I$ s, Q" m) r9 s0 ^
    if(!bIsFirst)
  ~$ O+ k: V/ z7 Z    {" \5 ]& ~# ?7 b& a" T2 _$ q' S
        bIsIDEExist  = (bool)btIsIDEExist;7 H- Y7 i: y9 h9 I1 H4 x
        bIsDiskExist = (bool)btIsDiskExist;5 r$ _  V; _  R4 S
        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));) k" n; G# x1 U: @9 b: F( f' X
    }
7 C4 Q2 I* ?- Z1 Z* t}
  y# b" N  A+ V% B//---------------------------------------------------------------------------
0 N2 ^, q+ w4 k; @2 r4 ]" d8 {// 调用方法:! q) \& H' A% G5 ?# c9 j
void __fastcall TForm1::Button1Click(TObject *Sender)
8 L% Q, q! G1 ~# i4 Y$ i{
) M  u% u' b, K# M) u    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);+ d6 [+ A( B" \& t/ C: N: f4 x  v
}6 X5 z! d! ^( v: @
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-7-2 08:17 , Processed in 0.038473 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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