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

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

[复制链接]
发表于 2005-5-30 19:22:36 | 显示全部楼层 |阅读模式
  #include <WinIOCtl.h>
, u3 u' O' z- `( p- N2 s#include <stdio.h>, T; `% B7 Q/ u/ {
* H; z% h! I8 E" W( Z
#pragma inline9 W3 s0 L9 W8 F% }7 L' x# Q8 M+ d
//---------------------------------------------------------------------------
. p4 w1 H: r! N; V2 ]// IDE NT/2000/XP专用变量
4 y' V' g" v1 q  d& M: ?#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS; w( [; C4 v5 f: l1 {
#define DFP_GET_VERSION         SMART_GET_VERSION
4 V+ T& C/ m% M% q, w. }7 p#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND  ?+ A. u& L! c* V5 H% M7 N. l
#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA# c% p9 ~3 c* t7 W% A! D

! _9 A& r' w( l- h  N1 Oconst WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令% c1 [0 U8 ?# s, L+ X# I0 k, g
const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
+ |9 r2 j0 W: \4 z7 \! }* c: c+ @# Z- W/ x" K6 P8 e! _& W6 Z
const int MAX_IDE_DRIVES = 4;
* R" p8 ^9 f! Y! g! y1 e
) V! ^. s' h8 V4 C& ^4 o/ R! z// SCSI专用变量
* N9 }: x$ @7 V) i% {0 U  Dconst DWORD FILE_DEVICE_SCSI             = 0x0000001B;
: p6 b3 {! j) ]$ V  o8 Hconst DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
0 b# |; v2 X: O$ vconst DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition; j" ?. A* b" Q' x0 A2 @
const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;. l8 O3 X1 H0 \  U2 U6 f
. b7 `+ Y! g: |  G8 i3 Q
typedef struct _SRB_IO_CONTROL
$ v4 V' f9 T3 s{' v% `1 U1 w. S7 d0 J5 v/ Z1 a
   ULONG HeaderLength;% x5 x2 g: A4 X8 F1 F3 N
   UCHAR Signature[8];
