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

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

[复制链接]
发表于 2005-5-30 19:22:36 | 显示全部楼层 |阅读模式
  #include <WinIOCtl.h>
9 q" y& w5 `% t, T4 M4 @* e( y#include <stdio.h>
" S# P- z1 V3 c2 a, w
( B$ |$ u0 a& O6 M# R/ w#pragma inline
7 B) Q5 c" D0 k7 `9 ~& w, P. \+ w& G( z& A//---------------------------------------------------------------------------1 n0 n+ {5 h6 s9 e' K
// IDE NT/2000/XP专用变量
' O9 F: Q: A3 D  T7 m* r' E/ K#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
% |% d% M- O1 Q( q, |#define DFP_GET_VERSION         SMART_GET_VERSION
& t" E) z3 v  D0 k1 Z0 S- r* R#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND; C- j, e5 Z5 P6 b
#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA% D; h1 `* j3 E" {; ^

3 |$ \( p* i* Z3 |const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令) ]) z" a& |+ Z4 }* O
const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令8 @" ?! z+ W) v. Q# S  K

) ^( }5 m; N% k9 g- U" Gconst int MAX_IDE_DRIVES = 4;7 T" R. P/ e. A; b

  o% P. E  {( X3 {& n$ ~// SCSI专用变量
: G+ c. }$ F% vconst DWORD FILE_DEVICE_SCSI             = 0x0000001B;* _# s( p! Z) j, L- R: m: r& m  r
const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
: T) [, J$ l8 y# o7 `const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
+ x4 ?% @( E  u% lconst DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;! n, a  \8 i: x1 X, m

$ f4 [4 }% C$ x" |typedef struct _SRB_IO_CONTROL" o( s; x1 K6 C7 V! c4 `, a6 B
{. Q' C5 t2 I5 Q/ e" I
   ULONG HeaderLength;6 H5 @4 {; n8 l6 L# z% r/ K! i
   UCHAR Signature[8];4 c5 [0 _8 \! Z: O
   ULONG Timeout;
8 Z) B$ g% L; J3 {. J    ULONG ControlCode;
! l, K9 R* p, T( ^# G    ULONG ReturnCode;' R- ]: P7 H# F3 h2 b# d
   ULONG Length;8 T8 P' n7 W+ S5 b9 o
}SRB_IO_CONTROL, *PSRB_IO_CONTROL;. a" [) ^# E) O: Q: n

" T; {7 f1 |& U; z: I! Y! q// 读取的主函数
7 h4 T# _) K. Z0 f! {  gvoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);7 W' L3 h; B8 @+ L. U

6 B' n2 h% A3 f// 辅助函数! P' b8 t) q( h1 A; @. A! {  ]$ b
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
( \& G* Q, D& ^1 n6 J0 ]// NT/2000/XP函数
  g% d: G1 U3 H1 s9 xvoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);; e0 n) g8 ]% [. b4 b; C$ G( W
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
* u! U( ^2 f: l6 i        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
( `( Z0 X. b! T1 L, H        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
. a9 [- Y0 }- ~+ k// Windows 9X函数6 u% K: Y  N& o* _. b$ m0 a
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);
* |& k9 Y! u9 J) @# N8 Q( lvoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
6 [' X3 K7 ^7 U, P! |. l; l        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);5 m1 `) s8 ~* P- L2 U
9 J% j" U8 |. g( Z. ?2 v
// SCSI读取函数(for NT/2000/XP)
0 c7 t) h5 z) O- m+ J  lString __fastcall ReadIDEDriveAsScsiDriveOnNT();" p) t2 b9 A$ o, n3 }, w8 o9 o  G
//---------------------------------------------------------------------------: r, d6 [. Y$ P1 _1 R+ }5 ~
// ReadPhysicalDrive7 R: y5 P# O9 P2 t% C6 ]0 |
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
4 c# S% H" U/ h* k3 |9 |! Z{
' [! S+ L3 p0 K/ x% D6 g5 {    switch(Win32Platform)( o, ~) O5 I6 c
   {& f" `) ?( _# f6 ]+ |# n, z
       case VER_PLATFORM_WIN32_WINDOWS:
) G% C- |* o0 t8 s% u            ReadPhysicalDriveOnW9X(pSerList, pModeList);
) {; \& R" F- @. E9 e2 ~            break;
9 z4 u, H( E  o        case VER_PLATFORM_WIN32_NT:
. `) r7 A( |) N+ {5 q1 S            ReadPhysicalDriveOnNT(pSerList, pModeList);
0 \2 O% Z3 p+ |( D! {            break;  t3 S- d" g, R4 T1 M2 `
       default:
0 ?& K# U+ o) F: @            break;
& s# D& L' O+ L3 }+ O    }
# t  `, a- S4 r9 w4 n. o}- t4 i0 A7 n% T2 R
//---------------------------------------------------------------------------% ^$ H6 D" m  L! K
// ConvertToString
8 ~7 i$ O, M7 d9 R' n$ X% g0 h5 }char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)! D: i" K& S/ E! F1 q, G
{, o% L7 E4 o0 w7 e
   static char szResBuf[1024];
: A3 U- l% E6 b& k( u    int nIndex = 0;
* q' J* m7 N5 e& E    int nPosition = 0;
% B5 w8 @, f# A4 \/ V6 W& m/ }/ A" g# K( p! M( g1 h5 ?! _% F1 K
   // Each integer has two characters stored in it backwards" P% M, d' q/ v! y. c
   for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)4 M: U4 s2 G6 c5 Z5 N& [
   {) I! Y* f! j) C
       // Get high BYTE for 1st character" I7 W2 X) p; f* e: D; A
       szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
5 [. {1 a- c# F; V" a        nPosition++;
$ Y! o: S  ]3 K" j3 s0 j- N2 Y0 `( O; L0 I9 Y+ F' u# N
       // Get low BYTE for 2nd character
' {9 N' b, d" c. a& N$ a: z        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);- A% a2 }* N/ H. Y
       nPosition++;
. f% H/ Q1 V4 \2 }4 k; ]8 t) H    }
1 d5 A2 L! l4 _
% ^( G0 h9 ^# C+ ]' d+ z& m6 V# d    // End the string% @- v9 I1 K5 l. i$ i9 g
   szResBuf[nPosition] = '\0';7 D; z! N$ Z7 V: Z2 y8 k

+ z* ?  q" E$ Q: `2 @. H4 V) V    // Cut off the trailing blanks
/ E/ \/ s" j1 }/ Y. ~    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--); X- g5 N/ h3 }
       szResBuf[nIndex] = '\0';
0 J1 G$ i- n* j0 ~9 y! A; d2 k+ L
# t5 D) Q( A- i3 X    return szResBuf;
' S$ t3 ]' Q- A+ B7 ^* s5 s$ g}7 n9 c+ m; ~, J/ h- g
//---------------------------------------------------------------------------
2 ^7 r( s- ~0 Z// Winndows NT4/2000/XP 代码$ T, l: h9 \7 F* O2 u  H: y1 ~  `' Q
//---------------------------------------------------------------------------& q7 M4 o6 ^  W1 y& F$ T
// ReadPhysicalDriveOnNT
' k" g8 T9 `: g) `1 [void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
$ P: k: O- z2 s5 i{# ]/ V5 C, s, Z$ n% O0 Y! a
   // 输出参数/ u  h% D2 X& z+ e" ]' S5 a
   BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
3 L0 R8 V, k5 [: K$ w. k: E' ?# L% z& z- h9 y5 S! S
   for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++); u! g" A# }  _/ ]- T. ]
   {
" {3 }+ X% ^5 ^8 }! R  \        HANDLE hPhysicalDriveIOCTL;
; k: Q: ~6 G+ M3 T& [$ x        char szDriveName[32];
0 y# a& m3 `3 ~; D/ L0 N% s
  t7 ~5 q) u  h4 m! A% ~$ m        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
! `  K7 _& T8 k2 g        hPhysicalDriveIOCTL = CreateFile(szDriveName,
& C# g. _) t  C2 V; ~( F                        GENERIC_READ | GENERIC_WRITE,1 N% u7 Q4 F/ r1 c* t
                       FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,7 K5 d) o& `9 f) g+ r0 W! O% J- J) q
                       OPEN_EXISTING, 0, NULL);/ |1 a+ X8 k) M3 s# U9 V' n# Z2 }

