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

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

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

  1. ! n$ e5 e% Q3 ~" b) H  c
  2. #include "StdAfx.h"
    + ~$ `! _- l/ v2 x+ |
  3. #include ".\puiddisk.h": `% Z7 [, H% g; s0 w: q
  4. #define _WIN32_DCOM
    ; \! t% e" Z& H8 @1 G8 c& |
  5. #include <iostream>
    1 w* {" x: F5 v. j! D+ `; ?
  6. using namespace std;
    1 ?/ G: K) V7 }: @
  7. #include <comdef.h>* O1 }$ D* J+ |1 A3 g
  8. #include <Wbemidl.h>
    ( x- l: d: ^5 M% s2 T; P
  9. 7 J. t% L2 \+ J- P2 h& C7 w
  10. # pragma comment(lib, "wbemuuid.lib")- e% F) l3 ^0 R$ E( D1 }4 Q
  11. CpuIDDisk::CpuIDDisk(void), r( G1 n& W$ \+ d
  12. {1 r9 s/ g7 W8 f' b7 T
  13.     GetInfomation();
    + r! g& m, v1 q4 d/ ?
  14. }
      ]$ l) J. \: d" y. V2 x( a

  15. 8 z3 t! ]1 s+ G) L1 O, c' G
  16. CpuIDDisk::~CpuIDDisk(void)1 R( T7 O  c. p* h; P+ ~
  17. {, O; X) d" d) f5 S7 X; h( D& T
  18. }
    5 U! [6 F  ~# A% h+ U
  19. int CpuIDDisk::GetInfomation(void)
    + [1 m1 F$ H3 ?0 Q; O' v- s
  20. {: L( O7 B' G) {- x" z
  21.     HRESULT hres;4 E6 i) g0 {, ^
  22.     //步骤1:不是必须的,COM只须也只能初始化一次, d/ V$ @9 Y- ]- a- P$ E# i
  23.      hres =  CoInitializeEx(0, COINIT_MULTITHREADED );
    % V* M- t; c& x" T5 t1 |
  24.     if (FAILED(hres))
    . w. a& y, i% ^8 J
  25.     {
      t6 T  |" K+ K  O8 f  w4 }8 k
  26.         return 1; //初始化COM异常:注意,COM只须也只能初始化一次7 H- [) b  B/ E/ O; M
  27.     }
    5 l4 S/ A+ N/ V1 p: p+ O
  28.     //步骤2:不是必须的,COM只须也只能设置一次. k7 q& _1 ^8 _9 h/ Z
  29.     //Set general COM security levels
    : H" u+ D1 f; O3 s# n: P: l
  30.     hres =  CoInitializeSecurity(' q9 P- v7 W) N3 C* ]
  31.         NULL,
    - E' x  ]' m/ b, K% Q  X: W: O
  32.         -1,                          // COM authentication
    / K% f% {/ ~8 @
  33.         NULL,                        // Authentication services
    1 O2 I% ?7 P. a1 p! b! G( R, _- n5 U: _
  34.         NULL,                        // Reserved
    * T5 [3 `) h: `+ d
  35.         RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication
    + S5 u! E; T0 y- e" T- }/ y7 R
  36.         RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  6 V9 r2 n4 Q8 n4 S8 p/ A
  37.         NULL,                        // Authentication info6 r% I+ P! r3 p5 n
  38.         EOAC_NONE,                   // Additional capabilities 1 @% L8 g8 P2 j6 ^3 b. {
  39.         NULL                         // Reserved! ?- {: `) F3 u7 S
  40.         );
    9 b1 ^+ u: h* s) X  |$ B3 P
  41.                      
    ! W* _# A7 [/ y# Z/ t# _: k0 Q  f
  42.     if (FAILED(hres))
    1 g; @6 ^# ]7 b. ]6 p. b
  43.     {* z5 Z5 S0 X" N
  44.         CoUninitialize();" k8 w; S& q. w" ]9 h+ ~" b
  45.         return 1;                    // Program has failed.
    ( w' e* G& }; R; C1 M
  46.     }$ j& D  h. h' ]9 u
  47.    
    * K: R$ N1 ?( u; k
  48.     //以上不是必须的,若已有“::COMInit();”,则要跳过
    " Z* y1 l5 m1 y% c# V0 m
  49.     //步骤3: Obtain the initial locator to WMI $ A1 P& @6 ^* T/ i. U  B; T, ]
  50.     IWbemLocator *pLoc = NULL;
    0 \  d+ D/ `& I8 {" W; t- R# ~
  51.     hres = CoCreateInstance($ ?9 U4 N  d  W" ~, D6 z& j
  52.         CLSID_WbemLocator,             9 S$ @( k, `' u% X
  53.         0,
    & O7 W3 L8 J+ q1 M" ~
  54.         CLSCTX_INPROC_SERVER,
    6 [* Y5 G1 c' g1 B8 j6 N
  55.         IID_IWbemLocator, (LPVOID *) &pLoc);
    ; M  o+ A+ L/ F# |& L

  56. " N* k) h8 j) h: F5 i+ a( ~/ f
  57.     if (FAILED(hres))8 ~& Q4 o4 W4 d
  58.     {
    6 M( z/ E( p5 z3 T
  59.         CoUninitialize();
    * r& ~2 D" v' V1 l0 @. c$ T. V
  60.         return 1;//Failed to create IWbemLocator object: M$ J; i. Y7 c9 P
  61.     }
    1 ?: `( k7 m. ?
  62. ; V1 m/ ]* z# C+ Z
  63.     //步骤4:Connect to WMI through the IWbemLocator::ConnectServer method8 N  q6 r3 s0 Q/ q/ K
  64.     IWbemServices *pSvc = NULL;
    " F4 z! l: h; p& j4 w$ u$ o
  65.     hres = pLoc->ConnectServer(
    . @, |: w: i% L6 i: Z3 A4 E
  66.          _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace4 m& v1 m* L2 W& I" s' m! Z2 H
  67.          NULL,                    // User name. NULL = current user
      F% z9 [7 ~* r  w9 b! w$ V+ H9 }0 U
  68.          NULL,                    // User password. NULL = current
    ! f; R& U; l% k# T& f
  69.          0,                       // Locale. NULL indicates current
    + |: b6 J6 C# `; }6 k4 F* L
  70.          NULL,                    // Security flags.
    ) U& Y: x! }, R# v/ @# C0 t) S
  71.          0,                       // Authority (e.g. Kerberos)) M' C+ b  E: `: {7 T: o
  72.          0,                       // Context object - b( u" w0 K. C4 D3 Z
  73.          &pSvc                    // pointer to IWbemServices proxy8 J' b' v+ c% ~, U8 X0 u* z
  74.          );  h2 I) d( e5 ~6 u3 A8 a
  75.    
    : k6 z) d8 H, G( b
  76.     if (FAILED(hres))
    ) x+ m5 g1 L* Y) g+ D  s2 B
  77.     {  c; I& ~& s- r
  78.         pLoc->Release();     
    2 G& D! k  @- d. m( ]% ?& V" d& c
  79.         CoUninitialize();# q9 o; h; P; ^, ]' l, z6 G3 f
  80.         return 1;                // Program has failed.' S; j9 j1 w1 X$ Z- J
  81.     }3 [+ a- g4 y# ?7 |8 `+ ~
  82.     // 步骤5: Set security levels on the proxy2 s6 I9 o# A% o
  83.     hres = CoSetProxyBlanket(
    6 y  }2 }: u$ M1 P
  84.        pSvc,                        // Indicates the proxy to set
    ) p1 |: z% v; j& q3 m* H# k5 p
  85.        RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx
    4 I4 t* V, g1 T0 T- Y& m
  86.        RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx, H& H" ]$ v' I7 M
  87.        NULL,                        // Server principal name
    3 I$ H( @; |6 x# ^1 M+ x3 d) M
  88.        RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx ) N5 R- |. \" c/ ^- b  Y6 L# f
  89.        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
    * T7 [& T( {6 z& R5 H
  90.        NULL,                        // client identity8 p* W8 ^) W  r2 ^) E
  91.        EOAC_NONE                    // proxy capabilities 6 B: q. k  g; i2 e1 V) d: ?7 S
  92.     );: c& E9 ]1 o- \; I( F

  93. 0 C! C( K. ]5 U6 s# I
  94.     if (FAILED(hres))$ Z, r8 b' y# ]( _6 u; o
  95.     {3 H2 _0 e, Q# B' F
  96.         pSvc->Release();  X8 V+ y( h* A
  97.         pLoc->Release();     
    # N" H* g7 ~+ F7 _% V5 B5 A+ }1 h
  98.         CoUninitialize();/ ?" }6 |# T6 n. Y, x
  99.         return 1;
    0 J# \( B; W! T5 f" u; o" D
  100.     }
    2 S$ ^8 ~1 h3 I) }8 i, L) V7 t
  101. + s9 k- S- @- u; J% D
  102.     // 步骤6:Use the IWbemServices pointer to make requests of WMI ----
    . C4 H( C& K2 m5 p; d; x9 r
  103.     IEnumWbemClassObject* pEnumerator = NULL;3 X. y- t& `7 }* t+ H$ F4 i
  104.     //计算CPUID
      U$ h, B5 m- w, {
  105.     hres = pSvc->ExecQuery(
    0 u9 i, E3 O; |" R- l+ k2 D
  106.         bstr_t("WQL"), 2 {) q6 g6 n% \2 t5 G
  107.         bstr_t("SELECT * FROM Win32_Processor"),//Win32_OperatingSystem6 o' l6 a; x3 G  M0 H# _
  108.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
    7 j" g$ o( g9 K9 w$ n
  109.         NULL,
    ) r$ P7 a& Q. K3 w3 {
  110.         &pEnumerator);; l! n4 U, }; p  m; ^7 T. K
  111.    
    3 v6 M- w6 N2 y0 [7 Z, v+ y  N
  112.     if (FAILED(hres))5 o, T4 ]$ _1 V' |2 \) q% T  Z" f
  113.     {
    ' S( g4 e+ V7 F" h
  114.         pSvc->Release();
    0 r" Q; h% `; A. |' R& Q3 l$ Y8 f
  115.         pLoc->Release();
    6 ]1 b* Y! e4 y7 y- Q0 w& C8 {
  116.         CoUninitialize();# Z$ b2 n8 l" G9 W1 Z
  117.         return 1;) h; t4 }( n- h
  118.     }
    , H9 F/ j0 n8 Z2 p1 n6 U3 L
  119.     // 步骤7:Get the data from the query 6 V3 ]3 D* m7 D) `8 X
  120.     IWbemClassObject *pclsObj;
    ' F9 R. ?& G8 f" A& [. d5 {
  121.     ULONG uReturn = 0;+ L* Z' d& m1 ]
  122.     while (pEnumerator)( _+ u3 m6 D* w2 F6 {* s4 a4 y
  123.     {5 l3 Q, {9 [6 f( G7 i% D
  124.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
    ! O- j; h& \1 }
  125.             &pclsObj, &uReturn);
    5 k# ?$ W3 e7 R1 f3 @

  126. & I6 S8 P$ A9 C# l' X7 o8 O0 e. E
  127.         if(0 == uReturn)
    3 o( W* J' W$ ^$ }3 j/ A
  128.         {
    " m4 }7 I8 e  d5 b& Y( U. [0 x
  129.             break;
    ) Q% Z2 j; H3 p" r% d% B( ^
  130.         }
    & V7 y9 |3 ~( @% v4 ^
  131.         VARIANT vtProp;
    1 u; v4 S, K2 F! W3 a
  132.         VariantInit(&vtProp);
    6 j7 Z3 R0 i5 g) z$ w& d9 B' L
  133.         hr = pclsObj->Get(L"ProcessorId", 0, &vtProp, 0, 0);
    - ~' K8 _6 A3 i
  134.         strProcessID=_com_util::ConvertBSTRToString(vtProp.bstrVal);//strProcessID:类级变量1 s- i  z& x7 K" h/ P! o
  135.     }, b$ p8 ^; ?# R/ d5 d1 `

  136. 4 H+ B5 o9 C  a% w( [
  137.     //计算硬盘系列号
    ) n3 \- ~$ O% @" M4 n5 ~! X/ C
  138.     hres = pSvc->ExecQuery(' k4 N- b+ I6 l% S1 r
  139.         bstr_t("WQL"), $ n; P5 L9 G) P. y# g6 G# o
  140.         bstr_t("SELECT * FROM Win32_DiskDrive"),$ G; m+ h* ^5 i& G; d% u5 F
  141.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
    4 ?; d1 s+ A3 c! l
  142.         NULL,
    2 F8 v  L3 P- H( z3 i
  143.         &pEnumerator);9 @& j0 u! u/ q( _) O( L0 h

  144. : ]4 ^$ }( T, U. X/ @# P/ d) M8 q
  145.     if (FAILED(hres))
    ' E, Q2 c3 r6 O0 z" F! [; K
  146.     {6 s; @( ^  j2 @1 C: |- A  ~
  147.         pSvc->Release();
    ' \9 `8 ], O$ r& F* A1 ]. W6 r0 J
  148.         pLoc->Release();% z' R$ c5 Z' J5 Q! u
  149.         CoUninitialize();
    ) B% H0 q; ^8 [; Q- }/ C
  150.         return 1; / Y& U# d7 Z* u3 A5 D7 Z  `3 m- c
  151.     }
    ) ~  m9 v6 [- H: L7 h7 G# @! g8 J
  152.     while (pEnumerator)4 l1 H, K. @- y) S8 ]
  153.     {5 N% X( s% B3 u/ ]* M7 g
  154.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
    ; e# |3 R  q4 v, O" b3 V
  155.             &pclsObj, &uReturn);
    / ^' T# g5 {) B- I

  156. ( M1 \6 t) b0 z& ]
  157.         if(0 == uReturn)' D) Q! }4 ^! j" ?# k5 o( x
  158.         {
    0 W- l2 {' {3 }- X. ?$ o
  159.             break;$ B8 J# J! q6 [( K6 K5 A! Y
  160.         }
    ( J' I& y: B' n& L- T; I

  161. 9 b) h2 r7 J/ Y; I
  162.         VARIANT vtProp;$ U# r  U% p5 F6 O* h7 K
  163.         VariantInit(&vtProp);
    ) s7 w  y; M2 o( n' ]: B. g
  164.         hr = pclsObj->Get(L"PNPDeviceID", 0, &vtProp, 0, 0);! d5 ?( j, y' U4 C9 v$ N
  165.     strDisk=_com_util::ConvertBSTRToString(vtProp.bstrVal);1 q# }- I; J( V6 D# Y8 t- E
  166.     }" R2 @: M- U7 M: B
  167.   k5 v# T6 p1 R" t( g. k) V
  168.     pSvc->Release();$ E) s! ^3 T" d0 N
  169.     pLoc->Release();5 o' @/ w1 l; E- P: j2 B3 s. n
  170.     pEnumerator->Release();
    7 q0 j. D* j, R% U7 Q2 h
  171.     pclsObj->Release();
    4 A1 O) C# D" j
  172.     CoUninitialize();
    - p( }/ t4 M9 c0 z* s- Z  w

  173. - f  m' V+ Z7 v( |$ P) L- J
  174.     return 0;   
    + y8 f  T0 B5 g+ D6 h+ i0 R
  175. }
    , T% F* P/ f9 B5 w4 x
