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

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

[复制链接]
发表于 2008-1-6 19:59:06 | 显示全部楼层 |阅读模式
代码框架,你所要做的仅是修改WQL语句,具体可看MSDN。以下代码为简介起见,一次返回所有的CPUID或硬盘厂商系列号2 n. L  Z( q( {' A# \7 ?
  1. 5 z5 }0 D4 C. z5 B5 F
  2. #include "StdAfx.h"( \9 G" T' y( n, _0 `/ R$ M
  3. #include ".\puiddisk.h"
    & K: }; A5 M" |4 C
  4. #define _WIN32_DCOM
    & [  S7 M9 }7 K8 Y9 y
  5. #include <iostream>: R+ R2 e5 B9 H3 Y5 J3 R4 J
  6. using namespace std;
    + t6 N. m& k9 C4 p
  7. #include <comdef.h>
    0 v+ Y! J8 L8 M0 C
  8. #include <Wbemidl.h>
    , r/ l& x) O% H% m! ?, v  g8 }

  9. 0 [" r+ v9 e% ]( H; i, _
  10. # pragma comment(lib, "wbemuuid.lib")
    4 E  D8 I8 D, e3 n! d! Y
  11. CpuIDDisk::CpuIDDisk(void)
    . c6 b9 q+ T( ~+ K+ _
  12. {
    / g3 a. y) b% I' o
  13.     GetInfomation();& I2 r( e. i, t/ v2 j5 v" V
  14. }$ ~; k) q- o9 D" U
  15. 4 i0 T5 S, j) t# G9 z6 X
  16. CpuIDDisk::~CpuIDDisk(void)
    6 @& y, K6 O7 o6 m$ D7 k& k" s
  17. {
    " i/ u( r9 M4 g" |- h& b. O% }
  18. }
    0 Z) M0 z, X% y+ B+ n: t3 s% X
  19. int CpuIDDisk::GetInfomation(void)
    ! w2 q! L* Q( t
  20. {1 T9 i: q% [  I2 K6 ~- q% i4 y
  21.     HRESULT hres;
    1 M5 M$ ~% t9 m9 t7 b& f
  22.     //步骤1:不是必须的,COM只须也只能初始化一次# g; M' l; R3 a* |2 ]; V( L
  23.      hres =  CoInitializeEx(0, COINIT_MULTITHREADED );- z" @' N; e4 f, ~$ G) y5 H7 {
  24.     if (FAILED(hres))" K8 q8 b- j( \1 l
  25.     {
    # o. V6 J5 P  m% W7 c, g. j! A! Z
  26.         return 1; //初始化COM异常:注意,COM只须也只能初始化一次7 P* \  I5 [; |! p, n! T: u
  27.     }9 Z$ }2 [1 I% w5 X1 O
  28.     //步骤2:不是必须的,COM只须也只能设置一次8 q/ X0 {1 |0 a) m5 S
  29.     //Set general COM security levels+ J' c% S9 m4 q4 }: `2 H& ]
  30.     hres =  CoInitializeSecurity(
    . m( V* }* J! [* n: i* D
  31.         NULL,
    $ b: u) ?/ m9 W/ P1 G
  32.         -1,                          // COM authentication6 k! x. F  e: g) i' B
  33.         NULL,                        // Authentication services
    ; u& z2 [4 |' I& N8 R0 g9 J
  34.         NULL,                        // Reserved
    2 {+ z2 _9 [/ O9 D2 E3 A9 V
  35.         RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication ( B' b1 N: v7 x3 c8 K* Y
  36.         RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  . s4 T: W( C* i; ?
  37.         NULL,                        // Authentication info
    & q* K, V* \% z; R
  38.         EOAC_NONE,                   // Additional capabilities
    2 U, K# q! s8 A% ~) y
  39.         NULL                         // Reserved
    ( ]$ x! d: s9 u) D, ~
  40.         );
    ; g. o2 i8 _$ y4 d8 f
  41.                      
    + h# \, {6 z" L. k5 Z$ R6 T
  42.     if (FAILED(hres))
    2 m7 D/ T. ]3 m$ U
  43.     {* s- }" _" Y, r2 ?3 P
  44.         CoUninitialize();& _% F, Z2 T: \8 O: u& P9 @
  45.         return 1;                    // Program has failed.
    % {, j1 N9 t' K; b6 S
  46.     }
    & @: }5 o) b1 n) p
  47.    
    : V: K$ e7 ^( S. x5 Z$ {+ u  u
  48.     //以上不是必须的,若已有“::COMInit();”,则要跳过, @" x& q; {! P/ r% [
  49.     //步骤3: Obtain the initial locator to WMI
    - _' r  @4 \5 m0 b/ S& H* a
  50.     IWbemLocator *pLoc = NULL;6 i/ l" t5 N. R2 P
  51.     hres = CoCreateInstance(
    - n: q$ V) k2 E4 u! [
  52.         CLSID_WbemLocator,               I6 T$ ~& `- D0 w9 s/ z6 k
  53.         0,
    8 E1 @; ^. l( H  R  c8 `3 X! ~; m
  54.         CLSCTX_INPROC_SERVER, 7 x# x( @8 Q) m) F( O; f
  55.         IID_IWbemLocator, (LPVOID *) &pLoc);1 A; l* S0 L  e$ I+ `; o2 u
  56. # c1 C8 t5 Y- {- B* O0 L; }
  57.     if (FAILED(hres))
    ! u9 \( ~2 X( ]  f
  58.     {
    - E& \& J- U* A
  59.         CoUninitialize();  f+ t% F7 W# t( b$ S
  60.         return 1;//Failed to create IWbemLocator object1 Q/ }1 |* M% K! I
  61.     }3 C& Y- Y0 V6 u! ~

  62. 8 a, x  [- C! L" P- Z9 ^2 O3 S
  63.     //步骤4:Connect to WMI through the IWbemLocator::ConnectServer method
    * s9 n# R4 S+ r$ M; m& ], n
  64.     IWbemServices *pSvc = NULL;
    ; c' ?" B5 J3 \0 a' m
  65.     hres = pLoc->ConnectServer(! c* n1 O) B( D8 c; F
  66.          _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace
    ' l& F- T, `. U( A
  67.          NULL,                    // User name. NULL = current user
    , `! s% D8 A# d. i0 r8 v
  68.          NULL,                    // User password. NULL = current# ^; s2 E# q7 ~& @& O3 h
  69.          0,                       // Locale. NULL indicates current7 L: P  I$ J% T6 U1 d: V6 C
  70.          NULL,                    // Security flags.  @& u! D* j2 _2 A7 Z# ^. `
  71.          0,                       // Authority (e.g. Kerberos)8 R( ^3 _4 ~% d/ z1 v# b' n0 G6 w
  72.          0,                       // Context object 8 B0 R' C7 u- T8 h5 Q) d" p' W
  73.          &pSvc                    // pointer to IWbemServices proxy$ a8 X( G4 r: Q2 F+ E
  74.          );/ u# ]8 r$ \4 ]
  75.     ( w+ [7 E6 c8 `! S  ?8 {0 @
  76.     if (FAILED(hres))
    ( l" }* k# F) q; E( P
  77.     {5 D6 B  `6 W) @
  78.         pLoc->Release();     5 P. D4 q7 m& {5 V+ h
  79.         CoUninitialize();; |+ S8 e4 k5 p& z
  80.         return 1;                // Program has failed.4 U# v% ?5 n# G
  81.     }2 X7 R& Y- d/ [" z
  82.     // 步骤5: Set security levels on the proxy
    5 P# S  B' F* b: ^' T9 {2 Y
  83.     hres = CoSetProxyBlanket(: X* h& ]# P$ K) `% K! P- Z
  84.        pSvc,                        // Indicates the proxy to set
    ' I/ f. A+ r' X6 `& T4 m/ l' `& D
  85.        RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx
    8 J& ^) [, {7 E5 W( T8 z1 w' D
  86.        RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx
    0 g8 Q6 x3 F9 o/ E; F
  87.        NULL,                        // Server principal name
    9 V2 p- d$ i1 \1 k
  88.        RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx
    6 `# w3 Y2 }/ w% ]/ e
  89.        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
    ! K' T& u& w! v8 [5 J$ r
  90.        NULL,                        // client identity
    7 \; J: M/ D" H7 ^9 U% A+ t
  91.        EOAC_NONE                    // proxy capabilities 2 d% r, z0 Z3 J6 h5 h# f
  92.     );3 [& \' L* z) t/ L& W; f  y5 H  `
  93. 2 }3 J, I) f% o9 n6 v
  94.     if (FAILED(hres))
    # o/ a$ B# n; j1 B# }2 }0 `
  95.     {( V. H" u1 n, q' ]; U
  96.         pSvc->Release();: h) z0 }. t9 c1 N& M
  97.         pLoc->Release();     
    5 Q/ x" v5 @6 Z; D5 d0 ]
  98.         CoUninitialize();& `& a8 g* |4 V  A6 |
  99.         return 1;
    0 Y- ~: [2 {& r) b% R% g6 M
  100.     }: e% i' f8 x5 N0 V. I/ w: ~* a
  101. 0 i  X2 [! f. w9 C+ b
  102.     // 步骤6:Use the IWbemServices pointer to make requests of WMI ----
    . P: O4 V( D  ^9 z9 A
  103.     IEnumWbemClassObject* pEnumerator = NULL;0 y1 |' s& ?: y! W2 T0 w8 b0 ]
  104.     //计算CPUID: w9 s) ?8 h) @
  105.     hres = pSvc->ExecQuery(
    " ^0 N1 S3 K5 z0 B6 y9 r( |
  106.         bstr_t("WQL"), * u9 ~, Z; n2 T+ ?' g5 Y6 O, {3 J
  107.         bstr_t("SELECT * FROM Win32_Processor"),//Win32_OperatingSystem, p1 K! L) n# W: E
  108.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
      A4 f. H/ T. U8 d( l' x
  109.         NULL,
    ; E4 a2 o  E/ c; [' M0 U6 \
  110.         &pEnumerator);0 v5 m4 p. l) m( [4 F
  111.    
    + d; L9 k- M! ^3 g# _  ^: k2 K1 H
  112.     if (FAILED(hres))3 o5 h+ `5 G& p6 |
  113.     {
    * \( r9 p4 H8 g' Q7 }5 a
  114.         pSvc->Release();* K; L8 L; q1 j4 {- `# Z
  115.         pLoc->Release();
    & D4 @. M* y4 H7 n
  116.         CoUninitialize();
    8 b& E$ B) q2 `* F' q
  117.         return 1;6 S6 J( m5 u4 Q& `. y8 Z- ?
  118.     }
    $ P& P4 K' L  Y! q" d! Z0 A
  119.     // 步骤7:Get the data from the query 5 G1 T# ~2 `& N$ P0 u
  120.     IWbemClassObject *pclsObj;
    # f( V) i7 C+ F8 v7 w* n! r1 A8 x
  121.     ULONG uReturn = 0;
    * F- O" n: m. t
  122.     while (pEnumerator)9 n! b; s+ {0 a) t4 d
  123.     {
    7 `" D; d3 P: m* ^$ _. M0 F) b
  124.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, ( _% B) C" R. V& K4 S* f0 O
  125.             &pclsObj, &uReturn);+ Q- X! J! b; p% a
  126. ; n$ W7 D" P, H1 t( D
  127.         if(0 == uReturn)8 q- b0 x) h" Q- I9 @) [5 x4 g
  128.         {
    0 r. p( U, o' Q( z! u+ Y" K1 X4 O
  129.             break;
    , k/ W& }( n# l0 e+ }
  130.         }$ A& r" {& y: }. _3 ?1 g9 y
  131.         VARIANT vtProp;
    # f$ ^5 s# M( w3 Y: W" x
  132.         VariantInit(&vtProp);1 V$ H% |5 v  u! o0 L
  133.         hr = pclsObj->Get(L"ProcessorId", 0, &vtProp, 0, 0);' P9 n2 x/ S/ h
  134.         strProcessID=_com_util::ConvertBSTRToString(vtProp.bstrVal);//strProcessID:类级变量
    7 }. ^: K" V; }: k  ^1 s, ^# i1 \
  135.     }
    7 K8 _& T) s1 w+ W% z
  136. 5 q6 D  L1 |% _. N% [2 E
  137.     //计算硬盘系列号
    % g, t# T. x5 h2 I
  138.     hres = pSvc->ExecQuery(3 C3 d/ [. n% n, k) K# F
  139.         bstr_t("WQL"),
    9 Z/ C" Z6 N0 z1 x$ c6 o7 y' A
  140.         bstr_t("SELECT * FROM Win32_DiskDrive"),6 F" V/ Z& o) k: X0 ]; t  E& G
  141.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, $ F" o: l/ l6 {1 R% L3 I2 M
  142.         NULL,
    " }, _+ {: k! _7 W( @
  143.         &pEnumerator);; v1 @: |! ~. @. K+ m, F& u
  144. ( ]) \6 c) N8 j( w* h( _
  145.     if (FAILED(hres))7 _6 v' F0 a$ K; z# {
  146.     {
    1 U* R& }% D1 ~# U+ v
  147.         pSvc->Release();
    ! `" _' S# r6 ^9 C5 s2 L
  148.         pLoc->Release();( g  v; r+ K& w6 P7 w; q$ Z  E
  149.         CoUninitialize();* x( t! h" ?6 R5 S) \4 K/ H
  150.         return 1;
    - s7 r3 V! S; ], {
  151.     }
    1 y6 t2 a$ |4 w4 q* H5 j
  152.     while (pEnumerator)
    # G* t, j' V- R6 I6 C( S
  153.     {: g0 `0 Z9 |9 t* w( {) v3 n5 O  c
  154.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
    ( Y% v% n6 x+ t7 d" P: \; Q
  155.             &pclsObj, &uReturn);
    3 Q* x# H+ R- X4 }. _( T+ c# v2 |
  156. - S9 S) r  I4 G# ~+ C2 j4 p
  157.         if(0 == uReturn)8 x. p' `0 ~# ?8 Q) D, L4 k0 m
  158.         {( ~3 t1 \3 X' [- B# e7 M$ [# {* Y9 A
  159.             break;5 n+ w5 d9 p/ h  ?- |6 H$ `
  160.         }# d" Q5 i& ]6 O: |) ]" K8 c
  161. ) D7 [; t# v# ]/ J& ?- v. m, t
  162.         VARIANT vtProp;5 @# d" a5 ]" d* v
  163.         VariantInit(&vtProp);
    ' ]6 D, s, W4 s6 I
  164.         hr = pclsObj->Get(L"PNPDeviceID", 0, &vtProp, 0, 0);8 b0 k2 i% d2 V
  165.     strDisk=_com_util::ConvertBSTRToString(vtProp.bstrVal);
    " \. P9 G' `3 u4 g+ |/ S) H
  166.     }
    . G7 v$ I/ o7 \+ x7 h" ~/ E

  167. ( q4 u8 M7 X1 X- P
  168.     pSvc->Release();( I! \/ T) t  i1 ?! _
  169.     pLoc->Release();) P1 ]0 d/ Y* c& {/ e
  170.     pEnumerator->Release();
    3 `7 v* K" g7 a8 T% }
  171.     pclsObj->Release();5 Z+ \6 Z( J/ \
  172.     CoUninitialize();
    : b) s) f: g6 V" x% s
  173. ! L2 `! A/ S$ Q1 G: L5 r
  174.     return 0;   3 n$ m5 L, c" u% a- Q" c4 p
  175. }8 r& T  p# k) Z, J1 x: Y, G) k
复制代码
 楼主| 发表于 2010-10-11 19:21:05 | 显示全部楼层
本文代码经ccrun(老妖)在Win2k下试验成功.
) C, V5 _5 i5 l( _; B6 O5 X$ B
0 e4 c( q0 q9 v9 O' u8 i#include <WinIOCtl.h>- F; x' y- |5 R2 ^5 y7 d
#include <stdio.h>
0 C8 U& V# e$ s1 ~5 `) c
6 @% {4 K- ^5 r9 o) `0 ]7 ^#pragma inline6 R: j# @: `# v; K7 I  I
//---------------------------------------------------------------------------; Q* R( ]  g* g& a6 `8 [
// IDE NT/2000/XP专用变量
  K, ~; U( C* Z% D#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS9 m: K3 m; l3 G) \$ D7 |
#define DFP_GET_VERSION         SMART_GET_VERSION8 k" c: s7 z0 u3 e9 _$ T) m2 e
#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND+ s4 \; i: }, ]+ Y
#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA) a1 c# s0 _; M/ Q# n1 N
9 b5 }. N- z. m1 ~$ W
const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令7 T2 @1 N. y( \9 i4 Z% t4 @1 }" ^
const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
: G+ c) t4 O4 j8 n; V( S0 s8 P% g% Z' n' z
const int MAX_IDE_DRIVES = 4;" u/ @/ V8 E+ D* V$ V# Q1 j+ P

5 Z0 _" k$ K4 e4 q& s4 }1 J// SCSI专用变量
) f8 Y0 H' Z5 t' z. wconst DWORD FILE_DEVICE_SCSI             = 0x0000001B;
* q: e7 b; p+ T6 e% w( gconst DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
  B5 n8 ^! W" W8 S9 Q1 J2 e" p0 I! Y2 oconst DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition( Y* e6 i6 {6 z
const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
' D0 \' q, f9 e( Y! }. j* F, O5 |/ G* i. H+ X: ^. i9 {% p
typedef struct _SRB_IO_CONTROL4 _. o: {+ K; H: c* v
{, d7 y$ f1 P/ Z; F& u3 p
    ULONG HeaderLength;8 g- n$ j4 _, T
    UCHAR Signature[8];( V5 I0 s1 s% m# }8 Y0 M
    ULONG Timeout;
% K2 }4 L+ \7 \: ~% Q: L: n9 q    ULONG ControlCode;
8 \& U9 K5 f+ T$ Z7 ]: e& r6 P6 H    ULONG ReturnCode;8 k/ u) e1 Y: V, I4 p4 @& [* q; i
    ULONG Length;
! v; a: i1 e+ i- z* n! \}SRB_IO_CONTROL, *PSRB_IO_CONTROL;
, ?* K1 S# L, u) y7 g( q" k  r: P4 h5 w0 T/ J/ p0 d
// 读取的主函数) j; [8 H' E% K1 ]4 _, l
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
: ]/ T$ M( n% Y, X5 @$ j
* C: W. B. ]2 V5 `7 m// 辅助函数; B7 o  ]$ `; g% l4 y
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);/ p8 d( k( H8 Z# j5 I3 M& {
// NT/2000/XP函数
) c# ~; \- z' {- \3 n3 bvoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
! j. W4 Y  |& C! K; P0 `bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,- T+ S( l7 `) D' l: }0 ]1 y
        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,3 l4 T8 T. {" l
        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
1 ^0 _. X" w( @- L; N3 b) \// Windows 9X函数" m# b8 j7 I2 ^# h( v" X
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);- c3 E1 ^5 M2 Z- F# G! P; p/ U
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,% m6 p0 A5 C! e9 F. m# B
        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);& n' A: P0 w; o" Z" t5 z% v

3 o1 w& d1 u  Q0 K/ \  }' ~% Z// SCSI读取函数(for NT/2000/XP)2 b5 _4 v" {5 q6 K
String __fastcall ReadIDEDriveAsScsiDriveOnNT();
  v6 c7 T$ Q3 p- c* |8 S//---------------------------------------------------------------------------2 y; B# u+ k4 m
// ReadPhysicalDrive
- D1 c" O8 \0 ~3 @void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)# U4 C8 o+ }. j) z7 f, ?
{
& h: I1 W$ |8 b) l7 _! I: @! V    switch(Win32Platform)
4 ]+ i5 u! y6 e, F+ @    {
: {  N! C( L% W# n3 Z        case VER_PLATFORM_WIN32_WINDOWS:8 R1 u) A' s! J1 H) T( U7 L
            ReadPhysicalDriveOnW9X(pSerList, pModeList);6 E  P1 F! t) l6 x* X+ t; S
            break;
! L4 H, m" R# S" I0 f8 h2 E' W5 L% U7 J/ M        case VER_PLATFORM_WIN32_NT:
" [9 m" @9 H- D            ReadPhysicalDriveOnNT(pSerList, pModeList);
) B8 q9 F1 ~% j            break;+ l, z" w- {) Z/ [/ s
        default:
) F5 Y( b" z' U8 \            break;; L3 ]: M$ @3 ~" x. F0 W! e% I
    }7 e; l  m, u8 X; J8 q! C# K  t$ ~
}
/ v& I+ ?7 C$ Y0 f& r2 p8 m# D. u2 t/ g//---------------------------------------------------------------------------
/ W7 \+ }1 g7 v6 D/ d8 i// ConvertToString
) S$ U% a6 X: \+ [: a9 L7 Nchar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)+ V; D0 p' ^# V6 k
{
' `" ]. w4 O' O    static char szResBuf[1024];
" {& F; p) S+ C2 }! y: S    int nIndex = 0;
& G1 P+ C2 f, Z$ s    int nPosition = 0;
. x6 N$ N! ^" n; v) \; n' y+ E1 G4 k% D& Y, M
    // Each integer has two characters stored in it backwards
7 q: C: k( N( y$ E% j' H    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
, F; P* q- l5 Q8 a0 }    {
; ]) }/ A. e  G: @, m& E: q+ u        // Get high BYTE for 1st character! R- g- Z- h! O
        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);% z/ D+ L6 H0 h$ ^5 L
        nPosition++;
% E2 y/ `9 o/ G$ `
, Z8 v' A5 [. \/ v) Z4 ^3 v! z4 ?        // Get low BYTE for 2nd character
$ `$ S5 t% A, P$ q        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);" r7 ?" G0 a3 N0 O: R) B
        nPosition++;
/ ?! E7 p9 S2 e, z% N4 I) Y    }
' P8 q0 Y/ J# F( {
/ Q! C/ {8 {2 U  R/ P% V5 L    // End the string3 p6 u) s7 A0 y' @
    szResBuf[nPosition] = '\0';2 e/ F8 _# K! L; V0 u8 d
1 L2 f: j$ ^/ ~) y
    // Cut off the trailing blanks! I; N, c3 t# M% n
    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
' c1 e( Z) q- L7 W' b- i% s- z& L        szResBuf[nIndex] = '\0';
8 l4 n, v5 a( N; u
. A, w) m& W: \# C: z    return szResBuf;$ D# y; f5 f, b9 U% _
}5 \# d% v1 b" a- h# O
//---------------------------------------------------------------------------, p4 r* w9 I) \2 C' o# `2 ?
// Winndows NT4/2000/XP 代码' e5 ?% r: F# m: K: r2 A
//---------------------------------------------------------------------------1 T: K! _- f5 ]
// ReadPhysicalDriveOnNT+ \8 r1 [6 F. ?( V5 X# _3 p- G
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
9 n7 H8 k2 |# q) |  b- ?{. d5 n; C6 q+ d7 Z
    // 输出参数
' R( L8 r( ?, k# J    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
5 l8 l: L4 I* K2 i4 i8 o) P  O7 w1 T; b
    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)7 b3 I5 L3 P+ |  p' N
    {# e, e: @& V) }( f. w$ c8 e" X
        HANDLE hPhysicalDriveIOCTL;
8 D( Z9 m8 Y! h3 I/ ^: [- m) x) g4 H        char szDriveName[32];  ~7 s8 P/ U2 X' r9 _

9 Q" i8 ^5 v3 l" C) g; ^        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
( f" i4 Q9 @; {# \; c! L" l2 y        hPhysicalDriveIOCTL = CreateFile(szDriveName,+ M' g6 w! B5 g  {
                        GENERIC_READ | GENERIC_WRITE,
" J7 p7 q5 t  w                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
) J7 u8 {% q, w0 T) [! }                        OPEN_EXISTING, 0, NULL);/ b7 g! {6 q, N" a
3 M4 U! T6 Q* B3 x5 P" O7 @
        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)2 ]6 X5 s- j# _% [5 E: i: r
        {
  f. z3 G  {# a/ T  u            DWORD dwBytesReturned = 0;
) N( C6 q4 g% o  e$ `. c% X, H            GETVERSIONOUTPARAMS gvopVersionParams;; q0 @% _0 V6 J
. A6 I( p- t3 {8 Z# M) t
            // Get the version, etc of PhysicalDrive IOCTL% p1 G6 }: |, Q  ]2 `0 j
            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
' c2 K6 p" i7 {+ O
0 u$ s9 ]4 V9 t& u1 b) v            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
; U: L9 g( m9 P7 v( k                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
6 ?8 A, y$ h6 f                    &dwBytesReturned, NULL))
/ v& L1 S. U* Z            {
0 c8 f, R8 n  |( B! V                continue;
. l8 Z# b9 R+ d( }% \            }
* F! ~" h/ C9 M! ]! Q7 X" i3 b$ u' \! J5 ]% s" e2 O: ^8 U! u. H
            if(gvopVersionParams.bIDEDeviceMap > 0)% X% G2 F0 @2 B; ~5 f! G. V: }( V
            {: j$ E; d9 j# G% z
                // IDE or ATAPI IDENTIFY cmd
: \4 `7 J! b) d* a2 S* P8 R( d4 Y: E' L                BYTE btIDCmd = 0;
# o- e% `/ F2 H5 z0 I0 d                SENDCMDINPARAMS InParams;' A2 K8 c1 _% U3 D! y3 k; s3 W
                // Now, get the ID sector for all IDE devices in the system.
/ y. B) q& F. K- }# {% }                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
# V: K9 r/ w6 v                // otherwise use the IDE_ATA_IDENTIFY command
3 Z* ~. {5 f/ L3 `' x9 F& {                // 具体所得结果请参考头文件中的说明
( K4 Y& ]/ l6 s2 u- [: P+ x) ~* J                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?/ U$ a2 T2 J* T& \, G
                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;$ F: Y/ j, A  u* I2 \
                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
* ^- }3 i! \. p+ O, D7 m                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
3 m) d6 v  T/ e" m" H& k" J7 m8 z' L3 q, R# b: T* @( g! h$ h
                if(DoIdentify(hPhysicalDriveIOCTL,
& E  [( G/ S2 g0 [* j# W6 ~                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
; B* Y( k5 C. f                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
! }+ S% N, `" o# i                {5 t& S$ n6 E" n! B
                    DWORD dwDiskData[256];
2 r' c8 f) p3 ~* M3 }6 d, X. V. s                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
9 {6 ^! A8 t9 {                    char szSerialNumber[21];% e2 M5 ]! g. M! e
                    char szModelNumber[41];9 m: ^# B( n, B" S( F% ]. R6 V
8 ?& V* ~8 B  N" B* X9 g
                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
& `7 R8 V$ P0 C- A& m                    for(int i=0; i < 256; i++)
6 z' K" a; H1 N+ [                        dwDiskData[i] = pIDSector[i];
, z( F4 f' `8 i, L                    // 取系列号
1 B: w  g* t" m* V                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));8 z! }: U, O( Z& U! [6 p
                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
' J/ j6 s* Y' @0 G4 l6 Q, V
) d0 m# Q9 D4 ]" J- I# V" T                    // 取模型号
) g7 {5 B7 g4 v+ j  L3 r* i                    ZeroMemory(szModelNumber, sizeof(szModelNumber));/ |  q( I. N& b) P8 N# @
                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
$ A5 e( g7 r3 W! @& M9 t* k# X* X  W  f# }5 M& t
                    pSerList->Add(szSerialNumber);
1 ?: \  D* |7 R' V1 e4 O5 A3 d                    pModeList->Add(szModelNumber);, X. t( s% o) v4 X$ N( w! q4 J
                }, O- M6 ~1 r$ l8 @4 C
            }
* D4 i) ]4 ]" J5 T1 N( v  {            CloseHandle (hPhysicalDriveIOCTL);+ W8 c$ |; M9 d1 |
        }' P. m, M- h) d* e( E0 G# U
    }1 m/ _8 X' f, F) X, r7 t
}8 A2 }' o6 ?, Y' A  |) [: P
//---------------------------------------------------------------------------! I2 _2 x, F- ~- V; |  z: P/ d
// DoIdentify
$ {# E0 \+ a2 {, w/ jbool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
) o  S! P/ S! C% ]( W9 y# ?              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,9 S6 z: Y& t3 o" d' ^
              PDWORD pdwBytesReturned)
