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

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

[复制链接]
发表于 2008-1-6 19:59:06 | 显示全部楼层 |阅读模式
代码框架,你所要做的仅是修改WQL语句,具体可看MSDN。以下代码为简介起见,一次返回所有的CPUID或硬盘厂商系列号4 M! V, b' R' e) E( Q+ }
  1. 7 j7 \( J% X1 J: m; J  q
  2. #include "StdAfx.h". W6 B9 L9 f& y; Q* \
  3. #include ".\puiddisk.h"
    ' P+ K7 G0 Z. C
  4. #define _WIN32_DCOM4 x/ m( G. F2 H% j
  5. #include <iostream>
    1 S, H2 D; [1 W. U! s( D
  6. using namespace std;
    ) p5 n5 b1 V8 f7 ]% I( A
  7. #include <comdef.h>
    2 B6 h$ w0 G+ z: I( L$ \8 b3 U
  8. #include <Wbemidl.h>% c1 a- p- q: r7 w4 Q. N5 s( U& ^
  9. 0 n8 H/ S2 P5 f1 G& a6 t& q' s
  10. # pragma comment(lib, "wbemuuid.lib")
    , R8 b" ?" C( {
  11. CpuIDDisk::CpuIDDisk(void)( H8 L5 _9 }% G7 C
  12. {
    7 T: {$ D2 m+ i! {
  13.     GetInfomation();
    1 R" N8 r2 s9 a8 _
  14. }
    : e2 A0 X3 J- R! s, k
  15. 2 Z" E7 e$ F4 b& Q* v* e
  16. CpuIDDisk::~CpuIDDisk(void)7 I8 @# S8 w) l& W
  17. {
    1 Y# x8 w+ V6 }9 m; `3 l
  18. }
    ! `4 x, s0 h5 L  }* C
  19. int CpuIDDisk::GetInfomation(void)
    1 e& _  Z$ N$ ~- z& }
  20. {
    * Q9 s8 S* D4 c
  21.     HRESULT hres;3 g! T5 e1 ~* h
  22.     //步骤1:不是必须的,COM只须也只能初始化一次3 A. E7 v) k6 g
  23.      hres =  CoInitializeEx(0, COINIT_MULTITHREADED );
    5 Z: ]- M* G+ d$ m. ]5 S
  24.     if (FAILED(hres)), ]7 j% g& T( I0 Z
  25.     {& }( h& @3 b" F9 Q- {3 N2 n
  26.         return 1; //初始化COM异常:注意,COM只须也只能初始化一次
    . J, N' d3 L9 j* S* L1 i7 S& Z/ Y
  27.     }* M, J) u2 N1 C
  28.     //步骤2:不是必须的,COM只须也只能设置一次! Y; P' S% Z0 ^$ |7 @
  29.     //Set general COM security levels. L6 I# s& b' H6 M! [
  30.     hres =  CoInitializeSecurity(! V( ?+ y6 ]/ e' V2 c2 T& I6 t
  31.         NULL, / Q; l: p$ g1 l8 S) a8 [
  32.         -1,                          // COM authentication
    ; \( m& j: ?' [* N: N# Y) C3 o
  33.         NULL,                        // Authentication services
    , Y: C8 |; J+ }5 ^$ t
  34.         NULL,                        // Reserved- W; \) N: V( o) F9 K4 L  X
  35.         RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication & ^( ?5 ~0 m  X( E0 W
  36.         RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  , T2 x) |1 d+ F
  37.         NULL,                        // Authentication info6 l9 D7 f8 {) ^' e- y; N& ~# i
  38.         EOAC_NONE,                   // Additional capabilities $ h# w+ c5 f5 F8 ^
  39.         NULL                         // Reserved
    % o6 T: d# d4 T
  40.         );
    + S1 E/ H3 ]$ h" [# C7 G! ]# J3 ?
  41.                      
    1 P% D  Z+ D$ M! [5 s
  42.     if (FAILED(hres))1 o, c/ Z, J5 W/ F
  43.     {3 k0 d9 f$ X) t3 D( s9 |: K
  44.         CoUninitialize();
    ; Q8 k4 A! b& J2 o4 U4 ~. J% G( o
  45.         return 1;                    // Program has failed.
    " b3 a( k* C# u# G" s9 O
  46.     }) ^2 Z2 r# f# u2 Y9 p
  47.    
    ( [: q" d" M- w4 _5 ~3 u
  48.     //以上不是必须的,若已有“::COMInit();”,则要跳过1 D4 t8 I/ H4 m( \% w* q4 y
  49.     //步骤3: Obtain the initial locator to WMI
    4 z+ C; A/ i5 x' G+ ?
  50.     IWbemLocator *pLoc = NULL;  N$ K* W$ u- b. t/ j( |9 C. I* G
  51.     hres = CoCreateInstance(
    " c, \) i% t  P
  52.         CLSID_WbemLocator,            
    1 v% b  s5 z2 Z3 T2 f. |9 E: C  b
  53.         0,
    1 H# y& p  U% Z$ P! m. v
  54.         CLSCTX_INPROC_SERVER,
    2 @0 A+ }4 r5 m- O' T
  55.         IID_IWbemLocator, (LPVOID *) &pLoc);* W# ]" V" I" E* ~: R$ \6 _

  56. $ ^8 _8 w* y, R
  57.     if (FAILED(hres))8 \9 r4 @8 [  r0 B" }" Q) p7 l; \
  58.     {
    " ?" g- A! p( j9 A7 `( h' N
  59.         CoUninitialize();
    $ ^4 c' _; ]* r" W' s3 ~* j2 M! Z
  60.         return 1;//Failed to create IWbemLocator object
    ' l( c. p; K1 |- g
  61.     }5 j) o* S: i2 n; r# y! h( h

  62. 5 M7 P9 w6 I5 U7 R
  63.     //步骤4:Connect to WMI through the IWbemLocator::ConnectServer method& L% x6 D3 m/ V/ `% v& E0 j  B# N
  64.     IWbemServices *pSvc = NULL;
    ( Q7 F4 H5 X4 O" v3 _  j
  65.     hres = pLoc->ConnectServer(
    * Y/ @1 O. Y0 L; y* E) \0 R$ ?
  66.          _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace/ L; h) n4 I/ r$ \9 L# R
  67.          NULL,                    // User name. NULL = current user$ _" a, z2 i! X( h
  68.          NULL,                    // User password. NULL = current4 Y, t1 n6 Y3 K$ T
  69.          0,                       // Locale. NULL indicates current* k3 z& m& L# |
  70.          NULL,                    // Security flags.2 c; i. T$ m- e# H- o! s
  71.          0,                       // Authority (e.g. Kerberos)/ F/ `: |5 x! U; M1 X% a7 s
  72.          0,                       // Context object
    4 ?1 x& b  Z6 ~% n% B
  73.          &pSvc                    // pointer to IWbemServices proxy
      `! L- w' x9 V1 B* A
  74.          );
    0 m/ q/ F8 L# g% \  G& k, n2 n
  75.    
    , |( ^5 U5 r% s
  76.     if (FAILED(hres))8 `: v! @6 W7 G% Q% s& Q1 g- S7 z
  77.     {  H2 S% f0 j; I9 q: B0 t) Z
  78.         pLoc->Release();     
    $ ^) ?3 T- g$ ~- z# V- t: u4 R
  79.         CoUninitialize();7 P3 W$ a2 Y$ Y/ h( _+ ?
  80.         return 1;                // Program has failed.
    8 i* F5 A( w6 `) z) Q1 X3 q( r
  81.     }* |, R( y) M( w9 z' t
  82.     // 步骤5: Set security levels on the proxy
    1 y, E+ Z# R1 e& s9 n
  83.     hres = CoSetProxyBlanket(
    6 d; t$ K, j6 o* j; Y  Z
  84.        pSvc,                        // Indicates the proxy to set
    $ b6 j2 i4 e& C: c8 o$ a
  85.        RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx5 C$ K" t* I; p9 X" T
  86.        RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx
    % W1 o  l1 b6 h5 o' [& V+ ~! p! e
  87.        NULL,                        // Server principal name 9 y1 h7 i: H1 b& {# c1 k
  88.        RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx
    " B9 j1 t* ]! @8 r# O. X- C5 N. o) }; z
  89.        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx2 W( `  _. Z% ~0 D6 v& x
  90.        NULL,                        // client identity% ^% u( K: H, t5 I% i3 m
  91.        EOAC_NONE                    // proxy capabilities
    % R, Y! k7 D2 v% q3 k
  92.     );
    6 B7 y! t/ C5 U  ?( f3 L0 B7 A! {7 _

  93. + J0 p! c- [- y5 Y
  94.     if (FAILED(hres))1 \: }4 f6 i( Z8 S; Z& W
  95.     {
    3 m0 R% _5 i( h; ?* o8 K
  96.         pSvc->Release();/ O& \. g' s4 B# d
  97.         pLoc->Release();     $ |; n. e4 u" V4 B
  98.         CoUninitialize();
    ' _# n/ q8 q8 y. F1 H( `/ c- p' f' Q
  99.         return 1;
    - h+ C& v! ~- ]- R0 z; w/ l
  100.     }
    ) L0 o/ K( Q2 ^9 m- r) z  ]
  101. ) R& l. x" S% u- s$ M
  102.     // 步骤6:Use the IWbemServices pointer to make requests of WMI ----
    % t2 N6 N5 {+ w; Z. _. `; d3 s
  103.     IEnumWbemClassObject* pEnumerator = NULL;7 W! i6 P5 C! ~8 a. K
  104.     //计算CPUID* @6 R* y2 d5 [5 I2 G0 H
  105.     hres = pSvc->ExecQuery(% [) P2 b6 r( n# ?8 r' v. {
  106.         bstr_t("WQL"), ) c0 }- }2 a3 G
  107.         bstr_t("SELECT * FROM Win32_Processor"),//Win32_OperatingSystem$ P$ J: c8 U3 U
  108.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
    0 O, B" V9 g' H
  109.         NULL,2 k- E4 j( |# d# [  Y
  110.         &pEnumerator);
    ! H3 B$ h3 o4 A# N; C) d* G" h
  111.     ; F9 A* q1 t9 t" g8 x
  112.     if (FAILED(hres))
    $ D( O( f. H- c: q( z  ?5 W; Y
  113.     {
    5 u& a5 y& N7 O0 }% X3 e
  114.         pSvc->Release();
    6 d6 }/ |- m7 s) M! y% H9 ]1 m4 `$ g
  115.         pLoc->Release();
    7 E! q6 k' ~! D
  116.         CoUninitialize();
    ! s' f9 L2 }+ @' T4 j5 U9 a
  117.         return 1;+ ]' v6 h. F! _, j0 d- B
  118.     }+ c- a$ M$ Y3 [" |0 B* N+ J
  119.     // 步骤7:Get the data from the query , {; ^9 U) i, m! [5 G) S. ^0 X+ a
  120.     IWbemClassObject *pclsObj;) m$ `2 k  s, J/ u
  121.     ULONG uReturn = 0;
    ! z+ ?' p' _+ w; C% g4 H- `
  122.     while (pEnumerator)
    7 F2 e- Z) j6 }
  123.     {& g' m2 B; _5 c+ t
  124.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, : i) B4 K" R& d! k
  125.             &pclsObj, &uReturn);
    5 S# g4 i% G! u
  126. , A1 p, ~7 t2 Y) P/ s
  127.         if(0 == uReturn)
    - a* Z2 k8 u$ c3 W$ S3 r5 Y% `
  128.         {) T% V7 _# g' J$ G) I3 V+ V
  129.             break;
    & k: R! X+ F3 s' J
  130.         }
    0 H. Y& o; e; h& C- p( S" L
  131.         VARIANT vtProp;
    4 k% ?1 b; }" S/ t8 ?- {7 h
  132.         VariantInit(&vtProp);# p3 L. b3 B9 K0 H* f" k3 N
  133.         hr = pclsObj->Get(L"ProcessorId", 0, &vtProp, 0, 0);
    ' G( G+ J/ ~' w: ?6 p7 N) Z+ k3 [
  134.         strProcessID=_com_util::ConvertBSTRToString(vtProp.bstrVal);//strProcessID:类级变量3 N" R/ X; Q! T5 J
  135.     }% s7 j3 ~9 K+ J7 a& \! {3 b

  136. ; E: Y8 J1 g  M" G4 d
  137.     //计算硬盘系列号6 w) x8 W6 F% M5 c3 i  x' [
  138.     hres = pSvc->ExecQuery() M% K  P3 R$ [" l( e6 F. a: G
  139.         bstr_t("WQL"),
    ! k3 q; ~" t4 ^0 }/ d) ?
  140.         bstr_t("SELECT * FROM Win32_DiskDrive"),; J. Y. @- [+ P/ R4 Q/ a  c/ x
  141.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
    3 b" F% s5 o( C: M  r
  142.         NULL,+ A8 d5 [2 W1 ]/ I$ C
  143.         &pEnumerator);0 M! l/ X; B! R8 r9 x9 W& H

  144. # k3 s- |0 D; `, p" g0 k
  145.     if (FAILED(hres))
    " n: g$ W% h5 X4 ]; }# {
  146.     {1 \& q( ?+ F6 C
  147.         pSvc->Release();
    ( M9 j: \" v# ~  ^- ]. b
  148.         pLoc->Release();
    % j, s% j( U$ z, o- J+ x" Y
  149.         CoUninitialize();8 m1 i1 r1 n/ P+ }6 h# }
  150.         return 1; - a* G# f: R, X2 |! [6 A
  151.     }3 b: |. M" ?- Z, |) D
  152.     while (pEnumerator)
    . i0 [' k9 z. }: [- X
  153.     {3 _% f0 y$ i: O
  154.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
    % z& @3 y/ ]: q) [. f
  155.             &pclsObj, &uReturn);
    ) F) O8 m; ?3 q$ }2 R* B' Z! b

  156.   E( `9 h8 R: b8 n1 A* o
  157.         if(0 == uReturn)
    $ K) t# {) H7 D6 j) I) E( B0 n
  158.         {
    7 J$ g* u8 z6 A3 ]) b
  159.             break;
    5 O( n$ a, `# U9 ~! M) Q$ n! t+ w
  160.         }
    . i) N; L1 w" k1 d! J1 q
  161. 6 J$ i9 _, {: X/ ?3 V+ t5 b0 s- _
  162.         VARIANT vtProp;# C- F! |- h1 f- B( H+ H) x% T  a
  163.         VariantInit(&vtProp);
    , Z6 l8 X2 \2 g+ T# c2 `
  164.         hr = pclsObj->Get(L"PNPDeviceID", 0, &vtProp, 0, 0);" M& Y1 V1 s* e: I  X( ?1 X8 t
  165.     strDisk=_com_util::ConvertBSTRToString(vtProp.bstrVal);3 C5 t. I- W- Q1 p& I+ ]; v
  166.     }
    : O+ c8 i" f: `; D8 N& s4 w0 |

  167. 7 S/ |' n6 Y, e1 g6 g
  168.     pSvc->Release();
    ' |/ d3 o4 D% }4 Y# F# P
  169.     pLoc->Release();' B- `/ @6 G: n, P$ O- B1 A
  170.     pEnumerator->Release();+ |- v5 }' ]" P7 P1 n- M* a5 l" j4 t
  171.     pclsObj->Release();
    8 {6 ?" Z3 g; c
  172.     CoUninitialize();
    # z+ P$ s& U1 k5 z

  173. ) q$ f) P5 s/ T# I: ^- L! n
  174.     return 0;   " C" |; [6 O8 J; n
  175. }
    & y. W( I; o) q
