找回密码
 注册
搜索
查看: 4366|回复: 0

[收藏]在Win9x/NT下获取硬盘物理序列号

[复制链接]
发表于 2005-5-30 19:22:36 | 显示全部楼层 |阅读模式
  #include <WinIOCtl.h>
% d6 i7 e1 ^5 Z6 t8 R#include <stdio.h>
7 Q, @7 |  o, R, H2 c$ y
% r8 R7 ]2 a; T# n7 u4 m4 x' P2 e#pragma inline
* n. p! a  U! e1 s" N0 i//---------------------------------------------------------------------------
0 ^( d5 X' i! a; \3 W// IDE NT/2000/XP专用变量
$ P6 F% h/ O+ b0 ?3 y9 J#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
- r7 v" `. R# U" C: m+ l3 ], m#define DFP_GET_VERSION         SMART_GET_VERSION5 ^! j2 z3 j2 q2 ]  X( s+ a' N9 X" L
#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
6 y: y# W2 y8 `- i4 l5 J6 x#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA/ x$ s2 n0 h7 g. q! z$ @
/ y& |' g% e7 Z9 R4 ~* M( M7 i0 S
const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令
) T3 D7 X; P. v, Q  o$ ]7 Gconst WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令, X% P6 S) ^5 s7 E' R" j* G
8 g4 A; h/ W' w- H
const int MAX_IDE_DRIVES = 4;& t6 O+ s0 x# C0 D
, ^1 l: {; u  m5 J
// SCSI专用变量" C1 i0 o5 V/ }( V
const DWORD FILE_DEVICE_SCSI             = 0x0000001B;
2 G+ D3 S8 W6 _0 g* k% Kconst DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);* {* W. B4 {( i9 C$ `/ D! X: G. v) v$ `# E
const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
0 G3 W* v2 q2 z: i$ Z7 a' fconst DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;. |0 |4 H2 _# Y: E- z

5 w# \* D* q% {( Ztypedef struct _SRB_IO_CONTROL
& r" y) D$ F3 o9 e- e% o) [{3 ]' {6 ], ~/ {: B8 ~4 N+ v
   ULONG HeaderLength;
2 f+ F" {+ b3 t% i% G- \( H; c3 B    UCHAR Signature[8];! X+ Q* H; R, C
   ULONG Timeout;+ [+ s: P3 U: h; r& A
   ULONG ControlCode;6 T; h% A$ g: w9 Z( J
   ULONG ReturnCode;
3 a( M- t4 J% A6 d    ULONG Length;$ V+ p$ `4 ~  K4 R+ p
}SRB_IO_CONTROL, *PSRB_IO_CONTROL;) Z4 a# [) f( L* i, n0 u' A
: Y7 t5 j9 F( q
// 读取的主函数% C) b, C, r0 v. P/ @
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);" D8 v. R) C( o: m* S& x

' a: o& ^4 f% u0 N$ Q2 u9 ]+ a// 辅助函数  \) H  B* G$ @" g
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);! e+ N) `0 o: C! H. H) u+ d* y: }. m
// NT/2000/XP函数
. x: I- E7 o6 i& h' O1 O' nvoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
( ~! `2 d5 ?8 p9 d9 _bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
! _8 r# Z$ H  b4 i  [6 r        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,7 H* m+ x. A4 |3 m* u
       BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
& n) l; P" w" \# i( @// Windows 9X函数7 m) Q  @8 @5 G! _
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);
* u/ I8 M/ S* g, c! Avoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
3 m3 F, [3 ?% H3 w        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
9 A! O% Z8 C' b/ h  C* A1 q
4 P: T% {2 K' t; U. z; ~+ }// SCSI读取函数(for NT/2000/XP)
7 c% k0 R9 g" b6 @, T2 K+ T4 hString __fastcall ReadIDEDriveAsScsiDriveOnNT();
- P9 m4 D4 E% e& j//---------------------------------------------------------------------------
0 j; t9 d- K; u4 D, C: N. T// ReadPhysicalDrive
1 x. ]& H8 y: q7 _8 V: Avoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
/ Z/ a, T, a8 u2 C, S{
+ E  w) T7 E% P    switch(Win32Platform)
" q" n; f( d8 N, Y9 k3 S1 S7 Y$ }    {
' w2 ~4 ^/ ~2 l# }/ g/ _* ^        case VER_PLATFORM_WIN32_WINDOWS:! b7 @( M9 U8 G: f* a
           ReadPhysicalDriveOnW9X(pSerList, pModeList);
2 u1 }3 `: B' Z# f7 p) L# q  A3 L            break;
3 {) h& h' k- p+ w4 H5 D9 \% K        case VER_PLATFORM_WIN32_NT:
* K, ?1 t0 {) P. \; V. p; _& D            ReadPhysicalDriveOnNT(pSerList, pModeList);4 ^0 t# u6 Q1 ?7 e7 M
           break;' H3 v$ a/ G: o7 o  Y1 U3 `
       default:% ]4 N" f( V9 V9 w9 T3 X
           break;
* H: B  ^4 x! p: x  |6 D* t    }! @) y0 x% f8 ^1 r+ K$ Q
}
& Q6 h. r7 q3 K' t; x; F* q//---------------------------------------------------------------------------5 h2 r* P8 S& s7 Z
// ConvertToString
. o1 F- y9 F; ^* j) X( m6 cchar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)( }' r. z: ^, l1 s: e2 n9 g+ F
{
: i& \* E/ a4 W/ I/ ]    static char szResBuf[1024];0 N9 x1 C" R3 I" N0 [! P3 j3 d
   int nIndex = 0;/ j9 x9 u" x7 ~1 c
   int nPosition = 0;# R, a& @; H! k( l3 w

4 t* L( [. [% l. p    // Each integer has two characters stored in it backwards
& M6 j0 z2 H; M  v% e& w) E    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
9 W: q: _' D" b7 `    {) d' u3 i6 W. c4 ?  K# U
       // Get high BYTE for 1st character" f  ^* S3 ]/ V
       szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);6 X! D: N/ y) t9 v" K; K
       nPosition++;0 o6 h& L! Z8 t1 Y) W/ j; g