* y$ m  s" K: D" H{
1 d3 O" e' g( p' `, f    // Set up data structures for IDENTIFY command.% k; r& C5 g0 N
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;# f7 I( S, K. C! W# I+ t4 E0 [
    pSCIP->irDriveRegs.bFeaturesReg = 0;
1 l: P6 _0 s3 K4 P6 j. m5 K    pSCIP->irDriveRegs.bSectorCountReg  = 1;
, B4 K* P4 p/ A+ q% s    pSCIP->irDriveRegs.bSectorNumberReg = 1;. Z8 r: I1 g+ Y8 X( E% |& h
    pSCIP->irDriveRegs.bCylLowReg  = 0;
* J" w* i5 z: K    pSCIP->irDriveRegs.bCylHighReg = 0;
; ^0 [/ h2 m" L. O0 y5 Z
$ S& I* M  ^" r& y) T    // Compute the drive number.(主盘和从盘所对应的值是不一样的)) n! K4 c/ u. m6 X2 A
    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;$ k8 n0 E  b; L& x* M+ t+ n8 k

" ]6 {- `/ i1 Q/ \8 c4 E0 @    // The command can either be IDE identify or ATAPI identify.
0 b! L( J' T. U9 s0 d    pSCIP->irDriveRegs.bCommandReg = btIDCmd;% Z6 X: U$ b0 f9 r
    pSCIP->bDriveNumber = btDriveNum;
0 O1 G! E' Z- C% x! N# e; S    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;# J' d1 z; P, N5 ~6 \9 J: v

3 X" j' d% A% x# B( R    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,- S$ p0 o2 N* _. y& U/ ?
           (LPVOID)pSCIP,4 r! f5 z/ e7 O  u# X! p! |
           sizeof(SENDCMDINPARAMS) - 1,
' L- h, g5 e2 s" k5 S, V2 g           (LPVOID)pSCOP,
0 \# @% y' J5 `: `/ K- t4 [) @           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,: ^. b- M1 ]; R
           pdwBytesReturned, NULL);
0 V6 b& ?( _' i( A}
! a. {1 l  v/ t4 q//---------------------------------------------------------------------------! Q7 Z" ^, U) x: ?* R! R1 j
// Windows 95/98/ME 代码
5 X  t6 [0 W  D# }//---------------------------------------------------------------------------6 j$ w  v: w8 P% g$ m: ]3 R$ G
// ReadPhysicalDriveOnW9X( l: a& l8 M5 M& g
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)( Z" l+ J4 b5 @; ]+ [8 w
{
  s7 R3 k  h& |4 _    WORD wOutData[256];3 ?$ F# h% c8 e$ ]/ x  k' s8 p
    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
  H- H# t  p' }$ ~3 O" F) h: U4 q4 D- d0 P/ I
    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
5 W% c' }3 Q1 ?* N. M8 I0 F+ U    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以1 x& p3 ^  ^' W- Z1 F
    // 避免蓝屏的出现。(期待高人能指出原因)
8 b  \7 o8 J1 z5 m, x: u; [# r    for(int nDrive = 0; nDrive < 8; nDrive++)2 T5 p; H2 |7 A# g# Z& X/ r+ g; ?! l8 K
    {- E2 F# n' ]& t! i- T$ z+ K
        WORD dwBaseAddress;
9 a0 q, }2 L1 n. }) h7 B        BYTE btMasterSlave;         // Master Or Slave
+ V( U! C- t. N; b0 k        bool bIsIDEExist;5 _3 O; p' e- b8 z: {
        bool IsDiskExist;
; u$ s, s* ^/ ]: M7 \7 j: n! i
0 e$ m! X3 o' H        switch(nDrive / 2)! ?9 e0 Q" N; V
        {
) Y6 i0 l( p3 N. \/ g4 ]            case 0: dwBaseAddress = 0x01F0; break;
% V9 b* e$ f% }& D. A            case 1: dwBaseAddress = 0x0170; break;
, g. B  t1 h3 x, \5 L            case 2: dwBaseAddress = 0x01E8; break;" c# F' `& W" d% g/ D9 t, Y
            case 3: dwBaseAddress = 0x0168; break;3 ~% q7 _! |8 F2 m, ~
        }2 u: [* g% f* E  B% N1 r4 Q1 J1 I
8 J9 x' Z' U& t8 V
        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
& Y# a: q4 A: e6 F, V6 S7 V9 r' M8 o) v$ C
        // 进入Ring0
5 r. \4 i* X0 C        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
, P8 o$ L  a: ]3 I- Z$ I" o                bIsIDEExist, IsDiskExist, wOutData);
/ M9 G) m4 \% k. E/ g6 O    }% d% C' Q) M' F/ C
* @2 K; |& Z. S  ^" {( p" D+ T
    // 开始读取
3 u9 ~( e( N0 X1 m3 R    for(int nDrive = 0; nDrive < 8; nDrive++)! k- S: Q. i/ `9 l
    {9 z1 S3 W% ~+ O8 Y6 r$ y
        WORD dwBaseAddress;# a" S  A. E+ L# z: ?' {
        BYTE btMasterSlave;         // Master Or Slave4 z$ S! g( X8 ~6 O" _
        bool bIsIDEExist;
! g' T) F0 n, T- O        bool bIsDiskExist;  N0 C$ U+ ?, u9 z$ [' q- t# G# E
        switch(nDrive / 2)
/ K! e9 \! B/ z+ D" t: j8 p5 X* F6 b        {! H$ o7 `6 `$ a) }4 i7 Z, L9 Y" B
            case 0: dwBaseAddress = 0x01F0; break;7 h& e" x7 S& f$ {+ k. W2 q4 i) ^
            case 1: dwBaseAddress = 0x0170; break;
- X" `1 U5 z) o8 X. W+ L4 P            case 2: dwBaseAddress = 0x01E8; break;' G& }: x1 p: b7 y  n
            case 3: dwBaseAddress = 0x0168; break;8 t1 d, S5 ~- ^" z5 G% ?$ F& C
        }
  w8 f2 _6 I! i" z3 p
' t8 G  w# X" }/ Z: F: ?        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
& t! p7 E4 n- G. e) U! O
$ S8 G8 m- L% N4 b: Z* `: [        // 进入Ring0
. n( @- e. Z) R        bIsIDEExist  = false;8 w8 N" k/ l  m5 J( t
        bIsDiskExist = false;
6 M% V$ i, v* x' v        ZeroMemory(wOutData, sizeof(wOutData));  U4 h/ {+ l9 h  Q3 s" m

  N6 i7 b5 W; E$ M        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,; ^- [# U1 l5 H% x0 T6 s
                bIsIDEExist, bIsDiskExist, wOutData);
2 i" h( F7 c5 B2 C2 P) h
( S! `' M  ]; N* n8 e9 h        if(bIsIDEExist && bIsDiskExist)$ N$ x" T) m9 |  u& z8 Q
        {
! v6 o1 g# Y( r1 T  S            DWORD dwDiskData[256];& ~" C8 q6 D% y' {1 |. x; r& j
            char  szSerialNumber[21];" }8 V- I4 M  c) s! R
            char  szModelNumber[41];; x7 N$ h, ?6 V1 F

! s# P6 @6 ^: W  @! ^/ c            for(int k=0; k < 256; k++)
7 X" w, p1 o# }3 z, C: z  o/ k6 U3 h                dwDiskData[k] = wOutData[k];1 b. m% D/ a& h: A

6 a1 A, E4 @; Y" W5 f- ?  W9 f2 {            // 取系列号2 m+ Y2 C0 R; d0 p  o* J) v
            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));2 A$ l; V" |  z
            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
