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

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

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

  1. 6 f% z# n, j1 a/ N3 _
  2. #include "StdAfx.h"
      F' g; t  v5 T( y; z5 A' `9 E! Y
  3. #include ".\puiddisk.h"
    % M0 a# W- \* ]: w. M/ I
  4. #define _WIN32_DCOM+ j5 {7 N% n6 O  R9 R
  5. #include <iostream>
    ( v7 V7 U5 b, k* ]2 A
  6. using namespace std;
    : E- ?" p  [5 o  m
  7. #include <comdef.h>9 l. d; P, W$ Y) x; g1 e# n
  8. #include <Wbemidl.h>
    . ?7 e; l7 @9 V8 S( v, P
  9. ( ^# Y4 ~% B' T" c! b; C1 S& j
  10. # pragma comment(lib, "wbemuuid.lib")
      w1 t; a& L6 H9 i: [  t" L
  11. CpuIDDisk::CpuIDDisk(void). n$ d& S. V& t  H, ~4 n: S( G
  12. {
    : o+ k& ?3 m& p2 B
  13.     GetInfomation();
    ! A! O8 W8 h( v1 l; t# k, [
  14. }, N' l  Z1 A; I3 `# S; u# g* H) {; s' [

  15. 8 v# ^) ]0 E/ i/ z$ d. y6 u8 Z
  16. CpuIDDisk::~CpuIDDisk(void)+ \% i& y+ q- i" D: {( H
  17. {
    4 {% s: |+ t$ n
  18. }3 J: v- c! }3 V2 ?0 P( x. g" w* @  X& W
  19. int CpuIDDisk::GetInfomation(void)# k( |' K1 v; ]/ h( u. e
  20. {
    6 N9 ^0 I9 @# ?% X- J
  21.     HRESULT hres;7 J# W; f% w7 F% c1 U
  22.     //步骤1:不是必须的,COM只须也只能初始化一次( S& H) X; P9 F  G2 o1 d
  23.      hres =  CoInitializeEx(0, COINIT_MULTITHREADED );, r) e* n9 C; T' S& Z
  24.     if (FAILED(hres))
    0 i+ I% v* \) D4 Q5 k
  25.     {! [+ x" b# u" s2 w
  26.         return 1; //初始化COM异常:注意,COM只须也只能初始化一次
    9 J1 m: h& ?1 u2 M+ x9 O
  27.     }
    ! E; A# B5 }2 R' w$ }1 W
  28.     //步骤2:不是必须的,COM只须也只能设置一次& E& }! G) I( q8 @% ?
  29.     //Set general COM security levels$ I. C0 ^: i  ]7 p
  30.     hres =  CoInitializeSecurity(
    6 z% T* ~% j9 N( N$ {  Q
  31.         NULL,
    + I* z& v* R# i& F( W
  32.         -1,                          // COM authentication
    7 @; u; T: F7 y9 T
  33.         NULL,                        // Authentication services1 t. g- ~8 D) P8 M5 V/ A. B
  34.         NULL,                        // Reserved
    ! I6 b, g& x4 F  v2 `0 D
  35.         RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication 8 F0 G/ j, i* P! K
  36.         RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  " J  F0 S& I# J# r
  37.         NULL,                        // Authentication info
    7 N2 ?% {' W5 _, c! v
  38.         EOAC_NONE,                   // Additional capabilities
    1 O) v1 U3 @; y
  39.         NULL                         // Reserved
    3 n1 z- B% Q% i/ {0 E' Y- n
  40.         );. G+ j% v$ L% E7 L& s6 f
  41.                       + n  J) c7 }7 |: _
  42.     if (FAILED(hres))
    $ O  @: Y7 U' e1 T, s0 L# ^
  43.     {4 V3 ?8 u4 }' ~2 T; }
  44.         CoUninitialize();+ c3 _9 ?" _) `4 ?$ A# ^
  45.         return 1;                    // Program has failed.9 _3 B) c& l7 H4 r
  46.     }. p& w* A) g0 f1 s$ }
  47.    
    6 |# l* j: I& O) i
  48.     //以上不是必须的,若已有“::COMInit();”,则要跳过4 u4 l9 K7 L, s' `* m- ^" E
  49.     //步骤3: Obtain the initial locator to WMI + d. a  ^, l6 a+ A( R0 x: g
  50.     IWbemLocator *pLoc = NULL;/ x' V) n+ Z4 _0 ^1 v, x
  51.     hres = CoCreateInstance(0 G% t4 n1 {4 V* N+ ~( |9 s
  52.         CLSID_WbemLocator,            
    6 @( j6 ~. D$ n
  53.         0, ( N% A: n8 p# S& I
  54.         CLSCTX_INPROC_SERVER,
    % h  D& D1 c( B- B0 D6 s
  55.         IID_IWbemLocator, (LPVOID *) &pLoc);$ M, E( v1 e8 t# ?& R$ B  ~

  56. 3 O& H3 I7 g4 U# I+ {
  57.     if (FAILED(hres))
    0 V+ Q0 K6 a7 C% A5 G: @
  58.     {
    8 q, M6 f/ v3 z, E& z
  59.         CoUninitialize();9 I0 D, P- W' `/ v/ u
  60.         return 1;//Failed to create IWbemLocator object
    $ [/ @& f2 ~, e6 t
  61.     }% B# e6 o& |& ]+ s

  62. 8 ]3 D0 f, ]1 M0 A1 W
  63.     //步骤4:Connect to WMI through the IWbemLocator::ConnectServer method
    + a' c, l( D3 i4 X
  64.     IWbemServices *pSvc = NULL;3 R% g, K9 D, U( K: u! b# |7 f  U
  65.     hres = pLoc->ConnectServer(
    ' G  a) u1 A% v" I7 X
  66.          _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace9 y& n' L7 M6 J8 T0 O
  67.          NULL,                    // User name. NULL = current user. ?; T9 U' d( \2 o$ J4 [
  68.          NULL,                    // User password. NULL = current
    # o( s( p/ X8 X
  69.          0,                       // Locale. NULL indicates current. n1 r. ?# ^. J7 @; o
  70.          NULL,                    // Security flags.: [5 H/ O& @" `0 H7 e" ^7 y
  71.          0,                       // Authority (e.g. Kerberos)( E4 H2 z% J/ X- I: S
  72.          0,                       // Context object
    % q! H5 X: d  f3 b
  73.          &pSvc                    // pointer to IWbemServices proxy7 s& W5 H6 Y. k8 F5 z  Z5 k( N" M6 T
  74.          );  w# U- t$ W) I8 T) D
  75.    
    0 }1 `& f( [  ~* V
  76.     if (FAILED(hres))5 B! H  g  t& g1 s0 y
  77.     {
    0 [& S* A8 g: J% o, `5 b; U% S
  78.         pLoc->Release();     - f; [. _* A% c5 s( b, s; G
  79.         CoUninitialize();
    ; M6 Q" C% d/ X7 f! p. S; W5 G
  80.         return 1;                // Program has failed.
    , Y: m, d$ j" w1 ~6 T
  81.     }
    ' {% S: C+ z0 A) J# \) R
  82.     // 步骤5: Set security levels on the proxy, Y0 I+ T* w! b) f3 [; E
  83.     hres = CoSetProxyBlanket(, S% T8 e* v0 i# |* T! H
  84.        pSvc,                        // Indicates the proxy to set! q8 `8 o" f+ c& H! f  A
  85.        RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx
    # z& [) ]* t. Q5 n7 L0 q# s, w
  86.        RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx9 d7 |( R, D3 ], J; h
  87.        NULL,                        // Server principal name
    , o% y/ W  d9 ~( E$ R' U
  88.        RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx 5 K+ F1 w/ P; J) ]0 e
  89.        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
    6 R6 X& |9 F. q( h
  90.        NULL,                        // client identity, `, `/ U: M3 {5 D  R
  91.        EOAC_NONE                    // proxy capabilities   C; y1 I, q* O# v
  92.     );7 k- D; c0 X& ?: D6 r1 m9 c& T6 ?
  93. 3 `0 J0 }0 E' Z  I; I$ A) u! T3 i$ y1 I
  94.     if (FAILED(hres))
    ' J  `. @, \" y" B1 R0 n& G
  95.     {
    8 X8 Q2 y7 i4 g. K1 g) ~7 D
  96.         pSvc->Release();
    9 M- t) i5 V7 Y- a- {: S
  97.         pLoc->Release();     
    - F, g- y. b# ~7 `) T
  98.         CoUninitialize();
    : }3 v( I% ^" i' `6 k
  99.         return 1; $ T4 S2 W& F+ i3 W& k, i$ l0 `% K
  100.     }
    8 e0 g" q' W9 Q) n8 f
  101. - D+ f% x7 h" V6 A3 K. f  j
  102.     // 步骤6:Use the IWbemServices pointer to make requests of WMI ----
    ! |9 w; Z9 S; q- G$ y  a3 `
  103.     IEnumWbemClassObject* pEnumerator = NULL;
    , o8 \( E8 z, U% T) p2 H2 `$ V
  104.     //计算CPUID1 X& a8 y8 }. C2 e
  105.     hres = pSvc->ExecQuery(' J5 T+ _; ^) C4 l6 Y  w7 r
  106.         bstr_t("WQL"), 7 y$ k2 {- `8 f
  107.         bstr_t("SELECT * FROM Win32_Processor"),//Win32_OperatingSystem
    ' I& W3 q6 K* [  Q# P& O3 i% z( g
  108.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
    ! {  f" }3 b) W( p$ h0 E
  109.         NULL,8 i5 W, D# ^. Y! K% F
  110.         &pEnumerator);7 S7 B" n/ o" ]/ t
  111.       Z) ?0 M! l3 |2 m3 F
  112.     if (FAILED(hres))
    ( x9 \* G) U' e$ `  t
  113.     {
    * |- A! O- [, V8 X& S/ X' ~' N
  114.         pSvc->Release();
    : }6 j% v$ d. G) `( V2 W
  115.         pLoc->Release();: }$ L7 W& x) Y  j
  116.         CoUninitialize();
    4 S- x2 k' R* y' h4 \' E" [
  117.         return 1;
    & t2 k4 D$ \  q
  118.     }
    & [! C" C- ]3 J2 X8 O8 R
  119.     // 步骤7:Get the data from the query
    . U: ~( f( [' b5 ~+ S
  120.     IWbemClassObject *pclsObj;
    2 j+ ?' Z* R2 H2 T* C5 @
  121.     ULONG uReturn = 0;
    ' K2 J. _( u6 G, e
  122.     while (pEnumerator)
    " t6 T+ X+ r9 q% d. q1 B
  123.     {5 K- g* z- J# C/ l, L
  124.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
    , `, w; e8 h; k1 \1 t
  125.             &pclsObj, &uReturn);# u6 \7 w5 T4 B! T/ L

  126. $ \7 @& I* n1 p! t* Q  V
  127.         if(0 == uReturn)3 s  c1 w6 b7 m; b2 `
  128.         {
    6 n' v+ }" C# h$ F
  129.             break;6 P% L$ v# @: O. C6 X) Q* ~! z0 Z6 c
  130.         }
    8 a: U6 O* N3 _; e; i, d
  131.         VARIANT vtProp;
    . ~" L- x% G' W( g, }2 z
  132.         VariantInit(&vtProp);
    + v4 Y9 D  t! l1 q8 {& Z8 m4 T
  133.         hr = pclsObj->Get(L"ProcessorId", 0, &vtProp, 0, 0);
    9 t9 m6 |2 s) Z0 z
  134.         strProcessID=_com_util::ConvertBSTRToString(vtProp.bstrVal);//strProcessID:类级变量9 Z! [$ f. ], S9 b
  135.     }; @5 g* Q9 r7 I' ?
  136. # `7 D9 c- J3 {' z! b1 R2 ~0 [
  137.     //计算硬盘系列号
    ( {0 M; {' C5 t
  138.     hres = pSvc->ExecQuery(
    % i4 L, {; O1 {: f
  139.         bstr_t("WQL"), ' N" f/ d- s( f) H) [2 l4 `
  140.         bstr_t("SELECT * FROM Win32_DiskDrive"),
    2 C+ c: ~6 K3 W" U1 ?
  141.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, * ~8 i% x6 n  u: _2 p
  142.         NULL,! X" l% _! w, w+ u  H5 K9 v
  143.         &pEnumerator);$ b% Y. O- l, }0 J  Q# @; w1 E) }
  144. ' F. g  k& S! L1 {0 ^7 i, n$ q
  145.     if (FAILED(hres))
    ' ?/ m, f; m- X  Q5 ?
  146.     {! t0 m- I% ~/ V1 x. K
  147.         pSvc->Release();
    6 b" O) c# `* Y  a3 e! p0 Y+ D' L) c" w7 ]
  148.         pLoc->Release();! m5 U2 }  t* c! Z# t
  149.         CoUninitialize();! o. Y2 r1 V7 X% [" r* i
  150.         return 1; ( a; ?  a' v" K  j& e
  151.     }
    , N* M6 A3 \9 f- x( Q
  152.     while (pEnumerator)0 W  [5 u' l/ Y
  153.     {
    $ ^- \6 R) V/ Z' R% \4 g; N, R
  154.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
    / n  J# o& u2 w7 Z* T# z6 G+ C9 T
  155.             &pclsObj, &uReturn);
    - L2 K1 F: H. s5 |  z/ k
  156. # ~* b" W7 n" y! `0 v
  157.         if(0 == uReturn)
    8 v* l3 q4 W  ~* Y) Y* X3 d
  158.         {7 k7 m( w! q% a9 _
  159.             break;
    * {% Y6 g- C6 C2 ~; t# j7 O
  160.         }8 [; V: G  J4 l/ g! }& h5 d
  161. : u1 v  G1 b1 v$ a' Y. {; j
  162.         VARIANT vtProp;
    ( P1 Q; @8 [/ q1 G% {8 M; r% r, x/ V  j
  163.         VariantInit(&vtProp);! H3 H/ t; C1 |# B5 ]2 _; J& A
  164.         hr = pclsObj->Get(L"PNPDeviceID", 0, &vtProp, 0, 0);
    & b# Z+ R6 y; D% s
  165.     strDisk=_com_util::ConvertBSTRToString(vtProp.bstrVal);
    7 V2 Q8 h$ H" t; L7 j+ b" }2 I. c
  166.     }
    & z* t3 @: V9 a! y; Y1 R
  167. ! J! B$ V+ @. O* ^9 J* q3 T+ X
  168.     pSvc->Release();
    + h' i* ~3 v9 M* T8 }
  169.     pLoc->Release();
    . o( {. o" o+ Q
  170.     pEnumerator->Release();, ^; a- K, D/ `+ e: x9 T! R, N
  171.     pclsObj->Release();
    & Y/ S* _# u' ?
  172.     CoUninitialize();
    1 q- }2 Q% e. e' s" m
  173. / P8 p8 ~% Y9 G7 `1 |
  174.     return 0;   6 y) O9 ^; [+ C* v
  175. }8 d, P3 k+ C8 B; X
复制代码
 楼主| 发表于 2010-10-11 19:21:05 | 显示全部楼层
本文代码经ccrun(老妖)在Win2k下试验成功.% H) P- M: z# @; i% p" C

& X; c$ ]- W# x4 l% V4 b#include <WinIOCtl.h>% Z- D! I5 n4 O: _, g& q
#include <stdio.h>
: `+ O. U0 \0 P. a  [( h( t! ~1 [9 j- p& h
#pragma inline4 [  F! p; v9 L6 H  N; p3 w, V' S, \
//---------------------------------------------------------------------------
- w5 H6 W; j" p9 J" G2 s8 P// IDE NT/2000/XP专用变量
. m+ ^; B2 j$ J" U- S& n#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
  k5 M% e: Y  d6 b/ A#define DFP_GET_VERSION         SMART_GET_VERSION. X8 K  G. |. ]2 Q8 x4 R
#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
. W8 ~) a- A$ w9 _# `4 W#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
! @6 R* x  l* o' x6 G0 K3 k1 R& q" w) u. o% ^6 M. H7 `4 E" L' k  O
const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令8 a' Z, L, J( |$ T0 ]
const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
/ v' I. L* N" c  \. P9 S; m5 m  h& u
const int MAX_IDE_DRIVES = 4;, @$ j1 R0 R5 a: y; P
% x7 o. M. o0 a* ]
// SCSI专用变量
) d* j; n" v. G$ u# \  q' |const DWORD FILE_DEVICE_SCSI             = 0x0000001B;9 C2 \; `7 A1 R9 T
const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
: \  F, Y( W$ \( A3 ]. P( L7 X% Gconst DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
/ w# u; w6 a2 dconst DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;5 b" d) c, R: S1 v/ c  p

  B! _, x. ^- X8 E8 F4 s8 Qtypedef struct _SRB_IO_CONTROL
5 U9 ~% ^$ Z" J: l{" Y2 k* I% V" b2 f' `  T
    ULONG HeaderLength;" ~' x4 z4 L! S# |1 F; [! G3 w
    UCHAR Signature[8];
4 o$ N& T! |9 u+ L& q! ~$ c    ULONG Timeout;4 i4 S7 ?/ l: O
    ULONG ControlCode;% |9 `3 e. S& N* c! Q: Z4 n
    ULONG ReturnCode;+ h8 E+ p" r" F: c0 ~1 `
    ULONG Length;
  C! X- _8 H( N5 N4 ^2 L$ i}SRB_IO_CONTROL, *PSRB_IO_CONTROL;5 S: I: \, X! a
3 M$ W5 m- F, x* ]4 m
// 读取的主函数! f, M3 W' _( t5 Y/ S
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);" H$ r: i4 \3 `+ F
$ s) m9 C, S( ^' f  f/ W  P* x, R6 N
// 辅助函数
8 X) N" M2 M% c% I7 d3 x& Q- S6 F! kchar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);+ p" v8 g) q8 y1 o6 r
// NT/2000/XP函数
2 N- u* [5 h: p0 I% C7 _+ i1 s8 Cvoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);9 w! Y# Z2 S! g+ q- L* k$ I! g" Q
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
/ J0 p$ ~8 c% s; O0 ?; C        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
9 d4 Q2 G! V; y8 B; E        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
0 g# M  H: h4 a" Z// Windows 9X函数
5 t- V: f$ }9 ]1 ]+ {9 y  w' ~/ H6 `void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);" P% e7 V; r1 T
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
8 Y  N" J5 e! _3 J+ F        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);& T( ^  ]2 T* A: h1 {' e4 f

5 \6 V5 `8 Z+ b+ I3 C, F// SCSI读取函数(for NT/2000/XP)" g: ~% _2 x% V5 u' q
String __fastcall ReadIDEDriveAsScsiDriveOnNT();
. \1 z" a! p8 R# s; U* ]# i//---------------------------------------------------------------------------
/ Y2 F1 u3 [# o9 d$ v, r# R// ReadPhysicalDrive
5 ?/ B7 X1 v# Z/ }: |! Vvoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)% @5 {+ r$ v9 ^* o3 L) X1 `. ]
{
; [) N7 v7 z  O: \  J$ \8 w    switch(Win32Platform)
2 V: e* R# b( ]  E; R7 P* m    {9 C: o. v+ A4 C7 `! z% i2 ~
        case VER_PLATFORM_WIN32_WINDOWS:( X# S/ w8 I0 K6 X' E
            ReadPhysicalDriveOnW9X(pSerList, pModeList);
- L8 R, P  o# x+ r            break;
& p- q) b( F) ~" p0 k3 m9 i: y        case VER_PLATFORM_WIN32_NT:. U- w( V! ?) Y' ?8 X5 X4 `9 N
            ReadPhysicalDriveOnNT(pSerList, pModeList);
& z# W: F4 s! Y4 F            break;
! E  l0 d! h9 L7 {' R6 D- m8 d        default:6 n/ j1 M2 |, h3 i7 u+ }
            break;) h! |% v+ T) E, ]5 R6 b% ~
    }
& ?2 m/ z; T, w1 Q* _}
: O9 q, Q% P- S. h* X1 |//---------------------------------------------------------------------------1 s3 Y- R1 v/ @6 M9 I7 x
// ConvertToString8 \, l1 T4 E( A/ q% }
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
1 T; ]; t6 S% d) D7 ^{
: W. T6 ]. C1 W) }+ I; A9 n    static char szResBuf[1024];$ F2 Y5 x; L8 b5 J. O# c
    int nIndex = 0;* j2 y; ?, _2 |; V+ B8 L
    int nPosition = 0;
