找回密码
 注册
查看: 4481|回复: 0

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

[复制链接]
发表于 2005-5-30 19:22:36 | 显示全部楼层 |阅读模式
  #include <WinIOCtl.h>: q- ^7 l8 `& n
#include <stdio.h>
4 c: Q) T+ o4 C8 B
5 a) ^/ }- o+ S$ s. n: }#pragma inline
0 h$ C5 J" [, [0 `+ r5 ?//---------------------------------------------------------------------------5 Z4 Y& q8 D/ i2 W- S
// IDE NT/2000/XP专用变量
- _2 Z; z/ z7 a" y  r#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
# D# s. k5 W- A& [1 M( ~#define DFP_GET_VERSION         SMART_GET_VERSION
+ K- l9 S8 W4 B) x: W#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
% @7 q1 n; E9 O) d#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
$ X. d* @. D" U8 }% N# Q$ q9 y0 M' S" {, Q; C
const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令& V' U8 j1 Y3 E/ k' a4 x
const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
7 v" E0 ]- s' e) d. H+ ]$ c! m5 g6 T* x7 N5 [( |6 k
const int MAX_IDE_DRIVES = 4;
8 F: l. H! L: ~: w! R3 x. @; ~3 ?+ p! s% t7 S! E6 A4 @, P
// SCSI专用变量
+ \5 q* P0 P8 q  ?9 T" W' u% n; ^const DWORD FILE_DEVICE_SCSI             = 0x0000001B;
6 B% [1 m  t0 {; xconst DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);* O$ G& k$ o; d; j) D
const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
" Z+ r' L2 n; Hconst DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;. p! ]. R% [( K' h5 h

. Q& {! {& Y8 v9 K5 y# l( V/ Mtypedef struct _SRB_IO_CONTROL6 I* q: P8 I! t3 Z: L7 Z( E
{
3 G. W2 s0 W$ F7 E0 \  I7 F3 p    ULONG HeaderLength;
1 m  t8 O" l1 ]% W% u    UCHAR Signature[8];+ G7 L; E/ A6 N
   ULONG Timeout;
8 k# Y4 N1 x% A; s, e    ULONG ControlCode;. I1 b. o) z. I) [  v
   ULONG ReturnCode;
8 g# H7 Q5 {* z1 L  F1 O3 q    ULONG Length;
! K- ~% e/ d6 f; ~$ u}SRB_IO_CONTROL, *PSRB_IO_CONTROL;  k. X$ c, b7 t* B* M' v) S. k9 j
; l  h8 t$ Z: o; r
// 读取的主函数
1 _7 q% P0 v& p5 Dvoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
. K- z" x$ B; w  c" |8 e1 u5 [9 o' b! _0 V9 B
// 辅助函数$ n. m# ^- H; ^8 d
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);8 W6 h( W# E) o! ?' {4 }
// NT/2000/XP函数
7 g+ m$ L3 i, W' a& E: Uvoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);) G* d- R+ _1 G/ H
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
& p2 I# @- [% K' a        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
7 F6 A& Z8 K; s6 [+ U( F$ K( G        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);! J* b  i9 ~2 `
// Windows 9X函数/ y% @7 C$ C4 U; m& ^7 y, Q
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);$ o+ r, H9 q0 ?
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
9 l! t' A2 S$ F* Q% P  c# c        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
( o, y+ L9 Z- n9 V$ |  n+ d* d% O0 D# d. o7 x  @& b
// SCSI读取函数(for NT/2000/XP)# `/ w! `8 x/ r# Y- R4 T9 S& e
String __fastcall ReadIDEDriveAsScsiDriveOnNT();
* R3 W8 x+ a. O//---------------------------------------------------------------------------
1 ^  o1 z6 a& T4 i0 _// ReadPhysicalDrive! v5 x) y. |5 n0 _, A$ x5 U
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
+ h1 G# n2 I7 Y# L$ L{
9 @! ]1 a, P0 O& R/ N    switch(Win32Platform)5 Y; K$ g! `/ t& R
   {
8 b' L; \. C$ X" B% f        case VER_PLATFORM_WIN32_WINDOWS:9 f6 G- T7 s: T" I! o# W
           ReadPhysicalDriveOnW9X(pSerList, pModeList);
# V5 p' ~8 n- X* x- A% s+ v. z; Z- g            break;. M, ]( r7 p. C* n* d& l
       case VER_PLATFORM_WIN32_NT:
' d7 {$ ~" W) I( j            ReadPhysicalDriveOnNT(pSerList, pModeList);
* {# O" f3 i3 h' x% c            break;
$ @; B5 ?7 _9 U( k- R5 d        default:. C5 `+ O8 R" V+ g
           break;
) z, K9 W) `. }    }
+ I9 d( u; K0 r( ]  [8 P5 p}. |8 d- V3 f% Z5 y9 W
//---------------------------------------------------------------------------1 Z+ d% S* t: x' g1 ^! V
// ConvertToString
% M5 a3 l' Q* ^char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)/ M( \+ }# R( I+ b; ^/ L0 i$ ~& t9 J
{
; G2 M, y7 b  L" Y9 n8 E, B2 v    static char szResBuf[1024];0 d4 B, ]1 I8 L# Z" T$ D5 R- S% H
   int nIndex = 0;
  M! t7 |$ D4 ?. D0 `    int nPosition = 0;6 I" I6 M5 ~4 X, U9 [! G

3 C; E( }- I* s7 [! i# R    // Each integer has two characters stored in it backwards
0 P$ ^+ W; T# G+ T    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
6 \( M7 o% C, N& \! _    {
9 e( X+ E& }% W7 d  t; @* f% r7 t        // Get high BYTE for 1st character9 C, g# R! @+ f
       szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);' j" Y& K' @- j
       nPosition++;- y) f8 u# f' e4 W$ P( P

1 {: l' [, ^0 I0 X3 X! q! e7 y1 f        // Get low BYTE for 2nd character
$ s& P' ?& W# n* O8 D* X5 j* M7 j        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);. o9 @+ F3 u+ z; [
       nPosition++;: G- }2 b5 `* r/ a7 |6 m1 m  \7 Z& b
   }! W6 T2 W7 w" G) c, j) W% K

1 |' c1 v: }7 l    // End the string- X3 e% @% R( {: t: U0 K
   szResBuf[nPosition] = '\0';
2 f7 p7 N) w4 f: C! c' j- v* o( a1 h. a
   // Cut off the trailing blanks
' B3 V, w; K: Q0 j8 n! f    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)4 S+ o0 l0 U1 e/ Z2 `
       szResBuf[nIndex] = '\0';3 ?. E: |; J; m4 e6 `' A3 v. a
7 s' l: Q% A2 ]% Z) L1 a9 u+ h
   return szResBuf;% M3 c/ B  |. n) O; b3 q+ U5 K" U
}% r: Q2 R1 C% G! O$ G7 B, d1 g
//---------------------------------------------------------------------------+ o/ L& \+ y+ x
// Winndows NT4/2000/XP 代码
' y2 x# I9 ]  T. h4 c. [1 |# t//---------------------------------------------------------------------------
2 q# O3 w( f" y- l$ f* ~// ReadPhysicalDriveOnNT
0 C3 B. E6 k8 H1 ovoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
3 o5 H. \! m) C$ [4 W! p; D& S  i{
  j6 h. m% h' f    // 输出参数! k4 e/ V# _3 N+ H) V4 _0 U7 E/ g
   BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
* L  |  B' k( d% ~* q: x$ E* [9 i$ `3 M
   for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
% e7 K. q# d3 M7 g$ Z    {8 p# \  b' C9 L, l7 x0 N5 l
       HANDLE hPhysicalDriveIOCTL;0 s/ u3 k3 {  ^
       char szDriveName[32];
7 h, N0 [  V% E5 ~/ @% q  W1 m$ h) a! p% H/ p5 n
       sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);( ~' T; N* }+ I! ?9 \7 w  j/ k% T0 E+ Q3 W
       hPhysicalDriveIOCTL = CreateFile(szDriveName,
: z8 S; J5 F2 r% x, A6 {) n                        GENERIC_READ | GENERIC_WRITE,+ }* F! o# \& H+ m
                       FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,* r1 M; T4 i" L
                       OPEN_EXISTING, 0, NULL);
( n6 b' |7 q% K: E3 y9 g; }
( r/ b! z7 T( ]" ~! i5 K        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
! K2 D3 U' R5 T. K' e4 o/ A6 u9 `        {
- q, C# e; r, H6 E3 q! V            DWORD dwBytesReturned = 0;
9 ^& |3 i* Z/ G- h# {/ A$ ~0 w" D            GETVERSIONOUTPARAMS gvopVersionParams;9 j7 D! L0 |0 U+ \4 V* M

$ k3 T4 z7 [" \3 _            // Get the version, etc of PhysicalDrive IOCTL
8 `8 P6 {4 x0 z2 ]9 h9 ~; @            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));4 }  T8 U; c/ ^& \( s; K

- U( Z9 w; d" J( J. i# S            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
* D& K0 e4 M3 _$ e+ p7 i                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
" W1 {. g% g6 P2 _0 `" o                    &dwBytesReturned, NULL))" j1 b3 n6 o8 U
           {0 V& i+ V! L* T. `- s5 x8 T4 U4 p
               continue;
) p9 Y" J1 h9 r            }) z  e) s8 O6 [5 C+ w. B
; N7 i- Z- b5 i/ {
           if(gvopVersionParams.bIDEDeviceMap > 0)* n' l1 O, q/ j0 k4 V6 ]
           {  t4 W+ q- b% s- X. H3 k
               // IDE or ATAPI IDENTIFY cmd5 e- n8 k: x) G% `- n$ c( L! E
               BYTE btIDCmd = 0;! p( @/ d. z4 j# C2 J) V
               SENDCMDINPARAMS InParams;
, K6 Z& S8 R; s9 [$ d! \# D                // Now, get the ID sector for all IDE devices in the system.6 I& |. d* N" K6 O: a& C+ J2 S. p
               // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,7 `! {( M* E/ o
               // otherwise use the IDE_ATA_IDENTIFY command
8 e# \* B) s1 S/ c: Q$ j$ M                // 具体所得结果请参考头文件中的说明3 m1 {1 f+ i8 ?( N
               btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?( E. ]9 J7 K/ a$ H" Y
                       IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;6 k/ z7 I7 a) y$ ?+ t
               ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
! M  z  G& y9 v4 J1 T1 P                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
+ d4 }9 X, n; m* f  R5 t
6 g5 d/ k# F' W/ K9 m                if(DoIdentify(hPhysicalDriveIOCTL,
" ?3 u, R( \. a6 F( u, `                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
0 B) p2 n0 O# O& K, F' N9 I                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
' I0 I7 ^8 Z- d' b$ ~  T& h                {+ u* `+ x7 p' Z. c2 M
                   DWORD dwDiskData[256];
  B) P: V3 ^0 e- W                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件: F7 u2 Q$ f6 R
                   char szSerialNumber[21];
/ O! i/ q/ U, Z* W                    char szModelNumber[41];
5 g9 N! z# O9 S' d$ t. B4 {" Q% e  F0 x0 X8 J+ s; [1 j
                   pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;4 F. {* B, e; l1 ]: L
                   for(int i=0; i < 256; i++), U2 b5 S) r# j& I) R( \
                       dwDiskData = pIDSector;
+ @' w: v( D7 b, N' T5 Z4 t                    // 取系列号# E2 m, f/ K3 P/ A+ v. @4 Y3 r! r7 B
                   ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
1 F6 G) M# J& y( u                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));0 r% _. {( i; B

; D4 f1 a7 n/ o% {                    // 取模型号* i) E7 ~9 d6 W( G; ~
                   ZeroMemory(szModelNumber, sizeof(szModelNumber));
4 G( R: X( ?6 d! R% r6 ?7 g% Y7 I                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
4 N3 N1 E2 z- m, H% b  \, V  x. m) o% P$ \1 i9 ^4 I0 @
                   pSerList->Add(szSerialNumber);
8 P( F  H/ s1 \4 j7 J$ B                    pModeList->Add(szModelNumber);& \. w+ r. Z' A5 A) M2 m- @8 q
               }
# l; _0 E- L- z9 I; ^  u! U; d            }* H0 `: f  h& t1 N1 l
           CloseHandle (hPhysicalDriveIOCTL);
% h- p/ C$ H4 t' q        }
9 L7 I% ], |* Y+ e& A) B4 o    }
3 ?# G  _; J- C3 M! D: F% q}
) U, n' N! c! X, j5 i" M! n6 v! t0 ]//---------------------------------------------------------------------------
+ m" Q/ Z! H# R; I! k7 Y) M// DoIdentify4 q% C' N5 ~$ i. S5 ?$ V/ L
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
7 A; H4 A" ]6 y) n9 Z              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,* [& Z0 ?" f: R" |/ H/ a
             PDWORD pdwBytesReturned)
* |1 y9 v! }4 b* m1 w5 I7 V9 i{
( H0 F* {# A* ]5 o    // Set up data structures for IDENTIFY command.
; Q* Q& X" T  h0 }" Y0 F    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;! t5 n" U0 i8 b) G7 v0 g, |+ o3 ^
   pSCIP->irDriveRegs.bFeaturesReg = 0;+ k3 L7 p/ z5 ^
   pSCIP->irDriveRegs.bSectorCountReg  = 1;
% `( V+ T9 X# m$ G* Q: ?    pSCIP->irDriveRegs.bSectorNumberReg = 1;
$ n% n7 K; S/ B, M    pSCIP->irDriveRegs.bCylLowReg  = 0;
# e/ ]) G" O3 Z+ v( A- n5 J    pSCIP->irDriveRegs.bCylHighReg = 0;
3 F/ p: O( i7 X% ^  a- E" u5 q. K$ b% \9 u% _4 c+ J% [
   // Compute the drive number.(主盘和从盘所对应的值是不一样的)
. z4 z" d9 K/ o: u: c    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
# t, r2 E5 Q8 K% y. p$ N" Q3 r. L+ f0 g: W: E: n
   // The command can either be IDE identify or ATAPI identify.) T! ~% o8 ~6 ^8 \+ V) ?, e
   pSCIP->irDriveRegs.bCommandReg = btIDCmd;5 M9 ~# q+ S, B" o! _. j, I' J) l
   pSCIP->bDriveNumber = btDriveNum;
: Y* p3 }0 k! _4 A, {, f' r    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
# \  s, t3 N4 H0 M, }9 ]' t
* C# c; j1 @/ m6 I: {1 y    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,& z) A. |" T! |/ c% a
          (LPVOID)pSCIP,
, \& k! U2 @+ X5 z: S9 c           sizeof(SENDCMDINPARAMS) - 1,
6 M, i8 d% F* Y9 j* S           (LPVOID)pSCOP,
! |( L3 q2 s; g2 ^- ]' j           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
: r8 m2 O* a( _# i           pdwBytesReturned, NULL);& v, H, o. i  \5 N8 [! N
}2 W: S9 z  h2 {
//---------------------------------------------------------------------------
) J8 u, f& y$ ?  |( A// Windows 95/98/ME 代码
( M& L. g) K6 u: y; E# P9 I! H2 t//---------------------------------------------------------------------------, p% y( ]) m& r
// ReadPhysicalDriveOnW9X
9 h' g3 \! H6 K( j$ bvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)( x2 e  q- U7 W5 U1 b' l9 S
{: W1 m4 n: e) v- R
   WORD wOutData[256];- z3 P+ B9 u$ d$ B
   SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
: m! N% b' Q/ @  p" e1 M6 ~2 @0 p: Y' J! U0 K
   // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
7 {4 b) l& i! S# b+ ]    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以6 J8 Q7 u. i- A, |$ T/ s4 b3 u) u
   // 避免蓝屏的出现。(期待高人能指出原因)  R& L# y! X7 E4 @" ^
   for(int nDrive = 0; nDrive < 8; nDrive++)
' m6 `6 f& o, `7 H    {
" D! O; r2 ^8 h# C5 e* l        WORD dwBaseAddress;
  Z: F2 Q6 }( c* k7 _3 u8 t        BYTE btMasterSlave;         // Master Or Slave' g- T9 @( E/ k* |% Q, s
       bool bIsIDEExist;
6 _, O1 H9 u* }/ P- [        bool IsDiskExist;
& p" y. ~% d" M. H' \
, o7 G6 ?% s7 t: I/ D5 ]- y        switch(nDrive / 2)
! |; j" C; B% @        {
# Z/ o2 h% V: C2 A; |            case 0: dwBaseAddress = 0x01F0; break;
2 D- Y* O* P  h: M! I            case 1: dwBaseAddress = 0x0170; break;
  C5 I  k# x; G9 }- @            case 2: dwBaseAddress = 0x01E8; break;* E# y# S. Z$ ]8 A: C8 _! C6 C
           case 3: dwBaseAddress = 0x0168; break;
9 C& d; h1 ?; j1 P! J9 D% j        }; W$ `/ G: I# Q! f
  P+ T/ u: m) Q
       btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);" u5 H( j7 X7 u

. v- l3 D( b# b2 I' `  n5 P5 \& r2 b        // 进入Ring01 c$ f& v/ E) E
       ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
7 ^# Q( {! u' F                bIsIDEExist, IsDiskExist, wOutData);
' z5 O# A8 K7 g8 @+ h& K    }
. V# q0 G/ n  a! \0 K0 p  L: r- x- e' h* Y6 a
   // 开始读取7 E% _. k( V  Y9 ~0 b* a
   for(int nDrive = 0; nDrive < 8; nDrive++)
6 i& _' M8 I. b. }    {
* w5 d0 o) h$ M3 C; M( P1 s        WORD dwBaseAddress;" b1 A) a. f  ~6 E
       BYTE btMasterSlave;         // Master Or Slave
3 V, c/ v" k. j% e        bool bIsIDEExist;2 F8 A% ?; N5 d: H
       bool bIsDiskExist;
% K; H& N  ~1 w! f" L: D        switch(nDrive / 2)' t$ p4 @: r1 u* a# u
       {
" ?) m* v9 x3 F+ |) ~8 c  T" r3 ~            case 0: dwBaseAddress = 0x01F0; break;
. f' ^- z9 W. e1 R; W7 }$ C, N            case 1: dwBaseAddress = 0x0170; break;3 N! L* [: s! U. F: d/ A9 ?
           case 2: dwBaseAddress = 0x01E8; break;6 q6 _% V1 h$ F- q% _/ b
           case 3: dwBaseAddress = 0x0168; break;1 k! Y6 A0 Q/ R$ o) A1 A4 r
       }5 @! E. u+ {0 e4 j. n$ e4 y- f; P
6 S) m- Z. q' H5 F7 c
       btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
( L2 O' D! f& R
' [8 ]8 b2 a$ ?& @0 T        // 进入Ring07 @( ^" l; {  B, i5 G" h
       bIsIDEExist  = false;
& d9 @4 }2 d: O: p% e  h        bIsDiskExist = false;! N) F8 H  g5 J* u+ D# E
       ZeroMemory(wOutData, sizeof(wOutData));
! @$ h6 d2 `5 S& M/ M" q7 o: W; W8 S! m
       ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,, z& z+ _; L2 b
               bIsIDEExist, bIsDiskExist, wOutData);; t% z* P! R8 w7 O$ L  G

$ t" y& v1 b5 l+ G) A        if(bIsIDEExist && bIsDiskExist)
) {+ @. _7 d3 B! e        {
$ V2 P# Y7 {* ^  C& ]+ P) j            DWORD dwDiskData[256];
, c3 {2 g3 n- K( c6 p$ x' y" c) X% J6 I            char  szSerialNumber[21];6 p; U1 O% v1 a& ~6 ^. Z- `& o
           char  szModelNumber[41];7 @0 \  ?2 |! f& u# w$ R

# ?* h& i" ]; {* b6 W3 O# s            for(int k=0; k < 256; k++)3 q6 u: T, D" Q8 D
               dwDiskData[k] = wOutData[k];
, Z: Z* E! p! z  H( p& Y( w' Z( x$ u% k% ^
           // 取系列号1 M$ e* R1 O% Z& @3 ?$ A
           ZeroMemory(szSerialNumber, sizeof(szSerialNumber));2 p. ~3 v3 P+ d  j! z& d
           strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));6 @- @' G4 Q0 M/ B: d

) G3 h' z6 T2 n' o* R3 _; ]            // 取模型号; J+ a- ]: l" d+ s* E
           ZeroMemory(szModelNumber, sizeof(szModelNumber));! R' M0 U% ^: v4 d7 Q$ @6 V4 S" v
           strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));# Q7 J- {8 J! _- \- I

