找回密码
 注册
查看: 8018|回复: 1

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

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

  1. 3 {. `2 q8 z3 z, z  {6 C! F
  2. #include "StdAfx.h"8 d0 S* _, H" x
  3. #include ".\puiddisk.h"
    6 K! N8 c- n  N3 H: s& [
  4. #define _WIN32_DCOM
    , E% U6 I$ t  s* G  D) [* K; T
  5. #include <iostream>
    : C1 U7 l0 \, }8 d* C9 g
  6. using namespace std;
    3 \! B( L: D% W4 Q+ j
  7. #include <comdef.h>
    % E% d6 D8 B* l% S; n% [: x, N
  8. #include <Wbemidl.h>
    1 ?8 K) d5 g7 e/ R& X1 C' f1 m

  9. % e; n2 z7 R# j: ~
  10. # pragma comment(lib, "wbemuuid.lib")6 t% G+ X* M/ E( _# q6 ~; f3 j
  11. CpuIDDisk::CpuIDDisk(void)
    6 K2 _- u8 m9 ^1 H* [7 C
  12. {
    0 Y" ^% S0 `/ M6 I6 V" V% F
  13.     GetInfomation();- }) S7 w: o( l8 Z- P
  14. }
    4 U, Z2 e. C8 g7 b

  15. ! T" k9 c8 s( Z4 H* m' @2 W" o5 t
  16. CpuIDDisk::~CpuIDDisk(void)% J2 ^8 h4 G  a! }; F
  17. {
      D* l+ B( |: G, h$ Q
  18. }6 m0 D/ X& B6 V/ U
  19. int CpuIDDisk::GetInfomation(void): k) a* `" d5 D+ ?: V
  20. {
    * ?5 Z2 l1 h# Y# r- m6 b0 \
  21.     HRESULT hres;
    ; Z8 t1 n. F* d. f$ Y  b& |1 I
  22.     //步骤1:不是必须的,COM只须也只能初始化一次
      f0 V0 r1 c2 R8 e: [
  23.      hres =  CoInitializeEx(0, COINIT_MULTITHREADED );
    ( `3 e. U4 ]8 p# r" D# u
  24.     if (FAILED(hres))2 y5 l/ U% I3 G9 l9 k' K
  25.     {
    4 [4 i( k) e- n
  26.         return 1; //初始化COM异常:注意,COM只须也只能初始化一次
    ; e6 a9 n: g1 W* z  B* C9 W
  27.     }
    % l. u; D5 z0 E6 ]
  28.     //步骤2:不是必须的,COM只须也只能设置一次* g. s' l; f# ~% v, i5 p, R
  29.     //Set general COM security levels+ g7 V+ @& j, G9 o3 z; R% e
  30.     hres =  CoInitializeSecurity(
    9 G, P2 r- D  h9 ^
  31.         NULL, ! R: y0 f' r  B( b# e9 B. c
  32.         -1,                          // COM authentication
    , M( |! l) t" V/ i9 j; n  |( x
  33.         NULL,                        // Authentication services
    - {4 ?2 V1 o1 M. U, F
  34.         NULL,                        // Reserved- m- \4 S* b6 J. G
  35.         RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication   j5 c; r5 S, j5 C6 _9 p7 B
  36.         RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  ; C1 x0 W1 V1 e* C) w( Y
  37.         NULL,                        // Authentication info
    ) {% j, K5 C  c( T9 Y" e2 y0 w
  38.         EOAC_NONE,                   // Additional capabilities 9 _5 g# J8 e- p# ~4 ^
  39.         NULL                         // Reserved. Y/ U$ \' W/ ?* ^0 A0 f
  40.         );4 M( Y1 I" Q9 m$ H! Q( m+ l% Z
  41.                         E2 r; d$ _5 ~0 S/ r- C
  42.     if (FAILED(hres))0 H3 e* X; [7 r  A
  43.     {
    5 ?1 _5 m! o" Q3 T& R
  44.         CoUninitialize();! `3 }" j+ ~: p& v! R( ?9 V
  45.         return 1;                    // Program has failed.
    - z0 }$ W3 a' g3 i; y
  46.     }3 K4 r2 N& P) B  ~/ u  V
  47.     ! U: N/ `7 {- e$ q- d3 {' k
  48.     //以上不是必须的,若已有“::COMInit();”,则要跳过3 q/ y- ?8 v1 ]5 \; C# G/ k
  49.     //步骤3: Obtain the initial locator to WMI " l- K3 w: E: d# x3 {; ?& |$ S2 f5 N
  50.     IWbemLocator *pLoc = NULL;% o1 B& J$ @7 |( G) s- _
  51.     hres = CoCreateInstance(
    ( E( h: |8 H2 a( d8 j# f/ a; J
  52.         CLSID_WbemLocator,            
    0 N* E1 u2 v$ S0 ?
  53.         0, . J8 d$ p, p0 M
  54.         CLSCTX_INPROC_SERVER, * U4 H; J# O' k4 G
  55.         IID_IWbemLocator, (LPVOID *) &pLoc);
      w9 X+ I! D0 \
  56. : C9 Q: P7 I- G2 D, a! q* {
  57.     if (FAILED(hres))
    2 p: g* v2 }, q3 X7 N( ~
  58.     {" Q2 E  B& S( j) S% b
  59.         CoUninitialize();! F8 X+ F( Q0 o. E
  60.         return 1;//Failed to create IWbemLocator object  V  H( o6 `! n. c3 [. H3 r
  61.     }$ t, J- w4 A/ n2 D# X5 r0 L
  62. 9 k" b$ S% ^* s4 T% f1 D% R! k8 u+ ]
  63.     //步骤4:Connect to WMI through the IWbemLocator::ConnectServer method
    % `  v0 L4 l0 j9 }/ k
  64.     IWbemServices *pSvc = NULL;! ^, n; @$ L7 H; B7 g
  65.     hres = pLoc->ConnectServer(
    " x+ h; Q" X  D# b: I' |5 k
  66.          _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace
    8 }1 K+ ?/ @, n6 |7 [: w- q9 q% }
  67.          NULL,                    // User name. NULL = current user" U' I7 ]. Q0 n" N
  68.          NULL,                    // User password. NULL = current
    $ ^% E. s, D& M3 N( S3 V
  69.          0,                       // Locale. NULL indicates current! F( a6 n& s8 z" r0 I" l9 p
  70.          NULL,                    // Security flags.
    ' B) {& A7 i/ j7 }" x/ w8 B
  71.          0,                       // Authority (e.g. Kerberos); s- a) y# Z) J# B
  72.          0,                       // Context object   P+ R) \* L: ?( ]( `
  73.          &pSvc                    // pointer to IWbemServices proxy
    % m, G3 `0 S$ P  Z
  74.          );
    . o# Q) q; y9 q5 e! l9 G
  75.     4 d+ X, m, |8 T% K# K( W
  76.     if (FAILED(hres))3 ?" u+ R5 j, h7 q
  77.     {3 @. S9 S. Y& l5 i; a
  78.         pLoc->Release();     
    6 L$ s+ ?; s1 M- y
  79.         CoUninitialize();: i, w: C4 O, \2 t
  80.         return 1;                // Program has failed.& w: y  S. f8 r7 y
  81.     }
    4 a! T) n5 L/ Z6 r# P9 |7 \
  82.     // 步骤5: Set security levels on the proxy
    ( L* ^, V  d  C9 G
  83.     hres = CoSetProxyBlanket(
    : j. s3 p1 L2 S( u. q: d  `- m
  84.        pSvc,                        // Indicates the proxy to set
    ! l1 Y; W$ \- @$ L
  85.        RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx% I- v7 b+ Y8 \
  86.        RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx' ^% K- N+ m4 P* H" m' x
  87.        NULL,                        // Server principal name
    % C& g4 A! A) g* _- q& R( L' L, {
  88.        RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx
    $ f; H; j1 J1 H" |) ~0 B
  89.        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx; M# U8 Q7 X! o
  90.        NULL,                        // client identity
    & T7 c& Y! e# }! c, [# r
  91.        EOAC_NONE                    // proxy capabilities
    2 B& e+ y' L$ V$ d) c. Q
  92.     );
    ! e  A, `# D! |, Q( a
  93. 6 S/ `* A, V/ c5 C3 p7 ~4 `
  94.     if (FAILED(hres))
    ) F5 Z# h, W' k! u* c( S5 n( r
  95.     {+ |3 F# \: y/ r  Y  W  R
  96.         pSvc->Release();# d2 x* u" e7 a- t/ v; q7 W
  97.         pLoc->Release();     . e' S. f$ t/ e* k5 G) `7 a; L
  98.         CoUninitialize();
    : O* z2 S" F6 R" ?
  99.         return 1; * f5 |0 G& X' _: X
  100.     }' Q2 U1 {  w+ R7 _3 q
  101. * Y9 h/ C1 P. b. c6 M/ _! {
  102.     // 步骤6:Use the IWbemServices pointer to make requests of WMI ----2 a1 `9 b0 E& {) j, S$ P
  103.     IEnumWbemClassObject* pEnumerator = NULL;
    ! w+ \; B# e4 L" V: v6 j4 s  p7 k
  104.     //计算CPUID( w8 r. Z3 C; D  Y
  105.     hres = pSvc->ExecQuery(
      z4 s; V' X1 U5 f+ w
  106.         bstr_t("WQL"), & A2 R% o# |: O- A* Z, ^& A
  107.         bstr_t("SELECT * FROM Win32_Processor"),//Win32_OperatingSystem
    - |9 E, E  o; J& w4 ?, P
  108.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
    : O0 Q( t: u# f# c' u
  109.         NULL,( L' t8 A: A5 v3 p
  110.         &pEnumerator);+ E* F( H" ?# {+ b, B9 R) h) `6 `; y
  111.    
    ' `' m: j+ |' \3 e; X9 z
  112.     if (FAILED(hres))# p7 A) l$ O/ V2 [
  113.     {
    " V9 z8 j3 e: g1 C* ~" `
  114.         pSvc->Release();5 s6 n9 F4 ^1 J% N
  115.         pLoc->Release();
    5 g7 m) `5 F4 m0 N4 S
  116.         CoUninitialize();
    + Q$ N0 a2 Y1 B/ c$ v  Z( v$ J
  117.         return 1;5 f% {% q9 N' p/ @! |7 S  F# J
  118.     }
    & M* O, k6 u7 x0 [/ B
  119.     // 步骤7:Get the data from the query
    , \; q6 F- K0 h0 f, Z
  120.     IWbemClassObject *pclsObj;& ]& `8 n" y8 L/ z
  121.     ULONG uReturn = 0;/ R4 ^/ P! R9 L- h3 n+ P/ |- `1 v
  122.     while (pEnumerator)" O2 i! S7 A+ i# u" v
  123.     {& ~* J3 l$ `0 V6 O0 s9 e3 c
  124.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, ! h  v5 V  O" X1 V5 ?* e
  125.             &pclsObj, &uReturn);
      a% a' c3 J+ T7 J- F

  126. : J0 I! b# e, V# o- h
  127.         if(0 == uReturn)
    / M" i( E6 ~$ |, s% A% J3 y# z
  128.         {
    4 u/ d4 c- G* `. k: p
  129.             break;4 P, A, n! \& I# j1 p
  130.         }
    , z+ x4 \) C1 p2 H, s
  131.         VARIANT vtProp;
    % ]3 J3 v$ A( P2 E4 I# s
  132.         VariantInit(&vtProp);
    ' E+ l: ]6 o0 }' H4 _
  133.         hr = pclsObj->Get(L"ProcessorId", 0, &vtProp, 0, 0);
    ! O1 \% u9 M5 U# z) i. y( U3 ^
  134.         strProcessID=_com_util::ConvertBSTRToString(vtProp.bstrVal);//strProcessID:类级变量
    7 m' U6 Z" y  m% k9 h3 T0 T
  135.     }
    + g# J9 v4 v  r; M' _, e

  136.   F0 x  _0 }; i. d6 l
  137.     //计算硬盘系列号# y. Z0 M2 u- O* ^1 L' {# h
  138.     hres = pSvc->ExecQuery(" Z1 [: V4 X, v( d6 E4 i% `
  139.         bstr_t("WQL"),
    / N3 P. @" N# y9 R' h
  140.         bstr_t("SELECT * FROM Win32_DiskDrive"),5 `+ r2 M" E+ \
  141.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
    6 }. t; y8 R% f/ a) y
  142.         NULL,+ c' W9 \5 M% m# R; K4 R/ c2 J0 F
  143.         &pEnumerator);" M: |% a- g5 |3 u  ^8 K
  144. $ N7 j9 v+ I3 [9 ]) m  ^
  145.     if (FAILED(hres))
    4 @& u! l: ~  \6 T+ r% P, ~6 B
  146.     {8 P" H: i( V0 ^) j8 h
  147.         pSvc->Release();
    / N/ N8 U# Q" C$ w1 r7 X
  148.         pLoc->Release();
    7 [9 X6 L: f3 I$ M1 F9 y  [
  149.         CoUninitialize();( |2 [& g) U, d& \; F; g5 P- \
  150.         return 1;
    : B3 t( [) D: Z3 @) |/ p" h9 i
  151.     }
    4 {- A# L8 q* s/ _
  152.     while (pEnumerator); _+ h$ J, Z) }7 }0 L9 {& X7 X/ s
  153.     {
    ( V( f) C3 h! e6 U" `- I6 G
  154.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
    7 _& a3 q' L$ E( c% ^8 ~
  155.             &pclsObj, &uReturn);9 U( T; C, U2 T' x' v
  156. + L3 V- L! y9 `) \1 h. [- m5 w7 W
  157.         if(0 == uReturn); u3 n" v" k; u7 {% k
  158.         {
    " w# U: f: g+ j8 z- ?9 V- N
  159.             break;
    9 ~+ ~! x1 q: o- h: D( o1 D. m& E
  160.         }
    , a& m; b% h9 N" X  R& W

  161. % t: |, P/ X% A1 Z: k/ n
  162.         VARIANT vtProp;# D9 {+ q8 t4 Q
  163.         VariantInit(&vtProp);
    - ^8 P% I4 V3 i' k9 |
  164.         hr = pclsObj->Get(L"PNPDeviceID", 0, &vtProp, 0, 0);
    , E/ Z  k7 U% p- b
  165.     strDisk=_com_util::ConvertBSTRToString(vtProp.bstrVal);' d3 Y% u4 K% x! _4 b8 Y
  166.     }& x) o7 Z& T9 K4 {% }' r
  167. . H" @5 r' U" u" X+ P2 f! ?" F% I9 ?
  168.     pSvc->Release();, @5 m* Y+ Z' O* ^( d0 |0 U
  169.     pLoc->Release();
    1 ?! N9 [! f- F4 P/ o( a. ?  D
  170.     pEnumerator->Release();; O( P6 l' u& d2 [/ [
  171.     pclsObj->Release();
    ) B- f' M* N7 @5 E0 z1 m! e
  172.     CoUninitialize();$ \; V% [0 [" d0 x+ i+ Y: X5 {
  173. * V* h& ]% U* y% X
  174.     return 0;   3 K5 l0 x+ M4 N/ \+ v
  175. }
    # M! h3 j: `$ e1 r. y0 Y4 i& r* {
复制代码
 楼主| 发表于 2010-10-11 19:21:05 | 显示全部楼层
本文代码经ccrun(老妖)在Win2k下试验成功.
% D* F4 R$ J' z+ \% G3 I- g/ a+ @  r3 C4 V0 c& U1 S) i
#include <WinIOCtl.h># Y9 f6 y* g1 Z, {: K8 c$ T
#include <stdio.h>3 D7 @$ G) T; Q" t. s5 C8 N3 ]6 Z

3 U1 m& @1 M2 B+ k# a4 V  C( C# B#pragma inline
. B( ?$ |- e6 ?5 M) i//---------------------------------------------------------------------------% p. ~! S; z. ^) o
// IDE NT/2000/XP专用变量# q% X( W7 F5 J# t; k% Y
#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS/ X% k! M( v( u4 E; r% f2 E
#define DFP_GET_VERSION         SMART_GET_VERSION- W* ^5 v( V2 J/ I9 N* t
#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
/ q# T* i8 U# ]" ]1 V/ N' \#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
% y& r- L9 ~9 m4 b
# c) n" c4 @( E/ R+ z% L8 Oconst WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令
4 a( q' C, ]- Uconst WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
3 H( ?( T  e3 E' z/ u# i! C6 P, j' x/ p9 e, I2 l, |
const int MAX_IDE_DRIVES = 4;4 k& u! r, G) ~4 B) x, h9 y$ b& m

  P! c" k# p+ _8 Q" N7 J, e" r// SCSI专用变量
, B9 |" |, j/ V" f1 |: R8 Fconst DWORD FILE_DEVICE_SCSI             = 0x0000001B;
( g, D) N7 r5 b' l9 H% O' [const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);3 d  ?1 w6 w* L% J" k! B
const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
& d7 v2 W# ?; m# b' n6 Lconst DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
/ N/ ?; ?3 Y- m2 C  O  y0 j2 \; q' B' T
2 Z. U& j, j1 o$ t* @typedef struct _SRB_IO_CONTROL
, S" A% |4 T/ Y4 ^{5 K5 ~, \  ]; {. J
    ULONG HeaderLength;
# |5 p# h* g! `    UCHAR Signature[8];* o# h  `- T. c
    ULONG Timeout;' p% P' Q7 T2 q# O
    ULONG ControlCode;/ r3 G2 H  d9 `4 C( @1 d# G
    ULONG ReturnCode;
! W7 \; r2 a% i9 y$ _3 q    ULONG Length;8 J+ k5 }8 J; _" s& U& f: {, ^/ Z
}SRB_IO_CONTROL, *PSRB_IO_CONTROL;/ Q0 O8 ^+ o2 s( F- m$ G5 }! `* D
' e& T) f2 R) U" e
// 读取的主函数1 J# h7 z; W+ O" g
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);+ q# ]" ?1 o" k6 s7 p/ J

9 t* `4 B+ M' x// 辅助函数
1 d9 w- A* |! i1 Tchar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
" ^9 O, L4 t7 {0 O7 u// NT/2000/XP函数& P5 l* Q9 S, @' f8 f" l: f
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
+ E& r, F& D! z/ n8 V( Q% rbool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,( r- D7 ?: G, j5 v3 |
        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,' G  m7 f3 }) J2 p7 M. d/ }
        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);7 r/ \) q" |5 p8 H3 y) M
// Windows 9X函数1 X9 v' c/ b- Z2 N/ L
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);
: |& p/ M* e: g, c8 R: [7 i# Lvoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,( v3 l- Z2 |) S/ u0 C
        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
$ M" X2 V( G5 S% A, k; E" S* h
" S. b3 {4 n0 ^9 G0 t// SCSI读取函数(for NT/2000/XP)
$ E" ]- O; ^" V" bString __fastcall ReadIDEDriveAsScsiDriveOnNT();8 \  M) C. \& W0 A' H9 g
//---------------------------------------------------------------------------
- D. b# p) H. e; T" H$ f' O// ReadPhysicalDrive' X' q' q3 o7 J! B; M6 d
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
7 E5 D6 }9 \: |6 q! y2 q: Z{0 |. ?+ W; k% v* p* |7 r0 `
    switch(Win32Platform)
7 \4 j% p6 I* |1 L9 Y: Q# \( T3 K. @0 o    {6 W; o$ {1 B4 e$ u
        case VER_PLATFORM_WIN32_WINDOWS:
+ f% |/ n  h, L8 J/ Q            ReadPhysicalDriveOnW9X(pSerList, pModeList);# g0 s- |7 |% \; A9 u7 ^
            break;
8 S. B6 h' Q3 A1 j. n" P        case VER_PLATFORM_WIN32_NT:5 ?8 s0 M8 X* z. k) H! R
            ReadPhysicalDriveOnNT(pSerList, pModeList);
  M6 i7 I! W, @- y( e+ d/ M5 E! o            break;
' b$ S; |1 N* w  M1 R2 \: ~& F        default:. P0 X# D/ ~* A
            break;& _5 `  F* Z; \( J- t" W4 j1 [
    }
) ^# C& R8 H6 U" d( |}1 A1 {4 L! u  q: p' e  }
//---------------------------------------------------------------------------" m0 H. a' I' D- n  b/ H
// ConvertToString
- j/ |0 J$ [% K) z+ Jchar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)1 i- v. h8 _0 E7 M
{
4 s1 n1 b- X" y' v: @! P" d    static char szResBuf[1024];
4 n7 Z  l* p. ?    int nIndex = 0;6 }- X/ y8 w- C' b
    int nPosition = 0;
# P9 w/ G, O7 V0 a! ]- o( P" h) p5 E) p
    // Each integer has two characters stored in it backwards
( a8 @2 `$ [5 X! [) \* V& W- E    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
' y0 {0 d: e0 s* H+ i9 I    {' w+ j7 f6 j: E
        // Get high BYTE for 1st character
% V/ `1 c8 j' l, ~  A        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);' {# |2 _. N' H1 t6 q) x9 k' B: y/ J# m
        nPosition++;
+ q" I4 q4 t; z* ^' U  S+ d% ?; O% Q5 V) Y% x) s, E/ y( J
        // Get low BYTE for 2nd character9 H. l  _( `2 ^& G/ M
        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);; E5 P. B/ \- ]2 {; ~8 Y7 d
        nPosition++;% S# {: H3 ?0 s. t
    }
$ B7 Z7 X8 M) N' |- v6 H3 O3 P* w: B% |* k/ h& r
    // End the string. ?5 l" \8 |) K/ l$ @1 b
    szResBuf[nPosition] = '\0';
( A7 n1 U. P  Z
. w0 ?) h# O+ ~# G    // Cut off the trailing blanks
! `8 {. k- f7 O* [: y    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)' H5 z: j4 F0 g+ r* f( v
        szResBuf[nIndex] = '\0';
' s, h) u& S& j6 y7 p' B# i+ k) J2 g' `" Y" i& V) F- H* y
    return szResBuf;8 v' O6 B( I  o& H4 p1 ]1 ~' O
}
/ k* h: g+ F6 f  W  q//---------------------------------------------------------------------------
" W: j3 }( @  D// Winndows NT4/2000/XP 代码
/ B; v1 J: r& t3 X. d% ]& @2 c//---------------------------------------------------------------------------! _7 T4 l0 T/ R7 U
// ReadPhysicalDriveOnNT
! o! |1 t1 Q0 i4 G. x% wvoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)2 X+ u3 H  E2 I: C
{3 K2 T8 K" R$ P, d+ k
    // 输出参数
6 I; K( ]# X0 v    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];& h$ C# L: x9 z6 }1 j, Y% @

- a/ X9 j, g0 ]+ y2 r& U    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)0 i8 z8 E8 P# M# @0 g) H9 `
    {& J1 a5 R" E4 l8 |& i/ D9 S
        HANDLE hPhysicalDriveIOCTL;
; u# j  m* i7 A        char szDriveName[32];
2 Y3 W3 s( j- R+ V5 C- X4 n7 W9 Q5 A. V4 L* l  E9 H: a$ m+ I" Y
        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
. L+ R& L( E# K! K8 H8 _        hPhysicalDriveIOCTL = CreateFile(szDriveName,
2 s" d. S' b3 D8 f* O0 X                        GENERIC_READ | GENERIC_WRITE,
+ F8 A8 Y  U1 W5 N                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,4 A) e& ]! T* Y; r
                        OPEN_EXISTING, 0, NULL);
- u( m9 @$ c, M: I+ T
9 Y& J" ?$ A2 ^$ C/ k' U        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)3 }6 V; N  ~) f: W
        {# V, k( ~$ ~, K7 N4 C( I
            DWORD dwBytesReturned = 0;& I" o6 t3 F9 p3 ]" x; z. u
            GETVERSIONOUTPARAMS gvopVersionParams;
/ S+ b( B9 D8 m  J% U9 t' b- {. K# a; U! B+ w7 A- p% K. H0 a
            // Get the version, etc of PhysicalDrive IOCTL
8 {2 V- R7 \7 q            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
) t5 W8 Q! ~* G2 B) ~0 Z7 r$ h: N6 e! |0 L5 P
            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION," q9 i/ X0 F1 `( M8 W
                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),5 M4 z  k! p: }. M
                    &dwBytesReturned, NULL))' ]% s/ g& k5 H! w
            {1 N7 s7 T- \  X! J# j( w) T! P6 [
                continue;: j' c0 {4 \7 O' d) S
            }, _& V0 y" G3 a$ V, g' z9 p, T! [; Y
, s' F: s  O5 j" b1 a# V/ I: S
            if(gvopVersionParams.bIDEDeviceMap > 0)
3 X/ e' F8 V" Q7 J            {) v7 ~' L" ~1 t! Y2 S% s
                // IDE or ATAPI IDENTIFY cmd! Y  s- B3 s5 f4 f6 o4 G
                BYTE btIDCmd = 0;$ V; Y5 K6 x+ n2 ?- L
                SENDCMDINPARAMS InParams;7 N# w5 ^! W8 Q9 M; e# ^
                // Now, get the ID sector for all IDE devices in the system.: w8 _9 a4 t8 S+ O( g( [
                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,; o2 J$ a2 o8 ^$ ~
                // otherwise use the IDE_ATA_IDENTIFY command
! s4 d  n/ i' G* ]% w                // 具体所得结果请参考头文件中的说明1 X# C6 k2 X' Z4 N
                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?: e& s1 t5 m: W: l6 A1 e" x
                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;! R; g2 r8 \5 I: D( g1 a* x% ]7 v
                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));* f% T. Z" A5 ~# T. L' t2 J
                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));; _1 m0 R. [% ~- R. h( @' s- A
0 ^% U' b* k" T
                if(DoIdentify(hPhysicalDriveIOCTL,
6 n5 V2 E) k+ q3 U# H                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
+ _; `- v$ R8 X  F5 C8 i% g4 ^                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))7 t" d1 h- B' k/ W
                {$ C* l  O0 ~5 h8 _" M1 p
                    DWORD dwDiskData[256];0 r8 o( L! k6 W6 Q
                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件! d, i. |! z- }4 J# @4 Z' W2 e
                    char szSerialNumber[21];3 n0 u$ [8 Z1 M/ h' C3 O
                    char szModelNumber[41];  t. {. k4 |% h" f! l

$ V& k7 F' a% G) I% o9 }                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;3 y- y) g& f, c6 \3 l1 R4 Z
                    for(int i=0; i < 256; i++)
+ \4 j/ V- U' M$ J                        dwDiskData[i] = pIDSector[i];) l9 Z1 X; Q# q# i  f3 ?
                    // 取系列号. e/ s7 n9 v0 p7 Q7 l0 s3 p
                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));) U+ j9 o& ]8 Y  K! _6 }
                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
. q3 o2 o! o. O3 X6 M) i* h) r
# h+ g! _3 O5 H! }                    // 取模型号
: r4 _: l0 a" R; ]0 _                    ZeroMemory(szModelNumber, sizeof(szModelNumber));
& |, J0 |; u" @' G3 Z+ d                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));# t/ B2 w, l" F* B  `! p% M$ i

$ j; i8 W+ G1 N, {: L                    pSerList->Add(szSerialNumber);
9 B& |* j/ `' b                    pModeList->Add(szModelNumber);' f& F/ Y+ F; _7 b) y+ T( N- y
                }
5 Q) {! N0 ]" ?* j6 q: ~3 ~6 f            }2 Q7 q/ k, J; M; @" W
            CloseHandle (hPhysicalDriveIOCTL);
. L. d$ }  @( B9 j$ G( `/ ]9 \        }
: p( Q. U& a2 b    }
$ I3 W7 U3 F' q" G}
' o4 O$ o) w. [' P( n//---------------------------------------------------------------------------
% b6 c, ]* J1 w7 \( j// DoIdentify
4 S! j; x5 W( i  L' O) t  N% v0 wbool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
# p' @. P$ X! V              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,% F# W* n) f) X; E0 p' M* T
              PDWORD pdwBytesReturned)% B1 w* R; `3 n9 }/ e
{
: s+ z; J' V; F3 q+ X8 _. d    // Set up data structures for IDENTIFY command.
0 Y- t$ A" l+ L, u    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;( v& ~( T9 t/ Y
    pSCIP->irDriveRegs.bFeaturesReg = 0;
' Q) I* L; {0 I, W* A" L  Z) K; `  ?    pSCIP->irDriveRegs.bSectorCountReg  = 1;1 R- }( M9 Q7 T) a! D8 ^
    pSCIP->irDriveRegs.bSectorNumberReg = 1;- _: ?, |4 ]" G' ^) Z7 Y9 N1 O
    pSCIP->irDriveRegs.bCylLowReg  = 0;
/ R6 |  {8 `7 d0 J6 W! X$ q    pSCIP->irDriveRegs.bCylHighReg = 0;
# Q9 v* r1 F( ^- k7 F* m' x( ]+ d: U; d5 i
    // Compute the drive number.(主盘和从盘所对应的值是不一样的)
) ~* t. v+ G; U# K* ^+ f8 E    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;, v5 o( ~# c$ J3 N

$ H" k4 e! F4 R: E7 q    // The command can either be IDE identify or ATAPI identify.8 l+ o, Q8 e& N
    pSCIP->irDriveRegs.bCommandReg = btIDCmd;
, L0 @4 ]1 _+ J8 u    pSCIP->bDriveNumber = btDriveNum;. T/ r) Y5 n& E7 A
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
+ `' V7 _* d  X- `% m& O% l3 {
  Z, U9 t# v; J) K, B    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,6 L/ q2 [* ?$ f) W
           (LPVOID)pSCIP,, k( ^3 d- l  W4 `9 `
           sizeof(SENDCMDINPARAMS) - 1,
( @- |0 Y6 W( j3 P* T* R           (LPVOID)pSCOP,; v) `& A6 Z! Q+ u. S
           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,9 _: ]! i4 X: l7 Y' {, r" D
           pdwBytesReturned, NULL);
( T% \6 A; x- X7 H* @}* A' B5 I. |6 }. d- J6 P" D3 J
//---------------------------------------------------------------------------
3 y% `8 a' O5 N* [! \) \9 q& m) t// Windows 95/98/ME 代码
% }' B  \- x9 s3 ?7 l- S$ S' U6 l: E//---------------------------------------------------------------------------
+ A" d2 n/ U, X" \1 t$ q) B+ L// ReadPhysicalDriveOnW9X
: I; j/ S& Z" O- Q6 C0 }/ Rvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)) E! |) D+ h- [8 [# ?* P
{
1 \% U3 n+ s' R# G8 ^    WORD wOutData[256];9 |- g- u6 m& d4 m$ U8 V8 P0 s
    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
: y* U5 r$ A% C9 q% d3 u! m  f4 s; N* `6 _  H8 {2 r( g
    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。& L( f2 N" @8 h
    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以/ i% A6 r2 u  E& g5 _3 M& c1 s
    // 避免蓝屏的出现。(期待高人能指出原因)3 _. a, f+ Z/ Q, Z. I: g9 E
    for(int nDrive = 0; nDrive < 8; nDrive++)
" o7 |0 ~6 l- q$ r5 K! F5 w% W- i  y    {
/ e1 y5 p* \; _8 e7 L( ]6 h        WORD dwBaseAddress;
5 r+ U( z- y  R- `  p) Q        BYTE btMasterSlave;         // Master Or Slave! f7 |9 ~* {! U8 B
        bool bIsIDEExist;
2 B# g1 V: S) k4 ?        bool IsDiskExist;
2 \5 A3 c, `7 {; U% ^7 C
) h+ M7 G4 C" l/ D! G+ q        switch(nDrive / 2)
4 `) y% W3 j3 A( V        {8 z/ A' I; i8 ?0 `! L0 |
            case 0: dwBaseAddress = 0x01F0; break;
+ x' [* g( x4 f# E# L" d' S            case 1: dwBaseAddress = 0x0170; break;( @% X" k7 B; M' N
            case 2: dwBaseAddress = 0x01E8; break;
2 ^6 `: V! X4 v            case 3: dwBaseAddress = 0x0168; break;
+ M% s& u! N6 [7 ?. Y7 L4 i        }
% `) Y; ?4 j/ l1 K* r: e! D& k: ?, i' y: a6 y
        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
- ]7 `; Q' N& }; Z; h: R  X7 p* F5 U8 V( P4 ]* z
        // 进入Ring0
0 d4 N% G- U  H' a4 q        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
0 g$ I# p# T( Z# R$ V$ t                bIsIDEExist, IsDiskExist, wOutData);
0 I& Q/ Y! ?* p& l3 E    }4 K# O+ J  N0 A& f& A4 Z
! u  W5 ?* @5 C1 ?  [; p  w
    // 开始读取
, j8 F' x1 g/ {7 V* G5 z! X    for(int nDrive = 0; nDrive < 8; nDrive++)( Y, B  I  H: d/ c! i) G) N8 Z
    {2 o4 I5 c% G2 K  |& [+ o
        WORD dwBaseAddress;; t# v! N- y2 Q# o) d
        BYTE btMasterSlave;         // Master Or Slave5 x/ d: p& }  R' @% W8 G# ~' N
        bool bIsIDEExist;/ C5 _+ }: g3 V3 Q" b
        bool bIsDiskExist;" c" h$ j9 ?6 n* z- j
        switch(nDrive / 2)
$ T* y4 G5 ]& u, B        {$ n! {% O# N: T
            case 0: dwBaseAddress = 0x01F0; break;
' Q- F& K- r1 Q7 k/ V7 @% g! |            case 1: dwBaseAddress = 0x0170; break;5 H7 s/ ^6 Q% u
            case 2: dwBaseAddress = 0x01E8; break;6 e, h) i1 O: W. E7 \- L* l
            case 3: dwBaseAddress = 0x0168; break;
7 d3 `9 o6 o: ]- v1 M1 u5 B        }" b$ n. n' u3 M* V
' o! |# t3 m' ~
        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
: }9 s% u9 P5 o# v6 ?! z. G1 Z& ]* t9 d$ H3 W
        // 进入Ring0
) f2 ?" U" L' ?  \9 C        bIsIDEExist  = false;# l2 B1 l" I" j( z' ]
        bIsDiskExist = false;
