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

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

[复制链接]
发表于 2008-1-6 19:59:06 | 显示全部楼层 |阅读模式
代码框架,你所要做的仅是修改WQL语句,具体可看MSDN。以下代码为简介起见,一次返回所有的CPUID或硬盘厂商系列号" |, k0 d$ ]/ Q; D; I4 k! Q" ?4 @

  1. # {0 r3 l: |5 n& u9 `7 N3 o3 k
  2. #include "StdAfx.h"0 Z5 U# p, R3 a, N4 Y! L
  3. #include ".\puiddisk.h"5 d2 u. N$ s, w, H% z5 V9 A
  4. #define _WIN32_DCOM* N( |/ r. ?7 c# y' K. Q2 \) _. l
  5. #include <iostream>
    1 O6 J5 y# u( A1 K
  6. using namespace std;5 m' t5 a& j. p4 I
  7. #include <comdef.h>
    8 k$ j( F; p0 a: y
  8. #include <Wbemidl.h>
    % b4 ~2 n" ]+ A5 `8 ]1 r2 [. Z' i+ _

  9. ! {/ l4 f$ T% e/ B: O- W) k
  10. # pragma comment(lib, "wbemuuid.lib")* h# o: s0 r' [
  11. CpuIDDisk::CpuIDDisk(void)
    * u) t* d% }( U0 I* s3 u1 P
  12. {( e% l0 E6 d/ [  c- F
  13.     GetInfomation();
    0 v- |4 f$ x0 P$ `6 R0 j/ f
  14. }6 y+ ]- Q: L% c

  15. 0 Q  f; o6 {7 @5 E. L' Y1 y7 Q( I6 U
  16. CpuIDDisk::~CpuIDDisk(void)
    ; f: k, `9 m3 `1 w8 C
  17. {- C: _6 c# B" l
  18. }
    4 U) \: v# p7 O
  19. int CpuIDDisk::GetInfomation(void)) r; a( b- d5 B* D
  20. {9 A. G$ D8 Y2 W6 s
  21.     HRESULT hres;
    $ f2 S" S9 M4 ~' z+ w' M
  22.     //步骤1:不是必须的,COM只须也只能初始化一次5 B3 Q" S, u, E  X( K  H# X
  23.      hres =  CoInitializeEx(0, COINIT_MULTITHREADED );( o, q2 m& M5 U" |8 _6 C- }
  24.     if (FAILED(hres))
    7 Y  J6 }& e& [0 J
  25.     {, w' A2 y" x/ k; P
  26.         return 1; //初始化COM异常:注意,COM只须也只能初始化一次
    + u0 Y, ?% M! M: B$ N5 E3 s% `7 r0 T! a
  27.     }# A, a6 n! B" T3 @! ~3 A
  28.     //步骤2:不是必须的,COM只须也只能设置一次
    ! V# ]- t* ?3 `& J" u0 d9 E1 M4 S1 _5 [
  29.     //Set general COM security levels
    4 q) M, n  ]9 [' p
  30.     hres =  CoInitializeSecurity(
    4 n( n1 A- X" O+ Z
  31.         NULL, 2 H- Q1 h4 ^- B0 ?8 X# u7 Z& p2 t
  32.         -1,                          // COM authentication
    & v5 U! V1 i9 k' u2 N: S7 Q
  33.         NULL,                        // Authentication services
    5 A. s/ j9 K9 ~" R8 y) q& Z% C
  34.         NULL,                        // Reserved4 n* ?! [! s- h! W
  35.         RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication
    3 n3 g0 _* F& s; m3 Z2 |
  36.         RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  6 |* C$ Q5 B6 x' x- e
  37.         NULL,                        // Authentication info+ A5 x' K$ b$ M! Y4 e3 N
  38.         EOAC_NONE,                   // Additional capabilities 0 \! {) a: q1 D
  39.         NULL                         // Reserved# E. h7 y6 f6 n2 D! P
  40.         );/ u8 Y7 f% {  s& J
  41.                       8 x: J1 w: ^6 `  n3 [
  42.     if (FAILED(hres))+ N" Q6 `' T% f. B2 q5 e( P
  43.     {
    + m0 G# ]. ~  y2 f* Q) a
  44.         CoUninitialize();2 i% C0 w. ?3 u/ o
  45.         return 1;                    // Program has failed.
    5 T$ \$ R7 M7 X1 O6 @
  46.     }3 C" }3 F3 q7 Y' z9 q0 Y  d8 M" v
  47.    
    ) i# B/ R( I$ Q' h+ I, }
  48.     //以上不是必须的,若已有“::COMInit();”,则要跳过
      v  m' x* n7 ?5 ^% k
  49.     //步骤3: Obtain the initial locator to WMI 3 M5 E5 }9 K# n. X2 A: E
  50.     IWbemLocator *pLoc = NULL;
      F1 N0 h7 @$ U' s/ K/ k: U; \
  51.     hres = CoCreateInstance(# u0 K! f7 |' f
  52.         CLSID_WbemLocator,            
    1 f  r0 `, @# `8 H
  53.         0, 6 D( \6 O) E. K4 e
  54.         CLSCTX_INPROC_SERVER,
    : j2 k( I3 w8 O! Z! o
  55.         IID_IWbemLocator, (LPVOID *) &pLoc);
    % C  y( z0 s5 A
  56. 5 M2 G- g* D& P! G  r) F
  57.     if (FAILED(hres))% a! ?+ X; P) r2 H6 }: \( C
  58.     {& u. O* \1 s6 I  ?* {
  59.         CoUninitialize();# l- X. |: u3 k, y) F2 `
  60.         return 1;//Failed to create IWbemLocator object0 L, }0 [- V& t2 H6 e
  61.     }, {% [+ F! f- j# f, r- J5 I9 B

  62. ! M8 k& ^1 l! Y: c
  63.     //步骤4:Connect to WMI through the IWbemLocator::ConnectServer method1 P  p- b: i0 f" p7 _% w
  64.     IWbemServices *pSvc = NULL;
    " q3 ~/ Y, W4 G4 w$ Q, @
  65.     hres = pLoc->ConnectServer(/ U# j; a( |* n
  66.          _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace5 P3 w8 {) c$ `- T% @8 B( ?
  67.          NULL,                    // User name. NULL = current user" u; m. D$ C5 a, A2 u. B
  68.          NULL,                    // User password. NULL = current
    / E! N% G0 U! |
  69.          0,                       // Locale. NULL indicates current
    . V: t* s* k3 R6 J
  70.          NULL,                    // Security flags.3 c2 K2 s. j" z" j
  71.          0,                       // Authority (e.g. Kerberos)0 o* J3 ^& X+ \
  72.          0,                       // Context object
    9 U8 k/ x. R( j8 i7 V
  73.          &pSvc                    // pointer to IWbemServices proxy
      j. w5 A2 Z4 M, a; a
  74.          );! j- G: S+ C! }" }; W; F7 d) j! [. [" q
  75.     , l' ]" R! f' L1 P
  76.     if (FAILED(hres))  j. g6 n, D' w0 V/ f- o. u# u8 l
  77.     {
    * k: q5 B4 C/ k' s9 @  }& _" Q
  78.         pLoc->Release();     
    $ @: p. H1 z3 P7 f3 l: P* G, G2 i
  79.         CoUninitialize();$ l$ u5 y) v- W+ u4 ]: L0 I
  80.         return 1;                // Program has failed.
    ' Y3 ]0 ]: j8 M- s
  81.     }/ o0 e( P* \- W
  82.     // 步骤5: Set security levels on the proxy4 d& }; G4 V  g& j/ _! q, F* ~* a
  83.     hres = CoSetProxyBlanket(
    - g1 x; ]4 S# j# z: [9 n3 N
  84.        pSvc,                        // Indicates the proxy to set9 q4 l) Q2 ~5 I4 w4 a2 J
  85.        RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx7 U% l) }8 U( F8 a4 G* }9 h. @( H
  86.        RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx& V% }* v, M, N5 }
  87.        NULL,                        // Server principal name / g8 S* f, f4 z7 m2 [7 g: Z
  88.        RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx 0 k3 F& ]4 l* e, w5 a
  89.        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx) g) M9 ^, j: B' Q2 x, a& \8 D
  90.        NULL,                        // client identity
    1 C5 M1 i' N$ w% ]
  91.        EOAC_NONE                    // proxy capabilities
    * [, b! M, V) E9 ?$ S  p$ a' G+ R
  92.     );* x6 E' c' x% `* n6 i  q
  93. " C& H* R  C  p3 W: O5 K
  94.     if (FAILED(hres)). {: C" w) e/ e' }% Z# U
  95.     {# _" h# _4 h; G) Q- A4 f: V  V, {# j
  96.         pSvc->Release();
    % c, O4 M% j2 r, G& l
  97.         pLoc->Release();     1 z5 B+ E8 g6 K3 o5 l$ I2 w8 n& X: J
  98.         CoUninitialize();
    % x0 @/ |7 ~1 {9 }3 H2 o
  99.         return 1; + `$ v( n  ^3 e$ n
  100.     }! m$ K" T5 y. T" ]
  101. " s& u! M  i, U8 D
  102.     // 步骤6:Use the IWbemServices pointer to make requests of WMI ----
    9 g+ P: e( F+ u* v7 g! O. ~
  103.     IEnumWbemClassObject* pEnumerator = NULL;
    7 ^! c4 h/ \  I
  104.     //计算CPUID
    4 K; K  G) H& F- `
  105.     hres = pSvc->ExecQuery(
    % F( U' r- e9 b' y
  106.         bstr_t("WQL"), 9 }* f0 o( U" m% q4 ~5 X; X+ w/ K
  107.         bstr_t("SELECT * FROM Win32_Processor"),//Win32_OperatingSystem5 |  C; k2 w- h3 Q1 P
  108.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
    $ J( ~0 F: S- q/ V# w
  109.         NULL,
    / m! ~7 b. t( K# s! k- a8 k
  110.         &pEnumerator);) y7 ~; s3 [; H4 X4 V
  111.     - E0 k2 x5 T% ?+ V' W$ T
  112.     if (FAILED(hres))
    ( T0 Q6 b& f9 W9 s) j" f+ Z
  113.     {
      P" }1 |7 D% [( e/ w3 s
  114.         pSvc->Release();4 {. b6 \* A0 ~: U" y* C7 f* j
  115.         pLoc->Release();
    ( V" Q+ c7 W, H( I6 d+ n- S
  116.         CoUninitialize();
    " _- W* c9 |0 {9 Y/ {( L2 c
  117.         return 1;
    . F# @9 S  z; `; J# g9 z) s: ~
  118.     }
    9 G; Q! Y% `" C1 i+ u
  119.     // 步骤7:Get the data from the query , p7 d4 _( w7 P: `( l, Y, ]' R( D3 w
  120.     IWbemClassObject *pclsObj;+ [  G  @% o) m: |
  121.     ULONG uReturn = 0;: H/ Y* c0 y& Q& n
  122.     while (pEnumerator)
    , n# g/ N' `# J2 l! b2 \
  123.     {$ h: r4 V9 `& _6 v6 ]
  124.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
    + X& A1 F+ G- C7 e# D
  125.             &pclsObj, &uReturn);8 y3 O8 L9 Z: O- U5 d* Q: r0 r( Y
  126. * w2 K% I. g0 j# D
  127.         if(0 == uReturn)
    3 J. n1 f/ E1 T; H
  128.         {8 f1 P0 {3 F2 h+ l5 N/ _
  129.             break;
    0 f7 D2 \, V1 w8 }
  130.         }
    2 G: ^5 _( W& R! k, D
  131.         VARIANT vtProp;
    & }( L1 {# w: D
  132.         VariantInit(&vtProp);) D2 U8 J' `% e: r$ P8 F
  133.         hr = pclsObj->Get(L"ProcessorId", 0, &vtProp, 0, 0);
    8 `' ~+ l# s  P% {9 p
  134.         strProcessID=_com_util::ConvertBSTRToString(vtProp.bstrVal);//strProcessID:类级变量
    4 u/ k. Q9 }" ?6 z
  135.     }
    4 _/ I/ A7 u. a3 I

  136. 7 i9 b9 f( `% W, |" t, ?. ~
  137.     //计算硬盘系列号
    7 p" M5 f: ]- Z0 `+ K
  138.     hres = pSvc->ExecQuery(0 U6 ]  r1 a+ Y' u" w
  139.         bstr_t("WQL"),
    6 Y' ]% G; b& U; b8 h6 z8 o0 I) O
  140.         bstr_t("SELECT * FROM Win32_DiskDrive"),& [4 q4 I( N# b0 A) u4 R4 K
  141.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
    8 v, b% U& ]2 F9 l
  142.         NULL,& _3 G, D2 R; n- M) s: }
  143.         &pEnumerator);
    4 z4 [2 M! x) w* O: |) J' U

  144. 0 h- S8 K" B8 r6 Z
  145.     if (FAILED(hres))" e" |1 N, `+ K" ]. x
  146.     {
    5 E4 O( g9 W# k0 k
  147.         pSvc->Release();( G( [/ x9 g& S3 D1 x  d
  148.         pLoc->Release();
    " @5 o3 _8 C; @2 O
  149.         CoUninitialize();+ `+ M* v" s9 F2 x! }
  150.         return 1; ; ~9 u8 Z  q9 i) L/ k8 n
  151.     }' a$ @; ^' T2 ^. i' n. j* ~
  152.     while (pEnumerator)
    3 f5 k6 b' K  T: @9 F* N* c5 G" \
  153.     {! j( a( a7 G/ p- ~+ D
  154.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, / t$ m8 @& E0 }- m
  155.             &pclsObj, &uReturn);
    $ |/ y5 F+ g5 j0 ?( o( M2 ~/ I
  156. : |: G1 |" E( O2 z! A& L% q! v
  157.         if(0 == uReturn). c6 v+ C$ J& V% m9 k+ a
  158.         {+ I; {1 Q$ O$ A
  159.             break;$ J( l4 T5 V* Y( D1 F0 ?8 ?
  160.         }# H9 J5 }4 H0 w+ X
  161. / M5 X" ~3 X: ^) b3 {5 A* \
  162.         VARIANT vtProp;
    ) I$ M: t$ [, V4 t6 V. p) H
  163.         VariantInit(&vtProp);" Z# R( J; p! h9 U! X: ~  j0 n+ o+ C! e
  164.         hr = pclsObj->Get(L"PNPDeviceID", 0, &vtProp, 0, 0);1 l5 I0 \6 ~7 v& S1 L
  165.     strDisk=_com_util::ConvertBSTRToString(vtProp.bstrVal);3 L: g: [! o0 X1 O1 R
  166.     }
    * V( [  ]* H# I" H

  167. " K$ _& y, E, Z, V: ^# b
  168.     pSvc->Release();
    4 [2 O6 X, b& l" R6 M2 B
  169.     pLoc->Release();5 {  _0 m# d* T3 b
  170.     pEnumerator->Release();
    * E1 }' s# X. A4 z& a* u
  171.     pclsObj->Release();
    1 m+ y7 L, \- a, U7 b
  172.     CoUninitialize();
    . M/ p' H2 Z5 K5 Y5 c
  173. ( m2 y5 F, l# B2 E% }& N
  174.     return 0;   , L1 Y% ~- I4 Y+ k
  175. }8 R4 _3 G+ o, ]9 g6 Q! \
复制代码
 楼主| 发表于 2010-10-11 19:21:05 | 显示全部楼层
本文代码经ccrun(老妖)在Win2k下试验成功.
% V& g8 ?% C9 Y- a# W. s; d" O, P2 c/ b7 r
#include <WinIOCtl.h>
$ c$ l: z: q2 T6 {1 l#include <stdio.h>
2 U' C. U) g# D4 [) h! B/ v; q- [9 r+ I* }# T: A6 a/ Q. o8 o% U
#pragma inline
9 ]4 ?* o" o7 c5 |8 D//---------------------------------------------------------------------------
6 x& D4 }1 z, c0 `. _$ \0 C$ @7 w// IDE NT/2000/XP专用变量
4 @" `7 a# T* e# L2 }& ~#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS# ^! u' z( |  y
#define DFP_GET_VERSION         SMART_GET_VERSION
: c) x2 O8 `5 z' F5 L: H7 @#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
  P, O; o% `+ N2 u  j- ^9 s#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA( ~: W  a7 l8 Q2 I

: B; n. j, J1 a$ v$ b7 H, Uconst WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令
  F) g1 S# l3 H- I1 @, W* M9 mconst WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令- ^+ {+ }/ T% w/ |4 y. F2 f" |

  Y* C4 a: y1 ^const int MAX_IDE_DRIVES = 4;+ G6 o. g4 Q  q

7 I1 _6 M( X8 E2 A+ d6 Z  O( V9 n/ Q) Y// SCSI专用变量
0 @4 i7 |8 H0 T6 R7 Y* I! Bconst DWORD FILE_DEVICE_SCSI             = 0x0000001B;
  A9 c- L- a7 d$ v7 f1 _. bconst DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);  _2 o* D- Z0 v) @: |3 b
const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
  K' ]# V: {, H  r! F) ?const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
$ c. v4 d) D. l4 l: \: D4 d, i5 }2 Q. I$ B
typedef struct _SRB_IO_CONTROL
4 ]( m* H& ^# o; G6 V( U2 }  H* @! h% X{; G4 `/ e" m8 ~# n
    ULONG HeaderLength;
- _- ~  q, w- j    UCHAR Signature[8];
" j+ T; `" J  n6 \: n    ULONG Timeout;
% Z9 A* v1 P3 R9 |" J( F    ULONG ControlCode;
& M+ m7 B) V# {/ p% P- U( Q: u2 i5 `    ULONG ReturnCode;
! K% `+ `+ k2 q- u- t9 N    ULONG Length;) y) D/ y' Y$ _( Z1 ^. q
}SRB_IO_CONTROL, *PSRB_IO_CONTROL;
7 c) w$ {' U: ?' q
+ `( I5 K* `! s/ S! s' m3 {// 读取的主函数
* P1 a$ t$ N9 @- J' Wvoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);+ k2 t! s- q8 L) {% K( _0 S
6 n0 `; t) t9 ]! Z  Q# l! r! F0 R
// 辅助函数# ]. E3 v, U2 }8 D/ ~! C
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
( i% D3 g, B  s6 j- i* @// NT/2000/XP函数
" @5 B, p0 X, U4 H& Q+ h: l) hvoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);* ?  y( R8 p7 B" `/ C* ~+ E
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,0 M8 ?" j' X0 Z4 ~1 z
        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
  O% t1 g; U2 h# K3 k        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);; p3 d) @# |6 x# P
// Windows 9X函数
  x) Q0 j+ y" c7 D1 N  m* wvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);& C8 }8 v! _1 X. W' a9 L
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,% v3 S+ x3 W# o4 b# e7 N
        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);% q* J. V7 l7 a& ^1 k