复制代码
 楼主| 发表于 2010-10-11 19:21:05 | 显示全部楼层
本文代码经ccrun(老妖)在Win2k下试验成功.2 ^) S0 X% N& c2 S% V: b
+ @: p0 u: B6 g/ d  ]1 Y1 G) V& {4 h
#include <WinIOCtl.h>
: d7 |) ^3 _7 P( q5 Q#include <stdio.h>$ `* I  I1 Y/ d: ]" T& s
. S0 m8 N& s+ a7 }
#pragma inline* c! m) w0 t7 {# e* o
//---------------------------------------------------------------------------
. W4 O$ x, G. q& L8 N# c" g; L1 l// IDE NT/2000/XP专用变量
6 c" v5 d8 F  }  X: R0 T#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
0 Q9 x+ x1 x- N/ Y#define DFP_GET_VERSION         SMART_GET_VERSION; D4 Y9 G; W$ F& ?+ G9 N
#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND9 g6 W" B# L. l) v- r; T' A" w
#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
* E+ f! V  f1 c% E. h7 D
; a: F$ V- L7 S4 `/ jconst WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令' o; q1 a( x5 v9 X& K4 w
const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
' q) v) C7 t* |. T- X) M$ x" x5 X4 ^& T" L7 D, K; i
const int MAX_IDE_DRIVES = 4;9 I/ `0 \" x9 y# Z9 v7 p8 q! ^" A
/ E' V+ h& N0 U7 |5 Z) K; x  C
// SCSI专用变量
5 u- j; Y& F# L5 \$ Fconst DWORD FILE_DEVICE_SCSI             = 0x0000001B;/ n4 J; F0 z/ [7 s0 O
const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);7 h! Q9 ~% x% N
const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition! N3 f* A. z  x3 a, q
const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;. h! _: g; x5 a7 W' y  F) o5 \
" ^& d- @8 _& K! S& e
typedef struct _SRB_IO_CONTROL0 s7 K) C2 U% W6 v' q
{% N  M1 V" v- H" i# Z
    ULONG HeaderLength;
3 c# A- H0 r6 Q  c; a    UCHAR Signature[8];
: \1 L; q+ \9 k    ULONG Timeout;
7 }: P& g; N. R5 H) U* v    ULONG ControlCode;7 r7 i# [+ q! N
    ULONG ReturnCode;7 i# }. L. [) ?- h, z
    ULONG Length;8 b3 s( S! O" C) C3 z% x
}SRB_IO_CONTROL, *PSRB_IO_CONTROL;7 T" v! U/ m" J$ ~8 z* ?, j