7 M7 E3 m; b1 l2 Y        ZeroMemory(wOutData, sizeof(wOutData));
9 _2 ^0 |8 D6 s' F5 |+ [  }5 c
/ B; k! {  \' ?* G: Y; c1 P# X        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,' F9 N( d! ~& K  ^- e& W& {
                bIsIDEExist, bIsDiskExist, wOutData);3 ^7 ?- s" r, n+ g4 o

5 u" f: k; E* l' K/ |# S        if(bIsIDEExist && bIsDiskExist)+ A. p4 g" M/ w' O( u# E+ A) ?
        {
! J1 h  y6 Y# t5 o. D4 h& _* S            DWORD dwDiskData[256];
# D) E4 }) ?4 h" ]8 n- R( Q            char  szSerialNumber[21];% ?8 R- s9 c( g9 H  j% }, e) V1 R
            char  szModelNumber[41];1 V8 H7 p% g: ?2 E; ]9 A
& a# I6 {4 p5 h, x8 z/ r
            for(int k=0; k < 256; k++)! a5 E' I& }2 g& m  }) a
                dwDiskData[k] = wOutData[k];
* }7 Q1 @/ t/ p) w: {: V# B: y8 R
            // 取系列号6 }2 d) q. e; }7 S, ~9 j
            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
$ P* C- ^/ F9 L+ |+ J; m            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));2 G( L# a3 X& f; Z/ x. q

  L. s5 @0 B2 v( Y            // 取模型号3 c, b  u: W! h" J, V4 N. h& [3 ^
            ZeroMemory(szModelNumber, sizeof(szModelNumber));' Q) v. |# D. z( `  A5 |
            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));0 w/ Z( D0 u" a+ T: k  \# P

- a: H4 X6 \1 x5 T4 D! [            pSerList->Add(szSerialNumber);
9 U8 i( @$ n3 z  R. t+ W3 y; q            pModeList->Add(szModelNumber);
( Z% W7 w' Z; I; d        }5 \5 ]0 U) n& _* s
    }/ y* J7 j% l+ W' }7 b' D
    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
8 e9 d! \. \2 d}
8 N: G9 U6 C1 O2 H8 _//---------------------------------------------------------------------------  ~- T$ Y* ~. x/ P9 ]# I' @
// 为防止不负责任的转载者,在此注明原出处信息,请见谅。; q! o7 ~$ {5 ?' B# |! i3 N
// 资料收集整理:ccrun(老妖),欢迎光临C++Builder研究: http://www.ccrun.com' O" ?6 Z) O0 r! \" z7 p
//---------------------------------------------------------------------------9 C8 f+ w0 t$ D
// ReadPhysicalDriveOnW9X_Ring0()( i: ^  A! I8 C/ v
//  z' J$ h# o) x: Q+ b2 I, `- G* |/ z
// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h" u, ?( W7 D: D8 y: x7 ~
// btMasterSlave = Master(0xA0) Or Slave(0xB0)6 o. l( s, W8 w8 l& A  x& d) B
//---------------------------------------------------------------------------
" _2 h3 Z! w7 u2 A/ q( C. rvoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,; k8 a3 h2 g  N+ O! g# e
        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)' R7 X* ~' f6 \* j% K9 t& Y' ~
{
* z# ]9 J) c, X% _+ A' t: `" V' g    BYTE  btIDTR1[6];% d! o) i* O# t( L
    DWORD dwOldExceptionHook;
- S( o  A% O* Y' S$ k& @    const int nHookExceptionNo = 5;
! Z( `, u! A/ Q' p' G9 T7 I1 W7 b; L% e! o/ i) [+ Y$ a% V; c
    BYTE  btIsIDEExist = 0;- u" i5 a# B! c
    BYTE  btIsDiskExist = 0;
8 F" Q  W/ T8 l0 N    WORD  wOutDataBuf[256];& N* W$ I" G5 J
4 E" `6 ]3 h8 D$ |$ Z9 x1 P( z8 Z
    BYTE  btIsFirst = (BYTE)bIsFirst;
) ]& e1 ?; S; A& x3 M8 j
! r  v. }, [, k0 o) @2 d    const BYTE btBit00 = 0x01;
) @0 H. G2 A! ?    // const BYTE btBit02 = 0x04;
/ ?% ~6 K, A* s7 _) J" S* @& z    const BYTE btBit06 = 0x40;5 \/ V* t8 _5 h5 C9 E
    const BYTE btBit07 = 0x80;
