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

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

[复制链接]
发表于 2005-5-30 19:22:36 | 显示全部楼层 |阅读模式
  #include <WinIOCtl.h>/ L, i) @( P: s& B. _% S
#include <stdio.h>7 M; n" V: U" [& p
! t0 J2 F$ v6 Q+ m: r) g3 B, R
#pragma inline
5 @5 p* j( {( {, L$ K//---------------------------------------------------------------------------
4 j) M  c" M7 @6 W  |( T// IDE NT/2000/XP专用变量
/ e- S5 C  }% T% D, p; v- V' d#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS9 ?  g$ K3 X0 t+ @
#define DFP_GET_VERSION         SMART_GET_VERSION
# y% `" n0 e* r' ?#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
) C) m- S1 w  O1 U6 I7 y#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA0 k6 b- ~- Q2 v1 A+ J7 [
- g9 k: a2 i, X' e
const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令' M6 E3 K9 C% I0 W& S& m: Z4 K
const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
; A1 O& C. }/ x2 S, E8 P# x5 b
+ l" Z, Z7 l! [+ o, Lconst int MAX_IDE_DRIVES = 4;) U7 Q/ k& y6 K0 z% ^( C

: T7 m/ l( }5 `# a* h// SCSI专用变量
  w4 }+ N+ s9 @; a2 xconst DWORD FILE_DEVICE_SCSI             = 0x0000001B;
( @+ w2 C$ [  m: Nconst DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);2 Z* K6 T8 L+ [  l
const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
7 S" J  I7 h$ t: G3 t# q2 Wconst DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;0 S) G$ `0 I0 U1 }9 W

8 Z" E$ B5 d9 K8 ^typedef struct _SRB_IO_CONTROL
. `* b0 H) c- V# F. k& @7 q. Z& E{
5 P9 f# P& p3 `4 n" F    ULONG HeaderLength;& t* C5 W$ h3 Q
   UCHAR Signature[8];/ b( f" ?. p* z" I9 @( Y+ p
   ULONG Timeout;
" f3 S( Q" @9 J5 T& r    ULONG ControlCode;7 C" y& E( l( U1 A. j# o8 ?
   ULONG ReturnCode;
7 @! W8 X4 o1 G3 d7 `) Q; s    ULONG Length;+ B( u; b. s' y9 m5 u
}SRB_IO_CONTROL, *PSRB_IO_CONTROL;
! e$ ?2 u- c# Y$ Z2 B: p
, D+ F" p7 u8 N$ w. v// 读取的主函数
+ X- q/ Z% l: J+ ~- y6 dvoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);, H6 C1 M" a, ^2 p' U
: X+ o0 V, @1 l7 w) g9 M4 K: s
// 辅助函数7 R2 z3 Z2 o( h8 L. G1 d0 M9 e
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);1 J- k$ n; y& g
// NT/2000/XP函数
5 ^+ V2 |1 y! a6 K5 rvoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
/ L1 r3 ?( m% U4 b$ z( H; [bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,- T" T2 f6 h7 p* `! S
       PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
1 c/ A) O7 d0 y  Q, J  f, @8 h        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
: S3 I6 T' w4 c! A8 P* A6 k// Windows 9X函数, p* C7 ^( I7 n
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);
- q0 ~+ C# Y6 g) ]void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,# A* I# Z: O/ D  |2 m$ }
       BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
' K5 J6 e$ P0 Q1 x; u+ V8 n6 {" M$ S$ ~; e
// SCSI读取函数(for NT/2000/XP)
- d4 g% c( P# ^' WString __fastcall ReadIDEDriveAsScsiDriveOnNT();
, w4 l( g+ p% Q! k+ R. m9 N" ^//---------------------------------------------------------------------------4 F# R% u' X/ |! ]9 G+ w6 g
// ReadPhysicalDrive
4 y' f! o2 I% q% ~. I" uvoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
8 A8 n/ p2 \  b- v: t) G, ]+ x9 s{1 R$ t- \; y' V
   switch(Win32Platform); c8 y) ^3 J7 e+ d
   {% }" l. x- d6 k+ F# k4 V2 i
       case VER_PLATFORM_WIN32_WINDOWS:
+ j8 K9 T* x. _; m) B            ReadPhysicalDriveOnW9X(pSerList, pModeList);
8 m5 ^1 Z* ^3 k* l1 U, n6 @1 ~            break;
* J# F  G+ H# s2 k- r0 h! V        case VER_PLATFORM_WIN32_NT:2 ~8 ~* ~% a3 h
           ReadPhysicalDriveOnNT(pSerList, pModeList);- T8 t# H8 e2 {0 U! p
           break;
