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

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

[复制链接]
发表于 2008-1-6 19:59:06 | 显示全部楼层 |阅读模式
代码框架,你所要做的仅是修改WQL语句,具体可看MSDN。以下代码为简介起见,一次返回所有的CPUID或硬盘厂商系列号
. V# H* k1 O' g- ^6 x! e7 H. f

  1. 4 k" R+ F% y8 H& X  L
  2. #include "StdAfx.h"
    0 W& h% o0 o7 ~! \% K% W
  3. #include ".\puiddisk.h"
    , E( z; B0 X' J3 w
  4. #define _WIN32_DCOM
    ' ~* b4 ]9 L8 {3 I
  5. #include <iostream>9 d# A1 {2 o6 c
  6. using namespace std;
    5 z, G' e, ~: E% L
  7. #include <comdef.h>
    * t6 |' T1 H2 @# G
  8. #include <Wbemidl.h>
    : w& A, r1 _# m/ R/ @! T5 u

  9. 7 u4 ?# T/ K& ~  r. {7 G
  10. # pragma comment(lib, "wbemuuid.lib")7 U0 u  D& v) |4 e
  11. CpuIDDisk::CpuIDDisk(void)% L5 W" P- Q  n# x$ g2 ]- A" D& n1 c9 m
  12. {
    : p/ n, Q. B; e7 D( J
  13.     GetInfomation();4 F& C5 `0 q! x* \# R
  14. }+ g9 y! V2 h8 r6 W% ~# h9 x

  15. 4 [, e+ J) K& {
  16. CpuIDDisk::~CpuIDDisk(void)# `- ^, M, G9 x$ ~& l4 Z. ~
  17. {+ }3 n# u- G0 {- j  q/ W" n  b) j
  18. }' P7 `! b; \9 a6 d7 T3 e. ^+ A
  19. int CpuIDDisk::GetInfomation(void)3 ~( W0 A8 [! `8 w! q! [% ~
  20. {
    % O8 z1 U$ q& @  r6 a2 P- A5 L
  21.     HRESULT hres;
    6 u% U4 R& ~9 t2 i% x# Z
  22.     //步骤1:不是必须的,COM只须也只能初始化一次7 F) u( x# s7 U* G
  23.      hres =  CoInitializeEx(0, COINIT_MULTITHREADED );
    9 i5 l7 w4 N5 x7 Y+ c/ Q; `
  24.     if (FAILED(hres))
    0 v( \# }6 I5 ?
  25.     {5 x/ z8 w/ |% a6 [0 v! P, Y. |
  26.         return 1; //初始化COM异常:注意,COM只须也只能初始化一次
    % Y4 g; A# W7 {8 R. H* E4 t
  27.     }% x1 u% N( x& X
  28.     //步骤2:不是必须的,COM只须也只能设置一次! h& y* V- S% f3 m4 h; M
  29.     //Set general COM security levels
    : d: d; u( v) \/ w) o. f' v+ ~8 L
  30.     hres =  CoInitializeSecurity(  i3 e/ I- T' W( S' D/ |( F0 n7 f
  31.         NULL,
    ! Q' ^5 ^( X& H5 {
  32.         -1,                          // COM authentication6 e- Q; Q* w  w2 q! B# {( y
  33.         NULL,                        // Authentication services; R# r* J9 p& ~! Q
  34.         NULL,                        // Reserved
    4 j$ N& i% y8 _
  35.         RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication ; Q2 r$ R0 x0 D
  36.         RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  2 ]) Y# i3 B* T: ?$ H. B
  37.         NULL,                        // Authentication info$ u; Q/ E& y9 W" _0 w+ j8 H' w
  38.         EOAC_NONE,                   // Additional capabilities
    0 d$ ^! V- S) y2 T1 |% r
  39.         NULL                         // Reserved
    . O  C9 X. b) v9 P$ U2 H
  40.         );
    / N5 ]( ~4 ?! y9 o3 t
  41.                       3 w1 H3 I7 g4 l
  42.     if (FAILED(hres))
    3 X; n! Z$ M* v( J. X/ ~
  43.     {& w: r, U3 D/ \: E- w' ]- T
  44.         CoUninitialize();
    0 U1 Q& z% \! d
  45.         return 1;                    // Program has failed.1 I8 |$ X6 q) |
  46.     }9 Z* u5 K1 P! r3 ]  v: G: |
  47.    
    . A" W  M. e5 L( b  T7 m
  48.     //以上不是必须的,若已有“::COMInit();”,则要跳过" y" F9 n& C( V- ~! o9 H6 J
  49.     //步骤3: Obtain the initial locator to WMI 7 \9 t2 f6 [9 X4 F; w- F5 U
  50.     IWbemLocator *pLoc = NULL;7 `" q% ^* |' E# M1 e; }
  51.     hres = CoCreateInstance(6 N7 ~; _4 t, C5 _% O
  52.         CLSID_WbemLocator,            
    5 _, P1 u9 w" h  X; S
  53.         0,
    4 a, j. j6 o" n* L
  54.         CLSCTX_INPROC_SERVER,
      t# X  {1 e9 E! v8 p
  55.         IID_IWbemLocator, (LPVOID *) &pLoc);  G9 F+ e7 Y1 f  r1 C- Q
  56. , h/ g% z1 O9 F
  57.     if (FAILED(hres))* `, t$ S$ M) q4 Q* T* @
  58.     {" D# a6 C3 X3 V( X+ a
  59.         CoUninitialize();
    2 J4 X& |4 W: K- s% g
  60.         return 1;//Failed to create IWbemLocator object7 w' v8 n" c- ?2 C5 u' S) r+ ^
  61.     }: W. `$ j) l$ N# ~

  62. ) A3 s' A, ^' i1 @4 |( T$ X/ ]0 `
  63.     //步骤4:Connect to WMI through the IWbemLocator::ConnectServer method
    7 b% S' ?/ y4 Z; c5 k4 }
  64.     IWbemServices *pSvc = NULL;) b$ A' G2 y9 Z) @
  65.     hres = pLoc->ConnectServer(
    3 ~8 t  K6 e" T/ K! w7 o9 k$ z
  66.          _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace2 K1 X" ]4 l1 L/ q# h# a6 X1 T
  67.          NULL,                    // User name. NULL = current user% I& o# P/ }+ K' X
  68.          NULL,                    // User password. NULL = current4 i- ]5 u; m/ s$ z  S
  69.          0,                       // Locale. NULL indicates current7 P2 M+ \" X0 }1 V- o6 ~
  70.          NULL,                    // Security flags.# n0 ^( h6 c" I8 ^  P
  71.          0,                       // Authority (e.g. Kerberos)& ~$ s/ N! l  N! I+ B% v
  72.          0,                       // Context object 7 ?1 T- t+ [+ \
  73.          &pSvc                    // pointer to IWbemServices proxy
    ) M+ g" h/ \4 I0 q
  74.          );& v% p' S# P' G. }' p' O
  75.    
    ) E* ^9 U/ n1 u6 n
  76.     if (FAILED(hres))  |2 t9 x' l9 L* J  P
  77.     {: m# H8 p4 H) p' P
  78.         pLoc->Release();     
    % v" y' {% R+ I. {% I
  79.         CoUninitialize();( `3 g2 ?6 o5 j1 ]) F) Q! a
  80.         return 1;                // Program has failed." k2 }* P' \3 Y- {6 T- I  H) x8 E2 l
  81.     }6 c3 g! T5 H$ {1 F0 t
  82.     // 步骤5: Set security levels on the proxy6 V9 i! |1 O: Q' R+ r
  83.     hres = CoSetProxyBlanket(% ]. m8 X8 A4 x0 Z5 c* i' G
  84.        pSvc,                        // Indicates the proxy to set
    ! N, ^: O* @9 p3 E, r/ x: w: L
  85.        RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx/ u. G- Z- R( i$ n, p% i
  86.        RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx
    7 M/ m" i9 z8 }% |) Z) }
  87.        NULL,                        // Server principal name
    / P. z. A$ I8 v
  88.        RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx
    . i* P- b. k; w! L0 E
  89.        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx& N3 d; p/ {. r  Q  J( J
  90.        NULL,                        // client identity
    6 x, @2 F* k) Y8 ?; k$ B- l
  91.        EOAC_NONE                    // proxy capabilities
    $ b& e" R8 V' q3 R0 C
  92.     );
    : ?4 l" J; [% `. v' U
  93. / X6 k4 [( K9 y
  94.     if (FAILED(hres)), Y# _9 S5 P: H( E
  95.     {
    , j. z- B" e% |# J% Y' t
  96.         pSvc->Release();( }, ^" i' H1 i( v7 `- x
  97.         pLoc->Release();     
    # @! F2 Q* t, G+ [% u; R6 E
  98.         CoUninitialize();
    2 I1 V2 h/ x7 o: [' @. t
  99.         return 1; 1 B! p& v- g7 x
  100.     }( _3 N0 h* a, y+ P+ O: j) e1 ~( C

  101. 4 p6 A- m- Y7 L; w! D! u1 n
  102.     // 步骤6:Use the IWbemServices pointer to make requests of WMI ----6 y1 |& \. d' m  z9 C
  103.     IEnumWbemClassObject* pEnumerator = NULL;" B0 ~  |# q4 z* q
  104.     //计算CPUID) r- p9 p( w8 r
  105.     hres = pSvc->ExecQuery(
    & a9 C- \; |9 D  m! z' s" b1 d
  106.         bstr_t("WQL"),
      w/ s' B6 D6 O" w) C  \, K8 |
  107.         bstr_t("SELECT * FROM Win32_Processor"),//Win32_OperatingSystem5 W, B3 `' S, l# {1 o4 Z
  108.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
      }( |6 y1 Z0 ]9 e- X$ U
  109.         NULL,
    & C6 u, F4 Y. f6 Y
  110.         &pEnumerator);3 f. r) }0 H( G" S# r
  111.     ) u" |) c8 @0 C2 s: U
  112.     if (FAILED(hres))) s5 g9 T  f) b6 H: H' l8 G1 t7 [
  113.     {
    ' A$ Z; w8 F. Q- `* D6 o) B
  114.         pSvc->Release();0 u$ j3 p% n) a2 M& o3 a0 f
  115.         pLoc->Release();. t# m* `, A1 y4 u. o( J
  116.         CoUninitialize();: z8 `0 R$ d6 o- D) C; ^  E) j
  117.         return 1;; q8 i; M4 ?3 u$ J1 J: p
  118.     }
    $ x5 X8 C9 |8 g8 x
  119.     // 步骤7:Get the data from the query
    : Q1 h/ a, `* `6 d5 d; Y- a9 H
  120.     IWbemClassObject *pclsObj;
    ) }; \& e/ p" s- y' U% X, s
  121.     ULONG uReturn = 0;4 k8 A8 w( b1 E0 a# ~$ n
  122.     while (pEnumerator)+ O! X- u4 t' D7 j+ Y# ^& ]
  123.     {1 |7 c( f3 A6 g1 p# @1 k6 X( K
  124.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
    ; z% t3 v! ^) m6 ~, V  f+ y
  125.             &pclsObj, &uReturn);8 k" u% y: S( {$ p  X/ g& W) i
  126. % H- I5 Q6 I1 }1 q( J- C9 K
  127.         if(0 == uReturn)5 l# G6 a3 f& h8 C* m# s
  128.         {  _& c# X. N4 x4 b8 ?2 G
  129.             break;
    + \- d) H4 ~( N: B
  130.         }# a# E' Y# _3 S+ O3 l
  131.         VARIANT vtProp;
    ; `& w0 N1 @3 v
  132.         VariantInit(&vtProp);1 }  R: ^" s' U7 {2 h
  133.         hr = pclsObj->Get(L"ProcessorId", 0, &vtProp, 0, 0);- Q) V( C; L/ K2 `2 B" d
  134.         strProcessID=_com_util::ConvertBSTRToString(vtProp.bstrVal);//strProcessID:类级变量
    ( N# p) ~  E& Z5 K! P4 z2 Y
  135.     }
    8 g  R+ i! }0 H! h! _

  136. # X8 e( L/ E" f( B
  137.     //计算硬盘系列号& G& @: `& ~# s/ v8 L
  138.     hres = pSvc->ExecQuery(" w5 w7 O) H) u; e
  139.         bstr_t("WQL"),
    : w& W1 f1 n7 s7 M1 {
  140.         bstr_t("SELECT * FROM Win32_DiskDrive"),5 }. ^1 B2 S4 n
  141.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 6 ~/ t% E6 _5 U6 x6 i8 A8 s8 w
  142.         NULL,: p( S: |1 E) l" f! i1 M5 ^
  143.         &pEnumerator);3 z% M3 T3 u. ?! S+ N4 x9 S6 c+ p

  144. " \* v  ~& @" [6 ]3 J3 w
  145.     if (FAILED(hres))
    4 c7 R# X* H3 L
  146.     {
    ! k) M6 a+ ^& I" y) }: f
  147.         pSvc->Release();
    1 h0 r6 X" k% B
  148.         pLoc->Release();
    4 j# ^6 S. J0 A0 L5 K& s
  149.         CoUninitialize();- Q6 L( f: f8 b5 r3 L) V2 `0 Z4 g
  150.         return 1;
    % q2 t$ t7 J" s( \5 ?+ U; ^
  151.     }
    * ?$ a. {7 t" b+ ^% o
  152.     while (pEnumerator)
    ) p( z, B5 X) V+ h- F. T
  153.     {
    , i  m! ]( _; p" I( i% O. M0 d
  154.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, 2 \  D% ?. ]9 H& b' F
  155.             &pclsObj, &uReturn);
    + `# Y. i9 M0 m# A& i7 w

  156. 7 C7 W- g' I0 s  p1 {; n8 M
  157.         if(0 == uReturn)
    ' v6 ^/ a& P# K$ j
  158.         {
    , K$ z( j, o5 G3 D$ t, ?( k3 d
  159.             break;6 J6 y* B# M2 O; n
  160.         }' a( U, m- X4 T; t
  161. : G" ]- P$ [4 p/ q3 G
  162.         VARIANT vtProp;
    3 F1 t+ f* a" w
  163.         VariantInit(&vtProp);2 u$ u5 g8 d. L1 n2 t- R, c, g
  164.         hr = pclsObj->Get(L"PNPDeviceID", 0, &vtProp, 0, 0);; f8 t" \. D! _+ y8 D) Z) n* y
  165.     strDisk=_com_util::ConvertBSTRToString(vtProp.bstrVal);
    6 f7 p8 J+ {5 w$ G6 o# M0 ~7 C
  166.     }9 b" l& ~$ |( @1 ~- U1 b
  167. ) b' l5 n$ r- ]5 K# g
  168.     pSvc->Release();
    2 g  _4 n% a' ~4 D5 p  @6 x
  169.     pLoc->Release();4 l* T5 K! _. W6 g5 Q* y* j1 k
  170.     pEnumerator->Release();/ g9 f, _5 K8 f) k
  171.     pclsObj->Release();7 u- t" Y  \5 o
  172.     CoUninitialize();8 M8 V9 |" q+ \5 ^8 n) S
  173. ' v5 `3 g1 ]" x' E
  174.     return 0;   
    * I: T' N- O9 y# t4 C+ L
  175. }7 t. D* e: Y, P0 [
复制代码
 楼主| 发表于 2010-10-11 19:21:05 | 显示全部楼层
本文代码经ccrun(老妖)在Win2k下试验成功.
; ?. c  S' R' o+ [- e8 x7 y% ^5 [4 m# y  T
#include <WinIOCtl.h>; l  w& w* u. ~/ Z4 q: `7 u7 x5 v  w/ M
#include <stdio.h>1 |" ~1 t* k; s% g
: k5 }6 @3 Q, C  `; Q/ N3 z" x
#pragma inline
; N- \# w5 S% h3 @//---------------------------------------------------------------------------
7 O5 ^7 u$ e9 \1 ?* ~( n& a9 Q// IDE NT/2000/XP专用变量
# N8 z! `+ t0 f) x$ P: ~) \#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
4 Y* z, v& |# M, s$ v. }#define DFP_GET_VERSION         SMART_GET_VERSION
9 p( \! }1 k9 h#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND3 r9 H8 ]5 V$ g: e8 `
#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA2 l+ ~  i( ^, ^9 _
8 }; U1 o$ X- ]3 D9 ~" F
const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令4 w: Z  I6 w! T: e& n) @  ?- @5 @
const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
! \; a# v+ N5 N$ e$ Q6 p  R9 V- I  N1 R
. t, s2 ~, x# D5 Q' econst int MAX_IDE_DRIVES = 4;! K0 O( ~- l" p# Y, L
$ z7 E; `0 d1 b/ c
// SCSI专用变量/ _/ F9 G( k4 B& j1 J/ {2 K1 Q7 u; g
const DWORD FILE_DEVICE_SCSI             = 0x0000001B;
6 H: E- ]( O2 y8 U1 Cconst DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);/ s$ P* y; C; o% d$ k7 X
const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
, R& P+ b6 Z9 V. b, e  ~" sconst DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
1 K+ W$ P4 I) N* {% M1 q& e7 r& J0 G0 J% ]! ?9 T8 u/ _) e
typedef struct _SRB_IO_CONTROL
  G. h3 y8 a3 k3 `' {/ I* g3 m# T. P{; E! H/ O( Q) i* }
    ULONG HeaderLength;# D8 v6 t& `/ }8 a! X4 Y
    UCHAR Signature[8];8 Q; |# u  r  \0 g+ G4 k8 R1 F5 `
    ULONG Timeout;