9 Z3 j) k) A% e$ j! [; R% M            pSerList->Add(szSerialNumber);
0 M" Z7 q1 ?2 U7 K4 J) r' c% D+ w            pModeList->Add(szModelNumber);& f9 B4 D$ h' J% q% I4 U
       }
- D$ i3 d+ a& n: t% W; Q1 V8 E; k    }( y7 J1 Q; |( ^% X' W$ M, s8 _" x
   SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
1 d+ H; ]0 T: w! r$ E6 p: j/ ^}9 H, T, s. e6 D% T5 _% S/ L% p6 T) @& ]
//---------------------------------------------------------------------------  Y" h2 x  y9 b. j7 e
// ReadPhysicalDriveOnW9X_Ring0()
5 y* R; @& \1 k- j3 u1 ~. O//
7 W  |  ]+ C0 E2 q& E4 r// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h0 M% G% D6 o5 p6 ~+ z
// btMasterSlave = Master(0xA0) Or Slave(0xB0)
2 \6 C: c+ U& a+ p//---------------------------------------------------------------------------
, u# @$ b/ X7 K+ uvoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
" S( a3 W. `. b' M0 s# d& Z        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)2 w7 x# y3 ~, ]/ O7 _! [
{
$ ^: v- [7 b! a. H* i' n" h! S    BYTE  btIDTR1[6];
) v0 a9 ?& A/ x$ O    DWORD dwOldExceptionHook;
  ^. U$ _  q" v( Y$ R    const int nHookExceptionNo = 5;
  P' M8 v7 |- Q: m9 C" U# ^8 {6 \, S9 q- x) a* }# m
   BYTE  btIsIDEExist = 0;+ a2 }* u2 p" L
   BYTE  btIsDiskExist = 0;1 L! n) g5 y. j# X
   WORD  wOutDataBuf[256];