1 _2 ^7 E7 x/ C& N// SCSI读取函数(for NT/2000/XP)  a6 h3 c" o# h; i
String __fastcall ReadIDEDriveAsScsiDriveOnNT();
' x8 X1 a! @+ h) e% L) o+ ~//---------------------------------------------------------------------------
, w6 ~. j# @. H; r; B# J// ReadPhysicalDrive
, X: M% v9 I, |# n5 U$ Cvoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)& S5 S1 Z0 q" b( d9 B1 d5 R1 o
{0 l5 J- H# m4 v) t* A7 ~8 c: p9 V
    switch(Win32Platform)
/ _8 o' ?+ g$ E' ~2 ~4 x    {3 c) Q1 C- ]  G# k
        case VER_PLATFORM_WIN32_WINDOWS:) f4 P  s: I6 g5 f& U  h
            ReadPhysicalDriveOnW9X(pSerList, pModeList);: X5 x$ u* m( G- @/ W! n
            break;
" V+ d$ U% P, n4 w% ?        case VER_PLATFORM_WIN32_NT:
; D3 E- H% b8 y: u, ~8 L) [1 ?            ReadPhysicalDriveOnNT(pSerList, pModeList);3 o/ _% D( C. p: G
            break;
: _2 R5 U* L; f: K) Y        default:
; V) S: m2 s5 f5 h9 [            break;
5 Q' l$ d" K. u% r% C4 u# r4 e$ M    }( C4 ]. ~# I2 x) w' A( D$ }5 z- L
}2 H, |# p# b' S: {" @
//---------------------------------------------------------------------------  ^% A# o  q7 ?; h/ D) X7 y- ^
// ConvertToString
5 d, R2 V+ s+ o, ?8 Zchar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
: ?. N+ U0 O7 w* e{
6 g* F2 `1 h. X3 \# ~/ O3 y# \7 {( c    static char szResBuf[1024];
/ p  b) q* ^4 z7 ~2 C. R. {+ P4 e    int nIndex = 0;5 g# E) Y6 d7 y0 l
    int nPosition = 0;
) y( _/ F0 _9 k1 E. o% b* f/ }, Z! |
    // Each integer has two characters stored in it backwards6 Y8 {8 r1 n5 o" \( R, C
    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
6 p; V* x! r6 D# V+ ?4 [2 `% D    {& M# B0 l. S$ S
        // Get high BYTE for 1st character
2 D7 `' a! U0 Y+ Q1 e' `        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);2 w/ l1 k6 c5 w# ]! j
        nPosition++;' Y8 ^, m3 c( C$ C, g

# x4 s' o% v9 [5 @) M0 H        // Get low BYTE for 2nd character9 r" l5 p& \1 [; X  A, K) W
        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
0 _$ }0 m6 N, T  u" v( T1 d        nPosition++;2 F% L% L+ N  I
    }% C5 I7 q7 Z+ Z- N9 R& m) ?
