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

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

[复制链接]
发表于 2008-1-6 19:59:06 | 显示全部楼层 |阅读模式
代码框架,你所要做的仅是修改WQL语句,具体可看MSDN。以下代码为简介起见,一次返回所有的CPUID或硬盘厂商系列号
" l& \. x1 [* ~" J
  1. 2 {. P9 Y# Z* Q
  2. #include "StdAfx.h"
    & x* A, H$ m6 ]& b
  3. #include ".\puiddisk.h"+ s) B* F0 i3 Z1 {* v& S
  4. #define _WIN32_DCOM
    3 W& M7 Q0 `' Q, Z( {  K& W
  5. #include <iostream>
    , v  p9 `& p/ f
  6. using namespace std;
    7 f- K( `& n9 B2 S) c6 O! ]2 E
  7. #include <comdef.h>( c1 v, L: \9 f4 l3 ]
  8. #include <Wbemidl.h>
    ! s0 P9 @" `' P! A

  9. ) Z& M, B7 H1 L0 f6 a9 j2 p4 [0 i
  10. # pragma comment(lib, "wbemuuid.lib")
    : E8 @) s; ?) q: ?$ H1 U
  11. CpuIDDisk::CpuIDDisk(void)
      m9 P4 v) L, S+ [
  12. {/ }% Q# U" G' i" c% Q, W
  13.     GetInfomation();" z3 |" @3 B$ @( D) q3 L
  14. }" ]+ l& k4 P& x6 H8 F) a- q

  15. 9 {* ?+ X1 G' o3 ~
  16. CpuIDDisk::~CpuIDDisk(void)
    - v% d. j! H5 |3 R- W
  17. {
    / {9 [- T" i) z- O9 D8 v
  18. }
    4 X" O" ^, O6 L6 J' o, {9 e
  19. int CpuIDDisk::GetInfomation(void)
    % v% h7 D6 r- a7 }/ Q5 x
  20. {
    % M4 N/ x' b& [* a1 F- M
  21.     HRESULT hres;
    $ l3 v+ w  h5 i$ l- J
  22.     //步骤1:不是必须的,COM只须也只能初始化一次
    4 p- g6 Y* p$ j8 D: q  v
  23.      hres =  CoInitializeEx(0, COINIT_MULTITHREADED );( g4 g& D5 i) G6 O, G/ b
  24.     if (FAILED(hres))
    / r! `3 ~. I" l! Q' d  I- s9 A
  25.     {  E( N. @3 p8 W+ y9 M8 [7 g
  26.         return 1; //初始化COM异常:注意,COM只须也只能初始化一次9 J* l! d& M2 l7 k* d1 |9 {7 M) d
  27.     }
    : B, ^; y7 S* P) {' l! e
  28.     //步骤2:不是必须的,COM只须也只能设置一次% G2 W( c: _- I8 v+ _( U1 S
  29.     //Set general COM security levels, N5 a" @. `# h4 q% u2 e
  30.     hres =  CoInitializeSecurity(
    , g) \3 i" r% m+ y6 o% i
  31.         NULL, " s" C: K4 g5 L
  32.         -1,                          // COM authentication5 g: K1 y. s: w5 l( i
  33.         NULL,                        // Authentication services) k" @0 R% B0 a! e* b" t! _
  34.         NULL,                        // Reserved
    - ?! a& z( S8 P
  35.         RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication
    1 H; y& k8 ?4 u9 `5 u" A
  36.         RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  5 U4 U; {; `" l( j9 k+ @% D
  37.         NULL,                        // Authentication info
    ( C  k5 M0 s9 c2 J2 G9 N# }0 c" f# [
  38.         EOAC_NONE,                   // Additional capabilities 3 Z6 N6 j9 t9 I5 }6 g; @
  39.         NULL                         // Reserved
    : \% x' V+ V, y1 \9 z$ i' D, p+ S: B
  40.         );
    + P! D- W2 [# p3 Q
  41.                      
    0 R% W) g' [7 g( z8 |
  42.     if (FAILED(hres))
    , @' w' |0 p* q8 @2 ]
  43.     {5 a9 s, z( Q% U/ X' H: Z) x
  44.         CoUninitialize();! Y3 Y! P) K% E
  45.         return 1;                    // Program has failed.
    2 u$ j0 a/ H+ h! W, e
  46.     }
    7 M: V) s( X# E" u" b
  47.     4 z+ n: `9 k* e* W) Q* m1 m8 v
  48.     //以上不是必须的,若已有“::COMInit();”,则要跳过
    , y2 ^$ h" t2 n% @9 u
  49.     //步骤3: Obtain the initial locator to WMI
    3 |7 R  `/ {# ]* u7 d
  50.     IWbemLocator *pLoc = NULL;, R: ~) @  L8 `% T! j0 o
  51.     hres = CoCreateInstance(* M6 n% ~- a3 i  Y* X2 e' e
  52.         CLSID_WbemLocator,             & g& {$ N2 ~/ ^' O0 s9 F
  53.         0, . S5 G7 ~/ v' s  \& z
  54.         CLSCTX_INPROC_SERVER,
    3 ?, |  D) S( q$ z1 z% Z
  55.         IID_IWbemLocator, (LPVOID *) &pLoc);2 c8 a( @0 I; m& v

  56. + p* W. ?9 ~; q: w/ C; G3 C
  57.     if (FAILED(hres))
    : i9 W# X/ O! ~* w
  58.     {3 q- O" r6 I# {
  59.         CoUninitialize();7 V7 s' i; R  c, ~- z5 p; l  ?
  60.         return 1;//Failed to create IWbemLocator object
    3 Z5 @: p) f( O2 i
  61.     }
    " u, r/ T' b3 P) q7 t

  62. ' e1 A5 K, T! Z3 R
  63.     //步骤4:Connect to WMI through the IWbemLocator::ConnectServer method; _4 E6 N* J% [6 l) d8 d" ]. Z/ v7 i" P0 \
  64.     IWbemServices *pSvc = NULL;2 A4 _. Y# {/ q& Q0 L! f
  65.     hres = pLoc->ConnectServer(
    . R# n7 k( Q" B2 e! q  z$ p# h) A
  66.          _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace) s& A. y) a* O  Z
  67.          NULL,                    // User name. NULL = current user
    * C# ]& ]% ]/ Z0 o9 o5 S
  68.          NULL,                    // User password. NULL = current, z* X+ a8 Q8 m' x4 f
  69.          0,                       // Locale. NULL indicates current
    / u' S# {4 H" |" {) W
  70.          NULL,                    // Security flags.
    ' L8 ^9 M( V! ]2 j5 k$ \  g
  71.          0,                       // Authority (e.g. Kerberos)
    ) s; K4 e7 i! ~' a% h
  72.          0,                       // Context object
    / Y/ J1 I% e( M
  73.          &pSvc                    // pointer to IWbemServices proxy; t1 O0 G/ y" \1 |
  74.          );$ U9 J6 v' `; v% }
  75.    
    / n5 J. `9 z8 f; E
  76.     if (FAILED(hres))
    * E. r- Q4 A* W' U% {' ?# i' O5 T
  77.     {
    5 e- r: F# z4 p: J5 v0 w2 E1 j
  78.         pLoc->Release();     
    " Z1 {( |* X8 ~: o. o3 K1 j( X8 a
  79.         CoUninitialize();
    9 F0 \4 Y/ i4 S( f# K+ `+ O- }. `
  80.         return 1;                // Program has failed.
    2 c% p: i1 [# X' u& j3 M
  81.     }9 E4 w* q5 z% |  p
  82.     // 步骤5: Set security levels on the proxy
    9 X3 X& `/ l, b( h, Y3 a; e: |" h
  83.     hres = CoSetProxyBlanket(
    , A# ^  n8 ?/ Y/ M8 u
  84.        pSvc,                        // Indicates the proxy to set0 d/ B- ~; D% V) x/ @: g
  85.        RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx& k( u: y% L# V; v& g& Z0 ~7 P
  86.        RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx  b, S/ k5 h- T% r7 `
  87.        NULL,                        // Server principal name 7 M' N# L# f% T9 y2 x0 ?  d* L
  88.        RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx
      n" v* o; |' o2 {- P
  89.        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx# E0 `% n( i/ X
  90.        NULL,                        // client identity9 n! Q& q0 S1 M8 Z; L
  91.        EOAC_NONE                    // proxy capabilities
    5 ^4 H& R9 e9 p9 _1 F5 E  B: {
  92.     );3 b% U" H, I* l1 i* f
  93. / D3 B" B9 r5 A
  94.     if (FAILED(hres))+ J* z8 K% s3 Q' ?6 I
  95.     {+ L$ ]6 `3 V2 t: w- H5 M
  96.         pSvc->Release();
    2 y% C" K, p: u  ^4 G2 B
  97.         pLoc->Release();     & ?+ |6 o% s2 v5 K
  98.         CoUninitialize();
    . n( {  M! w, G5 ?; K+ v- G, Y
  99.         return 1;
    8 g6 [/ D* R  {: ^& ^/ `
  100.     }1 A/ h4 Z+ n( l7 H+ }8 D' @1 Y6 H
  101. 5 W+ l* i- `( S% _, {# y! d7 `
  102.     // 步骤6:Use the IWbemServices pointer to make requests of WMI ----
    " _& |+ |* V, H" z( Q3 w$ j
  103.     IEnumWbemClassObject* pEnumerator = NULL;0 T5 E: ~  F: h6 C. X/ J
  104.     //计算CPUID9 Z. S" y' y7 \$ u; T! X8 s) s: ?
  105.     hres = pSvc->ExecQuery(
    # F2 L  w* A! Q; z+ m! X
  106.         bstr_t("WQL"),   m( _3 P2 P! b8 ~" s
  107.         bstr_t("SELECT * FROM Win32_Processor"),//Win32_OperatingSystem
    ! h" O- s$ T8 {6 F
  108.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, % z% H1 @( N' ~% c% i3 s
  109.         NULL,
    2 U. k0 \2 A2 l/ e% G( A
  110.         &pEnumerator);
    - G/ b  ]: A; ^9 r8 u
  111.    
    ( T8 ~" w0 F0 o9 g$ j
  112.     if (FAILED(hres)). }6 z( H5 e% \, a- ?9 q. ^, G; j
  113.     {
    1 o; |' S& }$ R: f( L. V9 Y3 C6 X  J
  114.         pSvc->Release();
    : u7 ~* [2 j- x" t+ L
  115.         pLoc->Release();
    4 p4 V" C$ }3 h' N
  116.         CoUninitialize();9 _2 H5 K$ d7 C$ w! s8 \$ V
  117.         return 1;
    8 H9 d' c' A: c0 Z# p3 ?# b
  118.     }
    : F7 _% l2 T. M1 P+ p0 o
  119.     // 步骤7:Get the data from the query + L+ R6 A$ P; [% u' m# z( y
  120.     IWbemClassObject *pclsObj;+ P' O4 r8 Z; `4 |
  121.     ULONG uReturn = 0;9 |$ I, R% h# S6 U
  122.     while (pEnumerator)! a: p! w3 }1 i1 D% J
  123.     {5 |" g) m1 j6 _" j/ _; k3 o, a
  124.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, % z! b9 y" L$ Q" b
  125.             &pclsObj, &uReturn);
    2 B/ F5 U7 H3 @2 n( C
  126. 5 j6 E1 I8 P) V
  127.         if(0 == uReturn)  Y1 q& M6 ~7 W9 D9 X8 V
  128.         {" m/ C$ J/ X% D# }. S" J
  129.             break;9 m" s/ ^( D. h0 w/ G0 q
  130.         }2 ?8 d0 W: o; }2 Q
  131.         VARIANT vtProp;
    8 h3 f7 J9 X: _/ r" c6 o
  132.         VariantInit(&vtProp);
    , t- }- U5 b7 a: v+ m2 ^8 v( ?' g
  133.         hr = pclsObj->Get(L"ProcessorId", 0, &vtProp, 0, 0);6 `% R  j) j. c1 d0 L; Q
  134.         strProcessID=_com_util::ConvertBSTRToString(vtProp.bstrVal);//strProcessID:类级变量
    5 \2 d( G" v2 c
  135.     }( p: E6 B# z1 C/ |

  136. : G0 |' Z1 x/ r# C4 X7 X+ E% l
  137.     //计算硬盘系列号
    ( W, y  n  c" h
  138.     hres = pSvc->ExecQuery(
    $ Q$ `8 a/ n" d7 a* q% _. @+ I9 E
  139.         bstr_t("WQL"),
    ) h9 T" |9 |, [% Z$ `# n
  140.         bstr_t("SELECT * FROM Win32_DiskDrive"),* S% Q' V5 H$ v* g, B
  141.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 8 O3 S2 Q( s9 l/ A7 N
  142.         NULL,
    6 e8 H4 w: _- j7 J* L
  143.         &pEnumerator);
      R- o" J6 A( k9 m

  144. * C* P" O4 R3 _7 x
  145.     if (FAILED(hres)): O6 n8 x6 x( j  G; I
  146.     {4 D  }4 i! P( L3 _! K' ~6 s& w5 p
  147.         pSvc->Release();3 o2 x* `6 v/ {8 D
  148.         pLoc->Release();
      R" M/ f" X/ Y6 C* R
  149.         CoUninitialize();
    $ P+ ]# Z% m' M' A
  150.         return 1;
    0 y& G6 l0 R1 v) q+ C7 T
  151.     }9 A. W6 k8 f  H  R0 M, R$ F2 g
  152.     while (pEnumerator)- e8 U# }6 a5 Y, s
  153.     {
    0 M1 s) G8 ~" Z
  154.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
    $ f; x5 f! @: |; U* b+ N, m
  155.             &pclsObj, &uReturn);+ F! E# z( J! x: N" q: K
  156. 8 R/ s" k! H- X2 ^0 \# |$ F
  157.         if(0 == uReturn), I' h1 ^# |: d$ H- ]3 Y! c
  158.         {
    ) P( C3 \1 I, r, ~4 O# o. }6 F1 s
  159.             break;' q  O1 e  z' O! p1 M
  160.         }
    ) V4 L" h7 O2 o, l
  161. 9 m! f5 i# b! [$ S, v
  162.         VARIANT vtProp;
    " {2 k* e& Z0 Z7 w
  163.         VariantInit(&vtProp);
    * c/ h6 f2 V1 e1 p/ b3 I
  164.         hr = pclsObj->Get(L"PNPDeviceID", 0, &vtProp, 0, 0);
    5 ]9 [/ S% }0 R
  165.     strDisk=_com_util::ConvertBSTRToString(vtProp.bstrVal);
    9 \: C& P0 |# ?
  166.     }7 p3 }1 ~- }0 L7 P  {4 M4 t

  167. : H5 c( G- l6 Y+ d1 {9 n
  168.     pSvc->Release();
    7 p9 u- L4 t0 K0 r
  169.     pLoc->Release();
    3 j( e3 Y. E/ r) ~7 s
  170.     pEnumerator->Release();
    6 @+ o5 P2 ~' m& u% ]0 ^
  171.     pclsObj->Release();- l6 T: q( C1 y
  172.     CoUninitialize();- P9 w. E8 @6 a, V$ k( U) G

  173. ( I8 t1 a- {4 }/ Q9 Y9 f
  174.     return 0;   4 q2 B# O$ `" J9 r" g  U7 _4 _! Z
  175. }) n5 S: |& b& W9 s& d8 ]
复制代码
 楼主| 发表于 2010-10-11 19:21:05 | 显示全部楼层
本文代码经ccrun(老妖)在Win2k下试验成功." f0 d$ y0 N- o0 e2 y

# z6 x* Y5 n$ C7 U# p#include <WinIOCtl.h>9 _6 m. q6 c4 O' a, c4 Y% W9 {6 s
#include <stdio.h>& D( R% H! w- r( a5 k

8 U2 _6 b# @9 r% S#pragma inline2 j+ y5 [6 v. Q& g  m* s: s
//---------------------------------------------------------------------------
% V9 U3 O8 M2 O# k// IDE NT/2000/XP专用变量
- _- E9 i. ^# {  c* C# C3 g#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS2 n$ p( J& {/ o3 K& Y
#define DFP_GET_VERSION         SMART_GET_VERSION1 C( Y9 B% q3 U4 {. l1 w
#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND  r! D8 |9 F4 l: Z; g
#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA$ A/ a6 p1 @' V5 N/ n
# s: A6 X' k; q9 n
const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令" W2 \% r5 e7 j
const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
/ J- f9 f( _* b/ V8 g3 }- F
- c" Z8 H. r* b$ Zconst int MAX_IDE_DRIVES = 4;; y+ |" x/ G3 Q/ j5 s

1 b% H" Q: H; B8 U// SCSI专用变量
: p" R0 U$ W5 C9 fconst DWORD FILE_DEVICE_SCSI             = 0x0000001B;- H7 r: U* _/ R* [
const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);3 l+ H. _: M4 u2 B! S; x! s
const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition/ q6 _3 H# h) N
const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;. Y7 }9 T! E5 _, U3 o& y$ t6 I  d

* K/ B. i' L; {5 I. xtypedef struct _SRB_IO_CONTROL1 P' c1 ~: O) E8 N! E% f/ z! h* n
{
& i. y: U( ^7 f9 p  D7 ~* n% j- ^    ULONG HeaderLength;
5 k2 e& P5 N5 A3 x+ W2 {0 R+ S    UCHAR Signature[8];
6 e. ^7 i0 E1 B    ULONG Timeout;% S1 ^3 W, |# {# c! I
    ULONG ControlCode;; N; S. S; t, \5 Q; H
    ULONG ReturnCode;8 I/ V' Q+ H, _7 A/ \6 D( h) H" F2 J
    ULONG Length;
+ b& B; D2 u' S* B* d0 ]}SRB_IO_CONTROL, *PSRB_IO_CONTROL;$ F, ?- l% M/ `4 c- I3 G( `
0 O& o* {! K4 h
// 读取的主函数# N0 k! d! ~: R9 C6 A6 ]% v
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
# N$ W& c9 b" x, U! Z8 n/ K7 b" Q- A9 O) I- s
// 辅助函数. ^& `! C3 e7 o5 |: c0 S3 t% N3 z; o
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
$ U+ ]& o( j5 G/ E// NT/2000/XP函数6 g+ b" \" [2 R/ ~. X
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);2 x# b( Y+ ]; I. w5 h% a  z$ R$ }' a
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,6 p5 r) ]5 C! S9 L$ S; S8 U# j) V
        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
/ ]: z0 |& D, _5 R7 ?- z        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);3 o% \+ @. f0 r$ J9 d, h/ [; |3 x
// Windows 9X函数
% v3 {  g5 n4 @9 svoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);, j% i$ j7 v$ R6 s; F4 e9 n
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
8 A6 K- ~5 Z7 U7 I2 e# t        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);/ w: w5 w  r  o; {: L
; w7 X) z+ z; N, ~8 w2 I: H
// SCSI读取函数(for NT/2000/XP)/ Q9 N' ]1 b. ^$ J
String __fastcall ReadIDEDriveAsScsiDriveOnNT();
; b3 ~5 r; a& N" g; D( x! y& y, B! g//---------------------------------------------------------------------------
# O  W2 m& q) I( {3 X: [7 R3 r! A3 ?// ReadPhysicalDrive) W3 n% y( ^! p; ?+ u! D6 E/ e( Z
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList): R8 y- \! \* D% J
{8 h3 s6 n" G" X+ ~$ S- J
    switch(Win32Platform)* c( G* z3 [/ Z) x# H
    {
) L8 O( t3 F5 G, H) [! J8 o        case VER_PLATFORM_WIN32_WINDOWS:
/ d! J, O( n" a5 }* i% }. Z; }% E            ReadPhysicalDriveOnW9X(pSerList, pModeList);+ O" g0 _2 W6 A2 u2 N
            break;
% a% o8 d' D* ?2 Y6 G  {        case VER_PLATFORM_WIN32_NT:
/ c" z' m5 h$ d& R            ReadPhysicalDriveOnNT(pSerList, pModeList);0 {& J3 d' X" j1 I
            break;. ^+ @' c" d4 }# p: I
        default:
( h, v1 x" `) ^/ W: u            break;
2 `& ~1 n# `: S# d    }
* }* ~4 |9 l; h0 S, O}3 O( Q6 X* g# u  d/ q& n/ Q- J( e
//---------------------------------------------------------------------------
6 |, p9 U2 j# L; w// ConvertToString
4 a, u* s0 I; C' ~, S+ S, cchar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
4 g8 @) q2 H/ h& g+ a" _; \% o{9 T! h7 G! o  o0 r8 `
    static char szResBuf[1024];/ z, o" b9 g: _1 \
    int nIndex = 0;) u; g' K( E8 O+ S5 k
    int nPosition = 0;0 h) ]8 P& e9 F2 D
1 ~4 m$ h) ?+ o
    // Each integer has two characters stored in it backwards/ U/ w! ~4 Z* P2 p0 L- f  Z
    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