复制代码
 楼主| 发表于 2010-10-11 19:21:05 | 显示全部楼层
本文代码经ccrun(老妖)在Win2k下试验成功.
! T! K0 V0 a4 a9 ]: [$ y/ ~, a4 e& s3 H* L( y) J
#include <WinIOCtl.h>
3 N- G; b7 t: f/ N  c! D1 S#include <stdio.h>" c+ H7 F4 n! T8 m+ H) _  e
) W* d4 f( [. d9 G
#pragma inline
0 N- q) |+ S$ N8 u1 c* L9 f+ s//---------------------------------------------------------------------------
/ K- x) T' `! ?; p( _) ^& N) n) ^" ~1 H// IDE NT/2000/XP专用变量+ s$ @6 h8 \" l7 m# V) \
#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
- C5 {6 {3 i) f, F% a- o2 D#define DFP_GET_VERSION         SMART_GET_VERSION
  q* K; b: u+ Y5 H" c4 o; p, L' v#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
/ {5 I: N$ V  D7 P& ^, l#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA/ b: |4 O( v/ K* h  Y

3 M# z) n% Y. k5 h7 tconst WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令
: @/ q( i2 p+ T. mconst WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令+ k$ k( s  D  f! w. _* d

: G0 ^! E- j- H9 x6 Econst int MAX_IDE_DRIVES = 4;
6 \' Y* a8 }8 {8 W0 @, V# E
. _7 x( w# N! r$ p8 }. E2 I// SCSI专用变量3 G' c; B  I; _( P0 q. x
const DWORD FILE_DEVICE_SCSI             = 0x0000001B;5 }" X: j& H( m5 i2 A; P. X1 W9 y
const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);2 o: K0 q, ?" \6 G( g. U9 L
const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition; v0 c- b2 d8 l4 O  z% G" g5 u6 i$ c
const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
( i3 F6 G1 ~2 Q* g& c- }* b- J
7 h! X+ W9 E+ `typedef struct _SRB_IO_CONTROL
! K! _& H3 u& r/ j; a' x) c. n{
( E* y7 E' Q& U2 y/ x/ l! ~    ULONG HeaderLength;
# k( O# G/ d: f9 `  P    UCHAR Signature[8];, B# J/ r- z( L5 V. a" o% [+ b
    ULONG Timeout;
4 E- F7 U0 V2 b5 c+ N) \3 J* {    ULONG ControlCode;7 R6 o- l0 }; z2 }+ }# }+ a. Y& w
    ULONG ReturnCode;* h* J8 ?8 ~" u7 K/ `  U
    ULONG Length;& O, n! m: p/ G9 f( e2 K# z! j
}SRB_IO_CONTROL, *PSRB_IO_CONTROL;
5 I) P* O& \3 Y9 E9 N
: T, v  S: x" W: R  i: y// 读取的主函数
/ F/ _* G5 P) \3 G4 F6 Y! P1 wvoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);! C( r" [: c9 P) O
# V9 E9 P& o* f, N; M
// 辅助函数
% T- [$ {0 V, L- I; }2 bchar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
9 K( Q! Q$ E+ b* C" I// NT/2000/XP函数
* A* E9 I  U+ {. j7 u1 R- f- `! ivoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
+ r# m0 ]& a2 abool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,7 v% \, _+ x% D, z. t1 n, M
        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
; z0 {! e" O$ X. F, {, A! W        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);3 k+ h# A2 t; J( g
// Windows 9X函数7 x# x: D  W1 n) [+ c0 m6 q
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);, P- x* X7 v; I" j1 ^% Z
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
7 X) I! O3 w/ b% D# F7 W        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
! e. J6 Q) k0 ^8 ]+ J6 y, L6 r( E/ ?% E  s# U# G- H- c
// SCSI读取函数(for NT/2000/XP)/ G0 B% K# m* H' f  m
String __fastcall ReadIDEDriveAsScsiDriveOnNT();1 z) n, Z# |# z% A5 l9 \' E
//---------------------------------------------------------------------------
$ l5 M) ?& S8 z+ {" ]// ReadPhysicalDrive: ^; z- ^" ^! z" Q
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
* V5 N4 J1 v2 b* B$ U- ?{
+ E& h$ r$ n3 D- c: [4 E% G  F    switch(Win32Platform)
" Q1 w5 a, ?2 a4 D    {3 V) p( Q: s* A  h6 d. |" u- i$ O
        case VER_PLATFORM_WIN32_WINDOWS:1 h. j' K6 y0 d% R1 ]9 X3 K
            ReadPhysicalDriveOnW9X(pSerList, pModeList);% R( s& C  Z, f6 x. l5 m
            break;- `' m$ H, d( Y. T
        case VER_PLATFORM_WIN32_NT:
( X6 D. l( F3 }: @% @2 D            ReadPhysicalDriveOnNT(pSerList, pModeList);1 p. M& ~' A$ Z: q
            break;7 b- A6 X1 I, E, [9 E4 Y! a
        default:; W7 g& R% X/ J% P  _
            break;
" I4 d6 l  q, \# z( I2 u    }' z5 K: Z0 d1 Y2 i2 H7 ]
}
. i. Z6 w1 V( k2 U. C5 U* ^//---------------------------------------------------------------------------$ E; N7 s0 F% m2 d5 s- w* c% `
// ConvertToString! M) {8 J# r7 s0 R" O
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)3 J" `+ u6 Z! w8 S
{
+ [" n# O2 R$ `3 w* j2 d    static char szResBuf[1024];
% Y- @- m! h7 i7 q0 d    int nIndex = 0;  K# L( Z8 R  d+ n- C2 l
    int nPosition = 0;
& i0 I% N9 }- d! {" r9 Z  _$ u7 U3 @; E  l/ o# j1 Q! L
    // Each integer has two characters stored in it backwards. B8 f: }4 n7 O
    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
- {/ {' b3 t- I! z0 Q    {& U" @) ~7 Y5 ?, _; O/ T7 F4 `! z3 ^
        // Get high BYTE for 1st character' `) o1 f1 k1 G
        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);5 l: W1 @& P  I9 C$ u3 N6 L
        nPosition++;# w8 W0 |8 C7 X8 m# N
) z# z$ d2 V' D/ t! [
        // Get low BYTE for 2nd character  u% H2 B- r( p  M% d9 _
        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);7 A$ G( C+ Q* D  v. ^
        nPosition++;
0 Q. J4 p6 r9 p3 g  Y    }' m# G5 O! S7 P; ^  N
3 ?. k! y3 _, a( c8 ]7 S1 i
    // End the string
9 h. \4 Q: r% H+ o    szResBuf[nPosition] = '\0';
6 c5 W3 E$ L$ O/ @$ c5 }( N' k% y( l4 s& {/ D$ U: x
    // Cut off the trailing blanks; X& ^# J; a$ W  J$ I
    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
6 F* B2 m5 P4 O" ~8 X+ |" k$ ]        szResBuf[nIndex] = '\0';' A  [2 s, c6 |# F
* F9 w/ \2 v- P: E
    return szResBuf;
$ I. h  Q1 ^; f6 V, X}
; s( b4 K5 A0 s& b" V//---------------------------------------------------------------------------
) ^) Z8 n; v2 s+ ?( M, W# Q3 }// Winndows NT4/2000/XP 代码0 V+ X+ ~; T% J  h$ u0 e' C4 ^6 k
//---------------------------------------------------------------------------
  O' X/ j6 J4 b. D" o7 f* w// ReadPhysicalDriveOnNT
. f1 w% f2 W7 y9 K' E! m+ evoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
, E6 y+ k& C2 m3 L/ Z4 j) o2 _{
# ]6 o# p0 J" z- F" ?. R    // 输出参数7 O" u" S# P4 |0 D/ j! }
    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
3 l- i1 ?, I0 X4 d# T, [' I  ~& G5 [% B3 F, P  J( T& I: h
    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)3 e6 f- N" V: j/ {
    {, @/ d0 Y$ V3 e. q' U# s8 B3 e
        HANDLE hPhysicalDriveIOCTL;" F9 }: }2 L0 S5 o
        char szDriveName[32];& F* l# |! }* c" [! W0 `
" J/ S# g% S* W4 z. G
        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
6 j# Q% [' E, e        hPhysicalDriveIOCTL = CreateFile(szDriveName,/ e/ e3 }1 b  O: H
                        GENERIC_READ | GENERIC_WRITE,1 I. i0 S# S( D5 ^
                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,1 F- r8 U3 T1 L5 S
                        OPEN_EXISTING, 0, NULL);
1 Q* p3 p& R( n2 [& \+ Z7 G3 i+ a
( R" B- L: a: D2 d. j: q        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
( o, l6 P3 J8 @. [        {+ h! z" m9 l! y* N% M
            DWORD dwBytesReturned = 0;
& ?  D( w5 |5 h; F) b8 P3 N* c            GETVERSIONOUTPARAMS gvopVersionParams;/ ?* M' }' V# n/ ^9 p% x- Y- Y6 X
' i3 D' p. H1 f3 ~8 m. m
            // Get the version, etc of PhysicalDrive IOCTL
9 P; F0 j+ S7 f: N  M            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));$ A. c4 }' o4 `2 l# L' `
0 F0 b  J$ g# ^" f  Y; j4 L" g+ X4 ?
            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
2 d& V# s6 f2 u                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),* h% @+ y" F  g9 F
                    &dwBytesReturned, NULL))
/ z7 R/ H; b6 H1 z6 w- y            {
  p# t. y: C- R0 X4 P- N" H! o                continue;
5 @8 c- J4 W$ p( O            }
' o$ A0 b2 n- t  j8 N! i6 h9 _* ]7 O1 j
            if(gvopVersionParams.bIDEDeviceMap > 0)
2 B% O# f* k. ]& }9 X5 ?3 v; ~            {6 E# j3 f; ?% L/ N4 F" H3 ~6 l: O
                // IDE or ATAPI IDENTIFY cmd
* a# w& W+ V: D) ?) @                BYTE btIDCmd = 0;
6 q, B! B' z4 ?2 K                SENDCMDINPARAMS InParams;
# e' G2 e2 K/ H: q9 L( _                // Now, get the ID sector for all IDE devices in the system.
1 b7 O* @$ }$ K6 I3 O# W                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
( H& Q8 L* k( G2 ^8 k( X- Z                // otherwise use the IDE_ATA_IDENTIFY command
, F' m" }# V" V5 p- Z                // 具体所得结果请参考头文件中的说明
! t+ j. i' T$ z2 V, M' c                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
( U: |) [5 ~+ _3 H1 F8 Q+ g9 [                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;- R! n  K; ]; b, O! ~) n" P
                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
$ T! [4 m+ U, w& V- Q5 i# K                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));( o! M$ |0 t$ G, G# c7 q2 P" o
- w+ m% ^; Q; U8 I1 C9 R
                if(DoIdentify(hPhysicalDriveIOCTL,0 ?7 o: G, A( u) c6 N
                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
- m* p, S& ^9 h                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
" W8 m% J% e4 J% D: ?. \                {
# X! l) m" a$ w+ o- R                    DWORD dwDiskData[256];$ H/ s3 d2 z) \  n, P; F0 ~0 c0 v
                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件+ e4 @9 M* Q3 M$ L$ t* q6 P
                    char szSerialNumber[21];
4 K, i# }( U% ~7 U# i# X# e                    char szModelNumber[41];
6 s" [1 j& s( q4 |1 X
9 y) j. r1 g6 I4 l6 c                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;5 x$ M: J6 y2 e+ c! K6 Q4 o
                    for(int i=0; i < 256; i++)
, o! G7 @' M' [% e                        dwDiskData[i] = pIDSector[i];7 [# b2 \) P' g" r; I, d
                    // 取系列号
  ~* I& z! d& X6 \$ h+ a                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
9 q6 d- B, e! E4 B                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));* d4 _- V7 ~8 n  O
3 E) z; v. C( {3 n% P
                    // 取模型号
- ^8 I+ _0 d. ?2 q                    ZeroMemory(szModelNumber, sizeof(szModelNumber));3 P+ x* O% k# Z2 H
                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));8 H: N; U, I! f) S# s  o' V: X

, h; U' C2 l0 b" k# ]) ]                    pSerList->Add(szSerialNumber);/ Y8 r4 z, B0 T" l( j4 w
                    pModeList->Add(szModelNumber);
: U" P  b5 f0 {5 O. Z                }
# ?* X# b* E  p5 r            }4 m" I( R' Q. `6 ^' j# m1 ?4 K
            CloseHandle (hPhysicalDriveIOCTL);
: p' R# z& W. U; _# m  t; S        }0 ~7 S) x' H) Y! r
    }
; g) v0 y; B, U7 b9 f}# X. {$ J+ p. b$ r
//---------------------------------------------------------------------------
6 t* O- K# r  Z: A' H( x// DoIdentify
; A! ?5 |5 u. ~( w) W! k; o+ mbool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,: y% V) \6 [7 E! [
              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,4 {. `" b" x1 B$ b1 q8 T
              PDWORD pdwBytesReturned)
& l& f5 N- V3 e2 I/ w2 S{6 E- Z5 q* E1 H* d3 e
    // Set up data structures for IDENTIFY command.
/ {8 @' z, F" e6 J' S9 d    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
/ W" R9 p( m' k" p    pSCIP->irDriveRegs.bFeaturesReg = 0;. w* o! Y2 O7 @! A
    pSCIP->irDriveRegs.bSectorCountReg  = 1;" I8 b" V5 L/ r5 ?
    pSCIP->irDriveRegs.bSectorNumberReg = 1;7 q# a. x0 l) `5 L" Y
    pSCIP->irDriveRegs.bCylLowReg  = 0;
7 s9 s6 ?; ^9 s6 S    pSCIP->irDriveRegs.bCylHighReg = 0;
" u  O" b& w( M" m, ^" M: |. a/ Y
* R, k1 ^# c: Q4 l; g: N: V3 n    // Compute the drive number.(主盘和从盘所对应的值是不一样的)8 f0 Q: W4 Z; j( |- Q1 q
    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;' b/ z: u% q; ^& h+ I& U2 k

* n* ]5 N0 D7 }/ B2 T1 `    // The command can either be IDE identify or ATAPI identify.
3 A6 ^% h, K9 M5 c4 f, s5 _    pSCIP->irDriveRegs.bCommandReg = btIDCmd;
$ A; o, P7 t# E6 ^0 t+ U    pSCIP->bDriveNumber = btDriveNum;
. ]% Q: S0 U1 v) f. [    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;% F4 e" D3 L* f% g& B7 u4 l

; P8 U" a8 h5 L    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,1 ~* q# z2 Q% k- c
           (LPVOID)pSCIP,
; u8 l% G6 \* u, P           sizeof(SENDCMDINPARAMS) - 1," _1 I5 F: d0 r& @
           (LPVOID)pSCOP,3 p( f. m: F& B# k0 w
           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
) @6 W: ^: n% ^" f9 w           pdwBytesReturned, NULL);3 R. _# J9 t; U  s. ]* r5 o% `
}  T& ~  g, b* p' d% H$ H
//---------------------------------------------------------------------------1 I( H  f1 Z; U6 Y
// Windows 95/98/ME 代码
: X& o. Z9 O9 P2 S5 w$ x* D//---------------------------------------------------------------------------
" W& |4 K- L) Y2 ~/ G! }// ReadPhysicalDriveOnW9X
/ w! ^& c7 q& D9 Lvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)
. S: D7 ~9 e8 g6 y- `1 e{
- L  _' o& U$ x; b$ U" ?9 {  ^    WORD wOutData[256];
  o% }; N7 K7 B5 b    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
8 T9 w& [, J9 n& K: w5 h) o
+ D3 I. d; k/ O2 S" f# S    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。8 E: O1 U5 c3 R6 ~5 G
    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以; z7 i, X* T/ b$ i; d0 q
    // 避免蓝屏的出现。(期待高人能指出原因)
2 H4 [7 ^7 V9 }  P5 O    for(int nDrive = 0; nDrive < 8; nDrive++)
% _1 G1 ?0 K) Q9 `    {6 m! l8 @2 b, n# @- }+ U) c/ c
        WORD dwBaseAddress;0 j* w+ [) d0 ]: o! p
        BYTE btMasterSlave;         // Master Or Slave
$ D+ y; p6 [& m4 ]! R; C. _( U3 ~  P( r  x        bool bIsIDEExist;
, n6 G! x* k- _* X- j        bool IsDiskExist;
' ^1 m) \; j! O
6 ?! }: Y$ v% L) y( E9 W: S9 P, ~7 N        switch(nDrive / 2)
1 K; A- g: J8 H$ W) L        {, w: ]% r' L5 O1 c2 Z
            case 0: dwBaseAddress = 0x01F0; break;
3 z3 ?; p# \' h$ M0 f) H            case 1: dwBaseAddress = 0x0170; break;# D# [% J- b' Z
            case 2: dwBaseAddress = 0x01E8; break;
- q" ?# c7 _" w            case 3: dwBaseAddress = 0x0168; break;4 O9 V. J; H. J- B
        }3 [% a7 |" D5 [! q" @$ j

& B8 C% ~, F9 B% h) T$ D: v. Y1 q        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
; K6 f  i5 ]9 d# p& \$ n( f( P- j& _
        // 进入Ring0