* Y7 B6 A$ Q- i* n& _
    // End the string) J: g, p* b  R  t$ m
    szResBuf[nPosition] = '\0';
6 G) f0 F, T9 \! o: ~4 Z7 S3 P: N& H) q/ C- e, D, o4 `: X( X
    // Cut off the trailing blanks* [" m* S7 t( s: c  T8 E* X
    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
' `/ _9 n# S9 Q3 m        szResBuf[nIndex] = '\0';) d0 U+ I, ^( W9 c7 W3 P

! ?& C! Y- j3 L' I0 D" c( i5 S+ C0 \    return szResBuf;
" U9 m1 w7 j' N( d; G9 j}
8 l4 T( Q5 i7 l/ u; [//---------------------------------------------------------------------------
3 d9 I4 N0 G6 \/ L$ W& Q: y// Winndows NT4/2000/XP 代码
4 e& o# Q: m2 d" s  m2 d//---------------------------------------------------------------------------
# @1 a( w8 j9 s) U// ReadPhysicalDriveOnNT
9 j/ }5 ~" h4 wvoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
! I0 b4 a, l9 k& o: U. g6 G* B{
9 L. @7 i' g! B& ]! V  j% e    // 输出参数5 l7 f+ o2 a+ M( A0 V! v8 p# R
    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];# I" K& D# W/ p
( {' W' Q8 Q' }7 I& b; ~
    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
( n$ l0 ^6 U! A& V    {6 y+ u9 d0 W' O! N6 L
        HANDLE hPhysicalDriveIOCTL;$ J. O* M2 o6 B$ X) ?' L- A: h
        char szDriveName[32];
' j7 O* r6 \- {# x9 W: P8 Y4 X$ T, w, d9 v) D
        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);; F: o( s, o3 l/ ]/ h* N
        hPhysicalDriveIOCTL = CreateFile(szDriveName,2 I5 ]2 p1 ], m! c1 r: K3 s
                        GENERIC_READ | GENERIC_WRITE,9 R0 |; o4 |/ w! ]; |- v( \
                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,! b- _# n. \- @
                        OPEN_EXISTING, 0, NULL);
. [: y7 \* j% g: b: C# q* ?6 ~2 f; P) e1 R2 D- L7 N
        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
. f7 j5 O5 a: t" }        {
7 T! y) o; B" R! H* Y' I            DWORD dwBytesReturned = 0;; V& T- l% K3 J" D
            GETVERSIONOUTPARAMS gvopVersionParams;
: D1 T6 h, ^$ U( X$ a. r
2 u5 f# @# x; z, j5 K! b" O            // Get the version, etc of PhysicalDrive IOCTL
' ~) _& U& F$ a7 F/ v2 t            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
: {, g' x1 x- ?4 n& f, H' n
6 }' Q- ^, ~5 \: ~! H9 ]4 K            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,2 Q9 T" R7 Z" z5 r3 l
                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),2 h* `1 `2 Q/ y8 j4 f; {6 ~
                    &dwBytesReturned, NULL))6 g0 r, J/ i! _$ l, h* c3 f. `
            {# |" _' R3 a9 e- h
                continue;4 j0 u4 X9 A2 K2 U& y
            }; E" Q9 [) f* ?" A; {0 y
+ d; H0 U3 J+ k& R' y% C( l9 P; u
            if(gvopVersionParams.bIDEDeviceMap > 0): @1 a1 Z# g. H0 ?; {
            {4 \! l, i- h  u' A
                // IDE or ATAPI IDENTIFY cmd# @$ S2 i+ g: g4 y/ x
                BYTE btIDCmd = 0;: _3 i: Q$ Q4 d* [: M+ U
                SENDCMDINPARAMS InParams;
, U/ w5 a2 \; w                // Now, get the ID sector for all IDE devices in the system.
6 K1 Q0 v1 U0 F8 t  ~' u' t# r                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,  O% X2 F" o6 v3 K7 U2 D/ W2 R
                // otherwise use the IDE_ATA_IDENTIFY command; J& Q, k- q3 ?6 O) ], N8 A
                // 具体所得结果请参考头文件中的说明
& B4 f' ?& K' ]1 F  e0 l1 ]* Z" l0 v                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?5 s; f3 S: B/ `! B" _4 ]) W( K
                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;% G# c2 m, F7 w! k$ d
                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));- |, O! o! V  u3 t# v
                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));! E% ]; [- \' k) r6 N: f4 p

3 _* B0 }/ C! ?7 U1 D                if(DoIdentify(hPhysicalDriveIOCTL,) |1 }4 j% ^& f5 h8 i! X5 a3 w% Z
                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,& b  x! t) }' B
                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))* n/ r, L, I$ r5 s+ J/ S
                {
* v1 |0 Y! g. y/ x) ~                    DWORD dwDiskData[256];/ p9 f3 v( F) s. p
                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件% C, N' s% y+ C
                    char szSerialNumber[21];
