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

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

[复制链接]
发表于 2005-5-30 19:22:36 | 显示全部楼层 |阅读模式
  #include <WinIOCtl.h>
3 M5 x' V2 s3 J6 d1 T9 B" K#include <stdio.h>) q3 t2 g5 X. a8 [4 Y& w! h& [

- D7 N8 u# ?& ^1 ~, X/ h0 o8 s#pragma inline% B) P! d" z6 i- B
//---------------------------------------------------------------------------
, }7 E# _( e5 {( n' S// IDE NT/2000/XP专用变量3 w2 }, r3 A! f: `5 \
#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
0 g5 t3 i. a3 i* M' S! M% I#define DFP_GET_VERSION         SMART_GET_VERSION1 Q  F& s7 ^: r. o/ X0 X) u
#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND, ^" G7 o) [  w
#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA& C8 g; d$ |3 v9 U: d1 m0 e

& w. T1 t9 E7 c2 z/ U0 zconst WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令
1 f! ]6 k5 b* G/ I# _$ L4 H0 }const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令  X) R. _) y. K2 S( r/ B0 I& |
1 F' N: K! _0 o6 c2 U7 i* ^
const int MAX_IDE_DRIVES = 4;/ y  g3 V) L; Y3 }% m
2 C0 i) O. U/ B+ p; p7 `  k7 u$ A
// SCSI专用变量
8 W0 M% m- Z  y3 O9 h5 v/ Vconst DWORD FILE_DEVICE_SCSI             = 0x0000001B;$ L7 g6 N+ m. L/ D, `7 d
const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
! |, g  `& |5 J! gconst DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition% h* T' ?* M# C, i" \
const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;6 o' F, r) y6 Z/ y% {1 d: T

2 q1 T9 `0 y' i# w2 e# }typedef struct _SRB_IO_CONTROL' ]& [1 S8 s0 m; B  n# T
{
; i4 r- \( e& M7 C    ULONG HeaderLength;
+ K. Z4 F( W% y. _: [" w: t. A    UCHAR Signature[8];# d3 z7 i" a8 [7 B" L
   ULONG Timeout;0 V/ Y& |4 Q* R  I, \; Z! Y
   ULONG ControlCode;
- L  ^0 p; ?0 p0 a    ULONG ReturnCode;
$ n, d. f0 l' ]1 z; W9 k/ k    ULONG Length;. N' n# Q; P9 a- ]$ }3 V8 Q+ a3 ]- ?
}SRB_IO_CONTROL, *PSRB_IO_CONTROL;0 d* D+ d3 g) }3 o) r1 p

4 L0 _4 l( `$ g/ X% T6 {3 V// 读取的主函数
3 ^" U) k8 ^6 F1 Fvoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
' f9 R  H: H- ]! w4 K! i: Z/ m
3 }: s, B  |1 i/ ]0 E; A- J// 辅助函数
% Q2 r; C& w' c1 H" V: Ichar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
7 ]$ A3 o( j- {9 Y2 F6 q// NT/2000/XP函数
: l" b) T  P; h2 O% Y$ Mvoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);0 V1 \1 E' n, Q" N4 |2 V2 G+ L
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
* B; t$ Y. K4 k* }! l        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,3 ~4 M" n2 P! _4 y& u
       BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
# r! U( A( j8 A// Windows 9X函数
8 l3 p3 F* Y  y% c) avoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);( Z4 t8 {! o; b: v
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
2 T% y2 \$ K2 U  N. }* ]3 k6 y        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);' z9 J9 v  E* e7 Z$ j
8 i$ z* c2 l8 A
// SCSI读取函数(for NT/2000/XP)
6 x+ j3 X) G4 ^% T- C8 [String __fastcall ReadIDEDriveAsScsiDriveOnNT();
. K, G, a2 X3 o, B$ D//---------------------------------------------------------------------------: N( G, X- J' h# T
// ReadPhysicalDrive
0 Y+ f, j1 c- ]9 S& [: N2 W5 Y( ivoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
5 \1 M% t; M! n. S' m! m1 [( |7 k{* {9 r+ \, p2 N: ^! V6 j  i3 v- Z
   switch(Win32Platform)
% W8 b6 T$ _; O: J    {
  {; }1 D& F  E, x0 S6 l" q* m        case VER_PLATFORM_WIN32_WINDOWS:: W7 O9 O! x7 I4 i8 X2 y
           ReadPhysicalDriveOnW9X(pSerList, pModeList);) p0 [2 o. X! Z% J' e6 L$ G
           break;
4 R& N7 i( Q  e& S' {$ ]' D        case VER_PLATFORM_WIN32_NT:' X+ P8 Z+ A, o8 [
           ReadPhysicalDriveOnNT(pSerList, pModeList);2 t* e- Y7 b1 H( R; @% g
           break;
0 I( |4 m* ^7 Z# a7 j/ [        default:
3 I, Y9 |. e# f4 ?8 W$ {            break;
3 z( g4 }) J! D4 b7 B! q    }
  v( ^2 y/ h+ K4 D2 J}
4 x) y: N# A4 Z: E1 v% O5 R//---------------------------------------------------------------------------, ]4 m- p6 X" I
// ConvertToString0 ?" P  F) E: c3 J4 {! q& W
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
' g0 m8 x% T% J; C8 C" I; n{
  j2 y! O& b8 H" q, O& Y    static char szResBuf[1024];7 N( B" {$ l4 U* l, V6 R' t
   int nIndex = 0;2 n: D( g% z5 d& ~, J; d6 G
   int nPosition = 0;
3 W* a2 E6 N9 S& g  x2 k0 M! K
0 L7 ]" ~7 X9 T) V" r) X    // Each integer has two characters stored in it backwards
3 S. |$ r3 f- Y2 w' L$ p    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
) a, g/ x8 q% b, [0 d* D& r; |3 V    {
  j" L4 r* V1 J+ x" v3 R        // Get high BYTE for 1st character
% F5 {$ X: r- s, ~- k0 y        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);* u1 o9 H! t9 B+ v& u: t4 R
       nPosition++;
/ {% |. i) M+ {3 v" r; T6 G, ]/ n3 M7 ^/ e" i
       // Get low BYTE for 2nd character" f) V; H/ m" P& U2 p: p! h
       szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
' g2 V6 O. r+ [0 B- T        nPosition++;
. y5 j, b) @3 ]' l7 h    }
% C2 `2 _8 V6 g6 m) c+ [7 z
2 {6 x- I: D# m/ [6 v6 }    // End the string
' w0 I. S* f1 q% h. |( i    szResBuf[nPosition] = '\0';+ M3 D4 y+ F4 _0 g

6 E0 P1 D& @$ @0 l: }2 T    // Cut off the trailing blanks( H" O- Y) N% B) n1 S
   for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
, y6 ~5 a! |5 v; a+ L' m        szResBuf[nIndex] = '\0';2 V% T' @! c- y* ?

3 e2 _- G# V9 d- V    return szResBuf;6 H& S- {* o1 L, {. s% z1 Z
}6 j: C' Y% L6 w7 J6 N
//---------------------------------------------------------------------------
+ s5 W; d) |: Q/ u. p// Winndows NT4/2000/XP 代码& f& D8 T: s. s$ M! |' j4 w! }2 p, |
//---------------------------------------------------------------------------
* p4 ?4 R6 j$ |// ReadPhysicalDriveOnNT0 v4 M9 x+ K0 q6 ]9 s9 n4 s  w
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
4 k  l1 j  M/ ~* C{6 @- _9 a$ Z4 S5 _- u
   // 输出参数* m- z& ?: }5 @3 _
   BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
% |2 k% z9 v& K- M: t/ M, c+ G# ]5 N" M6 w9 z+ T
   for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)  E" [5 b$ l4 s$ C
   {" L' @* R" Q+ u# ^# M" }0 X* X
       HANDLE hPhysicalDriveIOCTL;
5 t6 M/ `) D2 ^4 i        char szDriveName[32];, ^- z- y% ]2 Q+ }  o5 }" Q
& r/ s+ M  w/ M, h
       sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);0 K  g& K6 ^5 l( I( Q
       hPhysicalDriveIOCTL = CreateFile(szDriveName,
& {; |6 F9 K' B5 _/ y# l& P/ ]                        GENERIC_READ | GENERIC_WRITE,
) z2 f( G3 b: _) c                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
) p7 E  j3 N1 {/ P8 D+ Q                        OPEN_EXISTING, 0, NULL);1 H" M, `( P0 U( s

3 d0 H$ U7 q5 ^# z3 O+ x        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
# u/ D* \/ ?- |0 d( P8 s0 j5 \        {. T7 o5 ^3 j' U
           DWORD dwBytesReturned = 0;* W$ p1 l9 `$ R0 h
           GETVERSIONOUTPARAMS gvopVersionParams;
7 n! i* R4 ?2 j& |' t" e6 g% z
3 r- E8 ]: R8 v2 \2 W9 k% M            // Get the version, etc of PhysicalDrive IOCTL9 ^2 o5 _' }( E# J0 {7 s1 l
           ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));6 u7 f( C. {( T8 y( f1 W
7 v' _3 r2 @, K- w
           if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,! p" G  B6 Y8 F& u# x( Z3 F+ }
                   NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
5 W- r* g$ B: t* o2 K' w& m                    &dwBytesReturned, NULL))% Q& N! {+ S3 E3 p' w2 b4 }9 u
           {
/ U4 I6 s0 _7 b                continue;+ n% q" Q. A: j* L9 ]
           }& z# c4 f- i$ S: _7 a$ q9 j/ J

2 O$ h2 _; q( _" J            if(gvopVersionParams.bIDEDeviceMap > 0)
# k! L* P, J: _6 ^" w: Q  S0 ^            {5 H; s$ i9 n! ?4 S  x
               // IDE or ATAPI IDENTIFY cmd8 T; c4 U  b7 f8 c3 D5 D4 i1 k
               BYTE btIDCmd = 0;
+ O$ g4 a5 k  }  F  ]                SENDCMDINPARAMS InParams;1 m& D( [- V6 x: b! M
               // Now, get the ID sector for all IDE devices in the system.
. r" n9 r( Q. w: c9 }. F                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
7 D4 |# \6 B5 P3 i! s0 {1 K& j                // otherwise use the IDE_ATA_IDENTIFY command
- {+ X7 t/ O! `2 [( i                // 具体所得结果请参考头文件中的说明
& o- {% Y- F! D, b; B9 U                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
# \9 b' L- O4 E+ M- h" s) D) Z  ^" ^                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
: e/ _: D& K# a% {* |# r/ `                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));3 p6 T  r+ |) X
               ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));; p# K% X5 `& g7 O- F
+ M6 [% z4 `! S4 I
               if(DoIdentify(hPhysicalDriveIOCTL,
; ]! I8 A( m/ N0 d' _                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,) p) D3 t- [8 r% q) a
                    (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))0 x: B5 v. ~" ~/ y! Y
               {
* n  W+ l# r& U+ Y8 N0 f: }                    DWORD dwDiskData[256];
# J% O) {% G- L# [                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件8 M. P' s2 t9 v( T" B, g
                   char szSerialNumber[21];* D$ T8 K# O- `; ~+ a" t
                   char szModelNumber[41];
% G9 G% A! a- i7 n4 U% j
9 L( L, n% O9 j! P7 X2 C                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;: c7 |; Z: v9 g6 Z" y2 _# |
                   for(int i=0; i < 256; i++)) u$ r. {4 m9 c
                       dwDiskData = pIDSector;
" n1 w) r, M; o, [                    // 取系列号
9 O1 A# }+ s9 S# d# B0 j7 G. @2 y                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
3 q7 r$ y: C3 F: S                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));# F$ k5 r, I6 `, z5 R

. T$ t% P+ N4 a% Z& S3 [) _7 _; H                    // 取模型号
" M5 t  M$ p: B2 E. Y                    ZeroMemory(szModelNumber, sizeof(szModelNumber));% m/ ~5 J& k; F+ K. M# q( l  q0 r+ a
                   strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
; `; j; M' K" S7 h( x9 \  m/ S% m; h1 C
                   pSerList->Add(szSerialNumber);
) J4 Q5 _/ z! ~                    pModeList->Add(szModelNumber);
" n( Z% q5 B- R0 f                }
# |7 A0 H- d/ y& J, Z( f& ?5 i7 T            }
* |% N1 e$ B7 c/ s9 F3 B; U            CloseHandle (hPhysicalDriveIOCTL);
3 U: n1 `7 q# _, x1 u2 C        }
2 e( R8 q, _8 m4 w; c2 s4 ^    }
7 E8 n$ Q$ D* s}
) g0 S3 W" `* a* F  N//---------------------------------------------------------------------------) M8 r# K5 D% i) l
// DoIdentify
$ q. j" P. h  ?/ l6 T, \  Tbool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
) d' u, y9 m' E9 E- v+ ]7 X              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
; _/ {* C. U4 z              PDWORD pdwBytesReturned)* |; f3 ^( o; a% J- W
{
3 b6 w) q& Y# l3 k) S; H    // Set up data structures for IDENTIFY command.8 U5 g3 U5 w8 i9 W
   pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;9 z; |& D7 p# h8 V/ ^7 V+ `+ S: c
   pSCIP->irDriveRegs.bFeaturesReg = 0;; j# ~8 k* k' h5 ^! I* A9 C/ w8 P
   pSCIP->irDriveRegs.bSectorCountReg  = 1;
' F- p+ t; ]+ n2 M9 r& Y5 n    pSCIP->irDriveRegs.bSectorNumberReg = 1;9 x- i2 O; d9 K- w0 C- J5 _/ |
   pSCIP->irDriveRegs.bCylLowReg  = 0;
7 B, U1 u( K) L3 x. J    pSCIP->irDriveRegs.bCylHighReg = 0;1 m8 m3 `8 H# C5 D% v7 V9 {

, C0 p: U2 L: W/ l% K    // Compute the drive number.(主盘和从盘所对应的值是不一样的)
: S4 t* b  v# \/ r) ?, N, x7 p    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
( V4 G8 ~0 Y0 l+ M& L1 A6 N) G4 S
   // The command can either be IDE identify or ATAPI identify.
( ?$ b) a& a! A2 }0 o) [    pSCIP->irDriveRegs.bCommandReg = btIDCmd;  C3 h; u" W# b$ \$ L0 F; @5 F. j
   pSCIP->bDriveNumber = btDriveNum;% t. a9 T/ e7 M  m# \+ l
   pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;3 E' M( K% P6 Q* Q6 W
7 J" q* n  n3 V- f: K' @% l, E
   return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
, Y5 N% m" P, U+ u           (LPVOID)pSCIP,/ n) B2 U" u: o- \3 R) [
          sizeof(SENDCMDINPARAMS) - 1,4 j/ I: M9 @4 y) K' T3 s* H
          (LPVOID)pSCOP,
; Y7 N1 [( `: u6 I, Y           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
$ E( h4 h- U# {% D* h( o           pdwBytesReturned, NULL);
5 N/ I. v6 a. Q: u1 v4 @}6 {, ~2 q$ r* C% P
//---------------------------------------------------------------------------
3 e# M' Z. \# O( M5 t// Windows 95/98/ME 代码9 Q* Y6 J# N. A2 Q
//---------------------------------------------------------------------------
) a) F- n7 G( S# Q) g' c7 S! ?1 }// ReadPhysicalDriveOnW9X
4 L2 Q6 c2 O- \4 _void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList). O  [+ ]- Z: L3 p9 x. m- f# }
{/ D) |3 X+ L1 K6 @: c/ g7 `: @& Z
   WORD wOutData[256];" G0 s/ L+ V& L3 g
   SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);5 W$ z7 g  G" t" \2 M, r! z+ K9 z/ A
3 b% z8 l' F" _, b  {' B
   // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
- H% g% d9 s; t" _. @& `6 ~    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
+ H6 p1 i/ w" t7 ~0 X* C) H    // 避免蓝屏的出现。(期待高人能指出原因)
% `/ \  l0 A- _0 N* j    for(int nDrive = 0; nDrive < 8; nDrive++)% O% d% d0 V5 g' w1 U
   {1 p7 b4 y4 C. ?) k0 A6 n
       WORD dwBaseAddress;
8 o+ q/ i" F4 ~  ^" S1 O' X* y        BYTE btMasterSlave;         // Master Or Slave
+ B; _+ u& f# u0 O! t' e        bool bIsIDEExist;+ Q) M" w+ x4 G# |1 v: c5 p
       bool IsDiskExist;/ I2 j! n3 M9 A3 ^. G: Y
$ `( M3 U  ]) W7 x+ l& w  e, m9 K" u
       switch(nDrive / 2)