0 Y  x- a8 @8 ^; a4 A( G// 读取的主函数! U) Y3 c5 Z- D# H2 b
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
' T& \  X+ l: J! F* ?) M/ g7 B! _8 a* V! B
// 辅助函数  L% Q0 K$ U+ ^: J2 m# @$ ~5 c$ D
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
+ b) y6 U, |9 h4 t! q3 E// NT/2000/XP函数
9 I# x% n0 v4 m- f; S% g1 }( Mvoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);3 @! {; w% ?; g1 E6 z
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,8 P- a$ X5 Q$ u4 E
        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
$ V4 m+ c8 x# u+ R+ T0 j9 Q        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);! [8 `3 K0 s- d* V- m$ K
// Windows 9X函数/ _% s# H- C( q2 w8 X
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);
6 I0 ]9 l( {  f- B, G/ E4 Lvoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,9 }+ v$ E5 r# P( K! Z- z- k+ @
        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);" l' V2 [" Q- F" |& g9 M
+ t0 u* t1 X" E  M8 u. d/ c$ Q
// SCSI读取函数(for NT/2000/XP)" O  C0 M& q' E" ]/ w
String __fastcall ReadIDEDriveAsScsiDriveOnNT();9 O, ~) |6 ~. ~3 M8 Y4 _
//---------------------------------------------------------------------------
7 K% a; Y% J, M! q5 A// ReadPhysicalDrive
- ^" i2 _9 Y* _6 vvoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)8 ^( [! [8 O1 i' p/ Y6 O
{
3 q+ `  E" ^6 H, A  V. a( V( X    switch(Win32Platform)
7 _0 a) L4 N4 d3 ?& E/ e    {
! i7 Y/ {$ `( ]' r& @9 K        case VER_PLATFORM_WIN32_WINDOWS:
7 g& d' W, u1 r0 [. F+ m; ^            ReadPhysicalDriveOnW9X(pSerList, pModeList);
7 f8 \* V, {( q            break;
; d5 I: N0 E/ |+ c% T: |$ J8 D        case VER_PLATFORM_WIN32_NT:3 F- ^) y" q9 D( L' H/ @. e, @9 m
            ReadPhysicalDriveOnNT(pSerList, pModeList);
% @+ O5 }" w- M            break;
& `8 i" V$ m2 U5 H        default:
% S6 X% u+ Z. i7 V2 k6 x            break;
: ]- R, m, z% u5 ^    }
$ l* X( e* K; j9 g" y}/ N/ s# `; P5 l# w! Z% s
//---------------------------------------------------------------------------
# T- V; p; m6 w  ^  |2 c9 B% L// ConvertToString* s) o# {% Q/ [! y  m3 [* ~! C; R
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
7 a! U, D  W* r/ H( y, A& X% \{
5 @+ b9 O" U8 s9 F! ~7 q( R    static char szResBuf[1024];/ l/ p9 I& @+ y! ]
    int nIndex = 0;5 n% E6 a& m5 G4 v& }  _: K
    int nPosition = 0;) u) ^0 E7 X- D, C  w4 i& H! R, ^
