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

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

[复制链接]
发表于 2005-5-30 19:22:36 | 显示全部楼层 |阅读模式
  #include <WinIOCtl.h>. g7 q7 [5 F& N  Z  {' c
#include <stdio.h>. B% d+ B) c( Z. u9 X8 E- f
* V0 T2 V. F, e) T
#pragma inline; W1 ?& x2 W: h5 e; i, _) |6 z# Z$ [
//---------------------------------------------------------------------------  b% `0 ^& D: a& F. v0 t
// IDE NT/2000/XP专用变量. q& D; _; ~6 o. _/ o0 B
#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS4 g4 S: n8 O$ r. X+ E# h$ v
#define DFP_GET_VERSION         SMART_GET_VERSION
+ ]( t( t# \, u( G9 x# w. [#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND5 ^0 j: `8 w1 @2 ?( w
#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
; |$ D" q+ T7 `' v) h% Q0 w$ U3 p) c  J# ?0 x1 K: f, c2 B1 m0 O5 W
const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令
5 a/ \/ R1 J6 m  M" xconst WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
5 J; F; u0 E4 F/ A- r5 |" a6 @9 W5 y, n/ V" H4 ?! a7 {
const int MAX_IDE_DRIVES = 4;
* u$ c& I, o& b; ?( f! J9 r- I% O6 i% k
6 b7 [# b4 C- [. f9 G// SCSI专用变量+ Q& T: c+ [# d3 n- \, ?* J4 O
const DWORD FILE_DEVICE_SCSI             = 0x0000001B;
! _# `9 ?0 L! k6 gconst DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);0 O/ O' g! ?2 U! Y4 r
const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition- p& i" {9 d; M5 B
const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;+ J( r9 K0 ~  F# I
) s8 W4 T/ w# q5 x$ Z) z
typedef struct _SRB_IO_CONTROL8 ~9 d6 u: I8 f+ F& R
{
% ?  a. P' a! H1 Q9 Y5 d    ULONG HeaderLength;
9 ]! o$ J1 d- z) }2 N    UCHAR Signature[8];$ Z6 U# ]- T5 y( k
   ULONG Timeout;
1 Z+ n6 h) q$ o5 j. ]6 V( B! r. q    ULONG ControlCode;: }" h  V* Y" j9 R
   ULONG ReturnCode;
. y% _3 c; `7 @; `5 g4 l    ULONG Length;
. C8 m: W6 g% U" P5 S% g8 {+ @}SRB_IO_CONTROL, *PSRB_IO_CONTROL;
6 Z' v+ m) d1 A: f: A9 B
& C3 u% G9 h. P; b! U// 读取的主函数
3 B8 N2 }$ q  f8 J$ i3 ?void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
5 f" ~+ K. H# z  P4 a" T2 f- Z' M$ E$ J5 i7 w( @3 H8 F
// 辅助函数+ U4 W5 {0 V/ Z, w$ b& v
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);  n; p6 J# z$ |) t8 m
// NT/2000/XP函数
2 X6 `$ u/ q8 N% Hvoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
  M: ^6 e0 O1 e4 j6 |) w5 ~( ?, ibool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,8 E8 ~& H& V1 ^3 V
       PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,: d  R1 ~. K+ c6 A  B  Y( j" W; k
       BYTE btDriveNum, PDWORD lpcbBYTEsReturned);) H2 ^8 Z+ f: v9 f1 S4 U) J
// Windows 9X函数
; L2 ^  ?8 S, f0 @5 j" w5 H8 xvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);
. o8 u+ m# ^! H" c, M4 pvoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,( w1 S* p  n8 t5 ~# T
       BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);! W* {# U! y$ R+ f6 C: c4 f$ d

8 S( T0 f1 s" u4 |// SCSI读取函数(for NT/2000/XP)" a8 N! r' u2 j! y- n; \! A
String __fastcall ReadIDEDriveAsScsiDriveOnNT();
+ }7 t6 D% j( ~//---------------------------------------------------------------------------
1 E/ Z/ |1 v2 K6 o( r, n2 @// ReadPhysicalDrive" Y& B8 k/ T& n+ G7 I. u
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList): i, n. U8 J% b; ~" G
{
5 R" B, r3 @& h5 S& y1 O! A* ^    switch(Win32Platform)- \/ ]% u* ]: u2 w% d6 j
   {
5 Y- p" t, }  N4 s5 z        case VER_PLATFORM_WIN32_WINDOWS:0 V! ^) S& N4 L/ B) t
           ReadPhysicalDriveOnW9X(pSerList, pModeList);0 D3 M; p+ d! a3 f
           break;- K4 Z. t. N% i: {9 K! s( q
       case VER_PLATFORM_WIN32_NT:
9 x/ m6 e8 G- d' G            ReadPhysicalDriveOnNT(pSerList, pModeList);
" H8 n  W9 V, e# e+ \            break;
! s3 T. D. D. Z8 m, V% _1 D* D- P        default:
) b9 z3 q& [4 j6 n+ D            break;
" D% ]! d1 d+ O; z  p$ G    }
' C6 R, a2 _8 r, {}3 g( u0 n& {5 P
//---------------------------------------------------------------------------0 v/ z) t& ?4 n4 t
// ConvertToString; Z& m, M: h! x6 i5 u5 r
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
/ Q- J- j( L4 k+ u. M! O: g( Z{
7 G: C& r+ [4 r0 h! c    static char szResBuf[1024];
9 p2 r3 t0 ~/ F% J7 Q' V    int nIndex = 0;
" ~7 \- p: Z7 s! P/ J; |' I6 G" W, s# J. y    int nPosition = 0;7 h3 }5 p- G1 @5 P3 n

* I& p5 s$ O! Y    // Each integer has two characters stored in it backwards) H! G: s: {$ V' ]6 J, k
   for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)% F2 \* y" A) R" B
   {: O, w; s/ Q: f
       // Get high BYTE for 1st character# U; p. {  k) N
       szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);$ J: v1 k1 U" c' X% A& x/ s
       nPosition++;
! L' n" w% o8 r6 U# Q" ~
% x: J& V5 [% s* F1 {        // Get low BYTE for 2nd character
& C* j' s' N) L7 i5 W8 ^4 m        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
) }1 o$ v9 F6 |! e1 a, l/ X* V3 W        nPosition++;
- u4 B" u/ E3 O; ]    }
$ S$ [& R, S# w' |% W% d0 H6 F, e+ o* ]6 f/ {
   // End the string
! I  X" T5 q) x. I" K7 z    szResBuf[nPosition] = '\0';7 Z! R* F0 k# K/ \2 p: W2 ?3 N

+ }9 Z- R6 h# x' \* M1 ?& a    // Cut off the trailing blanks
4 b; a! K/ W3 j$ g    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
6 Z, G. s2 A% x3 p. R7 a        szResBuf[nIndex] = '\0';
1 j7 a2 s, x7 v; h  C$ W* S6 M& I, ?5 Z) w* p  H# Q& n$ {' V( I. E
   return szResBuf;& s3 n# L! m4 ?" m3 i8 b" D8 [
}
3 z! M( N5 U' t" [  e7 t//---------------------------------------------------------------------------. }) x, X7 n" H/ R
// Winndows NT4/2000/XP 代码
$ g4 U2 S  u6 V8 }! ~' z1 B( q7 Q//---------------------------------------------------------------------------
7 b( C: A0 u- ^2 ~: D4 z; z1 b- M// ReadPhysicalDriveOnNT1 J4 f2 D' {/ e( A" |% A
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
4 ^6 q: {' x" V/ u( U! M. ~{
& d* H7 u" N5 F$ r; i3 p/ X    // 输出参数0 @& Y9 {! s  R! {0 n6 W
   BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];3 M0 M3 G6 k8 l/ G0 ~9 l: _

7 I$ E  R5 o1 H) {7 V    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
4 Q/ j: v2 C( ~    {
7 l8 f! g9 E4 O. V        HANDLE hPhysicalDriveIOCTL;' {& t6 f5 z4 [: S' b2 g$ r
       char szDriveName[32];
! L/ @6 h1 O, v7 {, [# s' U* r0 R  }& v9 Z/ }
       sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);9 L, y! G, _$ |5 {, k# J$ g
       hPhysicalDriveIOCTL = CreateFile(szDriveName,
' T* N$ ]# D. q/ U6 P                        GENERIC_READ | GENERIC_WRITE,
2 ?6 [% I7 ~  U5 `                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
5 `$ [) s; p  i/ p* h                        OPEN_EXISTING, 0, NULL);
5 d) i. M3 M# n6 z8 l- ^* F* b0 s& f" k2 t( \/ k. C5 G
       if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
* m& d# Y4 V! p( J. r, r        {9 C3 F" f3 o5 y2 f* [
           DWORD dwBytesReturned = 0;% ^  t- V+ F9 l2 ?
           GETVERSIONOUTPARAMS gvopVersionParams;
$ b) a5 L, p5 v4 S
" \( a) \4 w# C  z& T% U            // Get the version, etc of PhysicalDrive IOCTL
. y- A0 J8 ^) K) Z$ f            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
7 L. M4 b: d6 z- m: t0 O* M% z+ A
. r8 m5 I7 d; C% L2 J5 @, S0 G$ A            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,/ O" B( a, K1 v/ d2 Y2 D
                   NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),6 q& [3 |7 g6 k
                   &dwBytesReturned, NULL))
1 }9 X( |- \2 F. Q( Z( \$ j2 J            {* D  o4 ^) X% l! j; N5 C
               continue;
" }! h3 I1 _' A: ^            }
6 m. X0 i3 A0 {  Z% C2 K1 h! O& S! ]2 @6 q
           if(gvopVersionParams.bIDEDeviceMap > 0)
3 I+ c2 z6 ?) M+ P# s            {
3 I$ R# }4 X# o. F( D& W# a                // IDE or ATAPI IDENTIFY cmd* ^5 r. l; H2 n% z! f
               BYTE btIDCmd = 0;
3 s7 u. g( L! v  c# t                SENDCMDINPARAMS InParams;
* j5 Y! ]1 E; g' w% \. \+ v5 k                // Now, get the ID sector for all IDE devices in the system.6 }' H% m1 G$ p+ [' R8 h
               // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
# N  L2 O2 z1 _8 U" O' C& [) J                // otherwise use the IDE_ATA_IDENTIFY command, j0 V3 g/ L2 U. X7 K
               // 具体所得结果请参考头文件中的说明
' a' g% R. K$ ]& C# Z                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?/ t, f* x6 K$ ~( p; J# g8 B! u
                       IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
$ W, k" y! s$ }! c0 U; g                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));( s3 P7 w; P5 A$ J* k2 E5 \
               ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
! F& r4 e' D$ Q& |, b. i6 r+ W" k9 ?& T/ }9 ]6 \& y) z
               if(DoIdentify(hPhysicalDriveIOCTL,+ u& [( b: l6 Z% X. z+ }
                    &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
, o5 E! R  d& b& f                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
- [  t( D8 R' [5 v& M0 q1 K( Z                {
- n4 y( U! r5 l: i) ]                    DWORD dwDiskData[256];
1 Y9 b) |; G1 x( r0 {+ U                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件! X4 S4 Z( o; K2 q- m; `
                   char szSerialNumber[21];