$ Q0 y5 g& L$ b0 S* L        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
0 \8 j7 u( E/ X3 T+ r& m                bIsIDEExist, IsDiskExist, wOutData);+ V  m; u8 B  B* L
    }7 @3 Z: @) M. w9 Q% o) S; o# e4 d

0 |: R! H! s% |6 e0 K) ?. `- [5 T    // 开始读取0 m' A+ `3 `% |* S/ M
    for(int nDrive = 0; nDrive < 8; nDrive++)" I2 r( S; \2 v# N1 Z& n( l/ e2 l: {
    {
. G9 C  @+ x4 s        WORD dwBaseAddress;
. T! F7 L  Y# q; K: i/ D+ b* {        BYTE btMasterSlave;         // Master Or Slave
- {) R+ i+ L& M0 o- o        bool bIsIDEExist;
0 d* Y# r, s# f/ @- p3 Q) ]8 C        bool bIsDiskExist;# G8 T6 v$ W9 Z/ y1 Y/ P
        switch(nDrive / 2)5 L) U8 n* ^( {; F: m
        {. p# V3 C. a6 t# a' z( N7 A
            case 0: dwBaseAddress = 0x01F0; break;; A( ~# n! |) b. ?, w. O8 B
            case 1: dwBaseAddress = 0x0170; break;
/ V& h) s' ?/ q9 m) o( |( Z: K            case 2: dwBaseAddress = 0x01E8; break;
8 d  `; }! Y* y7 a% M: p            case 3: dwBaseAddress = 0x0168; break;
  k& v- H+ i" o8 f        }