% Q4 F& A, |. H! R; ^  @        // Get low BYTE for 2nd character$ L0 J6 g; i& I: e; N
       szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);; y+ e) L# ~2 D; ~
       nPosition++;
( Q' M2 j0 ^* d9 e7 I    }
) f4 t% x' m' K/ U% K& L# a, J' g% f: \, v9 U4 l
   // End the string9 U# j! E; B: G  Q
   szResBuf[nPosition] = '\0';* A. ~' R2 i* F- N4 C  h" z/ @( {
6 s8 ]8 q  y  `/ c7 B( u
   // Cut off the trailing blanks) G4 W4 `( q1 B) ~8 S) d' D; H
   for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)* W0 D# v% G* ^
       szResBuf[nIndex] = '\0';
# @0 r$ I" u0 s, c+ d: j. w2 W" [
   return szResBuf;
1 F( O2 p. X+ F}
: l& E; `! _- ?0 X9 w//---------------------------------------------------------------------------5 ]% {( Q+ U( K& |+ u$ i
// Winndows NT4/2000/XP 代码& A& o# ]. Q: Z1 A' W. F  P  ?
//---------------------------------------------------------------------------
4 o8 w2 Y% \9 l& n4 `7 N// ReadPhysicalDriveOnNT
# z: @! t- D. `) _6 @- I. `; n0 l( lvoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)7 N' v% B! b4 h& v# o* ?1 d) H
{  n' \( Q' e4 M% C
   // 输出参数( U  q; H  }9 W" Z" W2 b9 R6 k
   BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];% \0 v+ f8 M, Y& A/ M: a# P
7 }& U$ h6 Z2 w: O1 L& J
   for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