7 p! {* g* u$ ~. Z6 l  [                    char szModelNumber[41];0 B% ^2 B5 t) B8 I. v& u0 ~

% R1 K( X. i: S1 y9 w- _* \5 K                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;) f1 F- z/ I# q$ F1 C% \
                   for(int i=0; i < 256; i++)
( z, F5 E! ^4 b( l" l, `                        dwDiskData = pIDSector;
2 b. _0 \9 B/ G6 B                    // 取系列号7 [+ \3 h4 R( e8 s: [
                   ZeroMemory(szSerialNumber, sizeof(szSerialNumber));! y; P2 h, @% b$ h. ]8 p- d& J
                   strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
. s0 b0 `, Y2 x$ T. r! w4 T5 L# G4 f% _3 c4 \6 x
                   // 取模型号: |/ |( X6 c) I# l" j# Y
                   ZeroMemory(szModelNumber, sizeof(szModelNumber));
* K; Q9 v1 Q9 t' U4 G                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
. }+ k" a4 x+ U& c( w7 [$ l# v, ]. I. B7 i% r- `" X- T8 ~
                   pSerList->Add(szSerialNumber);8 \0 X$ m& N7 L$ ?$ I: m* R
                   pModeList->Add(szModelNumber);
+ R& w3 ?. {4 S8 Y& j0 T: n                }* M4 W' j2 T# J. [3 Z8 P. M
           }
# q. Y% }# B7 F6 Y) ]            CloseHandle (hPhysicalDriveIOCTL);( w  Z: B2 q: |; V
       }