8 Y. {7 H9 K6 e7 _  J    ULONG ControlCode;
) r) p$ ~! s# t$ {& O2 [3 M    ULONG ReturnCode;
( X- u* C; u. c$ ^( D  Y    ULONG Length;7 W! B/ T& o0 m+ H5 \" B1 M  y
}SRB_IO_CONTROL, *PSRB_IO_CONTROL;2 E: [$ t- V  H3 g

6 e2 V: {5 H( }3 G7 i7 @// 读取的主函数: x; V4 S0 M5 V" t
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
" O+ ?$ n; o# Q+ _1 d; D  Y$ B
) g( D( ^3 H: A+ S7 K. X// 辅助函数3 t; u! V& m. ~7 N/ [
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
1 B" ^" i. V, T// NT/2000/XP函数- r3 c9 b, s" h/ P$ M2 D$ b
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
  h) r$ a) p' Y  Mbool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,, X- K+ O! u: o" Z
        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,( I8 \+ j) ~! H' {2 Y
        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
4 c8 z; Q: r7 x% L5 P// Windows 9X函数4 r# Y0 t/ R  H' ]$ y6 @
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);
- e+ H' q4 L& n% o. f( x4 rvoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,+ R7 H7 ?8 L; z; u/ ^
        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
8 `; F: S9 w  D) D4 h  Y4 D- @" X7 u$ `
// SCSI读取函数(for NT/2000/XP)- `+ g& J4 w& Y& E# w) U9 Q) c9 @* P
String __fastcall ReadIDEDriveAsScsiDriveOnNT();
9 V2 z* r1 F2 X8 I3 K' H//---------------------------------------------------------------------------/ P- T* T( x2 m, M9 X
// ReadPhysicalDrive
2 o$ A, e, C  {* Kvoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
+ E; p3 e& j. P5 o5 D{* A; }$ v; f1 H% r
    switch(Win32Platform)
' D3 J$ Q+ W% c3 M: M, {1 o" F    {4 U) K, h* `! r( Q& `  D
        case VER_PLATFORM_WIN32_WINDOWS:
% P; [2 }5 \) H$ e0 _            ReadPhysicalDriveOnW9X(pSerList, pModeList);3 ]' O8 d6 j9 r' B/ j: b: S
            break;
