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

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

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

  1. & @- V" o2 o: [0 V
  2. #include "StdAfx.h"9 ]! [. i) T; q4 Y. g) P
  3. #include ".\puiddisk.h") u. z/ c/ t! Y/ N3 z; D& a
  4. #define _WIN32_DCOM
      G" l/ q, Z) E; Z6 e
  5. #include <iostream>* @* U# L, s3 _& N5 Z: Q! i8 G: G
  6. using namespace std;. H1 y4 z' |% O! T. t0 y
  7. #include <comdef.h>
    3 e+ w! Q% n& @% U3 i$ O
  8. #include <Wbemidl.h>' m: {. Q* g3 }; l
  9. $ E- m/ }" D  E; b" p
  10. # pragma comment(lib, "wbemuuid.lib"): p  z4 x: B( [. |
  11. CpuIDDisk::CpuIDDisk(void)! {3 I1 |$ U3 y
  12. {$ F/ ^' v% L- m# d/ q; W: d9 G# ?  H
  13.     GetInfomation();: C- q' L* _2 V2 e, f8 y
  14. }+ b2 R$ A) r8 X
  15. & d$ R- q/ m( z0 d
  16. CpuIDDisk::~CpuIDDisk(void)) `* u- z) L' T+ U% f2 r
  17. {
    6 J. S- _- F6 N8 M! \
  18. }. G! e8 t0 R2 V
  19. int CpuIDDisk::GetInfomation(void), I' G. V+ ]4 k; ~  O/ y
  20. {
    # D1 ]! E  t9 p* d- R: L% A5 @) C
  21.     HRESULT hres;$ Q3 E' N$ I# x) m4 K) q7 L- Z
  22.     //步骤1:不是必须的,COM只须也只能初始化一次
    3 z$ w6 J9 T3 C) e& H) w# |
  23.      hres =  CoInitializeEx(0, COINIT_MULTITHREADED );
    " F, K$ D- ^8 x9 P
  24.     if (FAILED(hres))
    ' _+ B) f  M5 |  c! F1 V8 k4 U9 Q
  25.     {4 o% X* W2 j" D# s
  26.         return 1; //初始化COM异常:注意,COM只须也只能初始化一次- \2 a! S% U! P5 i% c  j
  27.     }
    . T# N$ o( m& ~: D
  28.     //步骤2:不是必须的,COM只须也只能设置一次  P2 W" s$ Q" W& R4 n
  29.     //Set general COM security levels
    : r: @) h+ @3 L# E
  30.     hres =  CoInitializeSecurity(
    2 r: y8 R$ Q' |- v9 v, Z! ]( c
  31.         NULL,
    5 L  A, p+ p6 _! T, G
  32.         -1,                          // COM authentication
    2 \6 F+ c: R' U. r
  33.         NULL,                        // Authentication services6 K; v# p9 V' f
  34.         NULL,                        // Reserved, V; v# f( L* O- K$ c
  35.         RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication - Q' g1 T- Q* [6 y' L( }
  36.         RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  
    ' X" v3 ^2 u# \$ w% R, J
  37.         NULL,                        // Authentication info
    0 N8 K5 @+ w" ]$ ], v
  38.         EOAC_NONE,                   // Additional capabilities ) b: i! w% E6 h
  39.         NULL                         // Reserved
    % t2 S* h" P$ u# N, D
  40.         );& K9 A7 L6 \+ K" P5 o
  41.                       . V! X- d" Q) w+ Y7 C4 v
  42.     if (FAILED(hres))) Q* @% p7 J( V2 C
  43.     {
    % [& K) }5 c0 _/ z2 a6 o5 H
  44.         CoUninitialize();6 I2 j0 t; V; m7 ?) D$ [3 s* v
  45.         return 1;                    // Program has failed.
    0 D9 C6 b- l& H
  46.     }; v$ _( R( E3 C: ~9 |( L6 U; Z! Q1 }
  47.     6 H  U* u, N* D2 w
  48.     //以上不是必须的,若已有“::COMInit();”,则要跳过
    & X9 U0 ^, o& k
  49.     //步骤3: Obtain the initial locator to WMI * B) |0 _1 d- i3 p7 x2 z5 c, y
  50.     IWbemLocator *pLoc = NULL;; x; Z9 {1 q- u3 Y  i* _
  51.     hres = CoCreateInstance(3 w. u( D; E$ t, L9 M- i5 [
  52.         CLSID_WbemLocator,             ( B5 h" Q4 d! V; K# c7 P$ [* ]% P& ~6 B
  53.         0, $ f" o- v+ d# E5 M7 [. q, N
  54.         CLSCTX_INPROC_SERVER,
    ; k9 c. _" d1 d3 y
  55.         IID_IWbemLocator, (LPVOID *) &pLoc);6 S8 C/ n" G: d* ]$ i% s4 v7 H

  56. % a5 K# d6 r9 {5 z# P
  57.     if (FAILED(hres))
    ' A$ w9 t6 e. K+ x" d
  58.     {. j& C/ }+ S6 [% b0 p
  59.         CoUninitialize();1 @& t+ x* ?& \
  60.         return 1;//Failed to create IWbemLocator object  F6 N+ o: G) d' n
  61.     }  E8 s3 P, v- s. C: E7 r1 k4 f

  62. 3 P1 i' Z* N% y2 q
  63.     //步骤4:Connect to WMI through the IWbemLocator::ConnectServer method
    2 r+ X& B, Y/ i7 g, p* s; k
  64.     IWbemServices *pSvc = NULL;
    ; ?* {6 B9 F* G7 C+ u% o2 W
  65.     hres = pLoc->ConnectServer(1 k2 ~9 d; @( x5 u4 o
  66.          _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace8 g  b" t, p/ [/ P5 R/ b
  67.          NULL,                    // User name. NULL = current user* C6 ^5 }, X8 n6 K# J* v! C6 R
  68.          NULL,                    // User password. NULL = current
    : x) ?: ]1 h8 y/ O# b5 X$ r' p5 J
  69.          0,                       // Locale. NULL indicates current9 W7 P  M; L8 P0 \9 H
  70.          NULL,                    // Security flags.
    ; A# p9 b& A# Z2 @. a7 u8 p8 `
  71.          0,                       // Authority (e.g. Kerberos)
    " u- L0 I. r# Y. f2 I% v" ?. \
  72.          0,                       // Context object
    $ O2 ^$ ^$ m4 d$ }4 H* y
  73.          &pSvc                    // pointer to IWbemServices proxy4 b0 n8 |  L- h
  74.          );& i- \# j, l* d* k; g% P: \
  75.     ! @7 I7 `- R" k+ V$ F1 G
  76.     if (FAILED(hres))
    5 G, o$ L( r  `8 X, i; M& @/ `
  77.     {
    : T9 ~3 R1 w/ \* n' Y+ u7 F+ N
  78.         pLoc->Release();     
    5 u* S& ?/ i2 o/ _, M' q' w2 N
  79.         CoUninitialize();
    4 r: S) h6 t6 x; @# q7 |
  80.         return 1;                // Program has failed.) ~  ~" e1 }1 w4 y/ l2 @
  81.     }
    $ I. l5 k, Y& ]) v. |9 u
  82.     // 步骤5: Set security levels on the proxy
    , M$ A: `) [& N( t! l5 o
  83.     hres = CoSetProxyBlanket(* e6 O% D  F4 T0 @, X
  84.        pSvc,                        // Indicates the proxy to set( a' ~# h- m* n
  85.        RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx
    ! y/ T! F+ S( |7 M
  86.        RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx; ]7 A- |8 a, H: y
  87.        NULL,                        // Server principal name
    5 i- B. b( G! {9 d
  88.        RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx 4 g' {( n+ u  P  H
  89.        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx8 ^. B6 O& K  v* y% G+ x4 F
  90.        NULL,                        // client identity
    1 L+ D* x8 n; v' C+ L2 L0 o: S
  91.        EOAC_NONE                    // proxy capabilities
      t) P; B/ S# e- r! u3 _3 d* ]
  92.     );; c  w% g8 L7 {3 S8 w3 K
  93. ( H9 S# y; N  i) `; ^: L3 N
  94.     if (FAILED(hres))
    " _! b8 P# X, E4 G2 k3 ?$ k; U# u1 y
  95.     {: r4 V1 G  a; _6 Y* A6 V# O! q
  96.         pSvc->Release();
    4 V/ A7 U8 s% H; ^- D# R; ?$ h
  97.         pLoc->Release();     ) i8 o; B2 [7 G2 a
  98.         CoUninitialize();! m9 u2 J+ _& S5 `
  99.         return 1;
    8 |9 L# t+ R" g
  100.     }
    " E* [# q  n3 \

  101. 2 Q+ p3 i) }! ]2 p: y$ e  Z+ O# o% O
  102.     // 步骤6:Use the IWbemServices pointer to make requests of WMI ----% d9 N" I0 ~/ T
  103.     IEnumWbemClassObject* pEnumerator = NULL;
    # ?" J4 L6 J5 D. U
  104.     //计算CPUID3 t/ ~8 T7 O1 w1 A) r
  105.     hres = pSvc->ExecQuery(
    & F' B- ~0 y. ~- C7 y
  106.         bstr_t("WQL"),
    / G1 N  Y, G8 v2 j1 f1 u# f" }4 g' n
  107.         bstr_t("SELECT * FROM Win32_Processor"),//Win32_OperatingSystem, N8 x; G2 b& w% X! k5 x! i8 ^4 F
  108.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
    # ^) [% x/ U. Y/ }" l2 G% k5 j% n
  109.         NULL,
    + V/ ?" A1 g* P0 U/ \2 f( B
  110.         &pEnumerator);
    2 D' p, K, n/ s- ]
  111.     - H0 N* U3 g+ N) T2 `- ~
  112.     if (FAILED(hres)); Z4 j- }4 H" x7 z8 \- n7 X
  113.     {
    . }. z) M9 e' u6 q. Q
  114.         pSvc->Release();. m+ h$ K* r% c% q& U! D2 s
  115.         pLoc->Release();, s' Z4 b: K, m6 y. w
  116.         CoUninitialize();# y, V. l+ f% d9 y' ]
  117.         return 1;8 {7 K; f" D2 j, \, u+ N9 k
  118.     }
    " D! o6 x' b* q& n
  119.     // 步骤7:Get the data from the query
    # U+ {+ d4 Z: ^
  120.     IWbemClassObject *pclsObj;, B6 T" z3 W* i% j
  121.     ULONG uReturn = 0;
    $ O8 ^& s1 r, G- J/ p- s3 f
  122.     while (pEnumerator)
    , }3 P9 @; J4 i4 P5 N# }
  123.     {
    ! N- Z! u5 g" W! I" R& z" s
  124.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, 9 L' R/ q6 s9 ~( ~% c7 P- L
  125.             &pclsObj, &uReturn);
    # G  |+ G3 J& r  s9 z& \( k7 S

  126. - b9 G& O/ x' y! X# _: Q, b0 E4 O: b
  127.         if(0 == uReturn)+ z6 V7 A5 g$ @
  128.         {% V; H# X+ D; q
  129.             break;
    : T' ]/ l9 j' V1 B
  130.         }- t* h9 t! H1 N! W/ D/ A% C# Q5 f
  131.         VARIANT vtProp;
    2 i) l& E+ d" D) x. Q8 ~
  132.         VariantInit(&vtProp);
    % X2 z6 V: i2 Z7 ]
  133.         hr = pclsObj->Get(L"ProcessorId", 0, &vtProp, 0, 0);
    & Y$ G3 w& ]$ I$ E
  134.         strProcessID=_com_util::ConvertBSTRToString(vtProp.bstrVal);//strProcessID:类级变量
    ! B$ X1 F4 j2 l/ Q" _" u0 c
  135.     }
    6 F; L! @1 e& M0 B# U

  136. ! g6 }7 Q" t" u" h5 N
  137.     //计算硬盘系列号
    6 k" ?- W, f1 u2 ?" p0 r" `0 f& C
  138.     hres = pSvc->ExecQuery(7 G6 `# [4 {6 A; i& e
  139.         bstr_t("WQL"),
    " D8 H% \3 ^" l. [0 \' q
  140.         bstr_t("SELECT * FROM Win32_DiskDrive"),
      j( T5 I1 b) v  W/ r# D) ?
  141.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, : K/ T, e6 F9 g0 p
  142.         NULL,
    5 ?- ?: Z. W8 G& e
  143.         &pEnumerator);
    * t( ^  U" |* ^7 O/ L0 {6 ~

  144. : }) U! j# F8 p+ {
  145.     if (FAILED(hres))
    $ E8 B% h% |$ T
  146.     {9 H  V& G3 c# L- W* U# o4 P
  147.         pSvc->Release();4 H/ W" T+ s( z% D  i3 V2 q
  148.         pLoc->Release();
      d: ~- E2 j& z% P+ z2 v  d
  149.         CoUninitialize();
    9 A: P- q7 u3 z4 v* {. t
  150.         return 1;
    + w/ P& P. Y" ^$ \; R
  151.     }7 M$ ?% m, K7 K- o9 Q, W: _4 M
  152.     while (pEnumerator)  f$ u* J7 R( T! J
  153.     {
    0 C2 e1 r8 _/ V9 S- _
  154.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
    5 J" F) @- M8 l4 f! C' r
  155.             &pclsObj, &uReturn);
    , X" N+ A. F2 @! Y
  156. - m  X) ^3 L2 `3 N2 f
  157.         if(0 == uReturn)
    $ l  [0 g) ]) Q" f3 S& q) z( H
  158.         {
    ( S- J( u2 {5 w# H3 F- N% R6 ^
  159.             break;
    0 n, e6 Q- P5 O- f0 o6 x
  160.         }" \4 m1 c# I3 H

  161. " {! U& v2 A5 m3 w. O  W6 D3 h8 |% i
  162.         VARIANT vtProp;) M$ ?5 I" v+ q, w
  163.         VariantInit(&vtProp);! H/ o7 y8 p5 f% c3 f+ a. B' a1 e
  164.         hr = pclsObj->Get(L"PNPDeviceID", 0, &vtProp, 0, 0);) x$ m: c3 J# U" D0 J" h
  165.     strDisk=_com_util::ConvertBSTRToString(vtProp.bstrVal);* e0 H+ {6 b. a3 h% \
  166.     }
    $ u) d) q# w0 ^& ~; F% W! @; b
  167. 3 p9 ?. }) l9 _3 |" B7 m" [
  168.     pSvc->Release();' Q4 j' T  y: M
  169.     pLoc->Release();
    0 x/ f$ x: m7 L' p& R$ u0 h) H
  170.     pEnumerator->Release();
    7 M( R( }' f9 K* b
  171.     pclsObj->Release();
    ; b  B1 s* P3 z# k& o
  172.     CoUninitialize();6 v* F; b' i+ y

  173. 1 n) u- i* I+ q4 G; `
  174.     return 0;   , b! y) J! g) f: n( w$ q, u
  175. }3 B/ `% s9 u! \9 k0 O/ `, U' A6 r$ p
复制代码
 楼主| 发表于 2010-10-11 19:21:05 | 显示全部楼层
本文代码经ccrun(老妖)在Win2k下试验成功.
2 t9 X$ f- }# M, i7 A9 U7 E
: V! W2 B, t. m/ [5 E#include <WinIOCtl.h>) _: I1 V: d8 i; d% Z
#include <stdio.h>; e* F- W+ ~' s

& K+ P: c" y& y1 E2 B#pragma inline% i, `! ~! E. s9 L3 m
//---------------------------------------------------------------------------
% U" v. k6 J( I2 r// IDE NT/2000/XP专用变量! N: n8 v! a& Z3 w- A
#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS# l) {' x* A. g) g
#define DFP_GET_VERSION         SMART_GET_VERSION
. B$ y. j' F# f3 r$ f#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
% q1 c1 G) V. p2 z#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA' H! {! v$ g. e* u3 W6 L$ ?( @