3 q) I( h% O+ p7 w' g# n7 [$ d0 \, y7 z4 z
        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
+ b/ L: q5 n5 \$ R; X- q
8 j9 e. J! v: s  o        // 进入Ring0
* k6 z4 ?; g: e  P# ~$ M        bIsIDEExist  = false;5 ]0 y9 s% a" ?' v1 w8 @7 O4 H6 G
        bIsDiskExist = false;
5 \- `* t) y; }2 ?: B        ZeroMemory(wOutData, sizeof(wOutData));
6 W- \8 w3 Q2 ~, b# |. K
, i4 x3 ]7 M2 ~1 z        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
9 Q" {* a( f. I0 r, a$ i, m" |' T                bIsIDEExist, bIsDiskExist, wOutData);
: `2 f/ l. V! ^( n6 o
- X2 I* l, E* H$ O- d' r) V        if(bIsIDEExist && bIsDiskExist)
/ h. J5 _. A& c2 S+ N. w7 Z        {' ~8 ^/ ^9 m) M' S9 n. a% [
            DWORD dwDiskData[256];
7 c  M8 Z1 p" p: `" r, j2 }5 z1 T            char  szSerialNumber[21];9 e1 X5 f3 n4 z+ U- x- U+ }
            char  szModelNumber[41];- ^5 s6 z( j2 }
3 R' B: {$ S; w; w
            for(int k=0; k < 256; k++)
. ^8 A; D$ s8 _' k* Q1 _2 r                dwDiskData[k] = wOutData[k];. Q% K8 k+ @2 B) B3 \# O
6 b  q/ Q3 I9 t
            // 取系列号
" M# l2 _$ O$ I4 l7 ~            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
1 Z3 q1 J3 v- U+ b            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));! b5 g1 g- C$ q9 Y4 I; w/ O: E5 l0 u4 t& r