2 r$ T' s# s5 _, M        case VER_PLATFORM_WIN32_NT:
2 H* M  Q$ z! f) J            ReadPhysicalDriveOnNT(pSerList, pModeList);
/ @7 z2 H. r  u4 [; J, R            break;! s0 D8 Q9 T; x' t0 D. G* s4 E4 D, T' e
        default:
3 Q- t5 [2 e% b8 n0 n            break;
# c6 l7 x# o9 L3 ~    }
5 `6 {: m0 R1 d  [% Z/ y}
- Y7 {# M2 ]7 V8 _) ~; P, H* `1 H//---------------------------------------------------------------------------; x8 c( w: ?, L3 _8 V6 L: G# m
// ConvertToString7 R% @8 S4 I! y- ~- @7 {( L$ w
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
- R4 Z1 {, j- v2 w  n{
; b& n3 c7 ~% B9 n1 m    static char szResBuf[1024];' ]% C4 F" L3 [) F4 L
    int nIndex = 0;
) v0 X$ v( k' X4 H& J- R/ ]# K& U% a    int nPosition = 0;
% ?( e( z" S( G3 Y* P& y6 y
& F- c+ B5 J, b2 Z' y0 z! ~. T" T    // Each integer has two characters stored in it backwards
$ ?! M9 e& s- }5 j, K7 ~    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)7 ~; \; ?$ ]' P
    {3 Z$ r7 ^2 K$ \$ j
        // Get high BYTE for 1st character
. w3 y1 i+ f9 l/ u        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
$ w. X1 Q+ k5 o, d9 w9 ^9 P: S+ r  k        nPosition++;# k% W8 L# p9 w, g/ P7 f

1 H8 B; O4 [2 f5 S8 n3 Q        // Get low BYTE for 2nd character$ b+ U1 `  j$ t3 V1 `! f% V
        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);7 a* p3 H3 N) t  J( ]
        nPosition++;
' Z  e# t8 H  E. Y4 S8 @    }3 z6 Y( u* R8 w+ \# I
5 b* y( N; w$ l! k
    // End the string
' j3 M& R, e/ a" l    szResBuf[nPosition] = '\0';
6 ?+ A2 Q) F3 _' K2 s. b) a1 }* f$ m1 ~" G7 N
    // Cut off the trailing blanks) Y, ?6 b9 |" z( S
    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)  }4 e& w4 X* N. D) y. D
        szResBuf[nIndex] = '\0';
