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

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

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

  1. & ^; p1 j: n  ^7 c# u
  2. #include "StdAfx.h"
    . y" J$ I6 i7 X/ Z) K7 Q
  3. #include ".\puiddisk.h"
    " G2 u' X1 F  C3 I. w8 c
  4. #define _WIN32_DCOM( b# a$ {* h8 M
  5. #include <iostream>
    8 U% [4 p) g) U0 ]: e
  6. using namespace std;  t) S. g+ Y0 F' I
  7. #include <comdef.h>
      x2 @6 w. ~7 I+ h5 b
  8. #include <Wbemidl.h>/ _8 v; C9 m  `+ K. U: s
  9. 7 ]; u. a6 t! ~& x! K& w! N
  10. # pragma comment(lib, "wbemuuid.lib")
    4 r& p) K4 J: F% b' ?3 Z0 U, ^
  11. CpuIDDisk::CpuIDDisk(void)
    5 M( |5 g4 s1 _" d( g
  12. {
    + ?8 T7 R. {! {/ i
  13.     GetInfomation();
    ; T) k! }& X: M$ y& i
  14. }
    . ~$ F* h( H6 a" g% s# w

  15. ! t1 L" D* S! U# u1 g  `# u/ A: j
  16. CpuIDDisk::~CpuIDDisk(void)5 M; H( Y  d6 |( S  N# B7 h
  17. {$ W( h) u# V$ M/ I
  18. }
    ; {9 D9 X) a4 e) H* W" M' L( Z
  19. int CpuIDDisk::GetInfomation(void)6 i+ B- [! D1 W1 s# W5 A! K4 F
  20. {
    0 ]; R$ b- n5 _/ j
  21.     HRESULT hres;
    9 T" k! K6 r) i' U
  22.     //步骤1:不是必须的,COM只须也只能初始化一次
    : l" W$ d0 ]& r8 a! L$ g' ~: B1 b) n
  23.      hres =  CoInitializeEx(0, COINIT_MULTITHREADED );0 T4 b+ n% H7 j% I9 Y
  24.     if (FAILED(hres)): [" k) ]4 r9 C) Y- I  [
  25.     {
    ; V$ n$ R  B8 m( M
  26.         return 1; //初始化COM异常:注意,COM只须也只能初始化一次- k1 p( a+ {0 X
  27.     }9 N- _1 g$ p: U0 T1 z6 `% s
  28.     //步骤2:不是必须的,COM只须也只能设置一次/ D0 v8 b* _& \& I7 M* z2 r6 l
  29.     //Set general COM security levels- f% C  R3 F, X/ D' [
  30.     hres =  CoInitializeSecurity(# a% l' \- ^% O# }! |5 x
  31.         NULL, . a6 W6 y5 v$ `' o, u+ {
  32.         -1,                          // COM authentication, A: `; p) P( l7 M
  33.         NULL,                        // Authentication services
    8 ~9 m  c+ ]# u% O- x( D" Q7 y
  34.         NULL,                        // Reserved
    ) h1 O9 D7 V& D3 v  C  U* m8 P2 z
  35.         RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication # r/ X" M. S, G' H. E: |
  36.         RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  
    # T, ~3 v4 ?! @- o( `# Q9 m' \
  37.         NULL,                        // Authentication info
    ) k& t. m; F4 d  z  W6 f2 W
  38.         EOAC_NONE,                   // Additional capabilities & I4 a0 Q4 t% z6 R+ ]9 }. X' \0 W. l7 F
  39.         NULL                         // Reserved- m. f! q: W6 [3 Q
  40.         );" A5 u. _: V; c, B
  41.                      
    ) r" s/ R0 h- `
  42.     if (FAILED(hres))
    7 J# g: v" A. `  I
  43.     {  M+ c3 u) V$ {7 }
  44.         CoUninitialize();. F4 N2 r0 O& q) T& H
  45.         return 1;                    // Program has failed.. m/ H1 G2 @' ^" f5 A
  46.     }3 p4 U  E& f$ e2 n
  47.     5 `! o! M  r/ v
  48.     //以上不是必须的,若已有“::COMInit();”,则要跳过1 ?$ S3 K2 ?( T$ |7 o5 ~
  49.     //步骤3: Obtain the initial locator to WMI " H0 J: B# K8 n
  50.     IWbemLocator *pLoc = NULL;2 A* P7 F8 j! m3 ]3 a* B
  51.     hres = CoCreateInstance(! I5 N: U& ]0 P5 l
  52.         CLSID_WbemLocator,             . @! S4 |6 Y/ z) ^& j0 _2 ]' T2 [2 i
  53.         0, - Q+ m8 d$ M2 \% _3 Y
  54.         CLSCTX_INPROC_SERVER, ; M) K4 B1 q. p3 z1 {5 @1 N2 G2 N
  55.         IID_IWbemLocator, (LPVOID *) &pLoc);
    ) I* ^/ ^1 X* A

  56. 7 H4 Y: }& l" ]' _; l1 |& F
  57.     if (FAILED(hres))
    $ o$ \4 k% I4 g+ Z' [
  58.     {
    0 i/ e* ?/ o8 j. Y- \9 m5 ~! A* }
  59.         CoUninitialize();
    - r' W3 s5 O1 o4 F$ J, G7 n
  60.         return 1;//Failed to create IWbemLocator object
    $ @1 H+ l2 r! |4 D8 }
  61.     }
    4 H" e% ~& l' Z

  62. $ J6 N& l2 Q/ ~( @# X
  63.     //步骤4:Connect to WMI through the IWbemLocator::ConnectServer method
    0 n( B% o; v8 O, J4 j
  64.     IWbemServices *pSvc = NULL;
      E' b) ~2 M5 v8 L) U
  65.     hres = pLoc->ConnectServer(
    5 P  g/ W6 g7 l0 @: c- C$ U7 e! {4 O
  66.          _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace7 c9 @. v* O* |4 S- s
  67.          NULL,                    // User name. NULL = current user
    6 A) K% q0 Q0 A% P; M3 f5 n" |9 L" l
  68.          NULL,                    // User password. NULL = current1 q% a& X& n. A9 G" z( g: w
  69.          0,                       // Locale. NULL indicates current" ^! a0 o1 [4 w' W; y( O4 F* |
  70.          NULL,                    // Security flags.' E: k5 n% V, \1 T  e
  71.          0,                       // Authority (e.g. Kerberos)
    2 T& D: _, p6 a  }
  72.          0,                       // Context object , \6 F; ]: I0 W7 [0 _, `
  73.          &pSvc                    // pointer to IWbemServices proxy/ [# g8 P) s3 n, A) p( m
  74.          );
    3 R- T8 \  ]8 b$ C* w
  75.     # I* s* }9 u) C, }* j1 a/ w
  76.     if (FAILED(hres))( Z8 u; m: t, v1 X7 o
  77.     {3 w- y& v0 q- o$ c9 S4 \! W6 x
  78.         pLoc->Release();     
    , G0 H' b: C& l/ H0 N7 I$ d
  79.         CoUninitialize();4 u# d4 T2 _7 @- j; A1 v* o
  80.         return 1;                // Program has failed.$ \1 |, e$ Z8 D4 F
  81.     }
    8 a/ n9 V8 ]0 ]) [
  82.     // 步骤5: Set security levels on the proxy! A- F1 o) T( l4 U/ W4 J
  83.     hres = CoSetProxyBlanket(/ I* x5 C/ c" K# ^
  84.        pSvc,                        // Indicates the proxy to set
    * E2 h, s$ f' w! V  m4 p
  85.        RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx8 Q' L" v, S& q
  86.        RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx; v- o4 u  e" L7 \# ~  k
  87.        NULL,                        // Server principal name ) I7 ~7 I6 w# j! D9 J
  88.        RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx 2 y! R! ^3 G7 u+ }, H- P& h& L
  89.        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
    - L* {+ H( ^2 X4 @( U! _2 a
  90.        NULL,                        // client identity/ p% b( N" o' P9 m! k8 l
  91.        EOAC_NONE                    // proxy capabilities
    / I  I) k6 j+ v2 ~6 S) M( G% X
  92.     );( ?) Q; C( B) i! ^% c3 W
  93. 2 [" ?# @" L" u# K7 C- `
  94.     if (FAILED(hres))
    4 J8 r" k+ M' d& V2 _' t  f
  95.     {( }) @. K0 y4 B5 k
  96.         pSvc->Release();; l' X' l1 M0 c, s# k# @4 y5 b. G8 u
  97.         pLoc->Release();     
    : y2 c8 e8 u6 k) K2 \
  98.         CoUninitialize();
    ' S% }/ Z7 [+ d8 c5 O  y
  99.         return 1;
    ( E. d* [* d$ D3 ?
  100.     }
    ( V3 N& m9 Z9 f4 I5 J% ~/ p3 n
  101. * u6 m1 Q  x, n. y* ~# v6 _
  102.     // 步骤6:Use the IWbemServices pointer to make requests of WMI ----* O2 M1 l$ ]* \; X0 W0 a/ S
  103.     IEnumWbemClassObject* pEnumerator = NULL;$ E; V4 k9 r9 L8 U4 R2 p
  104.     //计算CPUID  d" ^2 P6 B. y
  105.     hres = pSvc->ExecQuery(5 c  B, k( G0 w
  106.         bstr_t("WQL"), ( W5 K& t$ M0 Z. G5 F, O
  107.         bstr_t("SELECT * FROM Win32_Processor"),//Win32_OperatingSystem
    2 N6 w  H' l, \- h; W& F
  108.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
    : ]) R+ d9 ?( L2 V6 x
  109.         NULL,+ T, V& z% N3 w" u* K) j9 t
  110.         &pEnumerator);
    + n# b7 B2 r9 `3 V3 \/ z
  111.     7 Y9 ?& @0 d' ~7 Q" \
  112.     if (FAILED(hres))
    ; N/ r' W8 a6 X
  113.     {# m, r! P4 h5 P, S/ E9 l: M
  114.         pSvc->Release();
    / O3 b. q  P. M3 _6 R  \* |/ x/ g& g
  115.         pLoc->Release();
    , S$ ?4 U9 `/ I& Q2 r: o# K
  116.         CoUninitialize();1 w" e& ], ]  n( {8 a5 A% l
  117.         return 1;
    " r5 ~1 |% |- a( H" V4 k
  118.     }3 K/ r- L% \) ?( U
  119.     // 步骤7:Get the data from the query
    2 q" r4 [  |4 l+ Y
  120.     IWbemClassObject *pclsObj;
    / R" G0 ]6 u+ x5 i
  121.     ULONG uReturn = 0;
    ) o2 I/ c2 G8 H* s5 D; n3 [
  122.     while (pEnumerator)3 e  \. ^& D. t8 y6 {8 Y2 C1 K
  123.     {, d+ {, ]/ F  M# |
  124.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, - Y9 K+ J3 R! |- [6 ^( X
  125.             &pclsObj, &uReturn);4 m+ i" M. }& C  `* m- V$ M
  126. : v9 U  u. K, B4 _
  127.         if(0 == uReturn)
    & W: u- K' |+ J- D
  128.         {
    , I/ \2 x8 T$ N+ _3 x7 K2 Z+ X/ W& E
  129.             break;4 i6 y: I& k4 |4 y4 {1 z; J1 Y3 |3 |/ P. E
  130.         }7 A: B5 C5 {9 l. C! B
  131.         VARIANT vtProp;
    0 C: R% c/ N/ W' ^5 ]$ I
  132.         VariantInit(&vtProp);
    ! s6 `  f7 m4 f6 Y
  133.         hr = pclsObj->Get(L"ProcessorId", 0, &vtProp, 0, 0);2 C5 E4 d% S8 h: ^
  134.         strProcessID=_com_util::ConvertBSTRToString(vtProp.bstrVal);//strProcessID:类级变量
    % L- D+ D' D( m1 I  G
  135.     }0 y4 J* u# k+ W# s$ ]

  136.   R2 @9 r, |5 |# S1 E9 D
  137.     //计算硬盘系列号
    ! ^. J9 p' _. |7 d: R  F3 d
  138.     hres = pSvc->ExecQuery(
    : z4 M. v. W7 r) y5 j; Y/ K9 m
  139.         bstr_t("WQL"),
    * @. {5 w2 `; O% `
  140.         bstr_t("SELECT * FROM Win32_DiskDrive"),9 D( z, X2 m; Z7 g
  141.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
    3 G9 w, _" X2 K
  142.         NULL,# \) h' I+ u+ ^, e/ l
  143.         &pEnumerator);
    & p" R: Y0 A6 F" x' W6 G
  144. % y6 p  f; u4 g  g6 D! \& w
  145.     if (FAILED(hres))  x: d2 r5 p# s- ~8 Y
  146.     {
    # v* a7 ~7 l5 r% F  a! W
  147.         pSvc->Release();
    2 ?! X& T3 q8 G7 e& W, x! d
  148.         pLoc->Release();
    4 Z# O" o$ e% m+ q& b9 Z
  149.         CoUninitialize();1 l! [2 T9 i3 h+ j- X; x
  150.         return 1; * y6 D. q7 @% M  [/ a
  151.     }7 B, q+ f, o+ i8 v; v$ u
  152.     while (pEnumerator)
    . f# c3 V. D! I8 }7 p: {
  153.     {% u0 C& c: I6 `4 S$ V, G
  154.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
    0 g- |! f0 F# r9 ~: b+ H
  155.             &pclsObj, &uReturn);
    % h  ^# J& S' i, P7 @" ?# \+ ?7 _

  156. $ ^/ O" [2 E! z/ e! A
  157.         if(0 == uReturn)
    + h. ^: [: {6 s
  158.         {3 A! b* E* P9 i4 ~4 ^/ i" q
  159.             break;7 m$ T/ Y9 J, b9 i( }' n# Z  d7 O
  160.         }
    0 v" n; M. P6 m" i$ \2 t
  161. 3 D/ [7 _. ~* n1 v5 W, u  g
  162.         VARIANT vtProp;3 P! N% r) _! ]
  163.         VariantInit(&vtProp);
    4 ]7 E7 Q. ^% F7 C# t0 `' S
  164.         hr = pclsObj->Get(L"PNPDeviceID", 0, &vtProp, 0, 0);
    ! ^) l: D! M4 U' v
  165.     strDisk=_com_util::ConvertBSTRToString(vtProp.bstrVal);
    ( i: `( `6 L; M7 t! l2 w; r
  166.     }
    2 Y  M# j3 S4 S6 C2 `
  167. 3 L) B! w1 P$ ?) |% \- j
  168.     pSvc->Release();
    . i, K% w+ J9 @) p( K
  169.     pLoc->Release();  y3 |1 C5 l4 M; t1 H
  170.     pEnumerator->Release();% _+ ^" y0 w3 K  b
  171.     pclsObj->Release();
    ! d& E  Y! _1 i- r8 H  ?# N0 q
  172.     CoUninitialize();/ E& x5 T6 j4 k$ c! R7 h/ t

  173. / s" F: r5 r7 L' R
  174.     return 0;   2 x- e. H2 E4 ?, z5 n
  175. }! W: B! j* \( Y% h+ l
复制代码
 楼主| 发表于 2010-10-11 19:21:05 | 显示全部楼层
本文代码经ccrun(老妖)在Win2k下试验成功.
1 C9 M% f$ U5 p6 W8 W- U% i) ]0 I. [6 Z' ]5 V
#include <WinIOCtl.h>' H: _3 y; l* d1 l# {: Y5 y1 d
#include <stdio.h>
  c% q. t& b: Z5 T) Z1 f
1 G1 J$ e! f9 [/ p3 t+ @7 `#pragma inline
6 f: C8 o/ [8 b" u+ \3 {1 @  R//---------------------------------------------------------------------------
+ f7 r, h7 p6 w; [+ o7 m) A1 m// IDE NT/2000/XP专用变量
4 W# \! _$ ~5 @& i' U' j  D* z' u  _#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS" J  V# M* M4 ?4 c! |+ t
#define DFP_GET_VERSION         SMART_GET_VERSION5 J# A. Q5 x4 u. f
#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND; m0 u1 ?- E; i3 d/ I. U
#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA% m# O$ W+ R0 e$ l
8 t; ?' }6 U1 @3 N" o' s
const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令
5 G1 s) y5 K4 F/ P8 b3 H7 Aconst WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
  K4 A3 r$ K) X  h2 S; Q7 \% z5 e- S2 h  o+ J7 n# s' Q
const int MAX_IDE_DRIVES = 4;
7 p) b) ], g! j# \' {$ m6 Y
- t. q1 n$ `' C$ c// SCSI专用变量
! U7 c) L5 R: V3 ?' ^5 C8 k' Rconst DWORD FILE_DEVICE_SCSI             = 0x0000001B;0 s9 ^5 J, r0 L
const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
0 e0 i% b& K2 l4 bconst DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition  K9 p9 I: [2 O& ^1 U5 @
const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
/ ~' K) y9 t7 e& a8 z' _5 V0 _4 ~1 H1 G! y
typedef struct _SRB_IO_CONTROL
9 ^  g  p! r- R; b! Z! Y4 q{
5 C5 {4 K' U) T    ULONG HeaderLength;6 ?, F- w" g7 C4 ~8 t- l0 `: y
    UCHAR Signature[8];
1 C1 b: ?* j5 ]6 o" X5 h    ULONG Timeout;8 Q. W. ]. K0 s0 }' t8 z' z
    ULONG ControlCode;9 ]  \& p& W7 v- q& u
    ULONG ReturnCode;
2 E/ n$ [/ _% W& V5 ]7 _    ULONG Length;
. j" o! C# x# C0 p2 U$ _5 o. c0 j7 W}SRB_IO_CONTROL, *PSRB_IO_CONTROL;
! Y: ~6 Q* y6 N. Y# a2 R8 K; i3 L! b# C7 Z+ C9 l' O/ `. W0 J$ g( I
// 读取的主函数
* O' T0 f% L" N* }void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
5 R8 t7 Q: Q: t( A! M$ h- D3 q$ z) K, u3 T# j* B+ X, p
// 辅助函数
5 g: X: C2 e9 E3 P* Rchar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);8 b) V$ F6 _2 J  A
// NT/2000/XP函数( J6 l/ E- K6 p
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);& C" \% W! M' @* M
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,* B4 v. ^2 }4 `. N
        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,( q  z: N  I2 t" E& Q* I2 p9 ^0 L
        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);0 D0 K, E) z' P2 ^
// Windows 9X函数
& i- \! ^7 m/ _1 y4 o/ Z) T2 Lvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);( b; q3 n2 L+ P$ U. p( F) n
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,& m- L% }$ U! p" P$ _1 b
        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
' G8 D$ S' Y) V  S6 G5 v. W9 ~: \& X) x/ y# n; S; {# f
// SCSI读取函数(for NT/2000/XP)
$ _+ ~3 @$ b" j3 u/ ?String __fastcall ReadIDEDriveAsScsiDriveOnNT();
9 K* e- N4 e$ }//---------------------------------------------------------------------------
* u0 a# U4 o' {7 W; ^7 C// ReadPhysicalDrive9 G5 c. D; A0 N; g
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)! t* y; o; i* W$ Q: y4 a
{
! e4 }7 u0 O5 t- N$ X    switch(Win32Platform)
$ ?- F/ r$ E$ e) w2 F# f0 k; |    {
; x" c1 X4 l. I" |4 b8 ?        case VER_PLATFORM_WIN32_WINDOWS:7 ^% R2 a& o. V: L7 J- p: i2 n' X
            ReadPhysicalDriveOnW9X(pSerList, pModeList);+ r. o- M2 y; E5 D% [; B, Y$ {
            break;' h1 B+ \- ~. I! j3 Z
        case VER_PLATFORM_WIN32_NT:8 [+ U9 O  Q$ V( X3 z$ }
            ReadPhysicalDriveOnNT(pSerList, pModeList);
% c7 V" s' S. I7 H2 F            break;1 S. I# v8 A% J; j  H! d
        default:
3 w. b; `1 I3 S# w+ i/ v9 m. ~            break;) i% O5 T. h& k7 V& u$ C
    }! C5 C3 G  w0 A- Q5 H
}
" g* n, p( @+ v+ N* w. [5 [//---------------------------------------------------------------------------: b  X7 J* f" ^/ J
// ConvertToString6 w- U  Q5 ]4 a5 e- b" Y
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)- ^4 W1 _; y1 ~) Z( m. c$ X
{. B) Z/ U' h( j1 \" h3 u7 ^3 e
    static char szResBuf[1024];, e% D% T8 F3 Y5 e! r
    int nIndex = 0;
0 B3 C, D8 H* j% F    int nPosition = 0;+ X. Z# [  N% v- d+ j
# u2 n3 z: p* k" J4 @! `
    // Each integer has two characters stored in it backwards
0 d) R7 a  l/ y  o    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)  _/ E. \/ z4 |: k7 G. X
    {' f: r0 t* r9 U, ^5 b) O- v
        // Get high BYTE for 1st character* C) B$ T& i* c( o9 d! S2 l: k. T
        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
' Q# O5 A0 F, N8 E0 L        nPosition++;
: w) t7 L& W$ v3 j, R( w$ K$ a# ?$ K- p6 ^0 C
        // Get low BYTE for 2nd character
( B* N) @$ H/ e+ {& T) F, l        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
2 k+ O6 }2 w1 [. O( S8 f        nPosition++;6 v) ?0 N# g1 C, L; O' c9 z
    }
