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

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

[复制链接]
发表于 2008-1-6 19:59:06 | 显示全部楼层 |阅读模式
代码框架,你所要做的仅是修改WQL语句,具体可看MSDN。以下代码为简介起见,一次返回所有的CPUID或硬盘厂商系列号( V$ Z) e/ Y0 [
  1. ; ^0 w- i! I$ d9 i& |
  2. #include "StdAfx.h"3 b' ~& p# c% o0 m2 z+ l9 f) B8 v  m
  3. #include ".\puiddisk.h"
    : g  }/ k* N$ z* w8 D
  4. #define _WIN32_DCOM
    ; W! z# A2 ?4 A2 B( P& }5 b
  5. #include <iostream>
    3 N  k! ^1 j9 \3 R) N1 \- B
  6. using namespace std;
    % s" H, Q# s: k. O. u: ?7 v9 f
  7. #include <comdef.h>2 C+ d1 D9 {6 m: l% Z
  8. #include <Wbemidl.h>- U0 o2 h, d* M2 k5 o4 o
  9. , D8 O( Y6 z) I' E- d
  10. # pragma comment(lib, "wbemuuid.lib")
    % |2 y- R' ~4 j% o+ n& Y& G- C
  11. CpuIDDisk::CpuIDDisk(void)9 j5 |# Q' j$ m6 ?6 Q" m; h
  12. {
    5 A, u9 Z. T- {* Q% j. t) D( b
  13.     GetInfomation();! t  A3 Z3 S3 |) {1 t
  14. }
    ( r9 Y" l" J' z

  15. . @% A& D4 |/ O. c' ~% ?5 C
  16. CpuIDDisk::~CpuIDDisk(void)& t6 V' q# U: d' `* b
  17. {" v9 b  n8 E& Q  Z
  18. }4 o# {$ k6 X8 Q( ?. |5 L4 C2 Y1 n
  19. int CpuIDDisk::GetInfomation(void)
    6 K' f$ i7 d/ E6 X
  20. {) [& b* v$ ?! T$ Z- f
  21.     HRESULT hres;2 f7 Z  ~- k7 r' Z; g: M2 D
  22.     //步骤1:不是必须的,COM只须也只能初始化一次$ r' G& w+ |! \3 k+ R
  23.      hres =  CoInitializeEx(0, COINIT_MULTITHREADED );1 s! s4 J2 D9 t
  24.     if (FAILED(hres))
    / ~/ F4 w! _) I) v  T! S
  25.     {
    / k+ F% m9 ~3 i
  26.         return 1; //初始化COM异常:注意,COM只须也只能初始化一次5 i6 j3 y& u  m6 i
  27.     }! v' d: d  U+ x: M
  28.     //步骤2:不是必须的,COM只须也只能设置一次0 l% f) n; @) C5 X. y% w# Z
  29.     //Set general COM security levels
    , U5 r/ d) P7 k7 ?
  30.     hres =  CoInitializeSecurity(8 u: A3 c2 u; Q( n
  31.         NULL, # J9 q$ n9 ?/ P! t+ t, M9 T
  32.         -1,                          // COM authentication
    4 s0 h! H9 T3 o5 h
  33.         NULL,                        // Authentication services
    9 {3 ]. J* D: |+ _- N
  34.         NULL,                        // Reserved
    & \7 H/ [# t% K( h0 b
  35.         RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication
    8 h  F7 o; q& }/ ~4 `9 j; e! O5 O6 l
  36.         RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  + t! p! U6 u5 ]- Y5 x, A
  37.         NULL,                        // Authentication info
    + y: m  [6 ?/ G. H( K( A( z
  38.         EOAC_NONE,                   // Additional capabilities 5 ^( L: x$ X4 e' w$ T/ k& J1 S  H) n
  39.         NULL                         // Reserved5 N. `( x6 v. j3 `! m
  40.         );' f5 u2 W; t( {- k7 f+ A: C; I4 U
  41.                       4 k# u2 L/ k* m* d) d7 Y
  42.     if (FAILED(hres))$ @  k# n5 H% C( V
  43.     {, h% F! E$ H( j+ X- Y; k
  44.         CoUninitialize();6 @0 Z0 W5 ~* I7 x
  45.         return 1;                    // Program has failed.6 N; L) T5 ^. j5 X& g; \
  46.     }
    & C" ?7 @" N; c+ S$ Y6 l
  47.     ) e! {2 W0 y( i( c! q
  48.     //以上不是必须的,若已有“::COMInit();”,则要跳过
    $ o- p3 U- t. b$ _7 l2 q
  49.     //步骤3: Obtain the initial locator to WMI
    ' [2 Y- l7 ?' B3 Z) d
  50.     IWbemLocator *pLoc = NULL;, i7 H# J) e( i; V
  51.     hres = CoCreateInstance(( v3 O9 Q& H6 X( A6 p
  52.         CLSID_WbemLocator,             # B! `5 A  [7 B& H" Y; i, _
  53.         0, , O% C/ X' b- \  h! N
  54.         CLSCTX_INPROC_SERVER, ! F6 b% I9 x) n- ~9 A, W
  55.         IID_IWbemLocator, (LPVOID *) &pLoc);
      O" }2 L; ?  L0 h9 B3 R/ c# U

  56. ' J5 \# c% ?2 l0 w0 A( n. H+ b
  57.     if (FAILED(hres))2 E- V2 j# V) U) v
  58.     {" Y; J4 H% ^2 _  O- d
  59.         CoUninitialize();
    1 _9 ?/ Y/ C( [4 T  C$ v3 \
  60.         return 1;//Failed to create IWbemLocator object
    9 X" u, M6 b- Q2 `+ n
  61.     }
    ; v, D7 J+ I" ]2 @' S3 P% K

  62. 7 b' L. p$ G4 i8 s7 W; u, u
  63.     //步骤4:Connect to WMI through the IWbemLocator::ConnectServer method  M% E! v0 C; Z2 [( g
  64.     IWbemServices *pSvc = NULL;
    ( _# H$ X* f3 z! l3 a5 m% h( H; f
  65.     hres = pLoc->ConnectServer(
    6 p) I  g/ B/ ?  N  r2 O5 E
  66.          _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace1 a3 b/ n2 x* r- w
  67.          NULL,                    // User name. NULL = current user1 w5 C& e# t6 Y9 |) k; K% e
  68.          NULL,                    // User password. NULL = current+ V- `; w( P9 R# a- u( G* T! d$ V
  69.          0,                       // Locale. NULL indicates current
    ; ]# H" l5 d0 S  O8 D8 A
  70.          NULL,                    // Security flags.
    - H) f, F  C% b( k
  71.          0,                       // Authority (e.g. Kerberos)$ U4 i; T* g9 y0 ?; k- d7 e! N
  72.          0,                       // Context object
    / o0 o6 G3 c9 S7 x2 ]2 M0 E% R# A# q
  73.          &pSvc                    // pointer to IWbemServices proxy
    . q* A+ j2 P. l9 G: L, U9 n
  74.          );, y; J( E& {* \
  75.    
    2 D. q5 i  G9 u2 ~2 C
  76.     if (FAILED(hres))# n- ]+ @) p% t; @  x
  77.     {5 Q. L  j5 u1 {$ B. O! Y
  78.         pLoc->Release();     
    + h: J) F+ z  W  Y
  79.         CoUninitialize();6 T- x! Q; G% Z. K
  80.         return 1;                // Program has failed.
    1 Y4 s  ^$ E+ O9 \
  81.     }
    3 B  f- V% w) ^: M& j
  82.     // 步骤5: Set security levels on the proxy
    $ _! i+ p6 i; l" ?: u2 p) a
  83.     hres = CoSetProxyBlanket(: }" P/ Z: t; p% K
  84.        pSvc,                        // Indicates the proxy to set) H2 ~- J7 R  E2 P; Q* I1 I7 i
  85.        RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx
    " p% U7 c2 j3 R* l6 ^1 `
  86.        RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx$ `$ A/ O2 `: P& H" u
  87.        NULL,                        // Server principal name - @& N5 A+ ]8 s, a
  88.        RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx
    5 K2 j) _! r) e4 n- Z
  89.        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
    / Q/ I) n, ^+ ~/ R$ G, h9 D/ m! X
  90.        NULL,                        // client identity
    " V* A* f) o8 E: @/ ?
  91.        EOAC_NONE                    // proxy capabilities . v1 l/ r1 E7 Z  j! d% _- R( J3 O
  92.     );3 L" d( h5 K4 ]/ x+ p" M
  93. ( @! J  U* g- X0 F- u% V
  94.     if (FAILED(hres))* A$ v" B* S1 p  _# i% e
  95.     {) Q& m+ y+ N# M+ P: S& t' R; H
  96.         pSvc->Release();
    6 U* A. u  e6 Z
  97.         pLoc->Release();     
    6 ^4 B5 Q# k  B- n3 y$ C9 z
  98.         CoUninitialize();
    2 D# l3 g# g. r
  99.         return 1;
    & {) _: H* t+ l* u
  100.     }
      k( B- J7 p4 w6 P9 s

  101. ; P& F2 |2 w! C$ e) I
  102.     // 步骤6:Use the IWbemServices pointer to make requests of WMI ----
    6 I) A+ @1 c  O3 M' }3 T. g0 U
  103.     IEnumWbemClassObject* pEnumerator = NULL;8 K. S5 x0 o3 y* }% @) [
  104.     //计算CPUID
    2 n. O9 j5 T' n) q$ B, H3 N
  105.     hres = pSvc->ExecQuery(, q# v7 W/ g; z8 v- B' y9 s
  106.         bstr_t("WQL"), # m! j% U6 ]# Y: k- u) i3 W/ z3 [
  107.         bstr_t("SELECT * FROM Win32_Processor"),//Win32_OperatingSystem- Z7 J& }$ B( y* g
  108.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, : ]: ?, _/ Z, [7 k
  109.         NULL,
      b  |" ~% k0 G* T
  110.         &pEnumerator);1 ~3 w$ F7 @) O
  111.    
    ; _. }/ v4 b- B' v/ y
  112.     if (FAILED(hres))
    + n& M( N. D2 X' A$ H1 _( X' i5 L
  113.     {1 ~7 m) g% V. \$ V% S4 E$ f
  114.         pSvc->Release();3 j6 x6 I9 x$ D3 ~3 }% x6 P. u
  115.         pLoc->Release();' v, g1 _1 N$ J) G+ R1 J: F
  116.         CoUninitialize();
    4 u, ^% P7 ~+ [4 g) T, U) v
  117.         return 1;
      f9 n1 E# Z, E
  118.     }
    ' E& x8 ?: T/ i2 F1 E5 L
  119.     // 步骤7:Get the data from the query
    1 Z6 {. k. k3 `; E
  120.     IWbemClassObject *pclsObj;
    & Q0 D" d. B$ e) P3 b: o. y) ?& s
  121.     ULONG uReturn = 0;& ~5 l) c, K3 o; f+ B$ H' n* r4 U
  122.     while (pEnumerator)0 e  u# |* q: C: t
  123.     {7 o, }; m$ g2 c" {* C% F$ R. s$ H  G: ?
  124.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, # o# M( J( W4 A4 f7 e. f
  125.             &pclsObj, &uReturn);
    ) D: ]' |* Z3 v' J: P  E1 ]7 h
  126. ! t/ s( u& O8 D: J/ S  G% t
  127.         if(0 == uReturn)  f4 n3 V& I* k* P
  128.         {
    ' Z- D5 Q9 k8 x  Y& y1 ~7 M8 n/ W# D
  129.             break;
    ( J6 W! K. ^3 `* k) S
  130.         }7 y& L- `5 `# A
  131.         VARIANT vtProp;
    : A" Z0 b2 ]/ w* q
  132.         VariantInit(&vtProp);) k. H: I, y5 _* ?( ^+ z
  133.         hr = pclsObj->Get(L"ProcessorId", 0, &vtProp, 0, 0);
    , |, W9 R% q" T/ S1 p$ M- ~: @4 j2 P- U
  134.         strProcessID=_com_util::ConvertBSTRToString(vtProp.bstrVal);//strProcessID:类级变量8 a9 H4 A# I  B  u$ M5 d  [- b( O" Y
  135.     }
    9 Y9 S+ ?9 V) D! Q8 i
  136. % `; N* L+ j) Q) `6 |, g
  137.     //计算硬盘系列号
    $ r0 L. J  S4 H  B8 l) ?4 N
  138.     hres = pSvc->ExecQuery(8 I( U7 J# Y9 E# `& t" P& u- Y- F
  139.         bstr_t("WQL"), # U9 U4 `' B0 e" g
  140.         bstr_t("SELECT * FROM Win32_DiskDrive"),8 t& S8 a$ F6 G* U% l
  141.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
    ; x2 b# X* z8 i5 B5 M9 F. H
  142.         NULL,
    * b9 _9 L% e0 j" k( i! Y
  143.         &pEnumerator);! a. G: x7 ~0 U

  144. 6 J& `2 o+ |' p  p
  145.     if (FAILED(hres))
    & N% q9 _7 k! q6 k' [
  146.     {
    ' F$ P& U. O7 I- ^
  147.         pSvc->Release();
    " X+ m/ W: [  P" {
  148.         pLoc->Release();- O9 J" o+ J* B. z2 ^( F7 m
  149.         CoUninitialize();7 L) d" g+ y# l7 M5 D3 b: `
  150.         return 1;
    / O+ J  c1 }5 b
  151.     }
    $ y+ @: L; j7 ?5 F
  152.     while (pEnumerator)$ P0 w/ G! }- @" H4 k1 M& f
  153.     {
    7 F; F3 ]& s; d. n, D6 {$ N
  154.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, . @) e. }% X( @8 E
  155.             &pclsObj, &uReturn);
    1 y9 F# C7 r, V. ], `
  156. 6 b* l% [) I! l2 h
  157.         if(0 == uReturn)8 j- q! u+ _' a* ]% M- D9 T
  158.         {* Z' ?/ k4 M7 u, |3 b' n. U+ a- w9 _) s
  159.             break;
    * d  Y" n* T, g
  160.         }
    , h) S( y0 o; i6 r6 W
  161. 8 Y& N; {& N6 q" h9 \3 F$ V, |
  162.         VARIANT vtProp;
    ( C, ~8 q2 X2 X8 Z
  163.         VariantInit(&vtProp);
    0 U" H& c) ~0 ^$ F
  164.         hr = pclsObj->Get(L"PNPDeviceID", 0, &vtProp, 0, 0);
    " _  P+ g! v4 x+ Y9 T+ n: Z
  165.     strDisk=_com_util::ConvertBSTRToString(vtProp.bstrVal);
    ) U$ k/ ~! m$ |3 V' R
  166.     }
    6 n3 k  O. C' V% c! [
  167. ; b# f* D$ Z$ G2 p8 z& l2 Y# U
  168.     pSvc->Release();' e) X/ C& Q/ S% {/ I7 `6 E
  169.     pLoc->Release();
    7 {- K; J' M7 p% p. _" ~2 ?) v& ?
  170.     pEnumerator->Release();2 s3 a, M0 M, c2 v6 M7 L3 a5 m
  171.     pclsObj->Release();
    % Z/ L9 P# ^& h0 r1 H5 S! Q
  172.     CoUninitialize();$ K. ~, D7 w7 k; B. E/ k) q
  173. $ A& o+ X7 F% R* f( \) a
  174.     return 0;   
    0 n4 k: B) V8 ~
  175. }/ \- N, K6 W/ v