6 \+ c% P. C  T, A) X        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
2 T& m: \4 U& K4 M  Z        {4 q% C8 ^3 j  M
           DWORD dwBytesReturned = 0;2 t* f' s; ^3 k( |7 G
           GETVERSIONOUTPARAMS gvopVersionParams;8 H: N) g6 \9 Q3 q5 w+ ]8 p
3 R+ X. ]* L" z# h" I9 |, Z
           // Get the version, etc of PhysicalDrive IOCTL# l4 p# f: ~) j
           ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));4 L1 G0 D7 h8 O* q8 h+ D
& ]% N5 M2 k. g7 p3 j
           if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
7 N4 X$ ^6 d2 `: \  Y/ U# }: e                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),* A# r' S8 M4 |; F
                   &dwBytesReturned, NULL))
4 @3 J3 k! k& F: S& P            {3 v' G( l' F) a
               continue;
( l+ M: c5 o0 I- M            }
! g4 U1 U* W$ ]. A) v8 A
5 K1 f5 `) O% m9 c- g+ d            if(gvopVersionParams.bIDEDeviceMap > 0)
1 ^% C$ }4 P# `4 H% j4 o            {
' C* u! A9 Q8 Q2 t                // IDE or ATAPI IDENTIFY cmd) t; U1 m7 A6 b. e, }' r
               BYTE btIDCmd = 0;8 p( H1 @& r) H2 o$ ]
               SENDCMDINPARAMS InParams;