, V- N& v+ }6 Q: ~        default:* ]% [, P0 z* P8 L% x( n8 o" o
           break;6 r+ X9 I5 i- G+ z0 {
   }3 R* d  R' I, t7 n" M: Y, f( j
}
5 U# _0 M+ }! l" W% s! H//---------------------------------------------------------------------------
1 [- a7 t! v8 ^5 _// ConvertToString: j1 B1 G# s5 s: K4 t; z
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
5 a( H! F+ U0 X7 F& h{
( A* p8 n2 F- T! n    static char szResBuf[1024];# y% |1 v- {4 I: o6 g
   int nIndex = 0;0 ]4 }! E: u8 [( b3 m
   int nPosition = 0;/ V: G' ?/ _% G

* F7 T5 @  D( F; ~' f# v    // Each integer has two characters stored in it backwards
1 j0 u, y* m; c+ D. e( ^: I    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
% j& e( I$ o$ {4 T6 ^, ], q$ g    {9 T) N. b: i8 H9 d2 A1 J
       // Get high BYTE for 1st character% }& Z: V) p% x% e+ k
       szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);1 f; Y( h3 J0 G/ `1 o* y" {1 g
       nPosition++;
$ y1 g+ {+ P* g6 C  L& a: S' j! O
+ ~" W5 h7 ~* q7 ^# \( H        // Get low BYTE for 2nd character
' V1 w4 y6 a+ [* [/ W3 F) U        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);  e) j1 `# k3 r) y6 |6 N
       nPosition++;" b3 K$ e  m, B1 p- I- }" D7 S
   }
! V, @" F# Y; R) v
- N& Y) [- D: r% r0 t% p    // End the string) d# x3 \) m5 X7 S5 P2 a1 v
   szResBuf[nPosition] = '\0';
& E, R: A; o% \" `. v6 `" L& c; r
- e- x# }- m; L+ ?: e: d    // Cut off the trailing blanks
- N% t* |/ e4 N8 y: v; \    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
' v, K2 a' [) w( K  i, V        szResBuf[nIndex] = '\0';+ X- s, D3 {$ A2 U6 [; U
  J3 Y0 t  U4 y) G# b$ j
   return szResBuf;* X2 k# o+ F! Y( [8 A6 ]
}
" a; @- S$ \4 F; ~- n- M+ V3 n% I//---------------------------------------------------------------------------
2 ]* D) E5 t/ W; ]: u5 n/ O' I// Winndows NT4/2000/XP 代码' g) J  X& q/ q. |. W
//---------------------------------------------------------------------------
7 Q" ~4 ^+ Y) ]1 d! t// ReadPhysicalDriveOnNT1 _+ {0 {* Q% [2 E$ S! ]9 ]
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)0 P+ j1 Y! }: {# v/ S% o
{' h$ m  m7 n0 ]% [
   // 输出参数
3 J2 \, b3 X/ h6 K5 C$ o    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
4 [( e8 H9 W. K& B& X1 ], a% a% f8 Z" b* d; J
   for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)* e3 ~1 Y% L1 B% [& m! z
   {
' {; E9 Z1 J" ^8 O7 d        HANDLE hPhysicalDriveIOCTL;
0 ^$ _7 x0 b0 v) \! L* b        char szDriveName[32];
6 Z# i5 ?0 }/ i0 S3 ~% l
5 ]# }* x% K7 ]( X) g        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
4 B3 [; o6 r' m  w- R        hPhysicalDriveIOCTL = CreateFile(szDriveName,. f; t8 C$ ^9 |* g/ O0 E
                       GENERIC_READ | GENERIC_WRITE,; Y5 b# ]% v( Q
                       FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,1 ?3 i5 i. C4 j. K' I$ ~
                       OPEN_EXISTING, 0, NULL);
/ X+ l' G4 t' I; g; j: F1 x' m0 b/ P# f7 A; [" G- z
       if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)& o! [3 w4 w# C& I1 M
       {
- R8 w. r: R/ G9 P; V            DWORD dwBytesReturned = 0;
# l5 j: R% |8 v6 H            GETVERSIONOUTPARAMS gvopVersionParams;
% J0 ]3 ^& J) B8 N, P+ p) ^4 U( z7 w2 I* C- }# H0 I
           // Get the version, etc of PhysicalDrive IOCTL, x" G, c* p! P8 e/ d4 J
           ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));) R  ^. c$ G* U

0 w# ?! t# q7 [& m6 b' i2 N% i            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,. [) ?. P: z* j
                   NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
