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

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

[复制链接]
发表于 2008-1-6 19:59:06 | 显示全部楼层 |阅读模式
代码框架,你所要做的仅是修改WQL语句,具体可看MSDN。以下代码为简介起见,一次返回所有的CPUID或硬盘厂商系列号
: @% y4 S6 {  N. R
  1. 9 t3 z+ r% T4 D# v
  2. #include "StdAfx.h"# V; _( |, ^+ y/ L* o- i9 ~* ?$ D3 _
  3. #include ".\puiddisk.h"
    ( w% W6 M2 L0 C1 {& K
  4. #define _WIN32_DCOM
    $ l+ ]6 H; _4 I
  5. #include <iostream>; s9 ?3 A/ I4 F' d/ b
  6. using namespace std;5 t- u/ m. U9 K( k0 X
  7. #include <comdef.h>
    ( H: {7 c5 s; a: H1 w6 b* A
  8. #include <Wbemidl.h>
    7 r7 a. f- O; \) N; N! v7 C
  9. . Q% J: S/ N7 i8 A
  10. # pragma comment(lib, "wbemuuid.lib")
    / N# o8 g/ m+ E( K
  11. CpuIDDisk::CpuIDDisk(void)
      s/ c; I  ^1 }4 `/ F
  12. {
    7 [$ t: ~8 {$ Y0 w
  13.     GetInfomation();6 `9 b* `. E+ \# r$ [. B* R" w
  14. }& n# j; J* k% h& @( o- W

  15. " k- R$ k0 y6 ?8 m: J2 p; t
  16. CpuIDDisk::~CpuIDDisk(void)- y7 c1 s: j: T: C0 ^6 u
  17. {
    5 W0 ^* `4 N. M: Z, M
  18. }
    8 N; g8 {, x2 `$ E
  19. int CpuIDDisk::GetInfomation(void)
    1 n# k9 z5 }4 D9 N9 \0 n
  20. {
    , _9 {5 v9 r4 D: i
  21.     HRESULT hres;1 s) s" y# H$ H8 H5 O! x& q% i
  22.     //步骤1:不是必须的,COM只须也只能初始化一次
    1 C$ J# L! ]9 w& m
  23.      hres =  CoInitializeEx(0, COINIT_MULTITHREADED );" A! L( y' H. M
  24.     if (FAILED(hres))
    9 s, S5 @5 }  A0 i' F; W; K7 A8 }
  25.     {/ N* q; T. e0 L
  26.         return 1; //初始化COM异常:注意,COM只须也只能初始化一次, N( l  S# w4 n) I; Y8 I2 J
  27.     }
    1 A$ X( l, H$ A& E' `; Q
  28.     //步骤2:不是必须的,COM只须也只能设置一次$ |/ q! e/ w! k1 C  o) c- f
  29.     //Set general COM security levels
      F6 j: U, Q: ?/ d; Q
  30.     hres =  CoInitializeSecurity(
    ! Y3 n' Q- R  ]
  31.         NULL, 8 y) o2 B1 ~. C, d4 p
  32.         -1,                          // COM authentication
    , T  J8 a- e* T  _) N
  33.         NULL,                        // Authentication services
    # }) E( {4 C" e: a/ x9 Z& s% i0 M: N; j
  34.         NULL,                        // Reserved2 G' y7 I' f0 G) i+ P
  35.         RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication ! A; r% L8 n2 n
  36.         RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  ) |, [. m8 V/ `2 ^. a4 U
  37.         NULL,                        // Authentication info, i+ i- O# |9 }, f* L* Q+ \
  38.         EOAC_NONE,                   // Additional capabilities " H7 l& X% t* K6 L* d2 Q
  39.         NULL                         // Reserved
    , q9 e% U3 M5 A+ z* f
  40.         );& B$ a4 z, S9 G8 c% b3 q
  41.                      
    ; S$ |: @" R4 T2 E- S" Y" J
  42.     if (FAILED(hres))
    ! N6 e' U* P) C" p, P" r" T4 ]* y
  43.     {
    - r" T4 M7 l  H7 M4 `2 S
  44.         CoUninitialize();4 i0 R6 p! [2 y- I+ j7 g
  45.         return 1;                    // Program has failed.& v& _2 ?) o' H9 ~0 h  p
  46.     }& j) T- r+ X" z+ h1 P/ p6 j0 C
  47.    
    + q- S9 N/ C) S4 Q4 \4 `
  48.     //以上不是必须的,若已有“::COMInit();”,则要跳过2 c  U- O& _& i9 r2 |
  49.     //步骤3: Obtain the initial locator to WMI
    1 o* c. f* m  N
  50.     IWbemLocator *pLoc = NULL;2 n; H+ t; P" h! E, V7 f2 n6 E
  51.     hres = CoCreateInstance(8 T" q& A" ]+ ^% }0 _4 V
  52.         CLSID_WbemLocator,            
    % m) ?7 `2 Q# L0 q! g4 B' e
  53.         0,
    ; E6 A$ j9 D% q. `! c
  54.         CLSCTX_INPROC_SERVER, $ r' Z3 K7 N& E# h) W( v0 t6 n
  55.         IID_IWbemLocator, (LPVOID *) &pLoc);" D7 u$ x7 Y/ I1 c8 X2 {

  56.   u5 b! g, O" \
  57.     if (FAILED(hres))
    " s( E3 a5 x4 S# P1 G# @
  58.     {
    : v" k% P0 g* o- m' t7 J3 E
  59.         CoUninitialize();! F' \9 `# d( W$ m4 z0 R
  60.         return 1;//Failed to create IWbemLocator object
    ' a% y7 ]0 D+ W
  61.     }
    0 r: ~7 B* A7 H7 ^! {

  62. 8 H7 h/ C7 a& @. d# k8 |& ~( }* T
  63.     //步骤4:Connect to WMI through the IWbemLocator::ConnectServer method' R8 A9 B) p( m) x
  64.     IWbemServices *pSvc = NULL;6 e! _. Z( n+ F
  65.     hres = pLoc->ConnectServer(% O/ M/ u3 }- s. Q/ P
  66.          _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace+ i% ?' \8 Q  W$ k- _! x
  67.          NULL,                    // User name. NULL = current user' [5 P! \7 \+ f* p
  68.          NULL,                    // User password. NULL = current
    9 @: s( y1 e. P# S/ d
  69.          0,                       // Locale. NULL indicates current
    % e! \- S! O  E9 r; h
  70.          NULL,                    // Security flags./ m$ B* t4 a" \' Y2 x7 y* F
  71.          0,                       // Authority (e.g. Kerberos)
    4 }& z7 v* A3 Q1 c9 `7 |0 Q) j  G
  72.          0,                       // Context object # \$ c) M% B  u3 q9 O2 K
  73.          &pSvc                    // pointer to IWbemServices proxy. B4 _' }5 S% V  m
  74.          );
    . ~+ I1 m* c3 O3 c: T  w* d
  75.    
    % i$ `4 e- u* @- h
  76.     if (FAILED(hres))8 n9 h  G* M# H) Q
  77.     {7 L, Y4 {7 B& f, D3 @
  78.         pLoc->Release();     . p& v9 O2 o  X% X
  79.         CoUninitialize();$ }1 C, r% r1 X2 ~9 w4 l& m4 k
  80.         return 1;                // Program has failed.
    " v8 w# k; p8 K: x- V
  81.     }
    1 i6 x3 y! G% Q2 g! {
  82.     // 步骤5: Set security levels on the proxy
    / h+ d! ^. ?6 I4 T7 H7 `) M
  83.     hres = CoSetProxyBlanket(
    4 l; o% {1 G, r( @0 N
  84.        pSvc,                        // Indicates the proxy to set
    # L4 ^/ O# N- ?7 X4 A  {
  85.        RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx
    % v/ c* C2 `/ r% m; {
  86.        RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx) M  Y& ^8 w. B
  87.        NULL,                        // Server principal name
    9 w* Z0 N, c4 v$ |5 i+ M
  88.        RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx
    " Z' s7 E2 O# D" s0 r& o4 t( ]
  89.        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx4 _; N" t' I! F
  90.        NULL,                        // client identity3 L) x1 B" ^  G+ ^& X! R! f
  91.        EOAC_NONE                    // proxy capabilities & U! C; _; D9 g( w- t
  92.     );
    3 g) d& V+ V. ?) ~5 n" m3 z

  93. + y5 D- s; r$ w
  94.     if (FAILED(hres))
    , u# a- e0 L1 K0 k
  95.     {
    + X# s  p1 k- y4 l4 t
  96.         pSvc->Release();
    2 c) `8 K% M. R$ F
  97.         pLoc->Release();     0 w1 S; a' P. J, q; K
  98.         CoUninitialize();
    1 Z, T1 Y/ l9 H2 k0 u% d6 j
  99.         return 1; ' _% c0 m8 c' N: h! X
  100.     }3 w2 ~) }+ z; d  E+ h) `7 ^4 A* `4 X

  101. 7 R- @4 q2 n) P
  102.     // 步骤6:Use the IWbemServices pointer to make requests of WMI ----4 a* H% h3 Q0 Y+ F/ d% E  O! @
  103.     IEnumWbemClassObject* pEnumerator = NULL;! p9 {' q! U' t; P0 v
  104.     //计算CPUID
    ! M( ?4 R& u" i& f! \2 t: m$ S4 R
  105.     hres = pSvc->ExecQuery(9 b) D: ]! U- F! ?
  106.         bstr_t("WQL"),
    " p9 V4 F' ?9 r
  107.         bstr_t("SELECT * FROM Win32_Processor"),//Win32_OperatingSystem, k# Q) h) a: u  @5 D$ Z0 M4 J
  108.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, ( r- E- Q) i0 Z( E
  109.         NULL,' N4 Y3 d; \9 L' `4 R' G
  110.         &pEnumerator);
    0 t$ T2 y1 U0 k8 C: e
  111.    
    4 I: q, D- a0 x# z+ w" s
  112.     if (FAILED(hres))0 f; t# Q) u. N: l
  113.     {
    * n) h$ a$ N; Y' [0 C
  114.         pSvc->Release();! E6 [0 A" g% I% m- s  \4 f9 m) k
  115.         pLoc->Release();% \  z- o  _9 V! C, K! s  {
  116.         CoUninitialize();5 g9 ]6 }8 H; x
  117.         return 1;7 ~% I- G  U4 U$ R
  118.     }
    3 I. u) ]1 P5 @8 e
  119.     // 步骤7:Get the data from the query
    1 P1 ]! e8 ^# e- @
  120.     IWbemClassObject *pclsObj;* O$ W/ F" B7 ~$ ^  F
  121.     ULONG uReturn = 0;0 M1 |- W0 n2 t0 |+ b
  122.     while (pEnumerator)2 Z/ _" n! k" N
  123.     {
    : S8 z( V$ U) M+ c1 p
  124.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, 0 L& \) U( j# L- |. a1 I
  125.             &pclsObj, &uReturn);
    # t# _( Y( Y! k: j) S1 E
  126. 2 d7 R; y4 I, c9 A& m8 d
  127.         if(0 == uReturn)0 e- W4 F7 g& b& b- \' ], V# d# p
  128.         {
    1 x& W/ o1 F! G5 l8 i) Y4 F
  129.             break;* [& b3 N* s8 [! j8 T! _* a
  130.         }
    + H% B4 x8 j2 P
  131.         VARIANT vtProp;2 _9 u4 S4 x" ]- ^, C& \1 H. x
  132.         VariantInit(&vtProp);
    5 X. Y( I9 `' F
  133.         hr = pclsObj->Get(L"ProcessorId", 0, &vtProp, 0, 0);
    5 r  U9 K. X' \: l* S0 p) I
  134.         strProcessID=_com_util::ConvertBSTRToString(vtProp.bstrVal);//strProcessID:类级变量" r# O  [7 K) {# m1 _
  135.     }( J* `6 w; V# L! f8 ]
  136. 9 T. Z* f* h* B8 U5 w: w/ S, N
  137.     //计算硬盘系列号
    # Z5 _3 t) o" ~0 Y# E
  138.     hres = pSvc->ExecQuery(" J* }/ T4 m% K1 `
  139.         bstr_t("WQL"), , h4 B" Q! j8 ^) Y+ K3 _7 C
  140.         bstr_t("SELECT * FROM Win32_DiskDrive"),7 R4 X* c* V- t8 \, i
  141.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
    * a* S/ J% a# q2 a2 B8 u( B! q5 R. L
  142.         NULL,
    2 F/ V( O+ W# k: e
  143.         &pEnumerator);
    8 e" L+ v) `: w: K( z4 B

  144. - b& o5 l- x# z" t% \" e4 F
  145.     if (FAILED(hres))1 ^) ^+ I9 X+ P
  146.     {
    3 B  {" l8 q3 _2 }
  147.         pSvc->Release();- {( a" c  m! I9 Q+ b. v, A* m' c
  148.         pLoc->Release();' c( S, ~/ }/ u/ x/ b7 t! F
  149.         CoUninitialize();  q( {) {$ L9 q
  150.         return 1; * z# {+ |: b* w, d$ f. a1 I
  151.     }
    ) r- M; n7 L/ C1 d% x
  152.     while (pEnumerator), p, d$ L) t. M  y, i& ?" n' w6 l
  153.     {
    ; X" R; a! w# R& T% v0 C- ^
  154.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, $ u( z- n/ q! Z: T8 B. ?! T( e
  155.             &pclsObj, &uReturn);
    8 N, E# r' w/ ^
  156.   o! |& E- C; q
  157.         if(0 == uReturn)- I6 b' L" h  X5 K. b. g* {+ @
  158.         {; N4 C' F; m% o+ ?$ M$ ?
  159.             break;$ ]) O+ T1 B0 Y, \9 ~" E( z
  160.         }
      _. Y1 e2 }$ n1 o' B

  161. 7 j8 _: g: d. ^- x
  162.         VARIANT vtProp;
    & J9 W; b4 T0 g9 @1 B, a
  163.         VariantInit(&vtProp);& |8 q. U. }3 a1 G" K  J1 u
  164.         hr = pclsObj->Get(L"PNPDeviceID", 0, &vtProp, 0, 0);
    $ W  L& Z: T' `6 `* L2 w) g8 q
  165.     strDisk=_com_util::ConvertBSTRToString(vtProp.bstrVal);
    9 m+ O! v1 ]7 u6 J: ]  {+ r
  166.     }% q, S/ ~( l+ @% t2 e+ C
  167. . i; ?$ Q/ ~  E1 L, f1 p- W  e
  168.     pSvc->Release();9 A( Q' ?( K3 u2 Q! S% P
  169.     pLoc->Release();
    7 c0 E' Q% c0 C/ Y* I( y- b4 y% |
  170.     pEnumerator->Release();% J& B) x, K8 ]
  171.     pclsObj->Release();
    & \3 [6 ]7 T) t, d: l# U: e
  172.     CoUninitialize();: u! j1 Z( v7 K7 y
  173. / O1 w& C& b3 V; P
  174.     return 0;   
    6 z; j* z" l) ?# k8 |- t) m
  175. }
    / l& ^$ R. c7 M! O( k' \1 K
复制代码
 楼主| 发表于 2010-10-11 19:21:05 | 显示全部楼层
本文代码经ccrun(老妖)在Win2k下试验成功.) v7 J2 o' h" B- X
# B4 x  O/ P! K& U* _
#include <WinIOCtl.h>/ e$ B; U4 T  v. D7 }
#include <stdio.h>. Y2 F! t5 T/ p5 }# M4 Z  {
3 F/ ]8 w0 k' _6 ]! G' Z
#pragma inline
" [. B- F3 o9 y( V2 N//---------------------------------------------------------------------------% s# S4 Y# D5 e: O  V8 k
// IDE NT/2000/XP专用变量" N9 q& u! u4 H  `7 {
#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
$ K, q$ g; S3 i8 R" K5 `# M! g#define DFP_GET_VERSION         SMART_GET_VERSION4 c6 {! b" w. l6 b: _: X
#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND9 D' J9 w3 u' X7 Z, |
#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
. f- e" e- t- M9 ?8 I7 w) ?! j9 t5 u2 o. ?3 v
const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令% G/ }6 B, l, p/ f2 M0 d, T# R
const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令3 D# C0 s( T; h: \# j6 t

