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

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

[复制链接]
发表于 2008-1-6 19:59:06 | 显示全部楼层 |阅读模式
代码框架,你所要做的仅是修改WQL语句,具体可看MSDN。以下代码为简介起见,一次返回所有的CPUID或硬盘厂商系列号
. J$ P% [: e$ D! S+ u) F

  1.   i5 `. }7 W! p" ^
  2. #include "StdAfx.h"
    2 G4 T4 Q1 d/ Z  H
  3. #include ".\puiddisk.h"& f- R* D5 }% y( L
  4. #define _WIN32_DCOM$ ~- `3 |; L* n8 B# n
  5. #include <iostream>2 \- B/ b* G; o. _1 a9 Z. j
  6. using namespace std;, U2 v1 n5 l1 C" o2 R3 s+ K
  7. #include <comdef.h>
    $ [& m. ~; P4 n* m& X. [
  8. #include <Wbemidl.h>
    " X0 i( J2 j5 `

  9. 5 b8 ^: I' A! ^/ }
  10. # pragma comment(lib, "wbemuuid.lib"): K# m% [9 m5 r$ f6 V! V9 E
  11. CpuIDDisk::CpuIDDisk(void)
    ) k$ w  u3 n8 C# N# V5 O! s
  12. {
    2 p% W- P- y+ ^) W! }; _4 U
  13.     GetInfomation();7 F1 ?& H! N  z4 b7 `
  14. }, U" m0 i- Q1 U# {& f

  15. / r7 P5 `) \" g5 J# P
  16. CpuIDDisk::~CpuIDDisk(void)
    # ~5 E9 i- y( |4 h1 d' d
  17. {2 u( t. F7 w* E$ l  n+ \
  18. }2 B- Y- o: r2 @4 q, q2 o
  19. int CpuIDDisk::GetInfomation(void)" [$ ~1 x9 i7 y; F, O3 R' u
  20. {! v: @9 }% S0 Z. a2 M+ g: g7 U* `
  21.     HRESULT hres;8 K) _. l" P6 ]/ J& u) T
  22.     //步骤1:不是必须的,COM只须也只能初始化一次4 A5 G( c+ d2 o0 v; V0 D" K' g
  23.      hres =  CoInitializeEx(0, COINIT_MULTITHREADED );
    & o, d7 \' F( \$ ~
  24.     if (FAILED(hres))
    7 ?$ d2 |, D- ]/ \! [+ k' q
  25.     {. h9 g7 t7 I' Z. ^
  26.         return 1; //初始化COM异常:注意,COM只须也只能初始化一次
    # N. S6 E5 b0 f% i
  27.     }% h# ?' h* p4 v! b9 e% f
  28.     //步骤2:不是必须的,COM只须也只能设置一次
    ! J, v( h" A1 L, S+ V
  29.     //Set general COM security levels6 N2 I% [! w# n
  30.     hres =  CoInitializeSecurity(0 F% {: s: H3 S% L/ }2 o8 G$ B
  31.         NULL,
    8 ^* i0 K+ k' k( ?* {
  32.         -1,                          // COM authentication. W, A3 {$ R7 L
  33.         NULL,                        // Authentication services
    ' j+ U/ S( ]/ M; V( M6 `
  34.         NULL,                        // Reserved4 o! l7 o% o) g0 E1 U7 X' ]
  35.         RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication
    9 C; K" a5 b% K3 D
  36.         RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  # _3 q5 K  H7 [# q8 H
  37.         NULL,                        // Authentication info' \- r( T& `+ \8 [  _) W
  38.         EOAC_NONE,                   // Additional capabilities . h! T- ^) ~) X8 Y% E& {; f
  39.         NULL                         // Reserved
    & L' J' j1 s+ b: E3 |
  40.         );
    6 [/ i% Q4 i; o- U# N8 l
  41.                       ( e5 {- w! I: G& j* b
  42.     if (FAILED(hres))
    ' p/ N% P" [4 _3 q( [* ^% d2 _
  43.     {
    % ]: ?, B) J9 e. Z; D1 s7 X
  44.         CoUninitialize();
    1 J7 {' d$ x0 G
  45.         return 1;                    // Program has failed.2 w7 M% V- y2 J6 j. ]2 b
  46.     }# P* ?" n% O! w$ ~
  47.     # v# `: j" k2 N  ]/ a+ A( P9 ~
  48.     //以上不是必须的,若已有“::COMInit();”,则要跳过6 ?% R% }" p) {; U* ]
  49.     //步骤3: Obtain the initial locator to WMI
    % v4 B+ t1 H9 q9 i
  50.     IWbemLocator *pLoc = NULL;2 c% \" U- C2 y0 \3 ~1 K# u3 X. L
  51.     hres = CoCreateInstance(# L. x7 g( @8 S' G: V, w, I
  52.         CLSID_WbemLocator,            
    ! [3 T1 X( h9 u4 g1 y4 q! w# x
  53.         0,
    " T% i* ?$ j* a% J+ B5 P
  54.         CLSCTX_INPROC_SERVER,
    & N: x- i+ H1 G* q
  55.         IID_IWbemLocator, (LPVOID *) &pLoc);: u- D6 R% d, W: J/ Z

  56. & S# ^  x; v. q
  57.     if (FAILED(hres))
    & n1 O' l0 L+ U; \: ]! x' e7 Y2 m/ K
  58.     {2 J! T4 L: \+ P7 a) \2 g6 N
  59.         CoUninitialize();% v9 E% Y7 Z7 C% `6 \; f) E; z) W
  60.         return 1;//Failed to create IWbemLocator object
    $ @- v1 {2 Y" u) M5 m
  61.     }3 \9 u: q* f2 K
  62. " v, l, c- n+ B  ~8 v! E
  63.     //步骤4:Connect to WMI through the IWbemLocator::ConnectServer method
      e% r9 i! d) l  @2 }. v
  64.     IWbemServices *pSvc = NULL;
    0 n: N8 x$ f" M% l
  65.     hres = pLoc->ConnectServer(
    ( A0 Z! ?. y9 x7 h
  66.          _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace" N# e5 y0 r: b$ e, n. b
  67.          NULL,                    // User name. NULL = current user9 Z1 U. [/ q% N, ?  N7 u
  68.          NULL,                    // User password. NULL = current6 \9 k% |5 ]: a0 w7 L6 d
  69.          0,                       // Locale. NULL indicates current
    " o6 k. Y7 q% A/ d
  70.          NULL,                    // Security flags.# U+ P3 l6 ?# W! Y! j
  71.          0,                       // Authority (e.g. Kerberos)
    3 w1 H# E! q' c2 Z+ j$ H3 _: E
  72.          0,                       // Context object
    6 }; V8 E  c/ {# t8 Q& [- s
  73.          &pSvc                    // pointer to IWbemServices proxy
    1 o6 E! ^3 V4 i1 Z# s1 K; q
  74.          );
    6 L, K% C: [0 W2 e# k
  75.     ( [# d$ `: }8 B# S
  76.     if (FAILED(hres))9 U2 {" |2 m7 p8 W0 f2 ?1 N) H
  77.     {+ V' `6 \1 P1 ^
  78.         pLoc->Release();     
    + Z# K) r  E6 s5 [: G& m
  79.         CoUninitialize();3 a( Q6 N2 A  Y! l! h: U# X
  80.         return 1;                // Program has failed.
    ; ]9 i; n+ K( ]( Y0 U0 S# V0 N% I
  81.     }
    ; `1 t% H1 o" u( R$ {6 G
  82.     // 步骤5: Set security levels on the proxy: g; a# O5 H% }- w& N" c6 Z
  83.     hres = CoSetProxyBlanket(
    : _/ f- [! k3 o- n! w: l
  84.        pSvc,                        // Indicates the proxy to set
    7 N- |9 ]$ H+ v; A  s' l( @
  85.        RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx! s# S; e! o+ n: ]% U
  86.        RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx
    % _$ B2 I" `6 o% N! {
  87.        NULL,                        // Server principal name
    ( l2 o2 _) C( S' E7 B* H+ c& C
  88.        RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx 6 m6 w) e4 V" F9 j9 X0 }$ V; w
  89.        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
    7 e8 y+ I. {3 L
  90.        NULL,                        // client identity5 E% g8 ~" o# y  j
  91.        EOAC_NONE                    // proxy capabilities % \8 z4 h; [4 e9 f3 P6 G* n
  92.     );7 V: E& F8 ?  r' ~- z

  93. 5 N  D4 @/ l9 j8 q  I& B. s" U
  94.     if (FAILED(hres)); M0 Q( d) w* Q' t
  95.     {
    $ r0 ?2 g0 A' R4 @4 l9 q& V
  96.         pSvc->Release();
    ' `1 z# \$ |% \& E( a' @  g$ o
  97.         pLoc->Release();     
    9 P) v1 j! P. G
  98.         CoUninitialize();
    " ]. q9 p" K" N+ d  g0 y9 r; @
  99.         return 1;
    1 s3 {; g; H% d8 E- a) G; O
  100.     }
    / G: C2 j) x$ W, S2 ]. l" A

  101. + t3 {& I  r) G9 \1 Y, k; c
  102.     // 步骤6:Use the IWbemServices pointer to make requests of WMI ----
    9 `! _- B0 E% j$ n/ @; t: F
  103.     IEnumWbemClassObject* pEnumerator = NULL;) [# r2 N" w) F6 c% W
  104.     //计算CPUID
    8 _$ \: G- K/ L, N- c1 ~
  105.     hres = pSvc->ExecQuery(# k8 S8 R0 `9 T0 F
  106.         bstr_t("WQL"), - E5 i0 ]/ {& M: J+ O- u* ~
  107.         bstr_t("SELECT * FROM Win32_Processor"),//Win32_OperatingSystem
    2 W9 H8 g( F6 r0 x! I+ x" Y
  108.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 3 g. ^- g4 c2 Y7 h% y- [) {
  109.         NULL,9 t: j' H) ]( ]! I1 T
  110.         &pEnumerator);9 r3 C, U  H# ^8 D0 s
  111.    
    . I( w; v' g6 r# I3 J) W
  112.     if (FAILED(hres)): ^% r- a& n6 W! M1 b7 R+ k
  113.     {* g/ u" p% e, T4 a% @' G& |* a
  114.         pSvc->Release();) v$ U8 ~8 G8 X& g8 D! a
  115.         pLoc->Release();
    , e# Q, q1 P. H5 W, G0 `$ K
  116.         CoUninitialize();
    % T- `. y& |7 F6 d
  117.         return 1;+ X* p/ |( Z% C8 Q8 N' @
  118.     }
    0 {: q- F/ b! q# v  P
  119.     // 步骤7:Get the data from the query
    5 [4 m4 Q8 S! f1 g, U6 T
  120.     IWbemClassObject *pclsObj;
    4 k8 V; {; i5 ^2 z) u9 r& d
  121.     ULONG uReturn = 0;
    6 S: ~) h" y' z  ?
  122.     while (pEnumerator)8 [: O: F' K" G& ?- l
  123.     {5 i1 I" `& X- I" h3 F
  124.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
    0 t1 t% U$ A( ]* c5 [
  125.             &pclsObj, &uReturn);" f' `; `4 N  z5 P9 i* @' r" `
  126. # s- K- C# f) h" C/ r
  127.         if(0 == uReturn). s% V! u$ f) E/ J4 O7 D4 v
  128.         {
    8 j4 {; ~* V9 e2 u( n$ }( u
  129.             break;- S6 X: A: n1 m  V4 ~, M
  130.         }! D1 N0 R" @  Z: Y/ k
  131.         VARIANT vtProp;
    0 R5 }+ q8 P2 k; `
  132.         VariantInit(&vtProp);
    : ~0 I) Q7 J0 V. r: C8 Q
  133.         hr = pclsObj->Get(L"ProcessorId", 0, &vtProp, 0, 0);
    $ ?" b& n% {/ g" x4 ^
  134.         strProcessID=_com_util::ConvertBSTRToString(vtProp.bstrVal);//strProcessID:类级变量
    * d/ N& |% L$ \
  135.     }+ J" h  [2 E* W& b2 y( q& K

  136. 8 }6 Q- ^5 q- c1 l" X3 w) I8 s
  137.     //计算硬盘系列号" U; m0 P+ v2 h5 @; \+ J" W
  138.     hres = pSvc->ExecQuery(
    " V" o4 |0 [: }) c
  139.         bstr_t("WQL"), 9 p) {$ B9 F5 w6 @. O
  140.         bstr_t("SELECT * FROM Win32_DiskDrive"),. b+ w3 {) i# g
  141.         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, # p3 h+ m+ i+ f. [1 u5 Q3 X  O
  142.         NULL,
    & W/ ^! e$ Y6 Y$ X
  143.         &pEnumerator);0 m3 S2 h  ?6 u; R1 B2 C

  144. % u; R( K  {" \( T
  145.     if (FAILED(hres)), h  T/ Q4 ^# H8 o% W' Z
  146.     {6 A2 ~/ |1 A, V# ^
  147.         pSvc->Release();" E5 g* D3 j: D
  148.         pLoc->Release();
    . U; h' q+ b' f, n- I
  149.         CoUninitialize();
    ' q' T; G& H9 G& o# ]
  150.         return 1;
    : B7 m: v* @/ ~5 v
  151.     }# |: Y) V6 v7 L2 ]  _- ?% j+ f/ t7 f
  152.     while (pEnumerator). t# R  z7 r* w- i) p* ]$ ]
  153.     {1 O' o8 H# r( E2 E( H9 b4 _5 |
  154.         HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
    " c' h- w9 \/ H9 p
  155.             &pclsObj, &uReturn);( i# O1 _, F5 D- g5 s* h4 \4 v* g

  156.   H3 _: e0 ^& G
  157.         if(0 == uReturn)/ D# a4 g2 t# I7 T* k: A" S
  158.         {
    2 R4 I8 c5 Y/ @* a1 ]( r2 [& g4 w, n
  159.             break;
    / a8 H* h8 d: v# x0 B
  160.         }
    , u* q- V. x( V  T5 V  h$ O3 s3 D
  161. 6 }4 p2 D/ s# T' z
  162.         VARIANT vtProp;, Z1 x6 N5 j) ~& @$ ^  k; B2 P
  163.         VariantInit(&vtProp);
    + q+ x6 z  E6 H
  164.         hr = pclsObj->Get(L"PNPDeviceID", 0, &vtProp, 0, 0);
    1 J1 q& z0 z0 q! T5 D7 B
  165.     strDisk=_com_util::ConvertBSTRToString(vtProp.bstrVal);
    2 |5 I+ t! L3 X. J" D
  166.     }9 R( P. Z5 P' P: ]# t4 Q( y
  167. 6 Q8 K" G4 U  n5 l7 s3 ^  i
  168.     pSvc->Release();
    5 ^4 E- p  \; s, T* ^# P$ S1 l* M
  169.     pLoc->Release();% L! j/ L5 l8 s3 T2 P+ V- I
  170.     pEnumerator->Release();7 Y+ y) B' x4 p& b' N. B& U7 g
  171.     pclsObj->Release();9 ]8 x' p6 I" E
  172.     CoUninitialize();
    5 L5 M2 m# `9 X3 `1 d* |% v! L" U

  173. 5 [4 b: C7 T7 n" W# g6 i/ W6 w
  174.     return 0;   
    ' }9 ?$ S) K& U* g7 j1 o
  175. }  V1 ?2 C4 s9 z) m1 b
复制代码
 楼主| 发表于 2010-10-11 19:21:05 | 显示全部楼层
本文代码经ccrun(老妖)在Win2k下试验成功.
+ Y; Q1 K3 ^0 w. w; z7 r1 k8 U# M5 |! v7 Z+ e7 O3 @
#include <WinIOCtl.h>9 n7 ~/ v0 q  y5 j) J4 E( q
#include <stdio.h>
+ a1 C3 g( L0 i) B& p
, I  ~+ z5 L- D4 {& v3 t& v3 M#pragma inline
; I: v4 ]& h+ h- Q1 c( Y7 h. O//---------------------------------------------------------------------------
! n4 ^6 l% E0 u0 g6 a7 |7 w3 ^// IDE NT/2000/XP专用变量
+ @& q, e! E' E+ L7 z$ x$ K#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS9 {+ j: I2 u; P7 s' P1 M
#define DFP_GET_VERSION         SMART_GET_VERSION
: w' S  _  s: x3 V#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND. N% x# _% _4 X0 c) y. d9 b  y
#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA$ x$ h: R6 ?9 d0 v1 K% j& H
0 b. _/ F* m7 i# V0 V  v- z( B0 _
const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令% m0 g8 i, T( ?% o0 S) u. S8 Z- }- E
const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令9 j9 f+ S/ J6 H! M7 V8 j  j9 c0 t

& L; C& d+ a. n' H; Nconst int MAX_IDE_DRIVES = 4;6 a9 t$ d8 U% i5 `6 t: M8 J6 A
5 u+ n5 m1 g$ j9 X4 [
// SCSI专用变量
7 O+ w- t# w6 h8 r2 D* M( q. D# e, s" Bconst DWORD FILE_DEVICE_SCSI             = 0x0000001B;5 V( o* I% z  W* k
const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);* o& x: E7 o: s
const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition9 [6 c6 x9 X5 k/ Z1 d
const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;( s$ M; f/ `9 s: }2 }- R# k
1 {8 L0 |5 A( J+ U# N
typedef struct _SRB_IO_CONTROL' j- j$ \. T( M3 Q2 `
{  G; M' f# I$ W1 d* g' Z2 S/ v! x" O
    ULONG HeaderLength;9 b& B. L# U1 D  B/ x% O  |" i6 i( U/ \
    UCHAR Signature[8];
- o0 I; b; `1 w    ULONG Timeout;
3 y6 D6 J& E5 J, S2 J5 ]7 Z: D+ r    ULONG ControlCode;* d% E3 G1 B' o" L
    ULONG ReturnCode;/ v6 W5 U( c4 `! x
    ULONG Length;- Z: W! r* e# @; i, N
}SRB_IO_CONTROL, *PSRB_IO_CONTROL;5 J6 ?, z* J5 D5 [' m
! j& G6 R: z( L9 t/ }
// 读取的主函数. u' {% p. V' z& F: `& _
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
; {! R+ z( W8 P5 P* p' O9 J  f: X# |+ \  B( j/ L# k
// 辅助函数9 L' o5 Z+ d- }
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);  k$ x5 E/ C' b- _
// NT/2000/XP函数
; I8 F; }' O& ?. p0 Zvoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
7 W6 p% t, j, y' {- J+ g! Z3 `bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,- `0 p) m8 Q" Z: W+ E1 @# H
        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
  f9 l0 g1 h, E& Z0 e" G        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);: b6 i' f! `/ ?' V& m. h1 H: d- v, \
// Windows 9X函数+ a/ ~1 |6 ~, O1 Z1 x
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);( e2 e; G% O5 \( z# j# A6 B; {- r
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
( I8 D$ S) |5 v# i( A+ M! |        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);9 h7 ~2 v8 W/ H: @
; X. f1 N# N1 C
// SCSI读取函数(for NT/2000/XP)+ r% }7 |4 g3 F' d8 s. _3 }: m5 q) i
String __fastcall ReadIDEDriveAsScsiDriveOnNT();4 J: n: z7 k3 c6 C* h7 \; h! m
//---------------------------------------------------------------------------% v. [+ S) ^1 [, ~
// ReadPhysicalDrive
7 ~2 V" ^) L$ W7 \- l, H9 L, zvoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
# v$ k: X, e) K4 |7 o1 y) B{- Y7 A, q) a8 U
    switch(Win32Platform)
2 o9 `. g1 ]3 r  t    {
5 Q: A2 k2 @3 q+ ^( z: Z! {' E        case VER_PLATFORM_WIN32_WINDOWS:
1 p) C8 T# F# ^9 R            ReadPhysicalDriveOnW9X(pSerList, pModeList);
, r0 O) r; r7 c$ \            break;6 p, x; Z# l1 O; ^# @. U
        case VER_PLATFORM_WIN32_NT:
' F2 D4 @- _3 x# T1 \            ReadPhysicalDriveOnNT(pSerList, pModeList);: b4 O1 \' G' }) o7 [
            break;
3 k* M0 j3 V! y( j. l7 L        default:! u; |. }) J; \- d7 H- S. R! W
            break;
, w; m) N% K6 r% p: E$ {    }- t) Y; [0 p7 b
}. h) T0 {3 v7 ~% b( h
//---------------------------------------------------------------------------
8 O! r& [8 A4 g' E. y0 M9 G- x// ConvertToString
0 @, T! _% H, _% p( d' Cchar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)( p6 e3 _/ N% A/ B  `' f/ O- a+ i2 F
{& }2 b; d  l, [$ u( ]& z
    static char szResBuf[1024];' z' d( i+ C- Z, D  ^% L
    int nIndex = 0;1 B" Q* o% p& W6 Q
    int nPosition = 0;* A/ H; \) X# E; c. [
8 P0 F9 S  V, d+ ^2 W
    // Each integer has two characters stored in it backwards
- s; m5 Z2 ?- [    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)$ y6 w. P8 ^9 A7 P- w1 v/ P, y
    {
% J5 r7 V' j7 a6 E& v. z        // Get high BYTE for 1st character6 u2 h5 j) u, n2 o
        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);' K) i7 \2 J# d  w" z0 U4 i+ p  O
        nPosition++;
$ _7 ^" ?8 O5 b$ H/ X: O/ |" N+ G1 U! ]/ g
        // Get low BYTE for 2nd character, r5 h$ x' Q0 [3 k& W  D/ R3 C/ N! w
        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);9 N6 h* K; y, s2 V
        nPosition++;9 v* ^, K; x& `* K& I1 |, ~
    }) P0 s: }) U4 G8 f+ E, r! G0 K
7 ^3 ]. N, @- F3 q
    // End the string
7 V7 r0 T8 |' _- c* Y* N7 v    szResBuf[nPosition] = '\0';2 a  ]  ?; C6 d# s1 l7 |# c
( x9 F9 c$ B- d* y! ^2 c
    // Cut off the trailing blanks
8 ]1 Y& u3 F( S    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--). @) ?) r& Q9 C$ A
        szResBuf[nIndex] = '\0';; ~( S  F: \9 q1 ]5 i2 V* M
( V8 ]/ J5 h* g# [7 N( z7 [
    return szResBuf;7 {( W! W# V5 M$ Y; {
}
' T' [, H* x+ I, O$ l/ s//---------------------------------------------------------------------------; d/ v, _1 u2 T' r! {9 _0 S
// Winndows NT4/2000/XP 代码
* [# h; }3 ]* O4 b0 D+ {//---------------------------------------------------------------------------
& f3 k  I  K& d% ^  O1 A// ReadPhysicalDriveOnNT/ s7 i: h3 M: r5 L
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)6 N4 L0 H6 o6 F9 H+ C
{$ S; e" |% g* C- j+ t) e
    // 输出参数/ l) Q& l9 E; z: J& g( r* f$ K
    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];8 o) ?0 s* @: a7 P
/ C: w3 P5 `6 d) D6 A# H
    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
2 |( i2 h9 t3 r' o: L    {
) I3 S) G$ P  j% r  E        HANDLE hPhysicalDriveIOCTL;
9 J, @, y: T. M        char szDriveName[32];  R+ H  d( q6 {$ t: x

) F0 q" |2 ^$ {) v9 K        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);2 Z$ f& P4 }% S! W. u, U
        hPhysicalDriveIOCTL = CreateFile(szDriveName,: V! k# p" ]0 l+ n
                        GENERIC_READ | GENERIC_WRITE,
, u9 D8 y% f- z9 e5 e& ?5 B- P7 N                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
% J7 t. l2 x4 L' ?: ~6 z% V- i                        OPEN_EXISTING, 0, NULL);( [, G5 |" B  t: R

" k$ L6 R% {5 A. Y; v2 ~        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
8 l' V% r- [) y& m        {
' F& y# U( ]' g            DWORD dwBytesReturned = 0;- O5 X$ p4 ^; ~: m4 H2 [# D% y
            GETVERSIONOUTPARAMS gvopVersionParams;  J8 ?8 M8 o2 B( W+ g& H& T

  P) V1 ^2 K# x* V4 D            // Get the version, etc of PhysicalDrive IOCTL  i  X) D0 L% N3 E, z
            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));, X8 z7 `2 x# v; W. R

, ]0 ]* ^4 R. y& m% h            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
$ X$ m" [7 M" o                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),4 e! z* u6 A  B# ~8 @  {" s
                    &dwBytesReturned, NULL))3 o: G3 a. }- R6 P! S3 F
            {
* S5 ]4 W6 }( U& a3 a                continue;. N  r5 g' r4 y9 v% r2 t/ A$ C, Z
            }
9 u- u4 W7 i1 S
4 f0 l- e3 V. i+ @# Z2 J            if(gvopVersionParams.bIDEDeviceMap > 0)
( `; e$ ]) h( F) \) @& P2 d9 v            {
  i, Q3 B& e7 ]( J. w& C5 v                // IDE or ATAPI IDENTIFY cmd* e) g- E7 I( L' u" z
                BYTE btIDCmd = 0;
9 J3 {) `% o/ }3 B+ ]                SENDCMDINPARAMS InParams;
& l# E9 K* p  y, N, }6 |. D                // Now, get the ID sector for all IDE devices in the system.  @+ e$ z$ q# [4 u- C
                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,& i- P, w$ h6 }% L
                // otherwise use the IDE_ATA_IDENTIFY command# h) ?3 n  K; w+ v
                // 具体所得结果请参考头文件中的说明
+ k+ F, M# s- f3 b) @3 h                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?& d0 p; u5 \3 @" H; j% T3 M3 H
                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;6 Q- |9 u) `. M
                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
, V% Y; |/ o, m* u  c2 @                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));" q& e  u6 L. G9 n" T