; \& \' S" c( n* M6 h! a) L        {
% ?# J, t9 k6 T0 d( w+ r; Q; P            case 0: dwBaseAddress = 0x01F0; break;5 \0 m. |5 u1 Z
           case 1: dwBaseAddress = 0x0170; break;
) k# E7 f9 o. R8 H$ h2 `% A. F: h            case 2: dwBaseAddress = 0x01E8; break;
' E+ X  U" V- |' F' X            case 3: dwBaseAddress = 0x0168; break;- \4 g" Q# ?0 r! E) g: `
       }- g9 ^. Q: b7 |2 E+ l

- S! H& A" h# c+ K6 d! x1 ?0 F; }        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
! j# X. w5 G. v9 o
5 I: B( S8 T" y7 ~7 f        // 进入Ring0
- D0 l2 X5 B: m, \. z: W" x        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
# F# t0 J2 e: Y1 G7 o                bIsIDEExist, IsDiskExist, wOutData);
9 O2 X; N% X7 p6 ~; t) ?8 ~) R, M! P    }; @9 Y' x$ E$ S

% |9 c- L7 ^( [( j$ i    // 开始读取" }- V7 g) Q# ~# d
   for(int nDrive = 0; nDrive < 8; nDrive++)
. g( c8 W+ }1 [* I/ o# k/ j  i4 Z  P    {" W  s) S% r- v7 F+ A  h4 J
       WORD dwBaseAddress;7 E2 P+ x9 f/ n. F& J* E+ f
       BYTE btMasterSlave;         // Master Or Slave
  K+ M. T( r2 F4 m! {        bool bIsIDEExist;
9 f0 I6 ?( u# J: M* ~* w: \" z        bool bIsDiskExist;
9 a9 x' S+ O- J3 I2 d# f        switch(nDrive / 2)
  K) n8 V4 D6 d0 U; i  H! y$ ~7 O        {; Z4 T. b! b" O1 i* K! ?# U, k
           case 0: dwBaseAddress = 0x01F0; break;* k+ T! V% H5 H, e: v$ i/ T# T: N, T
           case 1: dwBaseAddress = 0x0170; break;
/ D) d! n, d0 \2 ^9 N. p7 ~/ T+ @            case 2: dwBaseAddress = 0x01E8; break;
, L7 c3 h8 G2 q- Y7 O) k# W  W            case 3: dwBaseAddress = 0x0168; break;* l  w' i. j* E+ d$ Z3 q) b
       }
+ N4 y- C& I, s8 T( d3 J$ ~2 B5 r/ `. f$ J( o% D! f
       btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
9 F) V# N5 ~2 B! `/ x7 K. G6 f" b+ |9 ^0 h6 M
       // 进入Ring0
- w' F9 m, ]& C; e( |6 l        bIsIDEExist  = false;8 w5 Y) T5 k& M6 A# F5 N( Z
       bIsDiskExist = false;
- j1 d% n9 W, t1 d+ @5 X( o        ZeroMemory(wOutData, sizeof(wOutData));
& b& H4 {) C+ I8 f4 c8 t' D) \1 t9 u/ I" U  u' Y- c
       ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
  U$ o# E1 x1 P+ H: K+ o8 |                bIsIDEExist, bIsDiskExist, wOutData);
5 P$ D, {4 s  o" x0 H# h) x
6 b4 Y3 r, U3 C7 l) k5 C/ D$ Q        if(bIsIDEExist && bIsDiskExist)# P- {8 `3 o- e/ Q
       {
& V- k% B  Q! w            DWORD dwDiskData[256];" n6 p8 G& U! s, Q  n3 G0 b' P
           char  szSerialNumber[21];
1 r) Y7 s1 Q, }6 C            char  szModelNumber[41];) P( R( C5 J, |2 p2 f# K  h
+ o  J  i" m' K  t  t+ N
           for(int k=0; k < 256; k++)/ E4 f# G5 a  f% [$ O
               dwDiskData[k] = wOutData[k];
2 d6 d+ Q8 Y+ M  Z6 x# T
- t, n+ v5 i5 C" h# C8 T            // 取系列号
% u# a  A" G. M. m) j* U            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
! e0 c" a4 P% B' {6 [            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
7 ~2 N  O8 B% `
, X2 U% p/ W* h3 p- Q) T& `            // 取模型号
  j$ ~8 t. K: \# _! a$ _            ZeroMemory(szModelNumber, sizeof(szModelNumber));0 L/ s% x2 _  d# J7 A, r
           strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));: O* c: S2 d# Z! V8 V1 i( O

5 k1 H* q" q3 R9 t( \7 N) J            pSerList->Add(szSerialNumber);
3 m+ L* p, J# V4 Y0 i            pModeList->Add(szModelNumber);3 ?; i) G1 }2 G3 @+ f
       }
6 X# _( i8 ~8 O+ K) O$ s    }
; u" _5 _# F/ y7 Q2 }* H+ g    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);! m# z# r1 p5 z- y- E! s
}
3 A8 k, w# o0 y  }7 g4 P# Z) }4 y" P//---------------------------------------------------------------------------
3 L; i! W  q% b, _  h// ReadPhysicalDriveOnW9X_Ring0()
7 |/ @9 R* Z; \) ]/ h9 N" r/ l+ `//5 K7 \' E; b3 L  Q
// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
- |; k8 R2 {1 Z8 b3 L// btMasterSlave = Master(0xA0) Or Slave(0xB0)/ Z% F/ I/ z% [
//---------------------------------------------------------------------------- a+ i) Q2 Y$ h
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
+ w5 H  @3 _' y8 y        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
; K# b" t! U6 G% f) }4 Q, D2 U1 N{
+ ?* w0 m8 C1 y9 F! `* W6 b    BYTE  btIDTR1[6];
7 |$ D9 q6 v: B# {8 ?& T% m    DWORD dwOldExceptionHook;9 \. H) Z/ a# n% {
   const int nHookExceptionNo = 5;8 l. v/ m* Y+ e/ Y$ A
+ D' M# O/ Y, P: o9 y8 p" T
   BYTE  btIsIDEExist = 0;
; G, ^) ^; f# n# k    BYTE  btIsDiskExist = 0;
2 C% Z  O0 ^3 c1 Y! Q: o% ~  R    WORD  wOutDataBuf[256];
' \3 A0 {: k8 N! o9 a0 I  N: z
- y2 c2 G) F# ?( |7 i+ P    BYTE  btIsFirst = (BYTE)bIsFirst;  o* h6 J) u$ V' n( \: a
0 k2 I+ P2 s) N6 n  K; [1 e
   const BYTE btBit00 = 0x01;- S' [3 H! B8 s4 F% t9 f
   // const BYTE btBit02 = 0x04;% Q- R% ~0 h1 }* Q7 {; ?# L
   const BYTE btBit06 = 0x40;
" \! n) O5 E# U5 x5 D4 a( i    const BYTE btBit07 = 0x80;
( ~) T1 Z2 y, p2 a    // const BYTE btERR  = btBit00;4 B! w2 W; q* L
   const BYTE btBusy = btBit07;
# _9 h7 F6 ]4 F, n9 c  ]    const BYTE btAtaCmd   = 0xEC;9 P9 l9 g2 L1 E
   const BYTE btAtapiCmd = 0xA1;% c. z4 U! S6 G3 W- S6 F: z

- y" q; ~. g: e: D    __asm! w8 E* G5 b7 J
   {
; t. b1 q& O9 f* S        // 必须先执行这条语句
- ?" J2 R* S; I3 Q$ j        JMP EnterRing0
7 e+ S! o! ^& V. u$ j$ `8 d
# [; `0 d5 c1 }        // 定义过程
1 K2 A: m  P1 z        // 等待IDE设备直到其不为忙为止# l0 _2 ~3 u# s
       WaitWhileBusy proc
. j7 v* Z" M3 x, n
( e4 R* @/ X$ Q. X$ \) D        MOV  EBX, 100000
5 V# d/ H9 C* v+ l" g7 l- Z        MOV  DX, dwBaseAddress
- j6 ]  m* @2 C8 u: I6 J        ADD  DX, 7
! q& ?: u" [4 O4 m3 j% f8 [
/ b0 [/ p( t0 R2 a        LoopWhileBusy:
8 I, O% y3 M! _  f+ o+ ?# R( r
" e( [5 @# L  w( |+ \        DEC  EBX" c. _4 c; n0 \( J3 F6 D. G
       CMP  EBX, 0; K' F4 o) G( b! Z' W
       JZ   Timeout
. ~4 z: ?0 [; D5 s        in   AL, DX& z: m' r7 K5 `. i) O$ R( D
       TEST AL, btBusy
$ w, f! B3 P) W- A2 d  b        JNZ  LoopWhileBusy
: V& s' `% @6 ?0 H# V        JMP  DriveReady
; b' n% ]- N. A' j2 r
! E  C# q0 e) Y: A5 U4 p; g        // 超时,直接退出
& K! y9 X$ ^4 _        Timeout:
( {1 S1 g1 k5 W3 W+ O5 S) H        JMP  LeaveRing0
* n- J, z+ [1 t9 _* D$ ]        DriveReady:7 Q. O: ?5 X1 U
       RET
8 l& V7 q" f# q; F/ B0 g        ENDP   // End of WaitWhileBusy Procedure
* c9 y6 b+ J$ n% {
! M$ m! N% ]- ?) o% n& F' R        // 设置主盘和从盘标志
  E8 z4 K* F7 u5 I9 d; P" O) v; F+ }/ U        SelectDevice proc
' k! K# A5 P2 m
$ u. G- n( h( k: t        MOV  DX, dwBaseAddress
: A( {8 F6 n0 ^( e7 p9 v' z2 p        ADD  DX, 6  P/ ?3 k( b1 d) I+ m5 y
       MOV  AL, btMasterSlave
1 {( b6 Z: J6 }, d& S4 P& t  t* G. G) e4 [) ]" a1 ]! o4 d: ?
       out  DX, AL
/ T' S8 a3 G2 l8 I6 N6 G        RET# a7 [0 }! J9 S) @0 j% D" Z4 q

" A: P5 S% p6 K        ENDP  // End of SelectDevice Procedure
# t, |# U5 U5 A6 L7 ^) O6 V2 {: I0 W/ K5 ?! B2 G* y
       // 向IDE设备发送存取指令
* h! O/ Y  F0 j( L, ~) y) u& M        SendCmd proc" H( n2 T, _9 B: r( U9 R: b
) D( p1 h% O5 |- g7 _
       MOV DX, dwBaseAddress
' y5 Y1 t. G2 X; m: `& _        ADD DX, 7
4 Y7 }+ E( a% `; n        MOV AL, BL // BL是主从盘标识,在过程外设置
0 l' B$ J9 j# r' `0 z# J& O3 r& Y+ _        out DX, AL! t% o$ d8 V9 s7 L0 c( J
       RET
& X! L2 q/ u. x) W! t        ENDP  // End of SendCmd Procedure3 }7 U2 T! I! w  n' }+ m- P

4 Q* ^# q; q  ?+ q+ K8 X        // Ring0代码; W: e! U2 {* H0 J* h# G# o
       Ring0Proc:
7 }: ?* x8 ^. T. O+ t% P3 o: ~        PUSHAD& X8 R8 h8 d! ^/ r' d# t! c
       // 查询IDE设备是否存在. v# b# z# k; E9 x: j
       MOV DX, dwBaseAddress1 c& O3 N  j1 Z8 Z2 P" T
       ADD DX, 7# n. |0 q/ H) j- \' W' H/ r
       in  AL,DX
* c- c3 e$ ^! X1 a& ~. \# ^9 t+ X% i+ r
       // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回% h  t& c9 x6 m- g2 ^- k
       CMP AL,0xFF. I! j1 Q( \/ h( P( j  K) S
       JZ  LeaveRing0) r& E! B. }5 T6 b, Y: d
       CMP AL, 0x7F
( _, i# e: {( G' W        JZ  LeaveRing0
% ]; T, H" i4 a8 l7 N8 c% S" ^
" |) b1 C8 V# u# d3 }8 n        // 设置IDE设备存在标志
; `0 L/ M% h' i8 r/ \        MOV btIsIDEExist, 19 E) r7 w7 \( G$ ?( U5 T
; I; m/ Q5 |  y/ M) w
       // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
2 k6 Q+ s2 {: Y( K        CALL WaitWhileBusy
3 T; s' P: B, B' c/ d3 O8 _        CALL SelectDevice$ W/ ^; k  W3 I2 W: b

2 Q6 L7 \1 I2 h5 @, D  u        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏* |3 C/ [' F6 Q7 o3 |: s
       CMP  btIsFirst, 13 o8 x8 X! G$ Z' p5 C
       JZ   LeaveRing0
; L; P: F% c& b+ k( c( @7 z' [4 O4 ?3 x, v& U4 n" J3 m2 u
       // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
9 O% K5 A9 z/ z. K! C* d        CALL WaitWhileBusy  _4 s$ O9 f+ R1 ]4 L$ n, X, T

' }8 R  k- ?; Y: [7 F/ c        // AL的值等于cBit06时,不存在驱动器,直接返回
/ ]+ W1 t7 Z# W4 ?8 [        TEST AL, btBit06# B# K2 r' ?; Q/ T
       JZ   LeaveRing0
6 H( L# B3 s7 c/ d$ ]
. f' q6 W' X, U  Q" _( P- S        // 设置驱动器存在标志6 Q3 y- E2 i5 H; ~8 ?
       MOV  btIsDiskExist, 1
. o& `# M2 n- M0 W. s1 V( K4 G" X  M9 e2 g9 P  [1 l
       // 发送存取端口命令
1 X9 ]. E$ z- d+ k) Q- ^! F        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
  p' d2 O4 G8 O7 d+ v        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
2 w( q; f0 }$ Y. U) m+ [        CALL WaitWhileBusy
0 O; o3 G2 s  i; e4 Z/ z        CALL SelectDevice    // 设置主从盘标识
/ V2 E1 R! u5 c2 H) B        MOV  BL, btAtaCmd      // 发送读取命令# U5 j$ x  j6 ]4 A8 L
       CALL SendCmd
6 p- y3 q1 |$ s        CALL WaitWhileBusy
% h& g) o" Y: u: g6 S% I* {/ u; f0 g# x8 V9 `
       // 检查是否出错( F1 O, V4 E. f5 V6 y9 z
       MOV  DX, dwBaseAddress