5 O# a) ?. g4 Y5 N+ n                    char szModelNumber[41];
6 l# H: B* b' Y8 u( A! o( R4 q7 I+ C
                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;; \& Q' ^  m  B
                    for(int i=0; i < 256; i++)
' A* q, H3 T3 t                        dwDiskData[i] = pIDSector[i];3 E7 I- ~) b+ g# |5 j
                    // 取系列号
3 |# e' S4 n0 r& f% r/ R                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
* E4 L) P" ~8 g- f                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
3 s- V8 G1 d; j# T( X5 N4 s" P/ h/ h+ L6 k' Y( a
                    // 取模型号7 U, @6 Y4 }4 x, \% K5 r6 r  B
                    ZeroMemory(szModelNumber, sizeof(szModelNumber));* E+ d! K+ _' }- f! a' w
                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));6 u1 q5 K. `$ W* g
8 g: q1 c" S! _* ^
                    pSerList->Add(szSerialNumber);
6 b) c3 }; ~7 H                    pModeList->Add(szModelNumber);
9 N; v6 \2 E! A, V                }
% `" d- q# _& C. q            }5 t' l' W/ ~. R0 @
            CloseHandle (hPhysicalDriveIOCTL);
) A3 I/ h- W' o) [! ^        }3 k4 L- M! O/ c3 P# N3 p% y1 ]
    }