复制代码
 楼主| 发表于 2010-10-11 19:21:05 | 显示全部楼层
本文代码经ccrun(老妖)在Win2k下试验成功.7 \3 P: Y/ h9 r4 D2 _

$ H/ M  ~: W2 R- B#include <WinIOCtl.h>
- v2 L8 X5 l% f" C5 P+ i#include <stdio.h>
) ]1 K2 G! N7 n+ r) Y
- r" {9 l- E( P; N4 k#pragma inline; }. |% g0 x, o& M
//---------------------------------------------------------------------------
3 k/ X' G3 o4 S- Q; `// IDE NT/2000/XP专用变量
8 Q+ g/ V8 R0 v- o* h2 g#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS5 N4 ^+ b+ e6 U% e, i5 |( I* r
#define DFP_GET_VERSION         SMART_GET_VERSION, n$ c* `* O$ Y+ P
#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND& ~! e" z+ k# u% ?$ l% t
#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA( C- B8 b. E# d. E- R. [* L. C

  j5 x# n! T% w: bconst WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令3 M* R. F6 T, K" N0 E0 U, ?8 Y" N
const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
6 n' I0 S: f' f
5 Y$ R4 d- y* v/ k$ I# Nconst int MAX_IDE_DRIVES = 4;
% V0 j. _7 B. P! b0 z0 F0 g! T% S  |$ P' B% M! |% J8 {
// SCSI专用变量
1 u7 J' H6 |4 D3 r. M/ zconst DWORD FILE_DEVICE_SCSI             = 0x0000001B;
/ N" K0 `6 I8 U4 N6 D6 Gconst DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
" @, V! ]- H! q' r5 Hconst DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
2 u8 o9 V3 O) |: \: O0 `7 Oconst DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;6 k4 t  K, j( Q
; @% i8 v; c# `9 v5 F# L* j8 v5 a
typedef struct _SRB_IO_CONTROL
4 z( i! P. {* }( n0 h. j. J- S. I{
' x5 V. y( [- h% e% I, _" e$ d. u    ULONG HeaderLength;3 |1 b, d5 _( Q/ F. N
    UCHAR Signature[8];
6 q! |! {! h) O' R# B  }, D    ULONG Timeout;4 Q, l8 H5 k! N1 w. M+ |
    ULONG ControlCode;2 O5 [! C" H/ L, a% k' `8 h; B# W# r
    ULONG ReturnCode;
0 N' P3 v* V% i2 x' Q    ULONG Length;1 z1 B6 V6 W) N9 P4 F% r9 {0 h
}SRB_IO_CONTROL, *PSRB_IO_CONTROL;' r' E6 d$ G: h: s  u, ^$ ^
, _0 [7 q" j& O8 P% x- i
// 读取的主函数
+ m: ~5 @9 S3 V, d: Tvoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
9 W4 ]# s4 s: e+ \2 ]/ x4 K9 E4 W5 s# U* V2 y. A4 x
// 辅助函数  [) ]9 g  O+ N( C( U9 K
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
3 v3 ]. s) N% [. s7 _2 h! t5 w// NT/2000/XP函数
: |( n" j7 W1 Z1 L) Lvoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);: p5 a! o$ v" i: `4 R
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
3 w: @0 p: G6 ?        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,( |' ^  J+ I8 C. u* k! Y
        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);. R# ~- p5 |8 M* T1 p6 ^6 R0 ~/ d
// Windows 9X函数
% i7 p' D4 O( S5 |" ?* Mvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);) i9 x6 Q- N, @" ]* k
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
3 D( O) y( c9 ^) x3 z  W        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
5 ?  z" {, q6 M& X; f9 P1 n# c8 x7 Q/ ^! {4 n6 [  A3 J, p0 g& E
// SCSI读取函数(for NT/2000/XP)
0 K9 [- C! z: \( d" iString __fastcall ReadIDEDriveAsScsiDriveOnNT();
3 k4 t4 m: j& ^* N2 `: R//---------------------------------------------------------------------------/ Y3 P- a  v" x- T2 d$ a( X" m
// ReadPhysicalDrive' O+ l% z% s* ~) ~, \( g, |7 t
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)" I+ o, k% ~4 q7 Y/ r
{- s% ]9 D& v6 V8 U! c# ^
    switch(Win32Platform)
( W: }7 s0 v& s# X: U! Z    {
- t. G: v& [7 q$ X1 J; [        case VER_PLATFORM_WIN32_WINDOWS:: U: z4 n) z+ R4 T; e: _
            ReadPhysicalDriveOnW9X(pSerList, pModeList);
& o6 m8 M6 Y& c* J* F9 ^            break;; K0 |; w- x" E% e
        case VER_PLATFORM_WIN32_NT:
( g. Z. U. S" s0 t4 N/ O* \! L- |: O  j7 s            ReadPhysicalDriveOnNT(pSerList, pModeList);
6 p( M% p/ e1 D5 B3 M" R! q# K            break;$ ?# J; S2 N: z% I; z2 k
        default:" a; l/ |, Z1 ]. u, N9 @
            break;
6 I$ E; z* i( u$ F    }+ a" o+ S3 R" C* _9 d. Q. q  }
}
% W0 l6 m' L) l% S//---------------------------------------------------------------------------
; D- Y; s  @. p" _# q* }// ConvertToString6 p0 q9 @$ F; O, E/ s2 b2 U  @" {
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
4 e& T+ V! B& v. @) w" _( B6 K; X{
4 _+ n, S! S  [' G    static char szResBuf[1024];) }  Z5 `) X, j
    int nIndex = 0;
3 f3 @9 H/ o/ e- i# J* Y    int nPosition = 0;
4 t( U' i1 f  B8 N: v! J8 h4 T: T' v5 y* v4 W$ t
    // Each integer has two characters stored in it backwards
# P  s' u9 n- M: Y, k) p    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
. O0 r8 x& \+ D4 ?$ D& V4 ^    {' T9 R- k2 K' L# u
        // Get high BYTE for 1st character
) r7 U* w2 \# v        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);# X$ b) l" c' Z! j( ^
        nPosition++;
1 U4 R( e. [+ r; ^- F- q/ d  s& f5 t  r; `/ w
        // Get low BYTE for 2nd character# d' {2 H3 G, G0 F# D
        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);/ i/ B) W0 q  h: n  I, @8 ]
        nPosition++;
8 O9 P3 F0 ~4 Y" d: {) c    }
2 E9 y1 e7 Y1 z$ {! a7 H1 j6 i( \: v' u, [
    // End the string" c( ~8 Z8 X, L
    szResBuf[nPosition] = '\0';
. L8 l7 c0 a7 @4 |; [4 j) C2 y0 X( E
    // Cut off the trailing blanks  I! `9 @9 F/ n8 K3 o9 o; f
    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)% ^" P- U9 U$ I) k9 H+ ?
        szResBuf[nIndex] = '\0';- ~0 D7 t0 V+ E) k5 Z

3 K! m& z5 E7 Y% |  \    return szResBuf;
. n- ^9 j6 o7 c, ~}
3 ]  W5 h. d+ i) g//---------------------------------------------------------------------------
, a/ N: C: q6 l/ u0 k" x# f+ `// Winndows NT4/2000/XP 代码
( _, t( c. C3 q& [. G8 H//---------------------------------------------------------------------------9 x4 F  x' I- B! R/ E/ _
// ReadPhysicalDriveOnNT6 F" o  ?8 k& i2 M5 ~
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)% h  h" U; h% ^0 q" T$ h* H
{
/ S- [: U( M  T( V: X0 t5 U    // 输出参数. F3 ?; L2 j6 B2 c  `1 O: ]
    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];2 W8 ~. ~5 u. H: Y
& n" i) H. u8 d( Q. r; S
    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)0 P0 U; n. d$ d4 W
    {
' {& [5 C( d# u9 e. m; {' M        HANDLE hPhysicalDriveIOCTL;# k& H3 K0 `, \& n5 ^: S) J4 Q
        char szDriveName[32];
4 o$ g6 R) h/ V- u. [* L# |" d9 }
- z8 [7 r. i9 r- B7 U+ C" r- ]        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);0 C- M& H8 l7 Q3 _! ]. T7 _
        hPhysicalDriveIOCTL = CreateFile(szDriveName,
) n1 o% Q- D/ [: c1 i                        GENERIC_READ | GENERIC_WRITE,% ]2 A8 k, i  D; ^6 }+ ^+ K. t
                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
5 ~$ ]$ E7 X0 S- k                        OPEN_EXISTING, 0, NULL);) m1 |8 y8 X8 b2 U( P% u

5 p6 ?/ a  c3 H' X* }        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)/ [2 m. H0 w: R# ~- F0 ?
        {, q3 B2 l6 U# w9 K' q
            DWORD dwBytesReturned = 0;
; U& l; r2 Y% N" g            GETVERSIONOUTPARAMS gvopVersionParams;
+ C# I/ q% _, O5 Q& q& x! x8 B, k( B) H2 `6 b
            // Get the version, etc of PhysicalDrive IOCTL" y3 r* C; j5 o, _+ r" n2 R: B
            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));* o$ x  u& L. x/ X4 C
' _$ G- T( Y5 I( y
            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
; R+ E- r. f& y3 f: G                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),: m* ^( d/ T7 p4 j9 [! \
                    &dwBytesReturned, NULL))
# B+ m: N: _4 b7 M            {
, Q. |' u) H$ m. w7 Z# G                continue;  w7 @5 {& A5 \+ x
            }3 c6 L4 D0 k/ F* r+ ~
! q$ E6 R* Q7 O# I; f
            if(gvopVersionParams.bIDEDeviceMap > 0)* _8 g! |7 k* Y7 X7 p
            {. p) N( a9 p! b* F
                // IDE or ATAPI IDENTIFY cmd
5 w9 a" k' E# Y9 ?- R8 K$ M7 \                BYTE btIDCmd = 0;
) z" M) {, g) [$ A: [                SENDCMDINPARAMS InParams;
5 }& J9 a8 k' M9 K2 E- ]                // Now, get the ID sector for all IDE devices in the system.
8 l$ B) g8 d4 Y) O8 G                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,: Z% B% |. l, f; u7 _; E" v- e$ ?
                // otherwise use the IDE_ATA_IDENTIFY command0 U% F+ N7 H4 D0 U: U
                // 具体所得结果请参考头文件中的说明
  F3 Z/ a3 \" S* K2 C, I& j                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?  p9 z+ h; x& D% l, e
                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