0 a' g- Z% `1 e9 x! L
8 Y9 h: [# H; C# `6 @' z, N    // End the string
3 j6 F1 a) |! W+ b7 j/ H! M    szResBuf[nPosition] = '\0';
, g) ?2 @0 |  ?8 Q, f* t, D7 @" s8 l+ q( [) Q6 Z; I
    // Cut off the trailing blanks
! l* A* M+ K5 H    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)% ^9 h) u1 P& q$ o1 ~; ]
        szResBuf[nIndex] = '\0';
/ A9 f- `9 Q" f! }" \1 n0 e8 O6 D( a
    return szResBuf;
: ?; Z* z2 j- r* z& r}3 r% I* |9 ~6 g, K
//---------------------------------------------------------------------------
* T7 l$ q+ l* W& J- a& @7 J4 `// Winndows NT4/2000/XP 代码
( }2 M+ V! i% c- K/ s! Q//---------------------------------------------------------------------------
4 A0 q7 f+ I( q! @1 `/ S// ReadPhysicalDriveOnNT
* F" ^2 b* }$ C* kvoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
) b* o+ _( V. [: N{! E% d6 M% i. a: l5 n
    // 输出参数
- m3 a1 F  }4 z/ R2 m# u    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];8 q. `" e4 J: }

3 k1 o3 U2 J/ v5 v- d  ~    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)& P9 m( M1 E  U# O- L# ~4 J
    {3 c3 g: \+ r0 m; R
        HANDLE hPhysicalDriveIOCTL;( R" }- R- A! E( f
        char szDriveName[32];, q) V7 h: D2 u: i6 X$ Y

. |! S2 K( W% x- g4 j3 h8 ^* y3 E! o2 X! |        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);( ?9 J& Z, O2 `7 Q) ~. y1 t$ Y
        hPhysicalDriveIOCTL = CreateFile(szDriveName,- J4 E# m( f6 ^; @1 C9 q: c9 |6 ?2 U
                        GENERIC_READ | GENERIC_WRITE,
' g5 ~7 v6 j" U  D, B5 A" L4 g                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,' c9 V& t: m3 O/ D0 m$ J
                        OPEN_EXISTING, 0, NULL);9 z" U7 R! H5 q& k8 ?

! N5 A- O" D& R9 t  m        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)+ F6 E; t" T- x: ?6 m2 G
        {9 G  m& Z- q4 h* [/ G
            DWORD dwBytesReturned = 0;
0 J; U* f+ m) l            GETVERSIONOUTPARAMS gvopVersionParams;) w! }( i4 g8 Z; k: Q/ |

! L* e+ A8 K; @* A3 }& j$ D6 z" C            // Get the version, etc of PhysicalDrive IOCTL8 s- \6 w9 g! f4 N6 a" o
            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));6 V: W4 X% E8 a( |8 p
3 ?+ E  i9 c8 C5 b3 v
            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,: @: c  Y2 Y4 |. p/ N
                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams)," Y' J% R* i; S2 c( E- S
                    &dwBytesReturned, NULL))
% y, M% S4 h* @4 s/ a& T( y            {
# ~. U4 v) [- g/ n. r                continue;
3 W7 Z$ j/ _6 Y+ K            }
! U$ S8 R4 L+ _% F  k% O2 E/ O8 X- i) Z% F( ~$ u
            if(gvopVersionParams.bIDEDeviceMap > 0)
% y! ^/ a2 e; m: l$ Y  m( U            {
  u9 D) P# y9 K' b% m: ]                // IDE or ATAPI IDENTIFY cmd
* V+ d9 f4 w3 {' F9 f  \" Z                BYTE btIDCmd = 0;
+ p* z- E' o2 Z- n, X- d                SENDCMDINPARAMS InParams;
& }7 V6 k% g0 c6 _. ^" C                // Now, get the ID sector for all IDE devices in the system.9 F9 |0 K) o; T5 A
                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,0 `; @- J/ ?+ @- s0 c8 l+ |
                // otherwise use the IDE_ATA_IDENTIFY command- V" ?5 l  r; @4 k
                // 具体所得结果请参考头文件中的说明& A# z+ z0 A$ V; v2 j- m8 h
                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
  m) h7 x. ]9 P7 a, P                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
1 Y4 L! g& O% r6 Q: C* F$ B/ g% t9 j) Z                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
# b3 A, M4 g  `. J                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));# i3 {: x+ i5 Y  Y6 v

