找回密码
 注册
查看: 8017|回复: 1

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

[复制链接]
发表于 2008-1-6 19:59:06 | 显示全部楼层 |阅读模式
代码框架,你所要做的仅是修改WQL语句,具体可看MSDN。以下代码为简介起见,一次返回所有的CPUID或硬盘厂商系列号) D% A6 x, G9 A) \- t# t: t- ^

  1. 5 ]0 Y4 F3 Z9 K( t' [
  2. #include "StdAfx.h"
    " J9 G+ l6 R, _  e
  3. #include ".\puiddisk.h"
    4 W# Q0 v* W. k1 E  E& b+ S' b
  4. #define _WIN32_DCOM
    ; I# g% P; S6 Y* B% J
  5. #include <iostream>4 D9 g! s4 H* r: p# i2 T
  6. using namespace std;
    8 {" q5 T. j/ q0 Z. l6 J$ J
  7. #include <comdef.h>
    ' n, K) Z! R* K0 i2 |  e! s; {
  8. #include <Wbemidl.h>' t1 q' i4 r, U& u

  9. - ~+ L6 f% N2 z2 y7 ]; p4 P* b2 T
  10. # pragma comment(lib, "wbemuuid.lib")3 X7 p( u$ r* O6 Z& P
  11. CpuIDDisk::CpuIDDisk(void)+ @, ^9 s6 [; `7 N
  12. {/ g- g) ^: O. p# H" h
  13.     GetInfomation();
    ( c( ]9 J8 X* Q6 J: M+ G* j* \
  14. }
    " U* {0 ^% Y% J( g: B$ Y6 ~) O) G

  15. + A/ d) t" m# Y
  16. CpuIDDisk::~CpuIDDisk(void)
    - b, Q. u. W7 F& u/ s; E
  17. {$ F" G  d/ S0 z, O. m, @0 r! t
  18. }. H1 h' j6 m. M7 v. D
  19. int CpuIDDisk::GetInfomation(void)7 H8 t& X6 A1 b5 f' C- y
  20. {
    $ e# x: F6 Q" Q& C4 w* O- n' E
  21.     HRESULT hres;- k* A2 X' _8 r& l9 C) R
  22.     //步骤1:不是必须的,COM只须也只能初始化一次
    % P7 G* j; k$ A+ v2 ^, C" I8 w
  23.      hres =  CoInitializeEx(0, COINIT_MULTITHREADED );# ?) ]) e3 T8 P* y
  24.     if (FAILED(hres))
    3 S7 P4 e/ Y2 R2 x% M( n- M
  25.     {
    1 j! f+ k2 \& f- w5 f
  26.         return 1; //初始化COM异常:注意,COM只须也只能初始化一次, t( F# B7 p5 X7 S3 o. i
  27.     }3 R5 i$ P7 x( P/ d
  28.     //步骤2:不是必须的,COM只须也只能设置一次+ [9 T0 e5 F- C2 o  u4 l4 ?
  29.     //Set general COM security levels
    ' c2 V+ a, ^5 a! w5 _$ c
  30.     hres =  CoInitializeSecurity(2 q0 f: K: j4 ?4 Z1 _. b
  31.         NULL, # z; M, _  w+ E7 ~! R' z
  32.         -1,                          // COM authentication: a, L: p: h1 D! s6 g  L2 Q& t0 G! L
  33.         NULL,                        // Authentication services
    3 @( C+ A3 b9 n3 I& E5 T
  34.         NULL,                        // Reserved* D/ S# n; [+ L. o8 U$ [1 Z& I2 X' y, _
  35.         RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication ( ]  W) }# d  @0 a! ~
  36.         RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  * L1 j) ]( L+ H. p% O
  37.         NULL,                        // Authentication info
    ) }3 x! J9 @# d( o8 x  I0 ^, H
  38.         EOAC_NONE,                   // Additional capabilities ; U& k& B+ A. U7 s1 y; [- I6 c
  39.         NULL                         // Reserved* F, S% j) R6 ^1 u
  40.         );% `% }6 h2 p1 m# ^, |# ~1 b, ~" f
  41.                       $ j6 {, [" n4 |# r
  42.     if (FAILED(hres))! k% O6 \0 U3 ?2 u' Q3 a
  43.     {+ q% L! ?: V* p( h! H$ y: |$ i' J
  44.         CoUninitialize();
    + T3 a) Q8 ?: v6 K) K& t1 `9 j
  45.         return 1;                    // Program has failed.
    + Q0 Q, [& C7 r( b
  46.     }) y7 i9 ]0 z* S, M" ?: n
  47.    
    ) C3 H5 t- X. S
  48.     //以上不是必须的,若已有“::COMInit();”,则要跳过+ l8 R8 J+ ~! l, V9 K" E
  49.     //步骤3: Obtain the initial locator to WMI : p) ~3 f0 K! i+ Y" y; X
  50.     IWbemLocator *pLoc = NULL;
    - n7 D& m7 S5 _* Z3 g
  51.     hres = CoCreateInstance(
    6 u% ^4 L9 R" F1 W. q
  52.         CLSID_WbemLocator,             1 v- y+ y' n$ A7 h
  53.         0, 5 d! P6 G) e# V) _1 \& A' {# A- f! g
  54.         CLSCTX_INPROC_SERVER, , [. J. i% d8 w4 E3 M) |
  55.         IID_IWbemLocator, (LPVOID *) &pLoc);1 h& t" i% U' }3 L" d, L
  56. 6 s4 w& ]% A4 S' |' `& a
  57.     if (FAILED(hres))# I2 n4 g# R" d1 d* y
  58.     {8 D( |+ D/ B( I: f* x
  59.         CoUninitialize();- s  A3 S  g1 s+ G! E
  60.         return 1;//Failed to create IWbemLocator object
      B' G7 f: b5 \& m: `3 w$ M
  61.     }' P1 j. c* F2 y: b

  62. ' b/ Y/ K$ Y7 _# F
  63.     //步骤4:Connect to WMI through the IWbemLocator::ConnectServer method
    6 q( J( b2 m, a2 z" Z& d6 `* r/ Q# U
  64.     IWbemServices *pSvc = NULL;+ D2 r% L( T! Q9 R! {! d
  65.     hres = pLoc->ConnectServer(9 S5 e- N; h2 _. v3 _2 M
  66.          _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace) u1 o- F9 I' n# V& ^) P
  67.          NULL,                    // User name. NULL = current user  f$ E0 x* i! w+ ]' L' T
  68.          NULL,                    // User password. NULL = current/ H  n: \9 r3 u7 ^/ y8 c0 Z
  69.          0,                       // Locale. NULL indicates current
    9 J( Q+ j5 s; r# ]
  70.          NULL,                    // Security flags.$ h* a6 s7 f: _# i
  71.          0,                       // Authority (e.g. Kerberos)% |2 z+ f% {1 U0 V
  72.          0,                       // Context object * s0 R  R- m/ \3 r5 H
  73.          &pSvc                    // pointer to IWbemServices proxy
    , f. F% f% z- u- h! X) @
  74.          );# T8 N) t/ U* T9 C/ Q# L
  75.     4 @* H4 J" z3 p# a
  76.     if (FAILED(hres))+ ~9 k) y; c/ n8 N8 d* |# M
  77.     {
    ' S$ [8 j4 h# G& j$ ^" a
  78.         pLoc->Release();     0 O! h6 h' \$ l# R3 z, ~: c
  79.         CoUninitialize();
    " {: F, o+ E- @  R
  80.         return 1;                // Program has failed.# {4 u: p* b8 e5 m1 ]/ Z
  81.     }7 L4 ?7 s( N' d( ?/ l. q4 i
  82.     // 步骤5: Set security levels on the proxy# j9 _1 E/ X) [" b
  83.     hres = CoSetProxyBlanket(
    $ s) V  L9 f5 ?
  84.        pSvc,                        // Indicates the proxy to set
    % _$ E* O6 c2 k2 x/ G) m
  85.        RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx
      z' Q4 E$ v0 w& C
  86.        RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx
    2 Y1 O2 E( t/ x% Y. E
  87.        NULL,                        // Server principal name 1 a; \9 B9 \) z* {5 C+ d
  88.        RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx
    + v) b( m2 ]/ w
  89.        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx. V' H2 O  J+ s! e
  90.        NULL,                        // client identity
    2 l/ G0 R3 M8 R! n
  91.        EOAC_NONE                    // proxy capabilities ) l( k" [8 I" q! K" g+ q% j1 U
  92.     );
    ! v3 X. S' j6 N& ^2 q7 ]3 I5 t- v

  93. 6 g7 W0 k8 {. `1 P
  94.     if (FAILED(hres))
    2 Q; L2 i6 f" Y2 s" J3 C
  95.     {+ Q3 v! |7 G: j5 O$ ]' _0 G( ~
  96.         pSvc->Release();0 W+ f  E5 [3 k* N5 r2 A& j. f0 X; H
  97.         pLoc->Release();     , Y( u! \% [! y5 h$ ?
  98.         CoUninitialize();  l$ _; j  l8 |* r+ V
  99.         return 1; , f1 j+ Y/ Q# K& a; h+ c
  100.     }" b' t, i8 d0 M  A; J0 E

  101. / M( ], o/ W8 ]/ F  T3 }; x& ?, R" I
  102.     // 步骤6:Use the IWbemServices pointer to make requests of WMI ----
    ( m- N# E' u; S7 [& v+ ?+ Y, y
  103.     IEnumWbemClassObject* pEnumerator = NULL;& R2 R! V6 Z2 X8 _
  104.     //计算CPUID5 B# T. z' L- ~. @! N$ f; q$ P
  105.     hres = pSvc->ExecQuery(& x: o5 R! H% U; z' M0 E1 }
  106.         bstr_t("WQL"), ( z1 y6 f8 Q6 }# H
  107.         bstr_t("SELECT * FROM Win32_Processor"),//Win32_OperatingSystem2 t( ^, T6 W1 _# _- T8 @1 ^
  108.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
    * l( d: o) Q' i1 t3 ~
  109.         NULL,
    ! z1 @2 c3 k; \8 W/ I5 a! r
  110.         &pEnumerator);' h  B  @! ~7 z' O
  111.    
    ( m( m: C: K. U/ I5 |* ^% B' \
  112.     if (FAILED(hres))4 A" x( {" s7 _* b* V- Z
  113.     {; \" Q8 q+ V, o8 P, ^
  114.         pSvc->Release();  D3 q6 W9 k# v: q
  115.         pLoc->Release();
    4 U7 z8 v: [! R* H
  116.         CoUninitialize();6 k; M% |; R5 p& x$ s
  117.         return 1;9 B8 ?& J$ ~$ V
  118.     }
    8 @3 L8 D4 h0 U
  119.     // 步骤7:Get the data from the query
    ( ^2 y" U3 _- ]" h4 X( Y, r) {7 R
  120.     IWbemClassObject *pclsObj;) l  j/ B9 |/ @
  121.     ULONG uReturn = 0;
    ' u% `9 |8 D7 w
  122.     while (pEnumerator). \3 Z! ]3 W$ z. K5 ]: H" S1 m
  123.     {
    " @% f( h3 ^4 J0 z1 b5 n1 T
  124.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
    6 ^8 k: k1 P9 F8 p
  125.             &pclsObj, &uReturn);1 A  ~; I7 W9 R, \# k) V+ W& S

  126. ; k6 }  B& @& s/ o6 f6 a! I3 P
  127.         if(0 == uReturn)) K  U( e( ^$ [, A
  128.         {
    6 D7 o6 u4 z1 u/ X3 B
  129.             break;
    ( S) M7 F, ~3 V7 `
  130.         }
    % s& c8 c3 ?' c
  131.         VARIANT vtProp;6 }) D5 ]1 ]1 Z2 p( d: t% n
  132.         VariantInit(&vtProp);, `7 e3 `) ^: e' D; m
  133.         hr = pclsObj->Get(L"ProcessorId", 0, &vtProp, 0, 0);
    7 G2 l' m# @# ~: [5 D5 V$ G4 W
  134.         strProcessID=_com_util::ConvertBSTRToString(vtProp.bstrVal);//strProcessID:类级变量
    & s& b) U2 y# Z" e( |' u
  135.     }! P7 O; k1 _3 R6 G- F; ^* R

  136. ! l7 U5 w$ A% G
  137.     //计算硬盘系列号* \+ k2 k+ h0 b0 \. a. t9 d; \
  138.     hres = pSvc->ExecQuery(# n: L& B2 g, G. _0 V; I
  139.         bstr_t("WQL"), 2 R& }% p# w, O$ v* Q- v
  140.         bstr_t("SELECT * FROM Win32_DiskDrive"),* Y+ ~, @2 {5 D5 x' J7 `6 G
  141.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, . ~2 @  D' Y" p1 ?0 ]
  142.         NULL,% `& r6 S$ ?0 S0 Q5 Y
  143.         &pEnumerator);
    1 C. T( y9 \! @1 h- c6 u; v- @# `
  144. # l# S: x, H& x7 D+ D; V
  145.     if (FAILED(hres))
    + w9 g: c/ }- l2 W8 z+ @" a
  146.     {
    7 y. h+ G" S, B/ u0 i
  147.         pSvc->Release();
    , p* \. v: K% v+ a: W- i! O
  148.         pLoc->Release();' e* Q3 l" h/ @. o
  149.         CoUninitialize();
    3 O' c! t4 U0 F4 x
  150.         return 1; 0 I" t0 F. r6 x4 b/ P$ O
  151.     }! ]" }0 P7 Z4 J+ n$ K! b6 H
  152.     while (pEnumerator)$ C5 r2 k  x: W& q  r! Z2 f7 r5 [
  153.     {
    , I6 }& B+ M- L' ^5 \- @/ ]
  154.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
    ( z0 Z, z2 I  Z# S" A
  155.             &pclsObj, &uReturn);/ L+ ?5 B1 l# X, t: l. g3 j

  156. 7 {# b# O" s+ j
  157.         if(0 == uReturn)
    ( c9 R: [' N5 O6 K  C/ X! ]
  158.         {  J8 K' N3 \# w  ^: l6 u* \) ]
  159.             break;
    ) @' n& V! z/ e  D6 Z
  160.         }3 [, V& y3 b, i6 x1 j
  161. 8 M: W* B9 F: i- m
  162.         VARIANT vtProp;& d  s* l4 z& S7 Q2 \9 r( o9 K
  163.         VariantInit(&vtProp);
    ' E0 m4 h" Q# d3 A2 j, K4 o' O
  164.         hr = pclsObj->Get(L"PNPDeviceID", 0, &vtProp, 0, 0);
    2 K  K7 o5 h" d  D8 c
  165.     strDisk=_com_util::ConvertBSTRToString(vtProp.bstrVal);
    * c' `# I! i) G7 _) |
  166.     }( y" e! h" r. I, W+ n
  167. 0 ~: z& ~) v% e- A$ D
  168.     pSvc->Release();9 j- k- i* e9 E' A7 g
  169.     pLoc->Release();
    / G# L4 |; @: d& w" u% E: w. D" n
  170.     pEnumerator->Release();1 i; w8 {' K! q" t& L4 t
  171.     pclsObj->Release();, f9 S; {( g" ^+ a$ X; c9 f
  172.     CoUninitialize();
    - W* x- j) b* K7 S
  173.   ~' y  Y  |- w
  174.     return 0;   - ?* C1 _6 v0 z) g
  175. }
    6 h# g# A- ]6 ]# p( y$ W% V6 S2 G) O
复制代码
 楼主| 发表于 2010-10-11 19:21:05 | 显示全部楼层
本文代码经ccrun(老妖)在Win2k下试验成功.$ Z- N. `( c* A( }. z( w* T' I
4 R0 [7 H! o0 m( n$ u* ?- @( C2 a
#include <WinIOCtl.h>
/ F6 F( D/ S$ S4 h7 M) Q#include <stdio.h>) F! V" G! H" L5 R0 @) f; ?' {5 o9 b/ {
% w& c/ M! L" A, E4 M) l& ?
#pragma inline
/ w/ l4 S, X/ V2 R//---------------------------------------------------------------------------
8 C* x2 e# V" ]" \* b// IDE NT/2000/XP专用变量0 y! s. G) o0 _' D! g
#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
3 N, b( j) @# X1 d: M#define DFP_GET_VERSION         SMART_GET_VERSION
6 y! Q8 X$ w$ p8 w' @* ?#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
8 L+ a6 l( L2 t4 S8 r#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
# m% t  J0 x4 G! Z4 \9 s2 i" ?0 a# o. X' \) Z6 i( b
const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令! s8 @8 c4 c5 C4 Y  V) d! I
const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令5 A1 r! y' E: s
: N; M$ |! `; [1 Z& f. Q7 v7 G
const int MAX_IDE_DRIVES = 4;
. Z( f  t, ?- H4 x5 W- q/ q8 P* S2 ~+ f4 d: [
// SCSI专用变量
, g2 O  f- R  a" p7 \$ T% ~const DWORD FILE_DEVICE_SCSI             = 0x0000001B;
" I+ U2 p7 v6 y9 w6 i" |# M" Aconst DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
7 Y+ X) H8 T) O  Iconst DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
4 x& j& s4 ]: R/ sconst DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
8 C0 l+ N. O9 x& f
6 Z6 ^& ]0 W4 U0 f' y3 a- D+ Ptypedef struct _SRB_IO_CONTROL# @0 F& L" S: V+ _1 C0 m" [$ k
{- N, `3 \0 K' l2 v
    ULONG HeaderLength;
- G# J! N1 \5 W/ m2 q" F  F, n9 A    UCHAR Signature[8];
/ X; b& T  c5 K    ULONG Timeout;* @" G  w; ~# g
    ULONG ControlCode;
; K# D' Z- t! c' L' u    ULONG ReturnCode;
! W( d) a; K* ~4 ~    ULONG Length;. o/ A: X' \( p* G
}SRB_IO_CONTROL, *PSRB_IO_CONTROL;
, W" ?* K1 k3 H3 C7 v. r8 R) U6 t
// 读取的主函数( d7 S1 @  A* e7 L% R+ \" u" [
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
7 I( T/ c& J) `$ _# G! l: G4 ~- a6 g$ W( f/ _
// 辅助函数$ d9 ^1 W: i3 _
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);2 O( J& ^& l+ h0 C+ r; a% f
// NT/2000/XP函数
: M2 o% q8 R% M6 v+ {1 \void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
! S! S  z3 a5 Y0 [% B0 Lbool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,+ I# i: E+ w: i1 E2 q, U: H- \
        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,/ a3 w. E- Y  V. h! J" B+ M( x; }6 V
        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
& i7 c( {0 [9 @: e" b// Windows 9X函数
- ^) q5 K( S/ Z4 l+ Pvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);- k! {& h) r9 D8 V
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
: t9 J9 J3 q* p; p! L# K/ c        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
5 L' T6 c! W# M; N; {
7 Q3 c' Z0 o9 h0 o+ @$ w  w// SCSI读取函数(for NT/2000/XP)0 ~# M7 e# Z' m7 {4 h/ B. Y8 _; ~
String __fastcall ReadIDEDriveAsScsiDriveOnNT();
, Y# z! m0 L6 s//---------------------------------------------------------------------------( r5 V; {1 t9 E' U$ @
// ReadPhysicalDrive
8 d$ ?4 b; U3 i8 H$ pvoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
+ N  X/ u  `  i1 b+ Z7 W{
0 ?% k# g5 W" r3 o& f; k    switch(Win32Platform)( E# R* ~3 k/ ]- t- e1 F
    {
. R. V4 L, @) {& Q, V- G        case VER_PLATFORM_WIN32_WINDOWS:( o  `2 M% a* T
            ReadPhysicalDriveOnW9X(pSerList, pModeList);, o% R$ P) f( q) r/ c' x$ ?
            break;, K' z! y  f& F  A- L
        case VER_PLATFORM_WIN32_NT:  J3 h7 M. d9 S3 W6 b
            ReadPhysicalDriveOnNT(pSerList, pModeList);% A" A4 X3 M% m
            break;) V1 l# e$ F6 m1 A' ^0 C2 s+ o
        default:
: ~( e9 }2 c* p# Y( T            break;
/ C( V8 y6 C% X7 c' T    }
- K" B7 m/ v, C" T3 q; X2 h: M( X}
6 c, b" ?$ e% s; B//---------------------------------------------------------------------------2 z3 g5 H$ Q8 r7 S2 g
// ConvertToString
+ D" i* x, l# E% |) {5 D+ ]$ achar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)4 V3 T( J; X/ u4 M4 }4 T* [
{
' U9 n' T6 u. g* C    static char szResBuf[1024];
6 [6 O& [; ?$ @6 g7 S    int nIndex = 0;) T2 B& j0 A9 X3 d( D: O
    int nPosition = 0;
! r8 C# @$ |) ^" Z. b, J8 c/ P# ~
! z& ^( d5 G# u% R1 W* n7 U    // Each integer has two characters stored in it backwards
# l% t# [! [9 R6 G6 O! F6 J, Z8 {4 b    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
8 X; @0 H" B8 L+ E( R8 ^1 J  E! Y+ t    {! T/ Q; {: U+ z
        // Get high BYTE for 1st character
- f1 n9 g  q+ V        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);9 x2 P0 R3 M7 p- }# |
        nPosition++;# H( A& p: K9 I

6 Z( G; Y" B% x- q+ H        // Get low BYTE for 2nd character7 G5 u% W1 o$ p4 G
        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
# z  k3 N1 r, q( `        nPosition++;
' Y9 ~" G; ^* H3 w2 \& u7 U    }
5 o: m' ^3 A) w
9 _0 S3 s" D$ t8 p8 J' f6 {    // End the string
  _1 `1 U: Q" f$ `    szResBuf[nPosition] = '\0';
; t) X1 }# O' H/ G1 e! l/ H% l6 p
. [! m! T+ l8 n    // Cut off the trailing blanks% A* X; p/ q! P' H* g$ s
    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
! h) n/ S. o& n        szResBuf[nIndex] = '\0';! \; R; H% A1 a, a- i+ d

& T, w3 i. I' d. V0 k. n    return szResBuf;
' v1 u" h2 q3 @1 }& p6 y}
6 l* g# F" {+ X//---------------------------------------------------------------------------
% ^9 m0 _$ n4 ]  ^// Winndows NT4/2000/XP 代码
4 C3 m8 I$ ?% |1 a//---------------------------------------------------------------------------
( I: t- x5 [% `// ReadPhysicalDriveOnNT3 u, p+ z7 Q# `! f
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)% i7 ^" M6 s) {$ M
{$ L: o) u$ v* ^4 {: p6 D
    // 输出参数- S- _$ D: A/ b/ x& W/ v( l
    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];: U, W* M, l3 |0 m: Z: k
2 Y0 S! m8 r* B. ]
    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
( V  e+ p: r2 p    {
+ l" @* |/ Y$ B0 ]% a( v        HANDLE hPhysicalDriveIOCTL;
# ]% ^% k9 Q( F: n0 V: k& A* \: J9 K) `        char szDriveName[32];
7 W! U$ t% T: E, w1 Q4 c% r
5 ^  U3 u4 s% s8 m        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
7 @0 K( s2 O! j; S. I- v        hPhysicalDriveIOCTL = CreateFile(szDriveName,
3 Z. o  c. A) U. K% N                        GENERIC_READ | GENERIC_WRITE,
" g1 l0 q# U6 Z5 m5 S7 E                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
$ ^1 O( _$ X) i; M4 O  y                        OPEN_EXISTING, 0, NULL);
2 ^) h. q1 Z0 Y8 B( W! x4 g3 X1 m6 p- C3 O+ T4 t  q; O; T8 m& L
        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
* ]' H! z) x  y2 a5 f3 w! i        {
) }" |/ a) a2 a9 ^/ S: e; w+ K            DWORD dwBytesReturned = 0;
& I! [: n% A% |9 ^  h5 z5 ]            GETVERSIONOUTPARAMS gvopVersionParams;0 z& W6 Y# q2 D: ?$ k

- h- f3 R( u& k* ^            // Get the version, etc of PhysicalDrive IOCTL
4 b! Y9 G/ ~3 ~% G            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));. W/ b5 w5 y3 b; S  |

! E- C* t5 I3 i3 h            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
* ~$ N1 R* @3 E& I! ~0 @$ H                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),5 n' W% @' N. |7 i
                    &dwBytesReturned, NULL))( y4 `+ ]0 S7 k8 R/ e
            {6 I, x6 Z* C& v& D9 L' S0 `
                continue;
6 g9 i3 z- [1 u! ^4 X( w# C            }* M7 w& Q. d: z: F& f2 d

+ N" U+ N  E3 y/ Z9 l& p' J. ?            if(gvopVersionParams.bIDEDeviceMap > 0). j: L2 S8 U5 ?4 m9 y
            {
# _( S. ]6 d1 c3 U  \                // IDE or ATAPI IDENTIFY cmd
4 Q3 D. |9 b8 l, X9 k                BYTE btIDCmd = 0;
% g8 [8 k0 M8 v                SENDCMDINPARAMS InParams;
) F) [* N1 P, V- D3 J                // Now, get the ID sector for all IDE devices in the system.* W( O: X+ K5 `5 s
                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
0 _$ q  y& a$ t6 m                // otherwise use the IDE_ATA_IDENTIFY command% H) u! T; |& ^- ]; C
                // 具体所得结果请参考头文件中的说明& Z8 p4 s9 f& A& ~, @( y
                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?9 [- k' x( o! R+ D& c4 F- ~' T( E4 b
                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;) \. U+ t: T6 u
                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
  E, @+ c7 Q( y/ ?                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));6 R/ w) G1 ^/ K2 z
" ^5 V) \8 K8 h2 V/ ?
                if(DoIdentify(hPhysicalDriveIOCTL,
$ z9 _8 D. |+ P                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,$ R% h7 C0 s4 N( r0 ^' g: O
                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))2 Y  M7 F$ i" V+ Y2 t3 X* S
                {4 z$ i* v7 Q8 e4 D7 x5 `
                    DWORD dwDiskData[256];6 T1 l+ ?/ R0 ]8 ]
                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件; f! P" A% N7 i+ s: N: S
                    char szSerialNumber[21];
( I' b# a' E' C9 m; F                    char szModelNumber[41];/ h0 J* p0 D' c3 C8 ^

* u  [' s$ _" z3 y( O$ M                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;! d6 S5 Y! y- a; U
                    for(int i=0; i < 256; i++)
3 _- F3 }+ Y) o# V8 t                        dwDiskData[i] = pIDSector[i];* Y" M2 K+ u( F1 ]7 {
                    // 取系列号2 R1 O9 q7 X) X  w' s& D8 f! t
                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
  s. r5 i. Z+ C! e# m                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
) i9 U! I- \9 ]! Y% t( X" s& W0 o
                    // 取模型号
" z- f6 q% }: [- S. J                    ZeroMemory(szModelNumber, sizeof(szModelNumber));9 _8 X- z( q' z3 T# R
                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));( ^$ s! c% A) i7 c0 d: h
# @' z3 C1 Z; c! S0 j& S# _( v
                    pSerList->Add(szSerialNumber);
0 J0 c, m  Y! ~0 t: X                    pModeList->Add(szModelNumber);
$ j5 Y% |5 r% b' g- \                }( n# j) ]8 b5 o1 ~7 q
            }
+ ^% l- w8 h1 F) d            CloseHandle (hPhysicalDriveIOCTL);
4 A7 K1 D; G3 |+ j/ {; t        }% D: r7 o# o" f9 P
    }# f% i7 J( X" Y$ q
}$ i6 g7 S! ?9 Q$ O& D9 N
//---------------------------------------------------------------------------, y1 Y3 X- L& f! B3 [
// DoIdentify
6 b" I' P! C* ^# E9 w. @6 p+ z/ Nbool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
5 Q$ I: }% n. t0 \8 _              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,8 i4 W% P3 Y5 y+ M; Y( @
              PDWORD pdwBytesReturned)
/ V# g6 N- n  r$ T, X/ J{7 H& j9 b: K5 T0 x2 w
    // Set up data structures for IDENTIFY command.
# a! D8 k' o1 ^    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;7 v8 F5 v- ]8 O  E1 q+ Y  A
    pSCIP->irDriveRegs.bFeaturesReg = 0;, n, I4 m5 q3 R
    pSCIP->irDriveRegs.bSectorCountReg  = 1;
8 C5 H* B: U. B# N: g+ _    pSCIP->irDriveRegs.bSectorNumberReg = 1;. S5 T7 {" @' v& Q  \1 R
    pSCIP->irDriveRegs.bCylLowReg  = 0;0 m* k3 ^* a( {* O$ h5 E% z! y, j" d
    pSCIP->irDriveRegs.bCylHighReg = 0;; n( n& u% z' J) s* V
, d7 }- W: c8 M; O
    // Compute the drive number.(主盘和从盘所对应的值是不一样的)
% |* J; L' A- v/ H) t) |    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;4 w/ Y6 T7 a6 m6 Z- T8 c

( U/ D5 F  [/ t: F    // The command can either be IDE identify or ATAPI identify.
* v2 \5 U0 d  V( v) ~% h7 |    pSCIP->irDriveRegs.bCommandReg = btIDCmd;: `$ H# R! v% x: C" w: U6 h
    pSCIP->bDriveNumber = btDriveNum;- ^6 i- ]* @0 R6 P5 D2 a
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;7 E2 e& K/ p' m* i
9 }3 P8 G' W# w8 {! }$ V' i
    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
! t' m; ^* q! B           (LPVOID)pSCIP,
7 {5 c0 O% C+ v* i           sizeof(SENDCMDINPARAMS) - 1,1 W) P1 B, A# p, O+ T" [
           (LPVOID)pSCOP," a  h6 I; W/ H' h3 X# v5 |
           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
- g" t' U( f* D' j) ~) h           pdwBytesReturned, NULL);6 L- h, }+ k. I. t$ y
}
: h. S* T8 x- ?' q//---------------------------------------------------------------------------- x7 S) ^  l  U
// Windows 95/98/ME 代码5 c9 C1 ~1 N' I
//---------------------------------------------------------------------------
; }+ z  A- d. S: ]// ReadPhysicalDriveOnW9X/ ]$ }5 t, a1 P+ U4 m5 d( p
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)
4 r$ ^% x! r, a% I+ g2 y{
( V- @% u* K5 l    WORD wOutData[256];
( h, u. C3 e4 M* t) z: K; u3 ]    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);, z6 [/ q: p) }8 ]4 a2 |, D/ N
' ^# I# J5 j, l3 r
    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
, @# ^* o6 a* x    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以% I! \! ?; s6 ]* L. O6 M
    // 避免蓝屏的出现。(期待高人能指出原因)( D0 Z& w+ ?( m9 h) I+ ?
    for(int nDrive = 0; nDrive < 8; nDrive++)  a/ R2 O" m% t% R, Y
    {" w9 ~( F5 _- ^
        WORD dwBaseAddress;$ X4 z. D- b$ ?/ K
        BYTE btMasterSlave;         // Master Or Slave& t! l+ a- e6 z6 Y
        bool bIsIDEExist;
+ g8 |! k$ E( A" U, V5 ]        bool IsDiskExist;
* ]4 j- D& v4 F4 c
- a' v" Q: Y) G' t0 L/ E  ]        switch(nDrive / 2)
: b4 a; ]" l5 j3 K$ P        {
( r& c) s/ z1 B. [4 N3 Z            case 0: dwBaseAddress = 0x01F0; break;: x8 C' M0 p4 [3 |+ i
            case 1: dwBaseAddress = 0x0170; break;
5 V) Y' X! u$ V2 @- w$ z: I            case 2: dwBaseAddress = 0x01E8; break;
+ P9 x7 h5 }; I: d4 r9 F: h' j            case 3: dwBaseAddress = 0x0168; break;% x( V- `$ C3 z1 G/ T& y
        }0 e: h( C4 c5 ]) F3 N
5 l+ G4 g5 k/ |( s' [
        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);* n% J% ?. E3 B" W1 D6 U" ?
, s. I$ N+ D" L
        // 进入Ring0
( h- p' U( |3 g" M1 f        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,: Q" X- X; U) j3 T( M, z; _: r; S) R
                bIsIDEExist, IsDiskExist, wOutData);! }- g0 W5 ^0 H9 m" T# Q
    }+ p* o/ L! ?% ~% O8 ?