" [, d1 O6 D8 S4 k; {                if(DoIdentify(hPhysicalDriveIOCTL,
9 r) S/ G' F) w4 b4 }                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
! Z/ e' w. r. w- K( }& S+ N' _                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))2 X! w* _3 k7 X" V5 H, X+ j5 z
                {- ^. T: H+ G8 w; R( A# C9 y5 D6 i
                    DWORD dwDiskData[256];6 d$ t/ c& ^% R3 W
                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
0 m3 [- l7 H- i( {6 J                    char szSerialNumber[21];
3 P1 u: v' ?' w0 K7 k1 E/ b! e1 n% l                    char szModelNumber[41];) V& v! @( Y' D: D& V
/ D5 z" h" z+ L# |
                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;8 Z( K) e+ z, j5 |
                    for(int i=0; i < 256; i++)# n! K1 D: h: t# e1 _/ t2 ^
                        dwDiskData[i] = pIDSector[i];
4 a% V' ^" N4 y2 V$ t, f" p                    // 取系列号
& w$ T: m# W; E% t                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));" k$ e! _" y' k9 y3 p& L! d
                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));, @! V* ?/ V1 f0 ~
: B. L/ O( E  q8 q& y9 R
                    // 取模型号
9 O( Y( X! F2 c6 R% U  Z( ?                    ZeroMemory(szModelNumber, sizeof(szModelNumber));
$ I0 s/ W" Z( K0 F6 ?2 o                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));- f, _. m) o  I7 `, R- L1 D9 D

$ ~" x5 i! r# G( _3 Q6 E  R# F+ g                    pSerList->Add(szSerialNumber);
( v% T( }! |% a. I                    pModeList->Add(szModelNumber);
1 C9 X1 T- Z2 n- h1 P8 W" F# w                }
! z6 d# N. H0 B- m* A            }
% u9 t! B. B' t* N2 B9 b4 E) X            CloseHandle (hPhysicalDriveIOCTL);* G# J& n, B& b6 c
        }! V6 Z# |/ D  N
    }
" Q/ J  Y$ f, f8 L& P) V}
+ @# X5 Z1 r. }) w6 ]//---------------------------------------------------------------------------! U7 A! j# \# x% {
// DoIdentify3 W( o# ^$ O- [. `  q6 ]! P
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
1 O( T* j$ ^1 h& `0 `0 G2 h5 Q              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,2 N3 M+ h2 g# I8 j) Q1 K
              PDWORD pdwBytesReturned): y/ }7 ?, ]+ B) y6 p# {
{
" u: M9 m! e( T: O3 E    // Set up data structures for IDENTIFY command.& A" |# }& E* u# F, w. U5 b: [
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
6 p! k) u" U0 R' K9 d1 x    pSCIP->irDriveRegs.bFeaturesReg = 0;
2 l: z! m% Q5 c2 m5 p3 R1 m# ^    pSCIP->irDriveRegs.bSectorCountReg  = 1;, v4 m! o$ i* N2 g3 E
    pSCIP->irDriveRegs.bSectorNumberReg = 1;* o  C, G4 D' I9 I$ ?1 n0 _7 v" I
    pSCIP->irDriveRegs.bCylLowReg  = 0;1 _( R% F6 v& ?
    pSCIP->irDriveRegs.bCylHighReg = 0;
+ k8 a- m9 D, L8 w0 {3 O
# z( Y0 M& g5 V, ?9 K' w! z2 S    // Compute the drive number.(主盘和从盘所对应的值是不一样的)5 B6 w! w/ X' R7 P0 K
    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;1 ]6 K: n, x& B8 @) W

8 O! b& f+ s6 H8 l    // The command can either be IDE identify or ATAPI identify.
# a2 U. O5 P1 N: F$ E$ U: y9 ^    pSCIP->irDriveRegs.bCommandReg = btIDCmd;; W% |+ i- A3 z
    pSCIP->bDriveNumber = btDriveNum;0 G1 Q# U7 l- P+ e
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
6 b6 e9 J. A* ^* U. o1 e' z& @" A# r" u
    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,- |' L" {6 w  L* m  m
           (LPVOID)pSCIP,
4 b4 W6 Q! D6 |  C           sizeof(SENDCMDINPARAMS) - 1,
# O0 ^5 ]" h1 s% b% o9 r           (LPVOID)pSCOP,
, K* Z2 {; W/ p! a+ P           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,. O9 Z; E6 Q& [$ Z" ~6 N. E, V9 j
           pdwBytesReturned, NULL);
/ P; ?8 a" A2 l" M- p* R5 X( \# H& i}$ q' a4 a% y; N5 D6 J4 w
//---------------------------------------------------------------------------
$ ^* n7 [, R1 B3 Y// Windows 95/98/ME 代码
: c1 h# |; v8 U, O" S//---------------------------------------------------------------------------
8 S; F4 r4 S  c( E( O) I// ReadPhysicalDriveOnW9X
# Q/ X. [7 x6 O9 O7 z7 Y* }void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)
+ ^* T, `2 O% d" W& A  @{
. c6 q- s+ g& v5 ?    WORD wOutData[256];
2 j* u2 w' Z' Z3 ]: s    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);$ k& A5 I+ [0 U5 r9 h. R) {: P0 _

1 S4 y  U6 n8 q4 `4 ]; P3 B    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
2 Q" v5 e" `3 g$ `' `. g, Z0 j    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以$ O, j  M* s! b  o7 M% {# Z( Q
    // 避免蓝屏的出现。(期待高人能指出原因)* f9 X' M5 w* x1 H) s
    for(int nDrive = 0; nDrive < 8; nDrive++)
$ N' j! Y/ a+ h$ @    {
5 _# Q- m9 s' S' p# p4 s2 [        WORD dwBaseAddress;
; E) P8 S- S0 Z# n$ e        BYTE btMasterSlave;         // Master Or Slave
) X2 l9 W# c+ F        bool bIsIDEExist;
! B1 t% S& _) K3 \# P* }; ~        bool IsDiskExist;
+ l9 z# S. V5 Z
7 d, T% @9 f$ b, _- o. n: |/ x        switch(nDrive / 2)
' R0 P. n/ v$ |! B* z' N( N0 ~+ _        {
/ F% r# {: F4 A            case 0: dwBaseAddress = 0x01F0; break;
$ ^0 @# |; e! f            case 1: dwBaseAddress = 0x0170; break;
9 _7 v/ {6 l, C' `9 u            case 2: dwBaseAddress = 0x01E8; break;
1 T8 r/ G* R6 y4 O: x            case 3: dwBaseAddress = 0x0168; break;! y% B/ Q/ ]: S
        }
' T1 w/ k- d# [% i3 @# _) z; u. z3 |) x
        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
/ T# v9 G+ a7 ?+ ]$ m) n& s1 ~) m1 I5 p) v, X& R: d
        // 进入Ring0
7 b+ q  h( w$ T! h6 }3 ?        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,; y5 w% ]# i4 n- k
                bIsIDEExist, IsDiskExist, wOutData);. C9 Z* Z4 P! l! t! `9 A$ e3 R
    }
. h  b, a* A8 f4 o& `4 Y5 C3 B
# G1 o3 a- ^, j) L7 l. ^    // 开始读取
! Q) S! E2 `" w& [) T9 x5 e    for(int nDrive = 0; nDrive < 8; nDrive++)( n! D: ~% J; D# ?* i- |
    {
/ l" M! `5 K8 {3 V' O        WORD dwBaseAddress;# P: A* Z# j- ^/ q
        BYTE btMasterSlave;         // Master Or Slave
1 |! ]9 C/ T9 c; U        bool bIsIDEExist;
" l" |% l! \; s. G& k( n: n        bool bIsDiskExist;6 |" o9 [" w1 f4 K
        switch(nDrive / 2)$ U$ s( Q1 p9 t6 G; m
        {/ i" Z- D1 [# W7 y& w' H0 |; ^; d
            case 0: dwBaseAddress = 0x01F0; break;
1 K8 q) w# _5 q) ]8 o) r+ f            case 1: dwBaseAddress = 0x0170; break;
: g8 e( ^( v) R% w) c" y, m9 v            case 2: dwBaseAddress = 0x01E8; break;
/ `# v# E! c) ?            case 3: dwBaseAddress = 0x0168; break;5 P* s/ b1 L' }* K- }; j4 K
        }
$ m$ l+ V: ], ~3 f3 k( j. ~# V; {/ e
        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);' s; D* X( B8 {9 u, V! z$ c/ F" G/ [" B

0 ]1 f! I3 {5 P  {5 i4 G" ^; d        // 进入Ring0
- [, {4 x  I3 l; n5 b        bIsIDEExist  = false;
: M7 a3 O4 q; S        bIsDiskExist = false;5 V) c: ?7 u; |! e& t& _/ `# {; ?
        ZeroMemory(wOutData, sizeof(wOutData));5 W7 a6 V+ ^: P! y' _* H
& g) _( X; @  x  N0 }
        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
2 f5 d0 Z. f# G% ~) u/ ~9 [& _, D                bIsIDEExist, bIsDiskExist, wOutData);) Y! g  {) j# j5 t: i

. i3 l! h. u5 `3 G; [+ [        if(bIsIDEExist && bIsDiskExist)
5 x! o( k: G0 i. g0 g+ `  s; `        {
6 {  [; E  P5 A% q0 Y- R            DWORD dwDiskData[256];6 ]& u  a9 Q; n1 e" y6 G8 d
            char  szSerialNumber[21];
4 R) n- Y/ j; h1 K5 W2 h5 N            char  szModelNumber[41];% \0 r3 M3 ]$ f& k( b2 e6 s& k) Z. f

2 `) P6 {( ]" V0 s' @; P; p- h            for(int k=0; k < 256; k++)
' C, i, _$ \  m3 \                dwDiskData[k] = wOutData[k];
# h7 p) T  C2 @' |' q9 D0 I- q3 w6 m  C0 l& T! ?4 s0 h  c1 V
            // 取系列号
# e3 p/ z% ]6 @5 M+ L            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
0 t  r( ^. C/ u" _. i            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));; S" R* I2 r* F+ Z3 i( ]
& ~2 a) N2 h3 Q! j. ?, }
            // 取模型号# k) r- c- F! P! {7 y4 H- l
            ZeroMemory(szModelNumber, sizeof(szModelNumber));/ B: X, _! e/ ]8 c& u
            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