: q" {# s8 {1 |$ cconst WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令. m% \$ P0 w5 ?) m; v) j# c
const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令4 P2 C4 y$ g9 G1 ?4 @7 e% w+ s8 j7 y" A

( M) y( B2 g5 ?" G/ L: x1 ~const int MAX_IDE_DRIVES = 4;/ q  @8 c) p; N) t: L& S" W
; }' K5 M3 e, d' H
// SCSI专用变量0 w  o: N7 h9 S4 F9 Z
const DWORD FILE_DEVICE_SCSI             = 0x0000001B;3 n( h1 ~7 N3 l: K
const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
1 u) C) f7 u6 Y) A9 oconst DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition4 E. |3 {0 h: ^9 ^3 M) ^- o
const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
: x0 P9 {3 ?2 s1 n' @+ ^; P& k6 Z7 P
" `' E* [2 W& Y- q2 i1 stypedef struct _SRB_IO_CONTROL
7 X+ T& \8 C: k{0 j7 c" O( B2 M4 [' m
    ULONG HeaderLength;
2 D& F" w2 y, A1 a    UCHAR Signature[8];
5 V& ?7 v( ~# L. ]; F    ULONG Timeout;
% J5 n7 y8 L: r! |8 B* G& N, {    ULONG ControlCode;- K0 s$ W* A: C) [( n8 V' x% X
    ULONG ReturnCode;% I/ h# S+ ~6 T
    ULONG Length;
+ G6 g% |' b0 Z! @}SRB_IO_CONTROL, *PSRB_IO_CONTROL;
% D; y/ r+ ~, }( S8 u9 I4 i% i* b' I
// 读取的主函数& a) M4 l7 T; m6 k8 u* ?
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
4 F2 t6 `% o  E
. r7 ]. i" b5 h9 e2 u( J8 C// 辅助函数& G. V. r4 o& Z5 A4 N
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
. N' i8 u  H3 K' I// NT/2000/XP函数# [/ I2 k/ R8 U. e2 G, @1 z
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
8 b) B. Y4 x( `1 s+ u0 Gbool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
0 E' k" X. |$ |1 ]        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,' H5 v; ^( O5 A' {! }8 X% N
        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);; [& e+ H6 H- ^8 ]1 ]) k$ L- C  a
// Windows 9X函数
" C+ O  S8 d3 W9 `6 e# W# V) pvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);& R' Z" ~6 c* l* G
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,% J0 S6 y- o5 b
        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);+ D( E' N; ^1 y0 x. m- z' v

" T# s; K+ j. S1 e! ^// SCSI读取函数(for NT/2000/XP)
+ @, W) B& V. U5 c3 g, I: bString __fastcall ReadIDEDriveAsScsiDriveOnNT();. N  |* t/ e7 l: C1 W
//---------------------------------------------------------------------------4 S6 A3 i# B' r" |
// ReadPhysicalDrive
$ l# ]6 ]7 W" m5 o. lvoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
) ~# u% s% a2 }$ ~2 l5 X% I{
9 s; S3 y0 k4 o- b- [9 s/ ?    switch(Win32Platform)0 ]0 l8 h1 H1 J& t" ~! N8 {
    {9 R) Y  L) L7 A3 j" \  L0 u5 {
        case VER_PLATFORM_WIN32_WINDOWS:5 X' J( O0 B9 b% `
            ReadPhysicalDriveOnW9X(pSerList, pModeList);