. r3 L& J1 U1 d0 K: C8 B: ]4 s) V    {
& S3 p, |1 d9 }8 _        // Get high BYTE for 1st character  M# A+ f+ A: I2 C
        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);  X0 Z0 ^3 g" ]5 H  S
        nPosition++;/ t, j% r$ _+ t/ [, ?

) |' A4 b5 c, l. f$ o/ x- T        // Get low BYTE for 2nd character
; c( h( s5 b# v7 n4 w/ r* F        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);7 u% p8 i3 a5 v! M; S& T2 u
        nPosition++;
/ A& ^" p; e$ R$ j1 }+ a    }
$ T# k' H8 w& _9 r, p6 Y) a) O, v* N! b; I: r" y
    // End the string
$ X8 P/ k- ^2 L( w    szResBuf[nPosition] = '\0';
0 w! ~' g7 U& @" J
1 C6 l+ ~: E  L5 |! r$ l0 s0 ^    // Cut off the trailing blanks
+ g- M% j0 f% |: f7 ?    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
2 k% O& E4 F. k& B0 M* x- h        szResBuf[nIndex] = '\0';
6 ^5 F* _- e. h! e; x8 \" n: S4 a/ S0 W
' A7 C, I" h8 @6 [    return szResBuf;
9 O4 U. A% \6 z& c}- J' z2 p! Z/ }& c. X
//---------------------------------------------------------------------------; n2 a( E. c' R/ r/ C$ u
// Winndows NT4/2000/XP 代码% O) b* h4 B- l
//---------------------------------------------------------------------------
4 @2 Y5 p. @; H, o) Z0 H// ReadPhysicalDriveOnNT8 V4 i) u1 g; p0 ?6 |8 s
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
) X( Q" T( l. o8 P) _7 ]( h. x8 r{% I! _' z) V# j- C, I8 L
    // 输出参数- d( C; @: R( z+ r  w" I
    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
# L2 h  E# X% r5 h
3 s$ ?6 m$ e8 |3 {8 {    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)8 Z0 o+ j/ v" ~
    {# k: Y% j- ]/ T& O2 W
        HANDLE hPhysicalDriveIOCTL;
' f8 i# U- B, n4 X        char szDriveName[32];3 G" C; g. t7 b( z
/ @/ ^3 W4 m5 W6 O. Q8 [
        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);2 g4 c, R  R6 Z$ e3 o2 Z. w. T( a% N0 e
        hPhysicalDriveIOCTL = CreateFile(szDriveName,! \' H* g& a: r' y
                        GENERIC_READ | GENERIC_WRITE,
" K( z& t- u# E0 E( U                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
, R& j* ]* n9 ]6 ~  a( {                        OPEN_EXISTING, 0, NULL);8 r2 A- x/ `2 Z! F0 `# p7 Z% q

9 F- `, G6 o! E; P$ \* N        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE): b+ E8 C+ K/ V/ q% T9 a
        {6 e2 l: X/ ]; E- d; P0 L; k) |
            DWORD dwBytesReturned = 0;( `1 I' h/ @0 v$ A9 T
            GETVERSIONOUTPARAMS gvopVersionParams;) U" X( y: H! Z+ ]; w0 _

& |# A* `- Z9 _7 ^( O: Z            // Get the version, etc of PhysicalDrive IOCTL
: {1 n& l9 h3 l4 v! T9 v, U7 d4 c            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));' d$ ?/ s! C; T: j

2 c+ y2 s$ r$ T6 p+ R9 f! J# b7 j            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION," I% `5 a, e7 Q: f1 z+ w6 M
                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams)," q6 ^: H0 }7 |! c0 e
                    &dwBytesReturned, NULL))
