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

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

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

  1. % w9 B' c7 r, L' Y; @: u+ w6 b
  2. #include "StdAfx.h"
    $ p  x( g4 E( l6 ?
  3. #include ".\puiddisk.h"# r3 I8 O: n3 l  N2 e/ U) B1 u( n
  4. #define _WIN32_DCOM8 o) {1 [; o8 p4 n# C
  5. #include <iostream>, `7 H0 }. ~/ X1 ]
  6. using namespace std;
    7 W6 d; O0 Y2 O; j
  7. #include <comdef.h>
    ' y! _* k3 T6 r( M: d
  8. #include <Wbemidl.h>
    0 p% I* P3 |$ q) r! ~8 E3 R& K

  9. " v' o2 t" L+ N7 H. k. S+ Y
  10. # pragma comment(lib, "wbemuuid.lib")
    ) o+ G* A' w6 k  T% \8 a; L$ o9 m$ b
  11. CpuIDDisk::CpuIDDisk(void). d; i% u1 K: I2 x0 _
  12. {$ N8 N/ f" L1 f# ?1 X6 |7 o
  13.     GetInfomation();9 [5 [& L7 O0 ]2 j: g9 R) D  a
  14. }2 x' G4 v# g1 C# B
  15. * H" b3 G/ b9 }
  16. CpuIDDisk::~CpuIDDisk(void)
    8 A3 J: J) v) p6 b
  17. {
    1 U6 V" n: z- i- K, V; |5 {
  18. }
    9 M8 r  m& U; c
  19. int CpuIDDisk::GetInfomation(void)5 N- @# Q1 z& m- b, `1 n
  20. {
    + }' J, ~' W2 f: [1 X2 ?% [& \8 n
  21.     HRESULT hres;
    1 u( w$ p2 g0 x$ G, g
  22.     //步骤1:不是必须的,COM只须也只能初始化一次/ J: {" N6 y. e! v
  23.      hres =  CoInitializeEx(0, COINIT_MULTITHREADED );
    3 h8 I. t( M( r; C" n
  24.     if (FAILED(hres))' a9 |0 [' L; h* g/ E2 s
  25.     {
    4 v4 h! H3 z; _
  26.         return 1; //初始化COM异常:注意,COM只须也只能初始化一次: c& P. E. u/ s' x& H8 l. J' t
  27.     }
    7 \' ]0 Y4 i' U) J  ]6 Y
  28.     //步骤2:不是必须的,COM只须也只能设置一次- d9 h' K+ y4 e+ E
  29.     //Set general COM security levels
    , l, G4 [# s: z7 u* F
  30.     hres =  CoInitializeSecurity(
    . u0 Z' H- e. N9 u! m+ q# w
  31.         NULL, 8 ^0 }+ R. R" Z
  32.         -1,                          // COM authentication
    7 p  |: D  @! T5 N! i3 O4 w. |
  33.         NULL,                        // Authentication services0 p& Z% e3 X7 ?2 ]
  34.         NULL,                        // Reserved" j; c) e, x; q3 U8 M9 [6 Y' e
  35.         RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication
    $ T3 |' [& }2 M& K
  36.         RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  3 B8 H* r8 D6 R# n' w& c# {
  37.         NULL,                        // Authentication info
    7 r/ Y) m; Y' w: Z
  38.         EOAC_NONE,                   // Additional capabilities
    : i1 k/ n* J+ G2 E! L
  39.         NULL                         // Reserved( G; ~2 O9 I; H. e
  40.         );
    4 B+ {, I( @$ p  r4 @* [
  41.                       , B# d' t# i+ g$ X0 ?, F& O
  42.     if (FAILED(hres))8 P1 h( c* V( x$ O- C# j
  43.     {
    2 M- J* X3 A" O: r6 \- m* P
  44.         CoUninitialize();0 g; D  P3 e4 k9 W6 |/ y/ W
  45.         return 1;                    // Program has failed.
    * ]( g; B$ x( L
  46.     }
    * C- `- g* [; N5 k
  47.    
    + Y& d2 U- W) v
  48.     //以上不是必须的,若已有“::COMInit();”,则要跳过
    - e& e5 }) @: K& w
  49.     //步骤3: Obtain the initial locator to WMI
    . ~; v' H, N9 w6 |, G
  50.     IWbemLocator *pLoc = NULL;$ B* j2 W! U& h1 z$ G6 t6 B- @) |0 W
  51.     hres = CoCreateInstance(
    $ Y( _7 ]6 }3 |
  52.         CLSID_WbemLocator,             1 _8 f% l' b( T# S
  53.         0,
    , _* a; n; i- U9 }* ^$ D$ T
  54.         CLSCTX_INPROC_SERVER, 9 v( z$ I6 `# b! d& o1 a
  55.         IID_IWbemLocator, (LPVOID *) &pLoc);/ U" |0 G0 A) B4 {/ S" v

  56. & y) k* b% h$ ]6 |3 i
  57.     if (FAILED(hres))* @, m. F! X# X: b+ C& U1 _( n
  58.     {4 |( ^# y0 Y; ?. C, Q4 w
  59.         CoUninitialize();# _% R$ g: q6 f$ x. _
  60.         return 1;//Failed to create IWbemLocator object0 ^8 X$ N& T* n  c! H
  61.     }
    5 c$ C- M; R2 G2 A% w7 A

  62. - G9 `5 j+ d- Y5 T( A1 U
  63.     //步骤4:Connect to WMI through the IWbemLocator::ConnectServer method
    1 u2 _. K* |5 T  d
  64.     IWbemServices *pSvc = NULL;
    3 q* L+ L5 @; i$ c/ _- G4 Z* T
  65.     hres = pLoc->ConnectServer(
    7 Y( g5 t$ h5 z/ M6 N
  66.          _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace
    8 r0 r( b4 _" A5 A3 Z1 ]) G+ f
  67.          NULL,                    // User name. NULL = current user
    ! E/ w+ \! |. c$ `
  68.          NULL,                    // User password. NULL = current: Z% Z, _! w: a5 Z8 Q
  69.          0,                       // Locale. NULL indicates current
    1 F: I/ C$ K6 S6 d
  70.          NULL,                    // Security flags.6 e0 h0 A8 o/ B/ U. U
  71.          0,                       // Authority (e.g. Kerberos)& F" [6 `1 d. i2 g
  72.          0,                       // Context object
    ) c. }4 j. u: u8 E: v, D8 \; X
  73.          &pSvc                    // pointer to IWbemServices proxy
    ) M, T2 u" n6 f4 x8 v# y- B( }
  74.          );
    2 ?9 c$ G0 L/ U
  75.    
    " C4 Z5 s1 j- x- F+ s' {
  76.     if (FAILED(hres))3 S) ^6 U; B+ r8 i! H4 S' b
  77.     {- _3 q% c8 q3 i1 Z% U$ H% l
  78.         pLoc->Release();     ' Y' r/ t) R: V$ Z$ m
  79.         CoUninitialize();
    * J) a+ F7 ]5 }! `' k
  80.         return 1;                // Program has failed.- H( a. S' ]. y( w
  81.     }
    1 I( K2 F) `9 C1 F0 s# ]$ V
  82.     // 步骤5: Set security levels on the proxy% t# U- U; \- T& ]
  83.     hres = CoSetProxyBlanket(
    ; U! I0 s, j( G' f* C( u; ?) f% i! P
  84.        pSvc,                        // Indicates the proxy to set
    * D- U3 M& q, I' f* W
  85.        RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx
    , q' y( C1 m/ [) z0 F* j# u  |3 l
  86.        RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx
    7 w$ _% ^  E* i3 X  {1 K" f2 M2 N
  87.        NULL,                        // Server principal name
    # a' l6 |& W: v5 T# J3 f
  88.        RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx
    ! D; `8 v- Z# W: }6 @$ J/ Q
  89.        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx/ g, i. _, E0 @$ |1 k
  90.        NULL,                        // client identity
    5 ], J) p3 q3 _3 s
  91.        EOAC_NONE                    // proxy capabilities 2 f+ v6 F& B: a  h
  92.     );0 X' d- V2 `& b% P( d& R
  93. " P1 i! C) O& y% o8 Q
  94.     if (FAILED(hres))
    8 ^; {: e, B6 v$ L/ l$ @7 x
  95.     {
    / x, H) w; H- ?/ ~6 k1 Q
  96.         pSvc->Release();
    + j" A" ?5 o+ Y( T3 U. r
  97.         pLoc->Release();     
    ' s/ a! ]/ f8 I
  98.         CoUninitialize();, |" S2 o% U; J/ B% D' ~$ t+ ?3 G
  99.         return 1; 7 c+ A, Z5 `5 b, L6 w' q
  100.     }
    / V8 u! f& x9 g- S
  101. % J0 S' `+ m9 I  Y- p
  102.     // 步骤6:Use the IWbemServices pointer to make requests of WMI ----
    ; K1 S! ~1 q+ W- l/ K* a7 q
  103.     IEnumWbemClassObject* pEnumerator = NULL;; |( V& x: i5 I" v
  104.     //计算CPUID$ s* `- c2 Z) t
  105.     hres = pSvc->ExecQuery(
    6 Q0 M" N) v6 R
  106.         bstr_t("WQL"),
    * ~. @/ B; f: c/ M6 K
  107.         bstr_t("SELECT * FROM Win32_Processor"),//Win32_OperatingSystem3 o* C* U7 B5 o  I6 r
  108.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, ; d1 e$ V3 C4 h9 N- Q7 X
  109.         NULL,5 w$ a* v. c/ ^9 z5 {6 J" G  y
  110.         &pEnumerator);( S. s5 [6 Y: @! }+ N* X
  111.     9 ?7 P$ a+ E( ?. s9 n9 E. D: U2 a' W
  112.     if (FAILED(hres))1 K" ]2 R( E6 J7 p; }0 c9 W
  113.     {; f3 y1 t2 I* o8 [+ c* Z( i
  114.         pSvc->Release();( c- \+ U5 V7 L
  115.         pLoc->Release();6 i7 x  _- x' b! q( n
  116.         CoUninitialize();
    & H. L( W1 f/ f. R' q0 y% k* d
  117.         return 1;
    ! Q$ ]7 g1 j' C# \
  118.     }
    " i" e0 |; O) `4 j/ v; r
  119.     // 步骤7:Get the data from the query ! x  s+ D* l2 p! J/ J! z7 K$ }
  120.     IWbemClassObject *pclsObj;
    3 |: W7 Y5 ]+ v( _$ q9 s& ]
  121.     ULONG uReturn = 0;
    ) j* g+ `9 F# z8 O) l/ i
  122.     while (pEnumerator)
    ( ^1 J# h) V/ M/ r
  123.     {4 P7 q: [/ G3 B( t) D/ b2 z
  124.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
    6 m; H/ G$ I! F6 A/ ^
  125.             &pclsObj, &uReturn);4 I$ q, s0 t4 x2 F
  126. 6 F* j; ]- G/ B2 I/ J% f, L
  127.         if(0 == uReturn)/ d# a2 ?; H/ D
  128.         {8 L! Y1 \% x1 W$ c
  129.             break;
    8 n- ^% ^* i8 n! C6 X# y1 A9 B2 _
  130.         }+ N0 T! R( S% B5 t: p4 P# G  y
  131.         VARIANT vtProp;
    * _5 I* C$ r9 X( Q" Z/ Q+ K2 P! s
  132.         VariantInit(&vtProp);
    : v/ L7 W. d. A, Y
  133.         hr = pclsObj->Get(L"ProcessorId", 0, &vtProp, 0, 0);
    5 N- I* A$ W0 r# p/ A- t  Q6 s, k, G
  134.         strProcessID=_com_util::ConvertBSTRToString(vtProp.bstrVal);//strProcessID:类级变量+ e, p. p% v* @& D- X! x
  135.     }
    8 @/ `% ^5 |7 O7 n4 c$ |% ]0 c

  136. ; i) T) t: P8 Y; a  O& c
  137.     //计算硬盘系列号% i  {$ I( I- Y7 T" w( j, z  c
  138.     hres = pSvc->ExecQuery(
    # o3 H# r8 c- ~1 R. l! J3 H. s
  139.         bstr_t("WQL"), - E. e4 s8 C8 K
  140.         bstr_t("SELECT * FROM Win32_DiskDrive"),+ b% D5 Q' j/ H- ~: k, o3 U5 G
  141.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, . Q, x, s6 K* ~- X& @7 p- N; i( M
  142.         NULL,6 @: X/ j- |) `9 c" H# U$ [
  143.         &pEnumerator);; o$ j. _$ y! h$ t1 D1 c* I

  144. ! M* @6 k: j" _- y$ P$ H
  145.     if (FAILED(hres))9 b; U, H* V5 Q1 ]* I/ A
  146.     {
    , x' N# l0 d) ~, S! c4 _
  147.         pSvc->Release();1 Y6 {' ^" F& B( x- c# R" N
  148.         pLoc->Release();
    / ^3 ^: q% D! t
  149.         CoUninitialize();, n# k) q7 o- v
  150.         return 1; + G& M1 v  m" L3 h7 v6 M
  151.     }+ I) R7 c; ?$ B6 C, \& u
  152.     while (pEnumerator)" d& u* U4 J- O
  153.     {2 Y3 F9 B* ^# B
  154.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, # N2 |! d5 o! r
  155.             &pclsObj, &uReturn);) |) K+ s/ Z8 s! }
  156. . x0 s2 T% v7 k: G5 r# f
  157.         if(0 == uReturn)- A' _; X8 l5 V2 V
  158.         {- y3 F& q. z8 n( S9 f3 B3 i& q
  159.             break;4 V# P+ G1 A8 S( D5 t. }. \) H- C
  160.         }; C$ G& h# u2 T6 G( p( @2 R

  161. 0 v( S8 p4 `3 B+ h# e
  162.         VARIANT vtProp;0 G  L9 j/ P, [8 G2 V& x
  163.         VariantInit(&vtProp);
    ' e1 _# @6 C! n
  164.         hr = pclsObj->Get(L"PNPDeviceID", 0, &vtProp, 0, 0);4 V7 n. s& I; J, _
  165.     strDisk=_com_util::ConvertBSTRToString(vtProp.bstrVal);" Y! l7 J' O- j$ ^4 z: A
  166.     }
    . @4 i; ^" M, D( Y

  167. + v. D8 r; z' Y2 r# s  j
  168.     pSvc->Release();9 Z0 q# ?& Q) \0 w$ m+ I1 o
  169.     pLoc->Release();
    0 }/ ]& H. y+ W* K$ L; F
  170.     pEnumerator->Release();% _: E$ h$ D6 Q9 N+ [
  171.     pclsObj->Release();
    ; C) ~  I" e/ g% F+ }
  172.     CoUninitialize();9 Z# K* G5 Y# a* z' H1 q8 d- g
  173. & \: m/ i( f( A4 Y* L4 M* ], D
  174.     return 0;   6 ~3 o7 ]4 E3 J; U
  175. }, P8 C7 K6 _! u, W) r
复制代码
 楼主| 发表于 2010-10-11 19:21:05 | 显示全部楼层
本文代码经ccrun(老妖)在Win2k下试验成功." M, a) g% g0 \: z& T$ [9 h

+ I0 \, \, P8 K#include <WinIOCtl.h>) y1 p3 b; B: u6 F! c
#include <stdio.h>
8 C( E* I! S4 G6 G5 u* X: o' d
#pragma inline
6 T4 N0 u: P' N% ~. D9 n2 }4 N//---------------------------------------------------------------------------
- `. e4 C3 x9 p' i// IDE NT/2000/XP专用变量
: q0 ?: |3 P" P# l0 t( m#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
' b0 u5 o% _! h, ?# N/ w#define DFP_GET_VERSION         SMART_GET_VERSION' Z# L; `  t4 q; \* M$ A8 J/ ~" d# Y
#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND! N" X# S' N( h  x- T& b
#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA) c( l' \. P  z6 I( p+ M5 i! M& D
$ S0 k5 m1 b+ w0 }" v0 V8 I: H1 w6 @) N
const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令" S9 I+ ], h* n6 _0 ?. b3 R
const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令4 p' N! e# S& _7 [" a# g+ G

- Q: u; C! L" }- ]* D& L/ hconst int MAX_IDE_DRIVES = 4;. T0 C, r' q! I- D& s% L

! p7 c6 @/ }  _' S( x// SCSI专用变量6 ^; O: z" A! a
const DWORD FILE_DEVICE_SCSI             = 0x0000001B;
8 m' I$ {$ R; F3 Z& e, ]+ l  pconst DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
4 [% v: `0 S" _! t! `const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
$ \" J" v5 t0 ]: w9 y. Bconst DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;5 u1 o4 p7 p: ?" K. X% r( V  {" p( T. M1 S
$ m2 s. [& v. J
typedef struct _SRB_IO_CONTROL
8 s1 F2 `# Y, k: h' o{3 G( w9 t' Q6 r- e
    ULONG HeaderLength;
( A& E/ J* T1 y# j    UCHAR Signature[8];
' C# \2 B! X; x: ]/ s    ULONG Timeout;8 d/ R' J1 m9 T) e2 y9 p% N/ p3 |
    ULONG ControlCode;
& x8 y: A6 O6 @- j" k- a- i    ULONG ReturnCode;! M  H* {. l7 d* @1 H- Q
    ULONG Length;
0 `. H8 P2 }- g: P+ O}SRB_IO_CONTROL, *PSRB_IO_CONTROL;
' c% O! N5 l+ q. S& k( f* |0 e* ^7 v
// 读取的主函数+ I/ ~  D- _5 O7 c
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);/ @# H9 r! H' C$ t  M% i$ w6 v% Y0 ^

) t7 K( k4 n! E. y7 e// 辅助函数
' Z  ^0 k: e0 A- b. a' b& ]char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
# U  P1 t0 A5 h% E- |// NT/2000/XP函数1 A; m+ D9 I* }4 Y; L
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);: p3 r: h, h& ?9 k% K
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
) X3 \  E3 V% R        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,% D$ D/ u1 f3 N: r4 h- Q$ n
        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);: D- I, F3 E4 C8 ~
// Windows 9X函数
. |* E$ \( ]2 V( B9 Y- @. Z; {void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);* [( Q" n. I5 w  v1 I8 \
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
5 H3 }6 ]# U' h+ ^. z        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);& L/ x. D9 t) V+ H, k+ i. F
6 R, i2 P; y; I/ n9 z" X
// SCSI读取函数(for NT/2000/XP)
7 S' D6 g3 c4 y  X4 K8 R! @; wString __fastcall ReadIDEDriveAsScsiDriveOnNT();; v4 I1 o. A3 H* m, w
//---------------------------------------------------------------------------
* z4 \( A) G! X! z! `# a// ReadPhysicalDrive
/ [2 a% O& R$ \" @9 x& o0 c% S1 j8 Uvoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
* u' W- v/ U5 y/ Y+ R. V{) S# l7 b3 \3 _, c. t% e- S- x3 I
    switch(Win32Platform)
5 `" ?2 s( A9 F6 s    {
1 X( s2 j% z- k/ d8 G! }        case VER_PLATFORM_WIN32_WINDOWS:
5 |0 T5 F! W1 p            ReadPhysicalDriveOnW9X(pSerList, pModeList);
; l( S# Y+ g) |  |- w5 g$ ^0 [            break;
- s( L5 m$ K, H( B& S, K/ s        case VER_PLATFORM_WIN32_NT:
  l& X& a( z" O% f: A3 X. g            ReadPhysicalDriveOnNT(pSerList, pModeList);
, E; J7 O1 i4 ^. A% g# n            break;
2 I6 S) ?7 c& y# P; W        default:3 M; b) O9 w. L& y# [
            break;
9 C1 v& C" E: S4 b    }  i' Z+ _8 A! ^# C5 l
}
6 }, I9 x) {1 l//---------------------------------------------------------------------------
; b, b7 ~# f3 }/ W! O// ConvertToString# U9 Y8 P. s" j! \+ _- o# a0 K/ I
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
  m' q! N9 v& K8 V{
2 C) A, H2 g: `3 N% g& C    static char szResBuf[1024];
4 m1 i# ~0 Y, ^) t    int nIndex = 0;
4 b" G% {! K9 L) ^) q8 c$ t    int nPosition = 0;" {% Q! e+ S1 u
' ?  G% }6 n. C4 A5 X
    // Each integer has two characters stored in it backwards3 H, T% p$ ^3 `
    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
& s5 U: I5 ]6 _# u3 Y    {. P( t) e7 k1 G8 l: p, }
        // Get high BYTE for 1st character
9 N: e' S9 c; C: Z$ c( E0 J4 e        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
7 l8 T- X& U8 c        nPosition++;7 ?% W8 I. C* K* e
# P9 v' W( N6 @$ D- o6 f
        // Get low BYTE for 2nd character
( ?3 G% [6 |: f. Y        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
/ P4 t2 T  |9 }  w; J& h, N: z        nPosition++;8 ]5 a7 T& l" V
    }0 f8 N1 t. M& U+ S

$ v1 Z# @2 q" o, C    // End the string! ^& m0 M3 v$ @$ L" x, B5 h
    szResBuf[nPosition] = '\0';
) b- ]4 O. d$ L' J) x+ K( L" d& ^0 e
    // Cut off the trailing blanks9 w3 T& N- X  {/ }2 a
    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)7 h$ v; \; Y, F/ N$ g* K" V
        szResBuf[nIndex] = '\0';
& k2 Y, a* u2 w3 U' B2 F: m9 K6 W+ b) X; y/ {, e
    return szResBuf;
! i( G. Z& X' {}
' j+ l3 t9 a1 V. l8 Z* o//---------------------------------------------------------------------------
8 c+ ]* B6 I3 _// Winndows NT4/2000/XP 代码
' c& N6 N9 r/ s' w: a. u//---------------------------------------------------------------------------
; u3 L. f* J- U3 {3 X6 U// ReadPhysicalDriveOnNT" S/ f2 _# S! k
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
( a1 [! O! J. n: L+ A1 `: I* a{3 P! [: w' |' C3 F" Q
    // 输出参数6 t$ y' c& r' `4 k8 Z+ a% y1 I6 D) ~4 P
    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
: x. }1 ~; k5 N$ D( f! K! d1 c8 l0 R" d) q* \" D& T
    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
( B. R2 F& [! _$ h. H3 w5 ]    {
  g$ \/ {9 I* g1 I        HANDLE hPhysicalDriveIOCTL;$ b" k, s5 l  y' f) D1 o; }. _
        char szDriveName[32];
- F5 l( E; n6 Y- i
% h, _) y7 B; R" G; q        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
5 C/ m+ x2 V, z1 y1 C1 w; H        hPhysicalDriveIOCTL = CreateFile(szDriveName,6 F1 m6 b8 k. \6 ^7 d3 D" u7 ^) z
                        GENERIC_READ | GENERIC_WRITE,
7 ~5 ^( z2 \! N) q: n( F                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,, }) `/ L* P4 V7 a4 }; ?* x
                        OPEN_EXISTING, 0, NULL);% z* j+ v8 G+ h) U
- v+ d/ U. c4 H' g* \
        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
9 x" }# H! I: n" j' ?( ~' B/ C" N, a! i        {
: a# Z6 {& L# }  Q            DWORD dwBytesReturned = 0;4 g6 |6 y6 G8 _( e) Q  |# k: Y
            GETVERSIONOUTPARAMS gvopVersionParams;
' l( e  ~5 W; D" i( y; ?8 p* g) \( {3 U
            // Get the version, etc of PhysicalDrive IOCTL
2 U! r/ _  N* w) j% l9 ]  N# I) e. Q            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));5 c$ Q/ b0 R! z

; [# f" m) t$ u& t, v+ E6 T            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,) k' I9 I6 m5 l* J6 _
                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),  u- S) h! J- n" p( f) N+ V$ M4 y1 z) @
                    &dwBytesReturned, NULL)), J8 o0 R* [5 p' {7 H* \, X
            {9 ?! L, I  b% ]. b, `
                continue;
' g3 g) V, @0 o  y6 t/ l8 C5 J  Z            }
, j+ ]6 k$ t# }: M/ G( a6 T( ~2 R5 |, L
            if(gvopVersionParams.bIDEDeviceMap > 0)
' {/ h. q( H. q& U9 c. I. P9 h            {
; ?9 {& S3 Q2 S/ q4 P                // IDE or ATAPI IDENTIFY cmd+ l6 `( [5 P! x6 Y$ N) I
                BYTE btIDCmd = 0;
$ F4 o8 A3 h2 |4 ]' H8 f: a$ H                SENDCMDINPARAMS InParams;+ p+ a) z" e% D3 @/ A
                // Now, get the ID sector for all IDE devices in the system.
: M, j* @- n6 n                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,3 L- f# E0 @  p8 {; u! S% O
                // otherwise use the IDE_ATA_IDENTIFY command
5 ^5 C/ l& c8 V                // 具体所得结果请参考头文件中的说明
  T- }7 v. d$ m0 A7 Y7 C. t2 q                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?6 Q7 F0 \6 U, T. l/ r
                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;! X) ^+ y3 `4 A& V+ u
                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));4 s' {' [/ J/ _( O' [
                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
1 ]: J/ c" a! M" l1 V
: v$ H% z! Z" ^% |" {0 a                if(DoIdentify(hPhysicalDriveIOCTL,) P; B# I) D# y
                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,5 P1 Z  k! B6 x% p# q, `& `
                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))# Q& |0 L7 r+ `
                {: F- L$ s; [! Z" O
                    DWORD dwDiskData[256];# K4 I7 m& `5 j2 s
                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
. l. X, {% [" V5 O2 O  f                    char szSerialNumber[21];
8 I. w$ G; T/ C# T0 S  B2 ]" @  _                    char szModelNumber[41];8 P' c/ U5 A7 K2 v1 q( _

$ z8 A4 E8 ?  m4 N! W                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
$ x$ }& u- Z# X' `9 q                    for(int i=0; i < 256; i++)
6 |" G  s+ B" ?$ S* t! w                        dwDiskData[i] = pIDSector[i];. u9 y% Q4 L) l. c! s. o6 I
                    // 取系列号; i: ]+ ?  W9 e8 ]2 r
                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
# d7 f) G3 _7 I                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));7 E( `( f! F6 |
5 b7 V: F7 `# K4 c# M% k
                    // 取模型号
2 N7 }) ^3 C8 `# z0 c7 D% L& v                    ZeroMemory(szModelNumber, sizeof(szModelNumber));6 O" p, s( I$ p. I9 O$ n6 ~
                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
6 E6 i: L$ V& U
; R8 y8 p% M8 u% k5 z2 Y  h                    pSerList->Add(szSerialNumber);* L: M1 g$ ]7 C. b9 Z  {
                    pModeList->Add(szModelNumber);
# Z, T+ W# p7 u8 ~                }
: ~( b% U: o- n+ z5 q2 {            }& z" z+ A1 x$ f. R, q
            CloseHandle (hPhysicalDriveIOCTL);
' N+ ^9 [7 W3 j5 r0 p        }
( a4 p+ C8 H$ i0 w$ y    }
; }9 X  j( O4 y9 f}
0 Y' v- _0 y$ b' M& H7 T8 B: L//---------------------------------------------------------------------------
& F% b$ h. C2 o. o. D& \// DoIdentify
0 b5 [0 e) W9 U% T  E8 i3 fbool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
2 u7 L3 `9 J7 c( T              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
$ ?: E6 b/ y; [3 R: q              PDWORD pdwBytesReturned)
1 f0 x8 c: R; |6 p8 M{4 J$ g: L6 Y6 F* \# v7 }
    // Set up data structures for IDENTIFY command.( G' O2 ?* j6 p( e, s0 z1 h6 y
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;6 D1 M) F+ G8 L- v* B8 ]0 v$ h  L
    pSCIP->irDriveRegs.bFeaturesReg = 0;
4 m2 }, u8 D' i4 H+ l    pSCIP->irDriveRegs.bSectorCountReg  = 1;1 C1 W1 e  g' [' }4 ]3 T: j8 y
    pSCIP->irDriveRegs.bSectorNumberReg = 1;8 Y* }) r8 L6 B, C) d: C% H6 A6 F
    pSCIP->irDriveRegs.bCylLowReg  = 0;! i7 ]% v7 g% g; P! ^1 w  C
    pSCIP->irDriveRegs.bCylHighReg = 0;
, H2 t% o. t9 F: ]# w( i, l* u
0 _( x& ?3 Z9 c- K0 `9 {2 d7 j. h    // Compute the drive number.(主盘和从盘所对应的值是不一样的)1 {: H1 R- D! C6 h* q) T
    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
# M8 d1 O- n$ r# L1 r" O( E! u# ~, N# M' S4 S/ O& W! T
    // The command can either be IDE identify or ATAPI identify.
2 T7 V# M' {# y1 `; p9 K+ ~    pSCIP->irDriveRegs.bCommandReg = btIDCmd;& H0 V; h5 M* k  j, e
    pSCIP->bDriveNumber = btDriveNum;  |" c2 f) w% z/ {0 O% m
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;2 r9 B% m7 q6 j. r

$ [2 d! F1 `* q- g7 b7 I/ T: d    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,4 _4 A' e- ~* V% G& E1 w1 E- C! X9 s5 A
           (LPVOID)pSCIP,
& q0 t7 @' F3 v           sizeof(SENDCMDINPARAMS) - 1,
) b9 l) q+ n6 V& ^! B; w/ P1 M1 T           (LPVOID)pSCOP,
; |! H& Y9 A0 n$ Y           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
. }. {6 {8 J& g9 |( ~6 W0 s+ C           pdwBytesReturned, NULL);! Y$ v( j% A/ M- l) j, _) z+ g! A; ?
}
* l: a2 c0 o0 l1 o8 c//---------------------------------------------------------------------------2 q$ c6 a' |' R/ M
// Windows 95/98/ME 代码* ?5 N( G; _- q9 Y% a( X
//---------------------------------------------------------------------------
! s. N& x4 ~' v1 w( O& k// ReadPhysicalDriveOnW9X2 R# J" y5 N; g# U8 h
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)
! q9 h' n: p9 x0 }{3 ^, ~+ v  T, Y; ^  }
    WORD wOutData[256];
& s2 F  H5 t4 A# o9 o    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);2 P* M( e) l  E, U, J; L
. }2 K9 U! L" H* E
    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。  J# M* i, K2 p7 D% a
    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以0 c5 M/ C1 i& D+ @) C( b+ J
    // 避免蓝屏的出现。(期待高人能指出原因)6 L& o4 |0 @2 n5 }  G5 D
    for(int nDrive = 0; nDrive < 8; nDrive++)
4 F: w( H8 p% n0 b  `% [    {
8 @* r, o8 F' X9 ~3 h- ~        WORD dwBaseAddress;5 W0 \  o' Y, p+ J
        BYTE btMasterSlave;         // Master Or Slave
% D2 U$ L0 e+ s, \! C        bool bIsIDEExist;
6 Q9 \+ k0 ~( m: O: `2 h$ m4 g7 Z        bool IsDiskExist;
# k+ E! ^. a2 W& ^/ R4 O5 R" N, I: h1 u& N3 \
        switch(nDrive / 2)' N# `: ?! `4 {% \8 X" `+ G. H/ U
        {
1 x! m, {' j) _; R5 _: S            case 0: dwBaseAddress = 0x01F0; break;
+ h1 v/ S" E& R+ f            case 1: dwBaseAddress = 0x0170; break;
- i& a5 ]0 b: i4 Y; y            case 2: dwBaseAddress = 0x01E8; break;
: I5 b0 ?# g- ]$ l2 F; }, w            case 3: dwBaseAddress = 0x0168; break;
' r& Y) y5 T( a* X7 R        }
2 k* }9 y! I2 T9 @2 m4 I' e; E
( Q! T7 Z1 j- s; L3 j        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);/ S, L: P; q) z- Z. G7 u9 Q

- _4 Y3 _4 {8 g        // 进入Ring0
3 W* c+ P+ x! _        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,  V5 M5 G( s0 z
                bIsIDEExist, IsDiskExist, wOutData);& j* d( M4 {% F) J
    }
- t4 }/ w. y& Q, w
5 P, Z( M' `0 s# z+ i    // 开始读取
8 B. a) q, I% e! X    for(int nDrive = 0; nDrive < 8; nDrive++)
' u* C5 F, G, M, h; B. z    {* ], r" n; m% Q. g  S2 e4 ]5 V
        WORD dwBaseAddress;, m$ g  m! i4 @* Z  j& a
        BYTE btMasterSlave;         // Master Or Slave
3 X. h5 q- Q  j. Q6 T        bool bIsIDEExist;6 h& f# {1 B2 f
        bool bIsDiskExist;9 e3 O! Y, H* _5 L
        switch(nDrive / 2)
% S( m# H9 h- m# R& ]- e        {
% i1 H; T7 h6 m9 Q% p            case 0: dwBaseAddress = 0x01F0; break;5 ?6 F/ K6 H4 M& V& u! Y: N: ^% @
            case 1: dwBaseAddress = 0x0170; break;. m; w2 o6 f; n: T" O
            case 2: dwBaseAddress = 0x01E8; break;3 y( v! I# o. {. h: I  E
            case 3: dwBaseAddress = 0x0168; break;6 ^) i1 _: E! w' f; O5 C
        }9 A) R9 B* l$ c5 Q4 E4 \
3 G9 @$ c5 U) {$ p( |/ z. o
        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);4 u; d7 U" A5 i( [
! C( f$ p$ B- J9 ?  c1 z
        // 进入Ring0
8 g/ ~' i& L( u7 E        bIsIDEExist  = false;7 `" f9 r* s  w! w
        bIsDiskExist = false;- t1 x  _4 o6 m8 e) G0 G
        ZeroMemory(wOutData, sizeof(wOutData));  s  X4 p- `/ \! C: [: {, e
# h' U2 r& ^6 I
        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
) e% o  J/ ~# u6 ]2 g: }# S3 t                bIsIDEExist, bIsDiskExist, wOutData);! x" Y% a, r; h, p9 D2 z

0 u  u* R8 E4 V* l) x) S8 }        if(bIsIDEExist && bIsDiskExist)
! z: P, o& T* }        {
  S/ N4 S0 S* F0 K5 G& U3 Z. w            DWORD dwDiskData[256];4 ^% q! u5 c& K0 f4 a. W
            char  szSerialNumber[21];
/ D2 s' L% T* G            char  szModelNumber[41];8 ]- [9 F3 k. b2 z- w  ]
" D/ J- b- C' i" a) B9 }  n' C/ M
            for(int k=0; k < 256; k++)+ e: ^& ~6 b/ a- {5 p% ?- s
                dwDiskData[k] = wOutData[k];5 R" e% J& B* k, q" @

0 ~* @( A1 u& j' C% \            // 取系列号& W( R1 B/ j+ K0 c7 O6 F) L
            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));$ q+ {5 v" D6 K7 \
            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
8 r2 k4 d$ n7 f! B! i1 P/ A* m" X( o1 e) F% Q- n) m4 [$ E
            // 取模型号
* s$ h# @5 e& ]4 ^            ZeroMemory(szModelNumber, sizeof(szModelNumber));
3 C' |7 y+ h+ k  k- M2 X# h            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
+ {' i% x7 N" n$ ^9 R* P# ?$ Z; s3 s) b; F- T/ ?) ~' j
            pSerList->Add(szSerialNumber);& Y- x$ P/ d' g+ ]( \
            pModeList->Add(szModelNumber);
7 Q: [5 V3 [7 s7 I" m        }
$ O' d! w- y% P) P3 t6 L    }$ d) u7 S' n. F7 {6 k3 ^8 H; I! ?1 r2 w
    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
+ L4 I3 [, S& @9 D. i$ ~+ g$ k}
! }; O1 R3 G8 y/ N//---------------------------------------------------------------------------# n3 E* O. @, W- v
// 为防止不负责任的转载者,在此注明原出处信息,请见谅。
" `" s4 T! R& _" N  N5 M// 资料收集整理:ccrun(老妖),欢迎光临C++Builder研究: http://www.ccrun.com
2 M0 d# _$ B! K; o2 d//---------------------------------------------------------------------------
# [) g1 z6 B% T( E* R2 v: x% m// ReadPhysicalDriveOnW9X_Ring0()& h' T5 [( c/ ]$ j/ r3 b" l; P
//0 \( o( S+ [3 V6 h" T9 `
// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
. v( @/ h) \2 ?/ U8 z# p// btMasterSlave = Master(0xA0) Or Slave(0xB0)% Z" a) W8 |1 K; D# q
//---------------------------------------------------------------------------6 n* l, O- |+ p- M7 g; e7 f
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
6 {8 K) N. ]# Y4 I4 w        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
9 `; o- u) D+ G3 B! h{' U3 b- n/ M7 S8 l/ J* w  n
    BYTE  btIDTR1[6];
- S( I! [1 c0 b9 R) f5 `1 C    DWORD dwOldExceptionHook;
3 a" Y, ?! ~1 w; f$ z: M    const int nHookExceptionNo = 5;% J' O: U! g6 G1 T" h$ ?4 @# C9 z
1 a8 [9 p& L& |5 r4 U$ K
    BYTE  btIsIDEExist = 0;
8 `# N1 f  r$ ]* P2 Z0 [( K* i    BYTE  btIsDiskExist = 0;3 z& C, i4 f! Z
    WORD  wOutDataBuf[256];
& W  x& M5 N: H+ @& E  W0 Q- Q9 q& K- o* }2 @7 j, C5 A: k
    BYTE  btIsFirst = (BYTE)bIsFirst;4 T* h  F* f& o

% C* H2 F  _0 ?7 F) X# f$ ~, O    const BYTE btBit00 = 0x01;
+ f8 \' k0 O. f# ]; Y, Y  I    // const BYTE btBit02 = 0x04;* W, ?, k- f# l! [; V/ q
    const BYTE btBit06 = 0x40;
" G5 B2 E/ a) t: D    const BYTE btBit07 = 0x80;4 N! }1 b5 F/ D- ]' ~5 x
    // const BYTE btERR  = btBit00;
7 {0 s' A. B# O6 n5 Q3 {    const BYTE btBusy = btBit07;$ ?9 ~* ?1 |1 `; M* ^/ V% Q
    const BYTE btAtaCmd   = 0xEC;) L6 O9 F* ~3 ^' U9 i) x
    const BYTE btAtapiCmd = 0xA1;
6 |. T0 {- `4 {/ ~" ]1 l5 n: o0 ?! c9 ~' O; o5 S# H' X" D+ A& H
    __asm$ F2 W: J, ^$ k0 |! y! z5 x  a
    {
( v% G0 a, y2 x7 n% Y0 G5 X2 q        // 必须先执行这条语句2 G. [( ]4 K1 `7 T' a( Z
        JMP EnterRing08 L2 T. s( i8 c1 _

7 s+ v( S( Q! ?+ o9 ~        // 定义过程
  [# A; N, }0 y! h- U( q+ }3 S- N        // 等待IDE设备直到其不为忙为止+ ~" @! t; l! o/ B
        WaitWhileBusy proc
) a1 x/ l" r6 `+ ?: u
8 W6 g& K  b" m: z( E5 G7 b0 X        MOV  EBX, 100000
) T$ M) R9 c) W& `3 G' r* j        MOV  DX, dwBaseAddress
" Y* B9 r9 b$ q# m) H        ADD  DX, 71 v" Q. w" w7 @! j

- y- K; B! w- P5 T  n$ {        LoopWhileBusy:0 A7 B5 ~$ d6 V9 \

8 R8 \/ F5 ?9 m* U  P* l        DEC  EBX
9 Y9 p7 o' P& m+ e        CMP  EBX, 0# G$ M: T& Z; F- P9 s
        JZ   Timeout
0 T( R: C$ U8 \2 R( C0 ?$ f        in   AL, DX' @! n' D3 b$ g/ K( K: Z  |
        TEST AL, btBusy# D) }$ |  p: S
        JNZ  LoopWhileBusy) g1 Y3 f0 o2 }+ G9 b; c" J. q
        JMP  DriveReady- m8 @5 U& b3 v1 c& c! v8 k. S* D. |
+ m. [3 T. r+ l
        // 超时,直接退出
, w2 A, p, r  k) C& @        Timeout:5 f; X/ V: y* |4 j
        JMP  LeaveRing0
( R0 j6 F  `* t. h: K) x2 k        DriveReady:
' B: q  o8 {& m( d3 q        RET
/ V6 [" t# W: R9 Z& j, h        ENDP   // End of WaitWhileBusy Procedure* J7 x* x2 q- d9 V9 t, e

$ ~+ m1 D# _; a( ]- g: L/ `        // 设置主盘和从盘标志2 I" N# R. G9 u# W3 Q! l0 U
        SelectDevice proc0 M4 ]- c& P* ]4 U7 P3 X5 G* {5 h
0 g$ W( T9 Q' J/ _  l* v
        MOV  DX, dwBaseAddress
5 z4 `8 G1 K) z& D' p) H        ADD  DX, 6
+ P  {3 H7 v3 W  ^+ r7 y        MOV  AL, btMasterSlave, f$ s- S" T# e

, G+ |9 b& ?0 ^: P1 b; x        out  DX, AL
9 g& U- x* k$ k2 u- d7 r) F        RET
+ F1 a( P! S/ P$ c( z7 l2 M! s" o# ?  b8 T+ I. h
        ENDP  // End of SelectDevice Procedure! w9 n# |4 z- b( d& F' O8 o2 A& e

6 p2 }) u8 b' c        // 向IDE设备发送存取指令7 J* n- x! d% d# w. T5 m
        SendCmd proc: N3 G$ e6 D4 S

8 D, J5 X+ Z& A; l+ a        MOV DX, dwBaseAddress
; E% d) r- u3 ^. R  V5 }8 U        ADD DX, 7
0 I4 O0 h. B2 u* p* N        MOV AL, BL // BL是主从盘标识,在过程外设置
+ u, ~- z& H9 y* e: L        out DX, AL5 G: r2 v( \3 E. t6 N4 ?: N& z
        RET
6 X( H5 l" F- `9 V( l! G) {* Z        ENDP  // End of SendCmd Procedure
. u9 ?: Q) W/ Z" P8 T4 t- t
2 T- J( D; b* u" O) N# U. P- p0 h$ x        // Ring0代码) s( R& r" P* o9 Y- e
        Ring0Proc:. J; r' c" M! y: v
        PUSHAD* L2 Z# e$ _3 ^6 w# U) b
        // 查询IDE设备是否存在
  N) q8 N& t- R" q) |0 \  ^        MOV DX, dwBaseAddress3 Y4 b* a3 @0 {4 C% `
        ADD DX, 7( y! B! t/ t; V) g' b
        in  AL,DX7 G1 M* o- u- }' R; J" w

. C1 B+ y8 \; ?3 r        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回& @) H9 d8 _! z3 o0 L' y1 X4 Q
        CMP AL,0xFF
- F' o8 j, d' ~0 `' ]. ^+ x' u4 |        JZ  LeaveRing06 y/ n/ Q, t. g3 F
        CMP AL, 0x7F/ L: k1 C" s7 `: r
        JZ  LeaveRing0
4 O5 Y. o/ U3 v) F- {9 k# M' ]) ^! S" P9 S, z
        // 设置IDE设备存在标志2 o4 B7 e5 A7 T( P, g& c( T
        MOV btIsIDEExist, 1
, M, F! b( q* r4 _7 r) T# ?2 K$ i" n8 T& a
        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
! K' \8 d7 {3 k: g, H0 [' _        CALL WaitWhileBusy5 R- b! `- @) d1 n  `
        CALL SelectDevice8 Q7 g2 s" J0 l$ k
, [5 F8 j1 k9 {3 h+ e
        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏5 W& o4 d: D0 n6 r. N3 s
        CMP  btIsFirst, 1
, j; S( ^" w; ]* T) g+ T7 U/ R        JZ   LeaveRing00 k: u) J8 c% L
6 B# y) r' l; F( b' D3 `/ J
        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???! v7 \( g8 E: Q7 b0 L, k# ]
        CALL WaitWhileBusy
9 S8 }0 B8 O) S- x
. c$ {" n5 r( Y        // AL的值等于cBit06时,不存在驱动器,直接返回' x+ [# S3 M& o& g  b* ^
        TEST AL, btBit06
6 _' ?+ |1 V( G1 _) H& E        JZ   LeaveRing0
3 W; q9 r- L( ]: Q! d& X. L, n4 [% U  k( P2 [6 d' L' p) @7 M' I- q
        // 设置驱动器存在标志
" z) D' n2 B3 u6 h        MOV  btIsDiskExist, 1
( R3 x: c2 T, L, w: V
" p" Q2 c" L" H; @+ F2 |* E/ j        // 发送存取端口命令
+ _$ F5 e* ~6 J! d% }0 r        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,/ p4 K" B) E( w3 w! t! T2 |
        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
8 z4 I* G; d) p4 k+ [, x0 r        CALL WaitWhileBusy
  o1 K0 C# z9 B: g/ W# v: W& I        CALL SelectDevice    // 设置主从盘标识
8 }- t' z! v! d6 `        MOV  BL, btAtaCmd      // 发送读取命令
1 N' T2 O6 m, [+ b1 |! P        CALL SendCmd
& _: @) o: P! p1 u9 S0 h5 H        CALL WaitWhileBusy
- h& b' a5 G, X3 @4 }
6 n* O; o. }" [; i& c  f        // 检查是否出错" R' Y4 L; k+ c1 d. V# `
        MOV  DX, dwBaseAddress
) M3 G; @. a5 I        ADD  DX, 73 P# l* P0 t6 I+ T6 T

) D- @1 m2 S' K& o( m# H: B" S        in   AL, DX* s, Y3 ~# l  u3 o

* F: I; r. W2 h0 T        TEST AL, btBit008 h3 Z# |0 R. E7 k3 L1 X
        JZ   RetrieveInfo   // 没有错误时则读数据
1 ]0 h9 \1 m5 T5 q- n/ k0 V% H6 @% H
        // 如果出错,则进一步尝试使用ATAPI设备命令
% q( S8 j0 C8 E7 c# u$ [# x/ M+ I& _# K( ]        CALL WaitWhileBusy% M* r; `3 s( z0 J2 ?/ O  M- B
        CALL SelectDevice
/ i& z2 o6 Z" ]        MOV  BL, btAtapiCmd, f8 R/ l- X  M" |) p3 p# c- ?
        CALL SendCmd
8 h& ^6 Y6 D( g8 [, i        CALL WaitWhileBusy
  T6 K8 V3 {/ L. ^4 K$ f; }
& D1 ?; T7 Y, p0 Y. z        // 检查是否还出错8 I6 W9 k7 I& }2 P; D# U
        MOV  DX, dwBaseAddress( ]0 ^' O# h- Q7 A5 `
        ADD  DX, 74 [: ?* N" a1 v0 g9 `
        in   AL, DX
( x& e. `% {  C        TEST AL, btBit00
1 D8 a* `$ f3 J7 Z* K        JZ   RetrieveInfo   // 没有错误时则读数据. [( w2 H/ W6 B; G
        JMP  LeaveRing0     // 如果还是出错,直接返回, [1 H8 t7 Z5 q2 B' |; e
1 s9 L- J3 B  D  e
        // 读取数据
; j& h& h# e: Y1 s        RetrieveInfo:) D2 k1 v$ Y* _! ?, Y0 T% e

9 I' }: F  o" [# N  x: W        LEA  EDI, wOutDataBuf9 I+ W2 _  X3 c$ d& ~2 u
        MOV  ECX, 256
1 M; @, y0 s8 o, v: M0 |5 O3 K8 y7 c7 h; z        MOV  DX, dwBaseAddress* W+ g: x0 r4 g6 _( O) h
        CLD
+ {2 n% H9 o4 N# v% P  w( N- }5 G% D; J( I" [9 O: w6 O
        REP  INSW4 l) v; q+ r" j5 u

0 g! z9 l$ ^. s        // 退出Ring0代码
& H7 o7 A; Q# G, g8 v        LeaveRing0:
4 j% [' D! b& a& {2 [! W
8 Y1 I  [$ d) |. O6 K2 k        POPAD1 q6 f1 _2 |: Y3 @) r; b
        IRETD. E: n4 [8 K$ r% O: y
# t/ @% t/ Z/ b5 D
        // 激活Ring0代码
+ w- f, Z' V! P        EnterRing0:. j* L  L8 e" B* n" G8 r$ i' `

; @/ F1 _- |& w3 b0 c2 S1 i8 j4 S        // 修改中断门9 G# y4 |- C6 D
        SIDT FWORD PTR btIDTR1
7 r2 Q. z2 p( x' E1 S        MOV EAX, DWORD PTR btIDTR1 + 02h' [4 D( ^2 Y1 k7 j
        ADD EAX, nHookExceptionNo * 08h + 04h
, _1 Q8 }! ?# @# c! j- S0 F) Q        CLI8 Y+ m% l0 C! S: |8 e" a8 C& z
& `& K/ Z6 G- R4 @+ l/ `/ L1 e
        // 保存原异常处理例程入口
1 x' S; Y# M; ~: d) ]- d7 L* ]5 N        MOV ECX, DWORD PTR [EAX]2 [$ I. ^. o. o2 S0 F
        MOV CX, WORD PTR [EAX-04h]/ }2 b+ R' @( ?9 d$ F' P( W
        MOV dwOldExceptionHook, ECX7 y1 b% d6 _+ F/ \) b1 R
7 x$ ^2 u- t8 ^
        // 指定新入口
( R+ i- N/ s1 K) K+ L2 Q        LEA EBX, Ring0Proc  _: t- s3 x+ W" U' l% D
        MOV WORD PTR [EAX-04h],BX
' Y/ g/ P# x9 A- M, Q        SHR EBX, 10h
& b9 m. ~" w4 K; j        MOV WORD PTR[EAX+02h], BX1 t6 w) W1 p0 R! J$ l- Z. N4 [0 d; v

4 I% Z! Y% r( A7 o! q1 x2 e; C        // 激活Ring0代码
# r& ^# Q8 N0 R2 \% i' i2 C- K$ c6 F% I0 O        INT nHookExceptionNo
* H$ R$ a: E' j9 g2 W! Z' V7 B% c  a. k& f6 B2 t- Q: k/ M
        // 复原入口
; c3 w% H4 d4 \- B/ ~0 ?2 w        MOV ECX,dwOldExceptionHook: q5 [; Z3 K. b( g# X
        MOV WORD PTR[EAX-04h], CX5 ^5 {' x1 k- G5 W+ K
        SHR ECX,10h
/ p/ m) P8 S5 O1 Y        MOV WORD PTR[EAX+02h], CX' m9 Z" g8 z. Z9 N( A; q& i/ a
        STI
8 i5 P' a$ }- e8 T7 z    }( w) c! F: U* U
    if(!bIsFirst): U' C1 t! I. b8 i
    {# I8 ^' v' R$ v* w% L- _8 e
        bIsIDEExist  = (bool)btIsIDEExist;
1 }& j8 @5 i9 ~  ]: v" P* a; ]        bIsDiskExist = (bool)btIsDiskExist;
' {* d' N/ y: e- y1 Y! k8 l        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
6 t7 b1 ]& r! g3 C    }
. A) b8 q( O& N1 v}
% a' w& s8 {7 y3 v//---------------------------------------------------------------------------
* T) Y! c% a" R! f7 r9 _// 调用方法:  n$ \5 }* h5 j/ w& R' R
void __fastcall TForm1::Button1Click(TObject *Sender)* I1 P+ F2 h4 y* S9 Q9 M. \! I
{, b8 L% c- D3 N" t
    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);) x& A* G+ k' i4 ?1 A* F% [1 H- A" H
}
6 F/ `& e1 i) d; L: Q, k
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-8-8 23:58 , Processed in 0.035885 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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