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

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

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

  1. $ p( a- {) |* z; x
  2. #include "StdAfx.h"
    & m, j: J5 Y, y: L
  3. #include ".\puiddisk.h"  B6 Q  Y( _% w3 A+ Q; x
  4. #define _WIN32_DCOM% o2 L* x2 ?' x! F7 R
  5. #include <iostream>
    ) \. y! D" y, s2 v6 L
  6. using namespace std;( \. Q0 u+ A, g3 u9 d* F9 d! z
  7. #include <comdef.h>
    2 u7 J  a) q: V0 w
  8. #include <Wbemidl.h>! ^+ P9 v6 {0 E" q/ {1 m

  9. ( D# O9 a' r. ^: \+ j
  10. # pragma comment(lib, "wbemuuid.lib")
    8 X1 }# S$ l" ?& C: O1 }
  11. CpuIDDisk::CpuIDDisk(void)+ v% D7 ^8 U  Y9 u# t; m8 y
  12. {
    5 H* }. F9 }5 Y- X) d" `  q0 B
  13.     GetInfomation();8 u2 K# Z) R6 m* ~+ K1 O
  14. }
    # F; R3 Q2 X7 j

  15. / j3 M1 F  g- C% ?! K* j4 H. k
  16. CpuIDDisk::~CpuIDDisk(void)
    4 b3 A6 l9 c# [6 \  |# K+ o7 R6 h
  17. {8 I% a/ h1 l3 }) Y
  18. }
    2 D# S, l4 |- t# M7 f+ l/ Q2 t
  19. int CpuIDDisk::GetInfomation(void)
    % g8 t$ t- G  e( @0 N. H
  20. {" V( O; p) Z3 \6 C: |  H
  21.     HRESULT hres;
      m9 x: d# }! y( `$ x/ E9 x
  22.     //步骤1:不是必须的,COM只须也只能初始化一次
    " g* s2 L- s2 m3 N( `
  23.      hres =  CoInitializeEx(0, COINIT_MULTITHREADED );% P% X5 i7 K6 \4 _6 Y, C5 |
  24.     if (FAILED(hres))
    & D7 o0 r9 q8 h: P
  25.     {/ ~, H& S9 [) w
  26.         return 1; //初始化COM异常:注意,COM只须也只能初始化一次
    5 y# v. X- i! ~% }7 q
  27.     }" d  X5 R5 @# e6 L. t( U
  28.     //步骤2:不是必须的,COM只须也只能设置一次
    ) P1 e% y& h0 a; o
  29.     //Set general COM security levels6 `2 x! ]$ ]$ M; b# u
  30.     hres =  CoInitializeSecurity(3 p6 z+ l0 \9 s( a1 m
  31.         NULL, ! e& F* m1 f' ?: n9 m
  32.         -1,                          // COM authentication# Q0 i3 ?8 Q9 i8 K2 J0 ^: k
  33.         NULL,                        // Authentication services  H9 i% d/ Q1 x, N4 J# Q2 [
  34.         NULL,                        // Reserved& A, ?0 h' f- X! G4 Q
  35.         RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication
    . x5 K  `4 I  ]6 S
  36.         RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  / o& R) c2 R7 n2 L; D
  37.         NULL,                        // Authentication info
    3 r( ]8 I% J3 q3 Z
  38.         EOAC_NONE,                   // Additional capabilities
    / c' p; O  O; M9 a9 T7 O4 q
  39.         NULL                         // Reserved
    9 y3 `5 A6 n$ v
  40.         );. _% I! v* O" F! ]7 U: u$ ^9 {
  41.                       / T2 y' F: y, a3 ~: E- n
  42.     if (FAILED(hres))/ _8 O$ R* E1 W( n) U/ k" v
  43.     {
    ( D4 o. t2 H5 V, q  h* v% s& u, O% S
  44.         CoUninitialize();. D2 D3 b( p* h1 T* p: J  |$ q
  45.         return 1;                    // Program has failed.
    4 _  Q/ Z  Z/ [& n
  46.     }. n  ]$ c. n# O; i: b& B
  47.    
    9 w- W/ |5 z% p
  48.     //以上不是必须的,若已有“::COMInit();”,则要跳过
    * n( l" c' i, k
  49.     //步骤3: Obtain the initial locator to WMI
      Z0 R9 T1 f7 A
  50.     IWbemLocator *pLoc = NULL;; s* F+ R9 X; S& l
  51.     hres = CoCreateInstance(7 u: n2 h# B5 c5 v; T0 `$ i
  52.         CLSID_WbemLocator,             8 L0 Z2 [; r1 d! m- i
  53.         0,
    & I  ]' C9 m# E4 j. c" G* O
  54.         CLSCTX_INPROC_SERVER,
    * f6 B2 ~. Q+ E" j" W; F
  55.         IID_IWbemLocator, (LPVOID *) &pLoc);
    - w7 A% p. x! R* X" R5 w
  56. 7 r+ ^4 ?4 o1 [, X
  57.     if (FAILED(hres))
    . J) Z. i+ Z5 \* E. N/ s& F" H5 l
  58.     {
    * F: Z& j: Z# l1 ~
  59.         CoUninitialize();
    " u" c0 s; C& b5 n  c+ y
  60.         return 1;//Failed to create IWbemLocator object( V5 j* k( [% ~2 m  Z
  61.     }0 e* Q0 ~7 o: F( I. H; H6 e7 K
  62. " h( J) V) s: K7 \2 A( c
  63.     //步骤4:Connect to WMI through the IWbemLocator::ConnectServer method- m  b% u) h+ _& C* J3 r: r" s  _
  64.     IWbemServices *pSvc = NULL;' e# I6 {  E7 d; i6 Y* |
  65.     hres = pLoc->ConnectServer(; ?% X2 f  l  @
  66.          _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace3 G4 T- V# v; d6 j! V
  67.          NULL,                    // User name. NULL = current user5 ~2 Y0 Y* X" z, J* b) w+ d
  68.          NULL,                    // User password. NULL = current! O4 x5 w. Q7 M/ \) E
  69.          0,                       // Locale. NULL indicates current& P; Z9 O" p: Y, b# t2 N
  70.          NULL,                    // Security flags." P7 n4 R3 B2 v& R% ]
  71.          0,                       // Authority (e.g. Kerberos)
    # ?8 N$ v# S& Y! ]
  72.          0,                       // Context object & U1 {& Y. c5 [' B4 m2 f
  73.          &pSvc                    // pointer to IWbemServices proxy! M6 F$ R3 `( [3 X; s
  74.          );: F0 P' ?/ O! W3 o% p! ~
  75.       ]1 K* [  f! V; u$ ~! }; h% t/ p( y
  76.     if (FAILED(hres))
    & s$ P& g! ^& \6 I8 Y0 J' f% N
  77.     {
    - j1 z# G2 s$ G0 l, [$ H) P
  78.         pLoc->Release();     5 P8 i1 v! y6 ~- c7 z- O3 B6 J
  79.         CoUninitialize();' a! A; g- V" {4 Q
  80.         return 1;                // Program has failed.# ~$ k3 D+ u5 U$ o6 {' y; ]
  81.     }
    8 [; Z1 Y% P, {9 C# S
  82.     // 步骤5: Set security levels on the proxy
    + p4 G6 ~8 H; ~# j
  83.     hres = CoSetProxyBlanket(  f; V9 q0 {: ]& m7 p+ Q
  84.        pSvc,                        // Indicates the proxy to set
    2 h# a8 z0 `! Y6 W
  85.        RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx
    ; N& l: F$ m- |" H: b+ @
  86.        RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx
    ! G  s) j. I. p/ {
  87.        NULL,                        // Server principal name
    ; B; o7 G2 ]( G9 @. x1 I
  88.        RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx 8 S9 O/ P% I# \% K, R. Z
  89.        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
    $ ~8 C0 Z9 Y7 u  f
  90.        NULL,                        // client identity+ \/ s( f6 k/ e! |+ X+ q
  91.        EOAC_NONE                    // proxy capabilities / d( J0 t1 b, y$ Q2 A9 `  l
  92.     );  l) R5 H1 u5 s5 \! p6 h
  93. : T, e2 t$ _8 P) c" B5 y  h& R' P
  94.     if (FAILED(hres))
    3 b% N9 p  X) _- s8 G6 @
  95.     {/ J' b" U" C8 U0 M4 t
  96.         pSvc->Release();! n) H/ n9 W- D; d9 B$ ]: N) R
  97.         pLoc->Release();     
    3 U2 \* e8 H! z3 q
  98.         CoUninitialize();
    $ Z/ Y" S( K8 f# N" A  W
  99.         return 1; : E3 b) E  \* y
  100.     }; Q7 O3 N. Z" Y! W! [! Q) |

  101. 7 C, @% q0 a, S9 ^4 a% I% Z0 I
  102.     // 步骤6:Use the IWbemServices pointer to make requests of WMI ----9 J! P0 H, {' U$ j
  103.     IEnumWbemClassObject* pEnumerator = NULL;1 }$ w9 {6 z% v9 {8 R1 ^1 S* ], g
  104.     //计算CPUID
    / z' O: q1 f4 G3 L
  105.     hres = pSvc->ExecQuery(
    4 Q! I9 i6 O# O' o
  106.         bstr_t("WQL"),
    * J: }2 g9 F5 P! ^6 N
  107.         bstr_t("SELECT * FROM Win32_Processor"),//Win32_OperatingSystem( g) A6 H- g. t' B
  108.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
    7 P5 I. P/ P+ x# u% {
  109.         NULL,
    ' ^$ s7 j- d. z+ q! c
  110.         &pEnumerator);5 k8 Q4 p: E$ l
  111.    
    , E4 @, m+ T3 U+ U
  112.     if (FAILED(hres))4 ], c# M, W  p  U; |
  113.     {4 j6 s' t1 r- |( F
  114.         pSvc->Release();. A: l# r- W7 Y" `
  115.         pLoc->Release();' N% h6 ]6 a; L+ o. m0 b
  116.         CoUninitialize();1 M! {. h$ u- \2 M
  117.         return 1;3 j) A, b+ Z# I8 g4 y. R
  118.     }
    + A( U! w! V, p* j# z
  119.     // 步骤7:Get the data from the query
    . [7 R9 I3 s4 e/ z
  120.     IWbemClassObject *pclsObj;
    9 G. e3 S$ B; @5 Z+ C" H
  121.     ULONG uReturn = 0;
    ; q' [, x0 ^, i+ ^1 O3 P* y
  122.     while (pEnumerator)
    % x0 g. E! W! G5 E" |' M) b
  123.     {6 \" {& Z; J& K; c
  124.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, 0 ^9 y" }5 Z/ U% i6 b- \+ g; A
  125.             &pclsObj, &uReturn);; u7 n5 e1 m- ?4 q. N

  126. % s' @) q- g! i
  127.         if(0 == uReturn)
    ; O# q9 L! E% x5 i) ?
  128.         {
    1 M; `: T2 C9 p- C2 p9 Q6 `
  129.             break;
    7 y: d0 a; j" V* ^( C6 |3 Y( |, w
  130.         }8 K% K9 B, a+ y* L- \) v( @
  131.         VARIANT vtProp;) A" e  u0 I0 d! V% F$ U; A
  132.         VariantInit(&vtProp);
    1 R1 ~" h9 F' M& U* O
  133.         hr = pclsObj->Get(L"ProcessorId", 0, &vtProp, 0, 0);7 Y. n4 t& M; T+ s9 r# o' |
  134.         strProcessID=_com_util::ConvertBSTRToString(vtProp.bstrVal);//strProcessID:类级变量& l1 F' {% g; a8 a
  135.     }
    : r' d8 L: m5 b' A4 m5 C8 c" |7 W4 w: z5 j
  136. 2 f1 {- X- S2 ?4 c
  137.     //计算硬盘系列号
    9 y4 f7 H- a9 o& U; h9 E' |4 D
  138.     hres = pSvc->ExecQuery() I% Z7 s& Z, l  Y
  139.         bstr_t("WQL"),
    . Y3 E* t6 U1 Y' o  {3 o- o
  140.         bstr_t("SELECT * FROM Win32_DiskDrive"),+ t1 F: a8 e$ _* Q; O
  141.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, * \& z5 I- a$ V- {& p4 F$ A% R
  142.         NULL,/ j' O7 _4 ?+ d# r+ L
  143.         &pEnumerator);3 R- S! _- i* k/ a  V9 q! \6 {

  144. 1 G7 F" L8 E( v' J& o" J
  145.     if (FAILED(hres))+ k; ?# b2 j! v9 M
  146.     {9 M! J" h/ D1 Q4 x
  147.         pSvc->Release();
    1 w5 z# v2 O: |7 m1 [  V
  148.         pLoc->Release();
    1 z  {! c% h: X" y
  149.         CoUninitialize();, o. A1 I- u) l4 p, V8 O! {( I' f
  150.         return 1; 3 d+ `6 y- \! b7 O4 E
  151.     }; k# {( u$ k$ _/ w& u4 }; X. d
  152.     while (pEnumerator)& {6 j* ^  N1 R# B; u5 R
  153.     {- Z+ M  Y# F. j
  154.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
    # j( M9 E9 t1 T! |: P
  155.             &pclsObj, &uReturn);
    - b! b2 J5 ?- S" t  H3 c' O

  156. 9 h  ~& |; ~# h+ U
  157.         if(0 == uReturn)& N$ ]: ^3 K5 @: b0 i9 E7 d" _
  158.         {
    ( ?8 A, C3 H$ h9 [+ \" D
  159.             break;
    $ T6 R9 O; L2 ?6 V9 a& z
  160.         }. G) i3 _* D3 @) t* D

  161. $ K0 B& H9 N  S/ k+ t* s# ~
  162.         VARIANT vtProp;
    2 I, X" f; g# x7 o+ r- E
  163.         VariantInit(&vtProp);
    : E% m5 L, d% J0 @) i  S2 u4 F% u6 A2 I
  164.         hr = pclsObj->Get(L"PNPDeviceID", 0, &vtProp, 0, 0);
    , i/ `  C4 }! a7 I
  165.     strDisk=_com_util::ConvertBSTRToString(vtProp.bstrVal);
    $ w6 r* }( {+ h! [3 |
  166.     }
    ( g1 T& C  b9 h( E3 D

  167. 4 b! n2 K* d9 D9 @% c1 ]2 S
  168.     pSvc->Release();
    8 Q7 H. O' ~% O5 ~: L" b
  169.     pLoc->Release();
    0 Z& h1 y% s- h
  170.     pEnumerator->Release();! g5 h; c. Z, ]4 C
  171.     pclsObj->Release();/ p  {; f9 l; H( m: e
  172.     CoUninitialize();
    + [$ b/ k) i7 [- a4 a
  173. - `! L+ g/ q& V2 |8 R$ v, z% t- l. t5 n
  174.     return 0;   
    : R# y+ ~4 e3 x* v9 Y8 I' M
  175. }
    + z! S/ k" h. @0 z& j# @) p( a
复制代码
 楼主| 发表于 2010-10-11 19:21:05 | 显示全部楼层
本文代码经ccrun(老妖)在Win2k下试验成功.
( G( s1 w) l" W/ d; a
& q2 ]* L' T& k& y/ a#include <WinIOCtl.h>
- S7 l: z) \1 h( X" Z#include <stdio.h>
" {& p. R* r: ~& ?2 ]! V8 k* ^8 F# P: J$ [. i( g
#pragma inline
% k- ?, Z1 ^  u0 U//---------------------------------------------------------------------------
  s6 g4 `# ?. g% A% `// IDE NT/2000/XP专用变量
8 _) e! H& h* F' L9 z; \  ^0 X# a) r#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS& X) a4 w9 M% ]5 I: J0 G2 `* K
#define DFP_GET_VERSION         SMART_GET_VERSION
8 X  N3 \# E; R* t4 m) O#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
6 \' t$ f# j* {4 a8 v8 }! {#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
4 l& _7 G6 {$ u. N4 e, Z) `# `3 |4 O3 i6 h2 g2 U' |2 h
const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令" e' p" u/ F) k" ]. Y
const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令: q& D1 J6 k5 Y; _" ^: y: g. M% V+ P
4 S* x, b6 h# F& Z' e+ O
const int MAX_IDE_DRIVES = 4;
, v/ ^3 [, ?) g6 ]5 T. ]/ t5 o' g; h# I
// SCSI专用变量7 C" q+ ^* H& A% p! G( i) N
const DWORD FILE_DEVICE_SCSI             = 0x0000001B;
- L  }. E* {& Zconst DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);! J3 {7 ]% \* u# h5 U7 ]
const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
. \4 ^! |1 q4 Y% x/ Oconst DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
/ P$ j* s, n9 f0 W# g1 t5 B* A& G+ [! o4 [4 f5 \; \$ @4 ^
typedef struct _SRB_IO_CONTROL
4 z# P* B/ F8 E# Z0 C{
8 |: j! i1 j2 V  L    ULONG HeaderLength;
# t) A& {! w$ X    UCHAR Signature[8];
, n" X2 V- e3 w8 n0 f2 Q6 S    ULONG Timeout;
* X2 F9 G7 u7 U9 x' w" N. {    ULONG ControlCode;
# e3 j5 P8 R- B% [7 q1 w4 C4 w    ULONG ReturnCode;/ s: r1 o+ f- Y" o( T9 @
    ULONG Length;
" _" V% K6 I# i" `+ {9 }}SRB_IO_CONTROL, *PSRB_IO_CONTROL;
) P' {* b! @6 D+ c9 U2 \4 ?! N6 x$ n: c7 @" ~$ u9 I
// 读取的主函数/ t; m; F3 {5 U+ M
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);- ]- o1 c8 j$ \4 W7 w6 p