' D4 o2 s! @2 r) i4 N, K. N+ v! f" j8 V+ }3 L9 {+ w$ m/ i8 }
            pSerList->Add(szSerialNumber);+ l) ~: r+ A" M) y* C5 L
            pModeList->Add(szModelNumber);
/ o7 V  f. F" s5 ^5 S4 i# H        }
" n  l$ w$ C3 I% t0 j( U    }
7 r9 T& c2 g7 q) F$ c2 u) u- Z8 q8 X; Y    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);" i  E4 F. x0 d7 C# T& \( S$ M- P
}  E: R4 [2 Z8 B1 x' l6 q) H
//---------------------------------------------------------------------------
6 q8 R, D- A/ w  V2 r: \// 为防止不负责任的转载者,在此注明原出处信息,请见谅。* T" i: U7 J# T, E
// 资料收集整理:ccrun(老妖),欢迎光临C++Builder研究: http://www.ccrun.com
( {5 S- w, D& U8 W//---------------------------------------------------------------------------4 \, F7 |% v' O$ k# Z
// ReadPhysicalDriveOnW9X_Ring0()
" I; f3 v+ N; y+ V3 L4 G4 i  S" \//! @0 E; U1 f  T9 }' c" y* z
// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h: }+ `& i* l7 o! j
// btMasterSlave = Master(0xA0) Or Slave(0xB0)0 M) g# P1 p/ ]' _
//---------------------------------------------------------------------------
: G( C! q5 v2 y/ g% P6 bvoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
! d% t" ^) u5 U' B1 |        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
+ \! P& Q/ M8 e4 z{
! a5 l0 [9 w  n4 R3 H    BYTE  btIDTR1[6];' P9 |: F5 e3 F- [: P4 B
    DWORD dwOldExceptionHook;
  q: P; \2 M5 ]; p    const int nHookExceptionNo = 5;( @8 Q: ~* D0 y/ [

. K0 m2 q8 }+ G5 ^0 c9 L    BYTE  btIsIDEExist = 0;
, f  Q, N0 I; ^# `- R& A' w    BYTE  btIsDiskExist = 0;
) k) I& O) o6 ?- x- r  \% g    WORD  wOutDataBuf[256];
3 j) f. Y2 V, w# H0 ~: H1 r
) O; t- ~& H: z    BYTE  btIsFirst = (BYTE)bIsFirst;$ v' D: H( z% [( A' I
; E# `2 ^; @7 N* e$ t. q
    const BYTE btBit00 = 0x01;
2 x# B( R3 q3 u$ \8 x* [! D9 L* w+ g    // const BYTE btBit02 = 0x04;
4 M1 K! S; c! N1 Y4 L, z3 ], ]/ k2 n    const BYTE btBit06 = 0x40;
9 n  R! Z8 r/ s: |. F! q$ N    const BYTE btBit07 = 0x80;1 Z: w& @' l$ {' J
    // const BYTE btERR  = btBit00;3 \* X5 V1 d) l7 g. x1 z
    const BYTE btBusy = btBit07;