$ V7 `+ X+ d( x4 s% r8 W& E) [                    &dwBytesReturned, NULL))9 ^3 J  r( d& U, c0 M' f3 F5 M% E
           {6 z, V2 ]( p+ c! y( c
               continue;
2 [6 N8 d; h) \6 M4 n1 z2 T/ d) J7 j            }
$ y  c' ~# K& j" {, G
  W  l- V: F" i& l" q( v            if(gvopVersionParams.bIDEDeviceMap > 0)6 ]7 A0 i4 H1 D
           {
8 }4 a% \6 k# T1 h5 [) s                // IDE or ATAPI IDENTIFY cmd/ V2 n8 s5 j  w$ j
               BYTE btIDCmd = 0;
. S& L2 \  @% T7 T: @# J                SENDCMDINPARAMS InParams;" i& m; F* Y* o
               // Now, get the ID sector for all IDE devices in the system.
4 p# A9 `0 f: g) ?8 H                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
" a5 P' A: a; j5 i6 q- j9 e8 |3 c                // otherwise use the IDE_ATA_IDENTIFY command8 O" m4 f! f# U1 |4 P( I
               // 具体所得结果请参考头文件中的说明* d# j) i( [3 V5 B/ K0 ?
               btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
4 l# B7 D; ]6 J) x+ A# j) X                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
6 p. g2 G4 w0 }                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
5 p  x! ?3 N8 ]. {# t0 l/ ]                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));) t+ ^; G3 Y6 I, {0 Y

  K/ t+ ^; u0 v& z0 `$ ~4 E: |                if(DoIdentify(hPhysicalDriveIOCTL,# @- ^' s. ^2 n+ y. S" J  W
                    &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,# k2 ~4 g+ B  p' a
                    (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))- W9 u. S( `, o( r
               {
: p2 g8 ?( v* l  s( l2 X' k3 h/ q                    DWORD dwDiskData[256];
& p# J0 f# U* T7 C8 n& I/ W                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
3 Z0 d; ^. w7 h, b* d) [; N: s                    char szSerialNumber[21];
( R# X$ ^; R- s1 M5 t. q0 Y                    char szModelNumber[41];
- W. m# O0 C2 w) A. X6 _1 {7 Q, F! c
                   pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;4 J" k3 t4 x, z4 j* u) C2 Z* E
                   for(int i=0; i < 256; i++)9 Y/ P. X3 T/ ?. [& M4 z
                       dwDiskData = pIDSector;
5 N! r# W6 i+ }; r                    // 取系列号" U. H4 k- |  x% [6 ~
                   ZeroMemory(szSerialNumber, sizeof(szSerialNumber));6 K- i5 d" b: l% u
                   strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));* W" E. P0 s5 b6 S5 m3 Y8 l

" h/ a  H0 i* k% V# L; w( K# J                    // 取模型号
! Q# f; e" ~1 j" Z                    ZeroMemory(szModelNumber, sizeof(szModelNumber));5 b% z3 _# Z6 J! c5 A/ P( l/ y
                   strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));! {2 K2 L0 \. n% `  E, ?% q0 }8 Q: p
- M1 |& O( v' S( y) L
                   pSerList->Add(szSerialNumber);& t# X0 V+ v$ R5 ?2 G
                   pModeList->Add(szModelNumber);
1 `+ d. @5 n  H+ e, `( h. T                }! d! a# j: `, |4 b5 U( C' I
           }( Q9 C7 N9 g& T3 F! {
           CloseHandle (hPhysicalDriveIOCTL);3 s: |$ e3 H) T: Z. [: K
       }) J+ Y0 A7 q% w+ T( w: N; U
   }
% N, M8 `: q. D}
/ b% f' ], ]' E) r//---------------------------------------------------------------------------
$ m9 D- p1 b: |: P/ g4 P  {$ e// DoIdentify
+ F. o0 p) [, y. P' Tbool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,' R9 L$ i/ E9 N. n
             PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,) j9 d' c6 F3 R# D/ n' F
             PDWORD pdwBytesReturned)/ _- K  U  x7 \6 d+ w( Q
{4 S( n$ z" m% B3 e! C1 t
   // Set up data structures for IDENTIFY command.% O+ Q+ q$ o# E
   pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
: s' s8 g+ V5 m! z  W! A$ ^    pSCIP->irDriveRegs.bFeaturesReg = 0;
' g  P% s& R6 j% Q; {. ]: G    pSCIP->irDriveRegs.bSectorCountReg  = 1;
1 g! M0 l% |* T  v% W  Z9 ^    pSCIP->irDriveRegs.bSectorNumberReg = 1;
. m6 `' [% q' ^9 W( _    pSCIP->irDriveRegs.bCylLowReg  = 0;
: \" l2 o  w& ]( k- R5 W    pSCIP->irDriveRegs.bCylHighReg = 0;3 P: d3 i$ X% b% f
* D  l8 A5 b1 v4 \4 a
   // Compute the drive number.(主盘和从盘所对应的值是不一样的)
, r* ^8 y$ `9 C+ Z, f    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;8 h2 _. p- z( N; v) ]

0 k- K* z" N0 W0 k, Q8 Y) u/ A    // The command can either be IDE identify or ATAPI identify.
* {% R- ^# q# t- U1 F- J7 Y7 L; @    pSCIP->irDriveRegs.bCommandReg = btIDCmd;2 H/ e! d. b- R0 h+ v
   pSCIP->bDriveNumber = btDriveNum;
6 s2 Z2 j6 e: x7 I( d( K, G6 u    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
. @3 ]( e4 F8 f" Z$ j$ Y% m) C# C/ [! h. s3 G
   return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,) R% I& j' q( z7 p+ E& x9 H
          (LPVOID)pSCIP,
; E* h( l! w5 t$ J. W: U) L           sizeof(SENDCMDINPARAMS) - 1,' |& c* B( g6 o2 g+ }
          (LPVOID)pSCOP,5 T* h6 W1 V$ i8 [% ?
          sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
" @/ N2 F9 C; b/ c           pdwBytesReturned, NULL);/ ^: }3 T5 |( ~5 l" F2 X- c2 M/ E
}9 L! K; u3 Y1 _5 ]7 V6 Q3 K* u
//---------------------------------------------------------------------------$ ^1 W6 G+ U, |8 Y4 a$ v! f3 @
// Windows 95/98/ME 代码
, E- z0 r$ t! s5 e9 m2 r$ h- T//---------------------------------------------------------------------------
' A/ U4 B2 F; x. Q- D( o// ReadPhysicalDriveOnW9X+ k& ~- q5 t5 L9 N; C& \2 ]) W1 \; t
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)
+ r5 i* C% I% W; `. a% z' ?/ I{
. s  ^+ L# Y" i: i    WORD wOutData[256];& V3 S: t% k& c0 d5 e; }
   SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
; v1 }" f$ _8 D: E! i9 B
% z5 H$ s* i" {    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
$ N$ Q2 t. ^% _* g7 L* R% f    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
/ b5 z5 g2 b( b5 B    // 避免蓝屏的出现。(期待高人能指出原因)
& v0 R( @& f! _* G7 ]5 N    for(int nDrive = 0; nDrive < 8; nDrive++)& W$ D# @# x4 S" U2 W! U
   {% ?- L* m  }! z
       WORD dwBaseAddress;
. R) Z% }  {, U# ~: q0 [! M  ?# @        BYTE btMasterSlave;         // Master Or Slave4 N2 @/ u1 |) l3 f! @2 }1 u
       bool bIsIDEExist;
8 ^! _( t& a* T+ j' @& ?# Y        bool IsDiskExist;
+ h7 f! X8 c3 P7 O. X. X: H- }, }& `; x0 j: d3 {
       switch(nDrive / 2)
& P9 I% n+ W6 v5 f; j2 l1 l. ~        {
! f- G. n. ]: Q            case 0: dwBaseAddress = 0x01F0; break;
3 O& S# _6 X) u3 Z, b" o            case 1: dwBaseAddress = 0x0170; break;
- e9 A: S( h2 ^1 }            case 2: dwBaseAddress = 0x01E8; break;+ N6 q% j% p0 ?: g6 P
           case 3: dwBaseAddress = 0x0168; break;
" @# g7 {. n7 ?" n6 a/ z        }
1 [0 a0 i% e! b' O5 `# m5 `
* b. ?1 _: R  P+ n" R        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
# G+ G3 ~' d6 G! k5 |% O5 \' @! f) i* r2 t3 Y) }; v7 E  `* x
       // 进入Ring0# `. @9 W7 a* X
       ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,8 o/ x! H; \3 t7 g! J
               bIsIDEExist, IsDiskExist, wOutData);  s  X9 s# D0 X  v
   }# H9 F7 J% H* H% r+ v0 v, o
, O! C8 p, k  S+ z
   // 开始读取
. `5 F7 @. q! {    for(int nDrive = 0; nDrive < 8; nDrive++)6 Z5 Q5 L- S: \2 K  \* c, i6 |4 E
   {
& f# ?6 c& N" }6 h' m6 ^        WORD dwBaseAddress;. {' M: p- v2 v! T5 j& _6 ]" }
       BYTE btMasterSlave;         // Master Or Slave
1 c! c0 \& r4 D* d4 v% C        bool bIsIDEExist;* P! [7 t, A& s: g
       bool bIsDiskExist;5 z& \: ^+ L/ j; y; \/ d' C
       switch(nDrive / 2)8 Q8 N: I  g& h) v; t0 k( b" n
       {/ L8 d4 z+ z# K
           case 0: dwBaseAddress = 0x01F0; break;
) A% S* |! I4 e4 N- d            case 1: dwBaseAddress = 0x0170; break;) Y4 m. N  `, s  b9 J
           case 2: dwBaseAddress = 0x01E8; break;
) Q6 B1 w% F, l+ c' u) Y2 \% Q; J1 d% e- s            case 3: dwBaseAddress = 0x0168; break;
. M5 ~6 E* Z0 o; ^# Y2 G: L        }, r. x) N# w9 B1 d3 E$ M7 S
. m5 J- Y9 K, k$ X& n
       btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);6 q4 {* g6 E1 f7 Q- q$ Q
% M7 F$ R$ [; L& M4 Y
       // 进入Ring0% t8 s6 {" n+ w1 x& {
       bIsIDEExist  = false;+ m, }$ p3 h) g) a& @: G. i
       bIsDiskExist = false;