, J& Z* E) [$ h3 h* s& p' N& x) C; L. ~    // 开始读取2 X  v6 O1 m$ Y: t; V
    for(int nDrive = 0; nDrive < 8; nDrive++)
8 s+ `, d2 Y8 h- U, h1 n: r8 D    {
0 a4 R" ?3 f1 d3 W' y        WORD dwBaseAddress;* q5 ]  _: L/ c' D# }7 F( L2 H
        BYTE btMasterSlave;         // Master Or Slave
5 a0 p: b7 E& X0 b. U        bool bIsIDEExist;. N) D( J9 W! Z* {; E: x
        bool bIsDiskExist;8 Q9 D! y5 v: }$ L
        switch(nDrive / 2)" I3 T6 Y; ?- D( g  D) V, L; n
        {" K, O; e& l' i' y7 u# w+ h: D0 S, z
            case 0: dwBaseAddress = 0x01F0; break;* T' v4 K' }. B5 z- M/ x
            case 1: dwBaseAddress = 0x0170; break;! F8 i7 o9 {$ E3 ~5 t/ a+ L
            case 2: dwBaseAddress = 0x01E8; break;' t1 v. T# c8 K- W& \$ G
            case 3: dwBaseAddress = 0x0168; break;6 t7 B2 u4 v7 P1 Z' ^& H
        }
" V; j$ ]+ S) e9 q( F, j, d: K6 v; r+ e/ D- r& T8 L0 ]0 x3 V1 Y
        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
4 l& y/ |1 b- G4 h; W& K! J$ X9 ^  `+ r$ F: a9 S) o5 h
        // 进入Ring0. ^$ F0 v3 s- _# z
        bIsIDEExist  = false;