% ~4 H5 _; \2 ]% ?6 K1 a    // const BYTE btERR  = btBit00;
& _# t4 ^& o) b8 g$ g- J/ m$ p    const BYTE btBusy = btBit07;
; [8 h; Q- {3 E& W' n    const BYTE btAtaCmd   = 0xEC;
1 b  D3 J% d* R, R3 @: k2 h) n5 b+ r    const BYTE btAtapiCmd = 0xA1;$ q+ Q3 j6 y  @5 M5 m
% N0 F# g1 J! @, |8 B' [
    __asm
$ D! R  U& V! E1 a/ F1 ^+ ]1 }1 Q    {0 E4 s% r$ r) x( M" J( T
        // 必须先执行这条语句4 f9 G9 f7 Z5 z+ F
        JMP EnterRing0
+ j& ^" P( c0 a. U2 P7 |
" f8 C) @. L2 p2 N( z: V. G' K  |  `        // 定义过程
( ]/ v* }* k, ~) F0 H- @        // 等待IDE设备直到其不为忙为止$ J/ t( W: i( m: z0 @/ W8 y
        WaitWhileBusy proc
# P& `4 e+ V" p$ G' P  V$ v; M! j0 @* o( ?+ N
        MOV  EBX, 100000, G' s& \# l; N5 o5 _+ P
        MOV  DX, dwBaseAddress
