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

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

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

  1. % R8 ]/ l8 l+ C4 R5 T* x
  2. #include "StdAfx.h"$ C; c5 a5 K5 d
  3. #include ".\puiddisk.h"
    0 e, P+ g; j  G- S0 ?4 g9 H, w+ p
  4. #define _WIN32_DCOM) L7 `  [% z! Q5 I; `
  5. #include <iostream>* r9 j$ w' Y# d% [- m) K
  6. using namespace std;
    4 H" h& ~0 s0 ~) j
  7. #include <comdef.h>
    1 d, ]4 N# ~* u( f
  8. #include <Wbemidl.h>) k) |+ W& p5 J( k: ^8 w

  9. 9 i+ y" `9 p, @- z
  10. # pragma comment(lib, "wbemuuid.lib")
    9 @$ k0 q0 P' A2 [
  11. CpuIDDisk::CpuIDDisk(void)
    % Q. f. p2 o2 h/ O& v' M
  12. {
    ; x' J, {, J( }
  13.     GetInfomation();
    3 [& h5 ^& R, @% L) h
  14. }
    2 H# B8 q) V; k1 v! {4 u
  15. 4 o4 `3 U4 s1 V6 Z
  16. CpuIDDisk::~CpuIDDisk(void)
    4 f1 K) T, M& J  B" J4 H+ ^; Q
  17. {6 ]) K3 ?! i6 D8 _3 M: O
  18. }
    5 ^4 m" `- u9 D. R
  19. int CpuIDDisk::GetInfomation(void)
    , a  o9 K& _  A' ^
  20. {
    " k1 A- S0 L. n5 @' }3 ]
  21.     HRESULT hres;
    + |) D" G& v1 V9 |5 p
  22.     //步骤1:不是必须的,COM只须也只能初始化一次+ ^! A! d8 m: E
  23.      hres =  CoInitializeEx(0, COINIT_MULTITHREADED );& F/ v# `- @. q& ]
  24.     if (FAILED(hres))
    . D! ?  g( [3 @
  25.     {+ m! ^$ e" r7 \  b1 m+ S3 E6 }
  26.         return 1; //初始化COM异常:注意,COM只须也只能初始化一次4 J, P  i. I* h) \* h1 b
  27.     }2 X  g% W" s! t8 O
  28.     //步骤2:不是必须的,COM只须也只能设置一次
    $ e4 }7 Y9 ?- v- O% f5 X
  29.     //Set general COM security levels  A( N, X; F) V! J4 p$ [
  30.     hres =  CoInitializeSecurity(# k1 j; _1 k/ n+ o
  31.         NULL,
    0 d& r( @$ m3 j0 p% C) B2 f
  32.         -1,                          // COM authentication1 R$ U7 ^& H0 ~  M. ]! C
  33.         NULL,                        // Authentication services
    8 K% Y/ u$ b/ a2 n7 d/ {
  34.         NULL,                        // Reserved
    / M, q4 k% r* \' |$ E" ?( C1 Q
  35.         RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication
    9 b8 B8 z9 N7 Y6 `. G
  36.         RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  
    " c1 U. o6 J9 w0 H0 M( v. W
  37.         NULL,                        // Authentication info, _) {  K1 [9 X- z  w1 H
  38.         EOAC_NONE,                   // Additional capabilities ; m* S& G) u, j/ W* W8 k
  39.         NULL                         // Reserved
    4 v  k$ \( H. c; R. I+ @8 t7 k$ y! F
  40.         );" u* ~9 F$ v. c4 U7 h
  41.                      
    2 b! G0 C& [8 ^/ W% q" f* e
  42.     if (FAILED(hres))5 F9 z7 S: A8 W4 i/ {
  43.     {( K4 _+ {: l9 ~/ K* G
  44.         CoUninitialize();
    ; q6 Y! d6 X6 X8 P$ Y2 E5 s- a
  45.         return 1;                    // Program has failed.
    : I  j+ \  c9 o# b9 d! U- L
  46.     }
    ) D6 C. m( |8 F0 a
  47.     , W5 f* K1 h9 E7 W: I! x
  48.     //以上不是必须的,若已有“::COMInit();”,则要跳过
    * G8 f7 B1 z& ]% a
  49.     //步骤3: Obtain the initial locator to WMI & b" E7 l9 `( m  d1 n
  50.     IWbemLocator *pLoc = NULL;
    - P$ c8 d$ n6 }4 }0 R) o  V
  51.     hres = CoCreateInstance(
    ( u3 B  h8 A8 i9 h
  52.         CLSID_WbemLocator,             6 x9 r$ ?, B% Q
  53.         0, 7 W) @/ w& k3 c( ]: a4 c! K# }
  54.         CLSCTX_INPROC_SERVER, * Z0 f9 q& M, U9 _
  55.         IID_IWbemLocator, (LPVOID *) &pLoc);  @  g7 x7 M1 }) l% \! I& J% |) i

  56. 5 K) |3 [' I5 s; }
  57.     if (FAILED(hres))
    ! ]! @% k0 [. Y: f, _3 {
  58.     {9 I  [; ]5 a* R% t; N, d
  59.         CoUninitialize();; E+ L7 |& c+ }' k8 l
  60.         return 1;//Failed to create IWbemLocator object$ v6 c- `, w! }" V
  61.     }+ \* ^0 `8 Y# ^2 i& R, P$ r
  62. ! W0 n3 e% J+ i( x" q' J/ h% q9 r
  63.     //步骤4:Connect to WMI through the IWbemLocator::ConnectServer method
    " b/ N2 _% p9 S* _8 \$ P0 U
  64.     IWbemServices *pSvc = NULL;
    ; k, p6 b- {% ]) G3 T' A
  65.     hres = pLoc->ConnectServer(9 Y, c4 r# ]: w: X7 F: a
  66.          _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace9 W. X  ^: w; H4 B2 R9 p
  67.          NULL,                    // User name. NULL = current user5 s4 z2 V6 [- }8 q; ]/ d. L6 h
  68.          NULL,                    // User password. NULL = current- x/ q2 |1 H- P" q. C
  69.          0,                       // Locale. NULL indicates current8 f" E8 |6 J( k4 j4 C
  70.          NULL,                    // Security flags.
    . _: ?6 \" [( i
  71.          0,                       // Authority (e.g. Kerberos)( h  l* J+ G, E! S  s7 U& b
  72.          0,                       // Context object 1 g4 C1 Y/ q2 A, T. `. ?; H* J/ N
  73.          &pSvc                    // pointer to IWbemServices proxy
    1 T; @0 E$ c1 Z7 z' P- G' b* k  O
  74.          );
    9 d9 q9 G7 ?+ }  R7 w  S' E$ R. }" _
  75.    
    # }7 g  m0 j* C
  76.     if (FAILED(hres))
    ) ~* I; y0 l: K
  77.     {
    ; f; j- i! @8 e+ S# N* A
  78.         pLoc->Release();     
    ( d' v" W1 v" G* X! q8 ?  ]8 `0 R6 o
  79.         CoUninitialize();
    8 d/ k  f* ]' [6 F' W
  80.         return 1;                // Program has failed.
    . x. q$ N5 Z' Z' A
  81.     }2 ?7 Q; O- f1 m- T* k  m
  82.     // 步骤5: Set security levels on the proxy) d7 ]+ l6 K* J8 m2 f' |
  83.     hres = CoSetProxyBlanket(
      Z4 i6 T, h0 g
  84.        pSvc,                        // Indicates the proxy to set* G0 q  L9 r+ a
  85.        RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx, F0 Q- L! U% b
  86.        RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx  b2 B+ s8 g! d# U( |( N, d
  87.        NULL,                        // Server principal name 0 s) |; G) B6 c9 w+ V
  88.        RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx % ]6 H( [: P# S( B
  89.        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
    1 o3 Z; X3 _# L8 O0 e5 v
  90.        NULL,                        // client identity0 Q6 Z( R- ~! g3 [- Y
  91.        EOAC_NONE                    // proxy capabilities
    4 v; L3 _" d& }- T& _5 @7 w/ R
  92.     );( C/ p. r" H" ]0 S7 g, I

  93. * ?" q1 b: J- d: y5 d& z; v& {0 m
  94.     if (FAILED(hres))
    7 \  ]5 s! z" p$ ?- V) R
  95.     {
    ( [* C. a! g9 E/ Y7 R
  96.         pSvc->Release();8 ^7 _1 D- s# r: @
  97.         pLoc->Release();     - w" a0 N7 ?2 Q
  98.         CoUninitialize();
    : U' O8 I* ^! t9 P  f
  99.         return 1; # P+ Q; J3 e( J# V- L7 s! V- \
  100.     }4 K, L  j1 J7 A

  101. 1 r4 _  k8 H, G/ l/ V
  102.     // 步骤6:Use the IWbemServices pointer to make requests of WMI ----( D$ }/ d% z% G5 W0 J) |
  103.     IEnumWbemClassObject* pEnumerator = NULL;1 c8 R, D$ @* T% A
  104.     //计算CPUID
    3 w! a0 d! Z5 X9 T
  105.     hres = pSvc->ExecQuery(
    ! Z, @; E; \% U
  106.         bstr_t("WQL"),
      P( O4 G, h' e
  107.         bstr_t("SELECT * FROM Win32_Processor"),//Win32_OperatingSystem
    6 {. E+ \  n, k3 x% w+ G* ?
  108.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
    3 R7 m: I& c1 x4 p, j
  109.         NULL,& B6 `0 ^5 f8 r
  110.         &pEnumerator);1 E  h  w, Q/ [) E7 |0 r
  111.    
    5 o% ]0 b; H7 }" C
  112.     if (FAILED(hres))" h0 {7 Y2 n, n' m# {$ G
  113.     {
    & J5 B8 W3 k# K! u" B8 x
  114.         pSvc->Release();) U7 p0 g& R/ \8 e) X, z2 i5 Y( P( Z8 `
  115.         pLoc->Release();& [3 \0 f' U% g- p* c
  116.         CoUninitialize();) M" i# L# x3 {. Q5 H, X
  117.         return 1;
    2 R- L3 d6 s) u% f
  118.     }
    $ c* @" _/ Y6 F% Z. b. ]  ], e
  119.     // 步骤7:Get the data from the query
    ) m. ]3 p1 }" D! P0 W* s! y5 _1 q
  120.     IWbemClassObject *pclsObj;
    ; z* Y/ b6 @" M. y5 Z, T/ U
  121.     ULONG uReturn = 0;
    " D2 q( R. s) L# s8 R3 p% w# Y
  122.     while (pEnumerator)  T) w+ a, J4 j$ I5 r. F6 e: p
  123.     {
    2 U1 ^' p  m( e" n4 Z, n
  124.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, " [% D) u" Q4 W/ u( z, v
  125.             &pclsObj, &uReturn);
    0 m4 k+ R- A, t. D, j

  126. " A5 a# L" F5 f0 Q; G. J
  127.         if(0 == uReturn)
    + s4 r9 U  l: W/ j' E: T
  128.         {
    . Y% m5 [' w7 _/ u4 J
  129.             break;
      G" {$ d" {9 C9 c0 W0 U
  130.         }  G4 D* ~" g* _5 B/ q
  131.         VARIANT vtProp;
    * y* r! l" j; E# w5 t) a- X: P
  132.         VariantInit(&vtProp);
    1 q1 t8 p) p: W: S* A8 t! t
  133.         hr = pclsObj->Get(L"ProcessorId", 0, &vtProp, 0, 0);
    6 }$ m% X1 U: |3 N/ C% l0 x5 x2 _
  134.         strProcessID=_com_util::ConvertBSTRToString(vtProp.bstrVal);//strProcessID:类级变量( H1 E& H0 w5 B3 z" w
  135.     }' v$ A2 }4 k$ y

  136. : c( t% k! {# ?* A
  137.     //计算硬盘系列号/ G3 Q" m: C& I2 U& A2 h8 {9 _
  138.     hres = pSvc->ExecQuery(
    - I- x2 S, l  @% L7 W
  139.         bstr_t("WQL"), # x6 J3 u- c8 r2 ~. `8 C
  140.         bstr_t("SELECT * FROM Win32_DiskDrive"),1 H6 F- W- r8 R
  141.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, $ o; C# {7 U4 I( }$ G. r9 l
  142.         NULL,
    - L) O! v( s) J- _$ G! _& C
  143.         &pEnumerator);1 V) M$ k' e# X
  144. " s5 S4 e: m2 N5 j5 T
  145.     if (FAILED(hres))# C; r0 q7 Y, f* I* h. U
  146.     {  @+ l1 A; `4 h
  147.         pSvc->Release();
    * V$ o: S/ N# ?
  148.         pLoc->Release();
    8 h7 Z+ S; Z' x& B& e0 E
  149.         CoUninitialize();
    7 Z; q  m" R2 ?% K, g, k
  150.         return 1; 5 u- V6 [9 C  d9 D
  151.     }
    ! j8 ^. i! B3 T
  152.     while (pEnumerator)
    / h4 e- A+ D7 b. d6 S9 m
  153.     {
    ' e0 X4 c) Q1 r+ ^6 O
  154.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, 8 r* B  k3 R5 q; x- A
  155.             &pclsObj, &uReturn);
    % I1 s5 d- ^) X- s' y1 y. a. u

  156. " j0 Y( p! R6 s: G# o  h. ~. d
  157.         if(0 == uReturn)- ^# C% L& {0 ]: x3 V" h0 B
  158.         {
    0 D" U- q0 i$ r8 M
  159.             break;
    7 C3 Y( {0 {4 V& t+ ?6 B5 W
  160.         }  P# A8 o) k) Q% u  y  M: w' [7 L
  161. # Y1 I! @5 s$ e+ X
  162.         VARIANT vtProp;9 E4 I* `# S5 |4 A5 \+ \- M6 ^
  163.         VariantInit(&vtProp);; T  b6 C9 ~* M% ~0 L' o* W! C- @
  164.         hr = pclsObj->Get(L"PNPDeviceID", 0, &vtProp, 0, 0);& A& A& e0 `2 _
  165.     strDisk=_com_util::ConvertBSTRToString(vtProp.bstrVal);
    - ^8 r) Q8 U1 d2 V3 m4 O
  166.     }- }3 S' Z# y: V5 J

  167.   Y( r( B3 ]( ?* d
  168.     pSvc->Release();
    ! x# v! U+ O* }" q0 R0 C% k! C
  169.     pLoc->Release();
    ! L2 v$ R2 p' W2 j
  170.     pEnumerator->Release();8 V  q7 y1 u6 Y/ M5 W+ |9 r
  171.     pclsObj->Release();7 W3 f9 Y# U; z+ m$ o
  172.     CoUninitialize();. C- `: g! e" k: l

  173. ; [7 f: ?, j  ?2 U  W
  174.     return 0;   
    $ `2 J7 t' u' t  C0 d9 u7 N6 s
  175. }
      ]/ d# n& P* i* f
复制代码
 楼主| 发表于 2010-10-11 19:21:05 | 显示全部楼层
本文代码经ccrun(老妖)在Win2k下试验成功.
' f: G$ g# t4 j) z
$ U5 |0 {3 A1 D& h( r- E$ V#include <WinIOCtl.h>
& ?; t# n0 x% E/ y4 `#include <stdio.h>
3 [9 t( O7 I4 d) E) v# X4 U9 m. r. t: {" V9 w
#pragma inline
+ p; W, f( K9 Z. v/ [2 n+ y//---------------------------------------------------------------------------
+ h1 H; `( R9 O) I) h7 \3 V// IDE NT/2000/XP专用变量
. e4 B+ N/ g( u2 _#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
6 s9 r. H; g1 R! N( K& _#define DFP_GET_VERSION         SMART_GET_VERSION
5 \2 c) \  o" c( C6 K) I2 Z' L#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND6 E6 j! D; z2 o  m4 x" r3 M6 Q; P
#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
* t3 ~1 e& K) P5 ~5 v5 ]! d2 {- P6 y' L1 h
const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令
( C: a& [6 ]3 |3 g# A' Q  |const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令; [6 _0 y; w& m" u

/ {- p& \3 k: h5 {: zconst int MAX_IDE_DRIVES = 4;
# A+ E1 H* p. A; T6 d
1 A% L* f8 V; y// SCSI专用变量
5 q3 N2 z' ~3 U/ t- wconst DWORD FILE_DEVICE_SCSI             = 0x0000001B;) {4 \, T: |% G% @% R/ X" ~: }
const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
1 H7 S. t  z% ?0 f+ [const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition0 L( W/ W/ Y. Z  y" s- d" e! |8 C
const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
7 M9 Y. I# D( C+ U- Z
8 o. T% E1 F4 Ttypedef struct _SRB_IO_CONTROL/ B1 x# X+ `+ r2 j# D
{1 V$ L" a; N3 z
    ULONG HeaderLength;8 W4 A# [9 ^: c
    UCHAR Signature[8];5 w0 V0 N; T  K1 U6 Y8 g
    ULONG Timeout;; i( [) }' y* B
    ULONG ControlCode;
+ a: n! |1 x. l, F    ULONG ReturnCode;0 z4 u  \4 T) g
    ULONG Length;; `, ~5 L4 i! W4 B9 p8 Z4 Y+ C
}SRB_IO_CONTROL, *PSRB_IO_CONTROL;
- A& X2 u# E: Y; `1 N( q) H5 ^3 q# o( Q/ v4 p( k
// 读取的主函数( f- y% B% ]& v$ Y- R2 H
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);4 R/ Y+ [- ^. y

6 F$ o% `! Y. V" ]! p+ K// 辅助函数
: E, u$ n0 i5 d7 A. E0 ichar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
% D8 W/ {; M' E" {; W// NT/2000/XP函数
; G- n: G1 T, B7 B6 @+ F$ U# bvoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
0 R  o0 c5 Y3 X) j( }( ibool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
1 M$ g) ?, q9 o8 u, L! C/ j        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,, P. ], |3 ^" y. Y6 b* U, _5 m. M& D
        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
- F7 p0 D4 S8 A" a8 S// Windows 9X函数
& l; H8 y% p0 c1 C  u% ivoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);
' t: j: X) K& F( T% r. z+ ivoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,  E# x, K# O9 w, K1 y- f% u& }
        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
+ J4 q0 |4 y, q9 G% G& Y8 z  N" x3 O1 m0 |# ?
// SCSI读取函数(for NT/2000/XP)
7 r# x: A! O+ s* E$ W: M7 b/ Y0 AString __fastcall ReadIDEDriveAsScsiDriveOnNT();; Z& W6 O% a8 r
//---------------------------------------------------------------------------
" a  |0 \5 g( R4 h// ReadPhysicalDrive
# b1 L$ ]6 M- P1 ]  r( jvoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
2 I: @$ I7 a% O2 j+ P& @. f{0 c* v9 j+ j  \- j6 ~  a8 V
    switch(Win32Platform)( V- `0 y) U) s+ b4 Y
    {6 P4 y3 f, X# \/ `
        case VER_PLATFORM_WIN32_WINDOWS:0 K. w% M( O6 [# S# j6 |3 \6 y
            ReadPhysicalDriveOnW9X(pSerList, pModeList);1 ?, B0 T3 X, a3 g$ B* m( D8 l
            break;
2 ~; T* e6 A, b; A* d* r/ D        case VER_PLATFORM_WIN32_NT:, }. n; C. I3 ]+ ]
            ReadPhysicalDriveOnNT(pSerList, pModeList);
1 D! p$ L2 ?" X# w  w            break;" d# F9 v( k( R4 E5 H8 _
        default:5 D: Q' O0 P5 c$ z/ V. v
            break;) P1 Q2 [% L1 g$ I6 {1 S- h
    }- U$ B, L; O+ f! W. v
}
; @6 G+ n- ^* P  B% Y; M5 W& v//---------------------------------------------------------------------------
/ W! c& Q/ _' m) M+ Z5 Q8 [5 i0 x( E% Y// ConvertToString
: }* U. C7 v1 Bchar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)5 N2 c  @- g9 u' ~
{
; c! N/ k! T+ u# y' N7 H8 a+ W    static char szResBuf[1024];
9 V3 ^  M+ I& y4 R! T; `7 m7 D    int nIndex = 0;
; E, J2 e$ Z' O  G5 K4 r    int nPosition = 0;$ e- p- {) O+ S

% R# e9 }' x* Z  k3 }    // Each integer has two characters stored in it backwards" Y+ y" e% y! e2 D6 C
    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++). X6 \: i7 m9 w# _/ J- K
    {8 [, P( W: M: k! c: H; i3 @' z
        // Get high BYTE for 1st character5 I& Q1 ?1 T3 C# q- R2 N, K1 L
        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
6 `) V6 H7 Q2 \. ~2 Y4 I: j$ w        nPosition++;
9 ]1 j4 X) X7 U; p2 G+ w
5 e8 }2 b& M9 o2 r0 [! I        // Get low BYTE for 2nd character
. z7 K/ ]8 v# K6 I1 E% }        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);: Q% Q$ S; j7 e4 W' u3 V; B
        nPosition++;0 |2 H9 r6 A! F$ @' n+ X4 k
    }7 q& x$ b" a, ^7 X3 ~( {