! H1 U# p. D2 U% L// 辅助函数# w" t, k+ J3 d( Z, l( }4 B
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
/ v" T3 M( E' g& Y( U: i- ~+ u// NT/2000/XP函数' y4 ~( n, |4 |: f( J5 @
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);: W" U7 J" ?' b( x; X7 }1 J
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,( r8 N8 ]/ [) g) }/ j
        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
1 I- c5 x! O- v. s5 ?        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
; |2 J+ c- W" Q' u2 o7 p0 ~// Windows 9X函数; c  D' G- P$ `2 |% s8 V- O
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);7 F! L+ L) c7 e: J0 `9 |/ `  c
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,& q! |0 d& ?8 [8 N# X
        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);/ P* q( ~8 R8 D2 _2 x7 p
. @) F$ z- ]: d4 u! i" w
// SCSI读取函数(for NT/2000/XP)( u2 b# b) x+ P$ p& w
String __fastcall ReadIDEDriveAsScsiDriveOnNT();
# R4 q1 w/ u" w- G" ^0 l$ d' l//---------------------------------------------------------------------------
" W: G9 a9 L- w* L4 p1 J// ReadPhysicalDrive
0 q8 l4 ^3 F% G# hvoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)1 J- G6 ~" ^1 n6 W% h% r# Y
{
, ]4 \8 r9 Z3 L) h' m, `& n& M, |    switch(Win32Platform)
9 E9 G- k2 u* J  _  n  x4 l1 P+ ~: b    {0 ^" Z$ p+ C( |& }( a, f
        case VER_PLATFORM_WIN32_WINDOWS:
- z& h& M0 V$ {7 \: U9 S9 E; `            ReadPhysicalDriveOnW9X(pSerList, pModeList);; y6 ^# l& z# I; M" R! a8 J" M
            break;
7 t$ K% y2 K. i* d  k        case VER_PLATFORM_WIN32_NT:
$ a. h7 }2 d9 f1 N            ReadPhysicalDriveOnNT(pSerList, pModeList);" [& y! {8 g- M7 w, Z) d
            break;
" t; ?7 i6 k2 Z9 `. u3 Z7 p        default:$ H1 T% s' g, ^
            break;
, h; d" q9 q4 t    }# S' v' E; u7 r; z
}
7 u3 w3 V2 e6 j5 d: A& G; A//---------------------------------------------------------------------------
3 }' K) Y6 o" e4 J! h// ConvertToString
/ O' e! f9 p' `- }1 y" b4 Tchar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
1 ?7 O2 E+ j+ }& ]) h( _1 ?{& ^- e; A/ e1 @
    static char szResBuf[1024];
3 s' V2 J! r$ U2 D0 {: U' y    int nIndex = 0;& _2 m" f% D: {% R
    int nPosition = 0;' t/ @" W: ~2 h+ l
, K6 M/ M- t  Y: D4 W
    // Each integer has two characters stored in it backwards
" A) w/ X# X& H7 h5 a1 w0 t0 R. x    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
' Y9 r7 T0 T# Z4 [% Y0 h    {
% G$ M( c5 U5 _        // Get high BYTE for 1st character
2 t( m/ E3 X6 v) F* h        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
! \( |* D$ ~, Q) m1 A! F$ F. m. w7 O        nPosition++;. x$ H$ i1 s5 r$ U: Y5 m* p% r
- g" w* r& J. [
        // Get low BYTE for 2nd character
1 L! c: a; S0 C$ o6 F5 z+ g/ y        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);2 X8 v" n# o; |" w0 o- L  [
        nPosition++;8 m' f! m6 ~7 p* E9 {7 i% {: v, T* z
    }
3 g" \, g  J* ]' l1 i, i7 U4 _5 [% l+ M1 g3 ~9 I7 u& _8 u; v3 o( g
    // End the string* i4 g* p" w( w$ g1 W3 Y
    szResBuf[nPosition] = '\0';& |& _4 j9 p$ a7 S8 I

/ T* ]2 A; \2 `6 u% q4 P8 i    // Cut off the trailing blanks" Y, y, o4 J8 p6 G+ L
    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--), A0 N3 ?$ s: g. i: h
        szResBuf[nIndex] = '\0';