% p3 Z$ Q& h& @9 T1 v# ]}
6 ?! z% [' B1 `7 k; l7 q4 h& U& ~0 k//---------------------------------------------------------------------------
8 C7 g- b% _3 @: j0 ^0 t// DoIdentify* f0 x' d8 x$ T9 G; e4 S: x- A* h
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,: V2 D) Q  L% A$ c0 D% ^4 z
              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
4 x7 T6 G% m; e& Z              PDWORD pdwBytesReturned)
, H3 o/ K: A; b! |$ n, c9 `- g{
! z! f# D  P/ \7 C5 l    // Set up data structures for IDENTIFY command.5 q6 u9 s9 Q7 [) ]: L% }: N! L4 |4 b
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;7 Q8 Y2 R! O+ b
    pSCIP->irDriveRegs.bFeaturesReg = 0;! [0 V& \9 M6 U9 j# G
    pSCIP->irDriveRegs.bSectorCountReg  = 1;
- Z) W5 w; B$ x7 i, r/ D  k. o    pSCIP->irDriveRegs.bSectorNumberReg = 1;
& l& E: O9 p; e2 T. n, t    pSCIP->irDriveRegs.bCylLowReg  = 0;
, |" t# ?- N  H* x6 M4 t    pSCIP->irDriveRegs.bCylHighReg = 0;
; Z  A4 q5 U3 D6 j' l- R& ?, O/ n8 l* h' m5 k* q# A/ C' b
    // Compute the drive number.(主盘和从盘所对应的值是不一样的)
" C. S- K! U3 H2 L    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;; x' y9 C' [/ K; A2 u
0 s6 p; _9 q7 Q2 t
    // The command can either be IDE identify or ATAPI identify.; v, H( S, ?$ @7 j4 \- p6 `) q, t8 s
    pSCIP->irDriveRegs.bCommandReg = btIDCmd;
, v7 k$ Q( j2 ]    pSCIP->bDriveNumber = btDriveNum;! I. k, d0 D! H  B7 O3 Z
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
6 _& Y4 I; n8 {$ k8 h
, o: f8 d8 S$ ]; s/ J0 W  P- H3 T, F    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,: z6 F2 h# w) c8 ?9 O
           (LPVOID)pSCIP,