0 W+ ~6 o) y: k7 L) [    }8 V5 [7 p9 j5 a
}% U  s9 A# }4 y1 |. i5 S0 S
//---------------------------------------------------------------------------/ h9 z- r* A- F+ l( n+ x; \
// DoIdentify% a( m& t! W# \+ Y  i9 Y8 ^
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,5 A( R) F$ ]" J2 |' n/ i, S
             PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
0 T3 B" R/ }4 w$ ~8 F              PDWORD pdwBytesReturned)9 D" @" ~* J8 q. B3 V0 _; E
{
/ N* s; V* i9 y    // Set up data structures for IDENTIFY command.* }; R' _. f  Q) l( t
   pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
- j% \; R( N6 }# w  x3 u7 ?    pSCIP->irDriveRegs.bFeaturesReg = 0;3 [5 N4 t8 P- I2 B# D
   pSCIP->irDriveRegs.bSectorCountReg  = 1;
( p+ I) M! L2 Z/ g* C6 D7 B    pSCIP->irDriveRegs.bSectorNumberReg = 1;
8 E/ T1 Y0 T1 W5 B4 {" o    pSCIP->irDriveRegs.bCylLowReg  = 0;+ \4 `7 d, k: z( K" E0 |5 L+ n& R
   pSCIP->irDriveRegs.bCylHighReg = 0;
  E  S! j2 k! z5 |- U: r1 u+ v! B. {  T0 G  `; p) P% ?
   // Compute the drive number.(主盘和从盘所对应的值是不一样的)
% d" ^+ {! }2 P$ N6 Z    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;- v; j6 E2 r  j2 x

0 r7 p8 E: e& q6 d+ m  S+ V8 W) a    // The command can either be IDE identify or ATAPI identify.
% p) {. ~2 E5 G5 g/ R3 n, @% ]    pSCIP->irDriveRegs.bCommandReg = btIDCmd;
% [6 ]) F7 R2 g" |    pSCIP->bDriveNumber = btDriveNum;- X! m3 H1 D0 C5 u5 _! k
   pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;" l1 p+ A( P9 V* Z- k! Q5 y( A

7 t1 V  Z% n+ w2 h3 V    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
9 K( G4 t, g1 X0 g, e: v) G           (LPVOID)pSCIP,
5 P! I; s/ f6 I( p! p           sizeof(SENDCMDINPARAMS) - 1,/ P/ b! Z, [1 ?7 N0 f+ M
          (LPVOID)pSCOP,; n, t. O1 `  V; j! A
          sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,2 l. G% U, O" C* s3 B* G0 @
          pdwBytesReturned, NULL);8 n4 `5 y, s" ~# L& }5 g3 c
}
- K- I, v. |" `; W  ^: B' d$ R" ~1 s- a//---------------------------------------------------------------------------. Q! M  ^; O0 b' n
// Windows 95/98/ME 代码
1 G1 O5 }& R. S  t//---------------------------------------------------------------------------
% x7 T  K$ s) Z& S% N// ReadPhysicalDriveOnW9X
+ S8 U, s3 {+ Z+ ?. S# T! B$ Cvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)5 ]% Q5 ?8 u; x1 T  o
{
' v& q8 H5 Q8 N    WORD wOutData[256];
0 P  A2 x1 Z$ n4 y$ L    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
- m3 \+ U5 X; t+ Y
, I2 Z6 ^5 Y0 k1 ?    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
2 X' R( a. H- H2 d, `0 i' a7 c    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
4 l& x) H' o# g' K    // 避免蓝屏的出现。(期待高人能指出原因)  e  T5 `# Y" J( w
   for(int nDrive = 0; nDrive < 8; nDrive++)
2 P0 W$ E) b& S: c- E    {5 U% X: }! r  Z) w$ s0 T
       WORD dwBaseAddress;0 O3 d  E; k4 H; j
       BYTE btMasterSlave;         // Master Or Slave
  }6 I9 x: c* h5 n" g% a        bool bIsIDEExist;' P* O( R! k/ J
       bool IsDiskExist;