3 k' S8 b$ q# C
    // Each integer has two characters stored in it backwards, S+ s  Z$ V. ?* G6 d6 [; J
    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)' y$ a- s& H) G( L; C' `
    {: E9 X& |' A$ }3 E
        // Get high BYTE for 1st character
$ J+ O2 {7 ?4 K+ E4 w) U; n9 }: r        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
* q& F+ }" h. G( I( o* L8 Q        nPosition++;8 V; i* s* s6 z
4 e3 y/ b1 }/ b& ^# R8 {1 D
        // Get low BYTE for 2nd character
  Y7 [  ~: l- p( c% _$ M        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);2 [4 j) t; G% w& K
        nPosition++;, y' N' R5 N% k0 K8 K. q
    }% Q6 O% l% a. m' G8 f, w

# u, W$ F; J1 o; t% G$ J* T    // End the string
, |) \1 M; j9 x( G7 j    szResBuf[nPosition] = '\0';! v: x% X6 _( l5 w- g  ]/ W

3 k$ o' [$ k  H: a: G$ r7 M. T3 R6 m    // Cut off the trailing blanks
4 ?/ Y: ~4 A  E; z. @3 S1 X' e' z    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)5 o0 c7 b  e+ X2 M) A
        szResBuf[nIndex] = '\0';
' m* p3 i6 N  d* s8 k) q
* ?- F  _3 R# J+ p: @* m: m: ~' B    return szResBuf;2 `: c) k# G2 x) s5 n( e
}' I4 m/ X. W0 a' f" G
//---------------------------------------------------------------------------8 J& Y4 c, X5 A- u4 {
// Winndows NT4/2000/XP 代码
9 d5 l% v* `9 U" a1 Y% D9 c3 }- v//---------------------------------------------------------------------------
( e' K$ k% Z$ z( n5 M8 l' X3 w( R// ReadPhysicalDriveOnNT5 B8 l: k/ g/ i+ B0 y' B" w. f
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
. b6 b& _7 S' a6 G$ T8 E6 N{8 T: F, F! N( f$ b( B# y+ P
    // 输出参数& Z5 w7 a1 t8 e1 P( s/ r
    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
1 d/ c: ^6 }2 e- J. B) ~6 ]
% ~5 ]5 G) t5 Z; J+ f& f# ?    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
4 `6 s6 V* P" v5 j$ j' a% k    {3 ?- v1 ~& ?# l+ q$ C
        HANDLE hPhysicalDriveIOCTL;  E: w8 w) R5 r5 u
        char szDriveName[32];
1 m4 p  g7 J2 g9 X5 @1 E+ |: f/ t% O+ C( n
        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
% g. t( E9 p8 W9 Q: e        hPhysicalDriveIOCTL = CreateFile(szDriveName,; _: a! h: B/ W( e$ b3 N: I- p; _1 s
                        GENERIC_READ | GENERIC_WRITE,
( [; Q* q" V: R                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,9 Q, i% \& r9 ^$ H; A5 [. C) z
                        OPEN_EXISTING, 0, NULL);& W5 X) R8 E, ?; e* o. G
5 b9 ]2 _  h& @
        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)3 c9 t) y2 K' K. ?
        {- _# m' N7 X; ~3 n! r6 d; y: s
            DWORD dwBytesReturned = 0;: e; |! y' _" q/ ?8 r
            GETVERSIONOUTPARAMS gvopVersionParams;$ Y/ j! J' y  `5 K6 O/ l

/ W# O0 S) M$ ]            // Get the version, etc of PhysicalDrive IOCTL
; R2 d' @+ I) }& ^% ^( b            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
; @6 @( R  {6 x( u  ~7 @2 b( h) ?" q, T" g2 A4 p; D' k  L2 b
            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
8 |! r5 [+ Z+ D3 c' S                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
7 x+ J9 g5 a1 y, Z# Y# [* V9 g                    &dwBytesReturned, NULL))
  J8 |$ w2 `( I! r            {
$ l& W2 S. ?. l  M/ Z                continue;
- l$ {. B% Z3 a% A+ A            }7 w" k  y1 W6 u9 D& e
! u) }) M$ l4 }% H
            if(gvopVersionParams.bIDEDeviceMap > 0)1 X7 \9 `4 }# u5 X3 R
            {
  U/ b* y4 {; R9 a! m, t                // IDE or ATAPI IDENTIFY cmd
3 ]9 e9 u8 v6 K; q; Q                BYTE btIDCmd = 0;
' C1 T& k. X6 s9 ?) ^                SENDCMDINPARAMS InParams;
6 X* a( Y3 b- [4 O, R1 |' \& y- k                // Now, get the ID sector for all IDE devices in the system.$ A0 B  X4 q. O$ ]$ ^7 T6 Q0 |5 `
                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,, }/ P& z0 u/ v1 j3 w7 _
                // otherwise use the IDE_ATA_IDENTIFY command
) ^) O! O7 X$ S3 M( h2 W                // 具体所得结果请参考头文件中的说明
0 f6 R! A4 W2 m& v$ [- V3 N                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
; ]" G/ }  {' Y# g  w) ?( E                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
- r, }6 f9 W$ X$ ^                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));) O1 i, T. ~" U6 c+ A* Y
                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));0 z: j9 h0 ?& E' L5 F7 W