9 X1 I/ C& N& [    const BYTE btAtaCmd   = 0xEC;3 v% ]. F$ k2 S5 g) z
    const BYTE btAtapiCmd = 0xA1;
/ F0 k: m" I) J1 R; R5 y
, n* y) A. m4 E, r6 K3 v2 P9 d    __asm
6 k* ~- Q4 f, @2 e    {
; t9 R4 p8 C6 i( B3 t9 C: S6 F        // 必须先执行这条语句! l9 {+ j6 [: o7 |" b% P
        JMP EnterRing0
- O% q& E4 `6 x9 ^5 ]7 z3 O. H; C; [4 h5 {! a
        // 定义过程7 D; w" }% W2 ~& E: H4 ~
        // 等待IDE设备直到其不为忙为止
# p3 f( L( k; A        WaitWhileBusy proc
( v/ n  d+ O! V& }- J% B$ |3 z  W) U+ \
        MOV  EBX, 100000) y. A7 W6 ]: u8 l& y, x( |/ {
        MOV  DX, dwBaseAddress7 p8 m3 t" T# z8 ~
        ADD  DX, 7
  \% }: e/ T8 `0 d  ]2 S
  N' l6 E* H5 G+ b6 n: z4 P        LoopWhileBusy:! z) g* {. y2 _/ w0 e- K& l+ H7 t. g
4 C. ?- M8 B8 L8 d( d
        DEC  EBX
8 k1 e; ~" L# O2 m; S        CMP  EBX, 0' i+ r) h4 v8 D0 `, a* o. U
        JZ   Timeout
& v4 o0 b6 H/ b* y) {: @5 R        in   AL, DX
9 u" k4 q% F3 z9 c, {+ Z        TEST AL, btBusy0 d$ k% F3 B1 w
        JNZ  LoopWhileBusy
( v; k- E3 O& W        JMP  DriveReady+ A6 o- k: }3 T, S
9 u1 E) }+ r3 s# e# y
        // 超时,直接退出8 G7 Y% G- x( ]& a0 X1 u- V
        Timeout:. C/ S% m6 _1 s/ N: O  l5 F+ Q. I0 y- d
        JMP  LeaveRing09 }7 J9 Y" L! }0 h: U4 D3 [
        DriveReady:$ b+ J# {/ ?1 u* Z6 {
        RET