7 J; U+ f* s" U3 A( [, k" P$ x0 v/ h3 q5 y2 [7 }( r9 f" g) V
    return szResBuf;# ]4 k1 {" }) V$ V
}! M" u; R9 h/ R( ?' G
//---------------------------------------------------------------------------6 X8 b4 D  u! u- }4 t3 _0 o
// Winndows NT4/2000/XP 代码
7 {$ O1 g5 P* R' M5 K- r/ |//---------------------------------------------------------------------------* ]6 V8 @( M. V( g
// ReadPhysicalDriveOnNT4 m' C* b; u( s+ x& N0 O
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
8 E: e9 b5 y, F5 Y$ [{
5 Q$ @% A3 G/ C' D8 S4 m8 s    // 输出参数
7 _# P$ |- Q4 R/ b    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];# g5 v6 f& T# b  d0 _9 n$ K
/ R1 p* Z/ ^; z, K1 \! j1 j1 I
    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
9 t" c# M! _1 ?$ |6 w    {
; ~5 q1 q6 _+ x. d$ I; V- j        HANDLE hPhysicalDriveIOCTL;  v0 r1 g. D9 _: _. T, _
        char szDriveName[32];/ B! C+ y- [: V* K  v4 l
4 Q# N! b. h' x3 C! Q
        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);* S) Q. L" \& L6 M8 ^1 O$ C
        hPhysicalDriveIOCTL = CreateFile(szDriveName,6 V& {# |3 Q! ~. \; M# a
                        GENERIC_READ | GENERIC_WRITE,* X0 I* z8 r4 N* Y* _! s5 A
                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,. M2 [/ s. [  e+ W- F
                        OPEN_EXISTING, 0, NULL);
8 n% @7 {( r5 ]: t. G6 K* k$ ^3 B& R/ D& E1 S6 \% t5 R
        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)7 @( L  c/ _* T* `' \! O1 r8 u
        {/ |# T: w1 h9 h" f* w
            DWORD dwBytesReturned = 0;+ M0 u( Z! U' s( h3 Q
            GETVERSIONOUTPARAMS gvopVersionParams;: D  s, g# B0 N' s" Y- M+ C: Q: K

0 A+ y+ w2 O) p2 J# ~            // Get the version, etc of PhysicalDrive IOCTL  n+ v: i, A8 ^- U
            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));6 D8 ?6 Q* j" Z! u9 |

; }/ P$ n/ }: M% ], F            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,4 l# u- R7 r8 b; L' X3 W3 p* \/ t
                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
# x7 g/ J2 {: p& P4 q( h, ]" l- O                    &dwBytesReturned, NULL))0 U: y+ v* M4 [/ B3 b3 y5 q
            {" t4 ^7 N, y2 X
                continue;2 W/ R- c4 ]: r& m( a4 _1 y
            }
1 D8 p7 Q2 A9 a9 R, J$ B9 F7 S3 N+ _% Z* T6 G) i% t
            if(gvopVersionParams.bIDEDeviceMap > 0)
/ M1 ~: H4 X5 R: g: N2 r            {# ?% g) s3 V6 S! e$ N( z
                // IDE or ATAPI IDENTIFY cmd
, {! k' P0 y, Z                BYTE btIDCmd = 0;
5 R: s$ B  @9 N& t6 ]* U: {& ^                SENDCMDINPARAMS InParams;; p0 N3 E$ }& @& M8 Y; @
                // Now, get the ID sector for all IDE devices in the system.5 t6 y: e1 Z$ n; o* T$ v
                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,+ X3 Q" U* U0 ?( C& d/ q* c5 b. l
                // otherwise use the IDE_ATA_IDENTIFY command
1 ^3 b1 S  }# ~- d4 ?) _& Q3 q                // 具体所得结果请参考头文件中的说明
* A% X. t3 i" J" B" {                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?5 G4 I' c% z% m1 Y+ Z6 F
                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
3 P2 n' H) T8 E                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
4 Y7 D, s- ^9 I: a                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
1 ^  {# ^1 V& @4 n) A, ^9 J& w9 W5 o- z
                if(DoIdentify(hPhysicalDriveIOCTL,
! P8 ]/ t' V" V2 {                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
+ o6 |- f% b& C. H                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
2 Z( e1 j" ?7 @3 c8 C) [                {
  E2 Q7 q& E% ]/ Y5 I  G* ?3 p                    DWORD dwDiskData[256];
3 x+ l  U8 F& s7 W                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
+ S5 u3 j4 P* H. Y3 [$ i% U' Q4 y                    char szSerialNumber[21];0 R1 X# [  v: g
                    char szModelNumber[41];
# T% ~- H8 K+ j  V
1 o8 ?1 o* b$ W) |8 w2 Z7 G                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
3 P+ G4 Q* f' f8 k. u+ u) X4 K) p+ K                    for(int i=0; i < 256; i++)
! W1 q+ c" \7 F2 {6 G                        dwDiskData[i] = pIDSector[i];
4 H, D  O' s0 \, k. o                    // 取系列号
( i# l3 V9 t7 J% W  e. }& C                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));, X4 q3 t2 B' I  k* J
                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));" \1 [  o) V. G4 L" w
5 H( A" a" ?+ x, J6 L
                    // 取模型号
. z7 d; _7 M" W/ ]0 G" J                    ZeroMemory(szModelNumber, sizeof(szModelNumber));4 i( w  G+ o) w; W
                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));  i$ |, i$ U; t: U( @5 `7 T

. }' s  a4 n2 k7 U% X' Q$ i* G                    pSerList->Add(szSerialNumber);1 V3 L& `/ T! Q3 j* N
                    pModeList->Add(szModelNumber);+ U5 A5 k5 k8 _" B2 @
                }
" _5 v* Q! t5 f; p            }' }3 s& x8 Q: s. g. R, J( x" ~0 c3 q
            CloseHandle (hPhysicalDriveIOCTL);
& |" s; g$ N3 Y' j) I$ k        }7 r; c5 k7 Z+ B. W7 Z/ I
    }
' p+ l  K4 y$ B3 F$ E}
. S0 g) W2 g, q//---------------------------------------------------------------------------
- C. q( y7 \9 M4 s" j5 C// DoIdentify
3 b% L" }4 W5 P+ b/ R, Rbool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
+ x5 M3 ]8 @( g7 ]2 o! d9 b6 p              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
5 o# [/ T, _: I8 W7 u7 U              PDWORD pdwBytesReturned)
1 b5 i4 ?4 i/ a/ y{
0 O+ g  h( V4 U. q& G    // Set up data structures for IDENTIFY command.
" {3 O" T6 j0 f3 A7 c( K% f    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;8 R& _: c, _' C
    pSCIP->irDriveRegs.bFeaturesReg = 0;9 l+ b. [+ ?5 _1 l7 L
    pSCIP->irDriveRegs.bSectorCountReg  = 1;+ `5 X/ m/ a7 D
    pSCIP->irDriveRegs.bSectorNumberReg = 1;
. v% u1 o% a0 v% L. g: F/ @    pSCIP->irDriveRegs.bCylLowReg  = 0;
2 G$ |" u3 x; Y' F* c    pSCIP->irDriveRegs.bCylHighReg = 0;2 o8 l6 g/ I( e
  ]6 L; Z0 f3 m
    // Compute the drive number.(主盘和从盘所对应的值是不一样的)- o# {% k, c" h- B8 @
    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;! z' ]1 \% E! x+ y* s( z6 b( V$ {

( d0 W  ]. p, E    // The command can either be IDE identify or ATAPI identify.: p. d& E4 g/ L2 N) `, S$ G2 l' T
    pSCIP->irDriveRegs.bCommandReg = btIDCmd;: L( Y& f+ `3 P/ T7 a% i
    pSCIP->bDriveNumber = btDriveNum;
9 p+ ^6 Y8 P3 m2 S6 h2 z; E    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
0 W0 G( {; j  K* Y# s: e, L, r+ x, X* u6 s" }) t
    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
, F( {; U( n6 |3 R% S           (LPVOID)pSCIP,
* I% F) W- i; X; r2 }: A           sizeof(SENDCMDINPARAMS) - 1,( j" [1 c- g. Q1 |- V9 Y  X# M
           (LPVOID)pSCOP,
9 q: E; y# I, L: y; y2 M           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,- Y( P2 Z, C, }# V: }8 M6 l# O
           pdwBytesReturned, NULL);
2 \$ T- _5 ]3 ~0 }, n7 m" ]}
) i' }+ n7 `9 u) s//---------------------------------------------------------------------------6 f& C7 t# O1 v2 X
// Windows 95/98/ME 代码
4 o3 ?& Z7 U0 m, [' |//---------------------------------------------------------------------------
7 ?9 }9 S+ |. N( s// ReadPhysicalDriveOnW9X
, B" |0 ~7 |0 R- h! {" Ovoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)$ \" }: g" q4 |" n8 f
{
: u8 [. Y$ Q& z; ~8 e, n    WORD wOutData[256];" n" D7 K/ G- z7 R$ m4 `
    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
( S2 Q6 k2 {* ?" S( L/ W- [8 t. l* J- d. R( o* Y! K. V; C! y* _
    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
  P* B& r1 [) G" f* e+ }    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
! j$ @. T4 h  s- S' m    // 避免蓝屏的出现。(期待高人能指出原因)
+ B( V* Q( g4 u3 i  T    for(int nDrive = 0; nDrive < 8; nDrive++)& B+ Z# _8 ^" \3 J% I
    {9 A9 y1 |( R( [. B: L% e4 T
        WORD dwBaseAddress;
$ i+ f8 \, ]" G7 K; ?        BYTE btMasterSlave;         // Master Or Slave) m, C, C+ j. O3 g0 C4 X! S) N
        bool bIsIDEExist;8 H& ], R8 o  _5 }* w
        bool IsDiskExist;
  ]8 |: e' R  }
) k& q$ O5 H. Y        switch(nDrive / 2)
0 `+ N5 @8 d& E        {4 X* o5 J$ ~, o  |* m0 i) a' @
            case 0: dwBaseAddress = 0x01F0; break;
6 S' d) U* e( V5 @            case 1: dwBaseAddress = 0x0170; break;
" E% e3 m7 g3 G( ]6 {            case 2: dwBaseAddress = 0x01E8; break;
4 P% I, _+ ?" U: W, L, E. T            case 3: dwBaseAddress = 0x0168; break;$ L. e$ M3 a) U& V5 y5 V& {. K
        }" V- y! {/ c& D5 D2 T( s8 ]
, ~6 Z4 K6 r  G5 U3 ?2 M( L' _
        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);; G1 @' r/ }1 I  Q

: h$ D* S+ a; ?2 h, D8 ]. Y7 d        // 进入Ring02 w2 e5 x8 u6 L. s! e
        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,$ U$ r8 H6 @2 K2 [2 }
                bIsIDEExist, IsDiskExist, wOutData);
- W2 n9 _7 X: A: d    }
1 a+ j8 c# h. I, c" o
5 ?) K2 w' X- Y& V+ Y+ i# U1 q    // 开始读取0 T+ B5 i8 w3 [
    for(int nDrive = 0; nDrive < 8; nDrive++)- t. q# r5 m+ B- P8 [% ]% s
    {3 o( n8 F+ n8 T
        WORD dwBaseAddress;
# a9 Q6 q+ E7 ], ^        BYTE btMasterSlave;         // Master Or Slave
7 L; p4 L+ r( U9 ?: k9 U# ^        bool bIsIDEExist;
) A( ?: s" e$ u: b& P        bool bIsDiskExist;2 ]2 O1 t( E& {5 O( B
        switch(nDrive / 2)3 N  E) V' b" a2 x- J
        {
% r/ h3 H0 w7 m" Y            case 0: dwBaseAddress = 0x01F0; break;
! m1 W/ ]! o1 [: X! F, w8 X            case 1: dwBaseAddress = 0x0170; break;
' l! ^3 C$ B/ v            case 2: dwBaseAddress = 0x01E8; break;
) [/ q; {; k2 F            case 3: dwBaseAddress = 0x0168; break;
. D* G8 Q* F, O% f% q: f0 n, X        }
* i& z; O1 Y5 @, T6 ]5 T) j- N1 H+ W3 a. `; X# ~4 n! v8 p" v
        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
0 `) A8 I% \, R6 O+ H7 B1 D2 Z0 N! U* }+ Z. ~  o
        // 进入Ring0/ o; B" W  q9 V$ x1 {* N; Y" D
        bIsIDEExist  = false;