' }. T: `+ K+ m: R/ w                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
6 t( G, U: \$ D+ s# P$ b' r                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));6 H. S7 Y( _% r3 A8 n
; }+ c  ^8 e% D6 q. b
                if(DoIdentify(hPhysicalDriveIOCTL,/ E) i! K& i( T/ Z& O3 @# c7 n0 B
                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,) J. j* [/ U4 H- s
                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))9 H$ D5 z1 `: ?. \" ^6 a5 Q+ ~/ h
                {
+ S& V2 Y& B; i# D  t: r2 A3 i9 p/ g. I                    DWORD dwDiskData[256];
6 n9 }0 _$ F; }) c                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件8 k( }& t4 t$ W
                    char szSerialNumber[21];5 K( b( C! X- m8 T
                    char szModelNumber[41];* K/ O! F3 J5 v( V# L/ T
, K7 K; {( w. U  K: q
                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
# a7 t% j1 I( W; e; C                    for(int i=0; i < 256; i++)
, g6 \, n" o1 g* Z2 h# A                        dwDiskData[i] = pIDSector[i];# [9 `! r1 G* v  H8 q' f/ H
                    // 取系列号& e! L% ~$ j) ^1 X' j2 Q. l
                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));2 l8 @: S  m" A% f- X
                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));* j5 r; {5 x  m
# {# k5 U4 l- l; J8 h
                    // 取模型号
- X  z% k0 l8 l9 q                    ZeroMemory(szModelNumber, sizeof(szModelNumber));0 \1 `; v2 t9 m# d0 `( g
                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
4 }! h5 k0 D+ P' \6 l; C8 [
& |+ t2 u: `& W1 m! X' f$ x                    pSerList->Add(szSerialNumber);5 d) ?6 Q( [# f' M- L! q
                    pModeList->Add(szModelNumber);
" l0 j, z6 X9 D+ U& D) d                }9 ~. c2 |8 P4 H7 {' t5 }3 A
            }
- h& A  F3 C% Z, r1 H5 t            CloseHandle (hPhysicalDriveIOCTL);) {4 J4 q- T, m6 X4 v2 }* x
        }
) z  m/ m8 \3 d+ y    }
% j' h+ ~+ \2 c2 g- [}$ Y5 p7 S* z) o/ G4 l! k6 [1 Z7 ?
//---------------------------------------------------------------------------
! E  r4 I9 ^! d" o9 L; A// DoIdentify3 @" f) m, A9 z1 @7 V& O
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
$ ~4 V/ @, t4 B# m9 V3 S( G7 s% Z              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,& w+ t$ Y% s+ A+ ^
              PDWORD pdwBytesReturned)) w6 |( P: [9 O3 ?" \- P
{
; A* l4 W) Q( N9 M3 A3 w- n    // Set up data structures for IDENTIFY command.
: n, c0 l1 j% p* ?& T    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
* ]3 m7 H& h0 l- l3 u    pSCIP->irDriveRegs.bFeaturesReg = 0;
- {& o& g3 m, u1 H    pSCIP->irDriveRegs.bSectorCountReg  = 1;
2 H# R2 j: K% \8 F    pSCIP->irDriveRegs.bSectorNumberReg = 1;
& `! l& L1 B/ j4 g    pSCIP->irDriveRegs.bCylLowReg  = 0;
8 p' J- W: g0 q! m6 Y  V" D( v    pSCIP->irDriveRegs.bCylHighReg = 0;# T$ \3 w9 w" ~8 I7 m. G8 O
  J; ?$ d1 T7 n
    // Compute the drive number.(主盘和从盘所对应的值是不一样的); y& E; S& g( D) q7 K/ e- D
    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;: F& A3 U  M* k7 `8 }" _0 G

1 J6 g/ E# q! L7 S) R" M/ p    // The command can either be IDE identify or ATAPI identify.! L9 T% }2 K% Z% f
    pSCIP->irDriveRegs.bCommandReg = btIDCmd;
& E2 g9 w. x* N3 O( x    pSCIP->bDriveNumber = btDriveNum;
3 M! i/ I1 I( a    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
* R  [: {, W* g& c  ]
) j9 ]# L1 c; E% C$ P    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,* ~# E" ?7 o1 O4 z9 b0 h* v0 a: G7 _
           (LPVOID)pSCIP,4 B7 j. S3 \' _, \
           sizeof(SENDCMDINPARAMS) - 1,* s. u1 g' G- H7 z: l
           (LPVOID)pSCOP,! v( u, G, S8 u8 n/ i
           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,/ ]3 s/ x, C3 }, H& Y
           pdwBytesReturned, NULL);
& _4 c5 H' B6 p! I) y; ]}/ f( D8 T2 e3 }
//---------------------------------------------------------------------------
% D; E1 `( C2 v3 Y6 R// Windows 95/98/ME 代码
+ |& l! Y( D4 M2 f//---------------------------------------------------------------------------6 o- B5 l6 T( b( }8 M4 P
// ReadPhysicalDriveOnW9X5 M9 ^+ O# s8 M* t) V2 ^2 m. ~
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)% \1 e/ r# N- O4 U& `* ~" o2 L
{
1 B, ^" i* }4 {8 I+ x    WORD wOutData[256];& m+ G8 x8 L3 K" g
    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
# K) {7 ^$ j9 t& Z1 k; P; i" r" p& m0 a$ v9 o( x' g
    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
% R$ i$ w7 F9 S3 N) r' q    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
3 U+ J! c" ?5 v    // 避免蓝屏的出现。(期待高人能指出原因)6 U# Q& w6 H: e0 Q; E, Q* ^
    for(int nDrive = 0; nDrive < 8; nDrive++)6 d1 r/ ~" Y% h7 D% F0 m/ J( A
    {
0 g! _, T4 f* E' g6 a( Y        WORD dwBaseAddress;& h. O2 S+ D3 Z& V1 L6 Z
        BYTE btMasterSlave;         // Master Or Slave$ _, P6 o9 w! r. H
        bool bIsIDEExist;* r  y% C9 ~2 W! z" }
        bool IsDiskExist;
6 X6 `' N& I& `; j  o4 Y
& K# i8 R. E/ o        switch(nDrive / 2)
' S9 j! t! d6 H5 H  I        {
0 n. k$ C5 a! k0 A& }/ m1 V- V            case 0: dwBaseAddress = 0x01F0; break;( R" q2 K+ R- E( n& a7 G
            case 1: dwBaseAddress = 0x0170; break;
) F" \8 o) z! C: N: t" X! z            case 2: dwBaseAddress = 0x01E8; break;6 N9 m- b/ f7 N" W
            case 3: dwBaseAddress = 0x0168; break;
4 W- `% I3 }% s        }9 G9 V+ w% R: W1 y' O8 r; u
+ w( ?0 r: ]6 ^; _# S& C+ h  ~
        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);9 @) [! G  L; u* c7 _1 {" A
1 I- N: m! @1 y& N
        // 进入Ring0) I$ n7 u0 b) @# `/ G9 N
        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,1 ^& K" O! |+ A3 E% \
                bIsIDEExist, IsDiskExist, wOutData);: p4 ?( t' l; Q% U& D! Y* O+ h3 b
    }' F* Q: Z3 H* _' X4 A$ }