* w" C1 C' M5 J" o7 T$ b' C        ENDP   // End of WaitWhileBusy Procedure
1 z: S% U0 @7 w6 ~9 \
7 f/ [6 s" \5 _( i' T3 g9 I        // 设置主盘和从盘标志
$ f" a! `7 q& y* o: [* D$ ?- `! E        SelectDevice proc
, c' {* G% W9 L+ G* w( |
0 g3 o  F; i$ C  }        MOV  DX, dwBaseAddress
6 o5 l1 h9 D4 |( |" g/ l& [        ADD  DX, 6* t9 I6 P6 d) F4 G' j& [$ P! r
        MOV  AL, btMasterSlave
. ~( ]0 T! E$ S" k1 }' t0 ~4 z, R% e& i+ n9 O
        out  DX, AL
- l* s& `9 S( A& f3 R9 V; N        RET
4 p/ T7 i3 u% A# [
) D0 ~0 q5 |6 B* _/ Q        ENDP  // End of SelectDevice Procedure
- v& H/ i/ g# n) B% C7 M; J# x8 \% L6 G+ \/ K
        // 向IDE设备发送存取指令# c* u, A0 e# U6 c- C
        SendCmd proc
. t* b$ g. ]/ ^! W9 O* \8 a7 U; G8 u5 j& o7 E! V
        MOV DX, dwBaseAddress7 Z+ p+ t8 y6 p7 a* K/ E9 a5 x9 A% m
        ADD DX, 70 d, W' E, U+ K$ c7 u" \
        MOV AL, BL // BL是主从盘标识,在过程外设置
7 }* ]9 y1 o# T$ k        out DX, AL' t0 A* ]3 M1 ^; Q6 g% Q
        RET
6 s8 T$ w5 k9 b4 D% y3 |        ENDP  // End of SendCmd Procedure
7 c  M8 t+ y+ f5 Z& h5 d" E5 _
! D* Y* v' Q  t3 g' B; w+ J        // Ring0代码
- r- T2 [8 }2 N" r        Ring0Proc:
. o* J) T$ i0 p  P* `+ |+ z        PUSHAD
% W% _' `( `% y        // 查询IDE设备是否存在
; B  g% e: M" G        MOV DX, dwBaseAddress/ f7 m9 b8 a" |& ]) z
        ADD DX, 7/ @  A' A6 f4 d) D
        in  AL,DX9 F# D1 @% x* N* _