5 m- Q+ Q( s  l1 k" q2 t0 ?        ZeroMemory(wOutData, sizeof(wOutData));
4 m1 o) @' t4 m5 E9 a% e* u; q8 q0 Q' p5 O7 ~) p( L
       ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,0 G" K* V; H& o  s. Q
               bIsIDEExist, bIsDiskExist, wOutData);
) x/ ]( \9 b% s; M
: Q! W0 }- F0 |- _' y6 C9 V  R        if(bIsIDEExist && bIsDiskExist)3 t8 Z' E0 |. M9 a% \  z
       {
2 a5 B* t$ \7 y  R% e* E            DWORD dwDiskData[256];8 r' g4 V* ^% q* e; g
           char  szSerialNumber[21];
& c+ h- q' A0 h7 `/ A( r            char  szModelNumber[41];3 S4 \8 [; b- ~5 l

/ L$ Y, X; c5 d            for(int k=0; k < 256; k++)
1 p/ E7 i$ ]% }# j, Y# ~: ^4 y                dwDiskData[k] = wOutData[k];
* J6 Q9 U/ e9 t) I2 m
! Z% S* {, X' P1 Y8 [            // 取系列号
( S; I; D# {  W0 f            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));4 i( Z) L1 n- I  s& S
           strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));4 ?/ l( _, L$ B  [, k; X2 A

+ `5 R: Y$ G+ N: R4 X            // 取模型号6 o0 G1 t  c; B1 f. M+ F9 o  A2 {
           ZeroMemory(szModelNumber, sizeof(szModelNumber));
- F& S" L- h% P. V# L0 G/ p            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));* I5 s% O& k8 x$ D
7 d2 j4 ]% c  Y1 `$ {% I
           pSerList->Add(szSerialNumber);
0 s4 I8 L, d6 c- \3 _) J0 C( n' a            pModeList->Add(szModelNumber);8 ]' S3 u' w) v+ C! B
       }  h! p: G7 a8 n! ^' s0 @2 d5 o
   }
8 A; }% s, \( B" [1 P9 r% N    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
/ k9 a" Q& \* p& g! P}' C' Z: W/ P& d- n! U& |. M
//---------------------------------------------------------------------------9 T0 @$ X  h5 r
// ReadPhysicalDriveOnW9X_Ring0()% v+ i6 d7 D& Z- Y0 k' {7 o! D
//
# p- e/ g( y+ `" V- |/ ^6 K( E// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
* s" }% z8 G2 A! [4 E// btMasterSlave = Master(0xA0) Or Slave(0xB0)
( r0 b+ U( O, p6 ^9 T9 v6 d; B! B//---------------------------------------------------------------------------
8 f; M0 @  p7 x) mvoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,5 {% @1 ]; B2 R0 \$ O& ^
       BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)4 b3 X9 t( K; ]% A
{
$ G/ |8 \( d1 F    BYTE  btIDTR1[6];) U5 f( q. B' n7 c& I8 _. q
   DWORD dwOldExceptionHook;5 c4 X3 w" `( _' X3 d5 D
   const int nHookExceptionNo = 5;
, B& T$ i4 J( N# F/ M
$ E- j9 }, @1 ~; B' Z) Q" Q3 S, ^    BYTE  btIsIDEExist = 0;+ }2 Y( H4 n) L8 ~- F
   BYTE  btIsDiskExist = 0;! B) j# A! n  `& F- P
   WORD  wOutDataBuf[256];2 l4 R. a; u! [7 C- i
# J( T2 X/ M8 [0 |) r. Y
   BYTE  btIsFirst = (BYTE)bIsFirst;
3 [; ~/ G7 a4 k/ @( J
+ Z3 ~+ F7 d1 E3 E1 z$ B" ]' d1 A    const BYTE btBit00 = 0x01;" J, ~( A) h) \0 j- a
   // const BYTE btBit02 = 0x04;% n! A" w/ F% E3 `1 U8 Q7 \
   const BYTE btBit06 = 0x40;% Y" z* i, E* R8 h. e: i
   const BYTE btBit07 = 0x80;
7 M# m$ |2 S1 @    // const BYTE btERR  = btBit00;
. m* U3 \0 Y8 M% z- L/ h. C    const BYTE btBusy = btBit07;1 x/ s6 q+ Q& K
   const BYTE btAtaCmd   = 0xEC;
/ y7 O" T3 B4 [1 H    const BYTE btAtapiCmd = 0xA1;
6 h" u: k: o+ O1 e( R' v2 B) D; Y1 ?" i, E0 f/ @! n) {# p3 U
   __asm; _5 }% ^* H2 Z9 M
   {1 p- m7 F4 ^' B* ^1 \5 Z( q" c
       // 必须先执行这条语句
7 n0 O% S0 x. L4 d" z- W* j7 ]5 u8 o- x        JMP EnterRing0
9 l1 H, Q- i, z1 E3 Y# R. l+ H( k) ]. \  u9 ~( N6 @
       // 定义过程* V# [6 v+ u. T1 a# _% S
       // 等待IDE设备直到其不为忙为止
1 I+ S1 S: _+ n4 R7 h        WaitWhileBusy proc; y& X/ t9 d& {  t! U: [! Y
) \) v  K9 \. q5 q
       MOV  EBX, 1000005 Y3 h! [3 u4 b: G! G4 A
       MOV  DX, dwBaseAddress
3 T' ^! `. P9 }: ?        ADD  DX, 76 R# u" \7 ~! Y7 m1 O
9 ]& A8 ]0 V, T% {3 p0 F% x
       LoopWhileBusy:  k- h3 q1 G: Z% [
1 H, d0 p" z: U2 C
       DEC  EBX
- y+ q0 j- n* c6 O8 H        CMP  EBX, 0! Q+ ^, Q1 h" f0 T, `
       JZ   Timeout4 Z. y& j# X" ]# t* A
       in   AL, DX
5 U% Y: k# m' h; `/ j! U2 ?/ Q' [        TEST AL, btBusy% e# G$ @- ?2 I- D* U
       JNZ  LoopWhileBusy2 _( z1 [& I" ~' M* D1 W
       JMP  DriveReady% Q8 x4 p# e7 L
( W8 e5 K; }0 s+ V, ~3 B
       // 超时,直接退出
5 b$ ]3 `7 \' C5 M. Z5 I/ `* {        Timeout:
* D6 K( g$ i6 J7 D1 E2 X# P9 f0 c+ r4 ]        JMP  LeaveRing0
/ r) ^. P+ T! {1 S, ~' u5 l! K        DriveReady:" |- D% \! s0 J
       RET
4 t. c% K! u3 d. f! T        ENDP   // End of WaitWhileBusy Procedure
- S: F4 O6 \' J) g8 Z: K0 t2 e3 V! ~  \6 k" g
       // 设置主盘和从盘标志9 X3 M( {* c% Q3 C+ |* {
       SelectDevice proc
" s& ]9 D  K! u$ E( K% f$ |; }
6 E2 n: H4 n  K9 z  N2 I1 d        MOV  DX, dwBaseAddress0 ^3 l+ u0 L7 T" A5 m
       ADD  DX, 6! B8 i( G' b6 _/ }* Y! Q/ O8 j- [
       MOV  AL, btMasterSlave
  i$ M$ z  [) B: g
: q" L0 t9 @5 {0 f- ]9 z        out  DX, AL
+ c+ t8 F; L1 a" d$ u3 U  Z        RET6 i; h* [$ ~# W8 [

+ U, ^9 f' e& E6 E0 J        ENDP  // End of SelectDevice Procedure9 L) }* X. J/ L9 j

5 F# v: h) z+ p        // 向IDE设备发送存取指令
& c% D6 h1 B. k( f2 n6 w) H4 \/ s        SendCmd proc  u9 S- y% M# x. L9 s' ^1 q

) C) O! ^5 ?9 g! e. S0 L        MOV DX, dwBaseAddress
. O1 D9 f8 K/ k+ P  s  g# O        ADD DX, 7( h6 g9 e! U; m8 q
       MOV AL, BL // BL是主从盘标识,在过程外设置
, ?! V9 C/ i% c4 n3 L: }1 K        out DX, AL
" S' j! K# [8 ~' E6 _3 i' M        RET
; o7 ]! o' S" a2 f        ENDP  // End of SendCmd Procedure
- k* e. {+ h# q, ~2 R) K6 G# Q; H; ^1 v2 [3 L3 p; O
       // Ring0代码
/ D; [) l& Y  v/ m3 w        Ring0Proc:
5 X! _% T9 I. O9 f5 l) F. c2 H        PUSHAD
& M# m$ n1 v- r* |+ Y        // 查询IDE设备是否存在* j, \! Q4 j6 d% P& |$ k2 Q% d
       MOV DX, dwBaseAddress
6 I1 ]+ ?+ T' q# v8 {        ADD DX, 7
& d+ K! E; r- b        in  AL,DX7 m: _, e$ G! J! e5 ]% ?1 g
* C9 z; f4 U0 M6 W' n# _
       // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回" t1 r- r" @4 Z. Q
       CMP AL,0xFF
( L( b% g# J9 T8 U* |0 ]& e        JZ  LeaveRing0
6 J0 b' N: y+ G* R  t$ A        CMP AL, 0x7F
& h  q. H* T3 p1 l, y9 r3 k- q        JZ  LeaveRing0
& @$ U6 T8 B7 Z/ `* H5 C9 S7 l0 d" A. n( a) A7 U/ G
       // 设置IDE设备存在标志
0 F  G( s. G+ F% g: A4 Y        MOV btIsIDEExist, 1
; U- B3 w3 y9 [" w; ?4 j6 j2 D  Y7 a$ ^' D1 x! {% ]
       // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)" D3 w  t0 _0 V% v1 S% Y
       CALL WaitWhileBusy7 P% r, r1 z4 _1 u; m
       CALL SelectDevice) r- ^- E, |; f4 R2 g
  f6 u& ~% a: C0 Q
       // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏9 t$ N1 ~' e% A: E% Y; n. a
       CMP  btIsFirst, 1" B# G/ {7 X/ L6 i/ \; Q6 i3 x8 k
       JZ   LeaveRing0
9 ?2 B  a( u, N3 v6 Q9 m: U, i- S- r" J+ t% l0 P$ v) p  h
       // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
- i7 u$ ^% m% t  n/ m        CALL WaitWhileBusy
8 k. Y" p! a' p( i2 t* ]
+ b/ \7 g' K, ^3 S5 i# a6 L        // AL的值等于cBit06时,不存在驱动器,直接返回- o. Q. O8 r$ d6 }3 ^
       TEST AL, btBit06
% W6 \  C0 x( \6 K        JZ   LeaveRing0
5 L; ]* K! L; p3 ?7 m
, x, G! O4 g2 l" x        // 设置驱动器存在标志- l1 t! D' N0 v" K9 o
       MOV  btIsDiskExist, 1( z# I" j! p2 n" T3 b
6 s4 \" G7 @# p
       // 发送存取端口命令+ r+ E6 k  ]# }1 E2 E+ z
       // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,% z  ?5 U& C: H9 U; q/ [; `9 S; m
       // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令, {$ F  U" r2 l# l3 G
       CALL WaitWhileBusy6 e! v2 h( d$ z) W+ N' s
       CALL SelectDevice    // 设置主从盘标识) O! L# s+ X. h- u5 w$ x
       MOV  BL, btAtaCmd      // 发送读取命令
. `5 N" x, H5 Y: s        CALL SendCmd
5 i/ @* y: u; U4 K% r- \        CALL WaitWhileBusy
  F1 @" k% e: r3 P0 q2 c, V9 }- t) X% y* ]
       // 检查是否出错  q. A  s. Z8 q' N/ [
       MOV  DX, dwBaseAddress
  W% d4 H) D3 i! n( D3 X        ADD  DX, 70 H% g9 c+ ?6 d: X3 A. d5 W; D

9 H- C$ g. {3 s3 Q0 |, i: t        in   AL, DX9 @+ \' p/ n! J+ {/ x
' }  g2 O) ~0 F" Z
       TEST AL, btBit00( l  Y/ h/ h9 s* M
       JZ   RetrieveInfo   // 没有错误时则读数据% y3 e% r3 V; n8 O" H8 _

+ i. H( {) d6 s1 f. {0 Q, W" A        // 如果出错,则进一步尝试使用ATAPI设备命令
' u! `% t$ f; s- r! s        CALL WaitWhileBusy
% `0 g+ r1 m* W$ F        CALL SelectDevice
5 \$ J9 ]/ ^. K  r        MOV  BL, btAtapiCmd8 U* f  e( f: O7 Z" y$ l! S
       CALL SendCmd
+ z  `( `: p& p1 W4 q4 K: m" J        CALL WaitWhileBusy
4 N8 v4 {$ j) I' o
5 j4 c- n6 [. K$ \9 Z, h        // 检查是否还出错  |/ W6 W" w. o* n- _$ j' C  A4 n% v4 x
       MOV  DX, dwBaseAddress
, r4 H; r  x8 V' m( J        ADD  DX, 7! v$ a7 [# e3 B' Z
       in   AL, DX
- |" f% _2 X* n$ I& l6 F, T        TEST AL, btBit00
! x$ O3 H1 J; M7 V& a& N% ~5 [        JZ   RetrieveInfo   // 没有错误时则读数据& E1 P% u  o' Y* O- m
       JMP  LeaveRing0     // 如果还是出错,直接返回
0 [. I( |6 z' u( `% J9 Q  D: F; C' `% a$ ]7 n5 @2 q
       // 读取数据$ @2 r& a7 i6 R8 u  u! b& F
       RetrieveInfo:
4 W+ g+ p! ]% X1 f; H$ k
+ l$ |/ |  F3 D# w# G: J8 L        LEA  EDI, wOutDataBuf$ u& ~/ `0 W0 @2 T9 F' g
       MOV  ECX, 256' T9 U- D# q9 A1 z2 p0 Z
       MOV  DX, dwBaseAddress' R6 a% O' f% N# z
       CLD# ]4 ?: {+ N/ y

/ J1 {3 I! U' ^( Q8 Z9 Z6 h        REP  INSW! Z2 L4 d8 o* {- v8 r
: @2 v' y. X$ V
       // 退出Ring0代码
5 [: @6 o' G- I        LeaveRing0:" Y0 A: e$ @; s  [

' B0 [' ?: J; A7 [/ a        POPAD& A- X% `+ ~, x- X3 K
       IRETD
$ v- S$ H0 N$ y7 k
  C+ `! S! V4 t  z; U9 V0 l        // 激活Ring0代码
  r. G% [9 x& l3 ~% d& l4 |5 Y        EnterRing0:
2 ?3 l3 i6 i0 x" M! F9 O8 `7 O! v) D1 R
       // 修改中断门/ \5 g% P: ?# M& _: F" y
       SIDT FWORD PTR btIDTR1
! s' K  G4 F' \3 b        MOV EAX, DWORD PTR btIDTR1 + 02h$ S( ~, h! M5 ~3 k* `. J
       ADD EAX, nHookExceptionNo * 08h + 04h% `+ j4 F7 h# ^8 ?+ t( _
       CLI
* u7 I5 ^' d* I0 T1 C' ?  b0 t" o5 _/ s: O, `
       // 保存原异常处理例程入口" _1 I* v" {) H
       MOV ECX, DWORD PTR [EAX]' J% q: O3 e* d9 S, D& Z) t3 _6 X
       MOV CX, WORD PTR [EAX-04h]
$ |* B# r+ d* C- q( h9 R% b$ D        MOV dwOldExceptionHook, ECX/ _0 |# w) b" e7 c" @% `$ g
1 F# S; ^! Y& x3 t
       // 指定新入口
* f" J+ G2 }  x        LEA EBX, Ring0Proc
- C1 m$ X+ |# o; j9 b  P6 ?        MOV WORD PTR [EAX-04h],BX+ S$ S, Z6 ]" A& D
       SHR EBX, 10h
3 g$ M4 O* f4 r% A* d* u' Q        MOV WORD PTR[EAX+02h], BX
; v0 T* I* n- g& A3 T# X0 [# m4 I0 O8 k" @
       // 激活Ring0代码
* L$ Y: z8 U8 h) f. t        INT nHookExceptionNo
' C9 G! M6 V. f6 N( e
" u5 ?0 K1 S/ s% F        // 复原入口# t( B6 b1 Y# ~$ L# S  P! h
       MOV ECX,dwOldExceptionHook
! s+ V# p! ^2 I& L' m4 o' F        MOV WORD PTR[EAX-04h], CX
  i- Z2 l2 m' G        SHR ECX,10h; S- X3 g9 n  g; _" `- M% r; d* ^
       MOV WORD PTR[EAX+02h], CX
- E) g. v6 I" a7 c4 S        STI2 v6 h' E& e4 w9 @! y3 X7 j
   }
# t* S, b& H" J: N/ \    if(!bIsFirst)
; ]* V; m( w  i, j- v, Z- i    {/ @& K& k8 y( {; [) ]
       bIsIDEExist  = (bool)btIsIDEExist;
9 b& L- L+ `0 t6 K! b        bIsDiskExist = (bool)btIsDiskExist;
' a% X3 d0 D$ V; y& y        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));8 ?& s* _- U% ^2 E
   }
9 b7 s8 w( w" k" _}
; M2 B1 X7 y# }/ [/ b7 f) ]//---------------------------------------------------------------------------
' p( B: w5 W" L( B8 H8 e$ }// 调用方法:
7 e8 Y1 D) j( I% u) Ovoid __fastcall TForm1::Button1Click(TObject *Sender)1 B. a* _3 _, F1 R. j$ z* h2 q
{
2 w3 m  p3 E, W5 w' F: i    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
; u8 i1 v& D5 E/ ?9 N4 `}
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-6-18 06:59 , Processed in 0.019939 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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