7 e1 s/ f, y( D) k        bIsDiskExist = false;
. c0 k- S8 v2 d: Z5 T: T        ZeroMemory(wOutData, sizeof(wOutData));
: U, H" |0 [1 `' ]! H
. F: z* F/ {) V# `1 t0 _+ U) w6 G& T        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,7 J) j* b8 m! q1 w. d# l* ~) W
                bIsIDEExist, bIsDiskExist, wOutData);. [( J' R/ C. e/ K9 k9 `: X

+ m0 g' i- U6 e7 T, H) z        if(bIsIDEExist && bIsDiskExist)
# W% x, w; b% s; Q        {
) {* H+ A4 j! {" r; F            DWORD dwDiskData[256];
* [4 }8 P9 G. M; ^- n8 s            char  szSerialNumber[21];
# T2 G+ y; a/ y- o4 w7 M            char  szModelNumber[41];
* Y) X+ `' H7 z0 @( C  l0 u/ P3 A+ Q2 N* r3 `$ E* E! R- o9 a( C
            for(int k=0; k < 256; k++)7 I! k$ ]& V  r! ~3 R
                dwDiskData[k] = wOutData[k];
6 s+ N* }3 w  F' L' ]7 ?& g" d9 \( i0 f# t* e/ t& v+ o
            // 取系列号8 `# a  U$ O( j' g' d6 F* r, C
            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));! h+ L* o8 R  S  M, g7 e
            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));# W) r1 L) c& }* o