2 z) V- N- A! t6 a            break;
6 L6 O; g6 r4 \5 [% D6 a        case VER_PLATFORM_WIN32_NT:0 U& O( ]% l% ?1 k' \
            ReadPhysicalDriveOnNT(pSerList, pModeList);! v5 W; a' w' @" S
            break;
# ?6 l/ i+ O  m9 `' Q9 `        default:6 ^3 A! ?# D8 F9 G
            break;
6 B" z3 h) A* ~    }
' ]2 f2 X  w# k  M* @/ {( |& ~}
, D% C; ^+ u/ G  k8 N//---------------------------------------------------------------------------- r- I- A' w' F1 q  y3 c% d
// ConvertToString) I4 ]  Q) z4 X7 B
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
& U" F/ g% T, e' s% u- b{+ q, N" [- Y. k- v, m
    static char szResBuf[1024];9 d" \0 M' |; x# m# Y) P
    int nIndex = 0;
( S* Q, S: W8 n1 @; p" T) ^: Q    int nPosition = 0;$ K0 _* V0 x( Y0 n6 j4 e

- P( z5 x' r# _    // Each integer has two characters stored in it backwards
/ w  L. ^) X4 u7 C: U# E7 `6 E( ?% d# W    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)% K: `* C' C+ h: f5 g
    {
3 D, E  G! n3 u! m5 V8 [9 I        // Get high BYTE for 1st character
4 z* v3 k) o3 C! ^. I        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);$ _- W! U- k% A: m
        nPosition++;" h, d1 @' H" U; q
. i: @9 Y3 V- u  i. N6 t8 \
        // Get low BYTE for 2nd character! x8 x# f0 v+ C; m( W( N9 L
        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);$ ~( X& E6 O# k) ~2 |
        nPosition++;- x6 M  h' G1 m: {
    }+ x+ k/ x/ ]4 {/ |6 Y0 @% i3 T9 ]
6 b% F( i3 e, h. l: p4 Q0 B8 X
    // End the string
: Q8 D2 d6 \# k) F( H2 D    szResBuf[nPosition] = '\0';
" b. @: ~$ L/ d% d4 A8 W0 J4 h
; r$ ]2 Y% \6 X! {' }    // Cut off the trailing blanks
. \- t, }  c2 B' N: C! \- w. v    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
; ]; K/ A+ e! r0 s        szResBuf[nIndex] = '\0';; S0 ~* U$ B, u& h( ]# V% P$ ^8 i
4 n" F; E. t: @/ o) j
    return szResBuf;' a& L% w5 o& n* W4 k0 W, N1 _
}
% t# u$ y7 H4 F$ S//---------------------------------------------------------------------------$ U9 w3 O* {) o4 \
// Winndows NT4/2000/XP 代码- B" m* X1 \1 Z$ {
//---------------------------------------------------------------------------
& P( c$ b( O  w; x// ReadPhysicalDriveOnNT/ h- X5 w9 b, T3 @# K% g- I. |2 e- ~
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
! i6 a5 P, v, A, R7 h* s& m2 s{  U5 ~; ?2 S) e4 m5 @* \
    // 输出参数  M6 i$ f2 m, e, Y8 }
    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
$ G& R) L$ ]  |, w6 c% `2 B
! S7 _' o& ~$ F/ d/ e  N    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)0 h3 F* o' t8 r
    {
  E' A: e2 K+ y% g& _, I        HANDLE hPhysicalDriveIOCTL;9 ~) ~6 T5 h3 j  c3 z- z
        char szDriveName[32];: N* X+ p  [0 ^2 E

4 }+ E) U! o) W) W6 s        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);! O- @+ b5 T4 j
        hPhysicalDriveIOCTL = CreateFile(szDriveName,$ D) P9 p1 q6 Y& n- w
                        GENERIC_READ | GENERIC_WRITE,
3 q, S+ n, I$ `( z1 d                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,9 B* o& w! U( w, V& a% A
                        OPEN_EXISTING, 0, NULL);% n. E, ^, S0 a' S6 i
* ]6 \; U6 p% M7 }
        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)* |, V$ S1 e; z% ^6 ?
        {# G' V. y2 x3 L% b& Z7 a
            DWORD dwBytesReturned = 0;5 ~* G& Y5 _5 U( A. E
            GETVERSIONOUTPARAMS gvopVersionParams;
8 l' c( ~5 Q( G1 s% s8 _2 p2 d3 N1 V6 d, J4 K
            // Get the version, etc of PhysicalDrive IOCTL, Z$ j2 D" W3 K7 T, R  P. {3 |
            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
5 ]+ t4 S& w  Q/ v( `" _, I* \1 a1 P
            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION," c8 l* Q4 z1 D0 F. p# [; `
                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),2 l, [1 B( F3 D0 k5 ?+ @2 s
                    &dwBytesReturned, NULL))
: V$ z/ x/ n1 ?7 m6 @8 t& v4 l' D            {9 H. K2 ]; d, H& L
                continue;
4 ?% O( @& {2 t2 I& a+ {( w            }
- D1 d; W' A4 E. \7 f+ x/ L, ?9 s; A( o: l+ v
            if(gvopVersionParams.bIDEDeviceMap > 0)2 e# r& D5 u% Z5 b
            {2 s/ \( `5 Q' W4 Z3 L+ ]! {
                // IDE or ATAPI IDENTIFY cmd- c# X! ?+ t- r' V& l! ], ?$ P
                BYTE btIDCmd = 0;
# R7 O2 ^# o  n                SENDCMDINPARAMS InParams;7 r/ K* Y: a$ U# j
                // Now, get the ID sector for all IDE devices in the system.+ x' n5 Z5 H* u8 o8 h
                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,4 Q+ v/ W9 J* |4 O
                // otherwise use the IDE_ATA_IDENTIFY command
7 [3 K; J+ q8 V                // 具体所得结果请参考头文件中的说明/ E; E5 h0 l3 E
                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
' o% @% c$ l* I2 T; F                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;" m8 Z0 n3 r- j! U2 F6 ^  ]
                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
1 k- t. u7 J' v. i                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));" r% Z/ C3 F( u" V$ F4 R
" E% u- }/ A* C: u  t- q
                if(DoIdentify(hPhysicalDriveIOCTL,4 s) s' e& T( w$ Y' m# |
                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,- j8 ]6 t. o+ H+ J( g
                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
; Z7 |. N& A& K                {
. F$ v2 n' ^2 p& g                    DWORD dwDiskData[256];0 }3 b  V! q/ E
                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
& ^7 z' R- z, m( K1 Q5 C                    char szSerialNumber[21];2 _/ U- d3 M" C3 }: x) y
                    char szModelNumber[41];0 ^3 h6 _/ q; _9 Z( k# w. l

, H% r9 Z' \8 P                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
% F) d, i6 ^& H; w5 ~% ?  K1 y                    for(int i=0; i < 256; i++)
# J/ g9 F, J7 r; p( ]( `6 }# ?                        dwDiskData[i] = pIDSector[i];2 b0 d# j  g* Q0 ], n
                    // 取系列号
$ D$ W% N( p% Y- k  C( B( s& U5 r                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
: D2 p2 N% V0 Y: Z+ r                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));5 i0 Y1 R7 ~, @0 o/ z: E

% Z& |  R: S6 C: U                    // 取模型号7 j4 J3 u1 \& q" S; ~6 z4 g( f* m
                    ZeroMemory(szModelNumber, sizeof(szModelNumber));1 \4 s8 Y6 r% R9 a* s1 y# _" {
                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
/ t% _6 j* `& s/ A% a( y! N3 [4 J- y0 t8 F) A
                    pSerList->Add(szSerialNumber);9 J" z5 X3 y- S9 U
                    pModeList->Add(szModelNumber);
6 F1 t- u) z8 F8 w! r% P! |                }
$ R* `8 }9 V' N2 }2 f! }            }
5 t8 I" v$ ]3 h2 U            CloseHandle (hPhysicalDriveIOCTL);
# z7 ]6 [' L* Y2 q8 k) e- C9 U        }/ k3 ~7 z4 F3 s, ?" H6 x
    }
& N! m& B. J  {$ H, h}
8 i) Z- c3 ?) @) R* q: W7 t" I//---------------------------------------------------------------------------, @( u) o0 n2 q5 J: U# C( Q3 g
// DoIdentify
. n, a; A/ f; p% Cbool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,8 G- O1 t; y$ r' x$ i2 ]" i- ~5 x
              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
. a8 |: ^  |! D5 f6 C" P, ~              PDWORD pdwBytesReturned); t. r  [9 }: W4 D
{
2 r6 H& F" ]3 g* p8 \: I" r% M    // Set up data structures for IDENTIFY command.
3 j* X# L* \3 F: i/ r- U    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;8 _' O; q* z1 L7 [6 V
    pSCIP->irDriveRegs.bFeaturesReg = 0;3 d. r' S3 o; }$ n
    pSCIP->irDriveRegs.bSectorCountReg  = 1;
1 x) _! U3 I; V4 T5 H    pSCIP->irDriveRegs.bSectorNumberReg = 1;
( t8 q/ m' M. N+ Y- h, W    pSCIP->irDriveRegs.bCylLowReg  = 0;) D* U& ?; Y; s, h( `9 B, m
    pSCIP->irDriveRegs.bCylHighReg = 0;
! N- S6 T8 A- c9 G+ A( c! ~6 N9 L5 z! h
    // Compute the drive number.(主盘和从盘所对应的值是不一样的)6 ^. R6 l1 _% t! g! N4 i
    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;& `! i9 L: F3 X- S! f

0 t/ p+ @, W8 e* m8 `    // The command can either be IDE identify or ATAPI identify.  j, q$ T# E% m  f% f
    pSCIP->irDriveRegs.bCommandReg = btIDCmd;0 t/ M4 `% Q5 o3 P( G
    pSCIP->bDriveNumber = btDriveNum;# {; B* r- B( t1 W! y+ p
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;4 H! Q+ i2 L4 y- |8 y! p
( \! j( o; M' P, {9 ?1 m3 f
    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA," m2 a8 v0 s# V
           (LPVOID)pSCIP,4 r2 }' V# M' `" |7 o) y8 h
           sizeof(SENDCMDINPARAMS) - 1,
: Y7 v# n! a4 Y           (LPVOID)pSCOP,* O* M: d' R6 \7 u/ _
           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,. j+ ]6 I' J: ?& c& Y; e
           pdwBytesReturned, NULL);
: Q* O5 S7 j6 [}
2 T1 [; Y. L* `8 K//---------------------------------------------------------------------------/ u! q9 D( M1 ?5 z8 N: W. r4 M
// Windows 95/98/ME 代码1 P0 v5 X( P' f& j9 u' a2 q
//---------------------------------------------------------------------------2 B! S9 o) X3 P8 A' L+ m
// ReadPhysicalDriveOnW9X
( J6 `2 p5 \) y( F1 ]) O2 dvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)
2 p$ i5 g' N, c6 c% B, z{
, K- r; ]4 q; `. r2 l4 R    WORD wOutData[256];
4 N' @4 \! Y3 A    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);& g8 K5 E6 S# I! E' J  Z+ z; p  n

! g9 q: l5 ~. y- _    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
9 J0 u. t) W% b    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以. D! [6 t8 w- l5 @* f( |  n
    // 避免蓝屏的出现。(期待高人能指出原因)
. f! g% A" b7 s% X1 P. t! H    for(int nDrive = 0; nDrive < 8; nDrive++)
; L. x. D& H5 N5 F    {" ^8 ]' W/ h$ d) ^3 m
        WORD dwBaseAddress;
% l7 z2 E* p/ l; ?( b        BYTE btMasterSlave;         // Master Or Slave5 m/ o  J. S* F% T+ T- a
        bool bIsIDEExist;1 d& L5 f9 `4 ^7 z) \% K. C
        bool IsDiskExist;6 n- y5 Y2 M9 k; U0 {
6 f1 q8 u* E2 ?) [
        switch(nDrive / 2)1 l5 m: ^3 f( M8 i
        {
; T9 d" U# J1 T/ t$ k            case 0: dwBaseAddress = 0x01F0; break;
4 d3 H$ j0 r- `# Y            case 1: dwBaseAddress = 0x0170; break;
3 b% Q9 q! ?# I8 v: y            case 2: dwBaseAddress = 0x01E8; break;
$ M4 B' ?% w! G8 [( M            case 3: dwBaseAddress = 0x0168; break;
# n8 {! X, L6 c8 u* s        }
! @$ f4 H* z  s# f, s# t7 Y% g) s# e8 K
' d3 c" ]( _/ R3 g: c        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
! S" Q! n: |: e, V! G5 x- n8 `7 V
0 l" Q2 ]. m* @' k% W8 d+ o! ~        // 进入Ring0  ?  [* O( e, w  q& Z8 [: s
        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
8 y( k$ \8 y4 A- l8 c$ n  Z                bIsIDEExist, IsDiskExist, wOutData);" o7 I5 L4 e4 M) Y. H
    }+ m: o, T: y# Q1 ^! z" Z( C
. u7 M* Z% O2 ?6 P
    // 开始读取
9 {& v1 W3 Z2 w- [3 ?    for(int nDrive = 0; nDrive < 8; nDrive++)
( _3 y* U! k& r1 b    {
) ~- e( l, `) U/ K        WORD dwBaseAddress;% ?3 G, y  Z4 ]+ X: G) h
        BYTE btMasterSlave;         // Master Or Slave
5 x; X6 M' Q! K4 ?% ~' K: }        bool bIsIDEExist;) ]( G$ y: n& W7 O' H( U
        bool bIsDiskExist;$ ]' B. M: E& Q5 q2 ]' ?
        switch(nDrive / 2)! B. C5 R9 z+ B% {/ x3 a
        {
, T  V. g' X. Z( j            case 0: dwBaseAddress = 0x01F0; break;
# Q+ J6 S) j9 U; C6 F            case 1: dwBaseAddress = 0x0170; break;
6 V( h  L" Q" f6 _+ a            case 2: dwBaseAddress = 0x01E8; break;
! n( s1 A6 U, k4 {( z# U            case 3: dwBaseAddress = 0x0168; break;! c2 h4 n5 O$ b5 j
        }, {  r6 ?" ~' G9 Q* y* ?; N
  o+ G, C) f; G
        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
+ s7 x& C; b! t4 ~# n& B( I- _" z8 a
" e- S9 k$ E% i. S! P+ i        // 进入Ring07 q) i, @3 X5 C2 T
        bIsIDEExist  = false;$ h5 y  q) V' M# M7 t7 D
        bIsDiskExist = false;
4 K- u2 o, A' u1 s        ZeroMemory(wOutData, sizeof(wOutData));" |# n% d: G( Q% s6 O

( j4 G+ S5 U8 {; l7 p, n        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,) W% y7 m0 j2 s5 F/ m/ R& B
                bIsIDEExist, bIsDiskExist, wOutData);2 L( w) n3 L* @  E  s
/ v/ s1 E$ ]" j# P) a6 D6 f" V
        if(bIsIDEExist && bIsDiskExist)2 J  d. Y' \' e. e( e) y
        {1 z, B9 p  q. D! d! V& x
            DWORD dwDiskData[256];6 M) z) W$ }5 f6 \5 B0 `
            char  szSerialNumber[21];/ L% e+ Q- G& l2 Y
            char  szModelNumber[41];! i: S1 O" F/ ~9 N0 d

- w  g) K! P) v3 {; I6 p3 O            for(int k=0; k < 256; k++)+ n+ c% w1 z1 b
                dwDiskData[k] = wOutData[k];" i3 G- m; u, u, s' X% P& ?

% Y) u+ _2 k* }            // 取系列号
+ q. [$ ^0 m. Q            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));- j! f3 o8 q7 @4 N! j5 S; {
            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
' N2 Q* ~0 c: |1 v  d; Z* o# B
2 T9 b; w- f9 v) H            // 取模型号2 v( E: ?  ]0 P& I2 k2 t4 d9 m
            ZeroMemory(szModelNumber, sizeof(szModelNumber));- X. M! J; p* j& V
            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));# ^, e* P2 @$ l9 P0 b) K7 L; F, @