( G/ @$ u/ h9 n; t7 f  G8 W& N* E, H8 S7 J) G- j
    // Each integer has two characters stored in it backwards
2 E* f$ k3 I' ]    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
6 p+ U4 q* q8 @6 k0 X    {
0 K) v" U' ^) h% }% a        // Get high BYTE for 1st character
" b2 C( U, s4 F" [6 ^        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);/ h. e0 R: V$ q" f$ o" M
        nPosition++;& m! X0 J& q8 T! ?, t" i8 y
0 j2 D' @8 f* `
        // Get low BYTE for 2nd character8 y4 m$ v; B) A, m. t
        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
# p) t& K9 I/ P1 F! j1 ~        nPosition++;5 R& j: h" y; X
    }
1 g' ~# h! T: w7 Q5 z' z! ^7 w) H8 u3 a7 e
    // End the string
9 d2 l* G( A! h    szResBuf[nPosition] = '\0';
5 x/ Y8 M( ~+ Q* k
3 [2 P% Z3 V9 V    // Cut off the trailing blanks9 [! B+ i0 w8 F7 M1 Y& c/ C* E
    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
& `5 f! W, T; f# m" v        szResBuf[nIndex] = '\0';
% g6 Q! j! K. L  i& q. b4 Q
) o5 P7 ?, E8 C    return szResBuf;% a! _+ B+ S' X
}
# R' c$ @3 ?* B0 }  e//---------------------------------------------------------------------------
" q& D; {( d6 _: ?. p4 y8 z// Winndows NT4/2000/XP 代码1 c+ Y# t+ Y: R5 T
//---------------------------------------------------------------------------$ O$ A: [( _! k6 T% a4 |. }8 h$ d
// ReadPhysicalDriveOnNT0 i- _- I5 Q2 e1 D& @, U% c
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
' h9 N+ _3 @) S  ?- N{/ o8 p! N% n: P3 g' A. b
    // 输出参数5 I4 d4 ]+ l! v* F+ R% B
    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];: p3 E$ s) c& |, m" Z, l
2 ^, }% g' R% O& Y2 e0 J2 B4 f
    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
6 J7 y" q" m5 Y    {) N- q4 Q- b5 c$ ~
        HANDLE hPhysicalDriveIOCTL;
  l" h0 f, H% B$ r        char szDriveName[32];
* P0 j0 S2 F$ n
- a, y$ N! Q" d9 f# Y! j        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);& v& O9 s0 V+ s
        hPhysicalDriveIOCTL = CreateFile(szDriveName,
' w6 r! j& T& |$ q! A                        GENERIC_READ | GENERIC_WRITE,
1 S, `% _( D8 g7 K: H                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
  P- T1 |. v- @- F- h- j                        OPEN_EXISTING, 0, NULL);6 N2 I: j. e( g& j# `

% j4 l1 f$ u6 \$ `. j        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)! Z+ n% \$ G- K" l, \2 {2 e& w5 d
        {  |/ {6 ~, B- j8 m1 Y
            DWORD dwBytesReturned = 0;
! C6 Z( C5 _4 F- j3 A+ b; O5 s            GETVERSIONOUTPARAMS gvopVersionParams;
" j7 S9 H; h4 w, r
2 ~5 U5 j" a, D5 s3 w2 y/ m" `1 g% _            // Get the version, etc of PhysicalDrive IOCTL7 J) `& r9 G8 |. T
            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
' M3 r' O$ I3 G5 W2 \9 T) N
7 C' x) V* @1 A            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
  _6 Z" H$ F# y2 m9 A                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
. l' F  S1 g8 ^* x8 n; q+ r                    &dwBytesReturned, NULL))
9 J2 ~  z( N$ m/ p. M2 K& P            {) r5 r6 [2 f% V! \# y5 ~" f+ E
                continue;
2 U2 f* W' d: D6 n            }; K1 V* ?7 f( E( E% n

+ y5 r7 g, Q: H, ?' O$ H- P  G9 g- _            if(gvopVersionParams.bIDEDeviceMap > 0)
7 [6 h/ A& U$ ]! |7 P            {6 k! W  O! c/ M3 P* u" M* u5 e
                // IDE or ATAPI IDENTIFY cmd
: j" Q: m) H1 z2 S9 ?2 @2 v. P                BYTE btIDCmd = 0;# K: `0 J# m$ x
                SENDCMDINPARAMS InParams;2 B, f. Q2 g! ?" h
                // Now, get the ID sector for all IDE devices in the system.! w: E* F! k0 R4 @( ?0 j
                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
# S0 `; r# V  t* |; G1 y                // otherwise use the IDE_ATA_IDENTIFY command
, ~* P: T4 v/ P, H0 s, X                // 具体所得结果请参考头文件中的说明* G0 ~2 G: P2 N( W
                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?6 a' Q  G) T0 r4 \& o4 z; M& y
                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;0 H0 X; c6 o4 g" x( m( e
                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
# G$ o) U4 e1 b6 W                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
0 Q9 g3 y; ]- ?9 Z% f+ h9 H) q' [8 d+ ^. g
                if(DoIdentify(hPhysicalDriveIOCTL," ~$ ~) B, n! \& R
                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,: O/ J7 W: c$ M2 u* D
                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
' E, @2 w1 J- H9 _                {
8 g3 f2 f, S% g( W7 c; @/ d                    DWORD dwDiskData[256];  @# R) }; c. q2 }- W0 _
                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件$ T& ^1 p! J$ c
                    char szSerialNumber[21];
) H7 r2 o: r' q0 r                    char szModelNumber[41];
# v0 C9 h& E) m# U% `, |# p: T$ D
" e- y: m* ]; [; w0 U3 i; Y# u                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
4 H8 D& L! Y7 x! y+ ]" Y. _                    for(int i=0; i < 256; i++)8 i* q+ G# t' G- E( O6 Q# c5 _, i
                        dwDiskData[i] = pIDSector[i];& e, y/ x: u! P
                    // 取系列号
# k: I; a8 {- E; I1 R6 ]- E0 A5 U3 r                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));& P# m2 w; P  P
                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));4 j5 h1 q  ], e+ Q8 ?2 k

% c/ e/ |8 v% {. b' |2 y$ c; F9 T) ]                    // 取模型号
" |) K1 ^& a# U: Q1 K& [8 Y                    ZeroMemory(szModelNumber, sizeof(szModelNumber));. q3 J0 {$ T0 ~1 C2 B
                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));6 g- b# f3 V9 l# Y( N" E) [, W
# R4 |% U" u! H! q7 O) ?
                    pSerList->Add(szSerialNumber);
/ L1 [  I- R7 S4 ~7 A6 B                    pModeList->Add(szModelNumber);2 W7 @& V$ l* m( X4 v
                }1 p. n& Q: s, c
            }
* h3 y8 z9 x0 {6 `0 P! }+ o            CloseHandle (hPhysicalDriveIOCTL);
2 s; J6 N2 e- W3 @- Z. b        }
" a; s' V3 Y( E6 Z8 J% V    }% Q( f, R" j; ~- ~  [
}
7 Q6 T6 j" Q: c0 ?$ R+ Z//---------------------------------------------------------------------------6 S* F. N0 j% ^7 S
// DoIdentify* g- U4 {) L& h0 l4 {
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,: J* X/ g  g$ c
              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
( t' Q9 ^: ^/ o. ?; F+ b/ `              PDWORD pdwBytesReturned)
" ^" Y/ L. W& {, x( ]5 j{( V" n/ L+ h. i# c/ @/ c* |
    // Set up data structures for IDENTIFY command.
1 q- w& |  ^* O. o% ~; ?$ [    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;& O: g6 C! R1 O1 C7 B9 ^" E( Y
    pSCIP->irDriveRegs.bFeaturesReg = 0;& A( |0 j, y) G7 W. Y% \- U
    pSCIP->irDriveRegs.bSectorCountReg  = 1;
5 E2 T+ Z" Z$ p# a  E  f    pSCIP->irDriveRegs.bSectorNumberReg = 1;9 y. J/ Z0 X( l* y$ ]
    pSCIP->irDriveRegs.bCylLowReg  = 0;6 X0 c: {6 i1 T+ t6 y# h5 O
    pSCIP->irDriveRegs.bCylHighReg = 0;
: ~% h6 L! Z7 O) [  u- q) I* t7 w3 f/ Y  v4 ?
    // Compute the drive number.(主盘和从盘所对应的值是不一样的)2 r& K! W+ u7 U* [
    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;7 ?& X* ^. m8 q% X& q5 d

& C- l1 _( B6 }6 H9 m. G    // The command can either be IDE identify or ATAPI identify.8 M6 ]" l( Q- i$ `
    pSCIP->irDriveRegs.bCommandReg = btIDCmd;+ {2 G% w8 d( C8 \9 i. B
    pSCIP->bDriveNumber = btDriveNum;2 i* a5 z- h1 K6 d. M
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;/ b! b* L3 y9 Q
- _8 f0 A, P- C/ T, w
    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
8 t) B, {5 U& j0 t- Z- l& y  w9 }           (LPVOID)pSCIP,
0 G9 ~& v2 z' J- F3 w           sizeof(SENDCMDINPARAMS) - 1,0 {5 o' Y! O, s
           (LPVOID)pSCOP,
2 a: ]2 k) r3 n           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
3 B6 R  j8 p* B, B! q4 H0 k           pdwBytesReturned, NULL);
0 q' [" |3 q. [, V/ X; \}3 N1 i# s4 ~6 u. g
//---------------------------------------------------------------------------
( @: f! v; L! l' p, M3 J1 F6 [* o: }/ q// Windows 95/98/ME 代码3 v8 K0 r/ e3 m: k) I* F
//---------------------------------------------------------------------------
8 Q, p! n- d: t1 i// ReadPhysicalDriveOnW9X# i: w0 f( ~5 Z2 u  }: }& f
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)5 N" n% ~6 X/ R$ c9 E) j, s) z
{$ ?, W1 s7 @# b  }
    WORD wOutData[256];
/ O3 P8 q" D+ p+ B+ r5 n3 a( V$ r    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
+ q7 N$ t) y- Y& R% Y4 {) D  d; Y+ z, I; \7 O5 [; ]) M' S& U
    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。" G/ n+ c8 T: F! [  o5 Q3 ?, d
    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
; ~+ c% |$ u) V, |$ f! g    // 避免蓝屏的出现。(期待高人能指出原因)
$ H) b% [3 q) _* N* j/ A    for(int nDrive = 0; nDrive < 8; nDrive++)
. Y7 o! U. ~: @! h+ r1 p( U    {- ]* Z) f% S3 D2 G
        WORD dwBaseAddress;