& @8 ^. A- A0 L6 ]1 q        bIsDiskExist = false;
& t6 g* f8 l- x% S7 |' G1 m        ZeroMemory(wOutData, sizeof(wOutData));
3 ~0 Y/ Y/ R' Q  a0 s3 t6 o
) v: O" Z. J" l3 _9 {8 K- O        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
, g  }, D. Q  Z; ?) @  n) u                bIsIDEExist, bIsDiskExist, wOutData);2 w; K* z9 M8 s

$ U" ]* Z0 W% G6 {$ h        if(bIsIDEExist && bIsDiskExist)' M7 |# a" o# l% u9 ?; z
        {
, v! a7 q; F7 |# }            DWORD dwDiskData[256];! g, G: D# f; O3 i+ L
            char  szSerialNumber[21];
8 @5 b8 q2 y# q' X            char  szModelNumber[41];
# v( Y  l, u' P& U* m! ]- m& E/ @( M* q3 m
            for(int k=0; k < 256; k++)8 e7 d! ^$ Y" a, a0 F
                dwDiskData[k] = wOutData[k];- ?+ X# ^2 G& P! Q# |' ~9 F7 ~
' R9 _6 e2 L1 g8 |) T
            // 取系列号
: o0 A! W4 ^/ ?+ j! e% H! p+ z            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
$ P5 K! G  k2 ~+ W' ?' i( |            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));( K' Y6 A8 Z4 {0 N7 ]# a7 _
7 m9 _/ L9 G  B2 \
            // 取模型号$ o% Z  ~: j3 m- @- Q" E& B5 \
            ZeroMemory(szModelNumber, sizeof(szModelNumber));
9 V" l' e! {3 O2 ~; z( N            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));8 l7 a* J$ h# }/ ^
  I# n5 P+ r& }9 k
            pSerList->Add(szSerialNumber);
( W' Q* A! E& S0 q( A5 H            pModeList->Add(szModelNumber);
! T' j7 t% c, h9 p        }
9 D9 S" k1 ~" c2 u% L% j    }
( W0 c/ T3 o4 j: U& x6 V: C    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
4 F+ J8 _: l; y. _; o) @+ w7 c}
6 X2 w) w* a4 k0 y% Y//---------------------------------------------------------------------------
* G* t- |; X: N9 q" f( w4 U// 为防止不负责任的转载者,在此注明原出处信息,请见谅。7 [! N+ [- t4 y3 B) |6 z: n, C9 ^
// 资料收集整理:ccrun(老妖),欢迎光临C++Builder研究: http://www.ccrun.com8 u. P$ K& U* n( ?% }! V: S
//---------------------------------------------------------------------------6 o' z' o3 T& S5 M9 i! l0 W
// ReadPhysicalDriveOnW9X_Ring0()
* T- d  a- q0 Z6 q, R, q4 s! S//0 a! C1 c7 H- h4 C) h$ M2 }
// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
1 C0 W) m3 P5 s6 ^& g& a- \// btMasterSlave = Master(0xA0) Or Slave(0xB0)
; a- [4 G; J" o0 f//---------------------------------------------------------------------------
; W1 I! l8 k) q+ V6 a' Uvoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
" M7 W: o8 g) C- _( t$ H        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)' C: ~* Q7 D2 E: g  a  n
{0 d; l, ^+ Q- h' Q
    BYTE  btIDTR1[6];
; H( s, @9 \8 ]2 ^! b6 u    DWORD dwOldExceptionHook;! F8 f& O; g6 R. X, c/ M1 v, {
    const int nHookExceptionNo = 5;5 A/ |. l2 q2 Q+ u% }

) E% Q! N0 x: `; Z! t, \    BYTE  btIsIDEExist = 0;, d& U- u+ r. C# z2 T/ A0 _
    BYTE  btIsDiskExist = 0;
  H: g6 R7 F7 W' Z9 z* d9 O+ }    WORD  wOutDataBuf[256];; l0 t. z% n% U' G( ^
! y" X' ~# t8 d; P
    BYTE  btIsFirst = (BYTE)bIsFirst;
" {: o$ l% j& x: y3 P( I
, }& t" B1 W0 M* c1 N    const BYTE btBit00 = 0x01;% k8 n1 K6 n9 o  h
    // const BYTE btBit02 = 0x04;
- O* t- x7 g+ z) g' \9 b    const BYTE btBit06 = 0x40;
! T7 l0 f9 @3 [; x! O' _    const BYTE btBit07 = 0x80;
! }2 x+ X9 C& I( G    // const BYTE btERR  = btBit00;; Q  @0 \! T8 p6 _4 I
    const BYTE btBusy = btBit07;0 d2 e: `- k* u1 N
    const BYTE btAtaCmd   = 0xEC;' H/ @- _( Z' E" O6 m+ n
    const BYTE btAtapiCmd = 0xA1;