5 T! L" Z- D$ a# _, h        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
) r: ?3 Z) a. S. G' j; o- k; W        CMP AL,0xFF' Q9 S; o- G  I1 `. J
        JZ  LeaveRing0
* ?  |6 k) ~& U+ k# G: K        CMP AL, 0x7F
/ ?3 g" o* Z' x+ j* R  v        JZ  LeaveRing0
0 t% `/ x% Q! ^' a. `
, ~/ d2 F- u: |! Q# N        // 设置IDE设备存在标志8 S, x& E" s4 G& M, _
        MOV btIsIDEExist, 15 w" m. ^* @) i# _6 H6 g1 X

# q: H0 o( L3 b* K/ Q& b        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)" ?. F0 e9 m0 r, p, A
        CALL WaitWhileBusy: C5 p# k  T; P6 P1 _* v
        CALL SelectDevice
4 y0 ?6 n4 ]: E# F& g& W- f1 r; g# b: ?0 D
        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
# v) R  L2 Y' r4 x. k& Y/ }8 @, j        CMP  btIsFirst, 1% i9 s9 H7 F+ y, \7 n) K" e, ?
        JZ   LeaveRing09 Z. y' P* P0 Z/ b6 z
/ M! a- v% Y, Q8 Z+ j
        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???& w  t6 s. Q3 g! j
        CALL WaitWhileBusy