- L5 B- y9 [. B; k/ M
: q. h7 ~- U9 u. N. v4 ^8 H0 Y    return szResBuf;
) |- X. |# d+ Q# m. n}
8 p/ V* L5 ]$ {; [//---------------------------------------------------------------------------
4 t, ]* A& k9 s; p) @% ^// Winndows NT4/2000/XP 代码
5 K9 _" N) N  w1 F6 T2 ?& D8 p* U//---------------------------------------------------------------------------
$ I, u' J/ X3 o% Y// ReadPhysicalDriveOnNT) V4 X0 C0 a7 X! S+ I" I  e
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)# k* e- i% ~# J& }+ l1 h
{1 e; }8 y' h7 G8 ~, j) O5 ~1 ]+ X
    // 输出参数
: Q3 S* t" B' F2 d5 y, h, @    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];  N% C# ?% p4 {1 V

7 ~4 Z2 g" Z0 l. I- {* P3 l0 h    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
  H$ Z0 a0 n8 G0 I1 ?    {
+ o/ \; T; Q% T        HANDLE hPhysicalDriveIOCTL;
5 C+ H1 b$ _" T: E: l4 i        char szDriveName[32];
2 x5 V3 g2 Y4 ?
6 \6 d* C3 n! X        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);9 R1 K) ]. F: q& Z! F
        hPhysicalDriveIOCTL = CreateFile(szDriveName,
, X6 u+ J) u* C6 |# T5 I  T                        GENERIC_READ | GENERIC_WRITE,  D: j8 n# x  ^! z' F7 s( V
                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
& ~0 i5 j6 o+ t- m. O                        OPEN_EXISTING, 0, NULL);3 A( P  Q. c, w$ i# Q

5 m( U% U1 G! u8 k, B        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
2 a) [3 n: G/ I        {5 k; T. H0 _+ Y" t
            DWORD dwBytesReturned = 0;
  H7 m3 z$ Q. v# p) b$ C6 n            GETVERSIONOUTPARAMS gvopVersionParams;3 O/ j& Y; W# z
& a" q0 K3 a3 A! O! h
            // Get the version, etc of PhysicalDrive IOCTL
- X! [$ D$ X% L; x$ b            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));. ~& S& ]& v% z7 s" b/ c* g
* c8 a' }' p! ^' U0 N
            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,/ P# ~, c3 |( [+ k4 j( M( I, K
                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),+ d8 A2 t6 |$ ?$ ?- o' r9 D5 `
                    &dwBytesReturned, NULL))
8 n$ a, X, [1 b$ q" s5 j6 \( h            {
/ r- g+ i" ~; z  m" G) O                continue;
9 K6 L1 C0 _% ]% ~            }
; k9 w; Y6 `9 ^' d$ y' \
) w* w' P  c  P* S4 u% K: ^5 b            if(gvopVersionParams.bIDEDeviceMap > 0)
/ \6 U3 _. z; C( }* N# \            {6 |0 q, w( i" N" M
                // IDE or ATAPI IDENTIFY cmd
  C8 {% n$ H, N# b. y5 B# }                BYTE btIDCmd = 0;
8 F* b. B) \2 K# l- Z( }                SENDCMDINPARAMS InParams;  L% Y$ b; k- B: l4 c8 @
                // Now, get the ID sector for all IDE devices in the system.
8 K: L7 {, F6 r& [7 i5 b$ S                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,& m% B. `  ?  B. w: o6 G
                // otherwise use the IDE_ATA_IDENTIFY command! o3 j% r% K/ q
                // 具体所得结果请参考头文件中的说明, P! |" e/ H: Q8 }+ e  V
                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?* E! Z, o0 b! P! h  P
                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;9 t. f; U0 i6 i
                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