* i5 @3 E* M/ m2 p7 z; [% y; Y1 h- Q8 Q6 ?9 K
            // 取模型号  ~& C$ B: }4 H: \9 a0 @  U  f* E
            ZeroMemory(szModelNumber, sizeof(szModelNumber));% B/ }7 d2 g2 [1 b/ p* o2 c
            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
  v) b+ E( v1 w. S1 v' m+ V' K' m; H( O
            pSerList->Add(szSerialNumber);
! Q) s; H+ M: @9 e$ |) {            pModeList->Add(szModelNumber);
7 T5 P. \  s& z3 H        }
1 `+ ]4 T: d6 G/ X    }+ Z4 U% w4 n6 u" X8 O, ]1 V
    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);' t+ X; n' Z+ Q$ h
}
/ G" X& P2 Z# X; v//---------------------------------------------------------------------------
' @- G& j5 k" y// 为防止不负责任的转载者,在此注明原出处信息,请见谅。
& u7 X2 ?/ G& d" X/ Y// 资料收集整理:ccrun(老妖),欢迎光临C++Builder研究: http://www.ccrun.com
( r4 S* ^* H$ {//---------------------------------------------------------------------------
+ J: Y5 z0 O3 y4 W7 _( p" g2 l: C  d// ReadPhysicalDriveOnW9X_Ring0()  J0 J5 b2 j" r: E0 f* r/ ]
//
7 o0 j, ~+ Q) h4 i8 E// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h! ^; T5 m; _+ W. M3 o
// btMasterSlave = Master(0xA0) Or Slave(0xB0)( C+ I" _. L- n6 ]# I
//---------------------------------------------------------------------------) L7 H% d5 l  s# i; w
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
% p5 R$ J$ D' Y" o9 ~        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
% ^& a! L$ g# q1 X% A  `/ V4 g{
! N; x$ t/ i/ X: s* p1 |    BYTE  btIDTR1[6];
$ ]7 ^9 O' |% I* j9 D- |( n0 j5 Z    DWORD dwOldExceptionHook;9 g/ a8 u% P  f, J" `* i
    const int nHookExceptionNo = 5;