6 H/ W9 v% v' e+ L  O& z        ADD  DX, 7
9 p6 s7 L7 \- C8 E  K5 E6 W0 S; p7 @9 }1 _! ?5 m0 o
       in   AL, DX
2 z4 Y4 y" Q$ _5 A1 B6 r  H+ ^; x- u% b% W, [  [! V
       TEST AL, btBit000 F2 p2 W3 |. U7 j( ^+ D
       JZ   RetrieveInfo   // 没有错误时则读数据/ y# q, ?  j& {9 g4 {' R  J2 p

& n. E5 O2 ~4 s" u        // 如果出错,则进一步尝试使用ATAPI设备命令( F! ^; {  ?' L% @' J
       CALL WaitWhileBusy
' A) D8 X) ?0 D% m' `        CALL SelectDevice
* z5 v, l& n" b3 y1 {1 Z        MOV  BL, btAtapiCmd
+ S5 e: L, N4 z, W        CALL SendCmd0 t) _( f# _5 L# \3 f
       CALL WaitWhileBusy- {: H" F% K: D6 A$ I* j

. K/ b! Y7 ^' H  U$ F, i, |5 s        // 检查是否还出错
* u2 y7 j2 x7 V5 w        MOV  DX, dwBaseAddress
# q$ k6 t7 M* A+ s        ADD  DX, 71 m; T( p: n4 G8 F1 }* N
       in   AL, DX9 @" h: U& Q2 s
       TEST AL, btBit00& c! M7 B4 `9 n$ }$ o' a
       JZ   RetrieveInfo   // 没有错误时则读数据
