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

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

[复制链接]
发表于 2008-1-6 19:59:06 | 显示全部楼层 |阅读模式
代码框架,你所要做的仅是修改WQL语句,具体可看MSDN。以下代码为简介起见,一次返回所有的CPUID或硬盘厂商系列号
5 _) A' O1 q7 U
  1. 5 D$ R5 ?! C6 W
  2. #include "StdAfx.h"
    ! _2 G& a2 h6 e4 Q
  3. #include ".\puiddisk.h"
    . D- ~" M2 |$ \+ C
  4. #define _WIN32_DCOM% x7 i1 S# d9 D4 D8 v4 C& B: w
  5. #include <iostream>
    8 R9 X  D& V8 n) k3 X) n
  6. using namespace std;8 l8 s- `6 a/ s
  7. #include <comdef.h>
    6 h$ o7 q2 M* B! ~) Y6 u
  8. #include <Wbemidl.h>
    4 B& }: A6 X% a
  9. % M+ ?2 S! Z, S1 }2 ?2 y( R: j; R
  10. # pragma comment(lib, "wbemuuid.lib")
    ; W- f) t5 E) \* g& o% T, Z
  11. CpuIDDisk::CpuIDDisk(void)
    ; ~! V& W- N! q  x
  12. {* y) ?5 O8 N9 S3 w- Q( p
  13.     GetInfomation();
    0 d8 R$ C+ A1 q* i
  14. }( d( K' E9 N' w$ I

  15. , t6 ~1 U4 Q3 |
  16. CpuIDDisk::~CpuIDDisk(void). k, ]$ K+ {9 x+ w* {1 R4 `
  17. {
    5 ]5 D& R, @; K( F6 R& O
  18. }
    % o+ w+ J5 N5 |- d1 f+ u
  19. int CpuIDDisk::GetInfomation(void)' N  {: y$ ]1 l: ?9 A& s
  20. {6 R+ z. @# y4 H2 k) @
  21.     HRESULT hres;
    1 O5 x/ D1 X! s; D) t
  22.     //步骤1:不是必须的,COM只须也只能初始化一次) Y. g0 s5 a  V4 S, q& T, A, I9 f
  23.      hres =  CoInitializeEx(0, COINIT_MULTITHREADED );
    : E  L; Z- Y6 s2 W; c
  24.     if (FAILED(hres))5 H+ {7 J6 w0 v; y2 Q" o& R* o. r( |' ^
  25.     {. h2 D* {: o3 o; t
  26.         return 1; //初始化COM异常:注意,COM只须也只能初始化一次
    ' P: m( P9 n1 b- H( t( W
  27.     }
    ) l3 ~2 d, u) X! B5 _
  28.     //步骤2:不是必须的,COM只须也只能设置一次
    / m* Y- T1 y  \$ C8 [
  29.     //Set general COM security levels
    & |4 G4 U+ O. T9 }3 l, b
  30.     hres =  CoInitializeSecurity(/ P+ }6 W! \, ]7 B
  31.         NULL, + R6 Q0 b& v% G3 v& b
  32.         -1,                          // COM authentication4 f7 t. b' ?7 ^' v7 v/ Y: m' O
  33.         NULL,                        // Authentication services# y* \5 {9 r4 t/ \
  34.         NULL,                        // Reserved
    # [0 h; ], t4 d; O! y  b  q
  35.         RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication # n+ Q- K9 c: M
  36.         RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  ! ~! B1 _& \& n
  37.         NULL,                        // Authentication info
    * A2 E( F% p8 G6 p6 E
  38.         EOAC_NONE,                   // Additional capabilities
    7 q! G6 b$ r/ {6 c' z- `
  39.         NULL                         // Reserved5 j# x! l4 S( {
  40.         );
    # U$ T( }0 [3 g: O, i1 d1 a8 d7 p
  41.                      
    6 q, F' ?; ?3 l  U! F, i* u9 M% j" y
  42.     if (FAILED(hres))
    / d1 {; x) ^( Q
  43.     {
    ! {$ V, g( u: K2 D
  44.         CoUninitialize();  }% b. C( q  f9 F: f+ p- k
  45.         return 1;                    // Program has failed., s4 c) l1 w% N
  46.     }* q2 _* V. f5 L" T! k5 `4 c
  47.    
    ; K; {$ g$ j$ q, b2 b* K
  48.     //以上不是必须的,若已有“::COMInit();”,则要跳过
    # u: k. C0 n  ?
  49.     //步骤3: Obtain the initial locator to WMI
    ' ?* b# W- a" [9 b
  50.     IWbemLocator *pLoc = NULL;
    / p! O: u" p; h7 b
  51.     hres = CoCreateInstance(8 s2 I8 @# q) s. ]
  52.         CLSID_WbemLocator,             . \# u0 |: p4 F0 _7 y, }: a
  53.         0,
    7 O, ~9 s+ u+ B# Z- s
  54.         CLSCTX_INPROC_SERVER, - l3 T6 `" Q( P8 z6 J# I" [" o5 E
  55.         IID_IWbemLocator, (LPVOID *) &pLoc);
      e8 L( p' y7 S* ]. r* `& L

  56. ) v  i6 q4 x2 x
  57.     if (FAILED(hres))  F2 S4 b) S+ S+ Z  {
  58.     {
    + M. X6 x7 v  ?& A7 j$ F3 T
  59.         CoUninitialize();
    " i& l6 M; ~/ W9 j- Z9 V0 Y
  60.         return 1;//Failed to create IWbemLocator object- {- b& O. ^) F0 J4 K6 k" o
  61.     }/ e( E8 n: a% A/ u, n

  62. , U, b$ ^7 v+ h" e. Q: o$ Q
  63.     //步骤4:Connect to WMI through the IWbemLocator::ConnectServer method
    5 i6 P  g; Q3 }4 w4 \8 E4 m
  64.     IWbemServices *pSvc = NULL;
    " \6 |9 ?5 c" s9 ~# }. [+ \
  65.     hres = pLoc->ConnectServer(
    & G  E# I1 \( n! ~! a
  66.          _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace
    / R5 a1 l: k! b, K8 E, w8 U4 y
  67.          NULL,                    // User name. NULL = current user) D  l3 ?5 A1 F
  68.          NULL,                    // User password. NULL = current
    ( n, V1 i  ^4 l, F$ l( P
  69.          0,                       // Locale. NULL indicates current
    0 Q% [4 {  @- ^* a, X/ a" R5 d
  70.          NULL,                    // Security flags.
    $ a2 q: |0 n% Q8 E; I; `
  71.          0,                       // Authority (e.g. Kerberos)
    7 t- n  N1 _9 F! F, s2 {
  72.          0,                       // Context object
    ! C' E. K9 D+ y  m$ ?& c
  73.          &pSvc                    // pointer to IWbemServices proxy
    $ D% u7 f' p4 c& X! T& M& n
  74.          );
    ( ]9 g* W( p$ i6 j' |( S
  75.    
    ( i; l5 x  Z9 q
  76.     if (FAILED(hres))
    ' L  R* m1 i! B# X
  77.     {' O% \; C6 {. b0 I$ X
  78.         pLoc->Release();     
    5 z5 Y: Q' j! K. R+ n# l9 n
  79.         CoUninitialize();4 K/ U8 E9 w4 a
  80.         return 1;                // Program has failed.# a' s( _0 m/ c' d6 `
  81.     }
    ) G- G3 g* d$ f, E- A( D9 t: \
  82.     // 步骤5: Set security levels on the proxy& \5 E" m' X2 q& [  B' H, k- S$ M
  83.     hres = CoSetProxyBlanket(
    ( ]" z* H- c, z3 h& b3 K3 h
  84.        pSvc,                        // Indicates the proxy to set; o1 G) a( H4 v. {: {
  85.        RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx
    . r) G1 \/ Y. [" {
  86.        RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx% _0 J5 ?" \$ r+ i8 \, C/ Z
  87.        NULL,                        // Server principal name % _0 d2 O3 Z& l" D
  88.        RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx ! U% K9 I) p8 D' s) u$ E5 x/ i) q
  89.        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx8 Q+ ?2 g" z. U) e
  90.        NULL,                        // client identity
    ) t+ e1 n/ F# |4 w' X: ^
  91.        EOAC_NONE                    // proxy capabilities - b0 l: ?+ u& \, U2 o" |
  92.     );
    9 F  d8 w8 i# F& T; s( t

  93. + |5 Y: g) m: R' \) L9 E7 `0 C) _# ]
  94.     if (FAILED(hres))' Z( m1 U" k" Z7 ?( e6 N4 P* f# ?0 [
  95.     {
    ; Z; s( b9 Q5 _+ ]# X
  96.         pSvc->Release();
    + o5 d  `# }2 Z+ e1 m. q; e
  97.         pLoc->Release();     2 v+ H8 Y8 P, x8 B8 r  |
  98.         CoUninitialize();
    9 Q: H" ?' m- Y% N( x' `! o
  99.         return 1; ' O; D# L4 F: h2 v" Y
  100.     }4 J! ^% d  O5 f5 A

  101. - g$ {$ }/ U; f
  102.     // 步骤6:Use the IWbemServices pointer to make requests of WMI ----
    , T/ C. N- A0 _! `8 t" f6 b
  103.     IEnumWbemClassObject* pEnumerator = NULL;
    & M& Y: Q2 Z2 d. x% r, i
  104.     //计算CPUID- ]" h9 }: X1 K; ?' ~
  105.     hres = pSvc->ExecQuery(" w/ @9 R4 n% ?8 `3 }# }7 m$ f2 a4 {
  106.         bstr_t("WQL"), . q% g% V6 d. N( D! r$ D6 X1 g
  107.         bstr_t("SELECT * FROM Win32_Processor"),//Win32_OperatingSystem
    1 A' G- ~" W* L- p; @$ P
  108.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, * B# L# L" f$ H; O) L
  109.         NULL,' w$ D' x. {1 X5 ~
  110.         &pEnumerator);
    ( b$ a# r1 V5 M! H1 X7 ~2 x, y
  111.    
      {2 x4 W* q* w/ v: g- K1 F
  112.     if (FAILED(hres))0 u! n# V- h; o2 ]( [! |. t
  113.     {
    2 Y# f7 R" D% t  _9 G
  114.         pSvc->Release();
    + {. o. k* `3 G
  115.         pLoc->Release();
    9 G8 {7 U- x9 U5 X8 B; f
  116.         CoUninitialize();
    2 o) x) c/ g) `+ L# g6 Y
  117.         return 1;
    8 L  ~. @% ]4 O- p9 ?* @/ U5 t7 C
  118.     }0 g2 S/ b1 M* O& I$ l( s) g
  119.     // 步骤7:Get the data from the query 7 D8 i. @- P' n# J
  120.     IWbemClassObject *pclsObj;  P: m% T( x9 E) I) T* W
  121.     ULONG uReturn = 0;: l9 i8 L5 A' t4 B: a
  122.     while (pEnumerator)
    1 R" a+ _6 M- u- l( X' K
  123.     {' Q; ~7 C& W0 L0 c; j  L
  124.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
    # N5 |; Y: E0 w3 f
  125.             &pclsObj, &uReturn);3 l- \( W8 R! T
  126. ; C0 O6 N) @: d9 v0 w
  127.         if(0 == uReturn)
    # C; \% s" d5 F
  128.         {" Y# z3 \- g1 g2 C
  129.             break;
    3 W# D$ P0 ^' {9 c  U; X; r8 A
  130.         }
    ( ~6 I  Y+ N, Q  p6 f6 u, W* C
  131.         VARIANT vtProp;$ t3 p! Q( k6 t6 C
  132.         VariantInit(&vtProp);
    * Z; @. @; t2 b  @% }
  133.         hr = pclsObj->Get(L"ProcessorId", 0, &vtProp, 0, 0);
    # P  F' |0 _6 I, F% a9 y
  134.         strProcessID=_com_util::ConvertBSTRToString(vtProp.bstrVal);//strProcessID:类级变量
    5 R7 z4 q' U* x% `7 L, Z& V# K
  135.     }- a/ C7 M5 O; D' h
  136. # N. z3 R- `/ X; y2 R4 @5 q3 M
  137.     //计算硬盘系列号4 x+ C" q# s6 B5 E" W
  138.     hres = pSvc->ExecQuery(
    4 ?) D5 G, n5 A7 o
  139.         bstr_t("WQL"), 5 I$ d/ ~. y* N7 t; w- [% U  ]
  140.         bstr_t("SELECT * FROM Win32_DiskDrive"),
    - R2 H6 A# x" q0 f/ h
  141.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
    " @- V0 @! y# E9 e5 D- S8 v
  142.         NULL,
    9 Q$ G. E1 D' o7 n7 C; v& o
  143.         &pEnumerator);
    ( E$ E1 t( J! ]4 S" }8 B

  144. 9 B1 ]2 d' s; S: V' Y! _) |
  145.     if (FAILED(hres))$ c6 T' X" f' h0 e4 w
  146.     {$ t5 h+ X; D' ^. G9 p
  147.         pSvc->Release();
    0 {0 B; \2 J$ Z: P. ^8 I
  148.         pLoc->Release();
    ; v, a" u" o$ q# I, N4 G
  149.         CoUninitialize();
    1 H+ a0 i, x7 k1 \0 o1 S4 q, Y
  150.         return 1;
    , r& ]0 X! s5 V. W3 f' r* m
  151.     }
    ! o+ u) Q$ e6 n- f- q1 S9 W1 N
  152.     while (pEnumerator)4 b8 @2 B& `: R9 g( T
  153.     {+ C- x4 d+ h# b) M4 l; a
  154.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
    & Q: `- {& F8 ~; u
  155.             &pclsObj, &uReturn);
    6 K0 b0 d  k/ R

  156. 9 a  J, n* [9 Y* T% q7 V( b
  157.         if(0 == uReturn)5 C% r% U/ q* q: q3 b' n/ `
  158.         {% G$ o- J: w$ }6 L3 B" u5 N0 |. F, m
  159.             break;
    ; u! d5 ?8 R. U& \4 V' ]8 r% k1 C
  160.         }
    # N# Q# o$ Z# J' G

  161. ( p- W- e- b: `9 j7 H
  162.         VARIANT vtProp;  k) M* E, ~4 x& b: x9 G$ `
  163.         VariantInit(&vtProp);
    ! C$ H  x; R  _& e" R
  164.         hr = pclsObj->Get(L"PNPDeviceID", 0, &vtProp, 0, 0);
    $ j* G$ ]8 ]! A& o: O7 l. k9 V
  165.     strDisk=_com_util::ConvertBSTRToString(vtProp.bstrVal);% N3 _8 |% S3 [/ g5 J3 v
  166.     }
    $ Z2 ^  d: z: Z. y
  167. 2 d) W0 W4 L# x; f! n/ w
  168.     pSvc->Release();7 [, x5 w& O, i6 \( Z7 i
  169.     pLoc->Release();8 [" {5 y' o9 D8 p6 h' E
  170.     pEnumerator->Release();3 A1 ~8 R  H: e5 E% Z
  171.     pclsObj->Release();( s: _7 v% ?( z0 F' T
  172.     CoUninitialize();# v( y# E9 O4 o% e6 `) V- l
  173. & S2 ^# L* d% S
  174.     return 0;   / R, _3 K3 h/ x1 Q7 r
  175. }8 h( f/ B) h7 o' i; |3 W8 n
复制代码
 楼主| 发表于 2010-10-11 19:21:05 | 显示全部楼层
本文代码经ccrun(老妖)在Win2k下试验成功.* B$ ]% ^  l* l0 X
$ |% `; C; C1 \9 q: {, R* u1 O3 V2 }: `/ g
#include <WinIOCtl.h>
; J* E8 y  t& G; A; _  r#include <stdio.h>- [% h$ P. L5 j& l
7 Q" l) S, y$ s$ B, W) \+ P
#pragma inline3 I5 Q, U/ ~, C2 E/ ~
//---------------------------------------------------------------------------
" C6 r+ {5 P4 o; {! V3 f" t( ]// IDE NT/2000/XP专用变量
$ V& d$ M  p# X4 \" L& a& t#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS7 b0 _2 N9 D) |! C8 [1 ?- q0 R. M
#define DFP_GET_VERSION         SMART_GET_VERSION
  `. `' g- G1 F) r#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND9 B; P$ s+ L9 `% i5 ?
#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
3 z. D/ _! U1 {" {  W- D1 R8 w) T% o: a1 X
const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令
" h9 c1 }5 w6 wconst WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令) L1 O" Z9 n) |
" v+ S3 _/ M3 \+ c0 S8 A6 P
const int MAX_IDE_DRIVES = 4;
- }9 b3 ]$ U. I4 `  I5 H
' f) T' D( `  j& x# ^// SCSI专用变量( V: T; ]" r/ n
const DWORD FILE_DEVICE_SCSI             = 0x0000001B;
) v3 w* V: c2 o! u# q$ rconst DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
5 H# u) r8 `5 f' f. iconst DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition5 v/ l6 F8 F- Q/ _: ?, i+ R
const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
" A# v/ d+ z$ p  F2 w) ~! x* R( f# A8 u+ K# d7 X8 f4 b" r! K& f
typedef struct _SRB_IO_CONTROL
7 w/ [8 n8 k( z5 U{
) H+ y$ ^9 s! S9 C/ {  o) n    ULONG HeaderLength;
4 X- {" M( E  M! ?    UCHAR Signature[8];( q% V& t! t1 W3 }. i. M
    ULONG Timeout;
! d& [3 W, X4 e* t8 W    ULONG ControlCode;
( S; h) J4 U, n    ULONG ReturnCode;
+ B' V7 D. Y3 o, J! S3 `    ULONG Length;
* n, Z- A5 t1 [$ ]8 h  U+ G}SRB_IO_CONTROL, *PSRB_IO_CONTROL;
2 u5 i% F4 Y! A/ l3 b& @! K9 d1 C
$ I3 Z3 n. s+ z9 h// 读取的主函数3 i1 w1 q  V2 d9 u3 `
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
4 h  F2 @: H# J& k9 Z9 t4 t0 Z; ^6 Z) S( F2 P" O) f
// 辅助函数
* q$ B9 x  _4 @7 l4 r* n  _char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
8 e* |! P- o$ `3 n; [* t// NT/2000/XP函数
6 y8 ?/ v0 A( J  Y6 z- C. [% n4 {void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
$ h4 C/ H& _- U5 wbool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,4 c) R. O' L: l: G
        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,; X' L: \) e) M* K! k
        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);& p% {9 m9 [- S* Y8 S) E
// Windows 9X函数
! {  w) u4 \+ ^void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);5 b0 L+ H. F* Y6 b# B
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
' N* C1 {3 F5 ?2 G        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);# ?! j, U- C8 B, u
; ~% R% f+ [  }
// SCSI读取函数(for NT/2000/XP)
. O. g% p) r6 `" }String __fastcall ReadIDEDriveAsScsiDriveOnNT();
, ^9 ~6 L% t" F" s- c# [9 q2 T% y//---------------------------------------------------------------------------0 y& W7 r8 X' _/ O
// ReadPhysicalDrive0 c' z, M. T( c, y; L7 P
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)  \) E) V; }! ^0 n8 {4 [1 W  @
{
- N& U* }; f, r! Q2 j* ^    switch(Win32Platform)
( n% ?# l1 a" L* L8 J% V    {+ |5 k! g# l9 h6 Z: Y" Y
        case VER_PLATFORM_WIN32_WINDOWS:( V0 E3 D' B3 N  w+ S" ]$ o! i" ?
            ReadPhysicalDriveOnW9X(pSerList, pModeList);
- k: c6 s+ V8 t7 E1 m, j9 E8 {            break;
% r+ G  O  P( T! `9 C* X% r+ D  ]        case VER_PLATFORM_WIN32_NT:
# T& K0 M7 ?8 B- F0 h, C( M* A            ReadPhysicalDriveOnNT(pSerList, pModeList);
. H- Y3 W% Z+ P: \( P; p% c            break;; m& A8 U8 @2 w/ F, m
        default:3 L0 y% j5 N9 e
            break;) s6 U3 @# R6 }$ j$ t
    }: [  t* f7 J5 R; w8 H4 Y
}
* i( u$ M7 F8 f; y. j, z//---------------------------------------------------------------------------
! n) U5 c3 k8 a5 x/ h! I! Z1 @// ConvertToString
0 l/ q5 M, x$ R1 @char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)+ I7 S3 W% k. V) u
{
3 o% m& N4 b+ B- V" v" n    static char szResBuf[1024];' s6 Q0 a% O# i" t. a, x
    int nIndex = 0;! J' S+ U, C/ }$ |& B# |
    int nPosition = 0;
. @0 H. L. \6 f
; ~- Q# T5 K, d    // Each integer has two characters stored in it backwards/ P' l* X8 Z; ^" ?$ U
    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)" K( J- x6 _4 K* V' N0 J
    {
% X3 e4 Y5 v% ?        // Get high BYTE for 1st character
$ |. P4 @4 n& i+ e0 u, H' _        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
% D0 N0 j5 \% U" a/ }. x. l        nPosition++;4 d( ]# a6 w# s6 v+ G& ^
0 c. ?8 t9 m# \/ o2 y+ C  v8 G6 Y: M
        // Get low BYTE for 2nd character- j' T1 o' ^7 P) W" G* n0 D* a" ?
        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
6 [; u3 E6 }" i" [6 E4 E  g        nPosition++;
( `$ M, U# z- `+ o) n    }' _9 K0 s7 s) e1 z

3 W/ r, o! M( f0 {) C    // End the string; s6 o) z- J9 Z! B- ~0 S+ K  g  C
    szResBuf[nPosition] = '\0';9 V+ v( T7 V- v% i* e

5 {+ O' @: V$ D7 c. }' I8 z0 R; G    // Cut off the trailing blanks% I" j6 ?, Y7 t% R. |
    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
3 m3 b. k- ~" F( k; u        szResBuf[nIndex] = '\0';
$ p$ g  \+ U: v7 @
4 `) d2 [9 L# v    return szResBuf;
7 d% H: P* e1 m}0 ]8 p5 }+ s) p1 H2 j
//---------------------------------------------------------------------------, L$ A0 k, c! k7 ~, u. p
// Winndows NT4/2000/XP 代码
: B6 [# z- Z: i5 j2 D! Q//---------------------------------------------------------------------------
3 i1 y1 w4 B6 c) l// ReadPhysicalDriveOnNT) \  I$ @8 Q% v
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
1 k- s1 w7 v1 V{
# L& c; X+ k! l4 _) ^: ?    // 输出参数- M0 f$ {: Y2 Z, I. v1 [: S
    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
& i/ D. F, ^, t- r  b1 U$ J4 X! A. \* x- A  n& i
    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
1 n/ `8 }2 z) d( L& V    {- `4 K' E7 o6 U+ Y9 K! ~9 y! {
        HANDLE hPhysicalDriveIOCTL;: {; X- P7 P2 X
        char szDriveName[32];
. i. \& H# }" @
) Q5 P+ \' B* E        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);) t1 I8 \( V% ?
        hPhysicalDriveIOCTL = CreateFile(szDriveName,2 f" b1 C$ \9 J4 r, x
                        GENERIC_READ | GENERIC_WRITE,, Y9 D7 s; [8 R8 m
                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,# L% S4 Q+ o1 `; Z% }. t% Q. ]
                        OPEN_EXISTING, 0, NULL);5 d4 A7 _# U  E* X

( s# a% [; N' }+ w; ~3 R7 ~        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
" z2 B8 S% Q# \) l+ B0 @+ {* v- T        {
1 h/ s' F2 d) M+ X7 M6 b) f            DWORD dwBytesReturned = 0;3 Q$ C& V) O+ B9 t
            GETVERSIONOUTPARAMS gvopVersionParams;+ H' \6 v/ m6 h% @. P3 G& e

8 `" H& _: H9 K( J' Y            // Get the version, etc of PhysicalDrive IOCTL
. R- I# N+ S8 q+ I! T) P            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));& z8 k1 d* T5 @6 l) ?1 a

; X' Z8 H- \3 @* Z) W            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
/ _# g, M+ R1 M0 C/ ~. M$ P                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),1 T9 k( i" K' d3 z/ X, g
                    &dwBytesReturned, NULL))" _  O7 n, I: r/ e2 U- c9 j
            {! m# G+ p7 \( `
                continue;2 s3 y7 l9 Z2 H9 V$ z( p
            }0 ~: A* Y) b' D  R7 q' |4 f: A# Y# P

, Z" w9 T$ i8 }: g            if(gvopVersionParams.bIDEDeviceMap > 0)" O  W/ ^' U, h/ ]0 _9 A" p) N5 K
            {
# C5 D% c9 M! c1 ~0 Q' W                // IDE or ATAPI IDENTIFY cmd
8 H8 W. `- n( @                BYTE btIDCmd = 0;, E" y. o5 I+ m" r1 q2 X6 M
                SENDCMDINPARAMS InParams;$ B6 G+ n$ L  f4 N: O
                // Now, get the ID sector for all IDE devices in the system.8 |: P% E4 B& {9 N+ E
                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
/ c( v# I  A! P( g+ M                // otherwise use the IDE_ATA_IDENTIFY command+ D2 `, f% r- ~2 P! n  {) v
                // 具体所得结果请参考头文件中的说明4 |- U8 \6 m5 f
                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
0 L, a+ f* r! L* X/ D! z7 A                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
% Q. F/ m1 m' Y% ]3 G- P. {2 M                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));) P2 i& S/ t& P9 g! R% v3 h
                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
( ?' j# P  |, j, K  A6 W4 n
7 [1 A7 C4 o6 _                if(DoIdentify(hPhysicalDriveIOCTL,+ A; V. K- K/ L) W( W3 Q9 N3 h
                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
* A! ?) C8 k/ {' q$ I0 M1 \                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
; g0 y9 D8 Q( s2 A4 f                {
; b. `2 a8 b7 y                    DWORD dwDiskData[256];$ |) n( H$ r4 ?' e8 C; x
                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
# F: f2 \' ?. N+ `7 Y                    char szSerialNumber[21];6 C# O3 b+ w) [7 \; ^- i: ^
                    char szModelNumber[41];1 u6 j+ s! \$ o. G# s2 r
$ C1 q" a0 u; {/ x, P/ U9 W1 d; H
                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
& E( N, |2 p. e$ Z- S                    for(int i=0; i < 256; i++)
1 B* C2 V) h+ ?% @. D, l                        dwDiskData[i] = pIDSector[i];
) H3 U* f6 F: ~, Z' P' J$ p: L$ c. L4 O                    // 取系列号" Z% U3 _3 O$ d, O
                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));' I' D9 O8 ]) R6 @$ N
                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));0 s( `) k! E" N& B% q/ ~

% y8 z* W) U( C; m- A6 ~                    // 取模型号
( O  y& U4 w6 Z6 |! ]                    ZeroMemory(szModelNumber, sizeof(szModelNumber));% W# `2 i3 s2 t. p- K
                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));, m$ h: U& v; U# Q( G- y
* V/ @3 L7 a8 h
                    pSerList->Add(szSerialNumber);9 h# b) h$ p1 }6 w
                    pModeList->Add(szModelNumber);* ~; H# u% ]# P7 g5 m  _/ a2 Q
                }9 |6 f8 d, x5 t" }. E
            }
$ Z- ]* g5 d, Z  D* D$ t            CloseHandle (hPhysicalDriveIOCTL);* Y) Z/ l9 q' M) X
        }) \. B' o% n, B
    }