/ G. k! F% ]3 Y  ^* o3 r+ x
( t( h; K1 {4 ^( `( s1 Y        // AL的值等于cBit06时,不存在驱动器,直接返回
- q1 s/ @; L0 O. F( @2 Y9 a        TEST AL, btBit06" P) C* v3 F" }& P0 O! e
        JZ   LeaveRing02 l3 l2 S- t; F/ @: R% o7 O
; F3 F+ b4 |# }# B3 A
        // 设置驱动器存在标志. S: w9 D8 }, W0 ^& ^
        MOV  btIsDiskExist, 1
2 x2 k$ a5 B4 K+ A% t0 \4 e( ]8 {0 o" I  b
        // 发送存取端口命令
) V8 A* k) l/ S        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,+ ]& A- \! D* \1 |; `
        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令/ X% d' M) B  }0 i" Y# b- j
        CALL WaitWhileBusy
$ ]8 w+ W! }- r9 }) u( p$ j( F        CALL SelectDevice    // 设置主从盘标识8 i6 m) |. _4 U4 ?( W
        MOV  BL, btAtaCmd      // 发送读取命令
1 W2 v! |" b# A3 R& p        CALL SendCmd/ @4 s: f3 I" c3 Z& O. u
        CALL WaitWhileBusy& {( k: \: {+ ]$ u3 q; |" u& z# L
, @# N! }9 ~) S" z# I
        // 检查是否出错
- z* _: ^' J0 N, W+ N% c* T        MOV  DX, dwBaseAddress
3 n+ a& t* Q- V7 \1 B, d        ADD  DX, 76 T- m+ E0 J& Z2 z
7 o- q! c) p  u: B
        in   AL, DX5 O% T4 w, r9 I1 U2 w! H, _

/ j( p& _  [9 n6 K4 ^6 p        TEST AL, btBit00
$ |2 C) U, p; z        JZ   RetrieveInfo   // 没有错误时则读数据
  d8 n$ c9 @( x: F8 I
- }( L5 A8 f) j) w  o9 D& \        // 如果出错,则进一步尝试使用ATAPI设备命令
/ N+ x2 y7 a+ Y+ @' |6 |        CALL WaitWhileBusy& [* G7 j( M! C7 B- o3 q
        CALL SelectDevice! Q5 H! e+ }% n
        MOV  BL, btAtapiCmd4 K* J: ~  w- i! m# J/ N
        CALL SendCmd
* @/ b: J) P" G$ T* U        CALL WaitWhileBusy
' q  R9 z# f) L# ~5 |8 z" P) n; @2 Q
        // 检查是否还出错$ R5 o& _% I1 c2 q0 K  U) o
        MOV  DX, dwBaseAddress
) S" T. r4 n! o# r0 F' N        ADD  DX, 75 P" F  b' V: Z
        in   AL, DX