! `' h% z* q# q5 X
/ D' A0 b8 v0 a    __asm
$ k8 x3 @/ a8 F4 o: g, W    {: g6 o4 C# S7 o; m5 |  [
        // 必须先执行这条语句
" N* L/ L- k5 t        JMP EnterRing0
. }& w, C! @7 f) D8 d% B3 Y0 R1 I) i2 U9 E9 ~
        // 定义过程. c  x/ x5 C) l- f! T
        // 等待IDE设备直到其不为忙为止
5 t+ G# q/ n1 ~        WaitWhileBusy proc" o8 ]. F! v( x3 [- n
' F! _5 n, a! z! a. w) t, O
        MOV  EBX, 100000
, `0 H/ O% x" b7 q* H9 N        MOV  DX, dwBaseAddress+ j9 U, C! F" [, P4 u
        ADD  DX, 7
4 V# W0 s0 p. c3 m+ T$ L3 l  T9 j2 H% n3 `  K4 g: Z
        LoopWhileBusy:# f- O8 u1 Q3 I  ~

% g- P( M# V4 {- \) T$ |        DEC  EBX' O- z' \, ^% w) \, \1 X& x0 t
        CMP  EBX, 01 ]$ h& A- Q: O# B) i. {
        JZ   Timeout; t6 @  u/ h  `. A
        in   AL, DX( M, }0 k( M# @+ W7 F, z/ ?
        TEST AL, btBusy
/ b7 x, L0 ^4 ?3 p        JNZ  LoopWhileBusy
, Q( c# y4 ?' Q+ s& `        JMP  DriveReady
" X! M4 o& ]$ M# l) {: V8 z" Y; x$ X5 e6 i& U' J/ V4 G: }* u
        // 超时,直接退出
! c1 ?0 [4 @1 n; D* L; Z& S        Timeout:# ~6 x5 ]- _' N2 z8 z
        JMP  LeaveRing02 A8 j9 y8 q1 V! W  ]
        DriveReady:
% U  a) v3 M9 N; M+ D* r: g( B5 i        RET( e0 S+ ?* ]. E* a1 a) y6 T/ @
        ENDP   // End of WaitWhileBusy Procedure