5 j( q% M" s! O2 O
    // End the string8 i# Q7 W2 ?/ v' \$ d
    szResBuf[nPosition] = '\0';2 r6 y3 E; T% K6 s1 T
" H- x, g" Q: {2 M( f  s; i7 K
    // Cut off the trailing blanks
) [4 Y( N  i2 F! ~! G  F    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
' ?* p: O5 `  V: U8 E( b& g) Q4 N        szResBuf[nIndex] = '\0';
3 c$ I3 t5 k; Q$ T/ `9 G  o5 x' ?! G
    return szResBuf;$ M" n! w6 W$ }( Z% x
}
* E' |0 L* ~  l, o1 y  m//---------------------------------------------------------------------------
- r9 e( Q! S3 U! M3 k. `" G9 l// Winndows NT4/2000/XP 代码
7 G6 V6 _; y) B/ u//---------------------------------------------------------------------------0 Q, f% i6 l8 s; a2 B
// ReadPhysicalDriveOnNT' Y; o7 Q! d# h! B) x
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
- U  C$ h' P5 R2 P{9 t9 Q. S" A; N
    // 输出参数; ?6 H* x8 w! u5 [3 m1 D
    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
' [: P" s! R2 r9 {5 j  o4 L
; v0 a/ x" i9 {0 v    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
& J% Z" y9 q* A9 v+ K6 ?( i# b    {
* A0 J7 v4 t9 p8 W1 t: d$ I        HANDLE hPhysicalDriveIOCTL;& V  {: Q, ?0 `; e! D1 P% L
        char szDriveName[32];* a/ {* n, ?3 n+ p. E$ d- U- R
7 _9 r1 T0 f: G  z5 t
        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);- _& ^% y$ k" j# f9 m- h- ]
        hPhysicalDriveIOCTL = CreateFile(szDriveName,0 x5 U7 |+ A- ]. V6 f
                        GENERIC_READ | GENERIC_WRITE,
/ @5 h/ r# w7 a( f9 |2 p" h0 o                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
! i9 }) Z2 `% [" V0 y" `5 ?                        OPEN_EXISTING, 0, NULL);
4 ?2 C5 y: e' _% W
  g, E- t+ Z/ q' A        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
  F7 U0 ~1 C) E% U7 l; a1 K, K! K        {' `' K5 u% N# U' J% Z
            DWORD dwBytesReturned = 0;
: [& X# v7 U  V* u1 t* u+ p+ `            GETVERSIONOUTPARAMS gvopVersionParams;0 a6 T4 O( n1 `+ |
! e* f+ D3 [& E+ q2 n& i! @2 p/ f# a
            // Get the version, etc of PhysicalDrive IOCTL
7 C% L8 t# G$ g' E. q" W            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));* b1 m+ }$ q# n/ F) Q* z3 |

" m: O; [  J- N            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
/ A5 O" _4 {2 j+ S1 O3 I* ?' T                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
6 `8 Q' r" H* s, J                    &dwBytesReturned, NULL))5 s1 r1 E$ ~' G, e3 ?/ I
            {
% l, O+ c9 r: E& ]                continue;) H+ b8 A$ c/ k) P% d. ?; E3 p/ q
            }
' k5 z! {0 p! `5 j* f$ _* [. i: h/ N: W. \9 S0 \6 \
            if(gvopVersionParams.bIDEDeviceMap > 0)" q& U. A2 y1 R- v7 Z7 J
            {
% m2 M5 m8 K9 C) Z. H$ K                // IDE or ATAPI IDENTIFY cmd5 X' A, V9 x* s. V& t
                BYTE btIDCmd = 0;
& h! _  J" c# \) N                SENDCMDINPARAMS InParams;8 `5 _7 \" D& V8 |7 b/ ]8 c: Y
                // Now, get the ID sector for all IDE devices in the system.
) Y- l$ A* ~& h! q                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,! G$ q& }( S7 v
                // otherwise use the IDE_ATA_IDENTIFY command3 g4 Q9 a: N. j: Z2 S9 V7 z5 }
                // 具体所得结果请参考头文件中的说明
. o6 X, y7 r/ `                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?8 r  K: d1 Y' _, E# m/ T
                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;8 n0 C  c8 j3 n2 J, h2 T1 Y4 i
                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));: m0 k( ?+ M1 `9 h+ \) J% ~
                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));* t4 M, e$ e3 f4 [, o3 D( m
5 |. Y* h* |) O4 ?. p; J9 j- W0 ?
                if(DoIdentify(hPhysicalDriveIOCTL,9 W: m  h' \  g; G- d, ~
                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
+ F, t2 O* ?% n' ^5 ?                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
, d6 E: _6 f5 ]1 L- }& w) e8 n                {
- N6 r$ R* v! R) b4 v8 G5 K7 b                    DWORD dwDiskData[256];
. U7 a0 |0 t( D9 N  W, X3 c4 b                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件+ v4 H  P' J* G, w7 O$ N
                    char szSerialNumber[21];1 X8 O: G/ z2 K
                    char szModelNumber[41];3 V1 k6 n: e" \! V9 a
; b$ ^7 N  v" B+ u4 B+ {  p
                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;5 i0 I& i5 l- B% ^
                    for(int i=0; i < 256; i++), _  l, C1 B. n: J) Q+ X7 q+ X. Y
                        dwDiskData[i] = pIDSector[i];
2 s, b0 G" J# w% g) K                    // 取系列号2 R6 v1 D2 S' Q2 E
                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));8 y  z1 |0 |& `& A' J5 l" [& I
                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
# a% U/ S/ t! {' B8 ~2 b' m3 n1 t' r9 `9 e3 u+ a+ s% i) Q
                    // 取模型号
" ^% `8 [2 H- E) c* n! u. V                    ZeroMemory(szModelNumber, sizeof(szModelNumber));
' ~. D1 R7 O. H2 S2 P8 n% m+ G: X                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));1 g  _9 T$ f2 f9 r- r
' t! ?$ `, l6 H7 U2 ]; L
                    pSerList->Add(szSerialNumber);
: f1 a7 H3 \- [3 B  O. w                    pModeList->Add(szModelNumber);: G+ [9 _, _( D* o! l0 T5 f7 H1 I7 K
                }
; z7 i2 Q, }8 i& Q0 I1 Z8 p7 X            }, |0 u6 \' ~" u$ S# _, e) c
            CloseHandle (hPhysicalDriveIOCTL);
7 M2 V3 d1 f+ p        }
+ u- a6 q7 q2 Z) o- n! f+ R6 i    }, z4 O0 X( A% Q% d) |5 L- x) i
}: W& u5 m8 O9 L6 n) X
//---------------------------------------------------------------------------! s1 I8 I. o# u7 K- B
// DoIdentify
) V! O* a+ E1 ~& Mbool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,5 |0 T8 H4 _4 _/ p- D
              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