, T1 }6 U0 h0 ^: _; i: Y* D, J( S1 @+ X: {5 I  z+ w
    BYTE  btIsIDEExist = 0;
3 ^. M* [; P$ e: ^  ~( N) c    BYTE  btIsDiskExist = 0;; T2 n+ l7 z+ ?! @5 d
    WORD  wOutDataBuf[256];' Z8 I9 F" b9 W8 X; z" U

1 Y1 V8 I5 U+ E/ Z2 N+ r, N- B9 K1 M    BYTE  btIsFirst = (BYTE)bIsFirst;# ~' s) b3 Z0 p( Q4 G% |
' r8 J" Z$ e: W; s
    const BYTE btBit00 = 0x01;
1 d# c: O9 P7 _& U3 w' _    // const BYTE btBit02 = 0x04;
) I- @' H: C) u7 j    const BYTE btBit06 = 0x40;
, G9 V. U& |" Z, o- c    const BYTE btBit07 = 0x80;- J5 \5 J- C+ _0 J0 N
    // const BYTE btERR  = btBit00;
, z7 [* a: j- p) n2 A' J) U    const BYTE btBusy = btBit07;( w& z2 X9 v* [& ~/ ^
    const BYTE btAtaCmd   = 0xEC;; T7 h, |+ e7 R, v9 o
    const BYTE btAtapiCmd = 0xA1;
4 O( z) d9 @: m0 U3 ]$ h. f3 P" e; ]
    __asm% ~8 g' K4 }; o  o# a  K) K  z
    {
! B3 i. q9 Q' C4 @5 A        // 必须先执行这条语句
& j# x' `) G4 X9 v4 Z9 W        JMP EnterRing0
% U' Q- {, ]  ]1 o$ L! k3 [. B8 }2 T2 i3 N# c* J
        // 定义过程
  S2 t' H1 i; n        // 等待IDE设备直到其不为忙为止
# z. k9 Q. U  P5 O. s* q5 q        WaitWhileBusy proc5 E/ I# W7 ~9 t- e; W7 A  `

0 E& F7 w5 j+ f8 I9 D7 g        MOV  EBX, 100000
0 m1 i" e+ o' V( Z  }        MOV  DX, dwBaseAddress
" ~( D7 A/ @% B% L        ADD  DX, 70 K+ y4 j0 a' k9 q" e2 y* O' G
# ^6 q0 c6 O2 T4 e9 J
        LoopWhileBusy:. v9 W4 D# p" }8 O' E5 O1 n
* `/ f* b; E# e! ]2 r
        DEC  EBX- b  {4 D& U2 w# x
        CMP  EBX, 0$ g+ _! U' `. T) [; y& P% F
        JZ   Timeout& o/ ]' @8 y' k5 }  }
        in   AL, DX$ V( z6 h; |- e& H# C
        TEST AL, btBusy& R1 ^3 h6 S; W  r
        JNZ  LoopWhileBusy
! Z" y1 w. \+ |! D5 h& b        JMP  DriveReady& |6 s" a) m: L