1 Z# w& H" m3 K6 k    ULONG Timeout;
% P' \0 j1 c0 O" G    ULONG ControlCode;
: B, H/ b9 p/ Y" u    ULONG ReturnCode;
# M  X1 T( @: a+ ]    ULONG Length;- s4 y6 O; ?& E  G
}SRB_IO_CONTROL, *PSRB_IO_CONTROL;
! e) I5 u8 Q. P% x; B3 W# v" m; I
7 A. D. H( {  ~4 {+ A9 \5 \// 读取的主函数
/ Z) G  \% @. {  D( Q& Jvoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
# H: X" A; B' a4 o$ k$ i2 w6 z7 I! W* Q+ U. Z  a
// 辅助函数. U" d; X! t  n& D, G
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
3 j7 _# M, z$ b2 \; e( z7 r// NT/2000/XP函数. E! D1 ^' }1 g0 T- b  V6 V3 F
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
; Q$ r! F; O1 X1 H% z& Ibool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,0 E. k. ^# {5 c5 w* {5 U# |% ?! s
       PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,, _5 ^' J4 z6 F
       BYTE btDriveNum, PDWORD lpcbBYTEsReturned);" e8 u& \7 y! I. C$ K
// Windows 9X函数8 \; ^6 z" |3 X& D
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);
& N2 g# P/ v6 u% t) Xvoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
+ X( m, S( D8 ?% ?0 _  ~: k        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);* p; ?& J( u. A2 O0 Y9 J: n
; r3 f1 n2 E# ^) f, C1 @1 U
// SCSI读取函数(for NT/2000/XP)5 i5 T2 i. e' ?7 ^; K* R
String __fastcall ReadIDEDriveAsScsiDriveOnNT();
* N+ a0 J2 c3 @//---------------------------------------------------------------------------
0 @" s: [% }9 ^4 H. Y// ReadPhysicalDrive
( n2 b$ x: b1 G5 X% {9 cvoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)5 y1 u. s8 j% n! u( P
{
( M) f# J8 d; ^% E    switch(Win32Platform)
  E+ f9 n' u7 g2 c% ^    {9 x3 ?3 ^; B2 i# D2 k9 h9 v. v
       case VER_PLATFORM_WIN32_WINDOWS:
+ N# k/ g6 F' v3 q            ReadPhysicalDriveOnW9X(pSerList, pModeList);
4 d- B/ ^9 O& \3 l+ b* p            break;. d8 K) ~% b6 n8 |/ ]! f, H
       case VER_PLATFORM_WIN32_NT:
* c  E8 @& g) C' P0 n& }3 P# H            ReadPhysicalDriveOnNT(pSerList, pModeList);
3 r/ ]+ d) ^  g8 |: g/ c+ k            break;. G! X. x# r+ t
       default:
* l0 o% I( e  {- J" Q! k: s            break;9 D  p% W6 T! N" I! W: p
   }
4 j0 }3 q7 n7 c$ M}
& H% T. v& p3 ]//---------------------------------------------------------------------------
! i! j- g& E4 d7 N& P// ConvertToString
( w% \0 o- u, V3 b/ Z6 e/ @: Y" Tchar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
: _" {) x7 k5 B/ }- k+ D/ q{
& S: E  O& Y7 j2 ]    static char szResBuf[1024];
. {8 L% [( n8 b- V' E    int nIndex = 0;# l- T  x4 m( D" Q
   int nPosition = 0;
" E% A! r7 l/ K5 r9 K% G8 _1 w  e& d0 H. d: s
   // Each integer has two characters stored in it backwards3 \% z0 g3 T, h: a4 [1 c
   for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)4 _3 x8 P; {  L. B
   {; x7 c! V0 f3 {# v
       // Get high BYTE for 1st character
% G. J  B& J5 s        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
: \4 ^' E, R9 E5 L0 b9 K% L        nPosition++;
9 U+ @! Q8 ]- I' R. d5 p
, c5 C% b. C5 y: R; g3 W2 c        // Get low BYTE for 2nd character8 A- W  H' Y4 V0 E) _+ d" v3 M- q# I
       szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);7 q2 H+ ?6 k; J1 }
       nPosition++;0 w, A: t6 e# E7 j5 @- ?6 D
   }* b" D$ o$ x8 u0 H. n

" J1 c  M) @; z" R6 l    // End the string
& j  P0 ^& E; t4 v! p    szResBuf[nPosition] = '\0';- B9 C" s3 Q+ Q# H, K

8 D9 v" X& a1 r- @% G7 E    // Cut off the trailing blanks
" [- {! K# }& }6 J* j0 i! D    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)4 s8 |9 y4 E) l3 p
       szResBuf[nIndex] = '\0';2 p, f, @6 f6 q+ z1 O- g  x

3 P5 K+ l" P8 N$ ?1 ^    return szResBuf;  I( j( l, \7 p3 L" H( s; p' K6 _" c
}" U7 f. h! _& m3 J; w+ D
//---------------------------------------------------------------------------0 a; z4 x" T4 `6 s( a8 I
// Winndows NT4/2000/XP 代码
3 Y; D- E+ P8 P//---------------------------------------------------------------------------+ Y7 ~1 e" P4 _, e5 P; J( o  P
// ReadPhysicalDriveOnNT$ |9 k+ N7 d# K, Z! Q1 ^/ P
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
: p2 R  b: S  ?7 F! i- T' R{8 E) Z5 O1 c* }( {1 O+ P' m
   // 输出参数
  v4 O! w5 @) {& z1 V# N    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];; R. @+ [9 A8 ]4 P, J
- L0 N7 p" Q! z: I" ^& o
   for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)3 n  o9 ^  s, n
   {  e6 v$ L, X. W9 Q$ @
       HANDLE hPhysicalDriveIOCTL;
6 R2 t! @; R( \+ X" i9 T" T& x        char szDriveName[32];
% m. K* w' p' \7 s5 ]( }5 K# `
' ~% t, B: T; F        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);0 B6 u1 q7 U2 X' A  s
       hPhysicalDriveIOCTL = CreateFile(szDriveName,8 J: U( \$ s* m
                       GENERIC_READ | GENERIC_WRITE,* @  Y- O' S5 X! N% h# j
                       FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
1 K+ y1 J5 P! v, |* u                        OPEN_EXISTING, 0, NULL);; o8 ~- u5 z3 U1 N( d
6 m" y5 @) }* `& U, i
       if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)5 c2 h2 @; m% O  b# ?1 }
       {7 ^! Z' e$ z$ q8 ~
           DWORD dwBytesReturned = 0;2 o( U9 J2 ~, v  X# H& t- L
           GETVERSIONOUTPARAMS gvopVersionParams;8 N  `& M* F: \( s7 X. t

8 y. `0 T, w/ C            // Get the version, etc of PhysicalDrive IOCTL4 x  M! T* p* i( j6 S# b
           ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));- [( e6 l' d2 g0 G& e+ \
3 F! a2 _0 z# j8 ?/ V: I
           if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,  ]. p: C" T1 X9 @
                   NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),$ }5 n1 v5 N/ Y( U3 \
                   &dwBytesReturned, NULL))5 W* {  n, \& |' E4 h
           {8 R$ ?- o5 n  U0 i2 [+ Z
               continue;
) s/ E$ q$ t# S* c/ o            }7 W$ v5 D) o  b9 q+ F) F* C" P  X/ e
5 O, |) C( k7 m/ f5 J/ h' s4 l
           if(gvopVersionParams.bIDEDeviceMap > 0)
' J: J4 r/ J1 o$ _1 \( R% f            {6 q! L6 q6 ~5 y8 B# \2 H4 \
               // IDE or ATAPI IDENTIFY cmd
* H$ L+ [3 r4 _, G5 M                BYTE btIDCmd = 0;" E* g% q* v( P& N0 E
               SENDCMDINPARAMS InParams;0 g5 U* D* m0 Q
               // Now, get the ID sector for all IDE devices in the system.
  @$ q0 N3 S' W' a4 j/ ~                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
% d' P. m; d8 I* h9 M& w  F                // otherwise use the IDE_ATA_IDENTIFY command
+ T2 Q" Z& P" C5 O# i  Q                // 具体所得结果请参考头文件中的说明9 }' `9 C! g7 A- r
               btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
9 N+ O4 b6 E+ W/ |                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
- G6 ^- S0 h" T                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));9 j: x$ J/ n  F; Z$ t
               ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));( R, K9 A1 ?( l1 c# o( ?8 u

: U! h( A8 G6 K0 V! g, ~7 x                if(DoIdentify(hPhysicalDriveIOCTL,
' M0 A' r3 `: r( C7 y4 |5 D; S  ]                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,0 X# R( ^2 Q5 c) m7 K
                    (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))3 ]8 ~( s0 _+ O
               {; d& p  C+ z( M5 t' v! g+ c9 t# s
                   DWORD dwDiskData[256];
0 U. a  N, ~  _                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
' O7 ^* R% D$ h3 f" J# H+ Y                    char szSerialNumber[21];5 X# \/ t- E! Z/ M- b  d1 b
                   char szModelNumber[41];# E1 V. b* f3 H! v' d, A  h
9 `5 J) L4 Y8 |+ v2 z6 K7 S! M
                   pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
3 z6 W: k/ g+ D8 d1 l6 o                    for(int i=0; i < 256; i++); u9 b& R% t% k/ U7 R/ l
                       dwDiskData = pIDSector;
3 H% a  D, ~: c/ {3 t% g0 `7 b                    // 取系列号7 \1 F6 z' a2 Z* J2 j0 {
                   ZeroMemory(szSerialNumber, sizeof(szSerialNumber));$ r# ?# w1 I2 T  a
                   strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));9 A+ b4 A: q9 F2 `! \# B
1 I% g) n" h, W% U# C  i' ^
                   // 取模型号# a8 q, Z# ?) C* N% m
                   ZeroMemory(szModelNumber, sizeof(szModelNumber));
$ b+ m, y7 Y; @: Q% t                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));7 }" }. F8 p0 {4 O. _  d
% S% U5 R$ J2 z8 |2 k
                   pSerList->Add(szSerialNumber);
3 O2 C) s/ e8 x) ]3 f                    pModeList->Add(szModelNumber);
, q  N  S2 n/ R2 `( C8 l& h                }
+ a4 w) R6 n4 Z/ D, J            }
  E! X" R6 d$ S- J$ ]+ K            CloseHandle (hPhysicalDriveIOCTL);! m7 E" o5 l' q- N
       }
% S) k0 X* ?' U/ u    }' u" n+ s6 i: E5 _" D* ^9 O. }
}
+ _) N8 Q: m, N) u. o. _: }# Z//---------------------------------------------------------------------------/ ~' C1 Z) I2 F( h
// DoIdentify9 M1 y  o, O) Z8 m5 k1 e6 D
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,4 p& g. ~& g  r. i, U7 e5 a
             PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
/ v; h) B2 L" |) l7 Q  F( }, {0 a              PDWORD pdwBytesReturned)
8 X  `6 ~0 i  e, X* T& g5 O8 Z, F{
& K+ E' ]: e4 f7 X$ c  _" ?) q    // Set up data structures for IDENTIFY command.
5 \0 y8 V8 D9 o2 h$ {% Q# `    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;3 }3 G/ S- n! A$ p; l, i4 n2 G
   pSCIP->irDriveRegs.bFeaturesReg = 0;9 i1 s9 j, R# [% D/ X
   pSCIP->irDriveRegs.bSectorCountReg  = 1;
) d" E& w' J6 ]0 O. K- L2 f    pSCIP->irDriveRegs.bSectorNumberReg = 1;
' G. Z- h7 w% N% |) d; q( x; y# D+ n    pSCIP->irDriveRegs.bCylLowReg  = 0;
9 y  P6 `: \4 q- ~' w    pSCIP->irDriveRegs.bCylHighReg = 0;
0 l& k, J7 U) P: l. I1 Y- Z: R. a+ _, ]; G- K, a
   // Compute the drive number.(主盘和从盘所对应的值是不一样的)
" }0 Y; Y7 o9 a& H    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;* k( ?; X% j, u9 Q, J4 J* R
! W# ^$ ~) D% |9 ^# s5 W0 z* _3 e8 w3 P
   // The command can either be IDE identify or ATAPI identify.- v, a0 A1 m9 H" ?, K
   pSCIP->irDriveRegs.bCommandReg = btIDCmd;
1 @) d4 l$ a8 Q' c. w4 }    pSCIP->bDriveNumber = btDriveNum;0 U. H* C8 O7 A
   pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;( g1 D6 _& @- Q

! m: \& Z1 j2 _+ Q9 |: o' Z    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
5 g/ q7 w: `4 q' ~- J+ P           (LPVOID)pSCIP,8 Z8 d- u" ^& l5 w3 P. Q
          sizeof(SENDCMDINPARAMS) - 1,/ m& i! v' f$ [% X5 {
          (LPVOID)pSCOP,
" r+ a" _3 N- x( \, G, F           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,, p4 n! W, F$ y3 |
          pdwBytesReturned, NULL);
* R6 d3 E& i7 r, C, O9 f" b  L7 m- q}
! D7 B! E; P+ ~4 s/ ~. h7 [2 _( D//---------------------------------------------------------------------------5 X# V3 Z  E9 N4 S
// Windows 95/98/ME 代码+ k" I/ R) U* E/ q6 t' b3 ], q! ?9 p
//---------------------------------------------------------------------------: I( J8 s+ d  B+ ?0 `+ k
// ReadPhysicalDriveOnW9X
+ Z$ y0 M# Q/ K, e8 p  }void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)
  m2 d, y( C' x. w{* L4 m; y, M" S
   WORD wOutData[256];8 Z% w5 [3 |. {9 u7 z/ g
   SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);& g4 G$ y2 H+ l

) {- Y, X" d7 y) i+ g3 A    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
9 v0 Z& \7 t* Q    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
1 m( Q1 I7 Y2 v6 D. H" C8 Y    // 避免蓝屏的出现。(期待高人能指出原因); P, ?* B% u8 ]/ S) v1 _
   for(int nDrive = 0; nDrive < 8; nDrive++)
& u- Q" s! G/ F* D    {
( C2 E( y4 T, i+ Q        WORD dwBaseAddress;. R$ ^  H  h6 ^" R& U9 B
       BYTE btMasterSlave;         // Master Or Slave2 M. p- C3 B" z
       bool bIsIDEExist;! R! t! t+ s3 g  Q: b0 H
       bool IsDiskExist;
9 c2 s# e) }! V
& ^7 q  u3 S4 C9 ?' O  g, t        switch(nDrive / 2)/ s' w$ ]6 V( K( Z8 \" B
       {- C9 a+ X$ ]  U. ~9 J
           case 0: dwBaseAddress = 0x01F0; break;7 @/ b- g1 a; x6 D
           case 1: dwBaseAddress = 0x0170; break;
) h2 u7 f- p- t. ~& o3 w: u) k            case 2: dwBaseAddress = 0x01E8; break;
1 v; F: `* `/ l2 a$ b: |! }, h! E/ M0 P            case 3: dwBaseAddress = 0x0168; break;5 N4 X8 g" l5 _5 x
       }+ }2 l3 \4 H* k# q

2 S1 i# s3 }* `) h" H" H4 x        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);4 L0 o3 B% o; H" m  r

0 x7 k  N# T$ [7 `7 o        // 进入Ring0% g5 C3 Q: l: f1 G6 @1 t
       ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
8 o) p5 c3 h) T! V6 q. q                bIsIDEExist, IsDiskExist, wOutData);
! k9 U. S4 r" ^( r    }. w) l2 N1 _, j8 l+ E/ i
+ d8 w9 |1 O! Y6 C" n4 w
   // 开始读取8 r& U  E9 Z/ e- X* t
   for(int nDrive = 0; nDrive < 8; nDrive++)
( l7 y7 i, l2 R+ o! i; T9 K3 h    {
0 k- c( V2 b, w0 O$ r5 |2 @! H0 C) e        WORD dwBaseAddress;5 s# k/ x. [3 P) K, c0 h! J' o( E: N
       BYTE btMasterSlave;         // Master Or Slave
2 H- {2 C7 g+ s: \        bool bIsIDEExist;
  @) a- |/ U! `7 r        bool bIsDiskExist;, p$ h9 t2 s7 x8 g% Q/ U& W  h. [
       switch(nDrive / 2)
# x& Z: \* |9 A4 U        {4 U! L9 b3 H/ e2 I; Z" _
           case 0: dwBaseAddress = 0x01F0; break;9 T5 v" w& s. ~% U6 A, s
           case 1: dwBaseAddress = 0x0170; break;
! C3 o( L' o$ j, ^& c' M' c            case 2: dwBaseAddress = 0x01E8; break;( t4 }2 a# ?; B6 @" h+ c2 w8 J
           case 3: dwBaseAddress = 0x0168; break;
! K# q9 U9 _. O- X; s& ?' J0 z( E2 m        }
0 W; l& O( e  L+ D( U( f5 |1 G0 y2 ?7 p/ k% T! T9 a, K2 \4 d
       btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
5 @* E: \- m% W8 h- j/ u
  l- m6 C0 ]) C        // 进入Ring0
- c4 T, a# L4 l        bIsIDEExist  = false;
- U( ~( U. ?- Q1 w# \# g        bIsDiskExist = false;
" A% _) J; O9 p2 C/ Y0 e        ZeroMemory(wOutData, sizeof(wOutData));
, s" p: k: Z, d
1 @& N2 y# v: e3 P2 c; b        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
1 Z* t& n# O% C; g2 |& C                bIsIDEExist, bIsDiskExist, wOutData);
" b/ V5 F' ?/ ^$ ?2 c  O( V% I# h, R
       if(bIsIDEExist && bIsDiskExist)
! k7 ]; _$ X9 x0 t; J        {% ~  M# W* B+ S
           DWORD dwDiskData[256];: |4 P) j; Y/ l9 T7 o
           char  szSerialNumber[21];+ G. F& d; y. z! d& @: L( m
           char  szModelNumber[41];% P) P8 \2 c5 {% }, q1 r& i: P

5 I& L4 g4 n& C+ F( k. A            for(int k=0; k < 256; k++)
" S- `) E6 k3 o. x! f) y- a                dwDiskData[k] = wOutData[k];1 u) L( x; e4 {- |

( Q% T+ `2 j( g            // 取系列号
5 S) f2 b- i$ |1 Z$ Z. r* ~8 ~+ o1 Q            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));2 k# M; X  A# c% |4 U
           strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));9 s+ }/ B3 S0 [/ w  W4 s

7 Y1 o0 X3 H0 o' B            // 取模型号
4 j1 w  a% {0 ]( n1 u* o5 G) S! K            ZeroMemory(szModelNumber, sizeof(szModelNumber));
8 h8 X; _6 `  R/ T/ f            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));* o) Z! Q! U6 p& D. c