, K7 R* U9 R, q5 C# d5 [                if(DoIdentify(hPhysicalDriveIOCTL,: m; X) [( [& Q5 b
                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,, u+ d7 C% ~: ^$ ^( J& Y+ t
                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))& X8 h$ v. u/ L1 e2 q% B- I
                {
% r2 D0 K( [. m; f                    DWORD dwDiskData[256];$ H3 _. a: e) V* n
                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
4 ^. R' C) V  S' q" I5 C5 q                    char szSerialNumber[21];5 r' h% l  q/ u" W+ d0 }
                    char szModelNumber[41];! T& S1 [( U  Q$ m/ W
2 i% F6 s" ]# M! b
                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
5 c" C3 s0 L7 A- n; n* s* \5 l                    for(int i=0; i < 256; i++)
" U; l8 j) W+ i# L2 j                        dwDiskData[i] = pIDSector[i];( F9 c2 A; W0 T, _
                    // 取系列号
% z, @4 `5 f  N2 I9 |9 u                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
1 y3 l8 V+ ]6 `, A1 r                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));1 n- o9 d8 J2 b, z

3 Y* i  @* r+ ^                    // 取模型号% W. i- J+ U; x. N8 }) o
                    ZeroMemory(szModelNumber, sizeof(szModelNumber));
# k4 e2 o( d+ @4 c, w2 N  |                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));& b6 I* z+ o) ]' l  D$ ]# r- w) T
: Z: \: M7 r7 `  E2 F
                    pSerList->Add(szSerialNumber);1 B% k7 X: g7 f$ ]( `. b
                    pModeList->Add(szModelNumber);
; b, ^7 G* z7 X' N6 R                }) ?* L+ O9 y. w9 ]6 \' b# r4 v
            }3 ~  T) T& L% S2 R- J4 P% }& `
            CloseHandle (hPhysicalDriveIOCTL);$ }& T3 {( Y0 k$ }. F5 z+ w
        }
) {2 r) _( c. C& A4 u; H# z. x. `1 x    }
  w+ ^% q: @. F3 o6 U" e}
6 U! i; E: r. E. A" }- ?: L$ \//---------------------------------------------------------------------------
; u& g' Q! r" Z; D// DoIdentify
1 n5 [, @- J/ ?. O4 Lbool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
$ ]! q; H1 s) e$ m% `              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
* k% K& u9 P# v6 b: @- f( T              PDWORD pdwBytesReturned). `2 o6 s  y6 _) x8 u; L$ q3 z6 {# ?
{; R# b5 o/ V  J1 p
    // Set up data structures for IDENTIFY command.
6 k/ Q) s0 c# X    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;0 v4 Q( k/ I) U7 I+ q4 @! p
    pSCIP->irDriveRegs.bFeaturesReg = 0;; |: r8 R) i& n! l7 C
    pSCIP->irDriveRegs.bSectorCountReg  = 1;% }# R" G; R& Z6 A- Y( e( g
    pSCIP->irDriveRegs.bSectorNumberReg = 1;
4 r, D5 L+ b" w4 A0 A1 t( {6 _    pSCIP->irDriveRegs.bCylLowReg  = 0;
3 j3 N+ c( T9 M9 w. M    pSCIP->irDriveRegs.bCylHighReg = 0;
  V/ J3 i# Z6 U
% l& s# x7 A* q9 Y5 A  @    // Compute the drive number.(主盘和从盘所对应的值是不一样的)
0 M5 d8 F+ J4 }2 e2 |+ H    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;: \; r7 D0 |& k/ O5 c4 n# r) j

1 j7 ~9 Q* z1 Z" a7 c. l; J9 p* N% U    // The command can either be IDE identify or ATAPI identify.( `* ?# ~# {' Q
    pSCIP->irDriveRegs.bCommandReg = btIDCmd;% b5 K; U; d7 S1 X
    pSCIP->bDriveNumber = btDriveNum;; a: E1 z* S1 ^
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
" |; \" F* [  H8 O$ ?- ~4 S3 \
; f4 e0 |: H5 c" U& ^    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,! n+ J5 d) D9 a1 L
           (LPVOID)pSCIP,8 h* d4 h3 o8 }1 `- j( W" E; A
           sizeof(SENDCMDINPARAMS) - 1,
4 w% U: |4 e6 A( Q: r3 n% I+ M$ ^           (LPVOID)pSCOP,& ?. y8 t2 u# }- z, \0 \  I( @
           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,$ z  j; N  x0 `& Q
           pdwBytesReturned, NULL);