; R7 ^3 G4 V( G1 w5 G) h        TEST AL, btBit00" f3 d( O0 A" s% O; ^
        JZ   RetrieveInfo   // 没有错误时则读数据' P! k/ X  D% o* P
        JMP  LeaveRing0     // 如果还是出错,直接返回" A. U. |2 ~& R) o

$ B6 f/ ^! w$ E6 f/ h2 y        // 读取数据
& R! K2 b1 D9 Q7 q, ]        RetrieveInfo:- X$ A' i& I7 c3 s- C- b1 h/ A

6 g% h- C$ g6 r" T! @8 _6 t' k# x        LEA  EDI, wOutDataBuf
$ I2 J, m! x! r2 O        MOV  ECX, 2561 T$ s7 ?3 {9 a$ k
        MOV  DX, dwBaseAddress9 [& Y& f/ [& a+ _% L( a4 o
        CLD& h/ ~; k6 i7 B) B+ u# w

6 A  L1 T$ ~0 @7 e/ e$ n" c2 n0 ?! q        REP  INSW5 a  O/ u' M& o/ N* b% h

5 g- T0 {. T, X1 _% @2 Y        // 退出Ring0代码
# B4 S$ E9 y: q, j        LeaveRing0:% [; M! J0 h" v) Y5 f( ~

- K2 `+ v" ]8 v        POPAD- I# Y" e5 D  n; Q" S  {5 o* C
        IRETD
& }; H5 D  |8 J# d" {; V- d. N
- R& M! \  R+ i2 ?0 W        // 激活Ring0代码" x% l4 W6 \# J2 V
        EnterRing0:
9 S4 ^7 R3 x1 p, U3 {* |6 i- D4 `
" U, |8 M  i7 w/ D# c        // 修改中断门6 v$ ^7 {9 W$ n/ ~
        SIDT FWORD PTR btIDTR1
& Q3 t# [$ t# ~4 Z9 U  z        MOV EAX, DWORD PTR btIDTR1 + 02h# ^' X0 e$ Z: l
        ADD EAX, nHookExceptionNo * 08h + 04h+ r( S; x4 Z( I7 Y; \
        CLI6 M5 b$ |1 V. a0 O3 S  f& K
. P: c) f; K+ U: S+ b
        // 保存原异常处理例程入口8 i' @- N/ E- U/ p6 T! b; e+ J) G
        MOV ECX, DWORD PTR [EAX]9 Q: t, h0 B3 [
        MOV CX, WORD PTR [EAX-04h]/ S' S7 g, K: K  \' e( C+ J+ \
        MOV dwOldExceptionHook, ECX, I# i( e1 o2 h: s' Q

6 X3 R. _$ e; N/ Q9 y* b, z; v        // 指定新入口& Q4 |1 {. ^' \1 _
        LEA EBX, Ring0Proc
  y# A" w8 q5 I2 L+ f4 u) ?" U        MOV WORD PTR [EAX-04h],BX
$ I) {- t2 h% ]2 j& Z7 U; y        SHR EBX, 10h. f# H7 N! d( a' D# @8 S: `  Z
        MOV WORD PTR[EAX+02h], BX
) X. k0 m" m" B4 x- t7 _+ G- A0 s  G* n# m9 B1 y+ `0 s
        // 激活Ring0代码
& {' K- k1 B! s. b- ]( q4 n& q* g        INT nHookExceptionNo( Z2 x% [) C& `2 [
) A% B) R4 B1 Z
        // 复原入口1 Q2 }8 R$ N- F2 _) @
        MOV ECX,dwOldExceptionHook
% Q+ ]/ z( l: R3 `) j* n        MOV WORD PTR[EAX-04h], CX2 p) n7 X4 H* s7 e$ A
        SHR ECX,10h
' O7 N2 B8 ?! M) W5 c        MOV WORD PTR[EAX+02h], CX* s0 {% ^* P. e, _; t, q6 x# ?# C
        STI9 @, Y. k' T, N, a
    }* ~0 _( F9 m) ^4 @2 ^# ~
    if(!bIsFirst)
  ]* P! j5 F" O! `9 D    {1 ~$ `: V0 E& D; g
        bIsIDEExist  = (bool)btIsIDEExist;' ?+ K4 W: J9 K& I% {7 E
        bIsDiskExist = (bool)btIsDiskExist;& G5 ]2 u1 g# R: G, K9 o( N) A+ E
        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
. `, A% q4 b. y& c0 A    }- G0 E0 K5 a* A3 Q9 k
}
( j2 L8 m6 @5 r5 t3 U/ o& k5 b4 f//---------------------------------------------------------------------------
% [, r) f0 o- U' W// 调用方法:
9 e- a6 A7 b' h* H% `% gvoid __fastcall TForm1::Button1Click(TObject *Sender)) C4 Y" F- E$ J6 b. ]& g
{# O4 P4 T1 Z/ \
    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);. ^6 s5 c  H6 B6 C7 p
}
, c5 k, q5 w$ @  k- D2 x8 O
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-6-18 06:49 , Processed in 0.018709 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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