1 J: n1 ]! r3 s8 Q' r( f}( ]8 r- n( I, l
//---------------------------------------------------------------------------
( R/ y# u! u7 N& X  W) `% B// DoIdentify% f4 k3 b, G$ x
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP," \* b" h/ a8 |$ W1 B4 O/ K+ d
              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
/ B" n7 W. c, X0 Q% ~              PDWORD pdwBytesReturned)
1 V8 `/ m3 `+ J: f7 W: f{
/ ^' M8 ^$ b' K: k    // Set up data structures for IDENTIFY command.4 c3 c5 }% O7 L  ~$ \" ]  a( D
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
& g8 a( O- q; \* O    pSCIP->irDriveRegs.bFeaturesReg = 0;
6 a( q: D( s% ~3 K$ `$ _    pSCIP->irDriveRegs.bSectorCountReg  = 1;' H3 y1 L4 @9 N) ~7 m
    pSCIP->irDriveRegs.bSectorNumberReg = 1;! u9 A* `. E. Y1 `& q, A
    pSCIP->irDriveRegs.bCylLowReg  = 0;$ s% B% D. H7 H- y5 W& C
    pSCIP->irDriveRegs.bCylHighReg = 0;
5 C- Q. D0 |" E9 \8 `+ n( E8 ^8 e% z, ], _9 X
    // Compute the drive number.(主盘和从盘所对应的值是不一样的)
; K( z* s% D2 G# K    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
* j6 E+ l! w! s: |$ x2 f6 |
% \2 K/ d* y) z1 q3 p1 R' o    // The command can either be IDE identify or ATAPI identify.
* @) k& |- G+ U" `( l* w: ?    pSCIP->irDriveRegs.bCommandReg = btIDCmd;
$ N4 Z$ O7 Z' _! V    pSCIP->bDriveNumber = btDriveNum;
1 Z3 V. w% O  [* N" Q# v    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;. J# r; ]6 B* c+ c

) a( h1 C& B) R1 J; D$ F6 |    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,4 N0 t0 I. j. q  q- W" @
           (LPVOID)pSCIP,
' V# _6 ?  J9 n7 j" E           sizeof(SENDCMDINPARAMS) - 1,
: O* |' @) }" N           (LPVOID)pSCOP,
7 f1 J2 v. [4 `' v1 z* `5 S: A           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,' V* o" r8 u$ Q1 F& n8 a
           pdwBytesReturned, NULL);# k6 w, D" o# _1 s8 g
}
: `2 N, c. @9 W. w! R+ L//---------------------------------------------------------------------------
' P& H) C6 ^: ]( O: C% l// Windows 95/98/ME 代码: o0 O: n0 Y: Q9 s
//---------------------------------------------------------------------------* G( o& @3 T! G0 W4 q  ?; A( X
// ReadPhysicalDriveOnW9X
  c% @* D/ Z' S/ Z8 wvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)& D; R# j+ l; M8 D  d# I' h
{1 B9 h- n# V  `$ k; ^' i+ W
    WORD wOutData[256];, Z; A5 z7 d3 _; \% K0 p% {" T+ o
    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);5 \4 }- m0 A6 a$ Q2 o0 z  ]

/ u% [( i. b( K" X( `$ X    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
$ @* h7 x8 k4 x/ p4 z( ?    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以0 q8 u( |' z% k" ]( C/ R1 k
    // 避免蓝屏的出现。(期待高人能指出原因)
5 D1 g; i+ L; h% Y9 R    for(int nDrive = 0; nDrive < 8; nDrive++)
8 A1 \( x2 s) ~3 o. w0 Y    {* S6 @6 R* M2 ~, N$ j
        WORD dwBaseAddress;
5 b' a+ J- W& C, ^# d# E( f        BYTE btMasterSlave;         // Master Or Slave
# B4 k% e+ @! y4 ^: f1 E* v& v        bool bIsIDEExist;
( T3 u8 J) @" z" J: M$ Y% n        bool IsDiskExist;
! h: t2 K9 o7 Q/ x9 _9 e) b; s, [% O, w% M- Y- V! A! O- x. s
        switch(nDrive / 2)" C7 V- x# e( M2 k7 o6 y
        {
: H3 u2 u4 \5 W0 D8 F            case 0: dwBaseAddress = 0x01F0; break;
6 c: r8 y* |( s0 R2 U            case 1: dwBaseAddress = 0x0170; break;) L% n( x. n* _$ }- N: l1 k
            case 2: dwBaseAddress = 0x01E8; break;) B; k  Z; C* Q
            case 3: dwBaseAddress = 0x0168; break;
& _, K* y) l( R: p        }
5 u+ I2 C  L1 X, V# f
! s- C3 ^5 e4 B+ C% @        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);; e  w4 t. M' C" I+ e' {
: b; @3 o4 K7 ^* X# e
        // 进入Ring0
% L' c$ q5 G7 l/ H3 R. ~4 e+ `4 w        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
  |; I; b# b; l8 z  b% N: {0 c                bIsIDEExist, IsDiskExist, wOutData);
$ n5 i6 a3 q% H    }
8 ]# H3 r- R( G4 W
* {5 ?! E, R, N# Z/ f/ x9 Q9 ^    // 开始读取
8 L5 j2 Y1 L: I7 G    for(int nDrive = 0; nDrive < 8; nDrive++)* v% _) ?6 d; }0 a0 e& D" u
    {
% l$ T7 G! L% q. z  V        WORD dwBaseAddress;1 _6 m2 W0 j9 ]. l
        BYTE btMasterSlave;         // Master Or Slave
, `6 u7 t1 b- H/ Z5 T        bool bIsIDEExist;% }0 F0 g5 F5 s) E7 F" m% ]
        bool bIsDiskExist;
( U0 V5 O& T# G! Z  t2 |' Y& J        switch(nDrive / 2)
# y# J4 j  E8 W+ X8 p5 [        {# d. ]1 F: z0 S% F1 e3 n+ \
            case 0: dwBaseAddress = 0x01F0; break;
7 g; M1 `& c# o, {! w            case 1: dwBaseAddress = 0x0170; break;2 C7 s  F7 x2 u( A  G
            case 2: dwBaseAddress = 0x01E8; break;
5 F6 n6 z* z; S5 G6 |            case 3: dwBaseAddress = 0x0168; break;( ]  g1 D9 c9 I4 n
        }
3 g% W8 b- y$ T9 |% ^1 a% t5 L7 c) g4 s% O0 c, n
        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);9 t# q0 r/ q; A3 i: q