* _$ c- b, P! r; M. A  ^}9 Y4 ]9 [. M! C9 t) G
//---------------------------------------------------------------------------4 `0 Z- g$ v! E
// Windows 95/98/ME 代码' U) M( X% j/ }) X: l# K" [
//---------------------------------------------------------------------------
7 b- G. d" W% R% o// ReadPhysicalDriveOnW9X% m5 G- z: {  y; h- `
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)+ r, i+ I. b  u3 \; ^1 t' c3 t
{# |% i0 q& d  C% ~9 Y7 p
    WORD wOutData[256];
, R; f( M0 T, t" }7 R1 H. w1 ~    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
2 S# m* d. W0 @6 ~* K; y4 T3 Y8 f! V1 B) N6 \- x
    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。! f+ |1 v) X7 C# I, G  O
    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
. t3 s' w5 c- O& o$ l    // 避免蓝屏的出现。(期待高人能指出原因)9 x% ]! `# m+ Q) E1 S
    for(int nDrive = 0; nDrive < 8; nDrive++)! H0 h! Y! a) t5 @& F& Z+ _  q7 S7 K
    {
; ?& X& E+ S  t& V+ A1 ]( y        WORD dwBaseAddress;+ P+ g, g7 _! V% s
        BYTE btMasterSlave;         // Master Or Slave
, B9 d4 `! z- |) O/ T        bool bIsIDEExist;2 T& d* F& R) R+ m9 E4 R% y
        bool IsDiskExist;
6 |9 O- w( }% Z$ }; W0 {, y5 A/ S. P+ ]6 l6 o3 u0 o
        switch(nDrive / 2); }9 R) Y9 G. }$ t3 S
        {
' \$ m  c& X- ]5 ]9 p; V3 l) A            case 0: dwBaseAddress = 0x01F0; break;! y/ d) O0 v2 A) q
            case 1: dwBaseAddress = 0x0170; break;. \3 p$ H; F* C
            case 2: dwBaseAddress = 0x01E8; break;
  h) a/ q' m3 ?  h* }8 r% Y0 C, t6 j            case 3: dwBaseAddress = 0x0168; break;  x# l: u- l1 ]. g! A
        }1 V: U- w/ f% e# R3 k1 @6 R% a

+ [1 K2 z& J" j% j) L* q; L$ E        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
6 r" b6 a, @* u) u0 H/ c( j5 c) c9 x  `/ F; d) e& M6 Q
        // 进入Ring0) q+ W% N/ L7 L
        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,$ D/ j* N- x! h5 j
                bIsIDEExist, IsDiskExist, wOutData);6 w. b5 k4 S& ]  X8 [7 {
    }' F, E% l! I' _* P

5 Q7 N4 K' \  A6 I! I: K) E    // 开始读取9 R, c9 u# p3 `- K
    for(int nDrive = 0; nDrive < 8; nDrive++)
% @4 v! R" ]3 |' \4 y    {! s; J' {4 D# c
        WORD dwBaseAddress;# c5 t$ X! g, f, w5 Y
        BYTE btMasterSlave;         // Master Or Slave
; I6 H* y' e8 p  T        bool bIsIDEExist;4 l* |7 x0 X9 n. Z- W2 U2 H( C' ]
        bool bIsDiskExist;  F: n( @, C: x6 T
        switch(nDrive / 2)- Q4 v) D' {4 ?
        {# l# Z$ g6 l# f. z8 W, G7 X' |7 U
            case 0: dwBaseAddress = 0x01F0; break;
$ x/ O$ i/ P4 P  e3 C& G8 B. i            case 1: dwBaseAddress = 0x0170; break;* A0 [+ k- q4 O! I) o: I9 ^9 b0 e6 ~
            case 2: dwBaseAddress = 0x01E8; break;
5 v$ h1 S( Z  O( Y' M            case 3: dwBaseAddress = 0x0168; break;; f7 U# I' S' N9 p# f! G+ w  h
        }
; x" r9 G2 e7 m( r3 `* |
0 r- \& G: d# Z4 @* c- E6 \& n        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
' w$ U/ X3 N4 c* S3 d" g$ @) V7 K8 R. i/ x
        // 进入Ring0# _: k5 p4 \" r# D1 h* |; \& C# L
        bIsIDEExist  = false;7 m/ j# [5 d% O
        bIsDiskExist = false;/ U+ E  [6 E& i" n: N
        ZeroMemory(wOutData, sizeof(wOutData));: o4 x5 ]" S0 W7 w% \8 \

; d/ m* p3 P; V; d* @* K        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
7 ]6 X8 K# C. v' f+ Q                bIsIDEExist, bIsDiskExist, wOutData);2 g: ^! t. d0 F! P2 c

" _- @; I4 z5 D0 M: [2 x        if(bIsIDEExist && bIsDiskExist)
% h. O9 X! d7 w3 G) L        {5 ~& G. k; Q* }
            DWORD dwDiskData[256];( v" M- s* a+ Y1 U
            char  szSerialNumber[21];8 B: A  E5 Y  C% I- V
            char  szModelNumber[41];
9 H2 s+ L$ H+ t7 M. E' q7 g+ L' L# Y
. @5 f/ z" b* n3 O6 W- `2 t            for(int k=0; k < 256; k++)
# M5 u$ Z5 J& q: [% f8 U- A6 h                dwDiskData[k] = wOutData[k];2 R; ~& G2 R3 @, H2 `6 w% z
' b% ~) H) p0 T  \  j7 d* n
            // 取系列号
5 A2 n" g' N4 l- ^% V, m            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
1 a  {/ D. h& E% t6 t5 {            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));" P* ^0 a; u) U# E) R+ s
# q, i! ?* |. p6 M2 a: X
            // 取模型号' C2 Y6 b/ i' a# J. K7 E  i' {
            ZeroMemory(szModelNumber, sizeof(szModelNumber));) v3 s7 @  d# `4 ]& w2 w3 @
            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
3 H. }3 K( \' {+ @" K; m5 d5 e. B2 @2 [7 N: y" X% [6 W: M
            pSerList->Add(szSerialNumber);8 H) J- @! O3 s! A7 S5 ~5 p$ s
            pModeList->Add(szModelNumber);
0 K6 V! ?9 q! }5 l/ A. o        }( L5 ^$ M3 t1 ?- U
    }- g4 F( ]2 Q! s8 }$ B5 c
    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);* S$ q& |: s. a
}
/ j9 C* v6 q" E- X: S) C: h: w//---------------------------------------------------------------------------; ]/ ?" r8 L! [' U" j. ^! S
// 为防止不负责任的转载者,在此注明原出处信息,请见谅。8 n. j- A& M) P+ C( G4 l
// 资料收集整理:ccrun(老妖),欢迎光临C++Builder研究: http://www.ccrun.com; N# L: N, z+ i+ r& d( f
//---------------------------------------------------------------------------4 D" j  E  c" K/ C
// ReadPhysicalDriveOnW9X_Ring0()
6 ?# W3 n/ ?  G' c' s//
& u. x1 B% t5 @* n# h// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
* @9 G$ ~3 p4 U8 M// btMasterSlave = Master(0xA0) Or Slave(0xB0)  O5 U" Z& V' N7 Z0 J0 D& a( ~
//---------------------------------------------------------------------------; y8 ~4 [+ `% @) {. B7 z
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,0 ^2 a/ n. D& k6 A
        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
5 }  n+ k  a* [6 z7 b{- V( x% a2 H5 v& i8 O9 Z
    BYTE  btIDTR1[6];
- T6 d2 }) E; P. m; d' Q    DWORD dwOldExceptionHook;& m7 Z( D, m! e1 C6 e
    const int nHookExceptionNo = 5;
, X. U: y0 o6 L* e- W7 a# m4 v* u
5 x* M( Z2 n+ A7 R8 q$ v    BYTE  btIsIDEExist = 0;
( S. {) x3 V% A# X, F, U    BYTE  btIsDiskExist = 0;
0 K0 s& |5 d5 t' V    WORD  wOutDataBuf[256];5 G6 u( a/ l9 [0 Z0 H

; ^! M5 J0 R9 |& A5 T    BYTE  btIsFirst = (BYTE)bIsFirst;
* c4 ^' b+ X7 o. b2 K, q, }2 p& \4 A. O1 z% x! i$ J& W) c
    const BYTE btBit00 = 0x01;1 b! P/ z, r6 _
    // const BYTE btBit02 = 0x04;
/ N. Y. m, ]& ?% T2 F$ Y    const BYTE btBit06 = 0x40;
% E/ }& V' k! ^9 H; ^9 d% R$ B    const BYTE btBit07 = 0x80;4 m) G- D! j% \' l" R- I0 u
    // const BYTE btERR  = btBit00;
8 r% F$ v/ ~0 ~2 k: g    const BYTE btBusy = btBit07;) J1 N4 G8 U/ c6 l) Q' R
    const BYTE btAtaCmd   = 0xEC;