, m# a8 v3 x# ]0 n6 T            {) \) I9 d  V, ?) z- X
                continue;
6 y9 m: w3 b! ]" r! J            }( a5 c8 T- v6 B$ T

/ R( A5 C& v8 j" ~# D1 h1 v            if(gvopVersionParams.bIDEDeviceMap > 0)/ k; U) o6 p2 _7 @" U0 `' n% g
            {
/ j% f& |) O5 V& b1 e8 y" J                // IDE or ATAPI IDENTIFY cmd
$ x0 K8 k% Y8 Q9 f8 D+ h! \                BYTE btIDCmd = 0;: W4 B) Z* X4 T- z  x4 H
                SENDCMDINPARAMS InParams;, T# C+ q8 B, Z
                // Now, get the ID sector for all IDE devices in the system.2 R; V9 F7 [1 j) g9 h" W1 W
                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,+ J4 I; E/ u% Q! ~
                // otherwise use the IDE_ATA_IDENTIFY command9 H1 O) z2 @9 ]  |& m2 a4 v; h
                // 具体所得结果请参考头文件中的说明4 e5 z. P7 k5 J9 k1 ^
                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?' u' y6 K3 R# {; t1 d1 H% b) Q& L& [
                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;; A, Z( _) E2 [
                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));$ k( g$ y2 e7 A7 \( w# U
                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
% B. V/ O  r1 C3 r
6 W9 d+ v9 J# R0 N3 Z                if(DoIdentify(hPhysicalDriveIOCTL,
( J# I/ K/ o; J, Z' a                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,4 d. t1 v1 z! n3 g# x1 X. B! ?, A5 x
                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))' u& V& ^3 q( D) L: ]% h
                {" X4 ?8 q# T+ r+ `# v
                    DWORD dwDiskData[256];
- i" v4 t( g( Y! z  C2 ]  {                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
( B8 {5 P% F$ q( Y) v& I! A( B: I                    char szSerialNumber[21];
- |% I( P7 h; V7 n  X- t9 J, d                    char szModelNumber[41];  V0 ^0 f! d! c' T( Y

' m. x+ W2 R( F7 V0 l                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
% H( H( g* L, G6 }  E! b6 M- V. Z                    for(int i=0; i < 256; i++)
% F3 {( ~/ V$ t0 }4 {  t& d                        dwDiskData[i] = pIDSector[i];8 C1 r( J2 V) ?
                    // 取系列号) C6 }& j; ?2 `* ]! K4 o; H
                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
2 }" L& K; f9 x& \                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
: H+ Q6 M' h( {2 M6 y
9 j4 Z" F" p6 {; Q9 s                    // 取模型号
1 X' |4 [1 n8 x! t: {# O. W7 e                    ZeroMemory(szModelNumber, sizeof(szModelNumber));- B- l: B% B9 e9 f6 c' B8 b
                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
4 l* b; l0 n2 ^8 k$ l
3 z+ Z- c1 B) x9 `0 Z! H7 ~" }                    pSerList->Add(szSerialNumber);. s, v( w" y* f. {3 G
                    pModeList->Add(szModelNumber);
7 u& i! m6 r, z                }
' `: j5 P) _0 U; ^# _7 w4 c            }; d3 Z% K8 a8 @. X# L- e, [0 K# H
            CloseHandle (hPhysicalDriveIOCTL);
0 d9 z$ Q, `3 i' k4 V) N        }
7 \& h1 p( `) b! Y" \# M    }( q, l' R9 C7 U" U+ V4 x& {, ~
}3 _+ h% _5 B; p9 l2 M3 _$ s
//---------------------------------------------------------------------------9 U; M$ Q3 c1 l7 w3 C
// DoIdentify
/ c- i% A, T5 W7 F5 g" Vbool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,; R+ b. G( S7 G" @- D" [
              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,8 A/ |7 S, l/ `
              PDWORD pdwBytesReturned)
) w  q9 k# |2 |* u. k{
6 s, v$ B: `8 a3 e& Q7 }- S* R    // Set up data structures for IDENTIFY command.2 B( d" h; ~4 E; [
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;4 O; U. Y/ [9 e2 g2 ^7 v
    pSCIP->irDriveRegs.bFeaturesReg = 0;
: z( N' N1 J2 D; A  y    pSCIP->irDriveRegs.bSectorCountReg  = 1;" Z+ d  Y% F" u4 R6 T' W6 g7 `
    pSCIP->irDriveRegs.bSectorNumberReg = 1;* [' p3 o1 }6 R  [" \
    pSCIP->irDriveRegs.bCylLowReg  = 0;
4 }! L9 C- y5 i    pSCIP->irDriveRegs.bCylHighReg = 0;* ~# y4 l! t; Q* J7 i$ ?

* E0 n9 A# E* l* s) O5 U# P    // Compute the drive number.(主盘和从盘所对应的值是不一样的)6 Z3 F0 Q  h/ F1 v
    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;6 D  ^$ U& Y0 [
# L9 x/ w$ u% o1 M5 q4 W
    // The command can either be IDE identify or ATAPI identify.
$ g7 z# S4 S7 u; ]    pSCIP->irDriveRegs.bCommandReg = btIDCmd;
( ^2 n. Y$ t2 {    pSCIP->bDriveNumber = btDriveNum;1 e( `6 G* Z1 E; q! V
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;/ T7 y: ]* s' S# f
) n, P& ~* P# Q% `
    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,+ V3 L9 C0 \* S5 T8 ]8 ~; b
           (LPVOID)pSCIP,& P, O8 Z: r0 a5 z
           sizeof(SENDCMDINPARAMS) - 1,
  _6 \! E1 E9 Y; |% d6 ^           (LPVOID)pSCOP,8 L: z% s5 ^# |( b9 r
           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
/ ]3 G& j/ E% |: p. V           pdwBytesReturned, NULL);
0 p6 b* F& o" s, Z# T, P5 n}
3 x  ~1 I5 P0 r( \% x//---------------------------------------------------------------------------4 N5 j2 ]8 w: t/ e. d/ X1 A6 a! x0 t
// Windows 95/98/ME 代码; T% M% [* }) O( h1 _
//---------------------------------------------------------------------------
( X6 o, f9 d& P3 L// ReadPhysicalDriveOnW9X* d% C( V# u. o4 U# r8 _
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)
% Q2 K1 L. ?& O( z{
2 M5 x' _- ?3 q; X" s2 p    WORD wOutData[256];
: j5 i" ]$ m4 A    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);  U& ^! V- X( o6 Y" m

' r% X7 F( ^9 g6 Q    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。' S0 Y6 W) M7 ~  ~5 u
    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以( Y/ B+ T1 n6 ?% z& q
    // 避免蓝屏的出现。(期待高人能指出原因)/ N4 Y( h* J3 I" A2 b
    for(int nDrive = 0; nDrive < 8; nDrive++)
0 z. _3 c9 \" \# T# l6 j    {
5 g7 v' X0 {; j2 l" r        WORD dwBaseAddress;
# P9 `0 D/ X) P) W/ D5 J6 ^1 {( x# ]        BYTE btMasterSlave;         // Master Or Slave
  Y/ ^; l7 p9 y- o0 z* `7 C0 T        bool bIsIDEExist;: N& K( w6 E$ s
        bool IsDiskExist;' N% ^2 b- j# ?) k- u3 z. ]7 S
0 Z- ?3 x' E( M6 W( ^
        switch(nDrive / 2)
# e( s4 E$ x+ v/ z        {: c1 j0 o; u1 A- @: Y9 H
            case 0: dwBaseAddress = 0x01F0; break;3 O- \, c# K9 U, Y
            case 1: dwBaseAddress = 0x0170; break;2 |% i& h" T' L1 n2 L
            case 2: dwBaseAddress = 0x01E8; break;
* V5 G# m& B3 h% M            case 3: dwBaseAddress = 0x0168; break;
, N4 V( S; ]3 i3 X+ @. W4 t; \        }
  k2 M+ L+ e0 c( v- |. R6 Y+ b( A2 D0 J& j
        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);) p' E, F4 D8 n. O# ~* Z
7 H+ ^$ W+ N, y$ i
        // 进入Ring0/ W0 I( ~! d5 K$ x& W+ S
        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
# q* u, q$ Y) Y1 M! D* \, W                bIsIDEExist, IsDiskExist, wOutData);0 h* ~: L4 l% P. e9 Y7 a3 U4 \+ r
    }
1 N1 I# p# w8 s3 ]. V& B4 j, N6 g1 _% c4 ]
    // 开始读取
  b" Z5 S( U; x5 x    for(int nDrive = 0; nDrive < 8; nDrive++)
; _- C9 v% [# {    {* s9 M2 h$ F! Z$ @2 B" K
        WORD dwBaseAddress;+ D& d) G) O, R) J( Y
        BYTE btMasterSlave;         // Master Or Slave  v3 m& [, z" e5 X' G0 o/ D/ \" ?; q" g
        bool bIsIDEExist;
# L2 p) [) D6 n( u" n+ _        bool bIsDiskExist;
1 K" v8 Q7 ?- X! p& K  h7 f        switch(nDrive / 2)1 Z+ ], Y! D; q& I2 B4 f5 O
        {
) {9 d' H: S& i6 }) J4 X            case 0: dwBaseAddress = 0x01F0; break;1 q  B1 t4 T$ ?& v! U( @( O: V) G( a
            case 1: dwBaseAddress = 0x0170; break;
& g; u% o0 J' U$ n1 i) g            case 2: dwBaseAddress = 0x01E8; break;: }8 g  G0 C) N; e7 a* z5 j% u
            case 3: dwBaseAddress = 0x0168; break;
1 F) Z' k2 |$ o6 D6 A- O        }
' Y* i: h$ U# d2 }, H0 o
2 y1 X* ^3 O( c  w6 g; i5 y4 W        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);% A3 L, D# j4 j# d3 P9 V
0 k0 K4 X' f) f7 Y" T: u
        // 进入Ring0# L6 K$ k4 A% G! t+ i# b' q
        bIsIDEExist  = false;& ~6 s$ B7 c4 M/ D& O9 x
        bIsDiskExist = false;  H1 K, K6 s2 x4 y7 u
        ZeroMemory(wOutData, sizeof(wOutData));, w9 C0 ~1 N# g1 i  o0 U4 r1 W

, [- S6 i3 U2 L4 b        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,. [5 h9 L3 C4 J: T9 T1 M
                bIsIDEExist, bIsDiskExist, wOutData);
2 }1 s+ n4 n/ K( i# ]# I, k- e, ~  {
        if(bIsIDEExist && bIsDiskExist)) Q" S% y# ~( E+ Z, B
        {
* R; D& R: q& c1 ~( H            DWORD dwDiskData[256];5 S8 }0 ]- _) D8 s# K
            char  szSerialNumber[21];
6 i# p9 }- b. ]2 l            char  szModelNumber[41];2 W" O' d6 f( C" b7 V) p
; F! R2 B/ ]/ e* Y- q1 f5 C
            for(int k=0; k < 256; k++)7 w# r4 b7 X" R3 B: ~1 s
                dwDiskData[k] = wOutData[k];
% b& _! ?: s+ B/ a' h& S, q0 F% Y9 h3 G: \
            // 取系列号$ F: x2 Y2 d( U( _! M- ^  Z* Y, t
            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
3 d/ A" W8 a! d) o            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));5 N9 r7 V) i6 ?) i/ d5 D

' G/ \" D/ \7 h3 L            // 取模型号
0 t) t# g. {1 W0 \6 |            ZeroMemory(szModelNumber, sizeof(szModelNumber));9 g) d" U5 T, d# b% X
            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
; F/ b. K8 g! Z2 J) z; |
6 g( W* U' X9 S: @# }3 F            pSerList->Add(szSerialNumber);
/ j4 C% t2 k8 F' W; a            pModeList->Add(szModelNumber);
% |6 S' g3 ]" E% y        }% F8 M% e6 F7 S" f
    }6 Y! @; `- W# O- B, [
    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
! c2 U& s0 H* I6 z8 F}
  I  X( _  k+ x# t1 u* z1 I9 f//---------------------------------------------------------------------------5 ?5 i  p7 @# x
// 为防止不负责任的转载者,在此注明原出处信息,请见谅。
. x* z2 Q& Z6 I' e5 O  Q) \// 资料收集整理:ccrun(老妖),欢迎光临C++Builder研究: http://www.ccrun.com
/ Q8 k) ]  v' B' `2 A$ q4 l! a" G9 {//---------------------------------------------------------------------------' n% u. a& o4 b6 H! G# S4 |1 f$ |
// ReadPhysicalDriveOnW9X_Ring0()& g* B" m4 q7 G
//
6 P9 R. l6 Q5 j9 ?! l' B// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h2 H4 ^6 o! p( A$ n( E8 ]
// btMasterSlave = Master(0xA0) Or Slave(0xB0)! G* L- F9 O& ?7 B5 B
//---------------------------------------------------------------------------1 ]7 \8 d' Z. }4 M6 |
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,2 `, C3 k& v) w, `, l- A
        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)6 z+ M, I( b1 f- H
{
3 c7 d+ ^- I/ f; c! T    BYTE  btIDTR1[6];1 A; p# Z7 t6 m/ G; T3 u- r1 s8 H
    DWORD dwOldExceptionHook;: C: l) h  j+ R
    const int nHookExceptionNo = 5;
  j- u, ?3 A2 b" o
1 o) M# W6 U. C) u+ L9 v4 Z    BYTE  btIsIDEExist = 0;) C6 x/ [/ d0 `2 o
    BYTE  btIsDiskExist = 0;( d! _5 R2 o5 [( t% [& I' `6 T6 n
    WORD  wOutDataBuf[256];* X$ N9 ~$ `7 a1 R1 i
# G% D- n# |, p0 D0 w
    BYTE  btIsFirst = (BYTE)bIsFirst;
! F+ y3 i3 W8 F9 e5 L4 S1 w! ?$ Y* X
    const BYTE btBit00 = 0x01;
, T+ p' {( F; K% A    // const BYTE btBit02 = 0x04;
! @0 F) i# d! d, Q; Y0 z' z    const BYTE btBit06 = 0x40;% \3 d" o& ^; H! q& V0 j6 Y
    const BYTE btBit07 = 0x80;% H; j* Q( m2 u& R. j* T- Y
    // const BYTE btERR  = btBit00;" }8 f3 X, T! j, w* A& C/ d
    const BYTE btBusy = btBit07;, n: U& X, L; D, R& J3 H) |7 `2 l
    const BYTE btAtaCmd   = 0xEC;, O" A# S3 P! M$ n7 E. S- e' s
    const BYTE btAtapiCmd = 0xA1;/ c6 I; O) K" e9 K8 F; y0 U

- `# o( y# a! j9 t8 P# I- l    __asm
, q& z& K$ l  r( X/ M" z' X. Y    {7 u9 ^; [% {- p( I9 C4 c# b
        // 必须先执行这条语句
4 U. v) r' {0 y) D( a2 |8 [7 C5 m. M- N        JMP EnterRing0
+ D, M7 P! p3 N0 L( H( `, |& c8 Q8 ~; z% h
        // 定义过程
& V# d! ~0 a$ W" H( q: {0 V- I        // 等待IDE设备直到其不为忙为止. J/ C6 \# n# u9 g
        WaitWhileBusy proc
8 b- c( [! h7 @4 k6 l+ C3 n$ Y3 b& H- i5 g: P3 D) T
        MOV  EBX, 100000
$ x/ Z* |0 B# h3 O& |        MOV  DX, dwBaseAddress
5 L2 r. a) W, J; b7 ?        ADD  DX, 7
) `& _1 F" k0 V- z, Z8 R# }. V, a' H% B+ l5 f
        LoopWhileBusy:
" K( d0 F0 f+ z6 `" w/ ^& N' v8 x# a' ^6 [' Q; _3 q2 b/ O
        DEC  EBX
8 t/ K3 z' R# z; C, b        CMP  EBX, 02 b4 R6 j! G8 M) h+ s
        JZ   Timeout
$ D/ r: a0 k; D9 @8 W+ M5 |        in   AL, DX
  ?' B6 j, r; A6 Y) F5 }! k* J; b. K        TEST AL, btBusy3 G7 f5 ?2 D( Q2 }" @1 ]) ]
        JNZ  LoopWhileBusy
/ V' D" e( Z/ x1 D/ L! Z        JMP  DriveReady
2 T6 F( p' ~; z! M" V5 U6 w
  R8 v8 D8 v/ i        // 超时,直接退出6 q- Y, R& A$ H+ \9 F+ l- ^! o
        Timeout:) i' w1 D: i4 Q9 [
        JMP  LeaveRing0( t% \, L& b# F  o+ [% Q
        DriveReady:
0 M# X( l0 Y: D# ]        RET
& S+ h  c& R% r) k) l        ENDP   // End of WaitWhileBusy Procedure) e! P' [  q9 b, R( D

+ z6 m: G( Z$ C; i4 ?+ `        // 设置主盘和从盘标志: |8 _4 S5 c, M8 X# L, c4 c
        SelectDevice proc2 k/ p  w. K. y$ y1 v) N8 N# L) Z4 @

% z9 ?& G1 }1 \        MOV  DX, dwBaseAddress
- h" U9 w8 g2 v        ADD  DX, 6$ u9 I) K- D7 E$ T! M5 V
        MOV  AL, btMasterSlave* V7 D9 D* j; l- ?4 O$ F; L* F. k

1 O% M1 Q, J8 D% r1 M3 L        out  DX, AL
& u: J( D) ~+ M# `        RET, I3 `1 x. i, H" U) |4 p) ?( y

5 t6 H; ]5 x. h1 e" c- F% n- h        ENDP  // End of SelectDevice Procedure
* ?, n6 ^( h. N% O( C
0 |! p/ I# @2 h3 b) _0 Z        // 向IDE设备发送存取指令: X. v; D% C1 u& `2 }3 [
        SendCmd proc% Z" P7 c" z2 d

& X( o( Z6 M: O- T. z        MOV DX, dwBaseAddress& m1 R4 i3 U( }9 T' f' c/ C
        ADD DX, 71 s$ e4 C3 ^6 ?; j' N5 ~1 [8 v) g
        MOV AL, BL // BL是主从盘标识,在过程外设置$ Z' @$ f. X: T: i$ z' ^( Y
        out DX, AL7 X9 w. G# l5 V8 d* l! u4 B& h
        RET
( |9 C" q6 ~2 d: k7 t        ENDP  // End of SendCmd Procedure
+ \/ j" ~% d9 y. W9 [( Y
' E' d% H7 @$ b/ d        // Ring0代码2 m  g3 H4 M; ]- _; G) Q7 D
        Ring0Proc:3 V) x% [. g' b# F
        PUSHAD- {0 ]: g4 o7 m. V" M
        // 查询IDE设备是否存在3 d; Z2 ]0 o# ?" c  }. L
        MOV DX, dwBaseAddress
+ _8 p- S; ?( p        ADD DX, 7; I5 ]4 _* I4 {7 M. e. l
        in  AL,DX3 n# m/ R/ H5 u# m: f' n- P

( G0 S9 {# b8 v. d; w        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
) v- J$ w+ ~* [4 r+ ]. k        CMP AL,0xFF6 t+ K3 P8 v& o# }4 _
        JZ  LeaveRing0" [" I+ z- R2 Z9 S' q
        CMP AL, 0x7F
5 V& I7 y; D0 M; V  X* N        JZ  LeaveRing0- E- H/ X3 u2 d! @% ]
1 }; O9 C) n& h# C# ?' ]5 n, ^) a5 o
        // 设置IDE设备存在标志4 z' N+ H& e. {5 Y) P# G
        MOV btIsIDEExist, 1, B& q' K' t% D% w0 l9 A

* v1 V/ k3 y: J        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)! c, W: Z4 K+ R5 R8 `5 E
        CALL WaitWhileBusy
2 ]2 t1 Y1 {% K* Z7 Z9 v        CALL SelectDevice
7 S1 |# h1 F& i2 r* t! `' s9 M( d0 J7 Y8 X4 d( z
        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏. W; _% }5 m& G5 A3 i$ O
        CMP  btIsFirst, 1
7 s( L9 y# M- e% J        JZ   LeaveRing0
; h/ r4 Y4 O& f3 ^) j2 V" R' g5 F
, k' ]9 N5 s! x( ^9 }0 o& l+ _+ p        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???& P# |& v/ o! P* i- W0 M) T
        CALL WaitWhileBusy
5 Q, ?. l% C. f% n4 [$ z
# M+ Z5 Y& @" W1 ?. ^1 S9 \        // AL的值等于cBit06时,不存在驱动器,直接返回- ^( F6 k# }  [( M5 m
        TEST AL, btBit06
9 j* N4 g; T. t  r        JZ   LeaveRing08 l0 s- E% ]$ e- N2 l, S  d8 }

. ^3 R7 r0 f6 S        // 设置驱动器存在标志
; a) s$ f, m0 O2 e        MOV  btIsDiskExist, 1
3 E- w) I% e- Z. S, X' h1 S+ f' S! L; L
  h2 Y9 D: e; m$ z        // 发送存取端口命令, G7 `/ F( }; c$ S, k; u
        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,  F0 d  m) ~, l; Q, c
        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令& W( e" I" q" q+ T) ~
        CALL WaitWhileBusy* b; w" `' D: K. R
        CALL SelectDevice    // 设置主从盘标识
/ ~( s1 S+ p; }7 Q        MOV  BL, btAtaCmd      // 发送读取命令
% }/ X# d8 D9 G( t$ }: N$ Y        CALL SendCmd" a+ g# n7 g- P. P! ]5 R" S
        CALL WaitWhileBusy" }  ^1 R# t- X$ d  u+ Z! \
6 C0 i, R6 O5 L* o
        // 检查是否出错