7 z  q6 p* k  w0 P$ l2 H) [7 T: O/ D: v4 R6 k; @# W  i
   BYTE  btIsFirst = (BYTE)bIsFirst;
% m- o- a; W# ^3 ~" A9 w
4 o; B" @4 U6 d1 H' W    const BYTE btBit00 = 0x01;
- Z0 M" e8 P8 k. {    // const BYTE btBit02 = 0x04;5 V7 u0 u0 r8 B* f# F
   const BYTE btBit06 = 0x40;
: g/ `+ A% |8 N5 n! }, y' x$ S2 N    const BYTE btBit07 = 0x80;
: q7 ]9 y% j: z* y    // const BYTE btERR  = btBit00;1 ?3 G1 z# \) @4 f, z
   const BYTE btBusy = btBit07;
( ^6 j1 \; ?% [/ v# X+ p! z9 |+ h    const BYTE btAtaCmd   = 0xEC;/ _3 z' o) z8 y; w$ D2 L
   const BYTE btAtapiCmd = 0xA1;9 T8 N1 ~+ h5 Q8 ]9 `: L% h

( ~% Y% n. A, q, N+ g    __asm! |. b% N' P% h$ {- {  r
   {
( ]) Q, F- `7 X! g        // 必须先执行这条语句8 H  b0 X  W7 C4 |' S) l; J
       JMP EnterRing0- a/ I% d- }7 G5 p- s! H
, x1 s6 f8 V) K, B  B% t
       // 定义过程* b) F- e: T+ B/ W
       // 等待IDE设备直到其不为忙为止
/ J- \0 C% H% E# d+ U        WaitWhileBusy proc
( A* E& s6 V/ S5 C6 X
# K+ |+ a/ f7 q+ B        MOV  EBX, 100000, x2 M  Z0 i* H
       MOV  DX, dwBaseAddress
2 t  ~9 O, i( C9 b        ADD  DX, 7* n1 q7 p7 d! D5 i  P! B

# c9 P- |$ E% x$ a        LoopWhileBusy:1 R5 z  m+ ]% m3 L; `+ A! p6 p

9 m% B0 P& |) D        DEC  EBX$ Q8 `+ U3 o# B+ j
       CMP  EBX, 0
) S& j: H% X/ |" E( s        JZ   Timeout
1 t; ~5 I& S' F0 Z( j7 Z        in   AL, DX
) P# E" f' f6 j2 U        TEST AL, btBusy
9 f9 @; c1 k& H/ \) f4 {9 x        JNZ  LoopWhileBusy0 f; Q# [+ L  u5 C; f
       JMP  DriveReady3 }( G- s0 b% q% f1 H
. Z0 G4 ?$ C8 @( c  k. C; n
       // 超时,直接退出
3 Q4 ^2 |7 V1 U8 f( M        Timeout:
$ o* l* C, C% _- G        JMP  LeaveRing0& M( v; m) S# L
       DriveReady:/ j; V/ K6 j+ C+ S- r
       RET
! ~8 R' f5 ]3 _% K6 S- S        ENDP   // End of WaitWhileBusy Procedure- G+ d# A. J# e  Y3 X
1 c# A: T. y+ U+ Y) w% P
       // 设置主盘和从盘标志! T0 `, Y" o/ r
       SelectDevice proc
- h- x, F" X1 H' s" b5 e. t! x( r  C# H! `2 b
       MOV  DX, dwBaseAddress
! s4 V! L( m6 n7 k        ADD  DX, 67 V0 T9 E5 Y, Q8 c# C- B: f4 w
       MOV  AL, btMasterSlave
  ^( ~& l; N+ t& q6 C6 B
" T. c5 J7 ]# Q9 @        out  DX, AL. \9 l, I; r* u: r
       RET
3 H* r) Z9 i/ z3 p
8 o- m- F7 c4 C  a        ENDP  // End of SelectDevice Procedure% d  |6 ]* F3 k3 T
9 S) `5 ~3 Z' m
       // 向IDE设备发送存取指令
% E; K4 ?' H% w8 s6 q1 t& E- v: D        SendCmd proc
/ g' y7 N2 E8 t( Q) f8 e! D2 r- b3 B7 P4 a
' K  j9 j9 B# i/ ~        MOV DX, dwBaseAddress
+ u3 @  N/ j& ]( Z: d, \5 l2 j, }        ADD DX, 7
/ T* l6 A8 X! `5 S6 K* p$ d        MOV AL, BL // BL是主从盘标识,在过程外设置' w9 p+ W: x- B
       out DX, AL
* N8 j# E( ^0 h  o0 R7 G        RET9 |7 C3 }' |3 b, I
       ENDP  // End of SendCmd Procedure
: V* \3 y* f1 @3 c
* `; P. m6 G' M4 q* x: F        // Ring0代码9 P' d0 N, L; T, |
       Ring0Proc:
  I# |( v3 n  k4 @- Y' P        PUSHAD
3 \$ y* \; d* b; g6 \9 n        // 查询IDE设备是否存在2 c6 @: `; Z* h& Z
       MOV DX, dwBaseAddress3 R  `) M" Z: Q6 z. Y
       ADD DX, 7/ g2 t* ?# r/ j+ X; M: D
       in  AL,DX
. w% C7 G* @% |/ F
* e2 H( E: Y" s        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回* [& x$ b: G" H' }$ \
       CMP AL,0xFF7 F4 K+ L* b! c
       JZ  LeaveRing07 c' p0 n9 s# K% r: w; y% `; a
       CMP AL, 0x7F& v( S5 _' O& a' E
       JZ  LeaveRing0
" j% |- W- o# y' I+ V$ u1 L
& P9 ?& n4 @4 X+ F7 @  \# |        // 设置IDE设备存在标志
/ y' i+ u7 }# |        MOV btIsIDEExist, 1
7 k- y2 b0 @+ `$ [% Y4 V( M$ e8 M6 y; V3 ?/ X5 `
       // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
" g2 z) k$ T4 J- q+ D/ W# E        CALL WaitWhileBusy+ C+ Y4 t' i' B+ b9 m
       CALL SelectDevice4 l: N  }  U- {0 B6 o% \8 A7 O

7 u2 S+ h4 [7 P4 }        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏/ d) ?9 x$ B7 `7 }, x) U
       CMP  btIsFirst, 1
2 \9 K& v: Z0 o        JZ   LeaveRing0
: P1 o- u$ e4 a7 y# [1 Q
, d# v3 B4 n3 M1 x3 K3 w+ H        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
6 @$ T* G0 f' ]5 Q8 N        CALL WaitWhileBusy
5 o6 X7 S5 D5 w  m
6 m/ C8 n& j7 B  g! `/ D2 R9 s        // AL的值等于cBit06时,不存在驱动器,直接返回
4 F! o& X& O5 u        TEST AL, btBit06
' U& c9 L$ m$ V8 J; }, D3 p  f        JZ   LeaveRing0' t( D) ]0 [) J* B. [0 g; G
" A7 }. _) t) [! y" a$ d! V+ f' K
       // 设置驱动器存在标志1 y& |# E+ S  x6 ^
       MOV  btIsDiskExist, 1$ R# [: n4 n' `: [# H( u
$ z/ L% C- g+ p0 r9 T, F. Z9 h
       // 发送存取端口命令0 f# p1 s6 Q: J: A, J# h: f# I
       // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,% `+ P  U+ D* T  A5 @' K. r& V0 t# z
       // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
1 Q3 h( _. ~2 }. [; i- y        CALL WaitWhileBusy
7 T* E( _0 A# g9 ^# u        CALL SelectDevice    // 设置主从盘标识
# e( i# \& ^8 D8 g3 M0 l0 s4 v; x        MOV  BL, btAtaCmd      // 发送读取命令$ J6 R) R. o/ N# V6 u& f; H) p
       CALL SendCmd
) ~5 b* p1 C; t$ M2 ?3 G; u6 F! a        CALL WaitWhileBusy, _' x  P& x9 M) c+ i/ `' v# w' y6 g3 R

* W" _# ?: ?5 G$ I6 [+ B        // 检查是否出错
& D# V- U/ q; S5 s" j" y" C        MOV  DX, dwBaseAddress
# W# l. m( [% ]. J# `        ADD  DX, 77 D. v* H' B$ {5 [+ g
1 ^5 q+ n& u2 X! r0 P6 n3 M
       in   AL, DX2 N% D1 e6 E; T0 a  e/ t7 C) l
0 j: K" T, a7 C) n
       TEST AL, btBit00
4 x8 S$ f0 |9 r$ x* H# v3 x1 }        JZ   RetrieveInfo   // 没有错误时则读数据8 u5 q( {# L' ~0 a& ]

5 @0 Z( ?1 r6 w1 H! p& U$ k        // 如果出错,则进一步尝试使用ATAPI设备命令
3 t- R! k5 h2 S: [* t. W: K) _/ ~        CALL WaitWhileBusy
1 B5 q! W  D5 b        CALL SelectDevice
# w4 ^! k, t7 M* i% G6 s  P- B        MOV  BL, btAtapiCmd; S1 O( J* P: S- O7 x
       CALL SendCmd( w) a4 D/ R" i
       CALL WaitWhileBusy1 H' s/ O7 C. }- {3 ]

$ S5 S. n# `: p% W        // 检查是否还出错$ B$ q$ C/ @: X* l9 f3 m! w) j+ x+ W
       MOV  DX, dwBaseAddress/ N$ K" ?! [- z6 o
       ADD  DX, 7
* w3 Q; \9 B) N! \+ l6 S        in   AL, DX
. f7 K! c( b8 U        TEST AL, btBit00
& V+ J. A, d# x9 c- Z5 p# d9 |        JZ   RetrieveInfo   // 没有错误时则读数据
& E0 \* R/ u* \' {3 i3 w/ I        JMP  LeaveRing0     // 如果还是出错,直接返回
; I; Y. N8 f1 W8 X1 O9 q5 ?. K& L6 G9 }1 N
       // 读取数据
% Z( Q6 C0 I1 z2 Q" [; k        RetrieveInfo:6 t4 F! r8 W3 v9 g" A1 f  R) f
6 C- F! O5 E* S1 ]
       LEA  EDI, wOutDataBuf
: Y" H1 K: m! J" U        MOV  ECX, 256
! x1 Z$ A# y$ o) ?% p0 |0 E/ Z        MOV  DX, dwBaseAddress/ Q; Q6 R. ~, X
       CLD
0 l& [( V& N2 p( B  ]4 i" }# G  k' ~% |: \
       REP  INSW
5 A: B: `9 @0 t9 p- e1 w  H, u0 \: d. o- ^$ K
       // 退出Ring0代码
0 \3 _: S# ]: j( ]9 K* @' k        LeaveRing0:3 l9 e3 Y# b" J( s8 S! u

6 _' d- ?) H1 E/ E, E9 z% V  `5 H        POPAD
7 f- t: q6 Q5 C4 t% K0 y: c4 V        IRETD' S5 j* \; f# H, L2 h
; F+ n& Q! \. \! S1 P9 W  v
       // 激活Ring0代码/ {3 y+ b9 b/ K! @
       EnterRing0:
' z% y, X9 V0 E' t
1 _# a3 b7 h7 f3 m- C$ U0 p        // 修改中断门! O+ A1 n# i1 Y5 S" @' v3 E
       SIDT FWORD PTR btIDTR1
$ p9 e, F0 G* K) ]        MOV EAX, DWORD PTR btIDTR1 + 02h1 I( F: D* q5 d1 g4 F, H/ Z' S
       ADD EAX, nHookExceptionNo * 08h + 04h
0 ?  t, M; b; C9 q" \7 c# }& `        CLI
5 \2 C) Y# g* f3 d4 V+ S
/ W6 p  u3 z" S* f        // 保存原异常处理例程入口
% g% }& f% B8 t; j        MOV ECX, DWORD PTR [EAX]* B* q2 [: ^7 F# B8 ~
       MOV CX, WORD PTR [EAX-04h]; [2 [( I# o5 {6 j6 a
       MOV dwOldExceptionHook, ECX* @$ L8 s  E: ^9 l# k# T

# |7 r* `* _! Y6 u        // 指定新入口1 |& a$ y3 M/ z* a" Y4 D+ l
       LEA EBX, Ring0Proc
/ Q- ^7 h7 v. W        MOV WORD PTR [EAX-04h],BX0 w$ K# c' L# L) Z6 C
       SHR EBX, 10h6 b2 H- u$ s1 g
       MOV WORD PTR[EAX+02h], BX
7 f: Q( _$ B3 _  a4 u. T+ r8 W$ _8 k0 Q4 c5 D
       // 激活Ring0代码
4 _1 F3 x* ~# |  u% H  e        INT nHookExceptionNo% E/ L! N9 h: o- @/ |

4 Z- f( v  }& C1 l) w9 T        // 复原入口& U' z5 r8 q) Z) `
       MOV ECX,dwOldExceptionHook7 U/ C3 P3 |9 B- f
       MOV WORD PTR[EAX-04h], CX2 X* Q4 z0 e) C6 ^3 g& W
       SHR ECX,10h
0 _" p4 ~3 b' `2 G6 W- V3 p        MOV WORD PTR[EAX+02h], CX
& X4 `2 D( N$ M. C5 {0 M* Z        STI
' e7 `8 M' B+ R/ @+ V/ R    }
; A& T  h& x- N+ `4 ]    if(!bIsFirst)
5 g7 ~2 s$ h9 }" N% ?+ d2 h    {# v! M3 s# M( s2 I$ G  T+ l" s$ F
       bIsIDEExist  = (bool)btIsIDEExist;
2 n8 X% A' B" g        bIsDiskExist = (bool)btIsDiskExist;
% D8 z$ i* c7 N, z4 h7 d& Z* U        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
/ }1 ^. V$ Q( ^+ V& q    }6 M1 o* s& L$ s4 }) m1 f: h" x0 S
}
' I4 E; k3 ]$ z1 b: A//---------------------------------------------------------------------------* W. U& S- \; ~2 J; Z& w. Y" ~8 P
// 调用方法:- c6 G, T2 g" v6 @) J
void __fastcall TForm1::Button1Click(TObject *Sender)
( L& T1 l; v8 ]( ~. D, t1 K) v{
- ~6 z1 D/ h( \4 d    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
& P: |/ B  G3 ]- y. @% M}
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-10-1 20:49 , Processed in 0.017786 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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