8 X+ J' o* g$ W% B# g8 f0 H/ N5 r    {
; u; `+ g, l# {        HANDLE hPhysicalDriveIOCTL;
- i! ^6 v$ l  z        char szDriveName[32];" u+ v. g0 O6 X

1 u% C$ m2 e9 C# v: f" b        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);( j! T8 N7 T7 u, O5 n+ T
       hPhysicalDriveIOCTL = CreateFile(szDriveName,1 F2 ?" u, [( F' q- B
                       GENERIC_READ | GENERIC_WRITE,  n- [0 Y5 f; ~
                       FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
( q5 f1 E4 H7 w: [4 N+ M                        OPEN_EXISTING, 0, NULL);2 R. J- U3 J/ @( k( G8 X; Z
' ~& H! j: @9 I6 }" [- y& p# `. a
       if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE), d4 a$ S. x$ |, _6 e" v8 I
       {
. L( z) [: C% C  M            DWORD dwBytesReturned = 0;( D- j) a: {' y/ W% [1 ]) L. q! y( J9 {
           GETVERSIONOUTPARAMS gvopVersionParams;/ N  t/ s4 P* v- i) v( D! T* M2 T
. J- d" P  I& v; j; s( {
           // Get the version, etc of PhysicalDrive IOCTL( p2 ^& Y8 k$ u* v+ z* C: a# I
           ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
: i, d  e6 d1 c0 Y1 p& ~2 K" K# D
0 _7 M+ Y% ~* \2 u5 o$ k# }  }' c$ t            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
% }: {+ a2 `& ]4 T                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),9 H& i% r4 f+ \8 K5 F: u7 G
                   &dwBytesReturned, NULL))/ s, ^" A% D" f0 f2 c, m' w' |
           {
- `  h9 W! n! y( Q+ W& o7 t                continue;
$ [% r7 q1 C8 v/ @" R            }
7 O% R: x) \2 ~
; U  h6 r; k! D% m2 W& _+ |5 o6 H' Y            if(gvopVersionParams.bIDEDeviceMap > 0)* g1 ^6 Z* a: w  C1 [9 S
           {* l6 x( L4 j# |( G! p* I8 x) q0 \
               // IDE or ATAPI IDENTIFY cmd
& e5 g  _& K+ @' g) g                BYTE btIDCmd = 0;+ ]" k1 S+ q5 ^) R9 a" B' `
               SENDCMDINPARAMS InParams;
& I. ~. ^, d/ ~' N. `                // Now, get the ID sector for all IDE devices in the system.
- T0 G; [+ N1 c+ W" W" ?& R" U9 i                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
$ _4 C& o9 U7 w$ @( x/ B7 C                // otherwise use the IDE_ATA_IDENTIFY command
% A+ n+ @* P( ]1 O                // 具体所得结果请参考头文件中的说明6 G! A9 A/ p9 |/ _! ?) o/ l
               btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
6 K7 d/ y2 [6 r! q/ D3 }. P                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
7 \6 Z2 ^, x( J$ S7 H% q                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
, w8 k: O* c6 o% a, j2 `. k5 p! K                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
  z* e5 j9 e) a# K. ^" X# C7 g  M8 I# E8 W0 q+ }9 C
               if(DoIdentify(hPhysicalDriveIOCTL,
3 W- E  O6 p  N" E0 L                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,1 n- t6 u# @" q
                    (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))9 {1 X% H6 s* c+ R( B" W- @. N
               {
5 O+ s5 G# _. S                    DWORD dwDiskData[256];
" c. b" y) k2 Y6 Z# A- r                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
8 A4 ~; o; W! {* T9 M                    char szSerialNumber[21];
; R: D9 B3 l/ F# K                    char szModelNumber[41];5 ?- i  X1 e; b( Y. P5 }# R

' n$ ]1 n5 c2 ]9 i7 _+ E5 `9 h                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
  i' @; N, L/ J: q8 t0 U6 y. r                    for(int i=0; i < 256; i++)
0 k# j) D+ x. e+ z                        dwDiskData = pIDSector;
% i# K# x. ~2 O" h6 I  X5 U                    // 取系列号9 v# ^" ?. z& v: ~3 S
                   ZeroMemory(szSerialNumber, sizeof(szSerialNumber));6 }( Q* Y6 [4 a# I- L& D
                   strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));6 m3 R/ ?( s/ v3 ~% L4 L8 z

4 r; i  T) Y2 {( M5 l4 p7 A5 t0 ]                    // 取模型号4 ~, N8 Y# a# e
                   ZeroMemory(szModelNumber, sizeof(szModelNumber));+ u0 I% ]& U9 |1 R& I1 j2 X
                   strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
6 |7 o4 j: l3 w
3 m7 L3 F! G! [& s3 |# w: N5 c# n: |                    pSerList->Add(szSerialNumber);
. s. K8 n* |8 @* s1 w                    pModeList->Add(szModelNumber);
8 K# m+ j. {5 c4 n$ Z; w                }0 d; I0 Z: [5 a5 X, V
           }3 ^3 [3 h1 {; z5 ^
           CloseHandle (hPhysicalDriveIOCTL);9 I- o" a/ v  w
       }. v( A0 O2 h0 _" v0 o6 P
   }
' \8 O+ ?: N' B" Q! |}6 E( }, Z( D! ^: j% {+ X- p  P
//---------------------------------------------------------------------------
5 Q0 D: @. }9 Y$ K! h6 y+ c0 p// DoIdentify) l$ J+ `: t- V0 o3 R4 y
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,: [! r$ B' @( O7 E4 f+ j/ s6 y0 X
             PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
, d7 c0 e  F! R1 z; Q$ r6 e% V              PDWORD pdwBytesReturned)) x) |, c9 ]0 i/ d8 K+ A  i
{
, T- e0 H( @2 R/ I    // Set up data structures for IDENTIFY command.
! p$ G4 B. e$ [+ J, r    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
5 a+ D2 n$ z8 }& E) P( c    pSCIP->irDriveRegs.bFeaturesReg = 0;: x) \; _, v! A/ D
   pSCIP->irDriveRegs.bSectorCountReg  = 1;* B& M# q4 k3 b9 r, }) i) u7 g7 |# ?/ c
   pSCIP->irDriveRegs.bSectorNumberReg = 1;4 b% p; @  P: Y: p4 h! y5 e" y, J
   pSCIP->irDriveRegs.bCylLowReg  = 0;
# J7 T! g8 ?3 x$ v    pSCIP->irDriveRegs.bCylHighReg = 0;  B' B" V8 Z, R) f; y. n) w. y1 R
+ s$ I4 Q: S4 u! L
   // Compute the drive number.(主盘和从盘所对应的值是不一样的); w2 h5 }! }+ z+ i8 F3 `) e
   pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
6 E! x' d' h$ H9 P* K$ [. T) @8 P% N5 o
   // The command can either be IDE identify or ATAPI identify.
. }. B% v. N. ~8 r- J: k7 k    pSCIP->irDriveRegs.bCommandReg = btIDCmd;
% R7 c" w3 o2 I6 O: h2 F+ [) i    pSCIP->bDriveNumber = btDriveNum;/ G% C$ x& W4 @
   pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
% L; h& x+ T# ]
5 ?6 E) X. t% B% p7 X    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
/ S- F& F7 j# K           (LPVOID)pSCIP,
+ ~  _% o( C0 p' v           sizeof(SENDCMDINPARAMS) - 1,* P& g7 F6 z% F) h3 V' i' e
          (LPVOID)pSCOP,) h2 ?0 T& O& ^, g; w5 B
          sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
3 G% P$ v1 X8 E: H. U# Q( A5 S0 `           pdwBytesReturned, NULL);5 t5 v5 A, s( z* k
}* l' \1 O; _& n$ o6 y. H7 q% Y
//---------------------------------------------------------------------------5 \3 b) _& Z( e7 J/ Y7 m
// Windows 95/98/ME 代码+ ]+ y( q% g1 G- X
//---------------------------------------------------------------------------
- ^( g3 Z( j( ?: G" Z// ReadPhysicalDriveOnW9X# J- ?6 @; v6 S& d' e
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)
# F4 \" F2 {  E8 Z{
- F, g5 M! a" h) N5 G, W, a2 X    WORD wOutData[256];
& A4 r: o( x; {: w5 Y    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);- V8 X' W) _# V. g
2 s5 L7 B8 i3 o% \2 o4 C6 i3 [
   // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。& @2 }& h: y- K& e
   // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以2 B# H- k6 F$ i$ }# A+ N1 S% k* K5 u
   // 避免蓝屏的出现。(期待高人能指出原因)6 A; X# a7 H9 d* K  `4 @: Q' ^! \
   for(int nDrive = 0; nDrive < 8; nDrive++)
: G# k' M3 o! j: _: c    {
3 ~+ [+ t$ a( I. P        WORD dwBaseAddress;
, ~' x* C4 b: g) q! W        BYTE btMasterSlave;         // Master Or Slave) M: h* T7 D/ [# D
       bool bIsIDEExist;# L" e7 A, c) ]8 ~  W: M4 v
       bool IsDiskExist;
+ s# F) b& M+ [3 m& v6 m2 T1 _' r9 J$ {' U4 @8 m1 F
       switch(nDrive / 2)' J$ X( e) Q0 j, `7 H- r1 }; s/ Z
       {
+ H5 ?$ W3 M5 V0 {            case 0: dwBaseAddress = 0x01F0; break;" z; V2 y( d; t& Q" w+ g
           case 1: dwBaseAddress = 0x0170; break;) t7 @2 k; N. |# ?4 \& P
           case 2: dwBaseAddress = 0x01E8; break;& C9 @0 E7 y5 y
           case 3: dwBaseAddress = 0x0168; break;) X. m% J1 U6 s; H
       }
" P0 P2 l! A4 B# T! |) k
; b# C$ Q9 t2 K: _. x" y& ?        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
5 q% y' i: F5 l) F
2 f; u, K- r$ P8 i6 h# Y7 B' T* Z        // 进入Ring0
6 H4 {! ~" Q* I. R3 r  J        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
9 u5 s' N% p9 E) P) T                bIsIDEExist, IsDiskExist, wOutData);
$ n6 g$ w$ O' r& t) {. S; `    }7 _$ r: w, q# O- J) v/ {# E

0 |/ t: ^3 \2 z/ s" K1 M: C    // 开始读取& P5 x, |0 ^9 I, S, y. f! o
   for(int nDrive = 0; nDrive < 8; nDrive++)
: }7 B( d' R7 g% S& i/ |    {3 H9 A, t  T4 I& H) V. H9 [
       WORD dwBaseAddress;
$ z, o- E5 Q) F& c2 v, S        BYTE btMasterSlave;         // Master Or Slave/ r/ B. d6 K* Z& d
       bool bIsIDEExist;# I* }& B1 J/ v0 P: f) J
       bool bIsDiskExist;
: s& ]' \$ t$ ~. h: W        switch(nDrive / 2)$ u# |1 F4 O2 }1 Q( O# I6 g/ M
       {
( h7 o5 b1 ^# H, {. ]8 M0 q            case 0: dwBaseAddress = 0x01F0; break;% r( Y; H, a+ j$ {. N. s- {
           case 1: dwBaseAddress = 0x0170; break;0 _  ~* x( ?! h, ^; D
           case 2: dwBaseAddress = 0x01E8; break;; q% q; R2 E+ N3 @' Y5 y7 t, w* n
           case 3: dwBaseAddress = 0x0168; break;
7 h3 b4 u- H" f4 f2 K, X! H5 _        }+ V; g, W- ^! K  ^8 w! n5 {8 F9 A
5 Q  X2 @* T: l  Z, T
       btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);! x/ W8 M( B. Q$ K8 C
% M0 s# Q/ \' D! O
       // 进入Ring0
5 K0 x& e- m: L6 H7 m4 k3 Z- [; W        bIsIDEExist  = false;+ y1 m; E9 g2 u) @$ d2 d
       bIsDiskExist = false;6 Z0 }, s. p+ o2 r6 n
       ZeroMemory(wOutData, sizeof(wOutData));
8 @$ V8 X  k: I5 M( R! T3 {5 B6 a! R6 t( {: h
       ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
/ ^. ~7 y1 Q/ P4 F2 `                bIsIDEExist, bIsDiskExist, wOutData);
1 u9 ^7 f" S1 ?, s) I% b: r- N3 W6 E: }) a' D: M5 c. ^
       if(bIsIDEExist && bIsDiskExist). \+ Y. ~' @6 k1 V
       {. Q' N9 X* Q4 H! O6 G7 J
           DWORD dwDiskData[256];
' }, O+ P; W$ o2 J% X            char  szSerialNumber[21];' }* B- y4 z9 m* S( X
           char  szModelNumber[41];
) }' r# l- m# q$ G  R0 v9 O
. u" @1 H& c0 ]5 y+ D            for(int k=0; k < 256; k++)
7 A) O7 V  {' K& f, B                dwDiskData[k] = wOutData[k];2 P0 l; T$ |9 a' Z& _- g+ W: L
; \0 j: x" m# u. Y
           // 取系列号
9 S$ m, v7 @; V' M            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
& _6 r6 |3 B( I            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
1 k, C7 L5 K: E8 n
$ L$ b' ~4 ~' x; K4 @8 b$ u            // 取模型号2 c$ H% [4 s! C, B
           ZeroMemory(szModelNumber, sizeof(szModelNumber));4 Z" W/ |7 {' A$ X& Z
           strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));: `1 P% Q5 d6 a) q0 |
1 U% e: [- d1 `# K
           pSerList->Add(szSerialNumber);
. ?0 M/ i1 X" B! w& Q: u$ R% t# R            pModeList->Add(szModelNumber);$ _$ L6 C$ |# @% N5 s
       }
0 `% Q, }4 o6 [% X    }0 ~* ~' W: L: r* V! G
   SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
7 d1 G% U- z7 w}  y% X8 c3 _! ?3 x+ j
//---------------------------------------------------------------------------
7 t$ i) s4 g9 v// ReadPhysicalDriveOnW9X_Ring0()
8 \7 g! ?6 _! S" ~, G//4 ^1 @6 ~2 C4 D5 V
// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
* M+ t+ {& C4 _// btMasterSlave = Master(0xA0) Or Slave(0xB0)
9 H9 {" }$ {2 \6 \& g9 j" D/ }2 B2 n" ^//---------------------------------------------------------------------------- |( z: Z3 @" d, \0 j
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
# C- }; Z9 X+ k        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)4 h  i! L5 _1 Z4 b1 S& K
{! ?# W( d. S6 a! |1 a& v( B
   BYTE  btIDTR1[6];+ m- {  z5 |# V0 ]! _2 E
   DWORD dwOldExceptionHook;
& r9 y7 z2 k, D4 B% i! W8 n# b( S    const int nHookExceptionNo = 5;
/ r% X  r7 d- _/ p; M. W
# x* @7 D+ l) ?    BYTE  btIsIDEExist = 0;
. l) L& E! k2 X; N0 _0 m* r) h  Y    BYTE  btIsDiskExist = 0;
2 i& M" Q9 `' g+ y- ~    WORD  wOutDataBuf[256];  i7 g: l* [; H& ]" S4 N7 Y
2 y3 W. t3 I, [2 S- J" h- H
   BYTE  btIsFirst = (BYTE)bIsFirst;
' z0 g, {8 k7 R& J( c
! R/ ~5 w1 ]3 a! E1 E* K! c    const BYTE btBit00 = 0x01;/ d5 E5 _6 h% a7 a
   // const BYTE btBit02 = 0x04;
/ Q7 g: N3 ~; Z# X" J    const BYTE btBit06 = 0x40;7 E) b; t2 M. O) Q' v
   const BYTE btBit07 = 0x80;
$ K# F8 ]7 e2 i9 h- b7 E4 Q    // const BYTE btERR  = btBit00;
" [6 i9 f  \' q7 F/ P7 ]. }    const BYTE btBusy = btBit07;. M) s% ^* @$ y0 l; |
   const BYTE btAtaCmd   = 0xEC;5 S1 B$ f  p: K2 W
   const BYTE btAtapiCmd = 0xA1;
% o. |5 O, ]' S+ _7 |) ]0 w+ }; U$ n$ t1 b3 |" r7 Y+ U0 `
   __asm* P$ A1 i5 z3 w6 E
   {- `6 L% Q$ S7 {& D# j9 D
       // 必须先执行这条语句
, _: x+ r7 Q' @3 U3 _, t        JMP EnterRing0
; f3 k% g9 E+ v6 q$ E2 N6 ~$ [! X8 \1 Y8 L% O
       // 定义过程
5 ^6 V: \2 K' W        // 等待IDE设备直到其不为忙为止
5 u# r3 H& [% U2 ~6 t        WaitWhileBusy proc
' N) m6 K$ S0 S1 X9 ]1 U/ h3 w2 O( _
       MOV  EBX, 100000
  T* E. m5 U( ~) e& t2 @8 \. L        MOV  DX, dwBaseAddress/ }) l4 B6 Z5 \0 p& x" G3 [
       ADD  DX, 7
0 D0 A# e* A4 ~( f+ o
0 y6 X1 I( ^8 n* w! [7 `        LoopWhileBusy:
. d5 V" J% c4 L2 T- q' G; e0 X4 ^, D# z# v" D
       DEC  EBX
* ]/ k3 P. k. S* J6 k( u        CMP  EBX, 0: V, B6 m. R4 {* E; I9 I; z! O5 t
       JZ   Timeout! W# h* T# {5 U+ `/ F  g
       in   AL, DX3 W; I, t$ u7 m( M
       TEST AL, btBusy
1 K- E, w* Q" h$ _. M8 U        JNZ  LoopWhileBusy
* {: V* E0 {* N# n1 Z9 |7 d        JMP  DriveReady- P2 {6 n8 ?. w* b" K0 Y! v; u

* w- M* _( a% L; b+ k; M/ a7 T        // 超时,直接退出
; H4 I7 L- a: W        Timeout:
; y0 u% X6 h. z, }        JMP  LeaveRing0
1 w' y( ~9 ^; U/ B' i        DriveReady:
+ n$ g8 Q) f" n        RET
& ]" t5 F# D7 u$ y5 s        ENDP   // End of WaitWhileBusy Procedure0 B/ t# b, {9 m5 A
' j! o0 w1 K7 e
       // 设置主盘和从盘标志5 j% X! b: C( H0 C& F
       SelectDevice proc. P$ s: m# R7 U9 P) O' i  Y4 k& X
: f' M& r3 L7 o9 Q2 h
       MOV  DX, dwBaseAddress& T. R9 c* ?3 s! b# ?6 i/ \
       ADD  DX, 65 q7 H: a8 V& Q4 Y8 {( h$ J
       MOV  AL, btMasterSlave
4 S- C5 ?2 |1 B
- H8 Q: S/ x1 U- @, O  f" `+ T; E        out  DX, AL/ Z& s, ]7 f9 R# ?% w, f; G! [
       RET
) D' ?* m. z/ f; @+ W7 [) F" `& d5 V: y: ^
       ENDP  // End of SelectDevice Procedure* E, n  U$ g- C5 _
1 C$ _( Y. L, v. t
       // 向IDE设备发送存取指令, E5 Y0 X1 N2 Z2 C$ U# y4 B, `
       SendCmd proc
- q: g/ \; A5 A7 i, M7 t- g+ h4 l- i8 ~; n* c8 f% f( O; h, F" I
       MOV DX, dwBaseAddress) j) r6 Q; u+ o/ F1 [
       ADD DX, 7
8 S9 \. w! J2 P4 s# @- s        MOV AL, BL // BL是主从盘标识,在过程外设置0 T0 A3 Y; ~7 ]0 u
       out DX, AL! r) R4 v1 |$ N- J' T& Y
       RET$ a4 k: K1 C% U, j: x% z5 y: l
       ENDP  // End of SendCmd Procedure, F, m" f* z* d+ x( b* G2 z9 c( {

- f. r: w  H, v        // Ring0代码* b( m$ F8 w' G! \) G' k9 Q
       Ring0Proc:
) _3 Z- d! B: m$ g+ E" V! R        PUSHAD/ W7 ]9 D1 d) O& A; G5 O+ v/ `
       // 查询IDE设备是否存在* x. E0 P* P9 ?/ q& U& V: E- V4 a
       MOV DX, dwBaseAddress' P  [8 i4 {2 i2 V/ Y* u9 o; \
       ADD DX, 7( Y6 c. [7 C5 z( a9 d" G2 U1 I
       in  AL,DX
. p5 O5 a. Y8 ~+ r, X  r
7 a6 k1 ?$ D  x# z* U: B1 D        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回* b" g& l' x: F2 f- s
       CMP AL,0xFF
9 w2 f! M( @: a% B        JZ  LeaveRing0
5 A1 W* |1 u2 h, J5 g# T6 Q! \        CMP AL, 0x7F6 ~) q4 r- \, m/ Y9 M# L
       JZ  LeaveRing0
2 _, B% o  ], q3 I+ n
& s" _* B* v2 G" Q) \$ o/ p        // 设置IDE设备存在标志
  N5 U/ ^$ B5 }+ D) }) C$ b4 e        MOV btIsIDEExist, 19 z0 ?: t! W# Z; j1 d$ ?

" b. p& e( Z3 ]# p        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)) y% b0 l" I( x/ M/ f* ]
       CALL WaitWhileBusy# H% l$ I, W) S  e  n2 u
       CALL SelectDevice
* w( ?2 O0 Y4 u: G# O4 `
: H$ J, x5 w- x& {  h        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
) h* w5 N; I5 ?1 }        CMP  btIsFirst, 14 q) t. U7 G3 Y% o( P( b
       JZ   LeaveRing00 L$ X! Z8 w- D+ v( k6 g% @+ f

( n& W  `4 v# p- p        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
/ z9 u7 ?8 f/ o" B5 @        CALL WaitWhileBusy6 [, n8 I! W5 q$ j& D

' j0 Q- ~+ Z. Z) e/ I        // AL的值等于cBit06时,不存在驱动器,直接返回
) H( d/ l& @% I4 y0 T; j        TEST AL, btBit06
7 j: A2 E/ Q$ ?* f; d$ k1 U+ C        JZ   LeaveRing0
- }. x- S0 B% R
# h5 R" b1 y" W- Z4 d0 G        // 设置驱动器存在标志! d$ d6 b" T& X" Z" v. g
       MOV  btIsDiskExist, 1
, o. [9 f/ @7 n$ e! D( K; d; h5 x6 _$ g4 P
       // 发送存取端口命令
0 a: d, T3 Y/ i2 k& j' o5 o        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
/ n: x5 g) p! c) }% ?% g+ ?1 M6 \1 `        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令& ]) m, Q( q- I
       CALL WaitWhileBusy+ @" V. {1 D2 P8 B
       CALL SelectDevice    // 设置主从盘标识
8 P; V% `7 Z2 Z7 [! b        MOV  BL, btAtaCmd      // 发送读取命令
! L2 t9 n* r% p  H. U. z' I        CALL SendCmd
" I! x( `* N" s% @( \4 Q        CALL WaitWhileBusy  e! _& w" s% e, {, ^

  \' x8 O- i# e0 w        // 检查是否出错& J  ~' `7 c+ C
       MOV  DX, dwBaseAddress1 ^* ?: S4 V. i& E3 N
       ADD  DX, 7$ }" i8 r$ [' f0 v; W! V4 r
# d1 T. ~* ^) f9 n6 p5 o# X& E
       in   AL, DX- {2 V. ?! e! O# i. v4 k

6 L( ?) c' K% `5 I& E" D        TEST AL, btBit00% B4 b! D5 W% P/ F
       JZ   RetrieveInfo   // 没有错误时则读数据+ A* Q. b5 E. ]  q/ \$ _) U
0 c9 h+ H2 K1 u6 K. [
       // 如果出错,则进一步尝试使用ATAPI设备命令
$ h( [/ ]/ H: Q: p( I+ s( ^, w        CALL WaitWhileBusy
) S7 N8 [# o; R, N+ ]0 c        CALL SelectDevice
# O$ ^0 e' L+ y, m2 o        MOV  BL, btAtapiCmd2 j2 Z, x! M9 F5 o- }; U" ?* n
       CALL SendCmd
7 O- E9 ?. F$ G2 y' z5 m( s  u        CALL WaitWhileBusy9 |6 S5 k8 Q3 L( G8 S6 b

! ~: c% S: m- B6 B        // 检查是否还出错
' k6 @; [# J! [- x        MOV  DX, dwBaseAddress+ g" S# Z3 W% ~2 b  M3 n
       ADD  DX, 7
* r5 p2 K' V4 V8 p8 q& h, ^        in   AL, DX$ f( A* R6 Z) k* ~
       TEST AL, btBit007 K7 j9 v) t" N! E+ u. k' s' V
       JZ   RetrieveInfo   // 没有错误时则读数据
8 r7 x3 O( M9 ^0 L/ z        JMP  LeaveRing0     // 如果还是出错,直接返回
; z% p* g4 W& @, Z# S. b) H& g7 f4 t3 z; N1 Q. G
       // 读取数据' n7 e( F) J; z5 J
       RetrieveInfo:
- x* G2 E0 `& U. V* Q9 d! N3 P" E: Y6 A+ {& ?+ k
       LEA  EDI, wOutDataBuf
& Y, O8 o$ i9 K9 }        MOV  ECX, 256
) O: L! K0 @# w: w        MOV  DX, dwBaseAddress/ U' Y; T$ K: K3 l$ J5 C
       CLD! {" L7 p4 B, P( ]$ d# Z) S3 y- v

1 j% W+ `, b' s% v) g- a        REP  INSW0 @; V; m; s2 G6 Y! o1 g' `
' O, }4 F/ n# q$ V* ^$ u6 G
       // 退出Ring0代码
/ w; o) G' G; v& I7 ~        LeaveRing0:
1 `' L2 D0 o9 {8 Y# r
* f. V7 C0 J0 v. Y3 l2 }3 y" w        POPAD+ G5 A* {1 ^- q1 Y2 D- O
       IRETD7 H* F! A* q3 \
9 K7 N8 S; o1 ~+ |) Q7 M8 l/ f: t7 j
       // 激活Ring0代码
9 I" I& |3 [/ m        EnterRing0:0 _3 I, M0 S: x3 R

* v: F4 W5 L2 n  s) t( d3 S5 r        // 修改中断门
  c7 V- c4 N/ W+ L  s( P3 n0 d- d        SIDT FWORD PTR btIDTR14 l+ o4 n  {* t  q; `
       MOV EAX, DWORD PTR btIDTR1 + 02h
# I% c9 @5 S) v4 o        ADD EAX, nHookExceptionNo * 08h + 04h
. Q3 q0 ?0 O& h0 W0 N4 n1 w$ W        CLI7 x! I$ v! k$ w. q: w

2 m5 ]) l! N) g9 ~        // 保存原异常处理例程入口
/ e% j! D+ S% a. Y1 v+ E) l        MOV ECX, DWORD PTR [EAX]
$ o7 F1 m3 c; [3 u# |        MOV CX, WORD PTR [EAX-04h]
6 w! }( b' N% S$ C, E- W" S9 G        MOV dwOldExceptionHook, ECX6 [& m* {7 f  o5 K. j

# r& j$ ^2 Z# m' u. v) ?        // 指定新入口  H2 W' R3 C: ]6 D
       LEA EBX, Ring0Proc
4 p' S3 d' U3 r5 R        MOV WORD PTR [EAX-04h],BX
. j4 ?6 ~, D" ^  y% x9 S1 W        SHR EBX, 10h* c: {% e$ V" u, b! q, s) \
       MOV WORD PTR[EAX+02h], BX
) H! s; W1 n* Q/ U! k
. y6 ~% g/ o6 ~% T% e( z0 K4 _        // 激活Ring0代码, z5 N5 H) [) s& O6 G" ~- D. P
       INT nHookExceptionNo. @' C2 M0 s' h

. G  d5 S$ \8 ]! F* ?7 e, w        // 复原入口: \6 H8 p' P" X% t  t
       MOV ECX,dwOldExceptionHook
$ ?: L! A3 x7 E5 ~        MOV WORD PTR[EAX-04h], CX
4 d: y& U5 ^0 r. [        SHR ECX,10h, D- M- l$ ~5 y" t
       MOV WORD PTR[EAX+02h], CX. m9 n5 }; H1 Z8 v) h6 I4 Q/ O, A
       STI
. s; O, z1 Z& Z' `    }
$ G4 L. Z! V6 p8 _9 U3 _, C+ N% s    if(!bIsFirst)
: ?' o9 R4 q, }' ?/ ~    {/ q4 I, H# y$ J) L
       bIsIDEExist  = (bool)btIsIDEExist;
" R  k3 ]  a2 a        bIsDiskExist = (bool)btIsDiskExist;
; W, n7 d  `$ k5 s        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
7 I. U2 h+ Q! v" N    }
5 ?  H3 u( }/ @" @/ l1 M}
' n( N2 a3 H) j- N0 G' i" O//---------------------------------------------------------------------------
+ {; K& W$ [, O  ^/ z// 调用方法:! w; j% q8 G4 X0 |# N' r
void __fastcall TForm1::Button1Click(TObject *Sender)# {/ N" F& F5 Z( k( F
{9 ?! Q, H8 Y% i5 Y
   ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);  L/ Z2 \  u; B, r& K  Z1 e6 _9 O
}
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-5-2 11:47 , Processed in 0.021087 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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