3 V; e8 u. I( {( k1 G+ d                // Now, get the ID sector for all IDE devices in the system.
! N2 m- D0 d" K/ N/ U, p                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command," g  M4 m, f% L- d8 s! D
               // otherwise use the IDE_ATA_IDENTIFY command
" G9 O, a% U, Q8 z- K/ }+ ~                // 具体所得结果请参考头文件中的说明9 m5 l# h2 J1 O
               btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
) x0 Y3 N( B  J" V; W                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
- H* o. G7 m' F1 y% L% x2 @' U$ o                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
$ L, d; x, v/ J/ }% w                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));& E2 e+ F* X6 a: A. }& A0 r/ @' ?

4 O$ {! P7 G" O' O5 s                if(DoIdentify(hPhysicalDriveIOCTL,
% ^+ D& {4 j$ R6 O1 ]) l                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
% p3 R# s/ `2 o' B' Q" \) C4 I                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned)). s9 C$ V. {. Z& O. e9 p4 S
               {
% `; H" k' `4 Z$ C                    DWORD dwDiskData[256];
+ ?2 N/ H& D4 g3 V% e                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件8 [1 |3 l- d% ^* y: K
                   char szSerialNumber[21];
% @9 q+ e  _% z4 i( V4 _* [                    char szModelNumber[41];
# O: j( L! e8 ^5 Q) ?/ a3 t
; T/ p# @% W, m# Y0 X- z& U: c                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;; X; N) y5 L% g' E
                   for(int i=0; i < 256; i++)6 k3 O' x+ |9 d& A6 K+ i
                       dwDiskData = pIDSector;
4 L  g- P8 a' J9 N                    // 取系列号6 Q) W6 }0 I1 `; Q9 a+ \
                   ZeroMemory(szSerialNumber, sizeof(szSerialNumber));. c0 X8 V1 F4 X0 {
                   strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));2 H6 j6 I3 t8 R& k
. |$ n, |( s5 I
                   // 取模型号
( b3 Z9 z: n9 \/ P+ U( j                    ZeroMemory(szModelNumber, sizeof(szModelNumber));
$ b5 S% Z7 L+ Q1 D' }2 m4 @) X                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
; q( p0 X# X  E& Q8 \1 U" U7 a/ d# ]8 S/ p* R- w* t/ l
                   pSerList->Add(szSerialNumber);
: k8 _1 Z& k. Q0 d! E                    pModeList->Add(szModelNumber);0 r$ _1 m4 j4 b: B
               }( y( }/ u5 |& t7 `
           }. v+ G3 T+ `, q% m
           CloseHandle (hPhysicalDriveIOCTL);
4 P2 \7 d1 k2 S2 s        }
* v1 x6 S9 t, ]+ x7 ~3 H    }1 {2 U/ b4 e$ [' o# f# M
}
4 e5 v" q5 I) L% q//---------------------------------------------------------------------------
- l( }: T+ H" V9 \+ @+ g. c// DoIdentify% ]% w( ?( }: t; O  O
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,5 f" y( L, i4 N! G
             PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
4 X7 l5 M8 J4 f5 n1 I              PDWORD pdwBytesReturned)
; L" @2 @  X  j: P{( |5 D6 z% F3 d2 |" }/ s( m
   // Set up data structures for IDENTIFY command.
; s3 S1 _$ B( j6 a+ c& y    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
/ h! M& r; _5 z( n+ n    pSCIP->irDriveRegs.bFeaturesReg = 0;
4 G, ?6 }9 \9 b' z6 y    pSCIP->irDriveRegs.bSectorCountReg  = 1;* I4 r2 t1 g+ @5 h! J9 O4 u' v* P
   pSCIP->irDriveRegs.bSectorNumberReg = 1;7 k4 c3 u3 t* h. ~  R! W. X* u3 E
   pSCIP->irDriveRegs.bCylLowReg  = 0;
5 @" p1 n+ f+ q! x, d1 q+ K    pSCIP->irDriveRegs.bCylHighReg = 0;, i- ^  S! G6 m$ \) J7 ~3 R( P$ ~$ G

, _  V/ C; S' v' i0 h* w    // Compute the drive number.(主盘和从盘所对应的值是不一样的)
& p2 L6 L0 B. ?    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
6 }, b2 {& w! S( z
' @/ ]' p0 N4 d8 d8 U- Y9 n    // The command can either be IDE identify or ATAPI identify.
; _; d1 f$ B8 P/ b    pSCIP->irDriveRegs.bCommandReg = btIDCmd;' `. D* M+ H  K2 J3 `
   pSCIP->bDriveNumber = btDriveNum;& x  L/ v6 ^% Q0 \
   pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;! {/ O% y+ p1 E7 |+ K) Z2 Y. f5 d

7 [! a* d) ^& _7 l; `" h    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
/ V! B. g" f+ Z  G8 Q6 ^- ?" n- P           (LPVOID)pSCIP,( m1 a: x! N. X9 i/ I
          sizeof(SENDCMDINPARAMS) - 1,: r/ ]- c; Z1 e) s; D) E  R
          (LPVOID)pSCOP,: b3 r+ y/ B0 O! V2 S  _7 o0 K
          sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,$ O# |4 p7 f. G; |, ?1 p, f6 ]8 g
          pdwBytesReturned, NULL);+ ]  o8 S0 O# l9 @$ Y
}) [0 P. y& }3 ^, s" B- V, ~
//---------------------------------------------------------------------------
" m8 a! u5 J9 w3 O% \& P+ Z// Windows 95/98/ME 代码# f# j2 G" @. ]- O8 x3 C) Z
//---------------------------------------------------------------------------
1 `9 s0 m$ _# x// ReadPhysicalDriveOnW9X$ V/ i# z: u. o0 A- b
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)
, n6 o' B( B* Y8 z9 m{
% u( @& [8 M( N7 p, e- n8 ^    WORD wOutData[256];
9 z- B# s# S) o7 V    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);) k, ~$ C% y& ^+ m) ^

) [/ V. f( x8 h5 h+ G6 L6 E  {. |    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
( Q6 W2 N9 W% S2 V6 i    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
* R7 ?: ?/ v) t; b* u/ V    // 避免蓝屏的出现。(期待高人能指出原因)$ P6 h* \' X! T6 e0 ?
   for(int nDrive = 0; nDrive < 8; nDrive++)
+ z; k5 W- h, i6 U' |) B    {) o3 N5 X; R- g  \5 [7 I; Z6 X: W5 z
       WORD dwBaseAddress;
' W" b1 O3 b# k/ j        BYTE btMasterSlave;         // Master Or Slave6 K& w3 ~- ?4 \5 [9 j( i! p
       bool bIsIDEExist;
  S1 o, A" Q* y4 j4 I2 v        bool IsDiskExist;
3 s) @" ~; F+ p" E$ C" ]* Z! a
* |1 _" A2 I# h  @! c, |9 N        switch(nDrive / 2)7 ^8 i; w5 |8 c3 h/ J& j( C
       {
$ d# F4 H. T0 H3 R' K. j0 N/ r" g            case 0: dwBaseAddress = 0x01F0; break;
% ^7 u$ {+ H/ j3 p- }            case 1: dwBaseAddress = 0x0170; break;4 p9 a# z) p# {0 @1 v( [
           case 2: dwBaseAddress = 0x01E8; break;
* d6 ~  N) p0 ?+ v- w            case 3: dwBaseAddress = 0x0168; break;5 j3 l& q$ I- o* y& K
       }
8 Y3 X2 S  [' E) [# r# X0 G. c3 B( O, T( C. b* Y* M4 Z
       btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
( O; N# _0 l0 p0 }/ q5 E+ U, J7 \  \9 M3 T2 F2 Y: D
       // 进入Ring08 W5 y7 Z% Y. q' L9 i
       ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,  Y8 a$ h0 K, m, s3 q* p" ^& h
               bIsIDEExist, IsDiskExist, wOutData);$ }( V4 _9 ^0 c0 G4 p7 [6 A
   }0 k! P" j" J$ C1 b3 x
' }4 p# H0 w$ t! ?5 C0 q8 a
   // 开始读取
6 ^9 `* }1 g1 `  e8 j1 V( _( g    for(int nDrive = 0; nDrive < 8; nDrive++)( t* e% F- T- Z9 X1 z- x" F# c! t
   {
7 w. i/ G3 S. `9 X4 G* Z        WORD dwBaseAddress;
( J. M' m. L4 [% k  R1 P        BYTE btMasterSlave;         // Master Or Slave) F4 J2 P+ h! [. B- M6 K9 @
       bool bIsIDEExist;2 L7 e" U$ c7 p+ q
       bool bIsDiskExist;2 {3 v9 v; {4 h8 ?
       switch(nDrive / 2)( G: G& |' a% m  D7 T+ G
       {: J# {7 T! N7 `
           case 0: dwBaseAddress = 0x01F0; break;0 l& F8 Z8 B! F8 G1 A
           case 1: dwBaseAddress = 0x0170; break;
; m' N' U3 |+ p            case 2: dwBaseAddress = 0x01E8; break;
9 X8 C! k9 Z2 k            case 3: dwBaseAddress = 0x0168; break;$ t4 ?( l) G2 ^' j
       }5 y& a: g/ w& |5 A1 T% Z

+ t- G9 B4 X7 _3 R        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
4 ]9 }% `" E6 X9 D* D$ x: m
0 U0 X$ R0 v) ?" N4 S        // 进入Ring0
7 l% c$ `8 o% @# i% e* r; v/ s        bIsIDEExist  = false;- v8 O2 j* g1 }. y$ q
       bIsDiskExist = false;, M& w3 f# O6 ^
       ZeroMemory(wOutData, sizeof(wOutData));
0 R) N2 c5 \: c
& a/ h1 j: I$ i: \( r0 x        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
; _! Q8 f8 T' j; `( K                bIsIDEExist, bIsDiskExist, wOutData);) v& p+ a1 ~/ U6 f

, {/ q. ~- A0 ?) w  q( M, W9 b        if(bIsIDEExist && bIsDiskExist)6 P5 U, K, S1 q1 K, Z# @
       {
' Q# n. M+ y3 M9 G* S            DWORD dwDiskData[256];5 e* ]3 {# m, N3 A* L) |2 `% n
           char  szSerialNumber[21];4 ^% q* ^7 n8 o, Q0 z: B# }/ _8 t
           char  szModelNumber[41];1 z- o) \. ~( c  o4 W  P: n
/ B; W% C1 S' S, f5 a' \9 J. O6 `
           for(int k=0; k < 256; k++)! Q+ `' x6 }( ?6 G* h  x# }' G! T) t
               dwDiskData[k] = wOutData[k];
( q, w0 x" ]( q! i
  B& r- j2 L' C1 h: }" j            // 取系列号
. k4 r  }) x0 N3 J* h6 b6 w; p            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));# }1 D" t4 H8 z3 \: o8 {" r
           strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));# e0 i6 x7 u, P; l
& \( j! x9 ~$ ?: N
           // 取模型号* S3 `- V, w: Q% ~7 b8 Z. p! X% j
           ZeroMemory(szModelNumber, sizeof(szModelNumber));: b: C) S6 O$ m
           strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
" B) L* ]' S, L$ E
7 f2 t: Q$ z. ^+ ~7 {$ i5 z            pSerList->Add(szSerialNumber);
, M7 n: Y2 Q' H            pModeList->Add(szModelNumber);# a  ?3 L: \, g# n4 Z( o
       }
( k1 U; Y2 \& n- J    }
  b  C  s% z: c    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);% a$ r5 Y/ z" w
}+ z. R- K1 w& X: N+ ?& g
//---------------------------------------------------------------------------3 J. H% V9 \% [7 w, o
// ReadPhysicalDriveOnW9X_Ring0()
1 l, Y# e3 U/ I//# R; l; ]- d% z+ d9 i4 H' J9 F+ D  [8 f
// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
9 _3 P  W2 T! p% M& y7 m// btMasterSlave = Master(0xA0) Or Slave(0xB0)
- b" J: x/ k. h$ O- ]//---------------------------------------------------------------------------
9 B* w5 j0 \0 o: F- {7 Zvoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,/ |- a% X& ?, o8 g) y( v/ W
       BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)  b* }& N; j; ^) r
{1 h/ e5 m( U( d7 s
   BYTE  btIDTR1[6];
* e  e2 _+ |6 k    DWORD dwOldExceptionHook;- _0 n* p( H) i' |3 Y- h
   const int nHookExceptionNo = 5;
- F9 `5 I7 K5 k. {7 b" W& q
! F% a4 U' Z: ~    BYTE  btIsIDEExist = 0;
1 v: B9 W; g' ?' e3 T  w    BYTE  btIsDiskExist = 0;' z, ]/ P% m" v( ]
   WORD  wOutDataBuf[256];
6 D- Q0 m! Z6 m/ }2 d  G& O
" J; g% J, j) D4 Y9 U    BYTE  btIsFirst = (BYTE)bIsFirst;
( a8 g5 g1 J2 E' p4 G
) l* _8 C( m1 W' V, P7 q    const BYTE btBit00 = 0x01;
2 l: @  k! b% Q, o    // const BYTE btBit02 = 0x04;* s7 P1 m' }, ~5 M* P
   const BYTE btBit06 = 0x40;+ H0 ^1 _. X9 d5 o& N
   const BYTE btBit07 = 0x80;
! D4 O' ~( Y7 s# d- X: W% A4 r    // const BYTE btERR  = btBit00;% X9 W) l- X- }5 w
   const BYTE btBusy = btBit07;
$ W: x. F; b1 V7 i7 I( V/ a# \    const BYTE btAtaCmd   = 0xEC;$ Z# _# l* u5 U# Q- }) a
   const BYTE btAtapiCmd = 0xA1;
5 P: y4 E' l( E0 S$ A9 `) b% w7 V
' K; R# ]+ h' U5 A    __asm  @/ w9 ]6 \+ I% b0 }' p% F% {; b
   {/ s& \% M; W+ j
       // 必须先执行这条语句
' T  w9 ?& Y# L        JMP EnterRing0- O1 w0 }0 V$ p; O( k( Z* ~

% ~1 _+ r! ~, t/ ?        // 定义过程
% D/ b4 U! l- B/ d- E        // 等待IDE设备直到其不为忙为止
: w  l' o5 @2 N8 B0 ]: u        WaitWhileBusy proc
% o, J0 u( H7 U" n; L$ p8 q; d, a1 m3 r* R# P
       MOV  EBX, 100000
4 P2 b1 }% J; P3 O& z* S6 k        MOV  DX, dwBaseAddress
2 A1 X6 {$ O" i: u# R5 ]- b* V        ADD  DX, 72 i5 I  e  K3 G. m8 n& X3 Y! Z

2 H1 S. F9 F. @' `7 H; L6 x4 I5 B- V        LoopWhileBusy:& U0 W' M( O+ d& _2 t: Y& Y; G% a4 y

6 y. d( K( q6 j$ s9 M        DEC  EBX; K/ r" c5 Z( G; P9 i
       CMP  EBX, 0( p. l- \3 _# Z/ t+ w6 c; \. s
       JZ   Timeout/ k4 O/ I. P, b- |3 h
       in   AL, DX9 C# _' i% }3 x1 K
       TEST AL, btBusy
& k9 {0 p$ q2 A$ _) @        JNZ  LoopWhileBusy
% {' ~5 {6 w$ ^' G6 b. r0 h        JMP  DriveReady' I7 C5 h5 o8 u6 K" o7 p

4 f& q# F+ K! _) K/ I        // 超时,直接退出
: V$ n2 `3 c+ s3 Z, f        Timeout:( N3 t# Q$ I( X6 f
       JMP  LeaveRing0
4 Y4 F: Y7 Z: `# b        DriveReady:3 M  P; @5 C( n5 p0 ^2 \# O! ?
       RET
/ C5 h" O& u0 W: g8 S' X        ENDP   // End of WaitWhileBusy Procedure/ [$ T( k% F( }( J. W: ]# [) C

) r+ T1 X' g5 D        // 设置主盘和从盘标志
/ D8 C, U. {( E8 K& y        SelectDevice proc- C( q0 a, u0 R' g- A
6 d3 }8 a3 r0 [1 X! }
       MOV  DX, dwBaseAddress1 g; \9 y# I. Z" ~
       ADD  DX, 6
" w7 N2 M) e  w' h0 A        MOV  AL, btMasterSlave6 f* L7 ?8 ^3 D( e" }+ `6 ^

5 v* g' n: M# n3 N$ k        out  DX, AL% i( _9 D% z. h$ d. E) d
       RET
: t7 I6 c' `5 r* J5 V6 s5 w5 Z' r( |9 D6 s& ?, X6 a6 ?5 N8 O2 f! }
       ENDP  // End of SelectDevice Procedure! x5 ?8 {4 f$ T, p% `( @
. C, S; u5 R% m' d6 l- g) {- D. l
       // 向IDE设备发送存取指令
  J% P/ v6 O1 ?# U- p& n/ A        SendCmd proc  p# r) l, W! e, M* H: r

0 G: B/ `( |) z8 [' s& ?/ Y        MOV DX, dwBaseAddress0 o" Y3 Q9 I1 L8 T
       ADD DX, 7
! j% K, K+ m  z3 K        MOV AL, BL // BL是主从盘标识,在过程外设置% |4 \& [: z5 |3 U* U
       out DX, AL
5 U1 d1 x) `9 f! h3 z        RET
: Z# |2 w4 _8 E' p* e2 R9 @        ENDP  // End of SendCmd Procedure
0 r& `( x3 h8 n- Y9 ^% N1 w  `) T( k7 [3 C+ y" l1 P
       // Ring0代码" k! a( b) G- k. }" H
       Ring0Proc:
/ Q# |8 C2 f" p7 J+ U        PUSHAD
# Y  v: ?* E  r; w0 @; l        // 查询IDE设备是否存在
% i: D# C# T! J  \( U        MOV DX, dwBaseAddress1 O1 e/ `) O2 |, L! r: s
       ADD DX, 7$ F5 v! g) U( }5 s7 r% Y/ W
       in  AL,DX' v2 g, {4 }9 ?5 P0 x1 \4 f

/ _' F& S: N) c, ]! f        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
+ @; R* _: }; {1 z* ^$ M1 U        CMP AL,0xFF
. i  v7 K0 |0 ^        JZ  LeaveRing0% k; E- z3 p9 G0 i, Q, N
       CMP AL, 0x7F
. I- a$ x7 G( M' s        JZ  LeaveRing0- Y$ Y+ h2 l1 J. e- F+ o% r4 k

; J  n  ~% y. u        // 设置IDE设备存在标志0 I6 j4 P% g9 J( z+ F& T
       MOV btIsIDEExist, 16 u+ ~, b7 l0 V, j& A* Y

" _0 H9 n# d+ J% h" f        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
. R+ s. n5 M8 d% e5 J        CALL WaitWhileBusy& ]. w& X0 B& A7 O
       CALL SelectDevice
( q1 E' R: ]& y; @2 X* V: ^+ b
# h2 V, y6 {3 [% a% L        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏7 P) O# U4 r6 |, i4 T& f4 V
       CMP  btIsFirst, 1
$ ]1 ^2 {2 @1 J, Z' \$ R5 q        JZ   LeaveRing0. @8 T, z2 {. b/ ?5 s

, J" N9 V4 o9 n, j1 A: x- G1 l/ _        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
, P1 H6 A  J% K, _( ?( E, c6 k        CALL WaitWhileBusy
9 ]1 L# k% Z8 |) v1 ?, w; K6 C- {
       // AL的值等于cBit06时,不存在驱动器,直接返回
! t9 J# v9 h% I        TEST AL, btBit06  j# J. r: ?! L% v0 P( w
       JZ   LeaveRing0/ e! Y! u4 c; }3 X, \4 U
3 L/ r# J4 @3 r) K3 t* P0 ^
       // 设置驱动器存在标志
* c. F5 S, w( ~, B# e- v1 ?        MOV  btIsDiskExist, 1
# S/ v8 Q+ \. p  A# b) i
) Y3 o6 k/ t) J0 M6 L3 p! ^  c- o, Z        // 发送存取端口命令
' B- P; d0 h; T1 P+ |" f9 g        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,! Y2 w3 E' ~6 _, c1 ?4 X1 n( s
       // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令) z$ C' f' B. H
       CALL WaitWhileBusy& t9 H3 k+ i; ], B: U
       CALL SelectDevice    // 设置主从盘标识) z  F! s$ Y: ^% E( U% B* C/ n
       MOV  BL, btAtaCmd      // 发送读取命令
9 m" U# Q1 o# g, \" y        CALL SendCmd% n8 @6 E1 v0 F+ G
       CALL WaitWhileBusy
1 E$ O: V" q6 E5 m' r9 p* r$ [2 M+ W% Y: i+ x  P# }& x: F
       // 检查是否出错) `# c; v- s9 P5 `% }
       MOV  DX, dwBaseAddress
( {. ?# V2 m! S( L$ j        ADD  DX, 7
3 O7 u( d' h% j8 S- j
3 m6 `1 N' t' `: T        in   AL, DX
  F+ |9 Q9 s7 L1 q# y# A8 M3 b, z7 e6 Z. T" A
       TEST AL, btBit00+ {9 U3 h: b" X4 k3 D
       JZ   RetrieveInfo   // 没有错误时则读数据& v8 ^; q( d8 N+ U9 G3 B
5 c% L: e/ }" e
       // 如果出错,则进一步尝试使用ATAPI设备命令6 I/ y0 F' Q7 ^1 o6 |4 y
       CALL WaitWhileBusy! v7 z& r8 x5 o/ E$ x9 i. ]
       CALL SelectDevice7 q, d' `/ V8 W8 g3 X1 q
       MOV  BL, btAtapiCmd  G# c8 }3 f8 P' r
       CALL SendCmd
7 ?8 V0 t7 A" ]; h) u6 h; Z- G1 N1 X        CALL WaitWhileBusy
1 s+ `8 B( @! {$ l: }# S
# j0 y: |; [3 `# D; Q+ M# ~$ J        // 检查是否还出错/ k1 y8 R: G- b4 v
       MOV  DX, dwBaseAddress) W1 @6 N7 W6 B8 j- X% Q2 r) f- @
       ADD  DX, 7) @" R0 g7 Z& }5 o
       in   AL, DX  \3 s8 g3 \; W' n9 y* C+ p! O3 [
       TEST AL, btBit00( [. m9 D# F) I) l
       JZ   RetrieveInfo   // 没有错误时则读数据
( v/ c" C  I. M1 c: F; s        JMP  LeaveRing0     // 如果还是出错,直接返回9 L9 x3 f8 X# X2 v. I& v

$ F1 I8 E" ]/ I        // 读取数据5 D! V. i% F/ _8 q1 J9 E: c) l
       RetrieveInfo:
6 C# ?1 L# [) |$ }& P& @0 r+ {0 |' t: U1 ?
       LEA  EDI, wOutDataBuf
1 E  s% E' O3 r2 t% W8 _7 I        MOV  ECX, 256
2 e4 q; M+ H! H4 \, k/ p3 G. b        MOV  DX, dwBaseAddress
$ O, L  t* N* J5 ^& k( D. o  S        CLD0 t1 M% W6 G. l8 y( {; W: g, B
( p# q/ I2 M8 x4 Z/ A0 l; m, R7 Y
       REP  INSW  R' g. v- O8 C% E1 B( }" Z

8 \# H! j9 U$ C4 l  f        // 退出Ring0代码
* n! n5 c7 i+ B: w        LeaveRing0:
$ _7 i3 I6 D+ K$ \) {; C) G7 d& _3 A
       POPAD1 s2 S$ r5 ?9 `) C; n
       IRETD
( M) z: t/ s5 t
4 N/ g8 [, f. o: p, w# R! S! H        // 激活Ring0代码
' `7 a& H0 J# B+ e$ w6 r        EnterRing0:
3 u8 s. G$ h" [/ o% Q$ \, l, B. |# I
8 o! @0 F! t4 L& e' t" e        // 修改中断门& M& |7 e2 m7 p. x
       SIDT FWORD PTR btIDTR1! p& P8 ]% v8 N: l3 ~$ @* U
       MOV EAX, DWORD PTR btIDTR1 + 02h' o9 _. W+ F% K
       ADD EAX, nHookExceptionNo * 08h + 04h
( @# F$ a: d! N- P) u1 @' [1 h        CLI+ ^. s& y, U$ W5 @: @

( m( ~5 y7 [. e5 y        // 保存原异常处理例程入口% M! ~1 n5 O  ]+ s
       MOV ECX, DWORD PTR [EAX]
9 e) _- E) k  ^  k: |        MOV CX, WORD PTR [EAX-04h]6 L! P. ]2 K$ l* _3 g# R/ ^
       MOV dwOldExceptionHook, ECX" w! e! A) l( K% e

0 o6 ?# ?/ F) |" W8 A. q6 F+ O        // 指定新入口
2 p0 U8 p% x' y9 L) k' x# G        LEA EBX, Ring0Proc: I0 g. [  O5 b( F
       MOV WORD PTR [EAX-04h],BX: B, b. L2 C3 |5 v, [
       SHR EBX, 10h/ T' W! J6 ^- z( a% S0 r9 c) W% R6 D
       MOV WORD PTR[EAX+02h], BX7 W! Y6 C! f$ G

# K1 u; s) S5 \        // 激活Ring0代码
$ {7 a& K& M. o# k        INT nHookExceptionNo4 ]" A( d1 E( S4 V* F
" v" a& R9 X% d9 S9 E0 O
       // 复原入口
  }/ t5 w. ]- \7 D* {# Y        MOV ECX,dwOldExceptionHook/ \( m0 R, y6 v/ K! m
       MOV WORD PTR[EAX-04h], CX7 F8 B* Z8 r% @- _5 W) ^
       SHR ECX,10h& c, F1 Z6 Q* f
       MOV WORD PTR[EAX+02h], CX2 \6 m0 I& }" n/ p
       STI( B8 E$ e0 ?! Y0 ], `, Y
   }
6 d0 [* V" y4 D; ]+ z! |1 \* ?4 H    if(!bIsFirst)
) n- q4 v7 D0 k    {! _) Q$ X# r7 e4 R6 ~+ F
       bIsIDEExist  = (bool)btIsIDEExist;
$ |- ?# z# R( B! l! Y        bIsDiskExist = (bool)btIsDiskExist;' |1 q% K; j; J8 P2 e6 w3 }" m
       CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));- U' B/ u( V. x
   }
& k  _( v5 L* M) w}
* N5 ]! {0 i; I//---------------------------------------------------------------------------5 s6 @; m% i2 `. W5 h) o2 b! ^
// 调用方法:% t* ^% \% R2 B# _6 |! _6 v
void __fastcall TForm1::Button1Click(TObject *Sender)
- e9 z  x3 r0 b" `2 k& a/ A7 \# K: m{
  H5 o( x, C$ @+ p' u    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
# W  q- @! D" z0 G7 E}
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2025-5-5 09:00 , Processed in 0.016434 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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