5 b1 M+ O% D* q% h1 {                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
, W2 D% s0 ~' e% ?
1 ^# y$ f- q/ Q& g4 X                if(DoIdentify(hPhysicalDriveIOCTL,: E( N7 {) W" s# E7 J
                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
9 f) w, o. G6 N! f& \* A                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
3 g; l' W- G7 @+ e# [* Y2 j' B                {
7 G0 A0 M5 e! R: w                    DWORD dwDiskData[256];
! z! a& f3 Q( Z0 G( g                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
4 `  b! v' l7 f% z                    char szSerialNumber[21];
7 i6 G1 ~  G) F+ `- X3 ]/ n8 u                    char szModelNumber[41];
/ s: G. z) E8 ~5 X. ?; Q; Y9 y
0 q! q7 y! s1 J9 R' C                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;6 l( s# `2 _  o+ a: P
                    for(int i=0; i < 256; i++)9 P+ A# C% \- F( y1 ?6 p! I4 X0 I) O
                        dwDiskData[i] = pIDSector[i];
4 z6 D5 o' l" y1 @! u. x% N                    // 取系列号! R! {" R% O6 G$ p# f
                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));" m. I8 H' a5 d4 w5 R
                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
" O% S4 y) Y9 X. K1 w5 i6 ]
3 [' ?: W- |' q6 z* u  l6 Z8 W                    // 取模型号: @( M% O; b1 |! p
                    ZeroMemory(szModelNumber, sizeof(szModelNumber));
9 x& H: y0 p* y                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));9 l' E2 V1 R0 V2 w4 |$ A
9 I2 @: {& G/ L$ @# u* t' X: U
                    pSerList->Add(szSerialNumber);, n1 o' f9 t& H( E
                    pModeList->Add(szModelNumber);
& {* _' ]1 y" Q+ V) H& b! J                }  f1 R+ j3 O1 G) @7 y1 _
            }$ [' {3 L$ _9 ]0 @( M1 H$ K
            CloseHandle (hPhysicalDriveIOCTL);
; q7 y5 J5 u0 M4 {  }        }
& P0 E5 _& N8 p' v2 Y9 U) ]* q    }/ v; ~/ t" b" D1 r2 p1 I2 ?0 D
}, v1 {3 U* x5 \
//---------------------------------------------------------------------------9 t- H4 t/ a/ X2 n7 I, t) u
// DoIdentify$ t) j8 S) m' l+ j3 R. X
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,1 I# `& g6 F/ [; R
              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
. A& ?# P; \/ @3 M$ m9 K( H# \              PDWORD pdwBytesReturned)8 X: S% Y/ ]" A# I
{
- M! K% Y  s; i    // Set up data structures for IDENTIFY command.& I8 }+ {3 s6 ?, \2 O
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;! I+ ^6 ^  T. H1 W5 }, p' x0 v
    pSCIP->irDriveRegs.bFeaturesReg = 0;4 V( r6 V' i4 t& ?1 a/ N
    pSCIP->irDriveRegs.bSectorCountReg  = 1;5 E, U9 C. J" ?. T
    pSCIP->irDriveRegs.bSectorNumberReg = 1;
, s1 R" \, ^) i5 D2 M: [% }( v    pSCIP->irDriveRegs.bCylLowReg  = 0;
! n7 {' s3 J% ~4 N/ `( @    pSCIP->irDriveRegs.bCylHighReg = 0;8 i# ]3 F) ^8 k( X$ E( {2 c& M! r; B

# S& {# }& n+ s2 \    // Compute the drive number.(主盘和从盘所对应的值是不一样的)
& m8 q+ t- m$ U2 ^# I" d9 E/ M    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;, ~! q4 `# f" z- W; G) U

% w+ s$ r/ R  l    // The command can either be IDE identify or ATAPI identify.
9 Z+ `% [6 K0 _' [% V5 b    pSCIP->irDriveRegs.bCommandReg = btIDCmd;' k" r" d' I1 a4 S9 P6 v1 A9 I( O
    pSCIP->bDriveNumber = btDriveNum;
7 y2 x1 s. h0 o) G9 B) Q8 Y- h) g    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
$ ]$ ^" |+ h% h- j3 D3 G4 X
5 h1 L4 p1 ]. J( e' k- y0 v0 K    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,' t: a3 g; U! ~2 I: Y7 ^
           (LPVOID)pSCIP,
, D  }# J  u4 E1 q           sizeof(SENDCMDINPARAMS) - 1,
9 Y! Y+ J; ?  t: ^/ F           (LPVOID)pSCOP,, |! T, u% ~% A, [9 A
           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
1 V  \0 h+ b( K: u+ K1 X           pdwBytesReturned, NULL);
7 z( {* ?- k& i  Z3 @# v}
/ f" N$ W% s, s2 ^//---------------------------------------------------------------------------$ }3 V! c# F, W6 `
// Windows 95/98/ME 代码
% F+ C5 i5 S/ j5 N, p//---------------------------------------------------------------------------
9 f7 X# U. Z, r// ReadPhysicalDriveOnW9X
6 H. m; n9 j- T. M$ Hvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)
$ L, |6 S4 K& O# T* S, I: B{& B7 k3 G' I( _1 k( ]
    WORD wOutData[256];
( i9 Z4 `" ]8 N! i; `$ W/ c! |    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);8 Q8 p" e% [0 O4 d( E! J3 e3 t
3 @4 A* a( q: i
    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。& E8 j7 g* v4 i. |% G+ \* U
    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
$ F  D2 D& g5 D0 {    // 避免蓝屏的出现。(期待高人能指出原因)
; l/ P5 b  e6 Y' ^& O) ~    for(int nDrive = 0; nDrive < 8; nDrive++)- g& o1 j; R4 q% d
    {1 s6 W8 k0 }  {# z2 u/ R* f9 T
        WORD dwBaseAddress;# }1 [8 a1 @* Y, L
        BYTE btMasterSlave;         // Master Or Slave
( @/ [6 j+ ~. G' o& X' b# Q        bool bIsIDEExist;% t& Z7 i3 q$ M; n: [4 J
        bool IsDiskExist;
; N1 O9 a1 N3 M( ^& w  L( k, h3 |- {: a& M; }! m9 d
        switch(nDrive / 2)
$ Q0 E7 b) E5 I        {5 n( G' x4 ?  p  j' l. x* B/ m
            case 0: dwBaseAddress = 0x01F0; break;3 t  C  [2 X+ c# i
            case 1: dwBaseAddress = 0x0170; break;
2 e* y8 |( Q- G; t# N0 \7 H            case 2: dwBaseAddress = 0x01E8; break;
6 e1 P- y1 C4 Y8 [9 R  r: s            case 3: dwBaseAddress = 0x0168; break;7 J7 d- M0 H6 ^3 J; H3 i
        }
7 R8 L# F* [/ c3 |2 C2 }9 ~7 x
2 D2 ]5 b  k/ m3 N$ ~        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);0 I+ p, Y4 ~; A3 G6 S. t# t8 M

! O/ p, A' N/ J$ V        // 进入Ring0" M4 O7 R% C3 D  L% C, X! H
        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
- p1 [+ s  x8 h8 f$ }                bIsIDEExist, IsDiskExist, wOutData);
0 J- @, e/ }2 O    }
9 g$ o2 r8 S+ P; |* w- V
7 d" ~4 @2 p# `/ _7 R' v5 _    // 开始读取
/ u) w. C6 K: ?. {  \# P. Z    for(int nDrive = 0; nDrive < 8; nDrive++)7 V: h& @* Q! Z2 n- m
    {6 e5 c- }; D+ ~- T
        WORD dwBaseAddress;
% y7 k! b+ j, y) \        BYTE btMasterSlave;         // Master Or Slave
! b1 F) f! x7 s2 L: E( q/ W9 S        bool bIsIDEExist;
% z+ R' t" k$ L1 C        bool bIsDiskExist;  N, b/ [+ |& d
        switch(nDrive / 2)
* Q3 ]; E/ g. B& s& ]5 F$ U        {' x; ~) ]- ?$ l; X- E
            case 0: dwBaseAddress = 0x01F0; break;' i( n, F/ [% w. E8 k
            case 1: dwBaseAddress = 0x0170; break;+ M- Q' V7 c, h- A1 H6 P0 d" E& o
            case 2: dwBaseAddress = 0x01E8; break;# m; O5 M& ~4 X6 x9 T" p8 g8 |
            case 3: dwBaseAddress = 0x0168; break;
9 \& Z0 X( D6 H7 I. ~0 K% y        }
9 y8 o+ V/ r" H  j0 X5 F, \# \+ ]( P2 B% A) F7 h
        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);$ S( H: Q: r4 b3 V' X* ?$ |6 T) j

0 l4 ?! t0 F5 n        // 进入Ring0
  c) ~: u" Z9 g6 \* D, A6 T# _- k        bIsIDEExist  = false;
) F0 E% ^3 [. p0 C; }  y        bIsDiskExist = false;9 @& Y& x9 g, _4 I2 Z7 S* N
        ZeroMemory(wOutData, sizeof(wOutData));
9 Y: v# ]6 b: j  {2 q9 f2 E  b1 t! g" F' M! ]$ m
        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,# \% u6 L4 Z6 Z8 o9 \0 J. j1 B
                bIsIDEExist, bIsDiskExist, wOutData);
5 L0 `! }# C( d  ?; }" j! Z; [5 f* t; Q
        if(bIsIDEExist && bIsDiskExist)
) L7 J3 A; R% a# \3 Z" J        {. V& m$ D. r/ H& ]( |; x8 L+ X
            DWORD dwDiskData[256];
' n0 h) ]6 R* c2 s            char  szSerialNumber[21];
/ W/ v( m( k! E( x, T) A) Y            char  szModelNumber[41];6 f- }  z7 ?7 i

6 k5 J+ M6 E1 l1 w            for(int k=0; k < 256; k++)! R1 R$ s  z9 [/ j. h- i
                dwDiskData[k] = wOutData[k];
. X+ k. P# l6 R# r1 T) c- G
5 W: D/ H" {7 f7 g2 |/ ^            // 取系列号2 C! s4 |- Y4 m
            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));, E1 F" f' r7 C; g
            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
6 }: N, n  f1 a, m4 s# |' M: b# _1 s% q  o$ @
            // 取模型号
9 x" ?: M8 t! ]' \0 `: K9 j6 s% Z            ZeroMemory(szModelNumber, sizeof(szModelNumber));+ U  B( N& t, _4 F8 _' q' M( d, T
            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
$ [# {* ^; N, h2 I* ]
0 C* W, ^5 t; o4 E            pSerList->Add(szSerialNumber);" `6 B5 {2 k$ N9 K' m, m5 F
            pModeList->Add(szModelNumber);; l! o: E5 N; I% o0 }
        }7 m- a3 h  L9 m  ~6 \" i- v
    }
5 x$ s, K1 a* G3 H: r    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
- @. I! y9 T1 W}/ ]  }% ?5 l0 `0 h4 c* d1 F3 A% `
//---------------------------------------------------------------------------& H9 N: H- r: ^% A3 T% K8 u( g
// 为防止不负责任的转载者,在此注明原出处信息,请见谅。
8 V' k7 V$ g4 b9 }: n. Y7 B4 o  ~// 资料收集整理:ccrun(老妖),欢迎光临C++Builder研究: http://www.ccrun.com
9 R& X5 ?& q2 I8 s- u, |//---------------------------------------------------------------------------
5 ]; _% J/ _: Z  t) j// ReadPhysicalDriveOnW9X_Ring0()0 ]' y" C- X; w3 W, d$ @. l
//
! a' V. b9 h% s3 v' O+ C( k// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h' b6 w- q* _; I# }) T
// btMasterSlave = Master(0xA0) Or Slave(0xB0)
  ]' X! a" D3 Q1 y//---------------------------------------------------------------------------