7 ~8 D$ }1 H+ Z4 q3 o6 U$ R        ADD  DX, 7
1 V1 U' O4 f1 O* ]/ r$ q, q  T' S
, q7 p  X0 w! I# y$ f4 U8 X        LoopWhileBusy:
' T- |( ~. R$ j" M: V8 J4 C: H2 a. J+ B7 q
        DEC  EBX( t6 l: j2 _( F" k# |, ^8 G1 A' w
        CMP  EBX, 0
" J% w' D' X5 X. A, w' `8 N4 u        JZ   Timeout/ c1 W$ T6 ?3 k, Z. v' \3 C* T
        in   AL, DX
0 o) [. M* j- W( w" A1 ]        TEST AL, btBusy! i" ~( S5 |* y1 y( v; P
        JNZ  LoopWhileBusy
  ]7 l1 F  R% N, |6 M( g        JMP  DriveReady$ v$ M1 e( Y7 O, ~! X  q2 o. P

$ u% o. n5 Q$ F- a        // 超时,直接退出8 F  H0 ?+ n) Y0 g
        Timeout:+ ^* L2 H6 ?8 F" R3 ^7 a0 L  R
        JMP  LeaveRing05 j6 e/ B, q; j
        DriveReady:- `6 r/ K) e- v6 u3 M
        RET
! j4 n& O0 x4 X$ s9 k        ENDP   // End of WaitWhileBusy Procedure
9 ]9 j. z9 Q9 o/ d* o0 ~+ |+ m. H1 D6 n5 N* r! M% }
        // 设置主盘和从盘标志
# W/ h& r% N& @# d3 L        SelectDevice proc/ ?0 b1 Q; H/ U. c! r: w; R. M

" n  V$ {6 z5 h' a        MOV  DX, dwBaseAddress7 M% I4 ?& ?0 W, g5 {  O
        ADD  DX, 66 Q; {* K7 a8 u0 M
        MOV  AL, btMasterSlave
0 f! E  j6 y2 D7 F! |. W0 E2 B4 }; d! m6 @+ ]' [( ^$ r
        out  DX, AL
, b" A& m; h4 F5 J3 u+ ~. y! b$ i        RET6 S1 Y% e- q! a6 R! Z
1 F8 J) K6 t8 ^7 ]' i0 Y( |' u
        ENDP  // End of SelectDevice Procedure* Q5 S* L0 T1 B/ O* i

9 S% Z9 F) a1 o& S, P6 e        // 向IDE设备发送存取指令
9 ^" O5 p: M' N! k# K# c        SendCmd proc/ T6 V1 C2 f$ }3 i1 @: S3 F. [

! b, @% X$ c& K        MOV DX, dwBaseAddress
( ~4 l# D9 g' e. h$ K$ y        ADD DX, 72 S8 Q0 C* g1 R7 O9 y* ~
        MOV AL, BL // BL是主从盘标识,在过程外设置) u$ a! S9 N- X
        out DX, AL
+ p1 l* }  _$ y- @0 ^$ I# n        RET
: h8 A3 M2 \/ {- y* b  Y) r7 G        ENDP  // End of SendCmd Procedure
& A3 y$ l5 m- \! q0 s& Y: l& F4 V" e! i! ~/ G  ]5 N
        // Ring0代码, c& {5 {1 j9 n1 K5 N
        Ring0Proc:5 h2 }8 b% h5 o2 x9 b% g
        PUSHAD
$ b; t' j) Z4 C0 a  }# d2 x        // 查询IDE设备是否存在
" G- b2 T% p+ q        MOV DX, dwBaseAddress
6 I8 K& g. v# r5 ^* i/ m        ADD DX, 7
1 }' @& s& U) \% G- M- u        in  AL,DX
" K- {7 p6 s5 r# b* j
8 I" @. G, H# I1 s& H  ?; D, E        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
" y$ q; a# D2 Q. K) J        CMP AL,0xFF
* p+ p1 Z) \/ j        JZ  LeaveRing01 P! \% R( g# B- N  L; ~( a
        CMP AL, 0x7F* L' S5 |7 r: A# o
        JZ  LeaveRing0  Q3 V$ e9 b) w1 I

! [8 V$ J: u7 B1 i3 U) q, C# M/ Z        // 设置IDE设备存在标志: n2 {/ ^' |0 C, l: X
        MOV btIsIDEExist, 13 ?$ x* s( ^8 o- }

4 [; H6 u6 d; Z+ B+ `! }        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)7 h) M9 }& Z: K2 n
        CALL WaitWhileBusy
0 t+ J% A6 m3 c% e. c* I6 `        CALL SelectDevice
3 ?5 [3 z% J. N+ H9 h* d
$ V* i; V- E, A( |( w$ M! I        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
' s% N7 b, c8 [5 J" L        CMP  btIsFirst, 1
3 J3 s- F5 S! J/ s. m9 I8 r1 ?* b        JZ   LeaveRing0
0 S8 u+ x9 H: f  w& y$ K( c5 ~2 A# {# m3 s4 V
        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???& A- G- Q2 c  u3 W6 N1 ?
        CALL WaitWhileBusy& E# k* l3 s6 X1 i9 {% e/ Q

& L% R, z5 a* T2 _2 W        // AL的值等于cBit06时,不存在驱动器,直接返回) O6 a' r/ h8 s$ o" }
        TEST AL, btBit061 [! V4 Z2 S) |0 f, k8 ^
        JZ   LeaveRing0; d8 p+ H: Z3 b* M) z# E: F2 \
! e. t8 F+ l0 |# r
        // 设置驱动器存在标志" r( _. ]* Y) q8 A
        MOV  btIsDiskExist, 1
) s0 F+ K: F: d0 F' m: S, a
! n2 U+ M' i4 E- w& ^" W- i        // 发送存取端口命令, H  E; y5 P4 \2 b3 b/ b9 m
        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,) Q  ^3 a. U5 Q* g) U) y1 C5 h" C
        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令! k8 L0 V! ~% D5 x
        CALL WaitWhileBusy& {( ^/ R1 y$ s# y( b2 U
        CALL SelectDevice    // 设置主从盘标识
6 w% D9 f0 a' R% `! ~        MOV  BL, btAtaCmd      // 发送读取命令
# S/ p! o/ g- r( z/ `        CALL SendCmd
3 w6 @* a' h! H) v+ O1 p        CALL WaitWhileBusy" O0 }0 X* t( d8 j2 l  O" P

- L; m8 e- W5 ?5 C, {        // 检查是否出错" K, v& D6 ?0 [# S
        MOV  DX, dwBaseAddress
! E+ `% P( Q$ F        ADD  DX, 7
& d- p- h. Y7 x1 p& L+ E/ m  I" X6 a- N1 d4 F. r; e
        in   AL, DX6 ~6 k8 g% z* F2 t& F' q3 @8 g3 w- w2 s
/ m1 J! B& S" X: p, Z
        TEST AL, btBit00" J" w% G! w+ a$ {, h9 n
        JZ   RetrieveInfo   // 没有错误时则读数据
9 M9 e5 `* m; i8 _9 S6 T
3 t' ?4 p+ G. N        // 如果出错,则进一步尝试使用ATAPI设备命令, D0 D' L6 B" G, F
        CALL WaitWhileBusy; j4 f( ?& O  s' x2 b& s
        CALL SelectDevice( Z; \# A7 T2 r( u2 ?
        MOV  BL, btAtapiCmd
7 e7 [! `4 A, k/ ?. ]8 O- Q        CALL SendCmd
/ M- `  h; @9 F        CALL WaitWhileBusy
8 P& Z7 P  S  Q0 X% }% z: W! y- b) T! Y! m3 y& c0 A
        // 检查是否还出错4 r9 v6 w% {: x
        MOV  DX, dwBaseAddress$ C: |! V% j) ^1 g) O
        ADD  DX, 7
5 F. V$ c1 R5 v        in   AL, DX
  `! o# V7 r' }6 P6 E        TEST AL, btBit00( x$ f0 V, M, b3 A+ y+ w: @
        JZ   RetrieveInfo   // 没有错误时则读数据
; X9 U: [/ `. D; h) P        JMP  LeaveRing0     // 如果还是出错,直接返回
& E( W% X8 x" M+ u& W  I. I
$ P" Z% U% S& c        // 读取数据
9 C& D9 Q. d1 {6 h+ f3 x6 w% U) t        RetrieveInfo:3 t! F0 v& U& d% p# H% {9 T4 q0 s5 I
) T& W% P) X" _2 X
        LEA  EDI, wOutDataBuf# G! M2 b$ R" a8 r. u9 [
        MOV  ECX, 256