* Z, I: l% d8 a7 [0 I6 M7 R           sizeof(SENDCMDINPARAMS) - 1,
  K- W' }5 S0 L; ?4 c  N           (LPVOID)pSCOP,
1 M* G5 k+ t& i           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,/ J- p# o, j3 L- V: F% t, w6 k( `
           pdwBytesReturned, NULL);# Z* q6 d4 q! z  C
}
6 Z, X8 M6 i3 [% C* n; ?9 Q8 n//---------------------------------------------------------------------------' U* A" Z: g. d- x2 Q* B+ Z5 i
// Windows 95/98/ME 代码& G1 I" u% y  [. T4 z: j+ O
//---------------------------------------------------------------------------
, s' F; E/ t  N( `& @1 L// ReadPhysicalDriveOnW9X
: y/ D, a+ n! A: x( yvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)# L3 @! t& v% v5 j( @9 l
{. K9 [2 J8 Y0 X2 U
    WORD wOutData[256];
0 `; U( o. b' v$ `; H" u    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);* R0 N' M* I* K! h/ p/ h' l
3 E4 X  g, C$ j9 p7 f4 a$ h4 y
    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。" r- F& p# n* ]6 j/ z
    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
5 X7 S1 X( a; k$ {$ d    // 避免蓝屏的出现。(期待高人能指出原因)' X( l2 k! g! C( m4 S
    for(int nDrive = 0; nDrive < 8; nDrive++)
+ q- \" a0 V9 ^8 l$ b* t& b+ ^    {9 X- p& @0 `8 ~9 F
        WORD dwBaseAddress;
- x8 u+ a+ n, g; V        BYTE btMasterSlave;         // Master Or Slave
" j- f. d% K4 Y  A        bool bIsIDEExist;
1 J* q4 A5 {' J        bool IsDiskExist;
1 @8 u8 R7 T1 A# k8 E+ x& P
$ d+ |4 n+ z. g5 t: D. S        switch(nDrive / 2)
5 H' N; Z: o' U  E0 j, _        {2 L' M6 s1 ^  m: z4 b/ K
            case 0: dwBaseAddress = 0x01F0; break;
0 h  X5 i" Q5 r& B! F8 m+ @            case 1: dwBaseAddress = 0x0170; break;
$ r4 W, L: q; r' r5 K            case 2: dwBaseAddress = 0x01E8; break;! b/ J; M3 p# h
            case 3: dwBaseAddress = 0x0168; break;
. ?0 t9 m; j: l7 d" n) I        }
; @/ ^. r- l! R" _4 x: v' S% |- v0 f
        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);6 M" B- }0 t- x) W0 n
  {+ m+ L" c8 b
        // 进入Ring0
0 ?/ m: ]( n4 ^8 e3 G) r        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,8 P, Y% [3 u, R9 e! J
                bIsIDEExist, IsDiskExist, wOutData);! V) `' V/ a, |: N0 `
    }( Z3 Q) l6 `5 O/ f1 z. ~
/ x7 r" u2 ]6 O9 v
    // 开始读取
  H* R! U  k* V& W$ G    for(int nDrive = 0; nDrive < 8; nDrive++)
: M, F3 m! ^; f: b) l    {' u) Y/ j1 G3 A, P/ |
        WORD dwBaseAddress;
( O* r3 d- z! X/ S, U" m        BYTE btMasterSlave;         // Master Or Slave8 A+ a. B: u* F  s' F/ O
        bool bIsIDEExist;. M9 e/ P( f; r' {* `
        bool bIsDiskExist;
5 t( E: ^( q( `" U$ M9 O; u) |9 V        switch(nDrive / 2)
( q) Y+ e, t  U; D' f2 m7 f- V- }        {' I  p" v8 A3 t9 v
            case 0: dwBaseAddress = 0x01F0; break;6 l# |- q) v$ H1 `% U* C- j! K! @
            case 1: dwBaseAddress = 0x0170; break;
# R; N. z% E% N' q            case 2: dwBaseAddress = 0x01E8; break;6 H$ k. H7 G$ C. j8 T
            case 3: dwBaseAddress = 0x0168; break;8 H) V" x7 R3 n
        }
) Q0 J: ]9 l9 ~& O: d2 Z9 P% }: W$ z- N& U! {
        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
. z- z2 i, \: w# K- L. \5 W" \$ F; L7 a2 t2 w  l6 L
        // 进入Ring0
; ~4 b3 h- y5 B, e4 b9 w6 C        bIsIDEExist  = false;: @: b" r' r4 c
        bIsDiskExist = false;' H1 h6 x" p& P" Z) w
        ZeroMemory(wOutData, sizeof(wOutData));
) |4 P* [* X* l% X- N9 c$ c
4 _# I9 |$ v1 @  V7 L0 z        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
6 H+ s: D5 q2 h                bIsIDEExist, bIsDiskExist, wOutData);
% p& \/ f; X8 B& z  ^8 O/ x
% V3 x$ c8 H7 |; f. B        if(bIsIDEExist && bIsDiskExist)
" x: e. y! p/ Q        {4 i0 z, ^: e' C' F9 R/ v. O6 N
            DWORD dwDiskData[256];7 Y' x( W/ |& a  M$ u/ C
            char  szSerialNumber[21];
' V/ U8 [) K, |( h: y9 g! z: F0 ~            char  szModelNumber[41];, W$ _; d# x  V2 z
4 m0 J% r3 e# i; a! E. S- j
            for(int k=0; k < 256; k++)
0 t4 |1 o/ W4 a# J( H                dwDiskData[k] = wOutData[k];
* g8 O2 h, i% X* E
' c2 W, ~$ p3 l. _            // 取系列号
" I9 |( ^; R: C4 _# f7 z            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
7 m8 X' p3 V+ y4 e7 G5 R+ g            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));' ^8 ?' W7 u, O0 `* K

! `3 D4 {- j4 Z4 w" o            // 取模型号% s8 Y7 @* y/ j; h9 s
            ZeroMemory(szModelNumber, sizeof(szModelNumber));, p4 H2 h( U( R
            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));9 C; G4 L4 I5 a0 }- U* t

* `; u/ L  p' X9 X, U            pSerList->Add(szSerialNumber);7 G/ p+ Q% d, W: |
            pModeList->Add(szModelNumber);
1 o1 Z% w6 o# t! r' k        }) z' K; R: s$ ]' g' R) x
    }
5 M: j, B2 q0 y1 ?4 Q9 U( e& \    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);4 S$ b  i, V9 v# Y4 b) @  m5 E; r! q
}8 I8 I0 J, R( a
//---------------------------------------------------------------------------
* i, @' b+ b+ `3 l, e; y4 f// 为防止不负责任的转载者,在此注明原出处信息,请见谅。, {# _& c! r- Z1 V. R% T+ ]1 C
// 资料收集整理:ccrun(老妖),欢迎光临C++Builder研究: http://www.ccrun.com1 m! I2 H) c( b6 f6 E9 M
//---------------------------------------------------------------------------! b. b( r1 |+ P8 [$ J% _$ w
// ReadPhysicalDriveOnW9X_Ring0()
# W; v) H9 H) _3 D5 m6 T% u* I//6 p/ ~: `( @" n
// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
0 G- l  E4 ?* p3 s" a5 T# V// btMasterSlave = Master(0xA0) Or Slave(0xB0)
% Z! j2 e+ N' X. [. Z6 ?0 V//---------------------------------------------------------------------------' R! J# O5 @6 W3 A# W* b
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,. j+ g+ \  E, S  n
        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData), }/ V: X; R2 K8 z
{! V$ v: s: Y# U3 X9 w8 D$ R
    BYTE  btIDTR1[6];/ O& N- Z& M: B3 }2 L. [- y
    DWORD dwOldExceptionHook;( Q( q2 T, E7 w" d' {. G+ g0 t( m7 L) l
    const int nHookExceptionNo = 5;
+ r8 Q  \  w2 h# F. L1 H# X# p( u3 Z/ M; v0 y$ t4 c" f; Y( ?8 m, Y
    BYTE  btIsIDEExist = 0;
; Q5 p2 \! F5 m& N# H    BYTE  btIsDiskExist = 0;7 V5 {# G3 @" u* ~0 b
    WORD  wOutDataBuf[256];2 e' ^/ T& t/ N( g' D9 I9 y
4 @8 X2 H0 ~& C% l& `( ]
    BYTE  btIsFirst = (BYTE)bIsFirst;
4 y' s6 q. h0 R5 u6 [: X; j
! I7 Z6 w% J7 c* O" {    const BYTE btBit00 = 0x01;
7 S4 S* H- D$ c8 R7 u    // const BYTE btBit02 = 0x04;6 }( _4 U2 b+ G# P
    const BYTE btBit06 = 0x40;' g- K% u) I% S1 {
    const BYTE btBit07 = 0x80;
# C5 B7 \- @: ]* ?4 j; x4 s% `    // const BYTE btERR  = btBit00;
7 F/ [0 }/ ]  y    const BYTE btBusy = btBit07;
! Z8 G8 G$ k1 j( h9 c6 ?8 n' P: e    const BYTE btAtaCmd   = 0xEC;$ G: |* s( j- A! S
    const BYTE btAtapiCmd = 0xA1;, F$ ]# H/ ^$ O5 W8 {
7 L+ g$ @/ \1 W. z8 p1 b% @
    __asm, k4 j8 W4 p0 b
    {
6 Y! B$ a4 M$ z- P) x  C# r& _        // 必须先执行这条语句6 S" S% e' B, w; `9 J* U
        JMP EnterRing0
1 w1 a4 |) A' E/ ^/ s4 T; s) _4 O$ m3 i& E+ w
        // 定义过程+ E7 o- L7 S1 v1 _
        // 等待IDE设备直到其不为忙为止
# \$ Y7 ~4 A+ U! l2 @4 I: v/ P        WaitWhileBusy proc2 v4 S& ?+ \: n7 L4 r: x
% S9 J2 Y# Y5 t9 l- n) _
        MOV  EBX, 100000
% c. H; H+ D& _8 P# X6 ~        MOV  DX, dwBaseAddress
1 q# G1 S+ c  n* ~0 h        ADD  DX, 7
! J$ P3 R7 Z: Z/ I5 `
; m* P  E& I* p* h0 r        LoopWhileBusy:
8 K* v0 W; ^5 @/ x2 l6 h* P% l3 ?
        DEC  EBX0 G& D2 a. y: }+ K. V+ I/ a/ y
        CMP  EBX, 0  A, [7 X! P* ]* A+ I& z
        JZ   Timeout
: p6 E$ t- a) r% s        in   AL, DX
/ i! Y& x+ O7 A* V1 X        TEST AL, btBusy
0 m. j4 N4 K) T5 G) b/ Z+ ]        JNZ  LoopWhileBusy5 Q7 l! m) V6 u& Y# f# K
        JMP  DriveReady3 i& _" y  Q8 q. a8 K7 y0 K
" e/ z" _" w9 i1 F  K- \  b0 _! c" l
        // 超时,直接退出
3 @/ |, \2 q# R, N        Timeout:
1 p4 T5 h. u4 b' a0 F$ y' a( z& A        JMP  LeaveRing0
' k: ~! y' B5 y! {        DriveReady:* E- Y- R! L; V! @) }
        RET
: u( _- S6 H  j& ~( u$ n1 E        ENDP   // End of WaitWhileBusy Procedure
# ~! p7 B! n( Q% S' s6 f6 `1 N0 Z3 [2 h! |( D
        // 设置主盘和从盘标志
: @; s6 X5 p1 ^* L5 w2 N: I, I        SelectDevice proc
& b' u4 C" F# ]; o; l, [$ K' s% u9 R4 [+ P8 q  w. B4 g8 F
        MOV  DX, dwBaseAddress
& q' F4 G/ N# n4 Q0 N3 N        ADD  DX, 6
) W! s3 S; p; {+ k, V0 q5 H        MOV  AL, btMasterSlave
& x) A3 @- F  N& Q5 y- V: h% ^9 U  {7 @
        out  DX, AL
3 F6 {# C4 F5 S/ @& K9 j. h        RET
7 M6 R3 c" E" k
5 K6 m. q; I& X# ^  r% o6 \/ R        ENDP  // End of SelectDevice Procedure
2 @  u* f, D6 n0 L/ m% d. p2 s: |; m/ @5 j5 O/ d! y' Z' I
        // 向IDE设备发送存取指令. ~7 a3 k; f- ~; V% N/ d
        SendCmd proc
( J) Z% S5 I1 h5 l4 d- h% D8 B% C; G  ]
        MOV DX, dwBaseAddress
$ f, @. C% l3 n9 M4 h: a/ d; C        ADD DX, 7
0 O: w8 f  ^5 H4 Z        MOV AL, BL // BL是主从盘标识,在过程外设置
5 q. l/ U' E+ \0 I- Y0 \: Z$ k& q8 l        out DX, AL
; A- C; i9 H! `$ v: }        RET! X" l) ~. u4 C* i
        ENDP  // End of SendCmd Procedure" c8 V: ?4 N7 M. t
; U% N7 [! b# g, l  x9 ^
        // Ring0代码7 m4 N% w: w8 e+ X7 b' `
        Ring0Proc:
3 V% h. X- e" O- o- D        PUSHAD
4 r+ j0 }1 n- L+ T        // 查询IDE设备是否存在
# n' n, D! S! u) i        MOV DX, dwBaseAddress
4 v# y$ R% N6 f( @+ _: _  R' c        ADD DX, 7, c+ q4 s# q1 N
        in  AL,DX7 t+ r1 `( q  r

. {7 c% r# x  y; e+ `4 }        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回6 a: E. @2 D* A# C* w
        CMP AL,0xFF
, r& ?, Q: Y0 `( u        JZ  LeaveRing0
5 ^0 E, r, _* B0 j+ K+ V/ l3 A        CMP AL, 0x7F
, r4 }' X+ @, }        JZ  LeaveRing0' Q( a+ d  ~/ A5 O
5 r$ m- x2 O3 v% U: J" ]4 C
        // 设置IDE设备存在标志( G1 w, u. p/ w/ M* s6 c
        MOV btIsIDEExist, 1  i- G( {6 o! A- Z5 n- P; b
: s) W% p! o, \* D* P) Q" R: O
        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)+ N# P: e) [5 u+ d/ B4 P: m
        CALL WaitWhileBusy
$ U  |1 Q4 _+ b" J        CALL SelectDevice
$ M" t- e+ b0 f" G$ \/ g) y
- @0 t" R* m" ?: h' o        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
/ w9 u( |  S  f& v1 c$ v        CMP  btIsFirst, 1- f# }6 z+ ^( |, B
        JZ   LeaveRing07 L. R+ t4 v+ U: B! m: ~& K

4 |, j8 r* M" R* I2 `( H3 n" K        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
8 y/ m3 [" C  u        CALL WaitWhileBusy
9 z  m' K$ E" h" Q1 O  \$ C. @& `6 t* Y: I3 B
        // AL的值等于cBit06时,不存在驱动器,直接返回. T( E( }0 W. ~7 E
        TEST AL, btBit06
7 b  W/ G( K  c% j( [( B        JZ   LeaveRing0
$ P: i; e8 Z; m9 |" u+ D# ~  t
# I; H& w/ u, m9 T6 t        // 设置驱动器存在标志- B4 t! t* O5 `  d; {
        MOV  btIsDiskExist, 1
1 q1 ~0 n& g+ Z- |1 I0 f
( i. P& L9 t$ }, I( @& w6 u/ p        // 发送存取端口命令  b- o8 L/ o/ e4 z, v: C. ~8 r
        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
# N! _8 Q! T7 u0 ~" L* g9 L2 ^8 J$ X        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
! w  C) `" y$ B3 N$ }$ z5 U2 f& I$ Q& z        CALL WaitWhileBusy% P5 T+ R6 {4 V% K$ _1 V
        CALL SelectDevice    // 设置主从盘标识
' h) N# B' r) g1 u6 t        MOV  BL, btAtaCmd      // 发送读取命令
2 x7 I0 y+ e! R2 }; }/ N        CALL SendCmd6 j1 J; s/ O6 J: M1 d% `& E; V, I! T' A
        CALL WaitWhileBusy
. c* z! r: U7 v# y/ Y
$ c- p& U, d3 I0 x: ~* A        // 检查是否出错* K3 }) ~3 v) |0 f/ t# {; n
        MOV  DX, dwBaseAddress
5 E* k- d6 n9 c" V# s        ADD  DX, 78 m" u, i+ Y7 `5 |3 B1 m
& M: k% {( O. T7 q; J5 w( f" ^
        in   AL, DX1 V; M6 j; p8 p0 v, a% `6 i; }% ~4 P
% j% T6 w5 c+ Y% _( `8 }
        TEST AL, btBit007 U4 l8 E- M. U# P
        JZ   RetrieveInfo   // 没有错误时则读数据3 R" z1 ]! M& x

( t/ `5 ~! G' \4 Z. _7 P4 Z        // 如果出错,则进一步尝试使用ATAPI设备命令* I5 ~! X1 E- c+ R8 t! v$ ^0 @/ q( _
        CALL WaitWhileBusy- O  p' @6 F& k; Z  s
        CALL SelectDevice  \$ [& C& i  ]% A
        MOV  BL, btAtapiCmd
1 e4 g  A3 y! O5 p) z! \( b        CALL SendCmd
6 z; L  {/ V- T( c+ j        CALL WaitWhileBusy1 B: t1 x5 L" d) K" |; [
2 E2 v* M7 e. W8 A: M
        // 检查是否还出错# w* x5 W( H! V. X2 n( q" R' e
        MOV  DX, dwBaseAddress1 b) c: ]+ g* N- c* L
        ADD  DX, 70 X; W+ C: W5 x
        in   AL, DX
- E6 e8 [( \9 P        TEST AL, btBit00
# K/ A8 S$ K0 C& C        JZ   RetrieveInfo   // 没有错误时则读数据
% ?( ~5 [: y0 ]# k4 m( K6 _        JMP  LeaveRing0     // 如果还是出错,直接返回
1 H+ h9 S5 N; q- @# u7 l6 w; V* a+ n. ~  U/ L9 b6 t. [8 g
        // 读取数据
- q8 _$ i9 d% R2 ^5 d# R        RetrieveInfo:& s2 F& p+ u. F; s0 ]- ?8 \

6 w3 a3 M' U2 w; [7 J+ L        LEA  EDI, wOutDataBuf
* U; N$ K; F' O! `1 u, C1 _        MOV  ECX, 256
! Z" X* a  D' e( a* _" _+ s( r2 P2 u: z        MOV  DX, dwBaseAddress
$ D7 T. y: A$ `6 j. Q% b6 K- _& k        CLD, ]0 {0 E9 o0 P; r
% S. q2 J/ [) t6 a) I! X2 _
        REP  INSW
+ }' R" P5 N. D# h2 h$ b
( E# `/ d9 R4 d- w, w3 P        // 退出Ring0代码* a) }% J+ U6 k+ C; m
        LeaveRing0:" E/ [, F/ G# S2 B/ t' c  ]* b% w
- `2 v" f0 c9 u% r% x+ a3 Q- e5 }
        POPAD
% y! u: c& b$ }6 f* u7 L7 l  c        IRETD
' W: ^& H. k+ N- s9 b, h( t( g9 ]% V+ \" t5 s
        // 激活Ring0代码( p7 O; ~# B. s
        EnterRing0:
1 L% Y' @0 b  O; P
" _/ e0 Y" H, V7 R        // 修改中断门
$ [; X: h! d" W$ M% k        SIDT FWORD PTR btIDTR1
2 N. Z5 M! ?9 C% U3 J) L3 x        MOV EAX, DWORD PTR btIDTR1 + 02h/ W6 `/ |, u* ~9 z' B, L
        ADD EAX, nHookExceptionNo * 08h + 04h
- Z7 p. f$ d/ F& ^        CLI
# R9 U" ^" M7 c( E- m; l; H4 v+ x7 A9 U8 m, [5 P5 p
        // 保存原异常处理例程入口
* n, G' Q9 `9 Y: H5 _5 G0 B4 m- e! j3 V        MOV ECX, DWORD PTR [EAX]8 L1 n& i2 L# y" [# n
        MOV CX, WORD PTR [EAX-04h]
0 S. [9 t# ?/ u3 c$ E0 P6 r        MOV dwOldExceptionHook, ECX
3 }3 p$ a  |  M' d7 U
+ U0 Q4 ]5 ~) l4 w        // 指定新入口
; P$ e; |/ y0 Z1 B, o/ N3 `        LEA EBX, Ring0Proc1 p# n* K% Q% k# y
        MOV WORD PTR [EAX-04h],BX0 B# h$ w$ H$ V. t: d( b# }
        SHR EBX, 10h
. F0 S# Q; V4 }# t0 W        MOV WORD PTR[EAX+02h], BX
/ ~" S( c4 g4 C, P4 {
+ R4 V" S8 r( r' o& w' f0 B        // 激活Ring0代码! u% W0 q% M2 b5 u' b" V/ ]
        INT nHookExceptionNo
/ E( g, @+ l9 m" y- t; Q! x  q7 T; ~( r# x
        // 复原入口) F( B3 M/ O, k
        MOV ECX,dwOldExceptionHook
2 |+ @$ V- i$ U* o        MOV WORD PTR[EAX-04h], CX% ]- E: n, r2 w* Z! i; ^- J
        SHR ECX,10h
% @- ?5 M) d" o# Q7 V% L4 J        MOV WORD PTR[EAX+02h], CX) U1 h2 W7 C! ^
        STI$ v5 b% f2 ]/ i0 D: J+ C
    }# e$ M' i( D- z" h& C
    if(!bIsFirst)2 H. i+ f4 C: h7 Y2 B7 J$ E
    {) s& M, w  V2 t, l
        bIsIDEExist  = (bool)btIsIDEExist;( e$ b9 v+ c$ O* e
        bIsDiskExist = (bool)btIsDiskExist;  s4 ?, H; f: |! }, q0 m* G
        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));7 F5 H% l1 i7 L0 I2 C& H$ c1 T
    }
5 o* r; \" A/ z, A3 |3 Q/ d}
* c) G, }3 ~/ Y//---------------------------------------------------------------------------
) s4 Z5 a- X8 n( F' u" q// 调用方法:
& a' W+ x  v" qvoid __fastcall TForm1::Button1Click(TObject *Sender)* v! R# _  Y% k5 d
{& ^3 u/ E4 b! y6 V
    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);; q* ~% n+ K& C7 v' p0 w
}& y! V# E/ K- d( k7 W
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-11-14 16:27 , Processed in 0.022095 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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