7 j/ v' p$ I: q- p, N! h
    // 开始读取
/ _$ s+ `- ^/ y, D0 d! T& [    for(int nDrive = 0; nDrive < 8; nDrive++)2 Q* J4 ^2 |- l! J4 _0 ?% _
    {
* X8 e4 h* ^0 m: K        WORD dwBaseAddress;
( o- ?" C: ^7 b! Q1 o9 L/ v, D* M        BYTE btMasterSlave;         // Master Or Slave' ^% ^+ a% d$ p3 }3 J+ u9 N
        bool bIsIDEExist;4 P# D0 C% m5 M7 N# x: {
        bool bIsDiskExist;
/ T) }9 d2 B7 T9 F6 _        switch(nDrive / 2)# b& b1 G1 u9 t* `
        {
9 S5 \( w% M1 L; H) L            case 0: dwBaseAddress = 0x01F0; break;2 X, Z9 B9 n2 v% D/ U" ?/ Z+ a
            case 1: dwBaseAddress = 0x0170; break;* a- d/ P  j' O# p; C/ r% @
            case 2: dwBaseAddress = 0x01E8; break;
7 f+ o0 x0 a" ]8 t            case 3: dwBaseAddress = 0x0168; break;
6 N3 O; T; V0 O' H. z9 f$ I8 X        }& U0 k& G8 O9 Y* W% [
1 I. V( y1 X% F) y/ R
        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);2 m' T, m+ q# n- {8 ?$ t