5 j( K  d! X+ g$ u, B) x
            // 取模型号! ~; y' f8 |: Q  m1 s$ ]- R. ^
            ZeroMemory(szModelNumber, sizeof(szModelNumber));4 {! d. j4 [  V
            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));$ d- A% H! m2 E# e

' Q% h6 `& s5 ]3 }3 i( m* Y2 _0 w7 v            pSerList->Add(szSerialNumber);
- {5 V+ ]+ O! g  k# o1 `; @1 _            pModeList->Add(szModelNumber);5 Z, [/ f! r" f
        }0 n0 ?5 C2 }8 Y* X- e" T
    }
5 D3 g9 j, ?6 U" V! X    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
% j, y; a# {  s}  i: @* V0 ?" ?  z3 Q& B- m: V
//---------------------------------------------------------------------------
: O4 y# j+ P% A8 n  Y// 为防止不负责任的转载者,在此注明原出处信息,请见谅。
! X( S; Z7 h* `' z// 资料收集整理:ccrun(老妖),欢迎光临C++Builder研究: http://www.ccrun.com: A& M% u0 s3 n2 T
//---------------------------------------------------------------------------
1 k1 y. I$ x( P// ReadPhysicalDriveOnW9X_Ring0()
+ |7 J9 R5 `) j5 `6 C//7 w& T% y5 ~7 ]' O9 X* \+ |- ?' w
// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h( O* h5 Q: f) r2 K3 Q/ S
// btMasterSlave = Master(0xA0) Or Slave(0xB0)/ o( E% Z7 p/ v; }. j
//---------------------------------------------------------------------------
" K9 o1 q9 R% M1 _: g1 L1 h6 Kvoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
0 p5 M; r' a3 b5 H4 Q9 R5 [- V" P        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)8 |3 w. ^. u9 ^$ A+ S0 |) F
{6 p" I5 D% }# C; F5 k+ Y
    BYTE  btIDTR1[6];0 i: {5 s$ {$ N$ L* @# U. f  `
    DWORD dwOldExceptionHook;/ p* v7 T7 q! }+ L4 q" p
    const int nHookExceptionNo = 5;$ }) _/ z$ w% M0 w% z7 a3 x7 \