+ e" |3 j5 _" b  b8 V; f- O7 Y; L: v* Y# O4 ^( L% H, s" p
       switch(nDrive / 2)/ f* U/ n8 i* W3 _/ z
       {
) z7 w1 v$ Y0 Y2 A            case 0: dwBaseAddress = 0x01F0; break;5 ]  B, _( g* u: q/ `& N$ s+ R
           case 1: dwBaseAddress = 0x0170; break;* Q! V/ ^4 [* e1 ]8 B
           case 2: dwBaseAddress = 0x01E8; break;) M- a1 B. C4 |! ^
           case 3: dwBaseAddress = 0x0168; break;/ I' X2 ]! c; Z8 A2 E0 V
       }: C9 I. b- `( r/ y

/ J% _: l# P5 S$ V        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
  D5 _: {# g" R. t: h
. W) X, Y3 ?. W8 I2 y        // 进入Ring0
6 f: E7 c$ S+ h4 m: P& j        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,. Y3 l3 A3 S9 Q' A) f: w5 L
               bIsIDEExist, IsDiskExist, wOutData);
# y, ]3 n2 U. s5 i$ x. H. p    }( ?$ ?4 _2 I3 Z3 T7 B
+ L* M' @7 V) i& e+ f
   // 开始读取
7 r9 m4 k, t. U; i8 _3 m) W$ C    for(int nDrive = 0; nDrive < 8; nDrive++)
$ i+ V2 S# F" r8 y( ?    {$ Y' e1 W) S/ }- a
       WORD dwBaseAddress;' U; ]4 E3 |5 J+ w+ ]
       BYTE btMasterSlave;         // Master Or Slave8 Q: W' |8 j: h/ {$ a1 X
       bool bIsIDEExist;9 a6 l# a' |& f4 f+ P0 i
       bool bIsDiskExist;