, }2 _" x2 ?7 P& h5 S8 E! [
        // 进入Ring0
* n& G& m9 p& e! p        bIsIDEExist  = false;
3 H; h! O7 b9 c        bIsDiskExist = false;
6 F2 n6 N+ a- g        ZeroMemory(wOutData, sizeof(wOutData));2 g4 {- Q  t5 F4 D& ]" G
. S0 v: p1 _5 Z* H: u
        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,: x, l+ b: w$ R1 a% U* s6 X
                bIsIDEExist, bIsDiskExist, wOutData);2 t; {9 Y2 |. j/ _, m

# u+ |- d0 m% V+ ?  u% e        if(bIsIDEExist && bIsDiskExist)
5 p& o# k- B6 M; Z        {  l1 u$ x) S& e) Y* s; d0 s
            DWORD dwDiskData[256];: Z; m# \! z) R) G$ T9 K
            char  szSerialNumber[21];: m4 c9 Y9 Y1 P& j4 N
            char  szModelNumber[41];3 j. l( T+ z' }5 Y- V5 O4 u+ \

  e! q; {, Y2 U/ O            for(int k=0; k < 256; k++)4 h1 Z3 I6 x) R9 i+ \% p
                dwDiskData[k] = wOutData[k];
/ i8 w; [6 S1 l' v: \% G: K5 ?2 E& W3 A5 d- |
            // 取系列号4 h+ A3 i8 y  G( H6 h
            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));, h) b$ w. _/ j4 I* n6 d
            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));, n) Y5 Q( m2 i6 t. f

( p) q2 s0 @" F1 T8 Z            // 取模型号
$ H+ v, O3 e  Z* T% t            ZeroMemory(szModelNumber, sizeof(szModelNumber));
2 ?% R; n' Q! E& g. w: ^' X            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));. c2 C% z4 {9 }' Z  o; ]7 k
0 {9 x  I& [7 k$ N3 ]4 l6 j, O
            pSerList->Add(szSerialNumber);7 D# X3 o: E, u$ k; F2 e+ W
            pModeList->Add(szModelNumber);# B( T% |3 }; @5 y( b* {5 \
        }