( I: c+ I$ y  O- `. F- z, S        // 超时,直接退出
$ r/ p/ b6 T+ ?. H' N        Timeout:6 o: b: Y* [$ `  v: S
        JMP  LeaveRing00 i+ H5 r% ^9 r& |2 j8 z7 w+ D
        DriveReady:4 k$ v: ~6 Z+ s& c
        RET# j7 @* w: h6 m8 W: B
        ENDP   // End of WaitWhileBusy Procedure) M' S7 B! T5 y
" u; ?: ?& }* ?% x8 c
        // 设置主盘和从盘标志
0 G; ]2 X7 {$ L: J* z" c        SelectDevice proc7 o* K$ `9 _2 L/ T/ ?2 U( D
4 Z- J8 ~0 Y( B! n4 d' _. ?, m2 K
        MOV  DX, dwBaseAddress& X9 B6 h, K  m4 E
        ADD  DX, 60 h! v8 }4 j5 _6 m- y* ~
        MOV  AL, btMasterSlave2 s: O! h$ }& x1 m$ ~; T3 H# [

" j% G- k/ ~4 V* X        out  DX, AL9 {$ o! y7 u7 g; ?4 c
        RET
+ x# s( X8 `- \* C4 J2 m4 l1 c! u3 ^5 t* v; f. ~$ Y3 |
        ENDP  // End of SelectDevice Procedure1 ^- M4 D) a: d& t& P& `: J