. l" V' E) O5 i" C3 ?, E            pSerList->Add(szSerialNumber);0 Z5 m. h0 S( r6 F# k
           pModeList->Add(szModelNumber);
# j( w4 V3 H& W- @" ^        }
/ }4 y) z" E8 K8 t. O    }
# |/ d1 ]  e) E9 V) u    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
7 j: {! _. _1 Y}/ q$ f+ i1 v5 W! B
//---------------------------------------------------------------------------
. g8 H, o& ?% ?' A' _// ReadPhysicalDriveOnW9X_Ring0()
, N: e/ T5 D5 A9 q. F! Y: t; P//# A! I1 {7 }; g3 x% w% s
// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h8 @, g; d5 f1 S  Q. n, ^# d7 o: w# v0 P. `
// btMasterSlave = Master(0xA0) Or Slave(0xB0)( h6 i; J% R( d6 o: _
//---------------------------------------------------------------------------. @  v. c) g# r
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,: j+ z7 C  X8 @4 R$ R
       BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
1 h- C& C, b8 \% c  R5 g' H; ^3 e{: c  v8 |0 J+ @
   BYTE  btIDTR1[6];$ K$ y$ p& f, E7 ~0 [1 j7 e
   DWORD dwOldExceptionHook;
6 h" r- U  t+ Y$ j6 g: }    const int nHookExceptionNo = 5;0 H. n* ]' R  t6 M( U* u
; O( A  d( y& i# C( j2 |% v7 j
   BYTE  btIsIDEExist = 0;9 F8 k$ ]( i3 e2 m" s& G, e% m' J
   BYTE  btIsDiskExist = 0;: Z; O' _* Q$ v. ~
   WORD  wOutDataBuf[256];
  X5 h1 h" H. C8 Z0 }5 \
( W, X/ _, Y, `    BYTE  btIsFirst = (BYTE)bIsFirst;
% i4 }  f" ?( K4 j1 {. d" K9 x0 E6 y. w( P/ ^
   const BYTE btBit00 = 0x01;
. e( L" W- o' I    // const BYTE btBit02 = 0x04;
; A% b/ e0 C: N/ ?# r    const BYTE btBit06 = 0x40;
. [* {+ ?3 s. Q, \& N    const BYTE btBit07 = 0x80;. d* E6 v9 Q/ ?. ~9 d* t
   // const BYTE btERR  = btBit00;
( r/ K8 H# p7 E. ^) _    const BYTE btBusy = btBit07;& y" n- w0 H' r; Q8 N/ a
   const BYTE btAtaCmd   = 0xEC;! F* ~* U, |* B3 D0 W
   const BYTE btAtapiCmd = 0xA1;
  L4 Q! e0 u8 P) S( V& |" o! U4 {( i, F3 g% e) t9 b
   __asm. @$ N- b/ o* x' |
   {
; \$ `8 Y$ L2 y# F' ^# Y9 ~6 b        // 必须先执行这条语句
! t; A% I/ j2 C1 |" b) ?% F        JMP EnterRing0
+ U! S7 N8 o) L; z) b5 H* y" A1 X7 H- l* j" _3 J  K/ c
       // 定义过程( f: J/ i! G. s
       // 等待IDE设备直到其不为忙为止
0 K4 I0 C3 L- t        WaitWhileBusy proc
+ `4 C5 o8 F& d3 o1 `& H
* R+ q1 F7 T  r( [        MOV  EBX, 100000: t+ V7 q+ {; `' h
       MOV  DX, dwBaseAddress
5 _, b- q5 q' I        ADD  DX, 7/ ?- a2 B2 x2 w  w
' k& {, f2 P7 L4 X
       LoopWhileBusy:& j& e' h) y; ]+ ^* b) `3 V" f

4 J9 U6 Z& A7 x, o        DEC  EBX
& I' e3 D8 r0 Z% Q1 M# s        CMP  EBX, 0
# I9 Z6 E1 [* r4 ?, |        JZ   Timeout6 y4 [5 E+ v4 F5 x$ s' O
       in   AL, DX: o/ m3 [4 m- Y  Z  E- c% Y& B
       TEST AL, btBusy
7 O( x+ v: C' G- v3 E, y; o        JNZ  LoopWhileBusy; C) J2 u7 ~" F6 B
       JMP  DriveReady$ g; A& U+ n4 e8 K
8 U0 [7 h6 R# }' ~+ D* b+ X
       // 超时,直接退出: D0 @3 q2 h: ]8 }% A+ Y
       Timeout:" K: u# ]2 l* Y+ V) _
       JMP  LeaveRing0" E& c. y! m! \: C. a/ u
       DriveReady:
, l/ o- a8 G' _8 ?8 n+ H( }        RET
4 Q5 w5 f1 M9 F7 I# r        ENDP   // End of WaitWhileBusy Procedure
1 n: S0 [8 U. D6 K* X! |7 r, W1 O4 b' D' S2 n
       // 设置主盘和从盘标志/ f1 H! Y, n: @6 a! t7 Q0 @: {
       SelectDevice proc
8 R( V* ]/ a- A0 O% E. |
9 v' J$ ~% j! Y: F2 x        MOV  DX, dwBaseAddress
" ?+ @# e7 S5 {; s, p8 F# H        ADD  DX, 6. A  m% w* @  f9 k, ~
       MOV  AL, btMasterSlave
/ ~, c, h% _% v4 d& f+ c7 p8 K0 z3 _  {8 M  [
       out  DX, AL
5 u. h! A; H0 U% V; `# H) y        RET3 C/ w4 a- T3 a3 j
% R( d: N; G0 b4 }8 n. O
       ENDP  // End of SelectDevice Procedure
; j( f  t: c: B% o7 o* w) `; T& }/ l7 v
       // 向IDE设备发送存取指令* F6 @$ D% G8 N. ~# L
       SendCmd proc9 D7 `/ X" Z/ I1 h* \

  M5 L$ a/ d4 ?+ o+ B5 c        MOV DX, dwBaseAddress. q  ~9 Z& Z- N' ~7 u
       ADD DX, 7
7 k% r0 t4 a2 N2 G        MOV AL, BL // BL是主从盘标识,在过程外设置
, V2 O- r; ]: `9 d  x8 i  F) Q        out DX, AL
! D0 B8 [7 K/ d' s        RET5 }! H: b( e' G* ?
       ENDP  // End of SendCmd Procedure
/ k- D6 r; q, }8 i6 F9 N$ h7 e+ E/ Q9 g! O- n
       // Ring0代码7 a; n! _5 N% V9 ?) x; b7 B# [
       Ring0Proc:. P: r1 L) Z' @. }- N
       PUSHAD3 n5 R7 @. _( i% y$ a# N
       // 查询IDE设备是否存在9 I) L$ _+ v, i2 v8 O/ o
       MOV DX, dwBaseAddress
6 `' U! [: m& ?/ h        ADD DX, 7* F; K& a/ l- p, R3 H1 R6 N
       in  AL,DX
# ^0 P7 y# M2 b, y7 j  R. B5 f8 S: [/ I5 ^( l, b
       // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回6 Y5 O* u0 T6 o
       CMP AL,0xFF" a+ r: H& _7 k, u- h6 _: e" n" r4 O1 A
       JZ  LeaveRing0* `# g  W2 n9 G
       CMP AL, 0x7F
1 b- a5 c, r  k9 i) m0 U        JZ  LeaveRing0
& [" M4 O& @. d9 J+ l5 o! n4 o; ^+ C/ c7 I; A. y/ Z2 q( `
       // 设置IDE设备存在标志/ W4 c, s0 Q( R/ v8 V
       MOV btIsIDEExist, 1& Y9 u; Y0 h9 s+ b" J1 D

/ ~( S2 O& D# Y7 {' m        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面): k# c2 U3 }; `# V  m; W% x
       CALL WaitWhileBusy
' }+ U. F4 h( L) F1 M. N  w        CALL SelectDevice* c4 _. p3 {  E7 B
) ?; O0 u: y, s' T: |
       // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
" Y* o! k# ~4 O5 H, v$ n        CMP  btIsFirst, 1* c* M, |0 c' d; @9 ?
       JZ   LeaveRing05 V! Y; {! s; o& I7 Q# k
  z5 k* A0 q+ N+ a3 Z: z) M
       // 第一次调用时,如果执行这行语句会导致蓝屏,Why???4 h3 V1 _, o. u- g, a$ b
       CALL WaitWhileBusy! A, G2 q: ~  _$ F4 [

) \: ?( Q7 |3 |        // AL的值等于cBit06时,不存在驱动器,直接返回
8 F6 U! f6 Z, E  ]. g. Z) d* D  e        TEST AL, btBit063 ^+ {) J& o! b; l) @" S
       JZ   LeaveRing0% W6 O; S8 U) p+ F  i. ~' Q

' c' T- x5 E5 t5 h: q# w        // 设置驱动器存在标志& W6 j% Y' ^! ~" ~' I
       MOV  btIsDiskExist, 1
5 R! L2 O5 g" U
5 e- }' _7 L/ b9 V7 D! P        // 发送存取端口命令
' h" w; d9 N" u6 L        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,( p% K6 S: d& B" i3 i) k
       // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
( b1 N. k/ H6 ?) e        CALL WaitWhileBusy
/ S( s; I* x4 X        CALL SelectDevice    // 设置主从盘标识
4 z! K3 t  [3 t5 i" K8 n2 I, ]8 X' b        MOV  BL, btAtaCmd      // 发送读取命令' f3 f* U: }6 D9 d" L
       CALL SendCmd
- I0 q/ E% V" I) [" J- i# O        CALL WaitWhileBusy
& Z1 T) I( l5 `: e4 z4 j4 ]1 l9 c+ J" O: y* F8 o) Q% o
       // 检查是否出错
8 X6 N# E  i6 Z( f/ Z! M$ F/ f4 T        MOV  DX, dwBaseAddress
9 e8 T2 b* b" `' Q        ADD  DX, 7
5 o' s; T' \4 L0 |' y6 G
$ h+ |0 g+ q8 J3 c8 q0 J0 m. p* o  S        in   AL, DX
' ^7 r  u/ U4 z; y( N6 b
% @5 p8 W4 w9 _$ j2 |        TEST AL, btBit006 q4 H  }+ y! r
       JZ   RetrieveInfo   // 没有错误时则读数据% U' @' J, W6 C  q
+ k  K) o3 B: B1 h, {" b' T
       // 如果出错,则进一步尝试使用ATAPI设备命令# d% S) ~% U& j2 c
       CALL WaitWhileBusy0 b) K0 j& {9 n1 e6 ~" c( y
       CALL SelectDevice1 \' H3 O" q  l; t( ~5 U- n3 h: r
       MOV  BL, btAtapiCmd
) _$ c  V! E3 w7 c$ g        CALL SendCmd
5 h" Z/ K2 b* A$ q        CALL WaitWhileBusy
# k, n: m9 m9 e; w+ }# D  m7 s$ \3 B. J( W4 f$ i
       // 检查是否还出错
  Q* J0 H& j9 N3 Q; L% r4 _        MOV  DX, dwBaseAddress
% M5 B  T7 V# \        ADD  DX, 7& ?$ l" x+ \  b" o
       in   AL, DX
  \4 m8 l2 H! t& @0 ]        TEST AL, btBit00. {& ]; a/ u. D& B
       JZ   RetrieveInfo   // 没有错误时则读数据
6 {' H1 }+ c1 g+ t: ~# x+ b7 d        JMP  LeaveRing0     // 如果还是出错,直接返回" I/ S$ l1 {! g3 s& q2 x
- ?3 n' f- x: f6 e
       // 读取数据
% k! m6 k" J# z& o        RetrieveInfo:+ _" ^/ J" W' B! P. Z" B1 v, V

' k3 i. A7 c- S8 d6 O+ v        LEA  EDI, wOutDataBuf
9 Q5 \  g$ I1 K, i+ x, @2 o1 f4 A2 e        MOV  ECX, 2560 E( w1 x: d% v
       MOV  DX, dwBaseAddress
; u+ }7 A1 R" R' M# A4 C7 r        CLD
5 _: n( H- z0 H
8 E+ L2 T) @9 v" R2 e1 T$ a/ \        REP  INSW
' ]' z8 ]2 u* m  M( r# T6 H/ \, j% l/ P8 j- A% G
       // 退出Ring0代码1 B! L( \5 k2 m% W5 k2 D) r) E
       LeaveRing0:
% n7 |- }; C! c- B
- V6 S5 f. L7 A% ^! n6 e        POPAD
1 G5 `4 J- K" y' k  t2 P/ \5 y: {        IRETD' p. `0 V+ R* [* g! v. n# L9 q: F

. F7 S% _' V! F5 `! A/ n4 v( k4 R        // 激活Ring0代码
; i5 r. F* O/ l        EnterRing0:
; c& t3 V0 ?  M: M( X" ~5 ~7 v
) h3 ]% [; M: f9 s8 Y) M, `9 c6 x2 C2 V        // 修改中断门
9 O1 D4 j2 h. D6 U        SIDT FWORD PTR btIDTR1
' d% q4 A, L% Y: y; i        MOV EAX, DWORD PTR btIDTR1 + 02h
6 ~! @1 U* M0 F0 R- G        ADD EAX, nHookExceptionNo * 08h + 04h4 l2 }+ V2 p6 ]& D$ v' q. V
       CLI
: M+ K/ z( Q; N/ I/ ~; m2 ~' @+ u( Y" P
       // 保存原异常处理例程入口
! |0 m0 {- _( j* W# R8 i5 t        MOV ECX, DWORD PTR [EAX]( D+ ]! O0 L$ [3 t- l
       MOV CX, WORD PTR [EAX-04h]
% E: [, s, P$ P1 `        MOV dwOldExceptionHook, ECX
3 g0 s6 V$ A2 ^4 N" s6 f- A
6 w' f( i5 S* L6 x7 Y! _        // 指定新入口
3 K! V8 W7 e; I" @) d! f  F# L        LEA EBX, Ring0Proc% ?( {- Q8 K4 e: T# H8 B$ O/ u
       MOV WORD PTR [EAX-04h],BX! v. n! w: R0 r7 Z" P
       SHR EBX, 10h3 z& _: e8 x5 Q8 F  d7 f
       MOV WORD PTR[EAX+02h], BX
. J0 h: W$ A: u; V6 a7 k* ~4 x3 J5 Y% U5 W& m& n# Q1 U2 P
       // 激活Ring0代码
7 |9 Q  b. \5 f: y" v( X% c        INT nHookExceptionNo1 h: b7 c/ v* x4 t1 W0 d# @
/ G7 |0 A/ s; F
       // 复原入口
  g1 a4 u% C4 o8 b& ~& N        MOV ECX,dwOldExceptionHook; Z+ I+ I, \5 P' z. |; Y
       MOV WORD PTR[EAX-04h], CX
) _5 d1 b; ]% ?! L% X/ {        SHR ECX,10h+ V9 o% ], l) e
       MOV WORD PTR[EAX+02h], CX7 U. P2 t2 n& H9 f# q. q
       STI
6 g, y! q0 h, {# \/ B    }$ k/ \: Z: u: B' y" R. ?
   if(!bIsFirst)9 T) t/ a9 C2 \, c9 a' K+ k
   {
/ Q# G, S$ f& Q4 ~1 S$ s        bIsIDEExist  = (bool)btIsIDEExist;* N0 O+ }' y/ g; Q, d8 Z! g
       bIsDiskExist = (bool)btIsDiskExist;4 G% C4 v) ~& ], Q7 W* z$ S
       CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
6 K) e; f) p$ J  b    }# q; x% }7 k8 R( L
}
) {. |% [; O! G6 {9 p% Q5 P//---------------------------------------------------------------------------
' ]9 M2 u- Q/ |% g6 y: ^// 调用方法:7 Q0 v+ J4 Y; I# H
void __fastcall TForm1::Button1Click(TObject *Sender)
4 j% B+ _8 L  R4 K9 {' {# h{
3 G1 p+ t$ ^; F- n/ ]2 w4 F6 \    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);6 b. J0 b; I0 D, A+ G
}
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2025-8-9 09:30 , Processed in 0.035455 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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