3 V5 h! f( ]$ {# r) A8 j  ]                if(DoIdentify(hPhysicalDriveIOCTL,3 ]% T5 l1 w- l/ q$ N, ?: I
                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
! ?3 w- R, @; L+ F  B' a/ N                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
5 b3 U5 A5 Z% V: B) _8 `                {
) F" w3 m" I( b, @+ }                    DWORD dwDiskData[256];- T& m* U4 [% i3 G# s
                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
/ @( j* J6 x3 f                    char szSerialNumber[21];/ Y8 o9 D' ~3 @4 I/ k  w$ ?$ ]
                    char szModelNumber[41];
. Q8 x3 `# N9 A+ o8 y: E) `5 N8 |: }6 Z$ _( J& w/ H( _; K: s
                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;) q, {' R8 S2 C+ E5 O+ z
                    for(int i=0; i < 256; i++)6 t+ j  N( N, x* o2 c
                        dwDiskData[i] = pIDSector[i];
$ Q! Z7 W+ E" `1 x4 _8 D                    // 取系列号
5 W+ [  R% E3 \5 S2 `                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
8 r  M8 b; u, d5 v/ V" b. q9 _                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));; |" H( \: o5 B% V/ K
, ^! J( G5 S. T
                    // 取模型号( l  a6 g/ K" ]- j! I8 G
                    ZeroMemory(szModelNumber, sizeof(szModelNumber));, M# v% Q7 ?. E8 _# {; m
                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
  A: T  w# D' D+ O; l. @, i
1 {5 |* R/ ?- o! u& r" B                    pSerList->Add(szSerialNumber);7 ]' z1 ~7 H% u, V0 V# A; |- E9 x
                    pModeList->Add(szModelNumber);
% e* j5 Z9 _7 j% b& ~  S% k; f  @5 u                }" j; O  i. M- n* w5 X
            }
6 J$ J7 X/ M+ j7 A* x4 x7 l/ }            CloseHandle (hPhysicalDriveIOCTL);
7 d( u. o% [/ _. }" o9 u  T) R        }2 Q) p; X9 \5 R) n3 L% e
    }
2 K' ]6 C' b& q}' j, V1 n, i, _( e
//---------------------------------------------------------------------------  }/ V" C. J$ f7 W* Z0 x2 [
// DoIdentify
! i. u  a8 e. H  I' |) n! @bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
) [: s7 b5 Z8 |& K              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,2 v) m: h+ P5 }, r: ]' ^) }
              PDWORD pdwBytesReturned)* J# g5 F5 j8 c# |3 c) b0 x
{# j" I% E3 H" J% \
    // Set up data structures for IDENTIFY command.7 x5 U. i/ K2 N( x
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;! V8 A# m; ]% @
    pSCIP->irDriveRegs.bFeaturesReg = 0;' U8 M" [+ f3 p9 p, ~  P
    pSCIP->irDriveRegs.bSectorCountReg  = 1;. m* w) M; z  m* H
    pSCIP->irDriveRegs.bSectorNumberReg = 1;
9 Q* T4 m9 N$ b( f! l; `  }8 {# E; a    pSCIP->irDriveRegs.bCylLowReg  = 0;1 H( t' ^9 e  g/ h0 g# ^# x
    pSCIP->irDriveRegs.bCylHighReg = 0;" Q) c. H" u! G' d4 V

1 \5 y2 [. n2 s+ |! H    // Compute the drive number.(主盘和从盘所对应的值是不一样的)# O$ |. j" z8 q5 H- U2 S" {& j3 p
    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;# {: k3 ~4 O$ V3 N6 r- D

% X) n" o0 u. Z* ~    // The command can either be IDE identify or ATAPI identify.& _5 }) |0 p/ ?+ V) O9 f4 [
    pSCIP->irDriveRegs.bCommandReg = btIDCmd;9 O$ N+ `0 t; e- C
    pSCIP->bDriveNumber = btDriveNum;7 q4 d, h4 T; m$ R5 [! n" f% _
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
7 e& L) b% m4 V, ]* J$ t. u$ {  L
9 X$ J. n5 z) `2 c  D    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,# D" b% C( e& Z: ~
           (LPVOID)pSCIP,* ]* a$ P/ i) X4 B3 m% P6 `
           sizeof(SENDCMDINPARAMS) - 1,
$ A5 @9 X& k" n3 i6 S; A           (LPVOID)pSCOP,
* c+ C6 z( o, k4 {           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
4 a" ?0 Z# D  {+ a( |+ ?. K           pdwBytesReturned, NULL);; x5 Z* L: }' q
}+ b1 D2 P) ^  P/ B9 y3 O
//---------------------------------------------------------------------------3 ~# U3 Y4 j: ?
// Windows 95/98/ME 代码: C* \6 F7 U' l1 f
//---------------------------------------------------------------------------
  \% A4 E  \: V6 l1 @9 R; L// ReadPhysicalDriveOnW9X
4 Q# M/ S% A# Y( dvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)
( F' k; N- `4 D{
' q+ a9 |' y5 x  R- G& v    WORD wOutData[256];# m$ g# g& p# p9 d& V' y
    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);. D! p+ R) M# e7 X# E* L' a