# V1 e4 I/ c5 n7 v' H            pSerList->Add(szSerialNumber);/ C- B5 Y$ g. W3 ?* x
            pModeList->Add(szModelNumber);
. R; r8 D/ q1 n! I0 Y# Y        }
6 x' q7 x1 B7 [    }
0 p8 P/ F: h, u% G    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);$ d0 @+ x: g0 O
}- _& F" k# Y  H& C3 U
//---------------------------------------------------------------------------
- t6 i$ g' v8 U7 H7 Y9 {// 为防止不负责任的转载者,在此注明原出处信息,请见谅。: M" L& y, B+ K8 C( T( O
// 资料收集整理:ccrun(老妖),欢迎光临C++Builder研究: http://www.ccrun.com1 S; q1 e) I% E- ]$ Y
//---------------------------------------------------------------------------8 g2 w" H! r4 Q( I  E( ], `7 {
// ReadPhysicalDriveOnW9X_Ring0()9 x* C; F# ^6 J" h; ^
//
9 R/ @, M- F7 X  X9 m  B// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h5 r1 x3 u2 d5 _9 S, i
// btMasterSlave = Master(0xA0) Or Slave(0xB0)
! ^) ~% L: s) n* _& T% v# h//---------------------------------------------------------------------------$ h- s/ v& M$ L  `& K
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
9 [9 k3 E5 d( y! o        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)1 W; K( ]4 N) l1 ]! D8 z
{: o) b! f2 M' @$ W6 [( ~8 Z
    BYTE  btIDTR1[6];