7 z6 x4 V7 k+ w  q' H# S8 ^
        // 进入Ring0
. M1 K" L$ q; w- I  x! F        bIsIDEExist  = false;8 {% r4 }1 S+ ]
        bIsDiskExist = false;
7 [- U2 E2 u2 ?        ZeroMemory(wOutData, sizeof(wOutData));
- w8 y! D) I$ e* p4 N7 b# c4 F  Z" t
# O& }: K2 T( _        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
9 d3 U% ~# D* X5 e) \                bIsIDEExist, bIsDiskExist, wOutData);
7 Y: }5 a: v+ [3 H- C8 a2 O0 }; F
        if(bIsIDEExist && bIsDiskExist); `+ n% q+ q( R! R2 X1 i$ Y
        {* w! \& m/ B* U( W1 y" L8 e
            DWORD dwDiskData[256];
6 `& C  d# m; _9 e& I# F$ s            char  szSerialNumber[21];
3 Y. x0 m7 o5 D/ c& K* c            char  szModelNumber[41];6 g. |( C" H; t1 m! u

4 ?% U$ J# Y# d7 X8 W$ o            for(int k=0; k < 256; k++)
$ }0 U% b7 t& v* D/ m                dwDiskData[k] = wOutData[k];
5 i* t4 L( r5 f7 e% `0 S
. m) P, l# Y6 N' d( b. h8 Z. J            // 取系列号6 E; N) }, Z$ c: w
            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
4 f; L! s* P# v% H. |8 n            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
* [' [, q: b9 L- ]; K8 [3 d8 S7 _: }
            // 取模型号
3 ]7 Q% `3 _- {3 c$ D) H3 I+ |+ Y& h            ZeroMemory(szModelNumber, sizeof(szModelNumber));
3 U' c! r0 q7 \, Z7 G2 @  x            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));- k! d9 p/ e& O! C, R5 S1 X
6 t, L0 ?% N/ R6 @" n/ o6 D* @. [6 a
            pSerList->Add(szSerialNumber);
2 k' N, |. }5 Z: Z            pModeList->Add(szModelNumber);
) y! ~! @7 [: x# B5 w        }: S6 [% R) R0 e3 k; C
    }. F: t1 y" f& S/ x
    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);  y2 A' Y7 o4 [* ]3 R% C' H/ }! _
}" P, y& \! r; B
//---------------------------------------------------------------------------
7 _1 _% k7 \3 x$ q7 L" E0 P* l// 为防止不负责任的转载者,在此注明原出处信息,请见谅。
2 i1 d! e- ~4 j+ P// 资料收集整理:ccrun(老妖),欢迎光临C++Builder研究: http://www.ccrun.com0 y2 a9 B- G0 D( ?7 a) P. s' W4 N
//---------------------------------------------------------------------------
9 l* p9 S. k& n- q, x// ReadPhysicalDriveOnW9X_Ring0()
+ K  H& z4 A( t; p2 M4 X//
! q" F  C% w& y* v4 m8 M5 B, m+ I// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
8 T. p1 k; A; S" `. ^& |( n// btMasterSlave = Master(0xA0) Or Slave(0xB0)
* ^8 }: L4 H' }4 [2 B1 k//---------------------------------------------------------------------------
: J5 c! w7 j% e$ j2 b6 `void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,( E% ]5 ^5 Q6 T9 c0 y* ^
        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)1 ~& N5 E) K/ A1 ~& G
{
: w& r2 D3 f0 ?- \0 Z- `    BYTE  btIDTR1[6];4 C6 W! c# p$ L. i* j
    DWORD dwOldExceptionHook;1 D" N+ {& ^6 S" @( i0 v
    const int nHookExceptionNo = 5;: C: d  m) `, \# Z* E2 z
& H" F+ Q9 Z% i7 x3 B
    BYTE  btIsIDEExist = 0;7 T- F% G: W4 x/ a8 ?
    BYTE  btIsDiskExist = 0;$ q: f- X* M9 o* l9 z* K
    WORD  wOutDataBuf[256];
+ O% K( ~0 F% D' T4 s3 O8 [- z# R, J; u- o5 e8 n! p% X+ s5 O
    BYTE  btIsFirst = (BYTE)bIsFirst;1 i0 p- V* l2 r2 G+ g
& V* X8 p2 ~& h+ X4 B& v7 B
    const BYTE btBit00 = 0x01;
) _& B- j$ g- b7 k; U    // const BYTE btBit02 = 0x04;8 w+ l1 T# T, p
    const BYTE btBit06 = 0x40;
; r" M& C( V' J3 A- c8 F    const BYTE btBit07 = 0x80;% p( r% p" _6 E# b0 E4 w% W
    // const BYTE btERR  = btBit00;
7 A& i0 i6 q; T3 h    const BYTE btBusy = btBit07;. [. T4 S! g! B8 N3 a0 G, ~
    const BYTE btAtaCmd   = 0xEC;
$ u1 y4 x5 m* m  }# b    const BYTE btAtapiCmd = 0xA1;+ D* \$ ~) g4 }" l- i9 R
1 m' ^; ]; j6 |
    __asm2 n# x; X2 h- a0 B  o! }1 h
    {0 n+ E5 U3 R0 R1 y
        // 必须先执行这条语句; p% {( H" P  E$ H
        JMP EnterRing07 B" \' C& `! M- m