3 K. P9 T7 M& E( `0 A& l
        // 向IDE设备发送存取指令' O% M1 ]% z. y# C  D
        SendCmd proc) A6 C; o" N1 F/ r6 n$ ]
9 s+ R* {* S1 k7 \/ x+ ^
        MOV DX, dwBaseAddress, j! ^: F2 [- e- |0 r! f' i2 K
        ADD DX, 7& U. M1 n' ?6 Q9 V! n
        MOV AL, BL // BL是主从盘标识,在过程外设置( ]+ j7 T2 E* L7 Z, g
        out DX, AL
6 X3 Y- i+ p* F; Z        RET1 J3 p3 C5 q2 _$ B3 Z
        ENDP  // End of SendCmd Procedure
' i' D% {2 ?! E  a* ^# ^$ Z' z1 r* h% W
        // Ring0代码  G# E5 X5 p8 F! _1 y) }
        Ring0Proc:; S/ v) ~8 d) ]& \4 P
        PUSHAD  q' J6 p" l- c7 T9 J( c
        // 查询IDE设备是否存在
- V, H" g2 s; @        MOV DX, dwBaseAddress
+ [7 i) e3 D8 I2 k        ADD DX, 7
+ a; p* U# U5 W' j4 H" ]        in  AL,DX9 v$ O& H% w; O0 w8 A& V3 \9 E

, k5 G) b" Q# t! T( C        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
8 @  g! i7 i9 }, @* J- [4 x        CMP AL,0xFF
2 e' j, `* ?$ ?" d% J        JZ  LeaveRing0, T- {- ]) Z) J
        CMP AL, 0x7F+ ~2 \' p& w) X5 G% F" h2 V
        JZ  LeaveRing0
/ ~' \& ^2 Z& I0 l" e: `" A6 Q# D% d  y
        // 设置IDE设备存在标志' g3 T& k" c. F
        MOV btIsIDEExist, 1/ T8 Q( d: {8 l; Z( V! d) X8 D4 h
4 u7 f' O' b* \, ^  e: H
        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
# y. m7 |- }2 A7 Y6 P; E        CALL WaitWhileBusy
  i# F; S) e% Q* l2 _        CALL SelectDevice
4 {# Z7 V2 v) D( Q
5 @/ M2 W9 ?  C        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
6 g3 i+ j5 U+ g7 g- b5 J$ n        CMP  btIsFirst, 1
% o& d' o3 `. o        JZ   LeaveRing01 i' _- v0 w" P6 ?$ H' K4 ^; X
4 W1 _' @1 X: a0 F4 `
        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???( c9 J1 F1 f  A2 d8 g; I+ |0 @
        CALL WaitWhileBusy) h, A# o( e% ?

; K0 h; I; h$ w0 u5 D% w        // AL的值等于cBit06时,不存在驱动器,直接返回
, y, Y% u" X. Z7 H5 f) F5 `        TEST AL, btBit06
2 K+ _1 H2 c0 U7 v! A, N( J0 i        JZ   LeaveRing0
7 G7 t7 r: n' V: ]) e/ b: f+ R2 s+ e# d: T& h* K9 ]+ i% ]! t( j2 [
        // 设置驱动器存在标志
9 _' M. B$ J. B3 |0 T+ V# h        MOV  btIsDiskExist, 1+ o% J+ I# Y6 [9 B

& j! v7 S  b' J) U3 J; J! _        // 发送存取端口命令
3 j, W5 H5 |6 p: R  G. R6 X        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
1 G; R& a. Y+ A5 E        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
" d9 d6 {- M: t, \+ l$ E. y: v: o+ S        CALL WaitWhileBusy
9 \! P/ S, x5 P% I; X        CALL SelectDevice    // 设置主从盘标识
, |/ `* D+ k, e; x$ ]" b% ]        MOV  BL, btAtaCmd      // 发送读取命令
! N. Z) `4 H, S5 ~4 v+ P        CALL SendCmd
1 L, N0 F3 {" O% t/ J5 Z        CALL WaitWhileBusy& Y' {3 L4 @$ c

% a, `0 k! p$ s) f        // 检查是否出错8 G+ A1 ]0 a* Y5 N" r/ R
        MOV  DX, dwBaseAddress- g. E7 d: ~: q) c! M, A* D+ k
        ADD  DX, 7
. m5 j  D- I. p0 Q' Y6 X1 z& K5 j7 l# K- h
        in   AL, DX9 [7 p2 F: s* N; i3 d; ?% z0 v, h

# x5 L5 p1 x, {) T: J3 S  ~0 I1 p% a/ K1 Z        TEST AL, btBit00
& i1 C1 G1 v; l/ G        JZ   RetrieveInfo   // 没有错误时则读数据' _2 V9 l6 ?. O% D+ D( p
) g+ ^; b+ H- Y+ @
        // 如果出错,则进一步尝试使用ATAPI设备命令: w& S6 o( E+ ?8 i7 b" f2 _' U
        CALL WaitWhileBusy) `* z: \6 k3 P8 D5 j
        CALL SelectDevice  x9 G" R$ \# l- d+ {2 m- l/ [# Z4 Z
        MOV  BL, btAtapiCmd' F& l( \# W" W
        CALL SendCmd: F# f6 h& m) Q, T
        CALL WaitWhileBusy1 {7 Z- m+ ^* c. z& n

5 p2 @% Y  {2 J        // 检查是否还出错/ |) H9 m5 {1 q, L  N' _1 ?
        MOV  DX, dwBaseAddress
1 q% b4 Q9 K) z1 [3 c        ADD  DX, 7
: T/ y4 @& Z1 L        in   AL, DX
7 h; I; n6 P7 a$ R% m& z9 g        TEST AL, btBit00
1 S8 Y8 S) y0 v        JZ   RetrieveInfo   // 没有错误时则读数据
' {# A5 |3 s" Q" E- \8 r# M4 U: A        JMP  LeaveRing0     // 如果还是出错,直接返回+ J% L; C4 d! S. a* p4 F4 X' _8 L
- D2 b  @5 t( D6 z7 M
        // 读取数据
( ^8 i7 @* e3 y% y3 W$ S" A        RetrieveInfo:# \$ r  p$ e6 W: p
+ [0 j) `) e7 o# c0 Z6 e
        LEA  EDI, wOutDataBuf
2 Q' I4 F/ o3 J& n) l1 q        MOV  ECX, 256/ ?2 D! p& T) ~& ]5 Z  h. F
        MOV  DX, dwBaseAddress, d' Y8 [5 Y6 @: [, \3 N8 b
        CLD
# _9 |9 w+ z  q/ c2 z
2 A5 u% B5 O: z! A8 ^& x        REP  INSW
! G3 C$ x; J& I7 Y2 U: \% e# O5 s7 \" k4 O- D
        // 退出Ring0代码
5 K8 \% @" D" G  I' J! e        LeaveRing0:; O6 h5 v1 O: C/ T% R* ?3 t( X
; M+ W1 m# c! ?( A0 r3 e
        POPAD( s& ^  @+ k0 ]
        IRETD
- ^! f/ L  D, m. k# m/ a3 H. t4 Q5 F, N6 y8 a- M6 R
        // 激活Ring0代码) Y* G/ [. r8 o  U8 m
        EnterRing0:
" X4 ]9 ~* A, N* S: r$ i; N; y( L: A
  e6 O2 a& D" j        // 修改中断门
- g9 C0 v% S; X; x5 q        SIDT FWORD PTR btIDTR1
2 A# O+ D  l3 x7 L        MOV EAX, DWORD PTR btIDTR1 + 02h  C) c5 E% N% d% h6 W& }
        ADD EAX, nHookExceptionNo * 08h + 04h3 Q/ m1 N! a% l+ I, W8 [  I0 k" F" s
        CLI& c- A. g! b8 X% D2 P* r1 @2 M

6 e7 X0 e  {/ x" X6 E. c        // 保存原异常处理例程入口
/ ~1 A. Z& A- s* Z, O0 F        MOV ECX, DWORD PTR [EAX]
* f0 Q; `7 b7 N: w* @. k* ~- A        MOV CX, WORD PTR [EAX-04h], E" h! X- w  ~0 o. l
        MOV dwOldExceptionHook, ECX
" _, N6 h# w/ L5 Z( h: j% l) P5 \! `1 N# b
        // 指定新入口
8 R/ S+ L7 ]" H        LEA EBX, Ring0Proc
+ G" N( J. g3 Z' B7 l, L        MOV WORD PTR [EAX-04h],BX
4 M  V1 D' J7 }# u        SHR EBX, 10h
# `' C' F2 X& E+ O  p6 c' v) b# K        MOV WORD PTR[EAX+02h], BX5 Z3 i0 G( g$ e( G# N9 b
1 E% _+ J, ^7 o# J2 q" u
        // 激活Ring0代码
/ ~- G7 A' t; L0 x        INT nHookExceptionNo
5 N' ?( z3 l7 _- w1 a) q1 l
; E1 g, v. \2 E% C        // 复原入口
; n3 i1 Q0 ^  v$ k: F' Z* P# a        MOV ECX,dwOldExceptionHook
3 f9 L# C' i$ N        MOV WORD PTR[EAX-04h], CX
3 D8 d* Q, I2 i) x  M7 g        SHR ECX,10h
2 {8 m& H  g9 W+ B! ^6 p        MOV WORD PTR[EAX+02h], CX
" ~9 T/ \& e. N4 o1 V! {+ |        STI. [( d9 r) C; y8 J4 ]/ N
    }3 @6 {. j( F% ^4 J3 u) M2 Y: a
    if(!bIsFirst)
' h1 V( k) _, q% w% K    {+ _) l3 S  S6 n% _& U9 E8 y
        bIsIDEExist  = (bool)btIsIDEExist;8 A# `- B+ r, ?1 [/ Q+ [
        bIsDiskExist = (bool)btIsDiskExist;
0 N' o: u9 F! k* g4 B        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));4 k4 @- [; d$ n
    }0 r5 R5 Q: A' J, ^; q& a" c1 _
}# [' O( q% X! I) B- M' @
//---------------------------------------------------------------------------
$ g: M# r1 d/ _// 调用方法:
9 n7 `# D+ k5 l9 ^void __fastcall TForm1::Button1Click(TObject *Sender)
) z4 O1 S4 h6 L- X; P3 S# H- v6 h{
2 D: v4 a! G# C: q. }% j    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);9 [, f: L3 [0 `- ]( k
}
$ g# _8 i( x. `0 ?6 a$ I4 t
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-8-13 20:18 , Processed in 0.021370 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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