& d( s" N& x+ h% \. P3 \0 ~/ ^0 ]  G
    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。# i8 k, }4 ^. s1 u6 c3 |
    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
  [& u% m1 O4 J    // 避免蓝屏的出现。(期待高人能指出原因)
. p, P& [. q5 Y  M( i3 [1 P0 a4 s* V    for(int nDrive = 0; nDrive < 8; nDrive++)# M$ ?- e1 X& H
    {
( K# A) F/ k8 I: {- z7 g        WORD dwBaseAddress;
; C$ ^( T# _* _& U! Q        BYTE btMasterSlave;         // Master Or Slave
/ a8 q% \3 I# R; @* q" ]        bool bIsIDEExist;; P! a* v0 l$ a" D9 k
        bool IsDiskExist;
; J3 Q; g$ u* K  A
* h2 }1 A: {5 A/ ?0 g+ l5 @4 {        switch(nDrive / 2)) K, q- u7 U$ N5 [5 w: a
        {. ]0 z, }  v( `$ |0 ]. e5 ~
            case 0: dwBaseAddress = 0x01F0; break;/ _. ^5 C0 I5 e2 T  t' S2 R' [
            case 1: dwBaseAddress = 0x0170; break;8 v' K( R  _3 f* @" I
            case 2: dwBaseAddress = 0x01E8; break;
/ Y$ |! o4 m5 h% o- ^2 w# J            case 3: dwBaseAddress = 0x0168; break;
0 E# K9 B: D8 _  I- z  P, K% W        }
% n3 _- a3 M: z4 N4 }3 v. X. H) F/ b  ]& K" _$ ]
        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
% Y; f* j# T: p' A4 t3 _; b
+ c3 k3 E) ?! j4 i7 W4 ^        // 进入Ring0! f0 J4 y0 S: B4 L. ]( p/ Y; ~
        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,# W$ Y9 o9 r. o9 D
                bIsIDEExist, IsDiskExist, wOutData);' |6 p, R( U, ^' Q3 R3 R3 M
    }
2 f0 v. \; e! J/ N7 `  q# C8 ^% _2 B! ^9 v: A
    // 开始读取) K2 r3 D2 @; X) J
    for(int nDrive = 0; nDrive < 8; nDrive++)
; p: h1 |; e: @# F9 {+ @6 n    {9 z: o' k6 w  R" }  l9 R
        WORD dwBaseAddress;
- J; z- B) u1 t4 B  O# O        BYTE btMasterSlave;         // Master Or Slave( s" s5 u  P4 U6 ]7 y5 M
        bool bIsIDEExist;
2 k% |0 q$ x* r$ V# i8 U6 k        bool bIsDiskExist;( }, H$ `& ?- l& u( ^0 y
        switch(nDrive / 2)" M. U; J: w# |4 }
        {" ~6 |" W8 p3 d# k8 u  T7 i* A
            case 0: dwBaseAddress = 0x01F0; break;/ j4 s& r/ J7 X3 Q4 P0 ?- W$ L5 G
            case 1: dwBaseAddress = 0x0170; break;- L$ u! e& a# T/ ^2 Y
            case 2: dwBaseAddress = 0x01E8; break;& c% G7 m$ }, o" w
            case 3: dwBaseAddress = 0x0168; break;0 G2 R3 U; U2 c5 M* N) g7 `; `4 p
        }
+ a3 x1 M4 V% f/ ~% q
: v% W: `; G" m, ~) R" l+ a        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);' y2 J  \0 @% `' O2 z; V" [( p$ \
+ ~& O3 c. ?* o7 [; ?8 t
        // 进入Ring0
: P8 B" m$ B/ j8 p        bIsIDEExist  = false;
3 q. X# I7 {" ^/ ?6 @& Z' b+ ^        bIsDiskExist = false;
) \: P/ C) J9 c( R( r        ZeroMemory(wOutData, sizeof(wOutData));
7 j$ z5 O# q% o) l  Q; e$ B3 S4 A' W$ m
        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
8 v- G  K& F; Q5 ?; N4 g0 K                bIsIDEExist, bIsDiskExist, wOutData);. [0 H$ g& f( T5 |% g  S
# f) b  L* @, ^5 I
        if(bIsIDEExist && bIsDiskExist)
' U! f+ l  C/ z% Z: o: p, M        {5 K- f, W6 m: C0 b  ~! a
            DWORD dwDiskData[256];
6 ]6 A) J8 }' Q; r5 z( Q            char  szSerialNumber[21];- z% T) t: F& Z/ f- A$ G
            char  szModelNumber[41];
- x, Q9 G9 i" x* ?" K
7 p+ h  p3 F: q' @% |            for(int k=0; k < 256; k++)1 R2 `! R+ ^6 u0 j  e) Q
                dwDiskData[k] = wOutData[k];
9 m' E2 d  w6 g9 |' M+ c1 {
- y3 z2 ?- @! K1 C2 V            // 取系列号, x8 S$ O7 Q' c, e9 P, i9 e
            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
/ X3 d3 Q, f7 f8 o+ S            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));7 P/ Y1 K: D6 Z- h  l3 |5 {
% w0 h( p/ R8 a: b! P/ ^7 u
            // 取模型号
: e" e0 O' O" Z6 v- o            ZeroMemory(szModelNumber, sizeof(szModelNumber));' d! ]  e% v! e
            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
) |7 _. g* a, Y/ l, t8 p' _; h$ e6 K9 R2 E- z) l! U0 c
            pSerList->Add(szSerialNumber);
% r( t) \1 w9 t( ]% a& I& t            pModeList->Add(szModelNumber);
6 j9 e0 i% i) g5 H  X" b* g5 V4 U        }; q7 }0 i) T; z3 x1 K# p
    }
; r# t& k' q0 l, {/ c    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
+ i3 ~) B9 b# X0 m! z: U}
# x  T2 n9 ^; n//---------------------------------------------------------------------------
7 F- h0 W  C9 w/ I8 C8 O6 _- j// 为防止不负责任的转载者,在此注明原出处信息,请见谅。; G( `8 S# i; b0 e& ~0 {6 s
// 资料收集整理:ccrun(老妖),欢迎光临C++Builder研究: http://www.ccrun.com
! y  g  L! B! a0 q) n/ J//---------------------------------------------------------------------------7 c. k4 A  }* s2 C' j- s
// ReadPhysicalDriveOnW9X_Ring0()$ Z5 o* m+ [0 i+ L3 j
//
( n7 `) {6 M: L/ F% L" z// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h. W+ E$ T8 B! p2 S6 N* _
// btMasterSlave = Master(0xA0) Or Slave(0xB0)& y! _, R# _2 w( F8 d, n& _
//---------------------------------------------------------------------------( f' }- X* }8 V; W- Z. g
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,* Z- c& e$ \; M2 s) B0 h
        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)( o7 u- g3 p* M( ~9 ^- q# M, o
{
- O  _" c+ q, p& L8 H    BYTE  btIDTR1[6];4 g% H& x: L$ }% n, p( A, `* ^8 v
    DWORD dwOldExceptionHook;+ R) |" r$ f, T8 w8 I6 W
    const int nHookExceptionNo = 5;9 z3 K& R# Q- f) [