5 J6 J2 E7 A/ {( |) ^& q    DWORD dwOldExceptionHook;$ Y/ x" {) g/ c# W4 ^' N& o
    const int nHookExceptionNo = 5;8 Y5 Q1 A, Y: ^- j  N2 a

: o) k9 w( B/ f( ^& Z6 W    BYTE  btIsIDEExist = 0;. X1 Z* p, Y4 o5 i7 L1 V9 \
    BYTE  btIsDiskExist = 0;: m- M4 C, ~9 F5 {- M
    WORD  wOutDataBuf[256];( Y$ `; r* Z. ~& v! k: Z
, P$ r6 c) b2 U. P% X
    BYTE  btIsFirst = (BYTE)bIsFirst;4 U! Q+ q0 }% j. C( ]' ]. r* b" W

6 K  x9 M* j# Q  K& D    const BYTE btBit00 = 0x01;
" u) [# ^" U9 Y7 Y    // const BYTE btBit02 = 0x04;- r, O: G$ H+ G+ L! B3 I& y3 w5 G( ^
    const BYTE btBit06 = 0x40;
5 ^2 M2 ^& q; N, M3 ~& r    const BYTE btBit07 = 0x80;/ I& p% l! d( m/ Z# o3 q
    // const BYTE btERR  = btBit00;
1 p) L0 l% s0 z$ k    const BYTE btBusy = btBit07;
& F2 c  k  [8 h    const BYTE btAtaCmd   = 0xEC;8 L  `3 s. h) M
    const BYTE btAtapiCmd = 0xA1;& ?5 i- [, v3 C

. }. {3 c7 C% S$ C0 M    __asm
7 i2 ]% e, {9 l3 Q. w6 h! e+ t- Q& y. [    {
! K! q' j. y" R( q* y        // 必须先执行这条语句
3 E* j( y3 l& o* v+ Y        JMP EnterRing0
2 l' l. }) K* C; W  G
6 }1 l0 b6 ^- V; X- @) G        // 定义过程9 j- l; K- c$ i" x) D  U/ |- D
        // 等待IDE设备直到其不为忙为止
# ?4 q" }# E4 `  n4 D2 k0 q! k' V        WaitWhileBusy proc9 R5 o' t; [. W6 Z: z- p( r4 A
, K. g8 W1 b3 Z: a1 m- N6 ]. X0 x
        MOV  EBX, 100000, W, e( Y( s. M5 u
        MOV  DX, dwBaseAddress; B% K) ]5 [4 f3 p6 |
        ADD  DX, 7. q+ d/ n- E* b! t
! k& S1 O% }% U
        LoopWhileBusy:- g6 Y) v0 }" Y& Y. k: X
1 S1 C+ W/ V9 }3 ]
        DEC  EBX