: b3 F/ E) q6 ~# {" [! c( V" b        JMP  LeaveRing0     // 如果还是出错,直接返回
* M" |! [) W4 e
5 F, n' S* k* A3 l4 ?' t$ a5 x+ V        // 读取数据
9 u7 J# }* |3 n* t7 ]8 G9 w3 @5 f) P, L        RetrieveInfo:* Q, s. e8 E3 K

# x/ g7 I, F& g* \# m) p( n        LEA  EDI, wOutDataBuf
) k: f+ l5 p7 T9 h        MOV  ECX, 2567 ~- k9 D3 U# `3 |' K
       MOV  DX, dwBaseAddress* i- z/ K" \3 F! g1 M
       CLD$ }% R/ x' }# O) Y/ K# ^6 T
5 P7 k0 q- j$ D/ l
       REP  INSW& y2 i. l$ j8 I0 k/ @9 `0 X

7 l6 O( b% _. }2 W  Q; L        // 退出Ring0代码; |0 T8 J% b5 L
       LeaveRing0:
& n+ u6 }4 K0 D1 {7 j4 F" W( |6 n( J( g) G, D& r$ J: [5 [' \  ]+ l5 O6 J
       POPAD
. O0 b1 K0 T* Q        IRETD5 H7 m( Z9 g5 X
- E: X6 z3 |: l+ T' {
       // 激活Ring0代码
6 H7 [1 q$ v' p* J: s        EnterRing0:2 j) @& k* a+ R6 I" N0 q3 m( {
$ r8 J9 x5 }3 I1 ]+ ?
       // 修改中断门, N- W: q" F+ c$ w5 b1 W
       SIDT FWORD PTR btIDTR19 ~% p& ~9 T: S  h# k
       MOV EAX, DWORD PTR btIDTR1 + 02h; H- M2 Q, f1 @3 [' k  |% l
       ADD EAX, nHookExceptionNo * 08h + 04h
! \  P' y( `/ B( U& j        CLI0 L& Y1 J8 U) |* Q# `
8 x$ O2 T6 i  {1 b
       // 保存原异常处理例程入口
6 N; L# `- m1 l1 P+ c. a( H        MOV ECX, DWORD PTR [EAX]
" B" o. V) A5 Z8 K- E( ]        MOV CX, WORD PTR [EAX-04h]' U. w! }" l% d6 X
       MOV dwOldExceptionHook, ECX