6 B% X/ E  M( o* _0 K4 Q; \        switch(nDrive / 2)
4 @/ o6 o: ?6 h/ j        {$ O1 W) M5 U+ V8 H" X
           case 0: dwBaseAddress = 0x01F0; break;1 I& u& T; i0 F5 H( T
           case 1: dwBaseAddress = 0x0170; break;' Y' q& w* D! K
           case 2: dwBaseAddress = 0x01E8; break;" W$ w: M/ b" x0 x; P. A
           case 3: dwBaseAddress = 0x0168; break;
/ k, N! \) P9 M# @- W% X        }
2 A; o; `' E4 g9 Z
) E2 g0 w; U+ R3 S8 R1 ~        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
; @2 D' p& ~% N( v1 H. g. q  A6 G* h) T) M/ X, N
       // 进入Ring02 i8 F2 N3 M# v* Y+ h: Z
       bIsIDEExist  = false;
3 q. l: T7 W9 n& n        bIsDiskExist = false;
! i! h; M; E! \" H$ C3 [        ZeroMemory(wOutData, sizeof(wOutData));. }" x, b4 ^1 r" E7 X# f

- k3 G! j8 i8 t  z4 P        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
- j/ \) e: L7 T8 o- {4 ^4 l                bIsIDEExist, bIsDiskExist, wOutData);
: O* j  e0 J2 D5 d0 M3 C
, [: i2 \3 W; Y0 e0 P8 }: N: O        if(bIsIDEExist && bIsDiskExist)- U/ N( F  V; I" Q! y' O" Q
       {
1 G6 z3 @0 f8 n8 V$ L            DWORD dwDiskData[256];
+ x/ I  f  q. |; I1 h  p9 F6 b' z4 b            char  szSerialNumber[21];
" V$ D5 l- C( a% T4 K) E0 w# d* w            char  szModelNumber[41];
3 o6 F! I: }% p# j
" t- h% C4 A4 @' F9 I0 b- U/ r2 h            for(int k=0; k < 256; k++)
0 S' O- d& x7 S2 @- s# }3 [                dwDiskData[k] = wOutData[k];9 z  m3 q0 h1 L5 ?6 ~! E7 `3 D

) T, p4 k+ F8 h+ E3 B+ |: K            // 取系列号
6 [5 |6 N  [3 i. K            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));9 x7 N, S' b! |8 P; Y7 A3 y8 o* G
           strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
' ~* C$ y' T# |5 A1 m9 z9 A8 I' M- ^; R1 b8 w4 ~5 ]6 ^
           // 取模型号" ~; _$ q% U; T( N' z
           ZeroMemory(szModelNumber, sizeof(szModelNumber));
* N4 P4 R0 `% q* x; P+ T3 F            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));* B* M6 m8 K+ K

7 w' P1 `: k& O; T            pSerList->Add(szSerialNumber);, w) \3 z& x3 G* M' h( ]
           pModeList->Add(szModelNumber);# R$ J4 H- r$ G8 L* w
       }" ]4 J4 {- N$ I
   }3 ^4 r0 t$ {0 z1 u8 V: M! x
   SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
) K, x. I5 H: |* W}/ Z, l' v2 y0 G9 c/ ?9 r0 m- b
//---------------------------------------------------------------------------3 ^& J# T& N, u: O- I
// ReadPhysicalDriveOnW9X_Ring0()* {: T3 d; i5 g/ \% v' k& K6 t4 A
//
, \& y$ \6 G  F  H  s' E// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
$ m( x: _' g4 {- j# f9 G7 W. J// btMasterSlave = Master(0xA0) Or Slave(0xB0)- ?" P' ]- N7 O
//---------------------------------------------------------------------------
$ J7 v; F4 ~  V" T2 B& C* O$ hvoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
3 H  L% Q. q0 [        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
0 o' d) E# [- r7 r. E{) y0 n& i& i) a( H& b+ r9 b
   BYTE  btIDTR1[6];
1 ^! L) A5 Q  P8 y9 I& F    DWORD dwOldExceptionHook;
8 E' V6 l9 G% b% z$ s. K4 ~    const int nHookExceptionNo = 5;& e; a8 P7 \4 p& H! ]8 v

$ P6 D  }1 J3 @  Y; T3 t    BYTE  btIsIDEExist = 0;/ O. G9 p4 S/ U* A  e
   BYTE  btIsDiskExist = 0;# U0 ~, q% q6 q: l% u
   WORD  wOutDataBuf[256];