7 M3 }! B- ?: j9 l              PDWORD pdwBytesReturned)( v7 p6 R. ?! r, U9 \
{
  l) D) K6 I* p- e* M3 n! ^+ Z    // Set up data structures for IDENTIFY command.. Y0 ]% K1 g2 `
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;9 |% C3 J  e" P0 t; s1 W# v( L
    pSCIP->irDriveRegs.bFeaturesReg = 0;. N, t. Z: Q# K; p! Z; {
    pSCIP->irDriveRegs.bSectorCountReg  = 1;) m( |7 G6 M7 C
    pSCIP->irDriveRegs.bSectorNumberReg = 1;
7 g, h: Y* x) D4 `6 m    pSCIP->irDriveRegs.bCylLowReg  = 0;
9 J) |; M# d: Y4 V( k, |1 d    pSCIP->irDriveRegs.bCylHighReg = 0;
! C+ r" D6 [$ ^* M; M
1 \2 p- h7 ]$ z- ^+ f/ k$ }% |    // Compute the drive number.(主盘和从盘所对应的值是不一样的)6 w& c  C0 o9 z/ p- C' N9 o
    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
- u* u) d2 l, l+ b( _3 ]+ z" F4 X7 g7 f! o5 |7 v: U
    // The command can either be IDE identify or ATAPI identify.
# a; B0 K; L7 B    pSCIP->irDriveRegs.bCommandReg = btIDCmd;% v/ G" s/ y3 y
    pSCIP->bDriveNumber = btDriveNum;* ^" S3 v9 H7 ?. F8 @, L
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;' v) L8 n) w& p

0 k" P/ j* \1 b9 `* Z$ k$ k( g    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
% p" ?8 r! g& w! _3 L1 e1 H           (LPVOID)pSCIP,1 B: N  U0 a2 h" x  B% r
           sizeof(SENDCMDINPARAMS) - 1,
  h0 o) i& d$ W2 v7 Y! q  w           (LPVOID)pSCOP,