8 N2 Y% B  ?$ p) J        MOV  DX, dwBaseAddress
% G, x' i6 t: b6 c9 F( ~        ADD  DX, 7
: b" x5 N( k4 A" Z. ?7 ~/ ^
8 J( N' q* S) y+ G        in   AL, DX
- j- s0 T8 I. Q" \3 `
( E6 P: H* d* z+ |" W" S$ j5 t, l, j        TEST AL, btBit00% B! `7 h: C! K+ h  o" m; i  N- z
        JZ   RetrieveInfo   // 没有错误时则读数据
" p: o) e6 h6 V0 L* v9 y, n8 Y9 K% h1 r
        // 如果出错,则进一步尝试使用ATAPI设备命令- {7 X4 L: ]9 N/ j
        CALL WaitWhileBusy  H. ^& f( o& h, f/ j! ]. b
        CALL SelectDevice/ M% [, _" _8 j$ t& J# [" [
        MOV  BL, btAtapiCmd
1 L) u* n, D- V$ o" P3 `        CALL SendCmd
1 ^% ]- u2 D. O/ I+ |& R        CALL WaitWhileBusy/ b1 g4 o3 F6 J: u* `. ?

7 F/ O9 U6 W# Q1 e+ _        // 检查是否还出错
. N. U* b6 ~0 N0 Y2 w4 p        MOV  DX, dwBaseAddress
6 j* [- I3 @4 G+ M( o4 f  a        ADD  DX, 7
* [+ x9 M' l4 X. w* x        in   AL, DX
9 z9 D% m. Z4 p8 |" E& v        TEST AL, btBit00
; Y! N; L  J) I* \% P8 E        JZ   RetrieveInfo   // 没有错误时则读数据
$ Y  K, K$ `# l4 h( x3 @* }        JMP  LeaveRing0     // 如果还是出错,直接返回
) a2 m% e8 J8 G* A; ^" ^7 O
1 n$ \( r: L$ |9 x! ~        // 读取数据
  h/ j: E) i. H$ e$ j2 I+ k        RetrieveInfo:
8 a0 `6 z2 v. r, X' v# P/ e- e. h8 h2 d& m
        LEA  EDI, wOutDataBuf# J+ Y' P1 s' G; j/ q
        MOV  ECX, 256" u. f2 f* ?3 I6 g4 ]6 M
        MOV  DX, dwBaseAddress
# m7 _  I4 {9 i8 \/ s" @. Q        CLD
+ r% s3 H  N3 S$ W' N( \
' K- W/ `$ E' K/ w        REP  INSW
& q; `/ n9 @6 b3 T
9 |" p8 G8 n+ Y6 O; e        // 退出Ring0代码& v8 F/ b- _8 f  J5 y
        LeaveRing0:
. N# i# m' w9 T8 U1 s0 _# t8 p2 A( N/ q+ h  [  r
        POPAD
7 Z1 m/ z  x1 }1 D  e+ A1 E        IRETD
- W: y& ]. ]! l/ n: s- Z$ l) N. f. _! J
        // 激活Ring0代码2 l. v( g' A$ }6 F# ]
        EnterRing0:
. G4 n! k9 K2 _; {/ x. J: j' }0 E5 P) b
        // 修改中断门2 {0 H9 K: G3 p: L
        SIDT FWORD PTR btIDTR10 s; m! _% L2 h3 k, g/ Q3 ?. T
        MOV EAX, DWORD PTR btIDTR1 + 02h& G* H0 C4 p4 Q+ g" h
        ADD EAX, nHookExceptionNo * 08h + 04h
* E( F/ S9 D: [9 |) C; e        CLI
- z! k' ?, v; Q  A4 v7 O" I* i% g$ M/ B$ A2 a+ D
        // 保存原异常处理例程入口+ X7 A3 b9 Z: x* g6 A! k# P  X* `6 Y
        MOV ECX, DWORD PTR [EAX]