1 j# [. S. \4 p/ `void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,- v5 c8 K5 ?; N3 ?/ G0 o* S9 J
        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
5 A* |. S  O) y. y7 J( G0 L! A( x{
" V3 Q. S% R* v8 r    BYTE  btIDTR1[6];# P; M+ G4 D$ i- @) w% r
    DWORD dwOldExceptionHook;! n" m( B2 x* Z( w9 [
    const int nHookExceptionNo = 5;
) m$ p& [+ _) W. w; O7 t, l% n, R' p$ X& S' D) {2 L
    BYTE  btIsIDEExist = 0;9 d, Q4 t  Y2 B& V
    BYTE  btIsDiskExist = 0;8 E. _# V9 F2 K. H" I0 i
    WORD  wOutDataBuf[256];7 [3 C2 N5 T  F0 W' o% v8 L0 J$ `$ U

, ?/ Y/ `1 U% x- ^    BYTE  btIsFirst = (BYTE)bIsFirst;5 [/ S+ q3 K7 l; @0 v. S- r. Z  D
3 b- \7 M6 E/ T5 b2 H9 y
    const BYTE btBit00 = 0x01;/ f0 J8 ^8 K- w
    // const BYTE btBit02 = 0x04;& s4 L4 c0 o- \0 m  _# c
    const BYTE btBit06 = 0x40;
9 S' E% A' b# e/ h& ?( W    const BYTE btBit07 = 0x80;
! I7 |8 M1 K: [5 b1 ]    // const BYTE btERR  = btBit00;
8 E/ I# K' a5 g* M7 [    const BYTE btBusy = btBit07;1 {3 N7 a( ~% [7 m: h$ Z: d  b" `
    const BYTE btAtaCmd   = 0xEC;
! G  F5 y$ Y' {    const BYTE btAtapiCmd = 0xA1;1 C. U4 s# @" i6 g2 A

( T8 {' Q' d# w6 P4 O& j# o    __asm5 q4 l' t) K. u' o9 N
    {" x3 Q: g) J& _# y) N
        // 必须先执行这条语句
) k* c7 N4 j; e6 r8 k: e2 j        JMP EnterRing0: l; A2 o  E! e  r
; @# g" w3 B/ R% G
        // 定义过程5 O; D) [7 |5 F6 K6 u# l# ^- B
        // 等待IDE设备直到其不为忙为止5 w% J5 _/ g6 O: V( e" s
        WaitWhileBusy proc0 \" e$ r+ @# O7 w8 a, I, j; j

% D* g: J# w$ v8 [4 y8 B% h        MOV  EBX, 1000007 `+ T9 M: s/ b* N2 S# G
        MOV  DX, dwBaseAddress- [9 g1 @/ r- i. k& [  D
        ADD  DX, 7
6 z1 R& r' l; @7 O
: o! O6 @; a  r) |        LoopWhileBusy:
# T5 Q' p1 C2 s, J+ F9 _6 W% m7 z, P" R. R- k* [& D7 h8 i
        DEC  EBX6 C' W& S  n7 K( i) j  Z2 G( Y
        CMP  EBX, 0
% @+ f+ [( |6 X# }2 m5 i' J+ B        JZ   Timeout
! R: Q8 `9 B3 @( B! w) y        in   AL, DX& B3 l; k7 G) l1 |) @
        TEST AL, btBusy( E, H* A% @! h
        JNZ  LoopWhileBusy
+ p8 L7 F' ]( [' e; F/ _$ i        JMP  DriveReady
- W. }( y" |6 w2 e8 ~& ]8 P, {  `! w( j
        // 超时,直接退出
7 n- ]% O( q6 C' K        Timeout:6 h- ^: D7 `) Z
        JMP  LeaveRing09 w- M. D, F) l8 _4 E) [# n
        DriveReady:! i. u( w/ p! V6 P1 ~
        RET
1 ^3 f* @' y8 i8 O( F3 {; R% F. ?        ENDP   // End of WaitWhileBusy Procedure
7 {' i0 C: X- r! \1 N/ y/ ~
4 P' U( j7 D$ S( z$ }        // 设置主盘和从盘标志
3 E& M) V1 q: d: x- c9 B        SelectDevice proc
$ j& v! Q4 |9 o, T  H( Z9 [6 J+ C0 G/ z1 q* h
        MOV  DX, dwBaseAddress
2 \9 s4 D+ e+ u1 V9 d5 C$ }- Q        ADD  DX, 6
, I. `* j( Y6 Y) H; g        MOV  AL, btMasterSlave
" Y+ ], {4 G% l% \4 c7 e! o0 \
; A/ a8 l  g1 u' E# E4 ^, B1 k        out  DX, AL5 [4 z% I3 M& H9 q
        RET
/ E1 B0 l. j/ x3 F+ e' v/ r: _6 B! L# h9 s8 ^4 m0 l2 y8 P, u& ^
        ENDP  // End of SelectDevice Procedure
5 k/ K$ F" ]& @, P$ k6 T& R. Z8 ]# W9 z: _/ U  P9 D8 m+ I$ N
        // 向IDE设备发送存取指令
9 K: C2 B0 {+ x8 B        SendCmd proc
' l6 E' K1 K2 C' q8 K
, T: b( [$ ?2 ~% e9 e/ D        MOV DX, dwBaseAddress
( ?; I( y" Z; O9 n! [3 \        ADD DX, 7% N  G$ ~' M& g, u5 X1 C
        MOV AL, BL // BL是主从盘标识,在过程外设置1 P* e5 f8 T  a: F$ f
        out DX, AL
, L. M! u. |+ J: D/ Y5 \' W        RET% u" d; ?) D4 |0 ^' Q
        ENDP  // End of SendCmd Procedure
1 S5 z- p/ O3 c3 I4 y  Y# C0 q( r* f( \* A: y) W
        // Ring0代码
3 }! e  u7 f& _! t$ v* q9 D/ F        Ring0Proc:
! R& \; }9 u+ @! l' M0 r* T        PUSHAD
3 D+ p( r$ f5 h3 ?        // 查询IDE设备是否存在
9 V7 d* D# k* w- [# {; b, B. z        MOV DX, dwBaseAddress! A1 j' x$ M/ Q9 y! ]! k3 O8 w
        ADD DX, 7
2 _$ j: h! ~" {1 c" q        in  AL,DX
2 B- W; R+ @8 a: e1 T' {& Q+ X0 A% a! M
        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
+ {: s% X, d( P        CMP AL,0xFF
1 j3 E" _6 W, Q) D  C        JZ  LeaveRing04 a$ M& U& i: G* i6 r& x7 F; U
        CMP AL, 0x7F+ k" {6 e' H  O
        JZ  LeaveRing0
1 ?! R( z6 U% _* y) U) o" k, n
7 W. C' o* K( Y4 R  g! b3 M# j+ C+ X        // 设置IDE设备存在标志& t' k  n" R; y; m: f
        MOV btIsIDEExist, 1' c5 P: Y: Y) Z2 ?6 X
5 f& E+ G$ O1 R" [9 W& Q
        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
9 f/ y+ R* d5 ^0 e7 h8 Z) F/ i        CALL WaitWhileBusy
  {/ U8 J1 j, B# a, x' w        CALL SelectDevice
. f+ z4 r- d8 @5 d; [; J7 O- l6 P: C- d" x" p. m& K8 z; Q
        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏9 [; E" ?' a0 [# M
        CMP  btIsFirst, 1
+ k7 Z2 T" X3 A1 r        JZ   LeaveRing08 s/ j* [3 m' c

' e5 U& Q, d  C5 A        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
$ k: z/ l: a( e  N# s; v) U5 G        CALL WaitWhileBusy& y9 l; n* p8 f3 c8 s% A3 K2 A8 q

* {$ E& @; \0 \# L8 U6 r        // AL的值等于cBit06时,不存在驱动器,直接返回  f) k* n7 p8 }+ U9 C5 A# C
        TEST AL, btBit06
$ X9 c3 V" p! r        JZ   LeaveRing04 v( A4 D7 ]; D+ U/ ]" \7 @, ~

, w  h# ^$ E. k: L4 ^# P! Y        // 设置驱动器存在标志
  T- [0 B- o, Y2 h- @        MOV  btIsDiskExist, 1" B" W5 r- K1 o; S, H% H
" V! a/ R1 a' @9 x
        // 发送存取端口命令1 e) Z1 t7 A" \! t( l( j$ l
        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,. y8 v5 g! l' j" J6 n8 N/ a  Q; @
        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
* o2 s% I: Q$ k        CALL WaitWhileBusy5 B- p% ^8 }# `6 F5 \% t' x5 z
        CALL SelectDevice    // 设置主从盘标识
0 F4 J4 ^" [/ Z6 L# m        MOV  BL, btAtaCmd      // 发送读取命令9 y# d+ Z- D" ~: ]! I5 }9 ]2 D$ m
        CALL SendCmd
% F  u! |) F# a" Y        CALL WaitWhileBusy, Q. O& E; y7 s' h( y
: i% a) X( o5 s
        // 检查是否出错
/ V2 S3 G/ A4 o        MOV  DX, dwBaseAddress$ |7 h! f" M% V0 K0 R4 \
        ADD  DX, 7
3 p& t+ I' U8 p0 q  R5 s/ f  c1 R
, j: c  D; F1 G        in   AL, DX% K7 U' |( l8 r0 H" c' ^$ {2 a* e

8 N7 g; E# S( t- q        TEST AL, btBit00# Y" t, Y, l+ \4 D9 \
        JZ   RetrieveInfo   // 没有错误时则读数据! c( d% l/ Q  I/ H/ |* w
: _# |5 o7 X8 `$ e
        // 如果出错,则进一步尝试使用ATAPI设备命令' u: k! P, b- W2 W" w5 A) p
        CALL WaitWhileBusy
9 }; U! C- @$ S" F# ^        CALL SelectDevice/ x& B" J/ ]9 Q; v5 Q, x& ~
        MOV  BL, btAtapiCmd
$ P( e& U( P4 V2 a        CALL SendCmd
9 Q) L$ v5 K5 n; v- C: X        CALL WaitWhileBusy
# ]) W9 g% Z. M) Z8 K9 X
; D% Z" q8 L; f+ f1 m% u/ S        // 检查是否还出错0 |! B! V/ _& e& y5 `
        MOV  DX, dwBaseAddress
2 D' I2 [$ `! B# V        ADD  DX, 7
* k2 W: b/ G* Z% O9 B0 [        in   AL, DX( ~5 b$ D. A! |2 }
        TEST AL, btBit00/ }8 @9 J* d6 n
        JZ   RetrieveInfo   // 没有错误时则读数据- \) ^; k  ~& k( Z* }4 r, N
        JMP  LeaveRing0     // 如果还是出错,直接返回) Z) h) s( p4 M4 w3 N6 b4 D  R
( }- P5 b* U  W' R- k' n
        // 读取数据" h! H% U5 [, v2 a) _: o
        RetrieveInfo:
) M  ^$ O# {" v: j' u$ {8 B
* v" |. i. ~. z4 m4 j( y. ?        LEA  EDI, wOutDataBuf" d6 R, K5 G/ \8 n
        MOV  ECX, 256
! }  G/ H! X1 Q7 b        MOV  DX, dwBaseAddress
& z; u/ P2 `, U& |) O- G        CLD% I$ J) j9 g! T2 {3 Q
. ?# k' d2 R" A
        REP  INSW& n/ t" D/ j- }
* @1 Y4 M6 i* d2 D5 D( u- Y/ y9 a
        // 退出Ring0代码2 t  j' r( ]! ^* l
        LeaveRing0:' H! P! C$ x3 c1 m
  G8 j3 u3 {. e/ j0 D
        POPAD0 D4 K; Q5 |9 ~8 |, [0 y( c
        IRETD
; J5 l- K7 A8 m
+ N' o+ E$ L8 H1 X  L        // 激活Ring0代码
5 P3 V( N: w- |) D9 r& A        EnterRing0:
  s) D  A7 L  ?6 S* E. O8 u+ N) L: q- R, \7 Y
        // 修改中断门
2 h9 ~4 K' y$ c5 `        SIDT FWORD PTR btIDTR19 p# H8 `* c; |) l
        MOV EAX, DWORD PTR btIDTR1 + 02h
! i- B% y2 N* O. [        ADD EAX, nHookExceptionNo * 08h + 04h( e/ r1 m0 V% i! G
        CLI
: C) l& v, I, M! H5 r% B( O: v
) C7 ]. ?5 V% N' C7 y        // 保存原异常处理例程入口( \" t1 K7 p% x+ o8 H: j. C- ]
        MOV ECX, DWORD PTR [EAX]# @9 f& P# V9 g+ j4 I
        MOV CX, WORD PTR [EAX-04h]
/ L6 }7 B) v/ W5 d        MOV dwOldExceptionHook, ECX
% M" {' R/ ^4 ]/ O$ P* O; Z" P% ^3 u( K- r2 E+ N: j! L
        // 指定新入口: P$ }7 b' m& H( |( P* t
        LEA EBX, Ring0Proc
; w6 b* E2 \" W  R& \5 z        MOV WORD PTR [EAX-04h],BX
: g) f/ z+ j0 U, e. I        SHR EBX, 10h
  }6 j" m/ t* b0 V: n2 c        MOV WORD PTR[EAX+02h], BX
' h* q% q8 A, l7 q6 c! r
7 c0 Z! M/ A; p3 Y3 S4 Z& V0 @) v        // 激活Ring0代码" V: G% k5 S# R7 o* c1 y& A/ j
        INT nHookExceptionNo