9 O- j% [* D: L: U3 t    }0 X" w1 m0 K6 i7 J. w
    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);1 s" j, m: |' y
}
3 N/ C+ C- }# @# n//---------------------------------------------------------------------------
; h1 c% R$ b; w" {/ [& K' h, \// 为防止不负责任的转载者,在此注明原出处信息,请见谅。
+ f  Y7 K' u+ f0 {7 e0 s/ B// 资料收集整理:ccrun(老妖),欢迎光临C++Builder研究: http://www.ccrun.com
% ]) ?1 j8 e5 Z7 p//---------------------------------------------------------------------------
7 u  e* O$ v+ F* f0 s& l// ReadPhysicalDriveOnW9X_Ring0()
2 j7 m: W% r* ^# o//
1 E" A* F( c" g0 ]' I5 [; F// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
" K, N9 E$ N; c/ b/ e// btMasterSlave = Master(0xA0) Or Slave(0xB0)# Z+ x/ m& X4 ?' m! Y
//---------------------------------------------------------------------------
2 D' v$ {; R6 [9 @void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,. i9 y) d; V& f! q! ~
        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
- ?3 R! _9 k6 J1 z; {) o{1 v% X! J# F3 t& D- N& T7 U
    BYTE  btIDTR1[6];
) O, r$ O$ r9 o    DWORD dwOldExceptionHook;
7 j3 k% ~% }( G; u! R    const int nHookExceptionNo = 5;
/ y1 ?+ h+ n1 C; y8 ^) {3 Z0 x
- }0 U5 ]1 ?7 W& T    BYTE  btIsIDEExist = 0;1 V# K8 m1 t- K  ^, `
    BYTE  btIsDiskExist = 0;
' P5 |; F- g$ s. y* ]( w) O$ Q    WORD  wOutDataBuf[256];
( Z+ G" B; \$ V) u: L9 z  g& R5 b$ t$ h5 ]; ?8 M
    BYTE  btIsFirst = (BYTE)bIsFirst;
/ ], b  J' X  p; c) ]4 [. O, z3 t- T. k' b' P/ i) g1 b3 o
    const BYTE btBit00 = 0x01;3 }" {& [  ]3 V* r0 Z7 H
    // const BYTE btBit02 = 0x04;