+ Y4 M" ~: p& Fconst int MAX_IDE_DRIVES = 4;  z! _$ U, Y5 J2 A6 j

- B) Z! p! i9 S) @// SCSI专用变量3 C# M9 O2 g- b7 H7 Y# ]
const DWORD FILE_DEVICE_SCSI             = 0x0000001B;) H9 P# G) ^: l) y: Z- m! B
const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);0 b# u2 E4 m; V+ H; b
const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition$ s6 B& k# s1 x. u
const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;/ ^- n1 v3 `) f0 g+ u! M
# M2 S- H0 l( e
typedef struct _SRB_IO_CONTROL9 ~  V. l) e7 e: S# J
{
+ h3 ]7 G/ _3 {  b2 e    ULONG HeaderLength;0 n& b1 p; Y6 H2 X4 I" S6 |
    UCHAR Signature[8];
1 x6 |$ I$ M. n4 r; S: m    ULONG Timeout;
! u5 W* b2 ^7 m: f% B3 ^7 Q. l5 c- J    ULONG ControlCode;
6 y4 m' h9 i$ }- K/ F9 |9 Y! K    ULONG ReturnCode;
# a1 t6 I' E. F; O( H. n    ULONG Length;+ Y& }( h  }, _3 z
}SRB_IO_CONTROL, *PSRB_IO_CONTROL;+ X' w  D, v2 X

# o9 Z. r1 A9 N4 H" O2 O& _// 读取的主函数* M/ e' \6 f6 n3 P# v
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);* Y; U% f2 z* l+ ]0 h

% T, w  ?, k0 ]) [  ~  A4 P// 辅助函数
3 x" ]+ j4 y, D6 {: x2 l- p2 Zchar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
# l& A; E* ?; v0 |/ w* L, q// NT/2000/XP函数# |% Z" k* ]5 @
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
8 F  b1 h$ o7 z/ j9 q$ [bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
) h  W$ m+ _; S7 @, s. k        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,3 n/ Z# M3 Y4 c4 n, d$ n8 ]! q% ?
        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
8 F5 e0 O6 x- Y! K8 C4 X// Windows 9X函数7 W( e6 w, r6 d5 |3 @/ y; n
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);$ X6 j, F9 G  I
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
+ M" d( S, f* a+ D8 i: l        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
- Z! I7 c& n) r  g7 y7 L
9 b7 R6 W- n0 R9 U// SCSI读取函数(for NT/2000/XP)+ H2 @+ Y5 m9 T, P& w
String __fastcall ReadIDEDriveAsScsiDriveOnNT();
) X" @/ m" l5 e: [//---------------------------------------------------------------------------
( ?* Q' C: @3 ~' M// ReadPhysicalDrive
& k7 S; u) M4 b3 _, [1 {3 qvoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList): E2 |" J3 x) ^
{; r- f: g& d% _, w
    switch(Win32Platform)
* W- c+ l" Y7 o% I  b- S    {; X' R7 I) Y: C3 H" N
        case VER_PLATFORM_WIN32_WINDOWS:
# \( V2 B: a8 f) V" [: K( Q; ^            ReadPhysicalDriveOnW9X(pSerList, pModeList);
0 y- `  L2 a/ b# a& I+ L  n            break;
& y9 U- N/ v' F" A7 ?9 v) `" Q, p        case VER_PLATFORM_WIN32_NT:- O1 I, z8 g8 R. I2 G! V9 N% k
            ReadPhysicalDriveOnNT(pSerList, pModeList);8 r4 ]; ?' J$ }0 p- n
            break;
