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

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

[复制链接]
发表于 2005-5-30 19:22:36 | 显示全部楼层 |阅读模式
  #include <WinIOCtl.h>6 _+ S  d5 h3 W1 b& N
#include <stdio.h>
7 Q$ c* Q+ ]9 y" L) x( k2 p% y# f+ @. B1 W( X) y7 a) X7 [+ z3 ]  p
#pragma inline
8 u; }& R& O5 ?* W; {, P//---------------------------------------------------------------------------( k; Z7 s; E2 ~  ^
// IDE NT/2000/XP专用变量
' W3 z" N6 _! C4 i4 K- w+ Q5 u#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS$ t4 s% @6 f5 N% H9 e+ K
#define DFP_GET_VERSION         SMART_GET_VERSION5 H. `; f! Z2 ?6 n6 ^, a' n
#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
; Z8 H3 T% V) }5 _$ h1 X1 x#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA9 W$ u( |4 M! q: I% a& k
* D/ r6 D: h2 i! x
const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令4 T# w0 Z% N& |# S
const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
  u: M3 |( R* B  }2 @# S% X- s1 ~6 ^6 @2 n
const int MAX_IDE_DRIVES = 4;% w9 F1 X; x5 `, b

% ~- s3 h0 Z  W5 V) d// SCSI专用变量
& S& @6 f1 A. [- _1 y) q6 @const DWORD FILE_DEVICE_SCSI             = 0x0000001B;
9 `; V# G8 ~1 o8 Wconst DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
) ?% [, b$ h  x; `const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
0 g" f; j8 z) Z7 X0 rconst DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;+ c+ z+ S( U1 ~3 A" a; O
0 m, B( i5 v( @0 A7 P
typedef struct _SRB_IO_CONTROL
1 M3 ^" `0 o5 D' j8 T0 ~{
4 U8 ~4 O" r1 G; o% N    ULONG HeaderLength;* l) F& J/ M4 L; m9 o; i
   UCHAR Signature[8];
7 f" @' L; s. E! S, Z, r    ULONG Timeout;8 b+ \- s( [' Y4 p( Q
   ULONG ControlCode;1 X, u: o, y$ s& G/ ~+ D. F( A
   ULONG ReturnCode;
! z& V2 }+ M: l    ULONG Length;
- K, A. `, W0 k$ W6 \6 d}SRB_IO_CONTROL, *PSRB_IO_CONTROL;
2 l6 L9 U) }: G7 m- H& _- Z& ?3 C: G; G! ^  O0 N8 f: u5 C
// 读取的主函数
* N5 Q4 d# [9 P9 F' d% D( L$ mvoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);# H% p- N& a) ]3 l' k8 @/ E

  Q" o8 b4 d. e/ P; W% m) F6 ^// 辅助函数. M# Y7 |# Z" ?5 X) g6 @" n
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);# E4 a0 s1 U% M9 b4 B# e' F5 U( N$ j
// NT/2000/XP函数
" u/ S6 }9 V" n6 ~7 zvoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);. r, _2 c5 m% M6 i
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,; S* d+ H+ l) ~* m9 I8 M0 }
       PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
! E# v4 [' T7 ]3 |3 F( s) ]! r        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
. K  A8 H" ~  b$ X// Windows 9X函数6 }  b. D4 @! J$ a
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);
* s1 G) m, b4 x, W! Lvoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
% `0 {1 o( A; Q  F! c/ \# V        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);- u3 N/ c( d: \8 s9 t
; t( o2 ~% o( l. e
// SCSI读取函数(for NT/2000/XP)
" o( V5 W6 g; iString __fastcall ReadIDEDriveAsScsiDriveOnNT();3 T6 |0 U# c- v- J8 u2 ~
//---------------------------------------------------------------------------2 o3 ]0 p* s* P* h, Z
// ReadPhysicalDrive
" m8 Y. @, N( d; Ovoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)9 ~. ^4 B8 _  f' Q# U' H
{
9 J, v! L  L' c, r& R3 f0 s+ u    switch(Win32Platform)" e8 ^' i, E7 K$ Z' R7 @) B# Z" z
   {
( O! E% N* V# N) X* m- E        case VER_PLATFORM_WIN32_WINDOWS:, w% z$ y) [7 \  d0 R9 N
           ReadPhysicalDriveOnW9X(pSerList, pModeList);  Q. m, p! _2 D' ]
           break;2 m: v4 b3 |9 U; M& \9 _1 s
       case VER_PLATFORM_WIN32_NT:
' t( c( W; U  J6 {5 l            ReadPhysicalDriveOnNT(pSerList, pModeList);3 ~# B8 H2 _$ x- N5 J
           break;5 Z# c2 Z6 Z/ ~, B5 S
       default:) f9 D, O3 w8 r1 x- T
           break;! Y; H# e, |- w& q) V5 A7 t
   }+ o4 Z% v! Z) }, J% t# f
}
( L7 E7 c9 \  E8 J1 u+ T: ^//---------------------------------------------------------------------------
7 s0 e9 m9 w; o// ConvertToString; [+ n# @9 h7 M' @2 Z  Z
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
6 z. F3 C$ j: }" G& U{; S& E. J; x/ e# i/ x3 R9 d
   static char szResBuf[1024];
" F2 L: }. O1 U/ Y  F    int nIndex = 0;" l' ^: Y% r4 C* W! b+ p
   int nPosition = 0;9 I& |7 d8 N. Q% F/ L% ?$ n$ w

" g. A- u: u2 j, S# C% J    // Each integer has two characters stored in it backwards# n2 J! L! _+ Z# g6 m: t- o% s
   for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
- o" q" G( b* Q' m    {
0 D9 J& \$ a5 m" O4 ?: g) }; U        // Get high BYTE for 1st character
- H( f# S$ y7 }+ D+ K2 `( u        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);6 C/ G6 q# C' O9 b9 N
       nPosition++;( c; p! M3 `7 n, B, [  I2 E0 ?
3 J1 _, N; z7 W9 Z4 n
       // Get low BYTE for 2nd character
( k9 W: s! T/ O  d2 c" O        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);* V" D$ C+ G% ]3 a( l
       nPosition++;+ e; n" v& I& h& K# S4 R
   }4 u  T) p  L$ m% C; O4 m
7 a- n+ A7 f% ^1 h$ H+ k
   // End the string
1 x! n1 c/ p3 }, N+ S2 H4 ~+ n    szResBuf[nPosition] = '\0';
& q) q. u2 q, I. p8 Y' l% Y2 x: p# H
   // Cut off the trailing blanks
) Z9 {1 T5 Z% L1 ?' U    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
! t+ E; w* I% n        szResBuf[nIndex] = '\0';& ^: t% m& V! \5 I- ~) T' R8 }

' }3 B( d; U# C4 i; p, K0 c    return szResBuf;
- }6 j( e1 @, g# f7 B8 p& u}
" A6 r8 Z" U2 H1 j& R//---------------------------------------------------------------------------; r! C- |1 i& g. W7 _/ @
// Winndows NT4/2000/XP 代码' \, J; d; t$ f. ]- z6 H: `& h
//---------------------------------------------------------------------------
% m7 K$ j* X4 u6 m3 d- E// ReadPhysicalDriveOnNT
$ `/ H9 P; ]5 E0 c. s3 e8 I( avoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
$ s% _6 u( X2 F% A6 ]) H{5 R+ w# P& }1 O; A6 v' Q% V* G
   // 输出参数" n: A$ h4 w" F0 E5 B( s# T* w; z
   BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
+ k0 {5 m. g$ U4 t, W: ~* x/ J% X* \
   for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)' S' c9 M# w3 q0 s3 F! r
   {, T; t- _: e+ D2 c. Y( S  E( b
       HANDLE hPhysicalDriveIOCTL;
  g7 G: }/ g+ F% s+ W/ Z        char szDriveName[32];
0 `; a: \! `& ]" x  E# \  V4 l( x, V5 C5 f9 U# c
       sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);+ h' w  n$ v2 ?: N
       hPhysicalDriveIOCTL = CreateFile(szDriveName,3 ?7 c; p1 V! }; y1 b
                       GENERIC_READ | GENERIC_WRITE,
* N: R6 z( d9 E0 W                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
  z& }$ I" @9 j, A7 _; T" [2 H                        OPEN_EXISTING, 0, NULL);
0 a3 m+ P* x( M  u5 r7 s- g0 A4 k* C2 [# K0 L. S
       if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)% }0 U' Q7 V% P- u1 O+ }7 z/ E* o. h
       {# u. U9 ]- z" ^, J( H, c2 _% R" |% V
           DWORD dwBytesReturned = 0;9 \( o/ l$ _! o, \9 `
           GETVERSIONOUTPARAMS gvopVersionParams;
8 O/ {7 T2 o; D; t
( \5 `6 U+ S$ h$ r( L4 D            // Get the version, etc of PhysicalDrive IOCTL
  n5 `( e4 E% w3 L2 i1 M$ ?            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));. E) U$ T' z' ~( }1 g
5 Q2 w0 c/ {! z+ ]: g5 E
           if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
1 {" Y3 h) }- J  j                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
% i; K3 ~# {. \, J& o                    &dwBytesReturned, NULL))
1 J( \5 K2 Q" ]) t            {
7 d" u+ J' _, d1 a& N6 ^                continue;
+ T6 o. j  G2 B9 g: D7 A7 a            }8 L8 ]$ K1 J6 B4 s2 \& i

0 R, x# c5 N, a" y, L            if(gvopVersionParams.bIDEDeviceMap > 0)$ a2 p/ {. p  L& W
           {
: p  d$ D1 X# f                // IDE or ATAPI IDENTIFY cmd
+ e! r% H$ o9 I; d" R0 x! w& r                BYTE btIDCmd = 0;$ i2 g1 L. H: \- e$ h( t$ s
               SENDCMDINPARAMS InParams;/ l: T2 B4 v. t+ f
               // Now, get the ID sector for all IDE devices in the system.0 h+ A9 v& a7 B
               // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
7 z$ C2 ^- P- `+ U: K                // otherwise use the IDE_ATA_IDENTIFY command/ h9 }) c1 Y( Q3 w
               // 具体所得结果请参考头文件中的说明' s+ Z5 g9 z; A, W  P
               btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
* c- J0 F) C# o                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;4 b' f) N# v9 ^7 Z0 l5 ^
               ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
) P' P+ u+ h% l1 N) ~                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
2 K# \7 X6 ?! _& w$ Y
( C/ F: g+ E/ `& R+ `                if(DoIdentify(hPhysicalDriveIOCTL,$ F* S1 O1 x3 `
                    &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,$ N* h, u; s7 i" W3 o, X" x) j+ P
                    (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))6 B5 w8 n8 b/ t5 L; P
               {
/ O1 n( ]7 {+ n; _3 a                    DWORD dwDiskData[256];
, R4 D. N- q* \; U                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件! G+ m! B$ ]1 v* c5 N. _
                   char szSerialNumber[21];" i" T7 o  g/ f+ v! d
                   char szModelNumber[41];+ s& ]% k/ M6 o; f' j$ m- u% D0 {

. n( ]' ?4 W! K0 D" [                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
5 X' j3 D* m/ e3 \* T7 ~& P+ {$ Y                    for(int i=0; i < 256; i++)
6 \" P( k0 F+ |: s. {, ?                        dwDiskData = pIDSector;
8 O1 _0 @3 y2 \1 k; u9 V                    // 取系列号
( W5 e( T. U0 a7 }6 Z                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
7 H$ b- S+ D7 D! [) U/ z                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));$ s2 i4 v7 O. K: j4 m0 d6 y/ `

( t; M; h/ Z4 u' d7 e+ l                    // 取模型号% u4 J6 X3 w1 I% Y/ v* }
                   ZeroMemory(szModelNumber, sizeof(szModelNumber));6 B; }& m0 s  ?' J$ S1 A7 R7 H5 t
                   strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));/ L5 s& p; q7 P. t1 f+ \

3 h7 |& z* `( M5 e* |4 N( I1 U                    pSerList->Add(szSerialNumber);
0 w/ ]! T! L, `/ C  r! F                    pModeList->Add(szModelNumber);
9 {( V6 P& F. U                }4 K% x& i9 [; R7 _$ L
           }8 G1 b) V8 I4 p& {/ s% \
           CloseHandle (hPhysicalDriveIOCTL);
4 G. p: k- Q+ b5 _0 S, ]. T; L        }
' m) v. h0 N* s& D% i" V& y  ?    }# c3 P! z" ?. S* u( b1 Z! l
}# f+ I' m2 ?# q$ W1 x
//---------------------------------------------------------------------------
9 g7 [* [1 i. h* S) ^// DoIdentify& ?" ]5 ^4 d8 U2 T$ \
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
1 t1 _) j4 u" [% [4 `1 o              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,4 v" O! j& a+ j, d1 D
             PDWORD pdwBytesReturned)& y5 g  H; E) M
{
; V; ?* M  r6 V8 l( X( ]( B' z    // Set up data structures for IDENTIFY command.8 e- D  v& h2 @: T, M/ v
   pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;. V4 q$ ]# H5 i
   pSCIP->irDriveRegs.bFeaturesReg = 0;4 a/ s7 V# {& L: e6 T6 L
   pSCIP->irDriveRegs.bSectorCountReg  = 1;
, ?: V4 |5 y/ A; p, Q. J9 A    pSCIP->irDriveRegs.bSectorNumberReg = 1;" C7 j/ B! E* u! r3 U
   pSCIP->irDriveRegs.bCylLowReg  = 0;
. D% k2 U( V: M3 q    pSCIP->irDriveRegs.bCylHighReg = 0;; H. r9 _; m+ k1 N  {
, N- l3 ~) R3 l1 d: Z1 F
   // Compute the drive number.(主盘和从盘所对应的值是不一样的)  S- R( t. P( ?! g( S
   pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
8 D$ L( m) F1 _4 u
8 i1 X5 _$ I" a" Q# M% C3 y% Y    // The command can either be IDE identify or ATAPI identify.
% W! _9 ~0 X4 a( l    pSCIP->irDriveRegs.bCommandReg = btIDCmd;/ n) t2 O* J& U' O
   pSCIP->bDriveNumber = btDriveNum;! D& D3 B0 d; O0 x4 Q
   pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;$ E' z: j& z8 M, B
6 j7 P: c- n& a
   return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,5 |) l% V2 N' `9 k
          (LPVOID)pSCIP," G4 w) |/ q. d1 _8 n
          sizeof(SENDCMDINPARAMS) - 1,6 b) J* R/ p1 O5 I( `/ Y
          (LPVOID)pSCOP,
5 b: g& s- o+ A+ S* ]6 T- t           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
; h. w: U/ d* b9 G3 p           pdwBytesReturned, NULL);
7 D2 D" E: e* O/ @. e% R}
) I4 V$ @- k# x! j& a//---------------------------------------------------------------------------" l- N5 Q' I0 b5 B$ O9 m
// Windows 95/98/ME 代码
. [; E! q9 S! W8 K% f//---------------------------------------------------------------------------6 l' v* R( x& f+ {) l
// ReadPhysicalDriveOnW9X$ ~9 x. D; c/ s
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)) ^* x9 Q1 V& a0 t2 J
{
' @! h( ~- n& R    WORD wOutData[256];5 ~! g6 B2 g# ^- A9 N7 K- M( i
   SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);* S9 N: h! K9 @/ X" C# n

& L# w2 g5 L$ b% ^' i    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
* f2 ?) y  A- \: L/ [1 {! x0 y    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
( x7 e' v  X. }8 `# w% w    // 避免蓝屏的出现。(期待高人能指出原因)- b: t" M! R0 O$ c- t" x
   for(int nDrive = 0; nDrive < 8; nDrive++)' v/ d; Q- c3 u$ ?7 k. J: Q
   {. j1 C  Y2 G3 U; Y4 V+ x% s$ p% e
       WORD dwBaseAddress;+ |6 q2 T; a$ Y+ J; i
       BYTE btMasterSlave;         // Master Or Slave
) M8 |# g6 i+ l5 u' @' G$ N        bool bIsIDEExist;
, ?( e9 ~  y; ~. E7 J5 y+ p        bool IsDiskExist;7 d" R" H( F9 M! Q3 [' I9 Q1 o
" Y& o4 e5 a" L* Q9 @
       switch(nDrive / 2)
2 E3 _1 D  a+ Q        {
) N- u7 C! j9 b0 d* p/ N            case 0: dwBaseAddress = 0x01F0; break;, ]( w- J/ Z  b; @
           case 1: dwBaseAddress = 0x0170; break;* [/ B* Z4 ]7 d$ m& y
           case 2: dwBaseAddress = 0x01E8; break;
. N  E0 s7 E/ @            case 3: dwBaseAddress = 0x0168; break;
8 F1 `! S# J/ W' i        }
$ k' ^) b1 W2 R0 N. V* Q3 k
2 R. ]8 w" k; C  X        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
2 Z2 I  E  {1 P, @' U
+ {. Y7 V" }5 e        // 进入Ring0
0 L) Y1 R9 L4 a4 m% l! U        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
/ B6 g- {- P- K& L                bIsIDEExist, IsDiskExist, wOutData);
$ g. d/ v  ]% @' ^/ [    }
% @& j  h3 a+ X- {: u( [* N+ @; L( V, J+ _3 q3 F" _8 X
   // 开始读取
" G6 L" \/ D5 C8 r    for(int nDrive = 0; nDrive < 8; nDrive++)
& `& _( t1 h2 ^3 h4 P  P. o. U    {
. C6 [: J: a) Y) X+ e  y* B        WORD dwBaseAddress;4 ]4 A0 ?8 k- ?4 z1 {* Q
       BYTE btMasterSlave;         // Master Or Slave
5 ?8 ?' h# m' r5 L( b7 Q        bool bIsIDEExist;
: Z* U4 `* _* @1 w) X        bool bIsDiskExist;  g7 R( h1 p3 u9 k) ?
       switch(nDrive / 2)$ c1 a/ P! X8 j
       {( [0 Q! J( T; K
           case 0: dwBaseAddress = 0x01F0; break;
' d0 S: G; C6 R  E3 s8 K            case 1: dwBaseAddress = 0x0170; break;
' v2 C! H5 o3 q. J* Z/ J, ^            case 2: dwBaseAddress = 0x01E8; break;
4 B8 b. a7 T$ s            case 3: dwBaseAddress = 0x0168; break;$ A. X  K- i; b
       }. G/ o" a; m* M2 M2 p

. V& S3 b' U% s- v        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);- x. ~' {, S9 f4 P4 D
3 l$ m/ h' P4 g
       // 进入Ring0$ X0 f" v5 ]8 f  }
       bIsIDEExist  = false;
; v! ]1 H* s  t7 S$ R        bIsDiskExist = false;
' ~7 K6 @5 M9 K- x7 W- p; M9 |$ x        ZeroMemory(wOutData, sizeof(wOutData));
( B  h0 y. V; }8 \5 b7 }/ f' o. @' L- u& M0 L" |  s  g
       ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
1 Z; }0 _% G8 u% I' H7 y$ R1 a! m                bIsIDEExist, bIsDiskExist, wOutData);* `( S; E' L: d3 |6 t2 `' E, K
( S. U; `7 ?# X) F! A' v; x/ ?. g
       if(bIsIDEExist && bIsDiskExist)* f) Z% {. m$ k
       {' t6 Q) ^( q9 p( z
           DWORD dwDiskData[256];
, J! z! X+ w; V0 `5 d5 o            char  szSerialNumber[21];
: T7 w) I4 [0 W9 z            char  szModelNumber[41];
+ s2 L0 o) \9 N6 R5 d0 _
: u9 Y; {8 U" B0 r            for(int k=0; k < 256; k++); a0 j3 l9 F" ?
               dwDiskData[k] = wOutData[k];
9 r: w- L5 }, e: ~0 l* v* E7 y1 w& Y- o
           // 取系列号
( o( _1 g/ r8 ^* X0 K            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));2 n7 @+ d5 C" |" c. J& {8 e% U# b
           strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
2 N( }9 X7 ]: e* w2 z9 q. S+ d& U1 k5 K- ?0 ^6 \8 z( \- W% N
           // 取模型号( V& W5 m$ w* W" h% k2 s( i6 g4 `( t
           ZeroMemory(szModelNumber, sizeof(szModelNumber));; M% o) P$ [* K
           strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));/ q% U, ^, M* X

3 m; S3 o# F( D' ?2 d; p4 C            pSerList->Add(szSerialNumber);
% u% Y# Q- d4 G) _, B            pModeList->Add(szModelNumber);! s: V: p7 x4 @, a9 T
       }+ W" m4 y. {) u, m+ K* `2 K; }
   }+ F* y8 j# h% A' q+ X
   SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
0 b2 |2 N& U3 [# k9 h( G, k+ f}. J7 h0 E) |' S: v9 M+ f2 N" F
//---------------------------------------------------------------------------
6 B6 K1 e2 f% ~$ e1 h6 E// ReadPhysicalDriveOnW9X_Ring0()
9 C% m: w5 F& e" v6 v& O2 w//
* q, }! U' Z6 a7 A  d9 T' d5 v7 v% ?// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
) d' J+ @) y, V// btMasterSlave = Master(0xA0) Or Slave(0xB0)
& M9 a) T7 |: S1 f& v//---------------------------------------------------------------------------
; e# P+ V. q& D; a* cvoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
2 F) j" k; _  Q  z/ b        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
' P0 \+ n$ F. m! S9 b# ~7 i{
. b" c1 s+ h3 v4 q5 H4 B, D    BYTE  btIDTR1[6];) J; _3 t8 E. C% y+ C7 P0 h# \* r/ j
   DWORD dwOldExceptionHook;5 X( a3 U5 @7 d* j
   const int nHookExceptionNo = 5;
& t; r: {$ B4 }( L1 ~1 t  e. @! f+ v2 P% ]3 q+ `9 O2 A6 f
   BYTE  btIsIDEExist = 0;
- N; f3 j. k% }! x, ~    BYTE  btIsDiskExist = 0;
5 ?& i6 @( A9 @9 d. p    WORD  wOutDataBuf[256];
. e8 N/ o+ a2 A, f/ |- k9 {& Z( y2 s8 y4 t) w5 }9 h5 e1 j
   BYTE  btIsFirst = (BYTE)bIsFirst;. V/ j" q* ]/ A6 t+ B5 N% ~) T0 l

8 l; q, s5 P+ _. D. z3 [- r1 x9 w    const BYTE btBit00 = 0x01;
+ Z6 I" [' m9 k+ d$ v    // const BYTE btBit02 = 0x04;
( I& u: h0 k( Y2 u: u    const BYTE btBit06 = 0x40;, ]+ y3 U' v- q7 o
   const BYTE btBit07 = 0x80;2 p0 f/ ^0 I1 `$ _( Q- _
   // const BYTE btERR  = btBit00;8 b" f" k! X: x* P3 b- H
   const BYTE btBusy = btBit07;
' P% x7 y6 Q( b8 p! x# f    const BYTE btAtaCmd   = 0xEC;7 Q; ^  X+ Q" ]" s" i* d$ p1 i
   const BYTE btAtapiCmd = 0xA1;
4 b' j' ?% I. Z5 x5 q
8 V: ~; F+ z4 {! W    __asm* s% f9 f- G8 F
   {
7 I: i" a/ |- ~. L- b% W        // 必须先执行这条语句
" V. O# f8 ^8 _9 F  e        JMP EnterRing03 {+ Z3 F, F4 u6 Z) w% l2 N$ p

1 h+ C% q' k0 f2 w        // 定义过程% v$ e$ l3 y( G' Y; B; t" m
       // 等待IDE设备直到其不为忙为止
, @* w$ W+ `; C8 P& M        WaitWhileBusy proc; _6 t" i# N! U6 q! {; A# l# J7 Y
+ }5 W+ [4 ]. H$ ]" H
       MOV  EBX, 100000
! T. R. b  Y# R% P3 ]5 g# k        MOV  DX, dwBaseAddress' q; V$ y/ X. M4 M
       ADD  DX, 74 \: I4 Q( c1 S% m1 A

6 u5 E2 c( d0 \2 }        LoopWhileBusy:  D5 m; @7 d6 j
% T5 [$ Y! D- H) _0 X, p
       DEC  EBX9 ?3 ?6 L1 X$ `; G( u
       CMP  EBX, 0, s& N' |/ I% h  T) N
       JZ   Timeout  W6 _  X; K7 W! V
       in   AL, DX
4 O3 y* \; T# k) q4 U) n+ w# I7 J        TEST AL, btBusy) ]2 X: g& f! l( z
       JNZ  LoopWhileBusy  f2 m" v5 Y# |3 T, ^+ }* K% V  C
       JMP  DriveReady
" [+ l2 o, Y1 J3 I7 Z; i% I) ~6 P$ P- V- F; ^, @& ^! R  E
       // 超时,直接退出
# r* \- J3 Q# m7 W/ h2 y5 M4 X        Timeout:
, U/ p* G1 c/ T. X7 B4 d        JMP  LeaveRing0/ G" \; @  Q7 I8 t' d/ _
       DriveReady:) m  N3 u* [7 q4 H, @6 p2 u
       RET
$ J8 ]1 `1 ?! S9 K) m        ENDP   // End of WaitWhileBusy Procedure! V# f  x7 |" O0 X" ]; A( }
" c% i. W" A' `8 f- D
       // 设置主盘和从盘标志  n1 S9 ~! \; G! \! u
       SelectDevice proc& N( W2 G: s# m0 B

  L. @$ t, @; D# V* F  U2 Q5 g        MOV  DX, dwBaseAddress
+ g, G4 i! p1 v6 G9 o" S7 P3 [7 V        ADD  DX, 6+ M$ \( f( j+ [; |
       MOV  AL, btMasterSlave
: Y+ K, E# i0 l0 I4 N; t- e9 }% C0 _" Y
       out  DX, AL" Q+ t* H: a( X, Q
       RET! B6 f  Y' c( {! C

6 @6 n( M" `: O1 B/ K5 p        ENDP  // End of SelectDevice Procedure, I9 e: q% H3 H1 F( F
- U6 C" m4 `( d
       // 向IDE设备发送存取指令
( O3 A0 w6 M% G8 }: c( j        SendCmd proc/ Q& x4 D- Y" f0 m' _
* R" L8 }2 k% L0 ?6 g% B- }
       MOV DX, dwBaseAddress: u0 h/ a2 `8 \
       ADD DX, 7
. z' H  v3 {# g4 t, n7 h+ Z5 m        MOV AL, BL // BL是主从盘标识,在过程外设置( x0 G! v7 c8 {
       out DX, AL9 z  e! ^9 x  u, i" F
       RET
& `+ o0 E1 Y# m6 J, u! I7 `        ENDP  // End of SendCmd Procedure
+ x! g( |( U1 A7 G9 v( x* N0 f) W
9 B! b* n* x2 i& ~7 A5 n        // Ring0代码
0 W& C, J, a/ {  {        Ring0Proc:
2 [! f7 u4 T# e: N* q$ ^7 K        PUSHAD
/ f1 ^; z2 r( o" ^# V# j7 ~/ T        // 查询IDE设备是否存在
7 v  S# X, x& Z& y        MOV DX, dwBaseAddress
9 g5 I" E% x8 C1 ~/ `  r+ ]        ADD DX, 7+ z+ O, a9 ?3 e9 }1 L' Y" j/ V
       in  AL,DX  m( H  O! j3 }3 k0 j

& q, `" E- @( x8 Y        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
7 T% N! \3 b! ~' @6 c" y        CMP AL,0xFF8 E$ B; I% i; k. g
       JZ  LeaveRing02 G6 C% ^  ~  J' j6 K
       CMP AL, 0x7F
4 L. D" h$ W: f* A/ T        JZ  LeaveRing0$ ?) T) Z) S: a& f9 ^
( }6 M4 v! K1 c  M5 E
       // 设置IDE设备存在标志& F) a4 P  c/ S& E
       MOV btIsIDEExist, 1( t. q8 V# t( M0 _$ s; I

# }2 ]6 v& ^  ?" F' ~( u1 B. N0 y        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)2 X/ j. f9 @7 ]2 d
       CALL WaitWhileBusy2 C8 H; N$ H8 M7 ]
       CALL SelectDevice
  {/ V9 P$ v9 |- e4 f
3 t$ ?0 @1 y. m& h. T* ]        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
$ n; Z8 X/ o- A- O. Q2 n        CMP  btIsFirst, 1* C, l$ \0 o! x
       JZ   LeaveRing0) I/ W% M, o+ w) m4 c+ \) k+ a
# |# J2 ^) Q2 j/ Q7 M5 ]
       // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
9 X# s# ~' y/ B" P$ X        CALL WaitWhileBusy
) g+ u: q) ^  o+ X0 D( k
8 f8 m0 q) M1 z- m0 b        // AL的值等于cBit06时,不存在驱动器,直接返回
7 o) ^; |: y- X        TEST AL, btBit06
$ m0 l( I+ A. I/ _" x' S' `        JZ   LeaveRing0
1 j0 f5 Y  |5 j6 n6 g
$ C4 M1 D8 d2 j$ V8 s, t% Z4 S        // 设置驱动器存在标志
8 Q9 R7 m4 f  P/ ^- R        MOV  btIsDiskExist, 1
" r) s* A5 x/ [3 b: i7 m& q. P$ q' Y* |9 e9 Q% m; I! w; _
       // 发送存取端口命令
# ~" V# a$ f1 Q' t" @6 ~+ D' a  G        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
5 c% h0 C6 F3 G1 v        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
+ K  N2 }( Y  R2 G0 B' k        CALL WaitWhileBusy1 N8 F, [: G; @1 w+ w
       CALL SelectDevice    // 设置主从盘标识3 S) o' L5 `% `3 v/ O+ C
       MOV  BL, btAtaCmd      // 发送读取命令! S3 j0 p. l  d
       CALL SendCmd, ~8 b. k: R- d* |3 H& E& j/ m& }
       CALL WaitWhileBusy
1 d/ {4 r5 r- v0 e# B4 a# U# {5 M, u
       // 检查是否出错
+ i+ G  H* E, r! X        MOV  DX, dwBaseAddress1 H" M& t/ T7 R
       ADD  DX, 78 H( O/ a2 P2 T; w

( ~6 I4 J, G/ u" U        in   AL, DX: \) Q; {& K) Q/ R3 W
4 A, M4 t3 T0 L2 G
       TEST AL, btBit00
9 H- T: _! P0 L        JZ   RetrieveInfo   // 没有错误时则读数据
! {3 f& z* t. Q; z# R: }4 |; A/ }% ~+ r+ ?! O
       // 如果出错,则进一步尝试使用ATAPI设备命令6 W) V+ _) {7 D% B0 a2 P4 @
       CALL WaitWhileBusy
0 N6 Y+ I  P* k; f9 ^; i5 U        CALL SelectDevice  ~3 D" D- D6 V* ~
       MOV  BL, btAtapiCmd
- b5 ~0 w+ M" V# [  T5 l- D6 q        CALL SendCmd
7 x2 T8 z2 v4 W7 d7 [        CALL WaitWhileBusy
7 F) q' L( F- R' I4 ^
$ }" i+ T- j1 t7 ]7 }- ^: g        // 检查是否还出错1 f/ @; g4 @2 R' A: U
       MOV  DX, dwBaseAddress
$ Z5 a: E0 m: }+ N% ]. B3 O5 B) A        ADD  DX, 7
4 m; z9 m- Y2 |  x+ |$ ~  v        in   AL, DX8 I% m/ X5 t9 F! G( j/ ]: \; i
       TEST AL, btBit00, i* B7 K) i7 W/ ?& l
       JZ   RetrieveInfo   // 没有错误时则读数据
+ @0 _% p( [/ ?& W" v6 O$ S        JMP  LeaveRing0     // 如果还是出错,直接返回
) f  @+ E" Z8 C/ q
- v6 |0 l8 ?( u        // 读取数据2 Y3 ]# v/ @! ?9 u. G1 p3 B
       RetrieveInfo:, x% U7 d9 X4 W. i, h" y

0 B. N/ c  R) X- [        LEA  EDI, wOutDataBuf
+ m/ c( ^- L. o- S        MOV  ECX, 2560 H0 D  y# ~4 |# `" V
       MOV  DX, dwBaseAddress; z9 k0 y0 g/ m) m/ e: {. V
       CLD
. O; D+ r7 Z2 X( @$ S3 b# w& k2 K  {$ d' D, L1 u
       REP  INSW# w) V- n- m7 b. @3 S0 [

5 P+ J8 p6 G4 c, W$ X& J( a' P8 ?: k        // 退出Ring0代码
2 f& d* H7 I! ~  i: Z7 I        LeaveRing0:: G5 k, c: P( C0 `- i/ _4 u7 [0 l

( N: I% P4 t' C" D$ Z) U/ t* F; T        POPAD1 G, n2 `3 F4 \% ~: F
       IRETD, \- n0 p4 i) l- P  [

  L6 [0 U8 m  T9 r' h' I$ o        // 激活Ring0代码
# ~0 P' m! N: [: {5 l        EnterRing0:
" M3 I0 V$ I! j- S
7 p* O& f2 A0 q4 u        // 修改中断门0 a4 x# ^6 ^5 W4 y- R
       SIDT FWORD PTR btIDTR1+ J0 l7 N+ f, D" |$ N  g. F
       MOV EAX, DWORD PTR btIDTR1 + 02h
, G# V8 k  [, W; ?        ADD EAX, nHookExceptionNo * 08h + 04h
) v+ F' C4 n  b$ B        CLI
7 p" \9 j8 y$ y5 M* Y1 O0 h
* C7 E2 I5 w. n! |# p- y. u2 I& n" w        // 保存原异常处理例程入口
+ q/ S& n- F; s" p5 v# R7 J8 k        MOV ECX, DWORD PTR [EAX]
( j$ j% p8 E( g" j) ^) f4 m        MOV CX, WORD PTR [EAX-04h]7 p  ?4 D1 i1 M$ N2 g
       MOV dwOldExceptionHook, ECX
# ]- F# }. Q3 j; b1 c8 ^: H6 F' d4 l7 J) g" M, v4 m2 ^! M) x4 n
       // 指定新入口) {$ ^: i% }2 D7 @% A4 q3 B
       LEA EBX, Ring0Proc
, ]3 r9 `' A+ b- S/ P' r! H        MOV WORD PTR [EAX-04h],BX' \* t8 Y3 P$ D2 l. d
       SHR EBX, 10h
8 o& H$ s3 G9 L' y9 @4 b        MOV WORD PTR[EAX+02h], BX
: Q  w3 w, z8 r! f4 U7 _$ C/ \/ j8 N7 B2 \4 W# R6 F) y
       // 激活Ring0代码
6 ?  o1 |& b1 o  Z- J/ S& D- @9 T        INT nHookExceptionNo
4 D, w/ |+ B9 X! r7 M( Z- h! T! W, i$ h
       // 复原入口$ [  @; j( j  ~% U1 ~1 M
       MOV ECX,dwOldExceptionHook
+ J1 ]; ^' h3 o* o        MOV WORD PTR[EAX-04h], CX( S  T3 ?' h9 s/ S; f8 s0 V  l9 x
       SHR ECX,10h( C6 w/ ]9 L5 Q( {0 W+ O6 i
       MOV WORD PTR[EAX+02h], CX
* {( ?0 [# M( Q7 D6 ^        STI5 A0 v; K; S7 v" ?
   }
, u0 m1 j2 L6 B! @+ b# L    if(!bIsFirst)4 T8 x: B6 `3 A4 ]4 L  w
   {- w1 t, @2 V( ]( k
       bIsIDEExist  = (bool)btIsIDEExist;
: S, ?- R% s: H% }$ C: F4 C# z: s        bIsDiskExist = (bool)btIsDiskExist;
. _& i# M. |+ R4 E8 b5 \" w        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
$ v, }3 v# [& R# q- e8 V( I1 f! D8 V    }% a# Z2 Y+ C. A; c0 u
}5 n" p3 ]( d5 g
//---------------------------------------------------------------------------
5 J2 D# A+ Q# j8 ?// 调用方法:
' F& h1 R+ m, K4 y( H. P7 {7 z. g% [, }void __fastcall TForm1::Button1Click(TObject *Sender)
5 L5 [; O3 i+ T1 t6 m. R{
) ~: ^9 e/ N" O; K  _1 U    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);3 D# H" N6 V0 X# `
}
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-8-13 22:53 , Processed in 0.019604 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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