+ p7 v3 b4 h- n/ U1 b    const BYTE btBit06 = 0x40;: {$ a, z+ G6 W3 a6 \9 J1 P+ p8 D4 g( L
    const BYTE btBit07 = 0x80;
% Q* G- f7 o6 }# d3 L    // const BYTE btERR  = btBit00;
4 c  U- U8 [/ ]9 y! ?    const BYTE btBusy = btBit07;
3 ~3 i/ [8 b8 ~/ u    const BYTE btAtaCmd   = 0xEC;
; D5 }  f' u" Q    const BYTE btAtapiCmd = 0xA1;* a; u; T5 ]8 v  u& r( `
* V  I4 Z3 t& R& L7 B# `
    __asm! r1 _4 d) g- _% y! ?7 Y
    {
% `- L% E" \) {2 L$ _  _1 t6 |        // 必须先执行这条语句- A" `5 G& _8 L+ \+ W
        JMP EnterRing0- i8 k3 n: ^; S% @/ f7 T1 @6 h

& `# ]8 j% {, D* K) C3 x        // 定义过程# Y4 }# W: L. D' }( y- p2 D/ r
        // 等待IDE设备直到其不为忙为止* z" ?! h! S, t; F4 A0 ]' N
        WaitWhileBusy proc6 o3 Z7 S6 |, \: m

, v0 S# s  [5 u- o' y/ Z        MOV  EBX, 100000
9 l5 T9 E7 K2 f* o  h' H( P9 ]        MOV  DX, dwBaseAddress: w) Y( s7 J$ ?
        ADD  DX, 7
" H* @4 Z0 o0 G' U4 _1 @$ s' j- _' U3 E% H
        LoopWhileBusy:4 V: s2 N6 n+ m( p7 F9 h7 X+ h- Z& _; ?

& w9 x, ]! f( a6 _! r        DEC  EBX" q3 F: ~+ D7 H0 k/ w, }; c
        CMP  EBX, 0
  o  |5 X* J9 w, W        JZ   Timeout' S- f  z7 V5 z/ D1 X! m
        in   AL, DX
* x  s4 n8 K/ r1 I! z        TEST AL, btBusy  ?+ W. s3 f0 {; [( b' ^- ~
        JNZ  LoopWhileBusy
+ }0 t. v  r5 [        JMP  DriveReady
  P9 b/ y4 Z7 @, S
) ~  X- u7 W0 k2 C/ p! R" m        // 超时,直接退出( i# j0 ]0 w* E1 ?  }4 @; O: v
        Timeout:
: j- |4 j( D" H7 [' \        JMP  LeaveRing0
) T; {' x* ?, p        DriveReady:
* `0 b- D6 U% x        RET8 T+ Z1 u# F6 v9 ?' I' @6 T
        ENDP   // End of WaitWhileBusy Procedure- U" Y& \9 H: M1 ]9 Z/ @# f
8 p7 s  ]0 p. J/ x' P9 c
        // 设置主盘和从盘标志" _& S3 q( z* o1 w- m1 ~6 @1 E# j
        SelectDevice proc
& V" R5 P3 k) `. }% E& R) H9 q4 `$ D  O. [9 F
        MOV  DX, dwBaseAddress/ |) y3 g, P) c" P* x( c* B
        ADD  DX, 6
3 \8 K. X6 a# p. O2 Z0 V        MOV  AL, btMasterSlave
' m% K7 I4 ?1 \- h* N; e# {1 C# S- n$ E  ]4 D# b
        out  DX, AL( P' m( |( G' V  n
        RET8 Z8 T" d8 D% d+ g* O% ^# X7 M: c

  A& R7 f" |/ V/ q        ENDP  // End of SelectDevice Procedure8 P$ {6 o1 |' E' f8 @7 h

, ?/ M+ B) U  h  i& B) W        // 向IDE设备发送存取指令. J- m  k5 E0 m
        SendCmd proc8 f4 Z# x: K. d