/ X7 N  M1 Y& f4 Q/ s/ F8 O        MOV  DX, dwBaseAddress0 x8 R  ~5 [: U1 X: j# |$ K& j2 w
        CLD! s: _6 T* I4 u: S4 H( s7 z; B" Q
8 w0 Z3 f3 |; a* N- j
        REP  INSW
3 B9 D+ f  O4 Z) m# R" X
# A/ l( S7 p$ [' B1 p' Y- {        // 退出Ring0代码9 |3 n3 T3 d( X5 d3 _/ Z) T/ z3 Z
        LeaveRing0:4 j1 y" v+ E8 w2 O/ u
/ h& {' m1 m2 N
        POPAD2 L8 K" J- a' {0 p0 H% V2 [
        IRETD
0 p5 R/ _5 w# F9 @
7 t0 ?5 x9 f6 L  Z3 ~        // 激活Ring0代码
# p: u7 y1 [7 O7 ?* |4 V+ \( J6 i        EnterRing0:8 }2 v6 J. v- K9 ~" G

. E: O' {- A: x- H        // 修改中断门
9 E9 p- }+ j# M% O, j8 d0 ]. o        SIDT FWORD PTR btIDTR1& l1 F( p* N( `* ?
        MOV EAX, DWORD PTR btIDTR1 + 02h
  Q) T0 E! R6 @        ADD EAX, nHookExceptionNo * 08h + 04h