* i* U* s' g: B- v" M( j           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,7 k! r% T9 B- {9 ^% F
           pdwBytesReturned, NULL);
% |. ]9 K% j6 Q" u9 O- Q9 H1 D# [}
( o- T& a7 i7 B, {//---------------------------------------------------------------------------
5 V) Z+ F% E: m, h- Z+ _// Windows 95/98/ME 代码
) T( h" i3 q4 M1 x//---------------------------------------------------------------------------1 L% C. u6 U7 C3 f1 O8 W6 x) Q; N
// ReadPhysicalDriveOnW9X% r# E0 |0 G- r/ X
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList), R, [& _* j4 P. i6 |
{  I) ?" X% ]! P( |% B' d- c
    WORD wOutData[256];
# C4 i% C+ e' {( P, q* C    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
* _1 A' P( I8 T: D* E# T$ C2 l3 C
1 \1 n, y1 ^0 |8 ]; q    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
5 g, Z0 M+ Z& {. R  R    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以& q8 x& j# {3 k; {0 O
    // 避免蓝屏的出现。(期待高人能指出原因)
5 X! G, T) }. U0 ~    for(int nDrive = 0; nDrive < 8; nDrive++)7 H3 W) Z8 N$ H2 n6 t
    {, j. r8 Y6 s- a4 M; w
        WORD dwBaseAddress;! ?1 g6 N" j) s) }# h; ?
        BYTE btMasterSlave;         // Master Or Slave& r  r6 t+ _0 W5 D6 p5 ]  ?) r
        bool bIsIDEExist;
7 H  ]# ]  u7 u        bool IsDiskExist;
, d, l) @: M4 d+ h$ b- e3 Q! T
! K: b4 g/ g5 q; ?& s" M& u- y6 S% h        switch(nDrive / 2)
: b0 ^3 ~9 m8 s- i- P- W5 }        {
6 V8 t2 @7 x5 G% _) G            case 0: dwBaseAddress = 0x01F0; break;  A0 z, R" {9 L. Y  Q
            case 1: dwBaseAddress = 0x0170; break;