8 X5 E4 v$ O3 C, _! B$ ~5 u5 a        BYTE btMasterSlave;         // Master Or Slave% p7 g# b, v+ X; Y; }8 D$ q
        bool bIsIDEExist;' l* e/ Q; T+ O) T$ x8 n4 X. x' r
        bool IsDiskExist;
8 r7 ]$ i# g/ _/ N1 J. L" t# }1 f8 k. X) n& s7 m# S. [3 [
        switch(nDrive / 2)2 n( Y6 E7 ~" U2 s5 h
        {
2 p* i6 y* i2 {: E* o  I7 J            case 0: dwBaseAddress = 0x01F0; break;4 n) c  u6 ~$ I1 u/ |
            case 1: dwBaseAddress = 0x0170; break;/ v" j8 o% v- C0 l/ r9 J6 o$ f% @: ?
            case 2: dwBaseAddress = 0x01E8; break;
+ w+ F& K' `/ ^1 F3 \0 z  M% V7 q            case 3: dwBaseAddress = 0x0168; break;
/ q3 ]: |. K' {& E        }
% C& v- }7 h) R* T/ y
+ n3 E+ I( E. ?* r        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
2 k5 W1 ~* a4 ~
3 `. r) N0 H) Z' b# I6 i        // 进入Ring0
. X1 s$ o) G# x/ i9 W0 ?        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
' x" K+ c6 a8 G                bIsIDEExist, IsDiskExist, wOutData);
& U2 Z6 Z$ l" H1 v- a    }5 `5 |( W0 [! a8 S# N+ T3 d: @
3 p* M) _+ Z! c" \
    // 开始读取
9 x! Q- t* k# Y5 j* o    for(int nDrive = 0; nDrive < 8; nDrive++), n/ v# _6 ~( e* z& q. W! ?2 N1 R
    {
( p; s; K9 |7 \        WORD dwBaseAddress;
5 K4 v# U* ~( V        BYTE btMasterSlave;         // Master Or Slave
' o- C6 n2 D" ~        bool bIsIDEExist;0 z' l" {) |0 N  L* P
        bool bIsDiskExist;
; o, K3 S( d4 Y5 Z2 ]6 F        switch(nDrive / 2)
/ T! s7 E6 u8 D) C+ t( @" |5 G2 [$ X        {
2 M1 `. _7 [' A3 @# n            case 0: dwBaseAddress = 0x01F0; break;
# u1 x  W0 @8 g& L2 f- M$ `- g9 m            case 1: dwBaseAddress = 0x0170; break;
; Z1 ^( Z* S7 \0 p2 X+ i2 _            case 2: dwBaseAddress = 0x01E8; break;  s, _8 i4 d/ g
            case 3: dwBaseAddress = 0x0168; break;5 V7 T# c# M6 |+ H( t3 r% M
        }
! H+ U! n7 G8 s" g- g: y* b# p% q0 M) ^0 X/ X( Z, ~
        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);7 I" P7 Y  M, q! A

. b0 M" i2 V( s, t. T; C        // 进入Ring05 n, d" L; b( p- Q& e: U7 V7 _
        bIsIDEExist  = false;& h5 |& Y' Q2 P) A/ N  C
        bIsDiskExist = false;7 t" p( y7 j$ ?8 [+ S/ G9 p
        ZeroMemory(wOutData, sizeof(wOutData));% c4 R9 U- H7 @4 f' {' F0 `8 |# }
; c5 H, \! y. {2 C8 N( i( g- c% j
        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,* I# t% ]+ V# Z& m* A8 _
                bIsIDEExist, bIsDiskExist, wOutData);% q8 h, S; f5 S* [

2 F2 {! Z. m. K5 R( I        if(bIsIDEExist && bIsDiskExist)5 a4 o/ U! i' R
        {' Y2 e4 x, Z8 M* b0 I
            DWORD dwDiskData[256];
5 ?" M; X# g- t8 t. z            char  szSerialNumber[21];
/ P* |9 w- N: y  r; l3 }            char  szModelNumber[41];
# K! [, e( G8 N' T7 E- w: G. A: a  {/ Y# d8 v$ |& K1 `
            for(int k=0; k < 256; k++)
8 V; \3 x! t7 V3 Z2 a                dwDiskData[k] = wOutData[k];
8 {  Z' }: n6 F; V
" P! f: Q& C4 g+ l' D            // 取系列号
/ T6 I7 E" z# d4 S& E; u            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));2 n8 C% I$ K* h3 s0 ~$ `) l
            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));( c- d! D9 p! d5 D( g
# `# P& c  T2 l* ]; G! }) b% B
            // 取模型号) F) q( U& @. T4 D, L( C7 @
            ZeroMemory(szModelNumber, sizeof(szModelNumber));
; b1 a& _7 B# M7 p            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));  M: F2 N: E3 o( [
9 ?2 |5 U% P+ G+ E
            pSerList->Add(szSerialNumber);
9 `0 y2 ?+ i8 j& j            pModeList->Add(szModelNumber);
! L8 v3 t3 W, X4 e9 \1 G/ y        }
( [. K6 Z+ Y+ n; j    }
; r' }: e7 l, O. e    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);0 e) P8 C% C" J( \" h& t* N7 R
}
4 v, h& S$ z( {1 E* _//---------------------------------------------------------------------------
: i; Z7 |  R( x: L! _& p: t  U1 a// 为防止不负责任的转载者,在此注明原出处信息,请见谅。
6 ]' F) A! ^3 U' O' y// 资料收集整理:ccrun(老妖),欢迎光临C++Builder研究: http://www.ccrun.com
1 W! T$ R0 T! \' p) A) e! ]( P//---------------------------------------------------------------------------/ h7 T' _1 d+ Q
// ReadPhysicalDriveOnW9X_Ring0(). j' B0 N  r. I  N1 `* `- |
//, I7 O7 {3 G8 W: B7 Q8 i7 Y; u
// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
% `% B$ K% M2 w5 V. O! ?( f6 a2 H// btMasterSlave = Master(0xA0) Or Slave(0xB0)/ s( P, ^9 p2 k' n
//---------------------------------------------------------------------------1 L3 a1 v: y6 J5 P( f. a
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
2 D! O4 [3 i% m) Y        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData): A- S  |$ {9 u. p: \( f
{
/ \6 X1 O" d5 K" J2 v$ y    BYTE  btIDTR1[6];+ d2 ^; F8 t2 I6 e- {$ [. p
    DWORD dwOldExceptionHook;
' M9 y6 p6 o8 j/ Q% o    const int nHookExceptionNo = 5;
4 F$ M) G) w+ e8 G0 E7 D' j- E1 w+ F+ C
    BYTE  btIsIDEExist = 0;
7 J4 T2 _; A/ ^2 W    BYTE  btIsDiskExist = 0;  A# p% s3 ~: N6 r
    WORD  wOutDataBuf[256];
- u) u2 @* q  [+ h$ d
$ ~0 A2 K3 U: ~* s7 T# a    BYTE  btIsFirst = (BYTE)bIsFirst;
5 \/ _* k7 v9 m  @3 S5 ~7 e) B0 q8 f; B/ r: k, _7 ]7 n
    const BYTE btBit00 = 0x01;
2 A2 _4 @4 X: m$ m# t' d* p    // const BYTE btBit02 = 0x04;9 x+ T& H, N3 ^  M" v
    const BYTE btBit06 = 0x40;
7 l0 |/ a5 n# ~% T) w3 i& _    const BYTE btBit07 = 0x80;% S3 S0 R7 Z' B6 r6 @
    // const BYTE btERR  = btBit00;
( T7 E( [- M. V  E1 Q. [    const BYTE btBusy = btBit07;
) A! w3 f# ~* n7 W4 x' r( h/ n    const BYTE btAtaCmd   = 0xEC;. s/ k  `4 @( m/ p6 M$ T  r+ U
    const BYTE btAtapiCmd = 0xA1;
$ q4 k. N% K# e, v) g/ l  _4 D7 R. L3 j3 K0 h- ^$ a
    __asm
2 l' A1 [: F+ r% L4 L+ j* f# p    {9 Y- A+ l/ P; Z* ]2 }
        // 必须先执行这条语句
$ P; Q& D% ^; f% ]6 S# ^- P        JMP EnterRing0& o- V! _+ z: s, d& M& A6 ?8 I
/ e- D4 z, a$ X
        // 定义过程
. {+ ]) j" C9 t        // 等待IDE设备直到其不为忙为止
3 @8 S, \3 P" \0 O& h& k        WaitWhileBusy proc
6 X8 i9 c3 w8 `% e) p0 U- J2 O- _/ U7 t# |% _5 Z. J8 A
        MOV  EBX, 100000
. b* D( u% l4 H3 c& m        MOV  DX, dwBaseAddress, ^3 Z* y# T1 Z' T
        ADD  DX, 7' M4 h/ k+ c* f5 B% |$ b, J
6 ^# r6 [5 e- Q) n3 }
        LoopWhileBusy:
3 v+ Q! I4 K& f( z7 J' ^0 n0 p1 w. R4 o8 D; D) g/ j
        DEC  EBX( {# N* l: i. W8 H# z
        CMP  EBX, 04 p8 B7 E: ]: k. @1 P
        JZ   Timeout
9 f. E# E1 ?6 F, @3 P/ R        in   AL, DX
1 e. \0 q; ^# _5 |: V% ], C! i5 w        TEST AL, btBusy3 ]5 H0 Z) X$ k
        JNZ  LoopWhileBusy
; b% e: Z& _& @' ]+ J        JMP  DriveReady
$ t. c  J* O  `3 e' @# O+ M) G3 X6 a+ D2 X1 _; W: z) S
        // 超时,直接退出( J; u  q% W4 u! }& R7 ]: N
        Timeout:7 E! _& `3 F% U$ d1 z: F: ]
        JMP  LeaveRing0
% p& ]1 Q2 T, n. ~$ f        DriveReady:3 e% ]- s- R! s9 Y5 [
        RET/ T/ C) v1 D* Y$ q
        ENDP   // End of WaitWhileBusy Procedure
+ m) H, b: r( Y. N" I/ S
# ]. z# f# v6 V0 ~0 p        // 设置主盘和从盘标志
3 u3 `: j4 z/ o1 v. w( t( r; z        SelectDevice proc
& J" _9 D* z. H& |& ^$ v
0 @% d2 L1 y5 z3 }3 |: q- \; w        MOV  DX, dwBaseAddress
  g/ Z) @4 Z' I9 A+ h        ADD  DX, 6, _  H! b8 N2 P5 x( g
        MOV  AL, btMasterSlave* ]4 d! u1 e% y0 \
: X% p1 Q+ |) {6 w) Y* S
        out  DX, AL
* I+ P# o8 l: e6 J        RET- F- @$ ]5 P! `, p# E

; o7 P, f- }) R        ENDP  // End of SelectDevice Procedure8 S- J' \" w1 j! U0 Y0 A3 W
9 b' P( o+ z- S5 |" k
        // 向IDE设备发送存取指令8 z6 P  J% E; k* s$ ~, s
        SendCmd proc$ ?; s! H8 s7 m9 I' J, T
4 ~9 v  f* G. }" J- m/ V1 L
        MOV DX, dwBaseAddress
1 s$ x: z, }" M; Q% u        ADD DX, 7& d7 W7 ~+ \; Y0 G4 Z
        MOV AL, BL // BL是主从盘标识,在过程外设置, s6 p; @+ J. \
        out DX, AL% U+ c/ i/ A& D7 B
        RET
4 n4 M( m  y4 T( n. ~        ENDP  // End of SendCmd Procedure
. I1 Z, e7 [! ?) r: j2 f
  d3 F, N8 y2 ?/ s# ?, C        // Ring0代码/ {7 `( @. B& w8 E/ c
        Ring0Proc:
0 r- a* @1 L5 L' F! g5 B; U        PUSHAD  B/ F0 @8 V( j  o" t* G& D1 K
        // 查询IDE设备是否存在4 c8 r4 Z9 n& ?! {: B  p
        MOV DX, dwBaseAddress) {/ o# _3 B0 ?* a  k' w/ u
        ADD DX, 7$ _4 M* A1 A  N7 t" K& ?7 `
        in  AL,DX
5 Q' ^+ f; g0 U* y+ y9 e
& [& T3 U8 F6 y7 J4 w5 [. j- r& G        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回: U1 p: Y$ C8 I; C' F, Z9 c' [! \
        CMP AL,0xFF, ~1 |' O" @' I) G( O6 X
        JZ  LeaveRing0
1 D: H2 m7 [) \- r        CMP AL, 0x7F6 f9 a/ s/ ?5 i% \+ f
        JZ  LeaveRing0
/ X. u1 P/ ?. M. l: J4 M6 u) D6 N. L# a% w
        // 设置IDE设备存在标志7 R) b  _5 X. u, ^& C( I  b+ k6 Y( G
        MOV btIsIDEExist, 1
* n4 j5 o0 L+ d& A3 u
$ h" W+ p# H3 B" W9 N        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
' T* i3 o+ i( z. M        CALL WaitWhileBusy
- \8 E1 r. A+ Q" X/ q" Z        CALL SelectDevice" H( D) g& E& |* C
. @6 _$ f+ c& s/ d9 m7 S: e, Y( M9 i
        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏2 o8 ^7 q2 d; F4 J" M! J
        CMP  btIsFirst, 1) A4 Y2 t' ~4 c: o
        JZ   LeaveRing0
  K% F, l; u1 q  b
+ M, j7 z2 y) [, `$ O  L* s" i        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
$ p/ k  z: J: s4 O* s7 W        CALL WaitWhileBusy2 z, E5 z  ?# E4 {! ?3 j

; I5 A# N' S$ r4 s, ^. ~# E        // AL的值等于cBit06时,不存在驱动器,直接返回% I; R+ y1 n2 p$ a
        TEST AL, btBit06  K! d* [$ M* u* ]
        JZ   LeaveRing04 q7 g5 G$ V" u5 L5 a. Q

( `( p& @2 P8 C$ F8 U        // 设置驱动器存在标志8 C4 ]+ W( @$ Y* `( \
        MOV  btIsDiskExist, 1
5 @  o6 P2 y0 i& T, E3 c
) ^! s. T7 [0 @& }" Q        // 发送存取端口命令9 E( X" W2 g# p) D! Y
        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
0 P8 I' n' r- w6 e3 p        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
' S! s3 W. M  F& S, C, a- V! L        CALL WaitWhileBusy
6 p3 y# S+ R$ r$ q/ O9 S        CALL SelectDevice    // 设置主从盘标识  k4 M( p& J8 @* q5 L
        MOV  BL, btAtaCmd      // 发送读取命令
) A8 D+ k; u7 Z9 R        CALL SendCmd8 G0 J) Z# D% ]% U
        CALL WaitWhileBusy2 L$ e* z3 M6 @
* K" B: F& C! c4 p( n  }3 d
        // 检查是否出错
6 ?* \, r! A% A) ~        MOV  DX, dwBaseAddress& Z; h7 U: v/ V2 m1 _
        ADD  DX, 7
8 f7 i$ a2 [# x+ n' {$ |+ z$ Q) k9 u8 \) `7 C, Q
        in   AL, DX
5 t) ?7 k3 c* o+ c$ A2 H( f& b* D
) t& X, g! g! U1 U! w        TEST AL, btBit00
2 {' h& N; M: L7 U9 e        JZ   RetrieveInfo   // 没有错误时则读数据
5 J1 s  l" j8 f- ]$ x8 R% f9 n5 a6 S& F( @7 @* @4 {3 f
        // 如果出错,则进一步尝试使用ATAPI设备命令) B4 u+ I# Q7 n" t& n' T) z8 n
        CALL WaitWhileBusy
8 v5 W( l5 F! B7 r7 }1 g        CALL SelectDevice
' r: n# n6 v7 P4 s  e0 t3 Q        MOV  BL, btAtapiCmd
1 z! ^, V1 ?8 w3 o. F% n+ D- \        CALL SendCmd
7 p0 I7 j6 U# _! s, @        CALL WaitWhileBusy
; z4 V# ~/ w+ `, [" Y
0 q% b8 [/ c5 T; Q, Q' I; C        // 检查是否还出错- y/ i1 w7 j6 C+ P; K  w
        MOV  DX, dwBaseAddress  V3 i5 Q# U( q: l6 v
        ADD  DX, 7
8 J1 {5 {. R" B% O- U        in   AL, DX
! o1 N. W$ n% {  [* d        TEST AL, btBit00) u' {4 [4 J3 X" {) {
        JZ   RetrieveInfo   // 没有错误时则读数据3 |4 ]- e# K0 X1 L4 D0 M2 E8 A
        JMP  LeaveRing0     // 如果还是出错,直接返回
& e% ^4 m  B- I/ }* F* Q# z
, I0 j  q6 I# s6 ?/ h        // 读取数据
; [$ F8 {* f: D$ M        RetrieveInfo:
3 ~9 }! E# ~7 z+ n& I4 l7 \: Z/ r( O! Z( q. E* O% A
        LEA  EDI, wOutDataBuf
! R) Y* e# ^/ R1 w) F        MOV  ECX, 256
6 S  F, O$ L. P        MOV  DX, dwBaseAddress- ]3 m3 O6 O; I
        CLD/ s% g! b3 d% n' x" b# \+ F
. l7 A( n- y$ m- G* ]
        REP  INSW, r* F. R2 m! z) R

7 A4 _: P; W- F- S/ o! `1 [        // 退出Ring0代码2 V) G% q: g* g0 w
        LeaveRing0:
+ j: E# o3 f  }: W2 C9 h% T$ \6 _2 e+ w: G2 M1 ~3 v8 W0 l
        POPAD- e; C! X( `: J- I( v
        IRETD0 p1 u9 ]5 \3 X
  G6 f2 |5 ~/ M2 `7 q
        // 激活Ring0代码$ G5 k- C# }# ~9 c5 p
        EnterRing0:1 A0 w+ Z# t+ C. m

/ Q1 Z4 p* J& n1 _        // 修改中断门  I: W. \4 m6 y+ p2 H
        SIDT FWORD PTR btIDTR1" B$ i: @/ f: S; T1 `" ^  [
        MOV EAX, DWORD PTR btIDTR1 + 02h
; @  E4 i3 Y/ ^: p        ADD EAX, nHookExceptionNo * 08h + 04h
) x' E  ~: A3 p4 b  H6 m; t        CLI
5 g. D) t$ E* e: [
" R# f$ k0 a4 U8 c% T) r        // 保存原异常处理例程入口
; F) I+ S3 x) u4 }- T0 V, S        MOV ECX, DWORD PTR [EAX]' h6 @$ m4 `. T% p" M& C
        MOV CX, WORD PTR [EAX-04h]