9 _, t" s; U  }: B1 _  ^- V$ }/ S) [. O: ?+ X4 J# d
        // 复原入口; A$ D( V) p: C5 M6 S5 y
        MOV ECX,dwOldExceptionHook  p: R1 v' y4 w; h  @$ l
        MOV WORD PTR[EAX-04h], CX  o0 }! `# i5 ^% O; v
        SHR ECX,10h+ W. r- M) H$ F
        MOV WORD PTR[EAX+02h], CX
5 d% J: p# [9 K: c        STI
0 a& l, ~6 }* c  w0 L: S, F0 l    }
- |, x5 y' L/ j8 Q) G8 y8 s6 r0 ~    if(!bIsFirst)
. p' [) q$ p. w" V; p    {+ L2 c' o& C9 u; \/ ^5 U
        bIsIDEExist  = (bool)btIsIDEExist;
+ B* x" j( U9 d        bIsDiskExist = (bool)btIsDiskExist;+ x6 o$ ], U6 |8 ]3 _' D
        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));) b! {3 Q3 ]. A; i. B+ U* ]
    }
7 e  x# n# M7 `, W' n}( u+ Z/ v; Q. d1 G/ `/ C) A3 H
//---------------------------------------------------------------------------
0 S( T7 G( i1 `- G0 G! {// 调用方法:
2 @6 o  o. G: ]# [* V5 |void __fastcall TForm1::Button1Click(TObject *Sender)  e( \7 c* L8 R! b
{) W/ k$ s6 ]. k* d. J
    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);& @% {+ O- h0 w) A# K8 k, [
}- \" g6 y) r. t
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-8-13 22:41 , Processed in 0.021712 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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