' j2 A  J3 Y7 `5 a, {! h
3 ?9 Q9 ?2 E' S% Z    BYTE  btIsFirst = (BYTE)bIsFirst;
5 i  f* T4 z/ x- J/ `$ E
; o3 o  g7 f0 d" Z    const BYTE btBit00 = 0x01;" @2 J, y* `/ x
   // const BYTE btBit02 = 0x04;: m2 c" c; N9 B- A$ e% W1 j
   const BYTE btBit06 = 0x40;) J; d$ C% v8 v0 \5 O$ v& I
   const BYTE btBit07 = 0x80;% f7 M- p2 j; f( ?( _4 d7 P" G2 b
   // const BYTE btERR  = btBit00;
: c9 K# g( Z2 e. L+ n1 F6 b  k    const BYTE btBusy = btBit07;$ F% j1 c1 q3 E
   const BYTE btAtaCmd   = 0xEC;
* s# r0 L/ `1 {/ P+ c$ H3 T' v    const BYTE btAtapiCmd = 0xA1;
( J  ^( A& x. }6 I) N8 @. n" f* r: B3 B# a# _6 }
   __asm
0 G* _0 P1 w) y    {
& h7 o9 M4 F# h0 w' |* b        // 必须先执行这条语句
7 K3 O# s& K: c; F) G' _( u        JMP EnterRing04 i: k% b  m$ W+ `

' Z4 d3 g8 C$ G) E        // 定义过程
1 f( m, E2 N9 a" ^, H        // 等待IDE设备直到其不为忙为止- w/ ^' S; n( z9 M9 k! D% e$ u
       WaitWhileBusy proc
* T. p  G. L9 C3 [  D3 W% v# ?* ^$ G8 I2 J6 e& W$ x  R3 @. C
       MOV  EBX, 100000
* q0 g( G6 G; V- W# p: u# T& N        MOV  DX, dwBaseAddress: w. X4 A3 ?6 ?4 Y& q4 |0 o1 R
       ADD  DX, 7
) V" K3 G2 Q) \8 h1 e( D7 F( P5 }) R- ]4 V. O
       LoopWhileBusy:: _# I8 g& j* L
5 T! S* a* F" Q$ b) B0 M) U
       DEC  EBX7 f7 {% h) y& K  k9 D
       CMP  EBX, 0
- q* z1 [  z( f        JZ   Timeout8 m( f$ ]6 w0 H) p% [
       in   AL, DX: Q7 b$ G1 p9 A0 T. ]
       TEST AL, btBusy  T' g+ W- y9 f" `0 c; p
       JNZ  LoopWhileBusy0 ]' P4 T$ B& \, c6 i% ~! ]
       JMP  DriveReady
% q3 u( a" V1 y) L
, n. G: a* L7 L7 j        // 超时,直接退出
6 G# t: h$ ]" Z; e* S' ~        Timeout:
# u* L4 G- P5 g- }% G: Y        JMP  LeaveRing0
3 _2 }2 g9 l- S# P7 `        DriveReady:
' B7 _: e6 s+ [        RET( N+ F0 ^5 w$ g' Z
       ENDP   // End of WaitWhileBusy Procedure7 t. v; b% k0 c1 }; S1 ^: i$ f

: a  a" \" Q+ \        // 设置主盘和从盘标志
6 @4 O, N3 X' e' `( V# a, z        SelectDevice proc
3 D4 R' S- f! l( p+ }  ~& ?8 Q# y; z4 N$ Z" x% W( h8 w
       MOV  DX, dwBaseAddress
4 m+ Q+ H2 z' y! l        ADD  DX, 6
, G: E+ P- f8 I" T! y        MOV  AL, btMasterSlave
+ q$ C/ z9 m7 s0 l, C# j* E6 \) Z4 r6 U; M
       out  DX, AL; y6 i3 r# G- w. S- ]0 I6 ~: b! [0 H  t
       RET: d0 a0 Q2 G; R& T& Z8 y
0 {& k# ]* d  g7 E# w5 i3 O
       ENDP  // End of SelectDevice Procedure
1 M( L; b: K( i5 {- ]5 w- m2 g+ j) F
       // 向IDE设备发送存取指令
- c& m8 @1 M1 Z% |        SendCmd proc
9 `3 ~3 ]# [8 n, N' ^6 q' @
: ~8 ]! t  Q) H3 H        MOV DX, dwBaseAddress/ z2 I/ L) |! l& j( _
       ADD DX, 7! B: H# a+ X# k5 ^
       MOV AL, BL // BL是主从盘标识,在过程外设置& B" U8 l2 K9 w0 O9 a
       out DX, AL: u( [: r2 d& D" z8 Q
       RET, j6 A; E) j+ U' ?9 S" B/ x
       ENDP  // End of SendCmd Procedure
1 N6 X: i1 G6 l. Y
5 q- Z+ w' C. \        // Ring0代码
  B, {& G. q% l' T+ t, y6 a        Ring0Proc:
1 P$ {; Z8 T( o/ E5 U# a        PUSHAD  G: H# a# G) L: v5 W* n
       // 查询IDE设备是否存在
$ n/ m4 A4 W$ T, x% @( D0 N        MOV DX, dwBaseAddress
/ l9 r( s; t/ l' R/ C        ADD DX, 7$ H% E' k# [& `5 r7 }% S9 Z* K5 z& m/ P
       in  AL,DX0 Q, R  y! o1 Q$ T0 c. e) @
. H+ Z4 M7 |" O
       // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回/ r% _4 Q& a! f% [0 A
       CMP AL,0xFF" m- Y* Q- N3 Z4 x$ a/ n3 D: ?9 n# Y6 }
       JZ  LeaveRing0% l" a4 m* F$ W! g. |* C
       CMP AL, 0x7F1 [( C" S6 Z6 N0 Y
       JZ  LeaveRing0
! [9 J* V4 c1 f1 v8 S
1 _$ _7 f7 c- z        // 设置IDE设备存在标志
# J8 P! n  D9 |" s        MOV btIsIDEExist, 1
( q7 ?! [3 p' X3 h0 x% u7 M. f  Q! t/ L  Z( p% C/ t9 q3 V2 b
       // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
- n3 V7 g7 v1 R7 T& T        CALL WaitWhileBusy
  K; r/ F. g# _6 P        CALL SelectDevice
3 a2 R; o+ }' ]6 N; [
- I1 ?( L8 I: c7 q; J6 }        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏9 |: E5 Z2 i6 M' }/ @
       CMP  btIsFirst, 1
! c5 I3 u, b# e        JZ   LeaveRing0" ?, d" N6 u9 x: m% P4 b) s

5 A. c/ B9 [' S# ]4 K6 J        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???* `7 Q, Q  H4 v! {! \
       CALL WaitWhileBusy5 ^* h/ `# d& u3 g- N0 v4 n/ n6 ~
5 f. o/ H- H, ?4 i$ s9 _
       // AL的值等于cBit06时,不存在驱动器,直接返回2 X/ z& D6 k% `
       TEST AL, btBit06
( @2 c: s, n! P" ~        JZ   LeaveRing0
' D1 p0 A1 e) B
% r+ G. D* m. B8 S- J, e        // 设置驱动器存在标志
3 Q# R; @0 E+ U% F1 p) a% J! B0 Y        MOV  btIsDiskExist, 10 Q+ [! S+ ~; r- J$ ]
  x  q# d7 i/ Y
       // 发送存取端口命令
  f9 d. I* y  S/ m        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,* }9 C* y! ]4 q1 n9 C
       // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
6 J5 O- w$ z0 ^8 ]4 y, ?0 e+ n5 o        CALL WaitWhileBusy/ v% J2 g: \" n  w2 c0 N' b
       CALL SelectDevice    // 设置主从盘标识2 Y5 Q5 e2 f/ w& W
       MOV  BL, btAtaCmd      // 发送读取命令7 e/ z) \* a% U# n  c4 B- N
       CALL SendCmd
2 ?$ P) [. m: `. K' f- C        CALL WaitWhileBusy3 d9 \7 t. d% y/ g/ @3 z

0 X# {7 W* s. d: N& |# b        // 检查是否出错
! F4 z, M% C( a7 ?( T        MOV  DX, dwBaseAddress
: _% U; u) F9 X- i" g& s        ADD  DX, 7
# D' E0 _* Y" @- f' g( [2 d
# `( Y6 a# r/ M        in   AL, DX. W) G* D* ], G2 \( c$ p! x
3 |0 {- n& b5 C& {1 k  r1 W( N9 r
       TEST AL, btBit00
; B) P2 m; ?. \0 J. Q. S& M5 d. o8 c3 g        JZ   RetrieveInfo   // 没有错误时则读数据6 t! h$ i3 t0 |0 z+ X/ e

0 k6 j& s) Q, i. C9 ^        // 如果出错,则进一步尝试使用ATAPI设备命令0 I0 H8 {6 D& Z4 f5 D2 z0 j) R
       CALL WaitWhileBusy
; L, y+ A$ I0 [9 Q6 q# @        CALL SelectDevice
; }% a4 ~2 D# y# [3 o( s$ f5 a        MOV  BL, btAtapiCmd& Z3 V2 f0 P- q
       CALL SendCmd6 G6 N" J8 g- z
       CALL WaitWhileBusy
% K# l( k) c5 ~( g3 _) q$ z5 I4 L8 \' V
       // 检查是否还出错
, {9 |! E6 i3 T5 d. Z        MOV  DX, dwBaseAddress* l3 E+ M* `# h; h% d, o# }" X
       ADD  DX, 7
0 h' w& _' _) ?# ~' V0 E, [        in   AL, DX. u8 {3 u, M3 Q- e- e5 L6 l
       TEST AL, btBit00# \' s8 O/ ^- K
       JZ   RetrieveInfo   // 没有错误时则读数据, w' b2 n$ S; D* z/ A5 _' W* q& r
       JMP  LeaveRing0     // 如果还是出错,直接返回
9 u+ Y! T  d9 b5 C& B6 N+ E/ i& ~7 I0 p9 [/ l9 d9 W; A4 H- l9 l: o
       // 读取数据/ v* S( l3 _  z, h
       RetrieveInfo:+ o% T% D' t: q  o
8 x" Y' Q/ s( N1 p5 z
       LEA  EDI, wOutDataBuf
4 L5 ]& ^3 V2 ~, ~) v        MOV  ECX, 256+ X9 s; U+ ]+ h, x
       MOV  DX, dwBaseAddress
2 @; t, I- D' x0 }6 ?  A( m        CLD
5 y- S* N0 s9 P/ o+ G& \4 Q4 u& I, \3 o  s+ r6 |- e: O
       REP  INSW( H% b* A' K' W- \+ r

5 G- y+ ^% [% W, B; J        // 退出Ring0代码, v( W- s2 q; \" a& |" G
       LeaveRing0:
! t$ I6 k3 r: M5 t* J" }+ C/ L$ [* H) ^
       POPAD, P- u; |  d4 W' c# G
       IRETD7 T( q2 m; J" R1 X
+ E. f  X& f: Z
       // 激活Ring0代码2 e; Q8 u3 n& q8 y& P
       EnterRing0:
* g/ f) e. t5 a3 @
; G& Y# ~. F5 b9 X5 C5 L        // 修改中断门
9 {2 i* S, F  Z# h, {; h        SIDT FWORD PTR btIDTR1$ U" [; g" ^' ?* w' {% [2 j* `% @' t
       MOV EAX, DWORD PTR btIDTR1 + 02h
# w) F" ?3 k9 Q2 h        ADD EAX, nHookExceptionNo * 08h + 04h5 w6 y  f7 O% K' O: z. I
       CLI
2 F' i9 \+ L5 P
0 K9 R" L2 \/ e5 I        // 保存原异常处理例程入口' Y/ D. H) ~2 ?/ X* R
       MOV ECX, DWORD PTR [EAX]
2 N0 e! ?7 w9 w. A  c3 H6 J& N        MOV CX, WORD PTR [EAX-04h]
& w) i& a: G! M, \9 O        MOV dwOldExceptionHook, ECX
8 {8 l7 n0 U8 k4 x1 D5 H
( M2 R1 d! b+ y; i4 l        // 指定新入口
( k. |, E, r  `8 v) p1 R# b" e; _9 x        LEA EBX, Ring0Proc
* e/ _. ^  j& r5 {) `        MOV WORD PTR [EAX-04h],BX
# q( p5 z5 f6 H% E7 o        SHR EBX, 10h$ Z9 J! L- m# x# t. V3 R  K1 L" h
       MOV WORD PTR[EAX+02h], BX. O0 C+ Q, a" j! U( P: P

3 A6 P+ I; ^8 }6 k0 ]& B        // 激活Ring0代码
. o1 x4 D; B" d        INT nHookExceptionNo
- i0 [& c0 M! A6 |* E+ \/ [% V$ u  J: |# ]/ V  O. J8 K+ \
       // 复原入口1 h. j) K3 r+ s& \0 Y" y
       MOV ECX,dwOldExceptionHook4 N  w' I# G6 _: u9 V" o0 r
       MOV WORD PTR[EAX-04h], CX
3 I' |# i- f* j% G/ ]6 V        SHR ECX,10h
, G) d- |9 H' T+ v' u        MOV WORD PTR[EAX+02h], CX
, ~0 m7 C4 _) }9 t        STI; M1 m! U' w9 P7 I8 m% [( M+ e$ @
   }
; ~) f* x$ Q3 x/ f* {" ?$ d. W    if(!bIsFirst)
# G; {$ k& ?  }# D$ L    {
2 @  L4 f4 f+ P+ i        bIsIDEExist  = (bool)btIsIDEExist;
" }+ F/ Z; a- D6 x* l        bIsDiskExist = (bool)btIsDiskExist;
9 e: N. v* ^( [2 G5 U/ @9 P        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));7 Z( s$ H4 c2 x0 L4 \
   }4 {+ H4 O" c' G. Y) F; Q8 Q
}& f3 i1 e- o) t/ p  |# B+ {
//---------------------------------------------------------------------------/ Z* P) D& c5 ~, O7 m5 {' R
// 调用方法:
& D. r+ W* Y7 r% s- dvoid __fastcall TForm1::Button1Click(TObject *Sender)
; v6 h+ J  L- Y# R; |{3 C# v6 H) z" C5 v
   ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);1 N9 W* d. F8 D! _
}
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

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

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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