$ h) o; K2 h8 {* Q    BYTE  btIsIDEExist = 0;7 ?- O/ M9 g& _; B
    BYTE  btIsDiskExist = 0;# U. h1 n, u6 }2 A
    WORD  wOutDataBuf[256];/ h, a. C9 r# h2 H
( i( x' C% Q' v8 t# X7 ^" f
    BYTE  btIsFirst = (BYTE)bIsFirst;( w( W4 _( _1 E& }* E. F9 \

% Y5 j" w' {+ b% j  X3 X$ ]2 v) V    const BYTE btBit00 = 0x01;9 x. u& @, f" G2 @" x' h8 P
    // const BYTE btBit02 = 0x04;
+ x0 U4 B, b4 g; q% h' O5 X( x    const BYTE btBit06 = 0x40;/ ]! ?( I" o! Q
    const BYTE btBit07 = 0x80;
$ }7 b0 o* D; n; J, h1 Q" ]8 W6 |    // const BYTE btERR  = btBit00;
- |" G7 L" {. _; h; r    const BYTE btBusy = btBit07;; L2 {* G+ Y. i$ ?& z" L) ?
    const BYTE btAtaCmd   = 0xEC;
  o& ~8 p1 ?$ W0 f0 M7 B    const BYTE btAtapiCmd = 0xA1;
: M" W% j! v: |5 G# ?6 P% B! g* @! F: u1 s( O# o
    __asm
7 L$ Z# B3 \$ c7 \% Y# Q7 |    {0 w' p% X) E& ]
        // 必须先执行这条语句
# L/ y: Y# f5 H* W' g        JMP EnterRing04 f( h6 r) D; I; z; C
3 y6 \- t- N  i. p( q- ?8 P( [4 D* G
        // 定义过程+ [& j! T: k9 J, ~4 A7 ?: B) W" ]
        // 等待IDE设备直到其不为忙为止
7 O& d. k: E  d, J9 t8 `# C, H        WaitWhileBusy proc- ~# H4 w: ~9 \8 P2 G

: h/ ~8 D$ y5 e5 z1 b: e        MOV  EBX, 100000
& k9 u- M, L: m: x5 k4 n5 h. D; ?        MOV  DX, dwBaseAddress) M) g, p) k) w/ ?& I
        ADD  DX, 7( ]/ `$ `' u  x& j6 F

9 m' M# `* m- J9 h        LoopWhileBusy:
/ @' F# y/ _1 p. M0 ^: Z2 q- k, J9 a2 Q2 g7 t" |
        DEC  EBX) S0 H/ t! Q' g
        CMP  EBX, 01 c% E" E& k' D0 V( I" x
        JZ   Timeout& |+ `) a$ Q: n
        in   AL, DX0 W0 Z/ b# J9 g3 v+ G
        TEST AL, btBusy  j4 l5 O) X& a9 o; M/ R
        JNZ  LoopWhileBusy7 \9 y% ]! R. W7 @2 [- e
        JMP  DriveReady
6 Q3 p5 S0 @9 G5 N, A2 v$ f) s8 \! Y; T( r/ [  G) h, d
        // 超时,直接退出! u9 X- Y& R, @' K& ^: @0 G' U# Y
        Timeout:1 r  p- |, J, L0 x% e3 e
        JMP  LeaveRing0
5 W, H; @' v' [4 j) i  G: E        DriveReady:0 [( T7 r( i' G( I: ?
        RET9 D* x8 x7 X2 _" l+ N) H6 M! k' x
        ENDP   // End of WaitWhileBusy Procedure
3 U( S  R' j3 G- q+ z8 }, T. H2 E& R, z
        // 设置主盘和从盘标志
9 l' H3 ?6 L4 C( B' q1 Q0 O; `# W        SelectDevice proc
; G% A" K, X6 H8 T6 Q" j1 L+ ?. x' {* R# J7 j9 }) W" N% ~
        MOV  DX, dwBaseAddress! w; [6 a' P8 y/ l5 x% R+ e
        ADD  DX, 6& F& I6 r6 A6 d$ C9 h
        MOV  AL, btMasterSlave& ?$ W: K5 M/ a) u9 O+ n; d% g
5 h& T+ _- H- F" B$ N
        out  DX, AL" d1 K" Q- L$ v/ ^1 |: n5 o( p
        RET1 y! W" I" A/ r
$ b5 B. d# Y! o" r( B# N
        ENDP  // End of SelectDevice Procedure
' q2 ^4 T" e1 ^! j0 H6 y3 ~; x. }
6 i: q+ s3 W3 {$ a        // 向IDE设备发送存取指令7 \  ^" r! U% l& @. D  l
        SendCmd proc
: p. z5 l: M% S3 t) j) V0 ]  ~* H! [" `7 v
        MOV DX, dwBaseAddress
* q; o' l: \7 X# R6 G2 L        ADD DX, 77 R6 P- M0 I+ u! F, ~$ N
        MOV AL, BL // BL是主从盘标识,在过程外设置3 r' Z+ j4 s( a5 U$ u
        out DX, AL$ r# K- m# [: Q1 H0 w; y
        RET
9 K$ O( o1 R/ o3 X4 {" Q* q5 _        ENDP  // End of SendCmd Procedure8 I$ e* {+ j' o* I$ R
- e1 s4 o3 y% U$ R; C. K2 a5 Z+ K
        // Ring0代码
$ R2 a% }) _- |) o( C6 o        Ring0Proc:
6 T$ g' P3 G* j- X! V        PUSHAD0 {3 Y  [$ @3 D0 E; C! q
        // 查询IDE设备是否存在
9 |' f* O/ D. W9 m" s; _        MOV DX, dwBaseAddress9 ~, ~' f. C/ L" T
        ADD DX, 7/ D8 Q- g, F7 X" b, I: ~
        in  AL,DX/ e' J+ _0 [4 s3 @, v8 [
: v) G" L, W" G3 f- n
        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回% w+ F! t# K) u+ h
        CMP AL,0xFF
+ d) U6 T$ L6 _& L) A! l; w8 @        JZ  LeaveRing05 M- ?, W5 a/ t% T7 U
        CMP AL, 0x7F' f3 i$ y3 T9 }5 Z" y, }; _
        JZ  LeaveRing0
0 \! c1 o1 p/ Q. ^& r! J2 M5 V! m9 @  K! E8 I% P, W' `9 M6 ?( S
        // 设置IDE设备存在标志
6 G0 v# ?' Y1 B- I; l% u7 B        MOV btIsIDEExist, 12 s9 J2 h4 ^" |" `& C
1 }, i+ t5 ], j# ?% X+ ]
        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
1 z$ h( `  |: R+ Z: ]        CALL WaitWhileBusy
6 [2 Z. F! P# i5 X' a* L7 V% j        CALL SelectDevice
+ d1 p# e$ H  x+ [+ t  s
4 h9 O$ v6 v5 J5 I+ S        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏7 c0 f. z% x* x. D. {" N; V6 {
        CMP  btIsFirst, 1# s+ m2 \, Z# B! t
        JZ   LeaveRing0
$ g0 H* V/ a. u$ k7 H7 I$ o4 a3 J, F' j- O, g* P2 Q; {
        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
: H" q8 ]* \6 c' e; J7 s5 Y$ ]        CALL WaitWhileBusy, X$ T! r0 o; R8 c( t8 }+ w

$ K5 r9 L/ h( U1 y+ e* P: m9 l        // AL的值等于cBit06时,不存在驱动器,直接返回
8 A4 x- T7 U% \" O; W  U6 E9 c5 ^        TEST AL, btBit06" ^3 B+ }- K6 E! s; s' ^4 T
        JZ   LeaveRing0
; i/ }; l# @# Z; i  Q2 ?5 }  `! z) J) y) @6 Y: b* ?6 ^( j
        // 设置驱动器存在标志
3 _8 N  E5 c5 t  \6 g        MOV  btIsDiskExist, 1
) t! v  ]: ?" p2 g9 a4 Q5 o" [; M9 T& D% f, q' _
        // 发送存取端口命令
. ~5 m' R; O9 U2 b' d4 t        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
( j- n1 P) O* ~+ p) D0 V2 _7 K: b5 C        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令7 T! P9 ~# [7 O9 F8 F3 `! A* W' u& K
        CALL WaitWhileBusy