# {% B4 g( b5 Y1 _  S    const BYTE btAtapiCmd = 0xA1;
& P( [) j, Q8 M8 s  ]. `3 c
2 v$ C7 v/ K/ c* {8 b) W; k0 ~    __asm
! a' U! [& @  ~  e8 t+ w! u) W6 K    {
/ J+ P" v6 N$ g        // 必须先执行这条语句% o$ i  @" d+ |8 V
        JMP EnterRing0
; A( G. A# }7 O  x! ~$ x+ H. h9 W: x
        // 定义过程
% v  M8 I+ z. @2 I$ A        // 等待IDE设备直到其不为忙为止
4 b7 ^; m1 T3 V6 f$ c/ ~* J, p( P        WaitWhileBusy proc
6 P4 l- O/ s* m- ~( z" O: v) G, _4 t4 \# J5 K
        MOV  EBX, 1000004 D" ^& L9 s- k% G& z
        MOV  DX, dwBaseAddress3 Y) N* V! [8 b4 W9 s# x
        ADD  DX, 73 J, v& H: i9 ]" K! ^6 v+ ~
! C7 @2 [$ U; U, @
        LoopWhileBusy:, c. c9 Q& Z8 d2 b' R" |) ~

$ ^7 T. H+ g0 r/ Z* I$ ]0 A2 L# S        DEC  EBX# A- k2 |) Y  f8 d% c! m8 W
        CMP  EBX, 0
9 S* ~, h1 F& ?& R# W! R7 B3 }        JZ   Timeout
; w7 L* ?0 t- g$ \/ o6 G        in   AL, DX
0 a' Y0 D* \" Z( B$ a$ e! \& D        TEST AL, btBusy! ?  C2 A- ?% I* Z' m$ @2 ]- I6 O
        JNZ  LoopWhileBusy
& d) r$ q0 ]/ _2 g, H# }( ^+ N; Z        JMP  DriveReady
1 h" D/ E# S! M& Y
: D5 p, t6 }( l5 n% o# |        // 超时,直接退出
4 ?( {( F9 Q! I0 w, e0 y        Timeout:
: y8 _/ r8 x4 p3 I. H        JMP  LeaveRing04 O) q7 |  v6 S+ ^
        DriveReady:. e/ {' n0 }' V- J- Y; T! Z5 G: A5 \  B
        RET% B$ v" K) V. Y  ^, V1 Q# }% t% P
        ENDP   // End of WaitWhileBusy Procedure
: Y  p, K) E( u3 t6 w: `% y" g$ \! {/ {2 H. n/ _
        // 设置主盘和从盘标志: s7 f2 C; x  X
        SelectDevice proc
: C1 h* h- l% U+ h; I
7 K8 P& Z! W& _$ K5 Y1 T4 K: E/ |4 g        MOV  DX, dwBaseAddress
: S: [5 r( Q+ L$ ^4 N2 H, A$ h        ADD  DX, 6% p- Z* X" N7 c) G0 p  a
        MOV  AL, btMasterSlave
3 T) G5 O! f' M4 I0 n
5 \. Q" l, {+ G' N. k        out  DX, AL
& N, _- o, `* ^( w6 _" [  D        RET! u% L' R! V+ n" t0 b7 h8 T

9 Q7 I$ v* s1 d1 [9 k        ENDP  // End of SelectDevice Procedure
  h. G( j. l; H% ~: t/ e! T8 V, G( `, x
        // 向IDE设备发送存取指令- E3 j5 c" |# H1 ?5 T9 i) P
        SendCmd proc/ [& N4 C+ z& w0 ^$ k6 }4 G

6 z+ K) ]; k4 ?/ s% X- {$ c        MOV DX, dwBaseAddress4 _% A# Z6 l7 Z6 x+ d
        ADD DX, 77 B) n4 {4 ]) i$ F6 Y' T5 K  P
        MOV AL, BL // BL是主从盘标识,在过程外设置
8 P7 R3 z8 I3 J        out DX, AL6 L7 _$ z+ O$ |
        RET
9 q$ ~$ `% z+ c; U4 s        ENDP  // End of SendCmd Procedure
/ i8 D! D9 L; G) R& k
2 f( ?8 i" i' i0 g# J' x( r        // Ring0代码
- V! t, Y# \, p' X9 D        Ring0Proc:
1 E& ]# f" Q1 i) o        PUSHAD/ M- [, b( O- p7 ~$ l- J
        // 查询IDE设备是否存在* t$ G7 ?* S6 M$ l( o
        MOV DX, dwBaseAddress( c( X5 S: H% ]
        ADD DX, 7
" N$ B! K5 u* P        in  AL,DX
- y, S" s4 Z) h( f: `$ O  ?- l+ s
% e1 I* X) X- |        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
- c* B, [' i: U# }        CMP AL,0xFF
7 w5 U, U. T* N  v        JZ  LeaveRing0
8 P+ k: U. r6 W        CMP AL, 0x7F
/ ~: K9 P/ d9 h& W  \# ^        JZ  LeaveRing0& N! i& ^, R6 L& ~
+ Z2 Y. w& e7 q- V  o6 N& f% m* C3 H
        // 设置IDE设备存在标志" _& z) U: L6 _0 z) R
        MOV btIsIDEExist, 15 e5 C8 t0 o% E/ _/ u; Y' K& f
) q! D6 A9 {- A
        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)& X" b, D; W0 z" J, U5 ?" _5 l
        CALL WaitWhileBusy
5 V, f$ Z  |1 @* ~        CALL SelectDevice! Y% J" [  B0 O