4 U# h6 }8 I' B, w$ S            case 2: dwBaseAddress = 0x01E8; break;
) B8 q( n+ X4 t- s$ @- ^            case 3: dwBaseAddress = 0x0168; break;: F  w% M2 e" j1 a+ r
        }
$ t) V' d& O8 _, c  _5 |" x& u8 x3 O: U7 S: e8 M) R
        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
0 B7 [! O0 T+ I* m& u8 W7 U4 I' `+ a9 x6 v5 k
        // 进入Ring07 e( I. }& y( C: m0 E7 y
        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,0 y1 Y" @/ w) V) c9 H
                bIsIDEExist, IsDiskExist, wOutData);; k# B( y; k' \
    }0 b3 r/ N0 V7 F- T" t" P" G

  b8 C9 I! @2 R/ U" y4 Z$ ^    // 开始读取
$ P" V. g" m0 B7 |; R    for(int nDrive = 0; nDrive < 8; nDrive++)
; g; C, e  Y8 c& U    {2 q1 E" P, R2 [" m2 |2 w
        WORD dwBaseAddress;
" d. C& ~$ H+ C. s, T. D" g0 t4 {        BYTE btMasterSlave;         // Master Or Slave
( x4 c6 k( J! }- U" ]* T1 x        bool bIsIDEExist;
. R' P! y3 y6 `! p        bool bIsDiskExist;. g& Z" l( J1 Y% e; H& s2 U
        switch(nDrive / 2)# H' W' H  V/ F2 z8 [
        {! v. x7 M& b: q' h) G' F
            case 0: dwBaseAddress = 0x01F0; break;* T" q: v8 K* T2 m- u
            case 1: dwBaseAddress = 0x0170; break;  n7 i: I( a" j, k+ H; M. `
            case 2: dwBaseAddress = 0x01E8; break;
7 y" O' A. Q* B+ R/ Q  q( H            case 3: dwBaseAddress = 0x0168; break;" N! L9 ~! _6 ~; s* h' |- D
        }1 h8 a; l+ E7 T) o) w" `
, x6 S3 W4 E! [, p( C
        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
$ x# t* V  }& @. ^
. |+ R& u  W* H* ^6 \% d' _9 ?        // 进入Ring0
4 R( N2 ]; z$ y8 n        bIsIDEExist  = false;  _) j, o+ i8 p2 F8 z4 P' }
        bIsDiskExist = false;% q+ u8 P- O7 b8 l. n5 a( m6 N
        ZeroMemory(wOutData, sizeof(wOutData));
( E! K$ h/ s( n% \
! [1 `5 Y* u2 W  V' c# A3 j1 K  \        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
5 `2 r+ _9 r; r+ k# T) o& R' e; T                bIsIDEExist, bIsDiskExist, wOutData);
. P4 Y" B' e3 `, K" M
5 v& D7 W  R6 Y        if(bIsIDEExist && bIsDiskExist)2 E0 I* e( |. G9 l7 L( t0 H
        {
* n! I) i( Y5 Y& b            DWORD dwDiskData[256];
! V/ F. ?, h9 c3 f( `            char  szSerialNumber[21];
; w4 J! e/ D3 r. q. l3 k  r% y            char  szModelNumber[41];
& H2 \1 q3 E# ^6 ^9 r% R- T6 o* ?! r7 M& m- D4 q4 w5 n
            for(int k=0; k < 256; k++)4 b7 h" _2 O: S2 J1 O
                dwDiskData[k] = wOutData[k];
1 D# X  \% _' O" R
* D7 d1 n1 W3 l; Y# Y9 a# @            // 取系列号- S0 [1 A6 q+ y9 W9 u
            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));+ O) w$ M0 F! ?9 N. e1 _
            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
7 U/ M. t2 v" G' S, p) y' @" r/ E. Y9 V# t& E9 G  L5 V
            // 取模型号
2 S: B6 _4 T  X+ ?3 ~" |            ZeroMemory(szModelNumber, sizeof(szModelNumber));
3 c  |! D& [1 O            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
5 M0 r: y: {! ?/ a) l, Y' D& [, ~3 G0 B/ v
            pSerList->Add(szSerialNumber);
3 d! X1 ^* O: w% `& h0 x            pModeList->Add(szModelNumber);
! c4 K3 u( o0 H/ M% K5 \( u        }
, S2 w' s/ t7 q$ ^( M% b. t    }6 ^% d( s' t- U5 I) T
    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);. g: ^$ Y0 i: y" [( `
}3 S- R0 D3 M, ?
//---------------------------------------------------------------------------
9 m$ N8 v6 L6 q' Z2 L) t// 为防止不负责任的转载者,在此注明原出处信息,请见谅。
! Y# w) `+ }- f// 资料收集整理:ccrun(老妖),欢迎光临C++Builder研究: http://www.ccrun.com
" C1 ^0 o2 z+ J. I: H2 G//---------------------------------------------------------------------------
, @, g2 a: B4 \  d2 e! z3 M// ReadPhysicalDriveOnW9X_Ring0()
8 ?& n+ G" Y# O; B" @' A) U. `9 w1 Z$ \//
$ l9 L7 h% o( Q0 m( D$ M// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h" V, I2 E8 Z$ r# V. v( n
// btMasterSlave = Master(0xA0) Or Slave(0xB0)
. Z/ D0 D" T) {; H" {" A: C7 H//---------------------------------------------------------------------------
( B$ o; e1 \+ J) K$ ]void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,# |2 e3 k* w- N
        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)4 m0 l6 H% i0 Y
{6 S7 L! a8 a0 k  X
    BYTE  btIDTR1[6];
+ Z$ a# D8 h- l    DWORD dwOldExceptionHook;
; q5 I" p/ N: a5 u& d% `0 N    const int nHookExceptionNo = 5;& A9 W$ ^$ C& T2 _' A) H
: ^' T7 P3 S" e2 w; p7 K9 P
    BYTE  btIsIDEExist = 0;" g2 I/ x" e6 d0 n7 ]! q( B6 ]
    BYTE  btIsDiskExist = 0;
7 w: {5 P/ u- d& X$ x    WORD  wOutDataBuf[256];6 X/ f; k( [+ B& z: X

" M1 V3 K/ x& j& a% R* `) _$ G    BYTE  btIsFirst = (BYTE)bIsFirst;
/ h$ B& K1 U' y# e
6 e- j7 n  \( _5 d4 ^' X: r% o! h    const BYTE btBit00 = 0x01;0 a0 {. H9 P( o9 {! c" L
    // const BYTE btBit02 = 0x04;
  f$ Q! Q6 l" f% q1 g* T& y! |    const BYTE btBit06 = 0x40;+ m9 u0 f1 W% K2 p/ D: }, s- Q$ E% u3 n
    const BYTE btBit07 = 0x80;- g/ X& R, d1 c5 S$ z
    // const BYTE btERR  = btBit00;
6 Q% R1 [' f6 W; `. m    const BYTE btBusy = btBit07;1 Z; H8 c/ T5 Z8 s* p
    const BYTE btAtaCmd   = 0xEC;/ |$ v8 V+ W" |1 W( l
    const BYTE btAtapiCmd = 0xA1;3 C6 m* U" _- p6 e3 k8 i# h

; b: [$ l( _5 ^6 G& J0 J# z1 i9 t    __asm) w: s2 k; L7 D" y$ b' @
    {2 Y7 \  X4 ]2 a3 d2 r# L. W
        // 必须先执行这条语句: X9 H2 c0 q: i2 a7 N
        JMP EnterRing0
# x3 S; I6 I) y6 l% q3 J+ s9 M% b
) d& b4 }2 H, k" s$ r/ s8 m/ n        // 定义过程
1 o. D0 I$ c; x* [; R; f        // 等待IDE设备直到其不为忙为止' Q( k) [0 k1 ?
        WaitWhileBusy proc& M4 M1 \1 V4 g4 F' O; I* J
2 C( v- N8 j! Q, S
        MOV  EBX, 100000
5 I# N' D  F8 G. t: ]        MOV  DX, dwBaseAddress
3 d8 F  `+ b4 |/ @        ADD  DX, 74 I: u" L7 b6 R! c# R+ Z& M/ f# ^' I
; x( f7 G9 W0 j( w+ b6 x& ]6 ^
        LoopWhileBusy:
) X6 d1 q, R8 i# o9 L4 d
, M+ r4 g) F2 q/ R( P        DEC  EBX3 g6 K% H0 B5 x3 ?, I
        CMP  EBX, 08 f( J4 F1 E3 v( W
        JZ   Timeout
2 \; C2 Y$ c6 R1 W; N7 n* X        in   AL, DX
6 E& _) x7 Z  C/ p        TEST AL, btBusy
8 V9 s" D% j/ l5 j) U0 Q7 u' @        JNZ  LoopWhileBusy  x  a/ `# u' b' f# h' v  m' _+ ]# H
        JMP  DriveReady. ]% f9 o& q% N1 ]- m% `

8 M( o8 [1 }5 h        // 超时,直接退出  ]( x% z  i8 E; \; E
        Timeout:
3 e8 A0 c" d- x. I  ?/ s        JMP  LeaveRing0
$ M% H8 ^) R: ]1 X' V& }7 P' I        DriveReady:
1 a' N2 M7 P1 `' K2 ^3 A9 e        RET  i: e6 J5 j2 X, Q4 T+ w
        ENDP   // End of WaitWhileBusy Procedure
8 d( ^! I& M: b2 E
, L" i4 `; y  y$ W2 R& n        // 设置主盘和从盘标志
# M" v; o- ?% w; s4 ]3 k        SelectDevice proc
, s; D- b0 a3 _+ q3 Y1 w# I' T: v% [8 A7 b% n
        MOV  DX, dwBaseAddress* w0 y' B9 O& [4 P" z0 I" Z* v3 E
        ADD  DX, 6: j3 ~0 }  N! j8 `/ t
        MOV  AL, btMasterSlave" L: I* `, G' y0 o' h' Z
' c. n9 m' M5 Q+ R6 Q  m, P4 Y
        out  DX, AL! }! i3 p& s6 t4 |4 l9 A) R" D+ |
        RET
) D4 {4 I3 E  @$ ~. c0 Z6 s7 f# Y/ f! |. y  X
        ENDP  // End of SelectDevice Procedure* f4 O5 l* M2 i- u) N  e

& {; q/ L" N( s        // 向IDE设备发送存取指令
* ]6 E9 X0 V$ B* t" z. q        SendCmd proc
$ j: I) D* [4 m! c4 b1 \
5 e2 i2 n' O9 F* K        MOV DX, dwBaseAddress7 I8 ~  X+ H4 K  D
        ADD DX, 74 H/ ]! F: U% S3 f+ _, k/ X
        MOV AL, BL // BL是主从盘标识,在过程外设置5 O& \7 `0 W. n5 q' E& Z) n9 T
        out DX, AL% N1 p1 ]; z6 E% I& }# Z
        RET
) @8 l4 M2 b; c3 k: J/ _* b! {        ENDP  // End of SendCmd Procedure* \% i; r8 ?/ w  C0 m* l  q
7 r1 B; D  }0 \  [% z! r/ |: u2 r* p
        // Ring0代码
6 x* b  n, i0 Q% X2 i        Ring0Proc:
0 n$ l; B# K& E% }2 r* Y8 @; ~        PUSHAD& T7 T/ Z1 j0 k/ \$ e2 i
        // 查询IDE设备是否存在9 c" L3 ?  m3 S/ D% `+ a
        MOV DX, dwBaseAddress, {* O: j; K: u& o4 U
        ADD DX, 7
9 C, U2 U* }  d% J5 I6 q        in  AL,DX) A% a5 v" y9 q

' W& B$ B  @' q4 A4 ^1 ]        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回( ~$ E3 G. G! ~- L6 K5 `' `' U
        CMP AL,0xFF
% l. i5 y. a4 E# A. |6 R% H        JZ  LeaveRing0
/ V6 R& D/ e$ }8 i, @+ x7 l        CMP AL, 0x7F* V7 N. q" r5 D. J' }0 a1 ^
        JZ  LeaveRing0
5 T0 R* K6 t4 P
% g# l8 S) l8 V9 z        // 设置IDE设备存在标志
8 q3 Q) B  U1 ^0 X3 Q% ]& h% q        MOV btIsIDEExist, 1! g0 ~0 @; |! O

6 b( z% w8 ^5 p% @. X. M5 ?        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面): B; T; o$ v6 z! Q( a6 r
        CALL WaitWhileBusy/ z. g- [/ Y$ c+ F
        CALL SelectDevice
8 r! O/ }; n! u) {. A  g% {
( E3 O  D1 a7 }; |, a1 d$ N        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
  R3 [1 E! q% {* @9 n        CMP  btIsFirst, 13 w5 R( B2 n) m. f4 ?
        JZ   LeaveRing0
4 w5 K3 O- [1 w& S7 U
6 I! l0 z3 ^! Z4 @+ o* S# Z* i& m8 a        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???* n( n' |. E9 s; _
        CALL WaitWhileBusy, M  m% [4 L, J+ M+ A
* o' Q# M- T4 H
        // AL的值等于cBit06时,不存在驱动器,直接返回1 ^( r$ W% d- l
        TEST AL, btBit06
+ q6 P4 L+ }, W* U" n3 }4 W        JZ   LeaveRing0
  Z2 r% w: V7 I/ C( W: g2 n# _" B. }- Z4 q3 r* [7 J
        // 设置驱动器存在标志
9 }4 |& x; p- `# ?        MOV  btIsDiskExist, 1
4 e/ X% |* _, @! P( Q8 t0 l' T" _& v0 e! D+ q  M( T
        // 发送存取端口命令
; g- i; t0 q* P2 c( l        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,) s- f. Z8 O& p, K7 n, h$ h* s
        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
6 a* }9 }$ ?1 u        CALL WaitWhileBusy
. o1 V. U( C' b0 J$ d) Y        CALL SelectDevice    // 设置主从盘标识
% w- f& R7 e+ D( {2 G% A- I        MOV  BL, btAtaCmd      // 发送读取命令
5 F: I2 m+ |4 z) N; F        CALL SendCmd/ O/ B: ~( x$ D$ O, a$ A* n
        CALL WaitWhileBusy
/ q+ _6 _( z. O7 T) i$ U! ]& v6 ^" D% c3 P" U
        // 检查是否出错
0 U. m4 j/ n% w! v5 R- g' U        MOV  DX, dwBaseAddress
3 P$ [% f& c, H8 V$ D4 F8 F5 f        ADD  DX, 7- q. t- D! p# R5 A: m2 d/ T/ }9 q
, o+ z) x$ S% n3 [9 I) c& O
        in   AL, DX+ {, t, B' i" Y% d( W

" k4 e8 Z3 e4 N/ w        TEST AL, btBit00
# Z* \$ W6 G( ^1 G1 \& G$ s        JZ   RetrieveInfo   // 没有错误时则读数据! I8 K2 [  z; U3 s" I& x, q' i9 F
0 c' V. n# [  {  p$ A9 o: \# M
        // 如果出错,则进一步尝试使用ATAPI设备命令( I$ c" ^5 G  N* J2 A
        CALL WaitWhileBusy
6 P; \& ?5 V# ^& v/ a$ z        CALL SelectDevice- P! B  X6 r0 G& F  `( m
        MOV  BL, btAtapiCmd
( C; P( k' T9 a        CALL SendCmd8 ]7 |" b$ a  F) y! w7 H
        CALL WaitWhileBusy
4 U5 @6 e8 I# l. }  ]- s1 E& q6 ], p" t/ ]& r
        // 检查是否还出错
! _8 [4 h) W7 A  k- F$ E+ w+ }        MOV  DX, dwBaseAddress
" ?; U8 R9 l$ K2 Z8 \9 A        ADD  DX, 7% y. i8 H- K1 K, Y' |% V- F
        in   AL, DX& m9 \" u$ v* J* w' y/ X" L( u
        TEST AL, btBit00' z9 V. r1 O" S5 t" j) B6 U3 a
        JZ   RetrieveInfo   // 没有错误时则读数据' o, D6 q  Z0 w( ^
        JMP  LeaveRing0     // 如果还是出错,直接返回4 \7 d  z8 B7 h9 E. y8 n1 x

  r% h+ B/ e1 _: Q5 Q        // 读取数据
' ]4 b* K- E" F9 t        RetrieveInfo:( w' i! A( m4 [3 P& d- X6 ]2 |/ Q8 t

/ f# `' g% s( y7 K: J! h7 r        LEA  EDI, wOutDataBuf: B( O& C' v( V! X1 ~' u! p
        MOV  ECX, 256$ n. ?) E+ F* M7 \# R: h: \
        MOV  DX, dwBaseAddress
; u/ e0 u& y& i* {* f$ T+ V        CLD
( m7 @! W/ u6 }+ v, |  e7 ]+ S: W! e( `& h: Z! f
        REP  INSW
% u# U# {) [& [2 K8 ?% Y8 X# j9 Z9 [1 e8 J1 o; q8 }
        // 退出Ring0代码+ ^; ?7 a( v9 P. a5 w: @1 X# O
        LeaveRing0:
  h7 B0 U5 J! v( o9 \7 N' q9 |* \$ Y7 k. b
        POPAD
, P& v6 }1 G' O7 q$ t5 ?: `4 I        IRETD
0 d; Z* C( R8 u  A/ m( E& L) E) L- j% {3 _& E
        // 激活Ring0代码9 x5 \: \( D3 n( {! H
        EnterRing0:
* N9 U, ~! S% J8 U0 Q, ~7 T3 @/ `8 w$ T: j& x
        // 修改中断门
4 |. L8 o1 T! y9 \! Z, b        SIDT FWORD PTR btIDTR1, n9 C' o& }3 r! a  A! @3 L2 {  h5 c
        MOV EAX, DWORD PTR btIDTR1 + 02h
- W# v6 y- a+ R0 x/ B1 N        ADD EAX, nHookExceptionNo * 08h + 04h, K; C6 ?+ j7 [- J# h- S, [
        CLI( b. q2 a1 J3 n# l
% c: |. Q# W- r) g8 u
        // 保存原异常处理例程入口7 Q, f3 U! Y0 t$ d, u6 h+ @
        MOV ECX, DWORD PTR [EAX]
8 h$ P3 L3 Z# G        MOV CX, WORD PTR [EAX-04h]9 f0 y9 l$ c5 n$ w0 X9 }8 ^4 K
        MOV dwOldExceptionHook, ECX, b$ _9 x; D( T1 C- @# [/ |4 \) h. a- I
( p! b4 E/ k+ ~/ E( e2 R) r
        // 指定新入口
' m3 y1 J# R+ f5 ?6 `  U, E' j7 Z        LEA EBX, Ring0Proc, U4 D$ }3 ~& o1 @
        MOV WORD PTR [EAX-04h],BX
9 Z: J$ [& C# |& S/ D( a        SHR EBX, 10h
( j$ F* @% e" T3 R3 @5 d        MOV WORD PTR[EAX+02h], BX
7 w+ B" B) l2 k* y
7 ^7 e' i9 {; @1 J6 d        // 激活Ring0代码1 Y9 p6 i) K; B( ~9 T- W4 o
        INT nHookExceptionNo
# Z1 d6 B8 X) U
2 Z  S+ t( ~8 j* P        // 复原入口
+ G$ |8 R/ Y; @* X5 g; K2 z1 n        MOV ECX,dwOldExceptionHook
4 A* o; |6 ~- {& C/ Y8 H        MOV WORD PTR[EAX-04h], CX
6 z2 d) B6 I( |6 S7 z. \        SHR ECX,10h
7 B$ c. P% @' @1 T- I- R5 Z6 j& w& `        MOV WORD PTR[EAX+02h], CX
4 A1 o3 A: C, c' Q        STI$ S1 m& e  A, I' j
    }
7 R8 v' `% S7 k' ~4 v    if(!bIsFirst)
% D, c) `- f/ h: @" y7 ^' \) D    {# d/ H% D4 U- A' Y& T: ^
        bIsIDEExist  = (bool)btIsIDEExist;
& a  ]9 d) V3 P        bIsDiskExist = (bool)btIsDiskExist;4 K% L( ^7 b4 ~# F3 A1 G! z
        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));, C6 t5 F" M3 ~$ v# s6 G
    }
/ k. ]& Y( w  @/ L& h3 E}* r6 x* F7 {7 t% w% @
//---------------------------------------------------------------------------( J: S* G2 x7 \" Q& a
// 调用方法:
" Q; U9 Z! C  O- \; Qvoid __fastcall TForm1::Button1Click(TObject *Sender)
6 [; z6 [# O; o6 o3 N! d{+ H5 f- m3 v( f5 t3 u( h
    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);+ B9 Z  y; ?! u( s* W5 {
}
* U# [6 k: T4 k$ N# M) l
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-10-2 00:15 , Processed in 0.021331 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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