7 Q8 T/ D3 A6 r        CMP  EBX, 0! F) f9 H: d: y$ e. U
        JZ   Timeout/ `* F0 K* n/ ?3 D- s: z
        in   AL, DX
3 I- P' F4 V' q7 n+ u& v        TEST AL, btBusy
9 O% Q0 G6 K2 R1 b        JNZ  LoopWhileBusy, E4 i% a: Y7 j- K* J
        JMP  DriveReady
& z' e8 [# Y( ~/ z* y
1 r+ ~3 W; }* Z        // 超时,直接退出
8 V- b; S3 c0 m" r' K. h/ q        Timeout:) y' X9 W( X8 c  e$ u
        JMP  LeaveRing05 @* p& }/ o9 F
        DriveReady:2 a" N3 S% I! h8 |- `
        RET
: f/ g  S& X4 q3 ]# \" J        ENDP   // End of WaitWhileBusy Procedure
( `- y! ?: m) H( V! e  ^6 T) \/ s6 v' p/ ?0 U) i4 G9 D$ X" l9 i
        // 设置主盘和从盘标志
6 m1 I' d$ r% @0 z; D        SelectDevice proc* b- ]' X1 v; ^# J6 m8 o
5 d1 l+ Y! ]8 H2 O, ?" _
        MOV  DX, dwBaseAddress
; y4 U4 ]6 S! m; T. ]1 t0 N        ADD  DX, 6
+ s6 P- V- x* n4 I" t1 G$ o! d. d        MOV  AL, btMasterSlave
; e; z% `+ C: z$ }0 K" D% V5 M7 |7 E0 ^
        out  DX, AL