& |5 N. J1 G& N        CLI
9 d0 A* s+ r9 b( @8 ^6 ^) J  i
6 E$ o  P8 e; V, U: Q0 c4 O6 z        // 保存原异常处理例程入口
1 {( ~( M/ L8 p8 Q" z        MOV ECX, DWORD PTR [EAX]" D5 t" |" ?0 J+ T% ^
        MOV CX, WORD PTR [EAX-04h]( h2 g, A  m/ b) o0 o8 Q
        MOV dwOldExceptionHook, ECX
% |6 \' w3 ~% l
- _/ z6 s" y) [/ c. I        // 指定新入口
. c! r0 p: p! b8 S        LEA EBX, Ring0Proc
/ y( p, \6 {3 J        MOV WORD PTR [EAX-04h],BX# d6 Z% L7 z, B/ }; v) {: ?  M, n* X
        SHR EBX, 10h4 |  C- O0 W% d
        MOV WORD PTR[EAX+02h], BX
  _  Z! y" {& h; K. r: O7 k
. P# _' s. R/ n8 r6 f6 u4 B        // 激活Ring0代码* {3 Q2 q: i& N, @
        INT nHookExceptionNo
) t5 \0 B; Q' c0 L' B
( N1 U* _1 y; z! x" d        // 复原入口, Y; u+ f/ C. s" @
        MOV ECX,dwOldExceptionHook
6 r6 z* F/ R: w% k+ b        MOV WORD PTR[EAX-04h], CX. \! q* W$ T% G+ C& w, V) u4 u
        SHR ECX,10h% X; b4 Q& X6 u2 g8 r; J3 ^
        MOV WORD PTR[EAX+02h], CX: k! x8 _& a& W% C% [
        STI
) ?1 b3 P: Y' Y3 y0 H; l  A5 f2 A6 J    }
$ L8 d! C4 m: `1 B" V/ x    if(!bIsFirst)+ h/ v' \" K* E
    {
: K4 Q9 O8 d5 M' m: j9 K7 x) E        bIsIDEExist  = (bool)btIsIDEExist;
; @+ \+ }# P6 P2 S  \5 T        bIsDiskExist = (bool)btIsDiskExist;, R6 b* W* K9 y! i- c+ C
        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
1 G8 u  I3 b; P2 L    }3 m& [0 _) U$ ^, |- s
}5 q) t0 v( T  s; P* g$ G' h
//---------------------------------------------------------------------------* }9 l7 R/ H$ H9 S, L* b& k
// 调用方法:7 e- e# H& X0 Y, _
void __fastcall TForm1::Button1Click(TObject *Sender)) ~5 `; p$ w+ @" r5 H
{
# a3 L6 q, \- {2 O5 N    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
) b* E6 ^  _6 i* z$ T}
3 t$ x8 V) {5 {) U; [& J
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-10-2 00:00 , Processed in 0.018933 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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