. i0 K8 a" v0 r% k    BYTE  btIsIDEExist = 0;. p/ l; ~: @3 I% o
    BYTE  btIsDiskExist = 0;. E" B* O- i) Z, |: X" J# b8 Q$ b6 b2 x
    WORD  wOutDataBuf[256];
% u0 [1 \: f, _7 k$ C% h: r+ C0 Q) X- N7 }" {9 U
    BYTE  btIsFirst = (BYTE)bIsFirst;
( N- `' s" C: g
# Y9 j0 ^6 z2 h; D    const BYTE btBit00 = 0x01;
2 u4 P6 l/ _/ s    // const BYTE btBit02 = 0x04;
* O: z6 X- o5 V+ ?" R# \    const BYTE btBit06 = 0x40;7 V+ h4 x  K- ]/ C9 V. y
    const BYTE btBit07 = 0x80;
1 f( Q1 `: w: b- E- e) m1 H+ b    // const BYTE btERR  = btBit00;/ _8 u) J5 g1 g$ F
    const BYTE btBusy = btBit07;1 ~$ I! Y4 z  }' t- D, i
    const BYTE btAtaCmd   = 0xEC;
: f% l) G# S$ K# y9 g6 n$ l    const BYTE btAtapiCmd = 0xA1;, s5 K/ J8 T. _9 i8 I/ P