/ ~0 q  Q! z/ `. `            // 取模型号
. H  B6 j( x( d) |1 t) E3 ^8 d            ZeroMemory(szModelNumber, sizeof(szModelNumber));8 g: N& s" W# g* F# K
            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
6 Z+ ~) Z7 x& F) u; V: @. `
- r6 |7 Q; B2 G: X6 Y# p( [            pSerList->Add(szSerialNumber);
9 X9 P4 ]& ]0 w% b, Z8 S% `            pModeList->Add(szModelNumber);
* Z3 I/ l& G5 x+ K1 @- x, n        }
1 B9 B$ L. L+ {# i5 Y    }& q  }5 a& P# X% c6 t1 G
    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);* T9 P. ]9 M& ^- N5 G
}- U% R+ L4 n+ a, j' {
//---------------------------------------------------------------------------5 U1 P$ d7 s8 y; K. ?
// 为防止不负责任的转载者,在此注明原出处信息,请见谅。5 i  Q8 h. M( i; X5 M) _
// 资料收集整理:ccrun(老妖),欢迎光临C++Builder研究: http://www.ccrun.com
8 n6 S: r' j2 H- N; k//---------------------------------------------------------------------------* S6 [, \3 o, T  H4 A
// ReadPhysicalDriveOnW9X_Ring0()3 E/ g, a2 x8 Z
//
! N- h! P+ T9 g$ x. ^// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h7 p! [- v" B' K% E! a
// btMasterSlave = Master(0xA0) Or Slave(0xB0)$ F; i% n) g8 [
//---------------------------------------------------------------------------
9 P0 h& K9 I" L9 V3 tvoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
1 N3 X1 v! r: F+ x. k        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
& Q( I' O: `0 ?! s1 h{  O  M/ w, l& ?) F- l3 A. t9 P: c
    BYTE  btIDTR1[6];
0 c5 E2 P# W3 Q" E  L+ n! i! J    DWORD dwOldExceptionHook;
1 w5 g3 u" Y! f" @! F    const int nHookExceptionNo = 5;% p9 Z# X# d. ~

' i' Q) U9 Z3 J4 d1 p" ^    BYTE  btIsIDEExist = 0;
2 T$ ?  y* Z5 o, I7 S1 i' c    BYTE  btIsDiskExist = 0;5 R7 \/ @9 t* t
    WORD  wOutDataBuf[256];5 y6 t9 Y% {5 E9 h' @
% B2 D: p! g( u6 \6 ~, \5 o
    BYTE  btIsFirst = (BYTE)bIsFirst;2 x4 W4 d9 x* P7 g) D

  [" F! o) v1 z: [    const BYTE btBit00 = 0x01;- M/ [( }9 G' [2 u
    // const BYTE btBit02 = 0x04;
6 d, ^/ g2 l( M. h4 j2 f    const BYTE btBit06 = 0x40;
; b9 N! f8 Z# D    const BYTE btBit07 = 0x80;
6 W& j4 [( V* q+ U    // const BYTE btERR  = btBit00;/ z/ s" Z, o1 ~5 @" \8 D$ `
    const BYTE btBusy = btBit07;, _4 l' E! }! ?/ P" S; o$ f
    const BYTE btAtaCmd   = 0xEC;
8 K9 S5 ~: L6 {9 Y+ e$ Z( `    const BYTE btAtapiCmd = 0xA1;$ \1 f0 _) C9 V$ Z  N
. W! t- E4 Z+ d/ t) i) s" H, O; [
    __asm
1 m* c, }: N/ L: l$ k. \) S    {
- D0 G, W$ f" \4 J1 x/ L( O9 b: `& g        // 必须先执行这条语句9 `! p" ]# A  g: o6 d
        JMP EnterRing02 R1 P' L/ V1 C6 U5 A

& {, }5 w; R8 t6 z        // 定义过程4 [0 h; ^6 ^$ g+ T" U
        // 等待IDE设备直到其不为忙为止# ~& \6 @0 f6 g0 _
        WaitWhileBusy proc9 F% x( F, ?8 N7 r* ?
5 _7 c6 b: s* ?" n
        MOV  EBX, 1000000 T  u+ Y! ?6 d* j7 n* p
        MOV  DX, dwBaseAddress# {6 V6 X, V1 D# h3 i+ B. ^* i
        ADD  DX, 7
9 _' Q: Y. d0 I% i* N
0 z+ p* R* y/ a1 j) V# c1 g$ g        LoopWhileBusy:
7 f, n6 q1 s/ [9 u' u% k+ z$ f4 t' [, L8 m  ^* C  M& Q5 }
        DEC  EBX
) U! \; D! ]8 w, G, _        CMP  EBX, 0
" A, L* h) ], b* k! f( d        JZ   Timeout
: x5 a: D" b8 M        in   AL, DX5 v3 [7 D3 g/ @. S
        TEST AL, btBusy
- E. J7 x2 |' b- F, L( e5 s8 i        JNZ  LoopWhileBusy$ t+ G! t% G6 H0 F  ^& a
        JMP  DriveReady
: |; J+ J/ n" J' \( [
! q) P8 R- E" i        // 超时,直接退出% L: F" o& c$ S8 M
        Timeout:
' M& ?9 i! ^6 t8 Q% s" ^4 O  m5 Z" V( {        JMP  LeaveRing0) I, X4 i5 T6 y/ z" l) u4 F9 `
        DriveReady:
: C8 N0 @$ b% B; N        RET2 n8 ?$ n3 H3 E. x, d$ i2 N
        ENDP   // End of WaitWhileBusy Procedure, k  k, R9 R8 `" C
$ q0 U! y2 [  }! s" k0 `
        // 设置主盘和从盘标志
) A4 a2 M" P! o) a. M7 }        SelectDevice proc
, D" ?+ L9 q$ p7 |2 B
- K% p5 O* W, a) {$ v8 M3 }6 Y- }! D! m        MOV  DX, dwBaseAddress3 H& N/ r! Q  d
        ADD  DX, 6
) u' R6 H" Q5 M4 Y7 d        MOV  AL, btMasterSlave; n8 ^7 R. }) L! J

* x+ |( O" s. g* a        out  DX, AL
. c3 Q+ E8 C& S' @' T5 y6 r        RET9 F* h/ g8 J* u& X/ }7 W* t
! i# ~/ o7 h4 p5 S, U
        ENDP  // End of SelectDevice Procedure% O6 J& A! w1 _) {0 h/ M2 }

) n6 F& N. o( o" X        // 向IDE设备发送存取指令+ f% O9 ?- F" Q* O* b- `. s
        SendCmd proc
9 l1 q! w0 I, K! f! g8 J6 p
+ L" R* v6 c1 m* P        MOV DX, dwBaseAddress
. V8 x& E- c4 F& r        ADD DX, 72 N; ^0 Q+ U( r# p; u* y. S& u
        MOV AL, BL // BL是主从盘标识,在过程外设置
  [+ G2 c# `+ b5 i: B! t5 B+ u        out DX, AL$ P+ m3 _! D) x
        RET2 |& w- H4 w, a$ N
        ENDP  // End of SendCmd Procedure5 R4 q9 y4 v5 b) @; ]% R