6 g$ U- ^! N. n, g$ c0 G+ O3 x& E        MOV CX, WORD PTR [EAX-04h]
; `! S3 s+ B! V/ R& o        MOV dwOldExceptionHook, ECX
2 f# W# T4 U6 g, w& m" k- J
4 b; B9 K: t' T/ L3 _        // 指定新入口
: H+ s: W8 i) h- p, U        LEA EBX, Ring0Proc! S5 a2 U1 W9 c
        MOV WORD PTR [EAX-04h],BX
5 t) o' s7 x5 u$ R5 n        SHR EBX, 10h
# m( S1 s# p0 k, B( }: k        MOV WORD PTR[EAX+02h], BX
* y' a& T8 x8 @4 n! C/ F% d/ |5 w
        // 激活Ring0代码& l% V; y7 y0 M! J; N5 @
        INT nHookExceptionNo) K- l' G; h+ b% l

4 J! n$ l9 J" y! P7 u3 W# N        // 复原入口
' U1 S4 t% I* E1 E        MOV ECX,dwOldExceptionHook! B8 K% f( ^# n8 j. u. O4 R! q
        MOV WORD PTR[EAX-04h], CX
+ ^$ W# a  b! c! ]; Y( M# e        SHR ECX,10h% a6 P# y( |: N
        MOV WORD PTR[EAX+02h], CX
$ o0 O) d+ k7 d+ G. n  c2 I0 f        STI' P3 H& S  `- w$ l. }- `' b) z
    }, E  }% Q7 ]; }& T& \6 t) k
    if(!bIsFirst)
- r% r$ \3 E; Q* _    {: i# T: x8 s# h4 l8 {# @# H
        bIsIDEExist  = (bool)btIsIDEExist;8 j  Z1 V& |/ H# {( L" l0 z
        bIsDiskExist = (bool)btIsDiskExist;
$ g$ ~& `$ q2 ]- ^. g1 W        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
8 I! E8 a% D; K# Y- ]    }7 K( R% f; U2 R, @6 g
}
. R: Y0 g3 G2 X0 V2 t//---------------------------------------------------------------------------
6 L6 j! F& R+ n/ q0 D1 K$ V// 调用方法:
4 \9 x6 x" E  i  }) J+ e4 Ovoid __fastcall TForm1::Button1Click(TObject *Sender)
  ^3 J9 X/ Y) J( f{$ o3 i9 D9 j3 C2 G/ h/ o
    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);; i9 ^. z, P* `+ j2 V
}
6 C# W! i8 X# Q
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-12-29 20:00 , Processed in 0.046732 second(s), 23 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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