2 j( z+ {3 i8 Z0 M# y1 T        MOV dwOldExceptionHook, ECX
2 i) h2 n, A: l! O; x4 x# M. H) R) l1 P! h
        // 指定新入口
& p1 L0 s" L. k( y+ ^2 Q; S! ~        LEA EBX, Ring0Proc
" F4 F; a, `- w* w# M+ }# c' n        MOV WORD PTR [EAX-04h],BX
( A/ w- v9 Y6 k: w        SHR EBX, 10h
' U5 Y; f. T% Y6 q! F- r3 C7 M        MOV WORD PTR[EAX+02h], BX
" \  H8 @- l! x& x; M6 E1 T
% ?- }6 F, k) d4 b, {! c) Z        // 激活Ring0代码3 e& C+ c5 S$ N6 y! R- G$ r
        INT nHookExceptionNo1 U  _, e4 P  T9 }7 P4 R

. ]/ U: X& `# C1 {        // 复原入口3 ~2 ?  s4 ^7 j- n3 d
        MOV ECX,dwOldExceptionHook
; x' c6 U% i4 I, j' J! V4 v        MOV WORD PTR[EAX-04h], CX# _0 A! U. G7 e: ?/ _+ ?+ u% d
        SHR ECX,10h
; d4 \4 |! c8 g( ~5 \        MOV WORD PTR[EAX+02h], CX) m: K8 C7 D  x5 O& \3 Y- |
        STI( A" q, }4 u  k! d" R$ ^+ R# z3 ?
    }
- t* U) g, d/ A/ {% P. I    if(!bIsFirst)8 C: b6 W& J2 l: V* t$ }
    {) Z( N3 W( b& l, X, K
        bIsIDEExist  = (bool)btIsIDEExist;& G+ l( s0 @9 M8 g! T: L) n
        bIsDiskExist = (bool)btIsDiskExist;
. E- r3 {% Y- I. S: t# V        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));  `; F& a4 h* o2 P7 r8 K- _! U
    }8 R% |6 C7 G! o5 B3 e8 d1 A9 E
}) F" T8 r0 ~. m, a( t
//---------------------------------------------------------------------------
+ v$ J+ A$ B  v- j  E3 G, P$ Q// 调用方法:
( U% \8 _. X7 {1 ^void __fastcall TForm1::Button1Click(TObject *Sender)8 w! g5 M- q7 h
{
1 m7 T  k$ c. r, j! x. q    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);  ~/ Z# j- o3 O0 `; B
}
8 ?& ^2 b4 q. J% \/ p& d
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-8-8 22:42 , Processed in 0.035942 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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