4 d* L' \! k( R  U5 {' c8 h        // Ring0代码
1 J$ R. ]2 t7 Y: D8 t# e  z; y        Ring0Proc:( {2 B) i7 D  `1 D* P
        PUSHAD
( s  `4 S; F* e7 [5 q/ M& e2 @* X        // 查询IDE设备是否存在3 `% i' _: I% L7 \) ^- P3 R& k
        MOV DX, dwBaseAddress
1 l8 T8 Z3 g) ~. Z) e        ADD DX, 7
% ]- X3 Y1 v; E% q+ L6 x: M1 Y2 ?        in  AL,DX- Q! A& {0 |( a, E& ?9 \

6 k3 n' s, e$ g3 [! ]        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
. u  h) B# A3 e# e' r& p# W1 T        CMP AL,0xFF
- d, H, j! s' A5 E" \        JZ  LeaveRing06 N, W, {* W) h- N4 @
        CMP AL, 0x7F( U& _# [. d& e: D* n) V. }
        JZ  LeaveRing0
+ {1 R4 [* @. l" f  I. [  f* Y7 H5 c* P- b
        // 设置IDE设备存在标志
8 _: A  J  f; A' o4 S  K        MOV btIsIDEExist, 1
3 ]7 A, Y: a3 D: f- _' Y
* H! T" y, a$ O$ N/ p! K        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)! U4 c& T5 k9 w3 d
        CALL WaitWhileBusy
3 N9 x! |, N7 p+ ]        CALL SelectDevice% J$ K9 r& M" s
2 ~3 ~+ t$ Z6 }1 C0 {* k
        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
3 P7 y) X$ ?6 v" R# R4 ]+ H        CMP  btIsFirst, 1
* t0 R; W1 Y- _  `! ?1 J        JZ   LeaveRing0  y" w8 m  [* {/ [2 [  f

5 b. h! ^, I; C        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???7 p/ X0 m, t* g3 J4 }1 L( s( Y
        CALL WaitWhileBusy
8 l7 X) [5 d3 U. }1 M0 A( o' n: ]2 ^
9 b0 q8 c, ~: E: f2 e7 f  @        // AL的值等于cBit06时,不存在驱动器,直接返回
( K. b. S9 @- k5 C        TEST AL, btBit06
, I9 O/ H; G9 s        JZ   LeaveRing01 N# y! B" D0 p/ Y( W
0 X5 N+ y+ I- k, n6 H9 m) K0 h8 F
        // 设置驱动器存在标志* ]& d- q4 e* M9 G
        MOV  btIsDiskExist, 1% `$ V5 Q% g3 j- I: J+ `0 ^5 k
& H# v# ~* G  T. |
        // 发送存取端口命令+ T* b, q7 K8 [5 m6 Q* w, ?
        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型," _5 y' r8 Y! m
        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
& i. ]6 T0 n( ^1 O. B$ |        CALL WaitWhileBusy
; n$ u4 a1 U# C! H) Q$ K2 r2 R        CALL SelectDevice    // 设置主从盘标识
  R% ~3 R8 T; v) `: Z+ ~4 |        MOV  BL, btAtaCmd      // 发送读取命令
4 h0 M" n1 o9 l        CALL SendCmd3 O* }: F: H% u2 v6 g
        CALL WaitWhileBusy
0 @* H! b! Q# b1 z% U0 t; S
7 H% i) |! c# d" ^) N        // 检查是否出错
* `; g5 J& r1 ^        MOV  DX, dwBaseAddress
8 K# ?' r/ @( y, @# I/ t3 y/ w) E1 a        ADD  DX, 7
% D3 ?- B. `7 n. h( U3 U
  R  s( l8 S2 I4 V) Y: s; }        in   AL, DX9 L% p, ?  h8 i. ]/ ?' z