6 [- h& m: w, [2 u) _3 ]$ ?& @" O        RET
! m% J4 A* d: E
" k9 W7 b* Y* j! _# j4 b, M        ENDP  // End of SelectDevice Procedure
  K- E0 \. a) Z! f! i5 T
, Z% ?% S: q' q        // 向IDE设备发送存取指令
3 l' \. s: s: N9 l8 |        SendCmd proc' ?' w  S+ W  L4 b
5 K3 R3 N' k' K6 u9 Z. g; ?
        MOV DX, dwBaseAddress
2 x! E% C6 v0 Y3 t' K8 w8 E7 q9 f        ADD DX, 7# p! w. [6 i$ \
        MOV AL, BL // BL是主从盘标识,在过程外设置; s* ^8 J9 j9 f: d- X* R
        out DX, AL8 r2 V9 ]% g  \4 }
        RET
! f* |4 r( u4 t- B/ K        ENDP  // End of SendCmd Procedure
4 [' }. @9 O/ k. q! \  c7 s) s, q5 u) G0 m
        // Ring0代码# ^7 L. J* P' H* l# u; Q
        Ring0Proc:& Z( f! q4 r% t7 U3 X) \5 Q" S
        PUSHAD1 u  {* C# S5 ~" J& R* T) v( A! I
        // 查询IDE设备是否存在! e: Y! g  r1 X' W- P  n8 a: O* s
        MOV DX, dwBaseAddress1 l2 V8 z, J. L) D' \( V
        ADD DX, 7
" N" u. O) j' @- b% I3 U: q7 [  q! K. B2 l        in  AL,DX
( b# L" p4 Q8 z' E9 N/ S$ Q$ G, E7 v5 r" X
        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
# R" J" r3 @4 X3 e$ T2 r8 [$ j. w        CMP AL,0xFF) v( b! r& y; C6 |* P
        JZ  LeaveRing0
7 c5 ]) u! W: S$ ]+ B1 i9 f0 q0 u        CMP AL, 0x7F' f1 v1 i4 T! `: ^2 \/ y
        JZ  LeaveRing0
; w  L, {- ]% `6 E, _! g. ~5 l+ v  w$ `) |" ^
        // 设置IDE设备存在标志
5 Z- z' c7 S3 l! t        MOV btIsIDEExist, 1
6 I5 Q7 T! k% Z% Z6 c& D! K
* `# I. p; D$ V$ d( R& D( H# n        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)2 ?! ?: E0 \# W- k6 I( i* m
        CALL WaitWhileBusy+ m8 ^" d2 P6 {3 u9 {* p
        CALL SelectDevice  j. ]$ i. ?2 x$ W" y4 M

! ~3 Y2 }' i" M6 x) b        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
" S5 Y5 M3 O% ?1 X7 Y        CMP  btIsFirst, 1
% D! n5 ]% ~8 I2 U5 J  G8 i  c% N9 S3 ?        JZ   LeaveRing0' z: X0 Z  s* T6 |  d- r6 Y% S
+ Z& y& @$ E1 U8 }5 b1 ~; R
        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???: E" P5 U* B1 Y" ]' s' B' C9 @
        CALL WaitWhileBusy# B+ ?8 U5 A" t% h7 u) m/ K; D

) P8 \7 g9 w: x/ p% z        // AL的值等于cBit06时,不存在驱动器,直接返回
% |7 W. f+ l4 o- z; X, G        TEST AL, btBit06
* q- Q0 A3 e7 d9 t/ G        JZ   LeaveRing0- M% M* [1 r& s* i
, A( o0 `# [7 ?0 X' P- i) r9 k+ X  W
        // 设置驱动器存在标志
0 g$ ~, n/ x4 F7 l1 \/ ^        MOV  btIsDiskExist, 1
/ e& ~5 V9 W( w) |* G
' h; _* n% A: N        // 发送存取端口命令
& I& ^2 G* T# d3 Z        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
  t7 E. ^+ ?( ~+ w% ]        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