3 i  g/ c, j: o& v. b$ L        default:. K& W( `3 H, U6 _
            break;
5 q5 d$ Q" @1 V. H6 `/ u    }
- r" T) ~6 s5 ~9 b}8 v9 n/ F/ z3 e0 r
//---------------------------------------------------------------------------
! m6 U0 V; F- a" }1 A4 c// ConvertToString
9 F# S/ P, S1 _* n2 |char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
9 \+ }, H6 ?* E9 [{; `9 |4 R! @& ~7 u) {
    static char szResBuf[1024];
- g+ ]: W$ i& I4 D0 K    int nIndex = 0;
/ [5 H- U" p: Q2 S    int nPosition = 0;
7 C  A9 M. O% l1 F7 q- w/ `$ D5 g+ r: O# r+ O9 }
    // Each integer has two characters stored in it backwards
- b9 F; a8 c( ^/ d    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
+ A) Z1 g: W- F! Y    {
- y5 q7 L: ^" c9 w# @( m        // Get high BYTE for 1st character4 M4 [. ?* |9 n2 e
        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);7 ^* A" h( |2 c: e$ a* p  d! \% M
        nPosition++;
) X! B* C2 Y0 g: a  X# s! ?; ^7 H0 }* @2 H- V- {
        // Get low BYTE for 2nd character: s7 G* r8 D: y. c3 J  z
        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
, S3 N( s% p& D5 U8 D% I" @2 g        nPosition++;
* B, Q6 Y% y, Z. o; L    }
% Q5 |) Z! C) v1 Q6 {% e) O3 U
0 p" Q" [2 \( f5 q2 J    // End the string
5 G5 i/ w- `: {1 a9 D2 q    szResBuf[nPosition] = '\0';
" g, G; H" p" P9 U. M4 @% A8 H
. ?/ Q1 P+ {" \# w( i/ @4 h    // Cut off the trailing blanks
. K' `  L. \) g, K( X8 R    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
; ?% }4 ^* D2 r9 {2 d2 d. M; e        szResBuf[nIndex] = '\0';, @$ _- K5 c1 ^! I# i+ }6 d
( S7 }0 q0 z. }' u; M& N$ s6 n# Z/ X
    return szResBuf;
7 I3 m0 j' f' ^5 ]: B}
2 E7 V! b8 B, }  a- e0 y//---------------------------------------------------------------------------
" b# J: P% a  c  z" ~" y$ \// Winndows NT4/2000/XP 代码1 d0 t( {4 H/ j9 M4 u. w* t, s
//---------------------------------------------------------------------------
4 G) x: N/ v7 {// ReadPhysicalDriveOnNT, ]8 {! [/ o2 s  N% f
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)# A, L) ^: }: `0 ^+ I" L/ Q
{8 U4 ^% @" {1 ?* b: f
    // 输出参数
  t, `. O5 {4 g+ B8 j/ T    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];1 G! O$ h1 U" d

0 I: k; m1 b7 p' Z; Y' ?' n    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
( |& ~7 Z& X0 |# [* I# Z    {( I6 n8 O/ Q. z! A( L
        HANDLE hPhysicalDriveIOCTL;6 ^: t. p, x1 y7 {& l6 e1 X0 S7 _
        char szDriveName[32];6 w3 v; u- ]- q- K

7 P* h( N4 E, t* P2 W9 A        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
- C$ E" O& ?8 c, F- u        hPhysicalDriveIOCTL = CreateFile(szDriveName,3 s; D+ R  J6 Z& E$ F$ [
                        GENERIC_READ | GENERIC_WRITE,
% ~8 D3 M$ ]6 z  S9 f                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
! ^. G0 }" s5 b                        OPEN_EXISTING, 0, NULL);2 b- N5 a$ u1 ^  |

  t5 o4 z7 i1 r1 w/ g  e        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
3 V+ n3 M6 B; Y        {) r2 F# k$ y) ^/ ~7 }
            DWORD dwBytesReturned = 0;$ X: b% l' {% ^- ^
            GETVERSIONOUTPARAMS gvopVersionParams;
, n9 z1 d5 D' @! g  }' K( U' u1 B5 B" V6 i
            // Get the version, etc of PhysicalDrive IOCTL
' I! c( P3 x* {            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));9 E; Y3 ]5 U% e8 W

! g6 J- A/ n$ ]# v& x8 k) a9 u            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
; P  z! n1 K( ?) A" O7 H7 H                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
9 }1 F$ w$ R) B! K) x) y8 d                    &dwBytesReturned, NULL))
$ |: O; ]: s8 \; I6 w  P% ^            {
" j8 m) Y0 _$ F% C                continue;% B0 M* ^# o' w/ o7 Y( j  r
            }
3 ^4 d1 P' r: m; q" x& ^" D" h2 z. X4 g2 Y* `
            if(gvopVersionParams.bIDEDeviceMap > 0)0 j- g+ c8 j, {* \4 E  z1 {$ K
            {" e8 X/ D: h: `% B/ J+ i* `
                // IDE or ATAPI IDENTIFY cmd
2 [: c" \5 f6 k8 `  W                BYTE btIDCmd = 0;) o2 _. u7 p* n3 q7 k
                SENDCMDINPARAMS InParams;$ X9 L5 T9 L* O) F- Z' K
                // Now, get the ID sector for all IDE devices in the system.
/ q( r  w' i2 f) {* E( s                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
% b7 p* E: M6 W3 k                // otherwise use the IDE_ATA_IDENTIFY command' V" h8 @/ T/ v" u2 k7 ?; }
                // 具体所得结果请参考头文件中的说明
) I! n& N6 i2 [, Z1 z                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?& I$ L  q8 Y" W: b" p- U, j
                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;) X( V5 E9 S( s* `- |
                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));& A0 J* T0 Y- S. Q3 [7 v. S! ^
                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));6 X6 w$ e& \8 ]5 g/ k$ e/ m

, [! ~+ F# ]9 J/ g                if(DoIdentify(hPhysicalDriveIOCTL,. }; e) X: K  N( e& i" b2 S
                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,# F: m: _' x  P% q7 S
                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
' C  h$ h! I, z  z4 |; d                {3 }- I2 u- J# e9 [1 k
                    DWORD dwDiskData[256];# I; t4 u4 n: ]7 l) k. `& ~. S
                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件4 _4 k- k$ P0 o2 {
                    char szSerialNumber[21];! B  A: M" J; D& ?. U1 \2 N7 K4 P
                    char szModelNumber[41];
; N' y% b! I* B- ?, b. Z! i' _6 \
                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
* D' V0 M) W# }5 A. j. _% d                    for(int i=0; i < 256; i++)
, K5 p, h; d7 p. Y$ G                        dwDiskData[i] = pIDSector[i];
5 g  Z" u3 P% W& R" s% p7 W) _                    // 取系列号  w+ n# K- }$ k, J5 `" {
                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));1 L4 n$ ~) o8 ~: y
                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
+ u" J7 J5 z- Z
6 v6 l+ f9 Y% |1 f% e/ ~' {0 T                    // 取模型号
( |% g3 n% L) H' h: y& E                    ZeroMemory(szModelNumber, sizeof(szModelNumber));
4 n8 P+ ?" e* D( e$ f                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));* j- l" b  O' I4 W8 I6 Z% ^
. F# G5 ]& X8 Z9 x& `. A5 _1 y
                    pSerList->Add(szSerialNumber);+ G& p4 F1 j" X# {* x
                    pModeList->Add(szModelNumber);$ _2 |$ I% ~1 ]) T
                }
) w3 B# @0 I& ]% C- p4 }* h            }
! q% c2 m& L0 y7 g% q' U            CloseHandle (hPhysicalDriveIOCTL);
: _9 \9 b* @' I$ L. v        }
/ I/ ]5 F' I: h2 d: Y: }    }
3 O& B* @3 n9 k" c" l: D1 \}
: R0 y5 A( R4 I9 ^# R3 F' e//---------------------------------------------------------------------------
/ A6 q- a' N0 r// DoIdentify
. K  Z! p& u- m8 i% S$ B9 Y1 hbool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,7 |0 P3 x+ s3 k, l1 z
              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,2 w7 I" @2 k; p: L$ `
              PDWORD pdwBytesReturned)! n2 {& C! b" h/ |+ X
{; Z8 N8 @) e# F" i
    // Set up data structures for IDENTIFY command.
, M. t' m% h% @# x# t/ o    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
: @' Y% ?1 [' `6 \" H. K1 c- Q! ?    pSCIP->irDriveRegs.bFeaturesReg = 0;
! f0 ?. Z- Y. J    pSCIP->irDriveRegs.bSectorCountReg  = 1;4 ~9 G$ B9 A* l2 F2 R5 n
    pSCIP->irDriveRegs.bSectorNumberReg = 1;
7 L9 p. F% `2 `. w& k7 d3 x$ K: U    pSCIP->irDriveRegs.bCylLowReg  = 0;+ u+ u( j3 `: R8 Q# N
    pSCIP->irDriveRegs.bCylHighReg = 0;0 O0 C7 W* B1 O0 Y9 K5 v% D0 Q0 m
7 C) n, w" _3 o, I0 G
    // Compute the drive number.(主盘和从盘所对应的值是不一样的)