0 a, E( {* \, S) N. i. o
        TEST AL, btBit00
, c8 G) s+ g* H. b        JZ   RetrieveInfo   // 没有错误时则读数据
: m  ]& z4 a* I$ K9 h2 G3 N2 @4 r  H
/ l( y' Y1 @5 c! D2 G4 v2 a        // 如果出错,则进一步尝试使用ATAPI设备命令% x5 j( ?5 a9 j3 n2 S1 ?
        CALL WaitWhileBusy
. H6 y3 n& D% m1 f# g5 m        CALL SelectDevice2 ]; p" D! U& g$ a0 z: X
        MOV  BL, btAtapiCmd3 o$ w# _; z3 K5 W6 L% y
        CALL SendCmd
/ A, w0 C* z7 r( u        CALL WaitWhileBusy, |3 T/ T5 m7 b& L! r, ~/ @

) D' L7 g9 `/ B        // 检查是否还出错4 n( H; d1 T5 a+ ^# P& }0 c( Z
        MOV  DX, dwBaseAddress5 N) h% v  E4 \% |+ @9 }) M5 G
        ADD  DX, 7
7 {3 j9 u% n# e- E! F# |  \9 R        in   AL, DX
) A: C- R5 d% p5 N/ ?1 r: W! k5 v        TEST AL, btBit00  A: m& c/ P  p# I# H( m5 u5 I
        JZ   RetrieveInfo   // 没有错误时则读数据