( C" `& P# m: ^( I$ x/ `6 t        CALL WaitWhileBusy( a1 |& V3 X% @1 h0 m1 U! G
        CALL SelectDevice    // 设置主从盘标识
! n% g# k* S6 b( m; F0 |7 w        MOV  BL, btAtaCmd      // 发送读取命令2 }8 V& h& z6 ?: X0 F
        CALL SendCmd. A3 M5 _# r# C/ `$ T
        CALL WaitWhileBusy
  E6 `; [3 ^. @2 [) E' R! u' l& C2 _
        // 检查是否出错( ?+ g& X1 d3 i0 y3 `; u2 @8 g
        MOV  DX, dwBaseAddress
2 g- U, `' a+ i( @9 o" I        ADD  DX, 70 T* k  l4 V! U' v* ~" e
. \2 E! c1 a$ u/ S3 z+ r
        in   AL, DX
& g8 w% L6 ^+ d' d( x. y' U( I( l2 k5 {1 d  V4 ], M
        TEST AL, btBit002 L2 Q0 F9 @: s/ t4 e6 ?
        JZ   RetrieveInfo   // 没有错误时则读数据
. ~/ Q* u. A5 P
0 ^+ O6 @( D% p& J# \1 }- s6 u        // 如果出错,则进一步尝试使用ATAPI设备命令" j! `8 k0 `' G
        CALL WaitWhileBusy
5 {: P/ |# a* d* U# {% y# K  i        CALL SelectDevice8 H" e4 \6 C4 a- h4 \7 [$ L; ?
        MOV  BL, btAtapiCmd) E3 p+ J  X; @0 @
        CALL SendCmd
) }" }- V6 l3 n* F& M+ ], \        CALL WaitWhileBusy; N; ?5 @1 J& Z: W9 t' @

  p8 o) u% M. t! f% W  u/ p        // 检查是否还出错& W) E, W* d8 ]( u) v* G$ n/ W2 N
        MOV  DX, dwBaseAddress
2 @$ Z; v! |8 b+ w, p2 H        ADD  DX, 7) m1 ?: |1 C2 `  k% c
        in   AL, DX; i& ]+ \4 B$ B$ @; k4 o
        TEST AL, btBit00% S' i$ ^; y# L+ `" g8 q
        JZ   RetrieveInfo   // 没有错误时则读数据( \. r! S* f/ p3 ]
        JMP  LeaveRing0     // 如果还是出错,直接返回. ^& C1 r& Y' ^8 j4 k

: ?+ [3 W. |2 G7 ~1 s: Y) e        // 读取数据
! I( l5 \' N1 C4 d' w, U        RetrieveInfo:
; ]$ l7 H# {( j0 ~1 t4 C
3 c5 k7 {" `5 p( W, K# q        LEA  EDI, wOutDataBuf
! A% f$ F4 P, u- ]- J9 T6 q  l$ {        MOV  ECX, 2568 L+ s6 W! X* l0 r& ?" S
        MOV  DX, dwBaseAddress! l+ o1 C  l' ?
        CLD9 x' G2 q* u: i' z; {' v8 e5 q

4 j7 r  {8 O- w5 O" a        REP  INSW
4 p0 A0 _" S' R1 `1 E& ^* T; `7 i9 D3 N6 O
        // 退出Ring0代码6 [! Y% ^1 B1 Y
        LeaveRing0:7 L: m! Z, \; R, _& x
* Y' n* @; F! c( O/ C
        POPAD" Q0 _+ \9 U- c8 t" C1 `
        IRETD  d3 x' I$ ]6 ~, D% D4 F
- g4 Y8 H- L8 u" @
        // 激活Ring0代码
; S4 L+ v/ a  U$ \) u- M! x        EnterRing0:
: `( S  N& H  [& E- q' z' w$ c8 d2 D. D" ?
        // 修改中断门. l5 Y0 i3 P2 u
        SIDT FWORD PTR btIDTR1
  D5 ^, g9 p" N        MOV EAX, DWORD PTR btIDTR1 + 02h
! U/ u& {( m: s  ?$ b        ADD EAX, nHookExceptionNo * 08h + 04h/ l4 p& s0 L1 g! k' A
        CLI# A' P8 x0 m9 Z9 V- d9 U/ U6 y
) _( y) Q9 N/ E
        // 保存原异常处理例程入口' b$ j: c4 S. d& t& ~- ?, S% ]
        MOV ECX, DWORD PTR [EAX]
+ j7 x& R0 O' [4 f! `        MOV CX, WORD PTR [EAX-04h]9 H% B' r& \# |7 G# }+ T
        MOV dwOldExceptionHook, ECX
* g& x3 u! r+ [1 W& v4 L, T4 c; Z: l6 B  v' V
        // 指定新入口
' b3 y3 T8 l+ K" Y* }        LEA EBX, Ring0Proc
/ b( C9 h$ t8 ~4 k/ ]        MOV WORD PTR [EAX-04h],BX% ?3 P# M+ O, g! E6 n
        SHR EBX, 10h: a- g  b* e  u  A4 i2 w, a& G$ {
        MOV WORD PTR[EAX+02h], BX9 h9 k& n, ~  W% Y# @
- }, n7 |. v0 [7 ]' U6 I; W. A, j
        // 激活Ring0代码5 Y# G3 C: c: F" ?9 g7 t
        INT nHookExceptionNo
2 U  [* w- D- I% H6 t: T, ^3 R3 X0 _. ~. k
        // 复原入口: y# }8 k; S$ Y7 n9 X- B
        MOV ECX,dwOldExceptionHook" l- s# ^$ }1 G6 \; p, ^8 {1 x
        MOV WORD PTR[EAX-04h], CX& N9 |( ]* I* |( O
        SHR ECX,10h& f. q5 f- k" n1 R
        MOV WORD PTR[EAX+02h], CX) A) g8 ]& J- G2 y+ T: Q( r1 Q5 [
        STI
- a/ h' ^4 @7 j' v$ V  v3 c; J* O    }
% o. S/ J, z) Z3 X* d7 ?' X    if(!bIsFirst)
7 `7 N1 R# A1 N4 A# }1 b" s& Y    {  y# J7 \+ [- M. [" o
        bIsIDEExist  = (bool)btIsIDEExist;4 _+ O$ A( v/ k2 a. f9 l4 {/ b
        bIsDiskExist = (bool)btIsDiskExist;
. z1 O$ K% _+ w5 P# l# m        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));5 K, ^6 x- ]7 B& ]) t# O
    }
( ?! e1 x& w, W  W- p% p, z2 o}
# R+ g9 R; }$ H! V) ^//---------------------------------------------------------------------------1 |7 X2 T  ^9 d" b, x$ b
// 调用方法:; _2 C0 Q% K$ u$ R' L
void __fastcall TForm1::Button1Click(TObject *Sender)
) t+ |/ G( N5 @2 x' @- T- Q{
( l. w, e# X% R3 B3 a    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);2 \) i6 }7 I, e2 I
}# o  u7 n) @- D7 O. n( J" J& u
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-12-20 08:49 , Processed in 0.031833 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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