. E2 I  }" @, g& {3 Z0 L  W  M        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
' X. q, Q/ O: I# f' Z* @9 A        CMP  btIsFirst, 1* F+ X7 V1 t! N) J2 A& ?$ |
        JZ   LeaveRing0: b4 F( y' x( R1 i2 i
8 [/ @8 L# s0 M# n2 r/ C
        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
$ S" ]$ P6 l+ h: ]        CALL WaitWhileBusy
, [" X, N% m; P9 I) u$ C' Q
6 W* r" l7 w: S8 T        // AL的值等于cBit06时,不存在驱动器,直接返回/ t( f7 x  j9 N4 {) R, y$ Y
        TEST AL, btBit06/ B. D) z+ ^- g
        JZ   LeaveRing0  F& t3 R& P1 k

* f  i% c5 z& D  Z) a2 I% U        // 设置驱动器存在标志0 B; R$ ?; |' e4 {. i
        MOV  btIsDiskExist, 1
, O# B4 ]/ h6 c! W+ S/ B2 I$ y9 V# T' w1 O) P# ?. b
        // 发送存取端口命令
0 x+ B- \( D" C# ]6 k# O. X        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,3 H3 _4 T' Q$ @9 E
        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令! A, X" t& E0 x  ^" i9 N
        CALL WaitWhileBusy
- r6 I& J8 G9 ?5 a/ x: h4 M        CALL SelectDevice    // 设置主从盘标识
, m/ h; R; G& D) ]/ X) R! H  M; x        MOV  BL, btAtaCmd      // 发送读取命令- h1 c7 _, q' B5 z/ U" U
        CALL SendCmd
  {# `4 Z/ S$ f. |/ w' s        CALL WaitWhileBusy. q' a, N, i  ~% V; c+ s' j
! Z5 W; p- k2 q; s
        // 检查是否出错& T9 d( s2 w( T- Q1 x! a
        MOV  DX, dwBaseAddress
6 X: W. {, A1 d( o' d8 Z. \* M! M        ADD  DX, 7# |5 `) ^, s, {  }3 _. k7 J8 J

+ i% a; Z( ~# R3 t$ Z, v$ G        in   AL, DX' X# z7 y9 q! N6 N
! J/ y' A+ P) ?. o
        TEST AL, btBit007 |, L. v, n3 S; h
        JZ   RetrieveInfo   // 没有错误时则读数据
( F9 [  H: R8 X- |1 P/ x) ^+ G/ G7 M/ Z, I8 E$ r2 Y
        // 如果出错,则进一步尝试使用ATAPI设备命令
' c) p4 o6 [8 b0 E+ s' x        CALL WaitWhileBusy' o- I8 K1 o# i" t6 L( w
        CALL SelectDevice6 z) {. U5 P, o
        MOV  BL, btAtapiCmd4 w" J0 K; T1 E" s* [
        CALL SendCmd
! e+ a6 m. D, q# s; C        CALL WaitWhileBusy1 e8 N6 y* E. d' D* w" E" T
9 A2 D1 l! z$ t2 o7 {3 p/ D( r) @
        // 检查是否还出错
% J# [+ A) G, m) F        MOV  DX, dwBaseAddress
2 H' {, W! i! I  N, ?" y$ m        ADD  DX, 7
: I" ~6 b1 |; Z% G/ _% G) B1 g. S        in   AL, DX
5 [2 d/ J4 s/ T( U: h1 Q        TEST AL, btBit00
! h9 K1 ^( d7 }; `, |( e        JZ   RetrieveInfo   // 没有错误时则读数据
/ d5 c4 L' N2 j        JMP  LeaveRing0     // 如果还是出错,直接返回
. `; N" h: t+ J; c
2 o3 x7 S8 o/ X3 I        // 读取数据5 o3 \' y# Y5 l/ b3 A
        RetrieveInfo:
7 l; r  v2 ~" \$ X& j$ S  l3 P: P! V4 o* b; z( ~( j
        LEA  EDI, wOutDataBuf* b- I' x4 p2 A2 H: S: Q
        MOV  ECX, 2568 ]& F9 m. W: L, w9 ^7 K6 E$ k5 s
        MOV  DX, dwBaseAddress
6 d4 V" I! z: ~+ v        CLD7 s3 v0 G5 J1 j5 i
4 A+ _, a3 b7 q% t8 }5 @- E
        REP  INSW
6 A4 C: v" x+ j: ?% ~, i8 C7 y
, y; C6 y1 n/ O- q7 a- T        // 退出Ring0代码
. q! c6 `5 b1 p8 h" s3 e        LeaveRing0:
$ V  N3 o- I9 f2 c% H8 _% _9 i; F# f! ]$ g: ~, k; e
        POPAD
6 r/ k4 w/ ?9 L3 V) ~0 D        IRETD
3 u* T. Y. O: Z/ j4 W
4 ^1 i* ~5 t+ u! D        // 激活Ring0代码, }+ l% t+ @+ Q  Z7 J' W
        EnterRing0:
8 T! t& N/ u! T7 y3 i! w, r  Q, C, S( q0 O; g- {2 e2 x& y! v8 k5 X
        // 修改中断门
+ E) L0 P3 a: J& k4 W$ j0 O% a0 \        SIDT FWORD PTR btIDTR10 G+ S5 H( w$ _- L& L
        MOV EAX, DWORD PTR btIDTR1 + 02h
6 B0 ~' ^* Z$ m8 a        ADD EAX, nHookExceptionNo * 08h + 04h
- [5 O4 K- B* c  @$ d# i        CLI# P; n0 \* v: v' V
: w* w* J$ d$ f9 F8 ?
        // 保存原异常处理例程入口3 L+ i6 l* q( r8 @
        MOV ECX, DWORD PTR [EAX]0 H1 A. Q& `: ~
        MOV CX, WORD PTR [EAX-04h]
7 z: G& s5 s2 S- r: A        MOV dwOldExceptionHook, ECX
6 x. X7 o; \) D' C
( |7 v/ u2 H! k$ \) `2 T        // 指定新入口
% H  _5 U' c- ^1 S% U: h        LEA EBX, Ring0Proc/ B0 U; S, E6 z( A. D$ K6 ?
        MOV WORD PTR [EAX-04h],BX
7 @! l) {6 V1 S        SHR EBX, 10h
5 r5 E9 |" X. ?. z% `$ L        MOV WORD PTR[EAX+02h], BX
, ~% n0 C. V! w3 i9 @+ @3 |: d6 l/ v
        // 激活Ring0代码7 u+ k* ^( W4 X% Z: \( F: \
        INT nHookExceptionNo: T  E8 M! p  X3 i9 ^# P

9 a0 ~1 @, B0 X4 L: _        // 复原入口
% X: ~1 X: `8 h        MOV ECX,dwOldExceptionHook
# k6 H% @( f- W8 S( J9 L  m1 d        MOV WORD PTR[EAX-04h], CX
9 x6 v4 I, ]0 ^; D0 l        SHR ECX,10h
# s" C8 O8 [0 Q, A        MOV WORD PTR[EAX+02h], CX; _4 w7 Z; s" k( j% `
        STI
. h9 }2 Q! q4 `7 U5 E4 h" g    }
  ~! }) z) N3 e% }) E    if(!bIsFirst)
: T0 R0 o$ G% A8 ~+ h    {9 ?; d, L! {( ?& G; f1 s
        bIsIDEExist  = (bool)btIsIDEExist;$ q/ K) V- X* S$ v
        bIsDiskExist = (bool)btIsDiskExist;$ d2 o# i8 |" o* G3 B
        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));/ y+ b$ q$ q. _! u' M9 {
    }* M4 \* G" U: H5 p& J# d8 W
}
! `8 |- D! B4 B" @5 {% W$ V: G' p//---------------------------------------------------------------------------$ {* C: B# Z+ @
// 调用方法:* c8 M7 E- K- @! ]7 k
void __fastcall TForm1::Button1Click(TObject *Sender)4 K& W0 S1 l8 o" U/ ~, {: h3 n0 H
{
% {8 C& I% F( [1 \    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);& H& w, R" \1 c' V7 O& l$ j
}
. L1 d7 G2 v, B% ~$ Y' Y
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-6-19 07:53 , Processed in 0.017885 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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