6 C$ D' m1 Q4 w3 {' E, ~1 d5 j2 h        // 定义过程
' Y+ h( i3 n5 ~$ [4 D3 z, t        // 等待IDE设备直到其不为忙为止9 D! O: U& U9 x3 ~& v+ Q1 _
        WaitWhileBusy proc2 E) ~+ z; j6 K( h: ?; [
' f/ }4 L, J. ~1 f6 D/ v2 e
        MOV  EBX, 100000  g/ L; Q' p( A3 _0 g5 D0 f, I
        MOV  DX, dwBaseAddress
7 e$ c; z3 w/ @! e7 P$ ]        ADD  DX, 77 `7 A2 g# {' I/ H( r# z2 z* N% i
* F6 T. N* K- V: h# i  v8 e$ G
        LoopWhileBusy:
' o+ W! n) ]/ ?9 E) \1 q9 r! K% `  ?! t- _1 Y
        DEC  EBX2 S6 x% [9 D5 |7 ?- l1 S: D; I0 X
        CMP  EBX, 0
+ s/ m' e5 y4 l        JZ   Timeout
; }9 z6 t" ]+ w        in   AL, DX
% D# R: d2 k! e        TEST AL, btBusy
% h0 l  Y% W+ d: x, `- U* k* |        JNZ  LoopWhileBusy
+ ^* L" k5 d" A9 c# h& `3 b        JMP  DriveReady3 I! S" I7 F2 i6 R7 }

! y8 j6 V+ |* C+ i0 r3 o" K        // 超时,直接退出
; A3 D( Z# @* d" T3 I        Timeout:6 G' ?. k+ {5 ]7 P. V9 u
        JMP  LeaveRing01 j6 _" {2 R4 u4 r& F2 a
        DriveReady:
& w$ i( l" k5 }$ z& R+ ]  r! }! Q        RET1 f, G3 n4 }: u: V: L$ e( ^8 i
        ENDP   // End of WaitWhileBusy Procedure" Q! q- O5 Z* v1 g. k- d1 E
: N# S0 R6 V2 s/ t5 [: i: W7 S: _6 u& F; F
        // 设置主盘和从盘标志! F# l3 w; y  Z# i' J) W3 {
        SelectDevice proc
! t) U7 n7 R% W2 ^( J* `; A* V( _" l1 d/ i( J* X) I
        MOV  DX, dwBaseAddress" H; @3 U5 Y! @1 o, h  X
        ADD  DX, 6
4 ]0 u& u1 k0 `) ?( C        MOV  AL, btMasterSlave
3 N& y" w3 R9 n1 z0 K! f6 y. g
8 [+ e1 }% O8 |! h        out  DX, AL3 s' R1 |* y6 C, ]
        RET( B, Q8 ~8 P) g  I. G+ z+ _  [
) C: ~, A5 n. r/ s1 e
        ENDP  // End of SelectDevice Procedure
5 _5 j9 I( r: C; K" c6 x( t- R6 y8 f7 m. e3 F
        // 向IDE设备发送存取指令
) t; H5 U! X( v/ K: a0 f, }9 l        SendCmd proc5 F6 y& t5 Y: c
% s/ m6 M/ I) A5 m0 g
        MOV DX, dwBaseAddress
7 k5 q, e9 H0 m" E; n1 M/ n3 e' j        ADD DX, 71 W+ T- w  m( ]! R. U
        MOV AL, BL // BL是主从盘标识,在过程外设置
. W: B: ^5 [) X        out DX, AL
" f- m% h/ O& P! V        RET
# p2 m2 R' |: R1 Y: g, V6 E5 y. ~        ENDP  // End of SendCmd Procedure; i8 G% C0 s, S4 n1 |+ V

2 F& i4 A- h; q1 I' a) b+ U5 b7 G" T        // Ring0代码
0 t0 |. k( N" n5 H        Ring0Proc:( Q# T+ v( n3 C8 ^3 |/ U
        PUSHAD
9 g0 L. i) i) H$ |7 Z% ^8 [        // 查询IDE设备是否存在
4 Y$ i* j6 V/ G- m7 U7 C        MOV DX, dwBaseAddress$ e( i4 m) a% g0 ^  r3 f
        ADD DX, 7
7 n, W2 A$ O& z" I" H7 `        in  AL,DX
7 \) E7 t9 Q0 J" l
1 c: K8 A" ^+ m0 p; Q        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
1 I6 m# f! q; L& h        CMP AL,0xFF
6 q2 C' ?  }" u        JZ  LeaveRing0
! i& e" l# W# `. I% K6 U, D        CMP AL, 0x7F7 |, y1 {0 f" F8 |+ Y9 a
        JZ  LeaveRing0
* O: @9 a; v9 r7 o% {7 E8 t! H1 i+ c/ e+ x8 k
        // 设置IDE设备存在标志
3 D- Q  u/ b% e% R, I        MOV btIsIDEExist, 15 a/ m; d: Z$ g. ^, |# I2 j+ p
/ v/ ~9 A& ?( l
        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
/ u( z  L0 z$ l$ U. r% L  a        CALL WaitWhileBusy' N( b3 B( a8 {! A
        CALL SelectDevice' s( V7 w$ E6 v- K+ a/ \. _
: w2 Z" j, c0 |% b# x) a
        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏$ i1 R+ u5 O+ r1 [0 f
        CMP  btIsFirst, 1
& O' B3 v$ W) L* V        JZ   LeaveRing0* D" W) {+ I0 w1 i: f6 ^
. r( t: n$ t& z# t0 b8 ]! g" Y
        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???" c6 C) p9 B$ O- a' c
        CALL WaitWhileBusy
' g" W' U8 B- ]5 F+ H" F
7 z) a. \; ?* D( v! ~1 P3 i        // AL的值等于cBit06时,不存在驱动器,直接返回
" i2 f3 T+ }. ]        TEST AL, btBit06+ n0 u" x* K7 A2 N: D3 o+ {* B+ |
        JZ   LeaveRing07 }* r$ D( F/ F; w7 {
! V, g  d8 |% H+ ?8 x: r
        // 设置驱动器存在标志
. }  l- @+ t$ x, \! E8 W. A        MOV  btIsDiskExist, 1+ ?7 z3 v- f, D2 y0 E1 R

+ [* I( Q+ P( x0 a; K! h        // 发送存取端口命令
7 B6 v: `. p; d) p) o        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,3 G+ h5 d, R% S0 r5 }. g% j+ @
        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
8 |0 U6 N, b% y; l        CALL WaitWhileBusy/ @7 \& x6 p" d
        CALL SelectDevice    // 设置主从盘标识5 ~! C5 ^8 |' H6 V$ A: \. N
        MOV  BL, btAtaCmd      // 发送读取命令  [0 q% [2 M, z/ f* G5 W
        CALL SendCmd
" N! R( {1 U2 _( N        CALL WaitWhileBusy( x0 d& {4 O$ e9 U
* q& p4 {! E# G* X$ F6 C4 |1 q
        // 检查是否出错
; ~$ n# I2 j- c. h  ~; I# v2 t        MOV  DX, dwBaseAddress7 C! q7 c  }# X
        ADD  DX, 7
. i; i7 T6 t# z- `9 Z9 x3 }9 E8 G9 ?$ s, O7 ^, t7 o8 S7 B. ^
        in   AL, DX( q9 h% N6 H/ t9 k* A  R1 u* f% R
. r! w4 ~3 \/ O- g) \
        TEST AL, btBit00+ |/ n1 j' Y1 E% f
        JZ   RetrieveInfo   // 没有错误时则读数据. A9 V4 w  f6 D3 W7 ?; {

- x0 M; D: E& F        // 如果出错,则进一步尝试使用ATAPI设备命令! C. H8 y$ ?: [* E" E( j
        CALL WaitWhileBusy$ v1 M8 m8 l5 _7 t/ M, ~
        CALL SelectDevice0 n* {# [5 K! n! |
        MOV  BL, btAtapiCmd0 H& Q8 `" T/ Z3 y" [/ Q: N
        CALL SendCmd, v7 q0 ]2 r/ A( b6 z! A
        CALL WaitWhileBusy' a" B: x) I* u7 }4 @6 a

2 O2 V1 c1 E+ t8 |" J        // 检查是否还出错
1 [# B2 i  o9 L! `  W        MOV  DX, dwBaseAddress
2 j% m8 D1 B2 {. N9 F        ADD  DX, 7
1 l% J( O# s. l7 i7 u        in   AL, DX& J" a  ]. P  p& s! }" r
        TEST AL, btBit00) _- m6 l- F5 a. q0 A
        JZ   RetrieveInfo   // 没有错误时则读数据, P% D" V8 ~0 i( M/ i& n
        JMP  LeaveRing0     // 如果还是出错,直接返回
+ {# k8 d% q7 m; w+ G- N. D7 }; @) ?3 k5 D+ z+ P0 s
        // 读取数据
, @# m6 {, D( n5 |- F        RetrieveInfo:
* x6 A! r$ u* |8 c( o! J
4 F6 k, d' ?8 y( q5 `& n  k        LEA  EDI, wOutDataBuf1 U8 A+ I* _+ c$ k8 Q8 C
        MOV  ECX, 256' I7 ?6 K( w  B! y" t$ p/ ^  v
        MOV  DX, dwBaseAddress' ^; X; G  ^! V9 ^4 q" g
        CLD
# l9 J% C/ P& o- q' y- u; P/ z/ q2 j: F4 f* o/ C" M# V
        REP  INSW
6 v* y& Z* h, [
) v3 b+ v. n" J  I1 D        // 退出Ring0代码0 H3 L7 V. n& J- E% F! V( s
        LeaveRing0:# F) B" U! i: U+ ?, H
8 U% n- q1 R3 c6 L
        POPAD
, X) F, K7 |. D$ D" j7 v+ [        IRETD; k4 l$ c* }" s( ]$ }# D/ w+ _
7 W$ `5 J" K/ ?: `: N2 j
        // 激活Ring0代码4 z1 n) C- |/ ~6 K
        EnterRing0:
! J$ B: G9 E5 Y7 W# b- ?( M
' l' c0 s/ O% h$ ]; [: Y        // 修改中断门( K0 `  U) V9 h# Z
        SIDT FWORD PTR btIDTR1$ U  Z! Y% O; w6 e; c$ Q+ ?! x- n& Q
        MOV EAX, DWORD PTR btIDTR1 + 02h! U8 H& o) A  t; @
        ADD EAX, nHookExceptionNo * 08h + 04h
7 V1 D( n% c( x) |+ w        CLI
" ~* B! y3 j& Y) f3 ]( J  o! E
        // 保存原异常处理例程入口
' n7 U8 S4 J' z& z/ u: R! E        MOV ECX, DWORD PTR [EAX]3 B; @) d  d& M, r1 o
        MOV CX, WORD PTR [EAX-04h]" H7 N$ e1 V2 g. ^
        MOV dwOldExceptionHook, ECX: X3 R+ q/ ]8 Y5 _- k7 F) m

4 a, A3 @3 i& @/ }        // 指定新入口
) g4 V/ f( I8 C1 |5 j        LEA EBX, Ring0Proc
* X5 a8 o: u3 C4 P1 Q- ?, \        MOV WORD PTR [EAX-04h],BX$ m( N% n" v/ A5 x7 i! _: m+ f8 h3 r
        SHR EBX, 10h) z+ \$ @" ]! m7 p  v, q& t
        MOV WORD PTR[EAX+02h], BX
, W' ?1 }. t. X5 l7 `3 K) g
5 M# _0 {$ G5 ]8 |        // 激活Ring0代码% q$ b+ L2 z' }% r+ z' O3 A( L2 I
        INT nHookExceptionNo
; i5 \, [% X# |6 D. o) G% ~% R. B. N2 N/ l0 G6 R% ^7 J5 ?2 p$ U9 b
        // 复原入口' j! T7 L6 s$ D
        MOV ECX,dwOldExceptionHook
3 h$ L+ I# t+ s! m# x        MOV WORD PTR[EAX-04h], CX
' }5 h5 u/ R  W. |% p        SHR ECX,10h! P& [1 T- H+ j+ p  C
        MOV WORD PTR[EAX+02h], CX$ n) R) _2 z4 m$ V* N4 U: i
        STI& A0 x7 }* \+ k! t$ \: k5 p
    }% _4 F3 Q$ K6 j- q2 j% B" W) U6 u
    if(!bIsFirst)' f2 B8 N+ _. K
    {
5 x- j! z5 U5 c        bIsIDEExist  = (bool)btIsIDEExist;1 Q$ H3 N% k# j7 q* O
        bIsDiskExist = (bool)btIsDiskExist;
1 z, p) i' n% V, h        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
( d) D* s  |, l" Y6 F# ]    }7 l# C& Y3 R' w
}
# D0 Y3 w* ]; L& C//---------------------------------------------------------------------------
/ O5 }/ s9 g# c3 l0 |  }3 l// 调用方法:
: _8 H. u! a" N; j$ p/ P9 uvoid __fastcall TForm1::Button1Click(TObject *Sender)
$ ?/ }: A/ W& ~- n  R# O1 d{8 K+ B+ |+ p, x' H6 }
    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
0 {8 Y5 [. q- I3 a}
$ m" ~" U6 ?: T# G. L
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-6-19 03:40 , Processed in 0.017323 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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