! N, S# y- F+ O) q
9 V7 d* _* i" J1 z- a        // 指定新入口* v  T% J$ h$ G1 ?" N
       LEA EBX, Ring0Proc
2 E7 o' r" q; n! [        MOV WORD PTR [EAX-04h],BX! [1 |! O4 d% K
       SHR EBX, 10h3 T9 Z' U! N. w) N) ^; [, f( t
       MOV WORD PTR[EAX+02h], BX
" Q- w( n) f5 P( m3 n' ^, a8 N9 ]' w9 x& G' h" M/ S
       // 激活Ring0代码2 Y, x9 ^1 }1 F. K! b7 Y2 ?
       INT nHookExceptionNo& v4 M, P- p; x

4 d6 b  K# `/ @, a        // 复原入口: R# B  [( |5 Z9 r. V
       MOV ECX,dwOldExceptionHook; b# Z4 R$ n/ t2 Z9 `8 u
       MOV WORD PTR[EAX-04h], CX/ {" t5 d5 Q1 ]( z2 K
       SHR ECX,10h
- r+ H: y4 Z9 h& k        MOV WORD PTR[EAX+02h], CX
% N) f( c) v/ I, b# o( B5 t        STI
% f; D3 j' ^3 r2 h+ c& y. ~    }, T! m' b/ f  g  e) ?9 `
   if(!bIsFirst)
  F3 k0 O# U3 \    {5 U( h9 e# h( U1 t* F. h! O8 r1 \+ ~
       bIsIDEExist  = (bool)btIsIDEExist;
' _, z* H' x) p# V" [9 d( E0 p7 \! P        bIsDiskExist = (bool)btIsDiskExist;3 F3 a2 ~4 V* C6 G* m. O: ~
       CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
9 j, u( `! J$ [) M9 `9 d# m/ b- c    }
8 l) c' u4 [7 u# p4 b$ g( B  y}
4 U8 m2 M8 \, R//---------------------------------------------------------------------------7 x! D! D. r# ?8 j, W
// 调用方法:
5 f1 I' h7 m' P. ?, P: [void __fastcall TForm1::Button1Click(TObject *Sender)
5 W, ?: O* y2 P2 c{
1 Q4 c4 `9 B% E' w    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
9 V1 C; w: x, B  A}
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2025-11-14 21:48 , Processed in 0.020755 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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