2 z2 Z% C( I( u: O        MOV DX, dwBaseAddress; Z2 `$ Y  r) T' D, [4 {$ o* P
        ADD DX, 72 a4 f7 C" J; b$ ^' e2 s9 c
        MOV AL, BL // BL是主从盘标识,在过程外设置* @. V$ r; U% Z# q# N
        out DX, AL
# t. B( E2 W+ t4 }2 T) u2 S- p' F3 G        RET
2 X4 }8 E" x9 x) `8 K! r        ENDP  // End of SendCmd Procedure
( H) U- a4 m0 G! `. k4 m
2 W% k. U2 x6 o# _/ \- I# Y        // Ring0代码! x0 O$ G  w2 o  Q* X0 T! T: q
        Ring0Proc:
! o  d+ d, Q3 s        PUSHAD
& o; r3 J( a) `+ i+ p" T' v9 n; a        // 查询IDE设备是否存在
1 K" [3 x* v5 X2 p' r        MOV DX, dwBaseAddress
  Y% V, D+ V' Q/ C4 K0 y% r        ADD DX, 7
! I& U; }* w0 J+ j8 z        in  AL,DX
  l2 J5 X$ p% e9 F- D. e/ \! e0 ^  L# q/ Q; g6 ^
        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
4 T# o) K) z+ `1 V: h, f* a: O        CMP AL,0xFF
8 F; P0 w. f/ W+ P+ Y5 T        JZ  LeaveRing0
; ]( F" J# h  h9 q- E# z        CMP AL, 0x7F
/ ^* d! A, h, f/ Y0 M' X        JZ  LeaveRing05 y4 J1 D) ~  |4 `* M

4 `! b# n2 g: ~: N        // 设置IDE设备存在标志
- ^  b  B) d3 u7 }        MOV btIsIDEExist, 1
1 v. K9 g# \  t! F# P( L5 }, t! m% J) L( v. j% a
        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面). m: |/ w* i; r
        CALL WaitWhileBusy
6 x. a  [* I" J& C" A2 T4 _        CALL SelectDevice& A% s- q2 M7 s

, i9 b2 l3 U* s( F        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏9 e" W+ P- u/ L2 `
        CMP  btIsFirst, 15 x( Z: d. T: _' B- ~
        JZ   LeaveRing0& J3 \  ?8 H9 B! |6 [

; Z7 R9 T7 e8 P' {, ^        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???$ W# Q% l) ~( x/ w! a( [, A% o
        CALL WaitWhileBusy8 q# C9 S) U1 [' S2 Y, ^
2 L( j& O& Y+ W2 h% }, R+ o
        // AL的值等于cBit06时,不存在驱动器,直接返回: K6 }! \$ f5 X6 R2 a, \
        TEST AL, btBit06. x5 S( O: ^# }0 ]; a, M6 j- W
        JZ   LeaveRing0* z( Q; ~% d7 P5 B

: c* j: Q8 o  Q/ s        // 设置驱动器存在标志
# Y  D. a  U6 m8 X        MOV  btIsDiskExist, 1
( z: w0 I( @+ I. x9 q
# t2 u- V& W4 D2 C6 \        // 发送存取端口命令* f# A# a# }! h) M% c% C3 I
        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
) |5 }0 O$ T, ^        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
/ F& ~' W  O7 A. m8 B; Y        CALL WaitWhileBusy) a- T$ g% s2 D2 G$ J
        CALL SelectDevice    // 设置主从盘标识0 H3 P$ j/ w7 K1 ]. n8 D
        MOV  BL, btAtaCmd      // 发送读取命令! q: P5 U: Q) x: m
        CALL SendCmd
" ]5 r) k0 V/ j5 ]        CALL WaitWhileBusy
  y) y( }! `/ ?5 r2 p& S
* r; s4 t: g, T  [' T4 D        // 检查是否出错
) c  Z/ ?% q( K        MOV  DX, dwBaseAddress5 z7 [" G4 ?6 a& G8 E
        ADD  DX, 7
! P% h' r" h6 n
# L# N3 P; e. `9 A4 i1 y4 M        in   AL, DX$ p3 Z/ X5 p6 {% P3 _

: r7 P& ~. }; p) `1 M& d3 b) A        TEST AL, btBit00
) F( ^9 i* Q5 A3 d# F" @& Z        JZ   RetrieveInfo   // 没有错误时则读数据
/ a) H$ c) X2 |& z% w6 X1 z6 l2 `" P, y% R6 |
        // 如果出错,则进一步尝试使用ATAPI设备命令
  _# J% J3 @! C        CALL WaitWhileBusy
' g; Q/ u& u: K% ?2 G/ @. O8 h! j        CALL SelectDevice$ H- T# }- I# p4 y3 [7 Z% \5 L1 Q4 O
        MOV  BL, btAtapiCmd
$ k( p% W3 V! s9 I        CALL SendCmd- c& u  U7 ~; l
        CALL WaitWhileBusy) i% o, b  n! Q* }! j5 {' E

! F7 d. c* t9 W& @        // 检查是否还出错
; J- N% ~2 m- L) \7 g        MOV  DX, dwBaseAddress
9 {- E0 A: t. i* y, `        ADD  DX, 77 \: W+ R4 j+ K) G1 I4 q
        in   AL, DX  Y2 g7 L  l* g* ?& J
        TEST AL, btBit00
2 i3 Z4 m$ T  y! Y, d3 Y3 K# }        JZ   RetrieveInfo   // 没有错误时则读数据3 B( Q, l9 ^8 r2 Q+ p8 a3 [" d
        JMP  LeaveRing0     // 如果还是出错,直接返回3 c2 f! w4 s0 y3 b; f7 c
3 `2 J: _8 s' G' t% Q# }; f
        // 读取数据: l% h  {2 |4 U" O
        RetrieveInfo:
( m0 K; G6 G8 X9 f! [  S: N/ q, V# Z
        LEA  EDI, wOutDataBuf
1 ^) \1 Y( A. A; H- Z! _        MOV  ECX, 256
; t  K/ e0 N5 S, s        MOV  DX, dwBaseAddress
3 y$ V, E9 X$ T9 Q& W, _: x' H        CLD
1 M+ O, T4 m" [% \/ g0 M; y8 V4 [* X1 u( F. g8 E8 B
        REP  INSW
) }1 e. h9 K7 M6 z/ }, O' G$ R
& K8 O1 l6 M" p8 W: |        // 退出Ring0代码
: U6 W- X7 W1 Q8 B9 A        LeaveRing0:
- s# O0 s" {6 F4 }# F  _" J3 E6 e
        POPAD
- f4 Z; Q. m; [+ w        IRETD! D; B' |7 q6 F2 u" x

  R/ q$ [$ [. D+ q% ~        // 激活Ring0代码. ?4 I5 k0 Q2 p" X
        EnterRing0:
: S- T; ]) F& `% x! X
  g6 h5 f3 m  ?& Y! E        // 修改中断门
$ B% k7 e2 y. y# g- V; T! o        SIDT FWORD PTR btIDTR1
* ?) `6 Z* G9 U; N9 P! Q* k  W        MOV EAX, DWORD PTR btIDTR1 + 02h
: ~2 s- q, b- [* m* g2 L( r        ADD EAX, nHookExceptionNo * 08h + 04h4 }6 h. b7 Y- K, W% q
        CLI
- Y+ u2 }  ^  ^7 `! H, |; i. o9 e% a; h* P6 f
        // 保存原异常处理例程入口' z) _. ^+ B# V' ?6 E9 u; m
        MOV ECX, DWORD PTR [EAX]
( P( i; {3 [9 u5 O        MOV CX, WORD PTR [EAX-04h]* Y, ?5 ?9 X- `1 E
        MOV dwOldExceptionHook, ECX' n' `+ h8 O2 C8 D$ P) v5 K! s

& s2 B6 L" `' T        // 指定新入口
. d$ J/ m0 z4 y( C' x* U7 ~        LEA EBX, Ring0Proc! @! }0 E1 v9 H" r8 X  O& j
        MOV WORD PTR [EAX-04h],BX' c% _4 x' B% d. w3 K9 S4 c$ u
        SHR EBX, 10h
0 }5 z- U6 I6 L4 N, O) P$ R8 |5 u4 K        MOV WORD PTR[EAX+02h], BX
) G5 x) s/ o. o7 L2 u  ]- B6 @- f1 j+ f6 \3 ]3 Z: U- F
        // 激活Ring0代码# T1 j. `' x: g$ ^
        INT nHookExceptionNo
; K/ C$ X, p" y% {- f; F7 S7 h6 \3 Z, R6 H7 L9 W
        // 复原入口" v( p0 k6 }+ {2 D- C
        MOV ECX,dwOldExceptionHook6 `% |6 R# e, y1 A5 O9 Z$ r( Z
        MOV WORD PTR[EAX-04h], CX
) o7 q. p5 G# g: |) h        SHR ECX,10h
$ e$ w7 G3 J* [. t$ N        MOV WORD PTR[EAX+02h], CX; W0 B0 F) z2 X' B9 g
        STI: @; t3 y; ?( d8 x% B
    }
7 n% }3 X* A9 W  S4 [, s5 K    if(!bIsFirst)3 D' {/ I; E, U! P( i2 u
    {
3 w9 w! p. p0 ?        bIsIDEExist  = (bool)btIsIDEExist;8 x! e" i8 `: w( F
        bIsDiskExist = (bool)btIsDiskExist;
) ^  }: P# L4 n2 G; i" r' P5 a        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
5 Y; f% e5 M0 m2 U    }
, K' \7 C+ f0 j}1 Y( h4 [( a6 O1 x- R
//---------------------------------------------------------------------------
, E7 ?7 D) A/ P/ ]" j. k// 调用方法:( m% a, F* S5 ~+ `- _- H$ [2 T
void __fastcall TForm1::Button1Click(TObject *Sender)
' j& |' J2 j( o* C( R{
8 V8 F! _" |) z6 H+ K7 @! [    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);: e; f* I$ a# k; u6 `! F
}
$ `- U6 {) Q0 t+ ?
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-5-5 00:18 , Processed in 0.016643 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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