8 d6 t, v0 A9 N' U/ u/ Z  r  k+ j# n- r
        // 设置主盘和从盘标志
  K+ e' Q1 R8 @3 {1 j        SelectDevice proc
8 [3 n4 M# \% V5 F8 l& d- T
& O3 y; A# k( H) H/ I. n        MOV  DX, dwBaseAddress
. J# K5 C$ z( _) C, s        ADD  DX, 6
6 ~7 q2 v& j) y( t9 g: W        MOV  AL, btMasterSlave! T- b7 k. W. `, ~& V4 w
0 o9 ^9 a/ l7 e' o; [
        out  DX, AL
& B. ^- u: c0 W5 L        RET
  H9 e0 E/ E! t
0 Z$ M$ Z3 \( E5 @        ENDP  // End of SelectDevice Procedure
  {4 a" W- Y2 B# _. A) B) r  ?$ W( Q7 `( h7 P6 a$ r( D% z
        // 向IDE设备发送存取指令
5 {0 [& x  ^4 q; E0 D1 O8 u1 ?        SendCmd proc% X. B- W, @/ o5 H, [, J8 l0 Z

% I) Q9 E5 @* {* n2 m3 c        MOV DX, dwBaseAddress3 F& y1 U- m0 N. J
        ADD DX, 7+ D3 d& o- u, X2 T: M
        MOV AL, BL // BL是主从盘标识,在过程外设置
6 t3 Q0 G9 R8 |% w9 q9 k' Z        out DX, AL
  Q: w4 G' k2 v  H( ?; H) z        RET: b. g) ], w$ U/ j0 P4 ]
        ENDP  // End of SendCmd Procedure* j) ]  J) ?6 k2 b2 L2 }
$ j* x# V2 i( y8 R) q$ y" W
        // Ring0代码
1 i) k6 S  ^+ j  m        Ring0Proc:' \) {( C# @0 P  Z8 h& x+ J7 }+ `
        PUSHAD
0 o0 ?/ U3 }8 r        // 查询IDE设备是否存在7 ]4 I3 b5 F3 N+ D, }
        MOV DX, dwBaseAddress2 b$ e7 i" ~+ z7 T/ h
        ADD DX, 74 `/ Z7 j6 t: ?/ F+ J
        in  AL,DX
# U4 W$ |( z+ i( S' ]% q( y
9 x9 T$ h5 F" Y- A* ], {        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
* P; ^, B& X3 [* i. ^' T        CMP AL,0xFF- K0 z  e9 [# ]
        JZ  LeaveRing08 r3 r+ _8 _3 p6 |, z# d2 N
        CMP AL, 0x7F8 k- J% T3 y; t2 T
        JZ  LeaveRing0
7 a0 _8 e; S+ E4 @& ~- V! ^3 w6 J. n; {
        // 设置IDE设备存在标志: e; X9 F0 X2 Y3 ~! F! \
        MOV btIsIDEExist, 1! u# G% C# b$ w" R7 t2 g2 v! p

1 a% {% O4 Z9 a        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
8 r0 \' g$ z7 y$ @: U        CALL WaitWhileBusy. c% n( ]/ c' H# q5 U4 ]- G
        CALL SelectDevice
+ \" r* ]( Q% s5 }2 ]* B" L) U1 r- o) c' ]+ m7 }) K. z7 @
        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏/ K' E- |: a. {+ R# c3 \. d4 \
        CMP  btIsFirst, 1
* Z- Z) B: o. m& Z. {        JZ   LeaveRing0
( P$ S2 \! Q9 F& h( ]8 x5 A. A% l
        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
, s! B) q$ w# V+ }8 y; m1 V- \2 r        CALL WaitWhileBusy
. K- O, y- h: k* x, r) d0 M3 i$ Q! s$ J' r" s
        // AL的值等于cBit06时,不存在驱动器,直接返回2 R2 ?) \  u+ T7 K- |+ g/ v: f
        TEST AL, btBit06" G. {, c9 a% N% ]# }
        JZ   LeaveRing0
, V& ]  E% k  P( A& I% Q& G2 @
) W; N# g" V$ p        // 设置驱动器存在标志  e9 m* F9 ^! T2 S5 w0 s4 H, N
        MOV  btIsDiskExist, 15 k' T( V7 n% |. N/ w. E. @. J) ]

6 E3 F  ?- G  l4 R0 U        // 发送存取端口命令. O9 l6 ~: l$ K/ I) B
        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,: L' D5 l5 x! ]; H5 |4 U
        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
& A8 S8 j: Y9 q6 q        CALL WaitWhileBusy& k! s) U8 G: Q) I6 |
        CALL SelectDevice    // 设置主从盘标识
% X. ?5 h2 h+ @4 U! z. m$ d: t        MOV  BL, btAtaCmd      // 发送读取命令7 ~; f5 a4 U5 O& [
        CALL SendCmd7 b1 w2 n  |) ?) p8 S( k- U
        CALL WaitWhileBusy
5 }1 \) X6 |6 t8 a
  T6 K$ e( b, V$ c8 k+ M        // 检查是否出错' r) s# [! @. d9 |
        MOV  DX, dwBaseAddress
: x' t# B1 P6 [$ l; `+ ]        ADD  DX, 7
' N1 z: O4 F6 y; M$ }7 N( c; s* T( Q4 n- G7 Z0 j1 K
        in   AL, DX' U6 f0 ?9 i0 n* u" p" }4 G# M! G. y
. C% I& n9 s* T" m1 t
        TEST AL, btBit00, i* ]* W* Z' a! j0 ?9 s7 N& }  U
        JZ   RetrieveInfo   // 没有错误时则读数据" J3 B( S5 ]4 Q* E9 ?

( Q" e7 ^% h& t# G0 y        // 如果出错,则进一步尝试使用ATAPI设备命令
  u; J. G' x! n2 l$ N# H- J2 {        CALL WaitWhileBusy
8 P$ q8 c) E* p$ `! q        CALL SelectDevice  J1 P, s/ A, j. j9 v( ^/ x+ |
        MOV  BL, btAtapiCmd
9 D! g3 l: _  m5 e        CALL SendCmd
$ }! u8 I2 O% q% t        CALL WaitWhileBusy
" C4 S. z/ I3 G* o6 U2 g/ i' @
( O% E' L: l" R+ T. s' |7 @8 @3 @        // 检查是否还出错8 c9 L1 m9 p' A& N
        MOV  DX, dwBaseAddress8 c' c0 r( ]( [7 X8 J. H
        ADD  DX, 7$ i& I. v: s! B$ s
        in   AL, DX
" U# e7 u6 d3 l9 K4 G2 Y0 o; ^        TEST AL, btBit005 I4 `0 i! r6 I! B$ |% G
        JZ   RetrieveInfo   // 没有错误时则读数据* q0 t+ G2 w: v+ z0 b' K# j
        JMP  LeaveRing0     // 如果还是出错,直接返回9 A  ~8 I5 |/ o: w
) D. c, O) @# ]" d1 q% v
        // 读取数据9 n4 o; ^# i+ h& [* R8 W  L
        RetrieveInfo:# f; ~+ J2 }; R7 ?; C: K1 r: d