: p( l0 N% w2 Z7 ?! }* f6 V    __asm
; K8 p% z/ K1 K9 g) Z  ~5 Y    {4 k& w% \7 @/ G" Z. ^% L& s: n9 |) ~
        // 必须先执行这条语句
' [5 r' [$ }5 s4 P        JMP EnterRing0
$ l. R7 C5 T+ p  b+ P7 n! ]  O8 {( Q0 F5 u* U  K
        // 定义过程; Y* Y. F9 b- n( ~
        // 等待IDE设备直到其不为忙为止
, z- F$ I% N+ K! |        WaitWhileBusy proc
. p9 e/ t5 Z8 \) e: r" [* g
2 ^. m4 `: f2 W- o% Z4 d        MOV  EBX, 100000# W! V' a$ m& @! s  h7 S
        MOV  DX, dwBaseAddress
" @) j$ s4 G' m2 X        ADD  DX, 7
) P6 Z0 Z$ q4 k( T+ W+ f3 {% n0 y
+ U5 f* e* Z0 q( K5 j        LoopWhileBusy:
: z) b- X. I2 V  y( b. v* _" O) W
5 i6 b% w/ y8 k+ N* E5 d        DEC  EBX
! p8 A+ T; a1 ^        CMP  EBX, 0
  T; Y0 i( V2 H3 Y4 P: c6 Y; [        JZ   Timeout
, q) _7 M0 b% I8 w% t/ ^        in   AL, DX
' X4 `( G6 T+ K( I( B( w: H: H2 y        TEST AL, btBusy
$ Y( k4 C2 u% B' c        JNZ  LoopWhileBusy4 l; \8 G. F. g: b5 m( R( F
        JMP  DriveReady: u4 |2 P8 v3 s# q8 Y! l
5 S6 N: T2 I, F# z
        // 超时,直接退出$ l$ @3 H6 e2 C/ n8 N
        Timeout:
* b3 ^2 R; J" a        JMP  LeaveRing0
' `6 ~& Z5 e* `/ L- b        DriveReady:( a' |7 P- T/ @4 R% {  h4 t+ l7 B
        RET- p7 P- h# z, `3 s8 x
        ENDP   // End of WaitWhileBusy Procedure
: r- y% [# W+ }/ B' G% M* ?* h4 e6 Y( T" ^4 m3 z. \
        // 设置主盘和从盘标志
4 L9 J: N: M- U. w9 O7 {        SelectDevice proc
8 h9 r: [% ?7 b
8 n* O0 s; b5 S& X! c& R. F0 E1 M        MOV  DX, dwBaseAddress* Z" r" |, V4 H# K- U8 g
        ADD  DX, 6$ D; Z, O& N) y6 g
        MOV  AL, btMasterSlave
0 u2 y; M7 N5 R* m& a8 l5 ^( ]  z% B; k+ s1 w. b
        out  DX, AL
% \  }: E; B) @* z        RET
9 U+ g: ]$ Z* Q3 n  z/ I& \/ y4 D
9 f+ |- [* F* f4 N3 D        ENDP  // End of SelectDevice Procedure
' _+ i& U0 d+ g5 @/ V' j" V6 ~% D% s& V0 e8 m
        // 向IDE设备发送存取指令$ V; h" `/ R( i, R! r; d/ ~
        SendCmd proc
9 v% P. {$ J3 X, l8 H0 @: y7 A# S9 F. F% k4 x
        MOV DX, dwBaseAddress$ A! s- U5 d% t" H0 K( V* b
        ADD DX, 7
2 g1 ~' ]4 Y+ O0 k# R8 X0 \- [        MOV AL, BL // BL是主从盘标识,在过程外设置/ C' {0 V: F; l  o8 f+ {% [% b  @
        out DX, AL3 h2 M* R4 @6 _% m2 u- g
        RET4 z9 v  P% L& b
        ENDP  // End of SendCmd Procedure
$ s# a4 I2 n8 S0 y) T. S0 c. Q& F& C* j% i0 s, m  [7 X& i( l
        // Ring0代码
' U' P/ |! _0 r! ^- S        Ring0Proc:( J0 P2 \4 A+ X" F
        PUSHAD
: i9 l1 Y& c& \* ^( l+ ^' b        // 查询IDE设备是否存在- R! b! w# A  f/ t5 Y
        MOV DX, dwBaseAddress4 X- V/ k) b; ^5 J' ~9 `
        ADD DX, 72 j$ ~7 O6 B1 R$ M% y; U1 p( A& T
        in  AL,DX' i) e4 m4 Y  @- J. b

) A7 E- _! k3 E+ x+ p3 u0 i4 V        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
7 A/ C! q. r, w$ `! C5 ]2 F        CMP AL,0xFF# H) r% B/ W2 o0 \7 ^9 @) n! Z% K
        JZ  LeaveRing0) C4 U# L6 W. x
        CMP AL, 0x7F
4 b( U: r" `6 O  [  Z: Y: ?) j) b6 P        JZ  LeaveRing0! I2 j% o- T7 \$ T$ `0 C4 P) I
3 u2 r  t" s9 `; B6 L
        // 设置IDE设备存在标志
2 m( X3 \6 I8 O! Q- Q        MOV btIsIDEExist, 1
! R7 i6 N# B( a, x
3 a* `/ b/ Z" D3 I7 ~) O# y  T        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
* L& T" h6 A+ B9 d* ~: i% {8 z) B2 B7 p        CALL WaitWhileBusy
) u# a8 C! Q4 v; Y3 u+ @7 J. ?' ~        CALL SelectDevice
( x8 K* T$ Q% W
0 }% p$ k( z$ r1 u" F- X' b        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏/ b& j9 A, M( c5 H6 C
        CMP  btIsFirst, 1
' c6 x/ S/ `" E- P" ]        JZ   LeaveRing09 Q  E: ]$ M% }7 e
) V7 Y; I8 P5 l- l
        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???4 ^9 c2 M. o' s# o# ^# `' W
        CALL WaitWhileBusy
4 O2 e4 \5 A- Y8 D  D1 e2 J4 `7 w  b4 S8 Y
        // AL的值等于cBit06时,不存在驱动器,直接返回
0 Z! N$ C5 e7 }% a! N        TEST AL, btBit06
/ W6 O( r! ]6 n        JZ   LeaveRing0; U. k7 ]$ k* p0 d& ^

' g7 x% w1 }. q1 T$ L- |        // 设置驱动器存在标志$ H& H* Y& e/ _: s* R
        MOV  btIsDiskExist, 14 S; t4 \7 J) }
9 c1 |" o& H% S, w: a
        // 发送存取端口命令
  j$ }! b, u6 t2 K. ]* H: Q/ s( D        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,4 W& x/ c. U9 ^: _+ Q9 W* _2 y" J
        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令% p* ?, b7 M5 w! h0 |
        CALL WaitWhileBusy' u& L" x2 Y6 \4 P4 a- w9 o4 O" }
        CALL SelectDevice    // 设置主从盘标识  g# \) `* O: G, K
        MOV  BL, btAtaCmd      // 发送读取命令
/ [. s: {8 a/ U/ {) G5 L! m        CALL SendCmd9 a" |; k* R4 f+ Z
        CALL WaitWhileBusy3 F7 C" A" V) u

( a  u+ m4 r0 w  ]/ }4 z& Y5 r) b        // 检查是否出错9 I4 \& c0 e& f  n- F
        MOV  DX, dwBaseAddress
2 d& @) O/ D/ k# N$ {( {# M        ADD  DX, 7. }4 Y, ~) _# I* ?! Y( O1 e

8 P# }0 j7 s" R6 a8 k        in   AL, DX/ h% N( t; l7 ]7 r5 ^1 z( s- k; [
/ q" j$ h; f3 O  g9 i$ ]/ I6 _% ]
        TEST AL, btBit004 ]4 i) v; O( i/ p
        JZ   RetrieveInfo   // 没有错误时则读数据! e5 Y) R$ a& q0 m8 [, l
! C, ]2 q. y: w2 ]; n+ J# J. ^
        // 如果出错,则进一步尝试使用ATAPI设备命令9 G) U8 w  I  b1 h) C0 _0 x
        CALL WaitWhileBusy
2 i' L# [8 F6 s        CALL SelectDevice- ]' C% P7 f& [( G7 n5 y8 F7 z7 B6 F. ?
        MOV  BL, btAtapiCmd! R, V: I& F+ V8 s
        CALL SendCmd) Y: F% l" Q. A5 b% d( O
        CALL WaitWhileBusy
  d# w, a1 \7 q/ p+ t7 m% b7 R
( @! i4 p! {3 G7 w' c* C        // 检查是否还出错, Q( Z5 J( m0 ], I& _  y7 W. Z: F% s
        MOV  DX, dwBaseAddress; {( I+ ]: @% g: G
        ADD  DX, 7$ ?9 a& d% ]- x: a
        in   AL, DX
4 b" \$ X1 d  d# K# R        TEST AL, btBit00
: k2 z- w" S+ }0 Q        JZ   RetrieveInfo   // 没有错误时则读数据
0 Z5 W7 @: ~: ~; S        JMP  LeaveRing0     // 如果还是出错,直接返回
. y! C9 g/ D* {4 T9 D7 N
8 |) I$ r: m' ?4 v        // 读取数据* ?; X& r. T8 K; }, H: L; K
        RetrieveInfo:) @5 ]9 o) L& v' ?9 D/ n

9 s/ y4 i1 ^0 x; S% u  Y, x        LEA  EDI, wOutDataBuf8 b: \2 Z1 |% W' p1 O3 ?7 s7 Q
        MOV  ECX, 256
: }2 N2 F5 [! S5 ]% u; {. q        MOV  DX, dwBaseAddress1 v( K  h; T. T$ Y; H2 P! w# [
        CLD" b/ ^* V% i0 n) z5 K& q
. m6 O! T' L+ t! O% w" i# n. C
        REP  INSW
. w/ K1 V4 z5 X* J" R) I1 X+ t
% a$ k* o9 N8 g0 {        // 退出Ring0代码+ J8 l- y9 ~2 ]& w
        LeaveRing0:; L+ W" u2 G; U/ v2 L1 ^

6 Z) E. s& i. R7 _        POPAD5 u' d  r- t7 X. e
        IRETD4 ^# Z* J6 g: ~
  I# W8 G% b$ e4 ]3 Z1 z
        // 激活Ring0代码
% j4 N# a% y! L4 i        EnterRing0:
9 \5 o2 ~. E# E0 F* x
$ Y4 e2 ^8 |5 j5 v        // 修改中断门
6 [# ]" K; O7 {, v5 v* q        SIDT FWORD PTR btIDTR1
# I& r0 S) ?9 G' D% R        MOV EAX, DWORD PTR btIDTR1 + 02h7 [; Q, q6 K7 \% T. B
        ADD EAX, nHookExceptionNo * 08h + 04h
1 S9 N/ ?+ v' \; J! h$ M        CLI/ t8 O* q: P; B- k

2 H2 d. \& B! e, h, _        // 保存原异常处理例程入口; X+ D. T: x# ]; g
        MOV ECX, DWORD PTR [EAX]
/ P7 t  j; n/ a, U& [+ ^5 `        MOV CX, WORD PTR [EAX-04h]
. c- N0 H' c5 f3 K0 ]) |        MOV dwOldExceptionHook, ECX
+ `: b; \9 j' j/ G: x. w1 R1 s% {) u
. d, s; w! k0 |: d- b0 ]8 k        // 指定新入口
1 v! E, j& {7 @2 G% x1 t" l        LEA EBX, Ring0Proc
8 A) Q, N5 K, r+ g# [        MOV WORD PTR [EAX-04h],BX
. H" p6 I8 _) e% q; R* z        SHR EBX, 10h
2 ]2 g  ?6 \8 |: d8 J$ ]        MOV WORD PTR[EAX+02h], BX) j- l+ g* v& m* A' k$ v

: G7 t2 ^0 Z9 d( U        // 激活Ring0代码) o4 Z1 M; v& Y/ u+ u
        INT nHookExceptionNo
  O+ K: a# P9 j4 S" m! \' p
6 g1 k% G, C5 X8 w, B9 P        // 复原入口' D$ H! _# [4 _0 V$ Z; E1 H4 x5 o
        MOV ECX,dwOldExceptionHook
8 ]5 b  S0 i: i" ^        MOV WORD PTR[EAX-04h], CX$ ^. u7 G+ y) H5 x/ h
        SHR ECX,10h
* K  j* w  u+ C# W" Q  j        MOV WORD PTR[EAX+02h], CX
) l$ i% _9 t7 u, \% ?. [        STI
. a+ n+ J$ s+ U    }% s6 a4 f* i0 w* x& Z! g
    if(!bIsFirst)
& _6 q/ O; E' k& \    {
. A7 P% R+ h. S* `+ w3 Y" P        bIsIDEExist  = (bool)btIsIDEExist;
/ k  c; Q. l$ f. u8 ~+ ?        bIsDiskExist = (bool)btIsDiskExist;
* [/ L) F. E& k        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));! v) H# x: W1 r* `. q0 r& w
    }+ B$ B5 g6 f- @, ]$ P
}
5 ^: V; m( m0 F+ I/ F" ~//---------------------------------------------------------------------------8 s8 F: C/ X$ U
// 调用方法:
  s+ Q. X! ]$ ?$ ?void __fastcall TForm1::Button1Click(TObject *Sender)
8 E- ^+ a% k; V! R' j. b9 V- s{0 H% V' E! k0 q- u+ a+ s/ E
    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);( N0 c5 T4 d  X4 C- _8 Z: N+ G
}
3 J% Q6 t( P% D- n8 f. G, F
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-10-1 22:53 , Processed in 0.017827 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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