% R, [; a- C2 U6 N        JMP  LeaveRing0     // 如果还是出错,直接返回
& Y/ P3 ~" E2 x% p
, f9 X0 B$ o9 S        // 读取数据' I. c3 x: R% S# h
        RetrieveInfo:
/ Y5 J5 C! L- ^* T- @: m4 n4 O. g' }: j3 X
        LEA  EDI, wOutDataBuf
. P; h, W( \% ~1 Z1 T+ Q        MOV  ECX, 256/ X9 k; l( N# X4 E# J0 e5 d! i
        MOV  DX, dwBaseAddress
& @2 g6 E: z7 g        CLD
1 W+ f8 j; c) O# F" F, x/ w3 ~: a6 S! f- D
        REP  INSW
6 u9 }6 j. x( d5 T7 Y  |( {5 Z5 e9 e  R& y
        // 退出Ring0代码
. a& c5 G, Z' j2 _$ C* u3 `        LeaveRing0:
6 a4 S2 i. L& a- ?) j+ f* ^$ W2 s
        POPAD
" h, F: J  Y$ m5 C2 [9 o" }        IRETD. g0 T8 m2 A* @3 H6 x
  C% v1 {! o4 b/ y" G9 _+ V7 C
        // 激活Ring0代码
: P( X. i2 B' |+ z% B        EnterRing0:; y  a) H% v: Q" @+ R  h

' N% d. C( R- t' U0 j" e        // 修改中断门
$ E1 D+ h4 c9 y: Y        SIDT FWORD PTR btIDTR1! k6 M. e, I: h+ n3 C
        MOV EAX, DWORD PTR btIDTR1 + 02h& ^! P# G* u. b0 H7 b) Y; C
        ADD EAX, nHookExceptionNo * 08h + 04h
3 e5 x: O) ]; u! P) V+ V        CLI
- v" g4 E4 |2 `$ S
$ d6 }2 F- a" n4 s        // 保存原异常处理例程入口
2 U# X+ S8 b2 j8 |2 B" l. u        MOV ECX, DWORD PTR [EAX]
% ^! a% h5 P. v5 u- {        MOV CX, WORD PTR [EAX-04h]- b+ R' e# p, T+ f( l0 |" }
        MOV dwOldExceptionHook, ECX
; {7 I! D. Z9 {5 `8 m# l4 Y' n" n4 V1 h3 B, A: ^- L2 Q
        // 指定新入口
# n3 \, \, i2 }% W5 C        LEA EBX, Ring0Proc
" l7 q, Z6 q" r+ N        MOV WORD PTR [EAX-04h],BX
. b5 J: H7 @9 M1 m. b+ |+ |        SHR EBX, 10h
% j5 b2 p6 H' P1 \/ V        MOV WORD PTR[EAX+02h], BX
4 ]9 o. E( z2 N  R
" N. L3 X- o& r0 v2 z4 k7 S, t        // 激活Ring0代码
; {3 @! ]& J7 L# p0 ~) h9 L$ `. W        INT nHookExceptionNo, ~. N- d' r8 E+ E( U9 B! s* g

, a- F. s+ b* L; o        // 复原入口
. f2 q8 z( `" J, J! X! v        MOV ECX,dwOldExceptionHook( ]" `. C* V! m
        MOV WORD PTR[EAX-04h], CX( O7 Y# @# n: A4 Y/ _9 j
        SHR ECX,10h
8 j- T  G' u- l. _- O7 o! U" \        MOV WORD PTR[EAX+02h], CX
7 B1 I6 l# B, a6 ]& U# x        STI
6 Q7 N/ j9 H  I! Z' e" X    }
0 G+ E' _1 \+ U8 m* f4 I' m    if(!bIsFirst)/ f. |0 S. S- V' ^3 u' z
    {, I1 f% K" W+ E+ p  ^
        bIsIDEExist  = (bool)btIsIDEExist;
; X2 E  C& _: @  t: t        bIsDiskExist = (bool)btIsDiskExist;
& [2 S$ a1 P% W# v, [        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
3 f4 ^* T  R2 z0 i! }0 ]6 G; I3 V4 s    }
8 o; W: t; B" t/ o' Z4 s}" _) [/ ?' m, G6 g& K
//---------------------------------------------------------------------------' Z! w9 N% B+ L+ \  _6 v" z' l
// 调用方法:" s" W: b0 I2 l) U/ ^
void __fastcall TForm1::Button1Click(TObject *Sender)
6 ?9 }* H( m1 k' V. ?2 w: X{
( Z6 G- w) ]& R# a9 k  s: o9 E    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
( ]* f, t7 e$ x: P, A  D4 V}
% r1 K! Z1 F' ]' Z) d$ q# O) F/ K9 A
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-10-2 02:38 , Processed in 0.020343 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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