5 V( \+ x0 h: }  ]* Z$ H0 S
        LEA  EDI, wOutDataBuf
6 K5 s/ r  y2 M8 f" K* j6 `        MOV  ECX, 256
0 Y" ]+ b" ?# t% g% V) g6 B6 d8 e# J        MOV  DX, dwBaseAddress
- g. {0 a9 L8 h" I$ o        CLD+ s3 T" b3 y7 c+ w0 c% k( z

( x. M) A+ k$ l, A) s        REP  INSW% }6 W. O& h% V

4 m3 [8 e5 M3 f* M! Z        // 退出Ring0代码; s- e+ F2 _6 O
        LeaveRing0:
  Z" o+ t4 u5 K! w
4 u. F( I7 O6 z1 Y        POPAD
/ K! V! b  e6 h; x8 w, p        IRETD
8 O' n- g! `/ w: W
2 b+ I1 T3 V2 g9 f7 z        // 激活Ring0代码/ A1 |' k' a) g. k
        EnterRing0:
1 {1 T) B$ g. s( O+ a; v, Q& i  V% i/ v9 S
        // 修改中断门
( G0 S% m0 D' a9 S        SIDT FWORD PTR btIDTR1$ R0 N+ f2 J8 z4 Y
        MOV EAX, DWORD PTR btIDTR1 + 02h+ t* o+ _& x2 z2 ]% i7 L
        ADD EAX, nHookExceptionNo * 08h + 04h+ N' p, g. l: j' G
        CLI
9 F9 L" R3 m# [9 [  `" L
, }9 N7 g3 j' M2 X% t( J7 }        // 保存原异常处理例程入口4 {9 a  G. c/ J% i! g1 D2 G
        MOV ECX, DWORD PTR [EAX]9 x3 |  o9 |1 g! w, O
        MOV CX, WORD PTR [EAX-04h]- x5 E* v# J+ k. z. b( ]
        MOV dwOldExceptionHook, ECX
9 g( x3 |% K/ B" |
9 y! }4 F0 R- d5 s, H        // 指定新入口9 m$ m& w% M- r1 Y7 e
        LEA EBX, Ring0Proc& d$ i, _" J3 }, {# x* l
        MOV WORD PTR [EAX-04h],BX; G3 `3 `1 ^+ o5 k; O) O. {! `
        SHR EBX, 10h& u9 A2 u/ ]7 ]" S
        MOV WORD PTR[EAX+02h], BX
+ R% ~/ |& ]' ~+ P8 n& I. |1 ^" t  N1 L3 R2 G% Z
        // 激活Ring0代码
; ^# c8 J' I; `7 U& D, e% `        INT nHookExceptionNo6 \2 l  |7 w: s

! ]* Q# q3 C4 D1 S2 V+ q7 M, O. \# B6 L        // 复原入口
; f* u% j: o9 O8 S: O5 C+ K% E        MOV ECX,dwOldExceptionHook
% w, d2 O8 W7 J& |4 n        MOV WORD PTR[EAX-04h], CX1 j* q  H/ P; B  j2 |
        SHR ECX,10h( B6 l- F' a! e; j* o1 b2 y
        MOV WORD PTR[EAX+02h], CX
, F3 _5 p) T& V/ \7 [        STI7 L+ M% E4 ]  N1 R5 i8 Y" Y- j
    }" D% j' l7 }7 J' K$ M1 ~+ A& n
    if(!bIsFirst)4 b% X. T' c( w& n; Z0 `( M
    {
& f8 }/ T1 z- S; ^+ X1 {+ U        bIsIDEExist  = (bool)btIsIDEExist;
- j* }% {. w3 j) g! N+ S        bIsDiskExist = (bool)btIsDiskExist;( m+ p/ [3 f3 U/ r( _( a# Y
        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));% F7 }  s  n+ L( ^
    }3 Y. y( t# e& e) e0 |# o7 T
}
7 ?! h: C" d/ }9 |' N//---------------------------------------------------------------------------
9 H0 _0 N4 A. ^2 f// 调用方法:
! j% w+ x! A' L, V2 c4 \void __fastcall TForm1::Button1Click(TObject *Sender): J0 E9 S. p, r3 j7 d* ]
{8 k0 H0 b5 y* a. d) G! ?" K
    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
* o2 t! p: d0 l: X/ \. W' i}
/ K: r$ a2 q! N9 w: k! y6 h
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-5-2 06:49 , Processed in 0.021915 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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