& D& }1 C4 f/ [. O    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;; _7 j  _, d3 v! p7 V1 v" D

1 {/ h8 H$ A* N0 `& ^# t    // The command can either be IDE identify or ATAPI identify.
0 {9 ~- A3 i( [& Q    pSCIP->irDriveRegs.bCommandReg = btIDCmd;; _6 O! |0 ]+ H& i1 B' ]& x+ g
    pSCIP->bDriveNumber = btDriveNum;
/ j8 H& U5 }/ |+ m( \( n% Q! l    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
1 ?' \% }+ E* J; E2 T9 \4 N5 @. R
, F9 B$ P! C% k: _% A( H    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA," \( U9 @8 P3 N" c. n" Y+ V" E5 F
           (LPVOID)pSCIP,
) u( P0 s' q# s! ^$ |           sizeof(SENDCMDINPARAMS) - 1,3 h& E* `$ F0 A0 n% N7 f  h/ u
           (LPVOID)pSCOP,3 {5 R# t5 x: L" `% `# f& W5 `: Q. D
           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,/ W' i( q7 W  S1 [
           pdwBytesReturned, NULL);* O! c( f$ Z) z5 j
}
& P% D  |1 l# T0 E//---------------------------------------------------------------------------
- X* S+ d0 o! p8 M// Windows 95/98/ME 代码
1 T& d4 s: c# z0 z: E9 y//---------------------------------------------------------------------------
4 J2 `+ Q! d5 X) }! X& U! l// ReadPhysicalDriveOnW9X
' p' M7 E9 K! d* L0 F2 p3 p: hvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)3 D, S4 L" g$ E7 R6 \0 r  a* E; F5 _
{
! p( `7 K! F2 a# J! ^8 B    WORD wOutData[256];
- p9 z9 a3 \: a! I" E    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);( p% T( N2 I. [: v# ^+ ^% f
* j2 c& T- w4 P4 P
    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。4 z  h0 [/ t7 Z/ d. _; e+ C7 g
    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以$ s7 b  A# P* ~; i' w! |. D
    // 避免蓝屏的出现。(期待高人能指出原因)
) c. W/ m- f. n. f0 N    for(int nDrive = 0; nDrive < 8; nDrive++)1 M7 q5 _( L' Y) Q
    {
6 _. x' X  t6 K        WORD dwBaseAddress;2 _: x) V8 B4 g+ O
        BYTE btMasterSlave;         // Master Or Slave+ K! o" [$ ]" o! h  [( l9 A
        bool bIsIDEExist;$ @" _( c/ A* i# B( f
        bool IsDiskExist;$ g" g- b8 B* ~9 Y( }
$ x8 N  b" ^9 u' S! k$ {( ]
        switch(nDrive / 2)
" o& q; @! G3 c. M        {
% _  l# ?5 e+ ]. `7 H3 m" u            case 0: dwBaseAddress = 0x01F0; break;
4 n) d5 f  Y# ~- P' U5 |3 s) U            case 1: dwBaseAddress = 0x0170; break;
* ?9 Z7 h! {4 y4 H1 U9 Y" n7 M# l+ i5 q7 h            case 2: dwBaseAddress = 0x01E8; break;4 B% L8 f) \3 U) \
            case 3: dwBaseAddress = 0x0168; break;
! h+ j; x6 C: S2 q0 h# l4 Y        }+ a5 \6 t/ P# i0 O" ?

) ?' R) B( {8 x/ C0 o; J        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
# V1 X4 F+ `7 p! Y& i( j
. S3 j4 Z+ P" u) T! t% w        // 进入Ring0
3 Q" Z9 ^- n" r' t: f        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
7 v1 A& W6 w! k7 z                bIsIDEExist, IsDiskExist, wOutData);- ]# S9 B0 m) f
    }7 }$ g: {- A( v) F* _3 Q: F( v4 L
% W0 m6 z; t$ R$ W1 j
    // 开始读取
; f' A* R, e% |7 F5 `    for(int nDrive = 0; nDrive < 8; nDrive++)$ D: S3 t5 R  y: s# M$ K9 X  w0 z
    {
% k, C% H* x+ j, S4 c        WORD dwBaseAddress;
1 R7 E/ w& p; U" K7 M        BYTE btMasterSlave;         // Master Or Slave
! G4 H1 n. i' k1 t4 h9 w, y        bool bIsIDEExist;
( ?+ u' D, G) a) \        bool bIsDiskExist;$ u4 Y) a  t; e( X* P1 Q& j
        switch(nDrive / 2)
  Q; N2 Q7 F6 T; p- \+ {3 [7 D        {
) s* n6 Z( h. q            case 0: dwBaseAddress = 0x01F0; break;
9 f( _7 q* s. n4 o- \3 b# I8 t            case 1: dwBaseAddress = 0x0170; break;
$ G) P1 F; U' M            case 2: dwBaseAddress = 0x01E8; break;
. F5 k7 L% E! W# s" ?. l, Z6 |. ~            case 3: dwBaseAddress = 0x0168; break;9 l+ |: ?4 k' E8 n' r& J
        }1 s6 x. n5 M0 S% [% J) A

6 L  W/ I+ s) t* d5 }        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
" R' x. k* E  s2 Q0 \% W* t5 K6 \: C0 I( G7 U
        // 进入Ring0
5 u8 K3 w" ]6 p) F8 h0 J        bIsIDEExist  = false;+ U0 i4 Q0 R3 i! a, K, U" E
        bIsDiskExist = false;
# m* I; k1 S) E; X( c        ZeroMemory(wOutData, sizeof(wOutData));
5 _: N/ b" o* P8 j* ?& d4 N$ F; z! c4 O2 `3 d/ Y
        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,( C6 U( r0 V9 E3 c
                bIsIDEExist, bIsDiskExist, wOutData);) w3 Y) V  ^5 k
% {: W  \6 N( i" k- L6 R8 h- @, F
        if(bIsIDEExist && bIsDiskExist)% ~- J% M# a6 ~6 P- e" ^/ n
        {
$ `# Y6 Y' v; o8 L2 @            DWORD dwDiskData[256];
) O4 G* M  B7 {% g/ l1 A" u2 g- e            char  szSerialNumber[21];
* M/ l8 \6 `( k# T% v            char  szModelNumber[41];# T* K, G% e( I5 u! N! ]; u, {

, u5 V8 j2 B9 X( X7 C7 ]; T            for(int k=0; k < 256; k++). H# W9 I9 z1 ~8 H+ U8 H6 E
                dwDiskData[k] = wOutData[k];
! ~& N5 O6 N! [
  ~# j& I: R3 @# N# |            // 取系列号
! S5 U$ V' b3 K+ o            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));+ W( r* o! Y3 d$ r1 N( ?
            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
3 ^) |5 G" R# X( m8 b
# M) Q4 q: W& k0 _            // 取模型号1 |4 r' {, l" D5 C: w
            ZeroMemory(szModelNumber, sizeof(szModelNumber));
' F+ X) X  ]- @: k5 H+ p4 N( C# Z            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));* b8 A3 y, v: t8 n9 a

' R4 @2 \7 i5 \7 |            pSerList->Add(szSerialNumber);
/ x7 d% V( Q5 v  ^, C/ i            pModeList->Add(szModelNumber);
6 w& K: S/ [1 }9 }7 k        }
' s: W5 p9 C3 h6 s( N0 o    }! L# r% G% r- B1 r6 Z% o6 Y- S2 a1 Q
    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);8 z4 J3 s  X: N( m0 @' j2 y
}- j4 x! D2 R( W+ R' U9 ~
//---------------------------------------------------------------------------1 p% N2 D6 p8 ~1 N7 e
// 为防止不负责任的转载者,在此注明原出处信息,请见谅。( o3 `* r3 n% r% A: e
// 资料收集整理:ccrun(老妖),欢迎光临C++Builder研究: http://www.ccrun.com
& ~  G, q& q3 T8 z  [; v//---------------------------------------------------------------------------+ L3 T0 k2 s0 o# _4 {! D
// ReadPhysicalDriveOnW9X_Ring0()
) r3 Q) {  g$ e2 x# k6 j; {; C//1 x5 G- `. G* Q9 s! T
// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h+ H" Y0 e  b; z( h- s
// btMasterSlave = Master(0xA0) Or Slave(0xB0)
" K" V; o2 l/ L- [1 s2 a/ {//---------------------------------------------------------------------------
+ U4 @0 S8 Q) t, K( R* Lvoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,' g- c  ^! h/ n( J: T
        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)( b. K. [' S$ f6 G# S5 J
{
& X7 l' ^5 K8 @. `    BYTE  btIDTR1[6];" X  J  P8 x" I. n- P
    DWORD dwOldExceptionHook;
. N- P9 y8 l9 t# N4 L    const int nHookExceptionNo = 5;% F/ W! Z7 B$ ]6 d4 k4 A5 `2 Y+ q

) R8 H6 [( b" N. F# K    BYTE  btIsIDEExist = 0;
! r  @2 u& s( {2 j! T' p1 P7 Q+ i    BYTE  btIsDiskExist = 0;
6 [  u5 |6 D: D; }6 g    WORD  wOutDataBuf[256];
) l1 F' w1 a2 E: y* L
0 {# u) g2 e3 @' m/ U: b  ^: `( G2 X    BYTE  btIsFirst = (BYTE)bIsFirst;- P, V  f6 z% W

% m2 v1 i$ `3 i4 \- _6 ?    const BYTE btBit00 = 0x01;
" U. n9 p5 L; \! E$ Y) O    // const BYTE btBit02 = 0x04;
7 K/ C6 S, U, W5 D4 m9 `    const BYTE btBit06 = 0x40;
& a0 i- e9 k! h" n    const BYTE btBit07 = 0x80;, t2 f7 G1 N$ ~- E
    // const BYTE btERR  = btBit00;
7 b7 B: H0 f) P5 W    const BYTE btBusy = btBit07;
5 g8 }: [, F4 B    const BYTE btAtaCmd   = 0xEC;, v2 ~; A+ K- ]5 d9 R( U
    const BYTE btAtapiCmd = 0xA1;! I; y+ {; z* D# M" c0 V# j
2 i; G- K' R, h. u+ I: ]
    __asm
7 P; S9 Y" j9 p& {$ q    {/ v. \! u( v8 y. `3 z. h6 T& l6 ~& x
        // 必须先执行这条语句: D  K. D/ e: ^9 _  C
        JMP EnterRing0
' ~* Q% Z; i# `: f, _; y7 A8 y. d0 i# k+ _3 _
        // 定义过程3 K! c9 ?' a! n6 b: d6 t
        // 等待IDE设备直到其不为忙为止5 s  F- n* |! s. a  t
        WaitWhileBusy proc
% v7 @  ]: `, P9 A' n% M
! \+ ]& ^3 A; I        MOV  EBX, 100000  d: `, v: J/ H
        MOV  DX, dwBaseAddress9 {  g9 @" y" B2 ^! V
        ADD  DX, 7
/ l  g1 S0 H5 Q" |- @' l- t7 A* r4 U: \' I5 ?! ]6 \
        LoopWhileBusy:! P& |' u! N0 M- a) Q$ c5 o

( h7 r7 Z" C% H! B6 }- d+ p        DEC  EBX
! W9 S/ ~+ c& a$ I. w        CMP  EBX, 01 E4 {8 P! r: {/ S  ^  r
        JZ   Timeout
( O- H; |' p! k) I, E3 {; L, M2 M5 ^        in   AL, DX
* _* w7 L$ _5 m" t4 j( C1 Z6 q        TEST AL, btBusy* i. J# j( m1 ]: p, p: u
        JNZ  LoopWhileBusy
# J* M8 w8 Z5 {' D2 I4 R        JMP  DriveReady( I$ d5 O  h- D* }

- ^! N# i, t8 a8 _        // 超时,直接退出
5 j& {3 G* A, ^9 {) D* t        Timeout:! m5 [* V  i% X
        JMP  LeaveRing0
. T- ?4 h. G) o- N6 S        DriveReady:$ r9 E6 @: q5 q& N+ \: X9 S$ q4 k0 l
        RET, ]: z( B, N/ q2 j  Q; \" [
        ENDP   // End of WaitWhileBusy Procedure, v9 o/ ?6 X# L$ [4 _
  k1 ?; E& A1 [
        // 设置主盘和从盘标志
( C: f' S2 E* {- _        SelectDevice proc4 |0 C1 l) a+ `" I2 ]
5 m+ v- t/ i% @( O  l
        MOV  DX, dwBaseAddress/ Q7 d1 y7 t- F1 P' L1 R7 t) T2 q* w
        ADD  DX, 6
2 N6 q$ g7 Z7 k+ n& G. T        MOV  AL, btMasterSlave) U- A  `  M/ k8 R( l, i
0 U' U9 ^1 S8 T, e1 S( O9 ~; k
        out  DX, AL; Z7 T: Y6 h; O
        RET1 ^) m, H. ^- v5 {( M
3 `, F# T- D) e) K; N% y6 `9 v
        ENDP  // End of SelectDevice Procedure
: I+ ~; _" b0 r/ b* A. K! w  z; x7 h- \4 ]& _" i
        // 向IDE设备发送存取指令* A3 u. ]7 E9 u
        SendCmd proc# z  `* V& r4 f( Y$ |* d; m0 G
/ P, [4 i4 m4 ]; }0 c( _9 L
        MOV DX, dwBaseAddress, V1 G4 ]6 \( M1 q1 k, [- ~
        ADD DX, 7
5 g5 N" O$ R5 F9 E        MOV AL, BL // BL是主从盘标识,在过程外设置
6 x! c4 X3 t3 n. z! x        out DX, AL: @9 T7 N3 k7 t4 ]$ i- A, y
        RET# u$ p  o; x* ]9 B+ V6 w* e7 ]
        ENDP  // End of SendCmd Procedure
$ j0 }( P4 C: {$ @. ^1 q! k, P4 C' h' X  |6 [
        // Ring0代码: h5 o9 ~/ A6 f. F: s/ \
        Ring0Proc:
/ O# m# M0 }8 N4 f3 g6 s1 E        PUSHAD
3 N$ ]- [; n& ~& T& V- x2 j' T        // 查询IDE设备是否存在7 q5 l) D# m* {. L3 |2 k$ J; x
        MOV DX, dwBaseAddress
0 G! R& [& g# l7 N! I6 U, u        ADD DX, 7
+ ~! h: k" W+ p. `/ S( |        in  AL,DX( h. S* Z: S& s8 g: b
+ D2 n7 W4 a3 x/ K
        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
- P$ U8 F7 ~* ?" O$ P        CMP AL,0xFF
6 h& g) a2 R4 b' D% H7 f        JZ  LeaveRing0, ]" G: ]) m4 h  b1 d
        CMP AL, 0x7F
# {7 o# q$ }& h        JZ  LeaveRing0
1 z4 Q! H. {0 q& x2 U" t) W2 c3 X- L: z! q: ^
        // 设置IDE设备存在标志2 [: ^( K  L; f& b
        MOV btIsIDEExist, 1
3 N( ~1 u8 ]- m6 q4 M8 x* l- i  e' a8 L6 O" n
        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)6 P! z6 E/ n0 V) I! i  ~
        CALL WaitWhileBusy" b/ m# e' e5 S1 X, k
        CALL SelectDevice
+ A. @( V5 K; V5 [3 y1 V+ H& d
; }( K* A/ v  B5 m6 m        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏7 r5 N+ ?& a- J7 p
        CMP  btIsFirst, 1
7 ?) J, |1 t  d7 a6 T        JZ   LeaveRing07 {. u+ L1 d* X! @+ w; p- t
4 ~# \2 {% ?* d8 c$ ?( C% `- q1 R' Q" e
        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???8 n! k$ B) m) ?  R6 M' D0 ?5 E
        CALL WaitWhileBusy
6 g$ X# U& I2 {) D" |; l* s
  `2 f% h/ C$ s3 @        // AL的值等于cBit06时,不存在驱动器,直接返回, Y: y8 h4 }* ?$ K( j2 l- k5 g
        TEST AL, btBit06/ D- F" z6 S- [2 d! U
        JZ   LeaveRing0' q4 C7 j) O  ^1 ?0 A, [9 n
: l$ K. K! S" m; z1 N5 _
        // 设置驱动器存在标志$ k  G, n9 ?# [3 w" v0 A
        MOV  btIsDiskExist, 17 L3 Q+ ?* g  {0 d
0 y, x9 u& ?' ^( Y% V4 Q7 A$ E
        // 发送存取端口命令
1 w$ R) Q7 N! s$ @        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
* N' ]8 y+ N6 i& k        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令8 ?8 P" T: N( `6 g6 _* [7 B+ }
        CALL WaitWhileBusy! M: i+ k0 Z  j
        CALL SelectDevice    // 设置主从盘标识! b9 x$ C- K2 O* p
        MOV  BL, btAtaCmd      // 发送读取命令2 {0 O% b' Q6 m  ^* a; }! H
        CALL SendCmd# G" s2 e7 }5 v8 ^9 V! B( i, p$ C
        CALL WaitWhileBusy
5 h# N( X7 t8 c$ |. n; ]* J9 U* H7 ]6 M" H" z
        // 检查是否出错
+ e/ Y9 O6 l1 L        MOV  DX, dwBaseAddress
, [) O1 X) Y8 d6 D4 B  ]  d$ p        ADD  DX, 7% ~; v, H- F" r! o6 J0 u* v2 @  K
6 ]" S# u. v% K4 v" K' U
        in   AL, DX0 [2 o$ q1 U; A, o4 m8 ?

: N* r; D* M+ ?7 {; B/ Z; S        TEST AL, btBit005 Q& `) |8 X8 \) e
        JZ   RetrieveInfo   // 没有错误时则读数据8 n1 v. a. h+ d/ k
4 b) C& V8 G2 @* C9 {
        // 如果出错,则进一步尝试使用ATAPI设备命令8 o) E/ s& w: f* }5 @% M% ^1 M
        CALL WaitWhileBusy
6 u9 ]; Q! q6 K+ R$ B        CALL SelectDevice( |! g3 ~! S6 u1 h& B8 n+ ]. V
        MOV  BL, btAtapiCmd
; I" p$ R6 P7 p0 [4 V9 _        CALL SendCmd1 t, z: ^9 U0 y* u4 \* p
        CALL WaitWhileBusy
. W8 s  q; Q. }5 i+ C' `9 W8 R% l1 u1 a
        // 检查是否还出错
. i4 F$ ]9 V& }        MOV  DX, dwBaseAddress
+ l; O+ m5 G" P1 b        ADD  DX, 79 ]; n; I% O- H6 R3 P$ z
        in   AL, DX
; K: Q! ^( V" |  U: @        TEST AL, btBit000 r$ v, Z2 q3 T: G
        JZ   RetrieveInfo   // 没有错误时则读数据# j1 P/ ?2 M3 G
        JMP  LeaveRing0     // 如果还是出错,直接返回
2 C. w0 N* }6 E- K
6 y9 k; J. _+ Z        // 读取数据# }* r) ?0 O( D- H3 e" c9 J
        RetrieveInfo:
! a/ m8 I5 c5 U( H& `( A0 s$ `" H& t7 J) s
        LEA  EDI, wOutDataBuf
6 Y& H( X- F4 l- h        MOV  ECX, 256
3 B2 N* G7 U5 r/ v3 n; f3 g1 c5 y        MOV  DX, dwBaseAddress2 X) g0 V( q! \$ H8 z8 l
        CLD6 P5 g' ]+ l. r) z. c
9 ^; K+ Q! c" x
        REP  INSW
4 E3 d6 W) H, k
. N1 G0 d0 Z* D" J        // 退出Ring0代码
4 E2 |0 |& ^8 b* p% s& }, e2 B        LeaveRing0:
$ q9 ~+ C( v" y, H( r7 A
+ m+ B$ B. }7 M4 |: C. c6 l        POPAD( F; R( A/ v" G. \! @/ ^* M( F
        IRETD
1 {! W+ K- P4 g0 S# c' ^
. V! c) {2 S% x  P        // 激活Ring0代码" w" V# P2 S  H$ ]/ J' r  @
        EnterRing0:) K3 T8 p. R# G& E4 C/ H
# N, F- w; b: e
        // 修改中断门) g6 H- @0 M5 n! n1 l7 Y+ K
        SIDT FWORD PTR btIDTR1
' }7 `! J" |. n! i        MOV EAX, DWORD PTR btIDTR1 + 02h
( X7 p% b4 ^9 |* h7 |# o        ADD EAX, nHookExceptionNo * 08h + 04h
! a7 w% `* V+ n* d% C; F2 F2 p. H        CLI; M! E/ R& q! l% y

9 M5 |4 K" E) b        // 保存原异常处理例程入口
/ M' i; U! c8 s4 p5 ~5 a        MOV ECX, DWORD PTR [EAX]
% p. D! a3 i2 R2 t; {8 C        MOV CX, WORD PTR [EAX-04h]' t' R3 Q5 t0 ?* e& ^2 S
        MOV dwOldExceptionHook, ECX: G# N" h( b4 i6 w' I( ]4 j% L. H

2 h) y& J% t/ _( A! ]        // 指定新入口
* R. j; V  l: }+ m6 q7 m% Y, V( p        LEA EBX, Ring0Proc1 |  ~- E6 j( {9 |% n! l
        MOV WORD PTR [EAX-04h],BX  N1 N2 J, i2 u- O; D! q. K
        SHR EBX, 10h
- R3 Z0 l' Y, |9 A& W        MOV WORD PTR[EAX+02h], BX$ a( B. W7 ]: b1 e* e/ C

7 h  ]  S- Q2 ~! B! c, H6 N        // 激活Ring0代码2 r, Y- L0 s3 r6 |8 r/ B( f
        INT nHookExceptionNo
4 j* |4 H4 W) k+ F0 s6 A/ M7 M5 R; |) w
- |8 v" L2 z7 X; \! z: x. Y0 O        // 复原入口1 |0 k( S/ u7 B+ }7 ?4 `
        MOV ECX,dwOldExceptionHook" b5 w# T5 d& f- u8 n3 C& m) b" m
        MOV WORD PTR[EAX-04h], CX
& }2 {" @. l; U- _; R        SHR ECX,10h0 t9 @2 b7 W- o
        MOV WORD PTR[EAX+02h], CX  k* l8 H3 W3 ^- L; P
        STI
6 ?7 F# W1 u( r" \% f    }
* Y4 u" ]" v, _( o    if(!bIsFirst)
7 S7 J& y- D$ ?) n7 n    {* @# E1 Z3 D# R
        bIsIDEExist  = (bool)btIsIDEExist;
/ M. E. x4 `) ^  u        bIsDiskExist = (bool)btIsDiskExist;: d' r' s$ w6 Q
        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));" m6 H1 a9 B) R: |: S4 |+ B) P
    }& {  _, @" `1 x' Z7 }' K* `4 K) t
}
" d6 W. k# w$ H9 `9 r/ g//---------------------------------------------------------------------------
0 Y; W0 g& ?2 Y' \7 Z4 C- g2 }// 调用方法:. n& r1 V) ^  _/ g1 G
void __fastcall TForm1::Button1Click(TObject *Sender)( }3 c; [3 }; \6 j1 M4 F" {
{/ ?3 ?- T5 y9 o! J) K7 B
    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
* d+ j9 w& s4 L- i! x' C}$ y. P# t4 D4 J2 C$ I0 E
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-6-18 04:49 , Processed in 0.025249 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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