" D+ J# V( p9 i  L, G9 k& `3 ^: Y        CALL SelectDevice    // 设置主从盘标识
4 J3 P. W0 t- {- H& ]        MOV  BL, btAtaCmd      // 发送读取命令
! R1 x+ n8 g: T/ |: A" |2 X        CALL SendCmd* Y' D- y# y3 w5 c; l) q# k
        CALL WaitWhileBusy+ T4 k7 F3 {+ z6 L1 [( j1 W; x

$ C6 x- @% y. y6 H        // 检查是否出错3 v% G0 g6 }( k$ z0 k
        MOV  DX, dwBaseAddress' H5 F0 z# T2 P
        ADD  DX, 7
& a6 ?! g% e, l9 ^+ {3 \" R6 G5 L" u1 T3 x& q5 X
        in   AL, DX) G# t$ p# a/ k

+ {, s% x8 a/ h. J' o        TEST AL, btBit00
- l$ V4 ]7 [  p: l% |& R/ q5 q        JZ   RetrieveInfo   // 没有错误时则读数据
; {) e4 d2 G! M' Y5 q8 z% ?9 H/ G: c% B2 H7 a4 ~6 b1 e3 _
        // 如果出错,则进一步尝试使用ATAPI设备命令0 t* V& H! a; i5 j
        CALL WaitWhileBusy
$ u8 w6 H, ~; b+ D1 [7 D        CALL SelectDevice
- C0 w: f( K5 d# H        MOV  BL, btAtapiCmd
% t/ E' q: L- G" u        CALL SendCmd1 p, D: Q, d8 t& r
        CALL WaitWhileBusy
6 u# x" ~$ Q, F# ]" j5 ?* i6 _9 g' _% Y% P. p
        // 检查是否还出错) v: j% w& Y+ C1 m# d! S' C, s+ `4 E
        MOV  DX, dwBaseAddress
, l1 U& I/ l- z/ O  S8 @        ADD  DX, 7
% R% W$ ?* _; J) R5 O+ V$ t8 I        in   AL, DX
4 s$ v( A: W. e$ p+ O$ t        TEST AL, btBit00( J% N! ~; d* E
        JZ   RetrieveInfo   // 没有错误时则读数据
* V+ S6 u- g* r1 H, d6 G6 H+ \        JMP  LeaveRing0     // 如果还是出错,直接返回9 D. [# E) A8 r: `6 X" f

( W) ]5 l1 Z" d# i, i        // 读取数据
) L, c. e& b- ?2 i        RetrieveInfo:
+ [  C. }! \6 p" T1 a& ]6 q
2 n6 F/ M7 x4 @( p        LEA  EDI, wOutDataBuf
6 S+ P8 H0 E- \  l& w& z5 I        MOV  ECX, 256" I# b; E+ W9 {3 u, x
        MOV  DX, dwBaseAddress
3 t5 [7 W7 \3 V/ j        CLD
2 q. J* R8 V4 h+ \* W
5 `( s3 G& p& }. K- P        REP  INSW; g- A' _# l! `+ B
1 l3 P$ w' V: l
        // 退出Ring0代码
2 a; F6 X0 b8 w' u        LeaveRing0:; j5 p# H9 {4 q: r9 Z9 f
/ ?  [* k9 R3 ?- j6 L
        POPAD. i" B2 s; V8 O
        IRETD3 w3 O( l7 k, ~  c

( @0 C: [* d; H1 }  P/ L; f        // 激活Ring0代码
1 {! b2 F) V, \: T        EnterRing0:
) S, ?/ ~! t& ^+ [% G4 P1 f0 t6 B0 t% F
  f5 G4 ~& D% ~: Z        // 修改中断门
+ K! G& p5 d/ B, ~6 r1 R        SIDT FWORD PTR btIDTR1
  D6 w! O* k: }, E        MOV EAX, DWORD PTR btIDTR1 + 02h- x$ j" l4 w8 ~9 ^
        ADD EAX, nHookExceptionNo * 08h + 04h5 B/ O, O5 d, T8 M# J/ r4 m
        CLI
  j; Y* H7 q( P9 _+ G4 w: P) n4 x5 E  H: C/ I, F1 e* s8 j
        // 保存原异常处理例程入口
4 T- y6 d' [4 W" l+ G5 M  |        MOV ECX, DWORD PTR [EAX]
, O4 h9 {/ V+ Q/ J        MOV CX, WORD PTR [EAX-04h]
6 I* d9 {: g+ r  y1 B        MOV dwOldExceptionHook, ECX
. Z, j6 q9 Y6 O4 ~* p* Y& J4 Q; V1 X% K- E
        // 指定新入口
9 {/ Y3 h/ J9 M* {: D        LEA EBX, Ring0Proc( M% i, W$ u! X/ {3 O2 e
        MOV WORD PTR [EAX-04h],BX
% F8 D, l; y& i, B        SHR EBX, 10h
8 s5 W) D+ m  E1 Y        MOV WORD PTR[EAX+02h], BX
* \9 _5 M# `7 s9 Y' `. b$ P0 i8 M8 E, ^7 |) W
        // 激活Ring0代码# d* |4 j+ \! b$ y- C
        INT nHookExceptionNo
5 ~5 O& ~0 p5 v* q
, A+ z/ f2 |2 a7 T        // 复原入口3 J/ _0 D8 c# ^& U/ [( ?5 B
        MOV ECX,dwOldExceptionHook
$ q* O" U; |5 J, g        MOV WORD PTR[EAX-04h], CX
0 t1 f/ |+ a. D" m2 j6 J7 T        SHR ECX,10h
4 p7 s" m: O0 f. v        MOV WORD PTR[EAX+02h], CX, i$ Y% r1 y* ]$ T+ y
        STI
# f% R7 A, I* i6 W; |    }4 |3 c1 [. m- {7 a, X" C  ?2 z
    if(!bIsFirst)
. P4 w# i- u* D, h    {
2 A8 z3 ?3 `5 H3 Y        bIsIDEExist  = (bool)btIsIDEExist;
" A3 N5 d* |9 P0 `: {        bIsDiskExist = (bool)btIsDiskExist;
/ ~: U6 @2 h. g1 m        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
/ b7 d7 K# z  R/ t" Y4 c    }3 d' B( r/ _6 v' T6 m" d( j
}- K7 p0 y; s3 {
//---------------------------------------------------------------------------; g9 w; b* l5 y, S7 x, f9 w" U
// 调用方法:
# l4 a" w  N& }- rvoid __fastcall TForm1::Button1Click(TObject *Sender)5 L4 H  P: O) O0 p/ Y
{
& v9 Y; B( C$ N9 @# a2 e3 H    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
9 w. y' v* s% ?' R( B# A& _0 Z}  M# x5 d& ]) J! s4 ^4 ]
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-9-16 17:25 , Processed in 0.037995 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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