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

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

[复制链接]
发表于 2005-5-30 19:22:36 | 显示全部楼层 |阅读模式
  #include <WinIOCtl.h>
5 g5 L2 A% a. C#include <stdio.h>
" q- K4 }; ]# Z6 P0 l: I' C8 @: c9 G
#pragma inline* _+ A: T+ |, Y  b2 o% u& W
//---------------------------------------------------------------------------5 C  F( r0 a3 y, |
// IDE NT/2000/XP专用变量
% @2 I/ M& R7 F5 a$ ~' i#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
8 p1 T' @8 o: O7 H2 ^#define DFP_GET_VERSION         SMART_GET_VERSION
5 x2 j1 K8 |; V- i, T9 @( a- C9 Z#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
3 d% d2 q8 H% M6 ~! r#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
1 |4 B( M8 ?* M6 p* X- y) P' ^  }$ K7 w: h* i  l
const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令1 u; A3 `8 j& o2 v, B8 r
const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
6 u5 L/ P; _2 K
9 }# i4 }# ]6 f" [const int MAX_IDE_DRIVES = 4;
/ s' V7 O. [' h) F* X* h( D& ?( K- w$ T  Y5 c( {& f& l4 P8 r3 ~; r
// SCSI专用变量; `; A/ N$ W) K$ u. s
const DWORD FILE_DEVICE_SCSI             = 0x0000001B;5 x  Q* p% D" H6 @
const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
) `8 A5 M, [& Z! }$ K, [const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
: k, ~0 f- G( zconst DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;+ l0 L8 t3 U' ~, L$ s3 c0 A

  I1 s/ w2 i, f6 ^% }3 ntypedef struct _SRB_IO_CONTROL
) D) i2 x( {4 t: Z6 J+ o2 M- D{4 h4 u, d' [2 P
   ULONG HeaderLength;- @  R6 N" h8 ?/ @, m) w$ U
   UCHAR Signature[8];- V0 P7 u5 u. [# V( E7 }+ g
   ULONG Timeout;( E6 }1 K2 u( }: H/ o
   ULONG ControlCode;
3 H: \% }: a. C8 p: F    ULONG ReturnCode;( P. M2 v: s6 A- A
   ULONG Length;
2 z% Y& C2 }8 v# H$ E4 E1 }* X}SRB_IO_CONTROL, *PSRB_IO_CONTROL;
* S- E( j& O8 k  t. p6 ]3 A( \+ |  |4 F/ g$ |
// 读取的主函数# q5 G: J  ~+ x, j: l- p, b: m+ [
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
% ~, D6 G3 F6 B9 z
9 q  T! u1 g  Y( ^' q6 J) E" ~2 o  S// 辅助函数! S# t3 B, Z' B- x) p6 Q( @
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);, H3 w5 p4 c+ L- w/ t" u# M* f% r
// NT/2000/XP函数
. p% {9 w% H3 Z, hvoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);- U& ^8 {! A6 {
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,6 O+ d& l6 H/ d1 d" g" u. H5 ~
       PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
8 a) Q4 X% u4 `/ f  |        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
% x. V! x7 |4 K  J, s, U; t// Windows 9X函数
5 i' t) N! |& E" \void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);
% k1 j) B3 h( M. `$ Kvoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,4 i6 S! k* s/ n' D) P* V3 K0 z
       BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
. Q- Q3 _. d) Q% K* z, M4 H- O
% ?9 }2 N4 d  ]( l// SCSI读取函数(for NT/2000/XP)
2 B5 E9 B( o; t  C& M7 dString __fastcall ReadIDEDriveAsScsiDriveOnNT();
" M3 G% ^) _+ @7 v- A3 b$ d" v//---------------------------------------------------------------------------
  ]/ H5 \# _4 q& W! i3 ]( r" f4 i. S// ReadPhysicalDrive2 d3 ~9 k) P/ w. q
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
* q# O' `7 r. [+ S4 n) X; I2 c{' ^% m8 ^6 v- J" n6 n  ^
   switch(Win32Platform)
) i1 A9 X; H% \) I    {" j+ ]. S$ e6 ^% h/ l3 ]4 T
       case VER_PLATFORM_WIN32_WINDOWS:+ f3 [& y5 w" J4 v
           ReadPhysicalDriveOnW9X(pSerList, pModeList);% e5 Z1 D  O3 D; O
           break;
2 k4 a+ A; U4 J" |+ S2 a        case VER_PLATFORM_WIN32_NT:! B. B8 Q" [+ K+ c! w
           ReadPhysicalDriveOnNT(pSerList, pModeList);) k% \# u7 N: K
           break;! E! D# e+ [( e
       default:
8 U5 d4 e$ U& \/ d            break;. I+ x) C' J9 `7 _  y
   }* A' S9 e4 e1 `( Y. F. H* h
}4 @2 L9 e4 `/ ^; I# f
//---------------------------------------------------------------------------  S+ {$ b) A$ e* `8 J
// ConvertToString
0 _7 }& c- [5 K+ L, Rchar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)+ \/ C: r  [7 N
{# G" ]& |" N( p' o4 y! A/ S
   static char szResBuf[1024];
7 X7 u* A0 l$ r$ b6 i    int nIndex = 0;
2 T9 |* G, v: g! {3 }* M6 O$ ~# G    int nPosition = 0;
5 r& [5 ^3 {3 ]9 G
. C) s4 R, d% N0 m& J: |    // Each integer has two characters stored in it backwards: g, [, g: |$ s
   for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
7 c: J7 r. @2 ~3 \! H" s- E" n! K    {
6 R& f* d) \+ O9 s4 a/ b6 u        // Get high BYTE for 1st character
8 X6 k) @0 _& K% P% T        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);) V) t# H; L% s4 m! u4 o' A% ~( o
       nPosition++;( g9 Q8 f% r' ?, `

5 C2 T4 y1 c0 H3 F" v. ~0 N        // Get low BYTE for 2nd character5 A) V2 c% D; @! w9 R
       szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);/ d$ u- b! ]5 a) M4 L5 X" N4 o
       nPosition++;( T. p5 s) o4 l3 S8 T
   }- p2 W5 |5 ?* y  E
3 ^% C+ k$ t8 {+ Q" E# p: _
   // End the string  A. z  |. G/ |" q4 d( g
   szResBuf[nPosition] = '\0';
3 a% E1 ?5 [8 D+ e6 Z4 M
, y# f2 {1 D* s  y- B* I8 K    // Cut off the trailing blanks
& ~& r  j4 I2 r* {" a0 ?* h    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)& u% U$ V2 N- D& C& x( L$ F" V
       szResBuf[nIndex] = '\0';" c9 T* u0 e) f& q$ |
: P, u7 c2 M! h4 g
   return szResBuf;
+ F3 K+ U6 n: E% S  ^}
, b* p; U! J) d* Z$ j. m//---------------------------------------------------------------------------% I, v/ m' U6 k* x/ S
// Winndows NT4/2000/XP 代码
- D) G- ?4 M  F//---------------------------------------------------------------------------
; `5 \7 Y" F) |. E// ReadPhysicalDriveOnNT3 E. w, u6 M  w/ P
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
& C! Q2 q/ r: g/ |' ?{
- I9 z* p* [4 z8 y, U9 }1 S    // 输出参数+ |: G. Q  p$ C# o8 M) t3 k3 P
   BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];  p0 q, ?3 z0 h1 [% m

. j* ]& y/ h$ e% e! ^4 N  v    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
) g2 G; S$ _# c4 g    {$ Z; I' V' K& y0 [4 j: }
       HANDLE hPhysicalDriveIOCTL;
7 _2 B; h/ H4 @+ }# q( h        char szDriveName[32];' V. L! f  |& ]8 x4 O0 D2 n
7 q+ s' @! G) Z& T
       sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);, v" {9 r& V: }* B8 F
       hPhysicalDriveIOCTL = CreateFile(szDriveName,4 l( V0 t% X8 P$ Q7 T4 \6 s- n% b
                       GENERIC_READ | GENERIC_WRITE,
1 v$ d4 B: I0 M" G/ I                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,2 Z$ p, O3 K9 s) b# ^0 D
                       OPEN_EXISTING, 0, NULL);/ r2 ^0 u  G  E9 i; ]3 g
. i6 F# v0 C/ Q+ j( M" h
       if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
5 h( r) X7 w3 u# Y* k3 X        {
, X- }* V. R/ a# a4 h; Y' o% @            DWORD dwBytesReturned = 0;
" C# \5 b7 f# E' L3 `: t            GETVERSIONOUTPARAMS gvopVersionParams;
/ r& i1 G& X. d# U  N4 R- o& t7 I; @2 f% Z
           // Get the version, etc of PhysicalDrive IOCTL
+ a6 y! Y, N1 F4 d4 C/ Z            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));& o* n, [, ^6 h8 w

/ Y( W3 s6 r1 k: g+ X0 T            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
) v) _2 X6 {" G4 U" |7 ~                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),% ?- l- Y& Z8 }4 O
                   &dwBytesReturned, NULL))6 w" e% d2 n4 a  c8 H
           {0 S, `1 c/ E4 B. F
               continue;
0 l. H5 l" z) {+ m) L6 D7 C            }' H* D. l5 O% Z* `6 B3 {
: _2 p' p7 V6 W7 j% D
           if(gvopVersionParams.bIDEDeviceMap > 0)
$ [6 k, \! @0 v8 `; w3 {' Z7 A            {
' V0 X# Z1 O+ K, I+ f                // IDE or ATAPI IDENTIFY cmd
: L; z% }5 X) r$ Q- C9 {                BYTE btIDCmd = 0;% q/ j7 Q9 C4 x: h! q2 o* q# k' p
               SENDCMDINPARAMS InParams;* S7 c- q" I  s  T& L
               // Now, get the ID sector for all IDE devices in the system.
* P' N7 ]" Y. X' P7 n; j7 G" ^                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,, V! |9 f3 i! L9 Y, n' D) ^9 d5 |0 G; z' Q
               // otherwise use the IDE_ATA_IDENTIFY command0 H) Q" S0 V5 @$ b4 w. k
               // 具体所得结果请参考头文件中的说明8 P6 `( v. O4 W4 E0 Y9 z: U
               btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
6 X# V. v: l, {9 k" M6 @  D2 `                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
7 O& Z; l$ T5 P- F                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));4 u1 r0 u7 U  X& j
               ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));9 q3 z- m4 s5 Q' O6 C* }, w/ K

; a/ W1 {0 H: P% M( R+ E, _6 p                if(DoIdentify(hPhysicalDriveIOCTL,
+ J! V! q: B+ \% f- E                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
- _" W6 |9 g/ {+ [; j" D5 W8 k. F9 B                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
, K  o. K9 ~* L+ s) G/ O                {+ D$ b) C9 z3 z
                   DWORD dwDiskData[256];
$ W. C; t/ a' [" g! P                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
, V& D3 N$ Z) O5 v                    char szSerialNumber[21];& u5 f& P* U, o
                   char szModelNumber[41];
1 a1 X) Q& t+ u3 @5 J! I5 A9 ]# n- `& q/ U/ n- K
                   pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;7 g1 z- I+ m% U2 [, L# w& C
                   for(int i=0; i < 256; i++)% k& y* l5 P+ D% p, K* k
                       dwDiskData = pIDSector;+ u# G5 ~, k  b, S
                   // 取系列号
6 u$ a7 T3 x3 F. t3 T* k& Z                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
  {7 m  g. O- Q9 f0 q                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));) c; W/ R* @4 ]4 ~. |& z
* u% y1 g9 ]4 s# ~
                   // 取模型号
* G4 j6 T3 b1 o. |! N' o5 A& B                    ZeroMemory(szModelNumber, sizeof(szModelNumber));
, p6 h7 |9 {2 B% T2 D                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));- E3 t4 ?3 ~- Z4 r, a( S6 T
- q! j  Y  \# A. v2 I1 d
                   pSerList->Add(szSerialNumber);
. K% S/ w/ _$ W                    pModeList->Add(szModelNumber);. f2 ^9 B5 D$ J8 j$ `' [
               }# b  I2 \; w7 b- t$ B, }
           }7 j/ x2 k4 m; p
           CloseHandle (hPhysicalDriveIOCTL);/ d. {! }- W2 q0 g3 Z! [& ~
       }
2 g, j- z9 k4 [/ N1 f# b1 B& j    }
$ n% V0 U. m% Y% `$ g}
" C4 n) U. ~* p4 e//---------------------------------------------------------------------------
1 f. Q" X' @/ N& j1 p// DoIdentify2 F- Y2 J/ ?3 k$ _+ \) R
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
8 o0 V% E! H3 y. q* j2 G& Q              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,: j" J3 x* v; ~: g# W' Y
             PDWORD pdwBytesReturned)
" O2 x- b( }$ |' r  D{0 ^3 v6 J5 N. M0 A5 K( f$ K/ I$ V
   // Set up data structures for IDENTIFY command.
$ F% ?: u  P; v' M# G    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
: U4 l% M* M9 C5 X, Q" x- [    pSCIP->irDriveRegs.bFeaturesReg = 0;
* n5 i: i+ \5 c, @3 n9 i0 a/ x    pSCIP->irDriveRegs.bSectorCountReg  = 1;2 G6 q$ |( S" r( D( Q) U! T" E6 W% k
   pSCIP->irDriveRegs.bSectorNumberReg = 1;5 B& s% Z2 O( l& d5 i* G
   pSCIP->irDriveRegs.bCylLowReg  = 0;
: @3 O; ]) g1 m, w8 D    pSCIP->irDriveRegs.bCylHighReg = 0;
0 t" v& V* n1 x- X- Z5 @5 n, n
# q/ [+ h5 \' Q! s    // Compute the drive number.(主盘和从盘所对应的值是不一样的)# J1 {7 ?) p* b8 ^( ^# m
   pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;- N! j" k) j; H9 L
$ y( s5 x# C) B
   // The command can either be IDE identify or ATAPI identify.
  }7 Q# H/ u8 w! \    pSCIP->irDriveRegs.bCommandReg = btIDCmd;
1 P  r* V; W! Z5 c- @7 K    pSCIP->bDriveNumber = btDriveNum;0 X0 c  m! y- u7 g, f. b3 c
   pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
% A9 M& W& H1 u* z6 d( q: ]; Z* O* X3 I
   return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
- H1 d* K" c+ K( T% S. G+ e6 t6 a           (LPVOID)pSCIP,
4 V# w9 x. _* o5 K" F5 }           sizeof(SENDCMDINPARAMS) - 1,, A8 X, p& t* W5 |$ V& H( n6 u
          (LPVOID)pSCOP,9 h% e" q" j9 e* z
          sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
- N9 s6 b/ m! i8 m% ~           pdwBytesReturned, NULL);7 G0 E3 j+ H+ V" B* V( t
}; V4 b9 u3 W( @6 s
//---------------------------------------------------------------------------$ T7 [& c0 f; s0 a5 q+ L" n. c
// Windows 95/98/ME 代码& ^) `( e' e8 |9 x/ i: ]# _0 P
//---------------------------------------------------------------------------2 I0 d# |8 i7 ^2 t! Q5 ]
// ReadPhysicalDriveOnW9X' o7 S0 |7 L& N8 W
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)- u& h  N* S+ \; s# H
{) g3 I) B/ _4 m1 h' O# F6 Q
   WORD wOutData[256];
0 p" Z, w7 |- Z% }% h    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
  X; p* p2 _8 R- J
0 `- H* f# s" c    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
% E! h0 h7 }/ G8 a    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
" \  ~2 y: [1 y    // 避免蓝屏的出现。(期待高人能指出原因)/ t6 W8 @4 d, W0 ~/ }- K- c8 _) O3 E, m! W
   for(int nDrive = 0; nDrive < 8; nDrive++): r( z1 `8 M. X/ e" S* W
   {2 \* z/ k7 z; l/ d+ O- ~
       WORD dwBaseAddress;( H) E8 X$ H2 z( f
       BYTE btMasterSlave;         // Master Or Slave
" T, G6 b! C+ L/ U2 ?) F        bool bIsIDEExist;$ v( I8 k  J! O8 B
       bool IsDiskExist;
- Q7 c, ~2 T5 [+ D" k1 n; w4 z$ t* A5 I9 n- b! v; R/ C6 ]+ P- [
       switch(nDrive / 2)6 I$ E) o9 {# e+ b# S
       {
( r- ]1 H1 v( m+ Y# L            case 0: dwBaseAddress = 0x01F0; break;
+ W# u9 W( I6 j1 a            case 1: dwBaseAddress = 0x0170; break;
7 z: T" X, K) B7 P  }. e( n            case 2: dwBaseAddress = 0x01E8; break;
8 g( e: L% \. V3 H) S' y            case 3: dwBaseAddress = 0x0168; break;; v- t# [2 x; Z( _9 b
       }5 W& p$ B! U3 u1 n8 v
6 l% S; Y1 {0 Q# _4 C  a
       btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);& w6 [. i7 O$ D. ~! u/ P
5 S# m9 B  G5 d8 z3 A) ~$ r( [
       // 进入Ring0
: [0 G7 D( X3 k; w        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
+ u+ \" V5 _' ~5 y' p5 g$ N, t' j% k                bIsIDEExist, IsDiskExist, wOutData);) p9 l3 C/ G2 E! I/ ~1 N& v
   }
/ {/ ^/ p/ f; [( ~, T. m
! y) t. N/ }1 {9 {7 \# K6 a    // 开始读取
. }9 V9 z2 f% w5 L" ?    for(int nDrive = 0; nDrive < 8; nDrive++)
# L* o* F- p5 @1 R7 h    {
! f- \) j* c1 h  W9 |        WORD dwBaseAddress;
  [' B- M6 d  _$ C, j: z8 A. N        BYTE btMasterSlave;         // Master Or Slave
; Y$ B* V* `  m8 b% U1 g. Q4 Y        bool bIsIDEExist;9 N( W8 u$ Y& j% j8 h* e9 H
       bool bIsDiskExist;" j; Z+ e, [; L( }6 E  W$ o
       switch(nDrive / 2)
3 |  D  t5 Z+ H+ ]2 m/ m+ Y        {
9 a% W' r, p2 T9 g            case 0: dwBaseAddress = 0x01F0; break;
5 O9 R7 ?( Y) o            case 1: dwBaseAddress = 0x0170; break;/ k1 o  c% |5 v- ?# `
           case 2: dwBaseAddress = 0x01E8; break;
- x" W  K- h; ]            case 3: dwBaseAddress = 0x0168; break;* j; x/ `& a& w' S2 r* B' E
       }7 T/ D. x; V3 l# o3 O1 B

3 I) |2 {4 w! _4 F% O5 m8 m        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
  y& [/ n1 l- l- L0 c' r( x: T  p& e  b; X9 o' f
       // 进入Ring0
) ]9 u. S/ c4 ]' I+ {3 a' f  ^        bIsIDEExist  = false;
$ t8 o- m6 e+ R# Y! {: {: y        bIsDiskExist = false;% D% w+ c; u, B0 i1 H
       ZeroMemory(wOutData, sizeof(wOutData));2 I- y6 O& C8 ~& u# r
, e5 {- I5 [$ J
       ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,( R1 }0 u  Q0 Z& s" ]
               bIsIDEExist, bIsDiskExist, wOutData);7 y5 ~4 a. X3 _: I4 c8 P

5 X: k& Y' ~* ]/ P6 [' P3 z* D        if(bIsIDEExist && bIsDiskExist)+ z4 _7 ?( z  k) Q: e
       {
$ O* [% m: }6 h6 S/ N5 ?( n8 _            DWORD dwDiskData[256];
9 d2 m0 K! K5 j! U, v            char  szSerialNumber[21];
2 K6 D6 v3 R  a" e% \            char  szModelNumber[41];2 w! h2 n  f, M

2 L: B, @1 l" O1 n            for(int k=0; k < 256; k++)
4 O, z+ f  _' A2 [  F% p: H                dwDiskData[k] = wOutData[k];3 }  o% Q) l: I2 @  I  j& m& N" g6 V

5 w4 `% C5 t- D+ K" V7 F            // 取系列号
; M6 u, s0 @  _. G9 N. f% H            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
% m" j: |; R1 W* a) t' O            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
* N4 V* }) c; w: s7 K
2 f( j* M) Z5 t1 s            // 取模型号3 K5 t5 w  j$ |
           ZeroMemory(szModelNumber, sizeof(szModelNumber));
/ e/ o; y0 R1 D7 ]# e  g% m) T$ l            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
9 S8 S9 a1 [) \& v/ A! I% @% P
3 t) C7 u9 _+ |; W/ j0 g/ Y  Y: H( Z            pSerList->Add(szSerialNumber);
! k' X' F% O: k9 r/ _$ ?& c& O6 F( S            pModeList->Add(szModelNumber);. |$ Q- [2 m( V
       }
; O( A( H. a: l& ]' d, g! E    }! G) g9 v( f  u! E) x" C4 P
   SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);  y  r* K& G. ~9 }$ E& h: Y& l% Y
}2 v# J; [9 ~  o+ h$ r. K
//---------------------------------------------------------------------------
2 y7 a) n; P& x# `" d// ReadPhysicalDriveOnW9X_Ring0()+ T" M1 p" j  h
//: V, `# m1 A' u  I. w# X4 P
// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h! t) P7 x( I2 f/ p0 T) w
// btMasterSlave = Master(0xA0) Or Slave(0xB0)% J2 ]' K0 v" s  B" B
//---------------------------------------------------------------------------- i' ^6 p; \9 |* T  z5 u4 }
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
% U6 F1 v" U0 k, N% z( l8 M9 B        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
8 P& J& F; V: l1 u: w{' U5 d9 r& B  G; v- ^4 k+ S, J
   BYTE  btIDTR1[6];# c# v2 ~# ^( z7 o
   DWORD dwOldExceptionHook;
3 j3 d, D8 L, F9 m8 r    const int nHookExceptionNo = 5;
6 G* y( t8 X0 F$ I! R/ M  W
9 ~: T: N% L6 |) N% e7 K' C; f    BYTE  btIsIDEExist = 0;8 N" Y) T- O- X" Z: D& `" R, b* R# B
   BYTE  btIsDiskExist = 0;
& E, D/ |. [/ u  Q    WORD  wOutDataBuf[256];1 P- s/ J+ i' }
$ q7 A5 F  h. M- a, K$ O' y' Q% r1 j
   BYTE  btIsFirst = (BYTE)bIsFirst;
# U" f) ^7 G; D4 B, q0 F. @
" B/ A6 J# `# N1 U    const BYTE btBit00 = 0x01;* A" P% z9 x$ ?
   // const BYTE btBit02 = 0x04;
- d6 ?# c" @4 m1 \( V9 s$ z    const BYTE btBit06 = 0x40;
) [/ C3 Q& D6 l" I    const BYTE btBit07 = 0x80;. j; {; F' q* f% V: ~5 @1 p4 d
   // const BYTE btERR  = btBit00;
  n, h2 h! O6 j3 e5 H) ]    const BYTE btBusy = btBit07;7 Y; X& e9 I& I! n
   const BYTE btAtaCmd   = 0xEC;6 J$ s1 ~/ Y$ B; P6 c# I
   const BYTE btAtapiCmd = 0xA1;( K5 G2 o2 w" @' F5 @2 R" [
; G, a8 a+ }2 c& l" @; y
   __asm+ G/ C$ Z7 z2 E0 o7 `7 P; g2 c- i
   {
5 o. H7 q! R6 k2 _" f        // 必须先执行这条语句" G$ r; M7 S( o2 Z1 Q' Z0 g* `
       JMP EnterRing0
8 O6 N( |7 z9 U- i$ o% C0 e: O4 z9 M' u4 {- V* M0 t2 @# v9 m' }2 [/ {
       // 定义过程' ^* s4 Y8 e5 ?$ [0 W" a- |
       // 等待IDE设备直到其不为忙为止- W* X2 U* [. L& P4 _
       WaitWhileBusy proc
3 [7 Q, D8 n  C. c7 v
. h2 n8 b7 {8 d8 l6 o        MOV  EBX, 100000
# Y- s- c% k9 a  d2 d' d* L        MOV  DX, dwBaseAddress
6 r9 x9 Z; J/ g2 {/ A) |8 g        ADD  DX, 7: @! a# k* b1 S0 t0 h/ ^8 w

6 |' x1 Z$ G# e1 @$ }, \        LoopWhileBusy:
. ^* e$ F: d& M% v0 Q. y& \9 I7 h$ N7 Y$ j. C. N0 ^. v
       DEC  EBX4 b$ W5 {; F5 }& a
       CMP  EBX, 0  N; |" l. \7 _
       JZ   Timeout
# i! P$ r$ `+ J- A4 H8 O        in   AL, DX
9 O8 w( m* [) s/ n. P0 K        TEST AL, btBusy
/ ?7 _; \* r% x' b5 G% g% F, z        JNZ  LoopWhileBusy
. p2 `' p. ?: Z) r% W) K) w0 q        JMP  DriveReady* x$ F8 o' E' e+ t/ x' `. W

4 t# t# P+ N- z! s. k- w        // 超时,直接退出
7 M2 }1 ^, }6 @! W" A5 x        Timeout:0 [4 O8 L1 g% d9 v1 Z! p2 V
       JMP  LeaveRing09 K# \0 L) w* P% s% w
       DriveReady:
+ x( I+ ~$ K& V! v/ {        RET: {" {% `( D, q0 t
       ENDP   // End of WaitWhileBusy Procedure
( J. A% g9 c7 Y  q! v1 O; ?' B! w) S1 t- b, M1 T0 ^
       // 设置主盘和从盘标志8 c! z5 }$ N. l
       SelectDevice proc0 u2 N% M9 \* q7 w+ J" e

2 Q' ]  C7 {6 X) e! m8 [        MOV  DX, dwBaseAddress
/ v7 G& h3 b' p- V! C1 S& W        ADD  DX, 6
  b7 {& z2 y* K        MOV  AL, btMasterSlave
3 f6 e, S: Z; ]0 A% ~' j* g; D! k; Y% Q2 I3 ~5 Z5 k8 Z
       out  DX, AL
2 y) o7 s2 t1 e; E        RET
/ X! b0 w8 a- J* r
  O7 d/ X& C9 M8 \( G  m        ENDP  // End of SelectDevice Procedure& `* q6 g2 [# F" d- E
( x0 z( w/ Z/ S8 G8 [1 e
       // 向IDE设备发送存取指令
) |7 {3 r- R7 ^! h4 `        SendCmd proc
, c/ U) i+ D: k  O, V0 F' z: D+ `
& o, M$ A7 R, c& V/ \& f- ~4 g        MOV DX, dwBaseAddress$ u3 R( {1 z- h3 ~- P: k
       ADD DX, 7
* v- g# J! {( ?) T        MOV AL, BL // BL是主从盘标识,在过程外设置
7 \7 k4 M8 H, L0 @( [$ w        out DX, AL" |* Q7 P5 M  B- Q
       RET' w/ g6 Y2 N% l6 h. X/ s& ?" r
       ENDP  // End of SendCmd Procedure
6 [1 j$ ]- M, u% {1 Y7 M5 S0 M! ]+ q. e/ A3 a
       // Ring0代码
# k5 H5 |$ k$ X        Ring0Proc:
* e/ R- J1 S0 r9 _        PUSHAD
3 X: M$ \2 O7 {) x/ N9 o        // 查询IDE设备是否存在
  V" a' |; P: {. d# f; a3 \0 v        MOV DX, dwBaseAddress& }; a3 {3 B2 ~% t2 l) [* I/ h
       ADD DX, 7
( H! c3 l$ K) x! o. g% G        in  AL,DX
" ]/ A! y/ A! q/ [. o) w9 h( [  L6 q" W' N, n! u% R
       // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
1 j  k% C7 n6 w& T$ |6 o! P  `        CMP AL,0xFF  p/ T8 z7 g. m# b* E9 k: `
       JZ  LeaveRing0
( W4 t3 N' y2 ~$ B. n% \        CMP AL, 0x7F; n. L# c* c- j; V
       JZ  LeaveRing01 b8 L+ K/ |8 t" j
) [2 |- X, t  K8 r& f( l
       // 设置IDE设备存在标志% ?* Z+ @, R9 `, {
       MOV btIsIDEExist, 1) O; e  n2 i: y; h' H- L7 Y, d" K
/ r. N) t- z( z3 D( w" N- l; R2 t
       // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
$ \* r' Y: M+ I3 G9 Q6 z6 @* _        CALL WaitWhileBusy. ?' N+ M+ O0 s& x+ _1 s+ U
       CALL SelectDevice8 f0 ]% ]6 ^3 X* m" \+ T: W, C( T
6 ~: y' S  v% K- Z6 }
       // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
6 E5 d7 X$ o0 J7 ?, q        CMP  btIsFirst, 1* S" c6 h; F: f6 a5 V
       JZ   LeaveRing0
% {* Y* a9 C3 P$ L) n
6 \4 W3 c, R/ k! x; ]; A2 T        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???' M0 U( w7 m5 D& @
       CALL WaitWhileBusy2 C7 T1 u" b% Z, R: _4 M5 R
# A: _: W6 ^  l, _( ]1 v4 s
       // AL的值等于cBit06时,不存在驱动器,直接返回# }- i% Z* t' `# [; L' S
       TEST AL, btBit06
* R6 j' z- \  F, O        JZ   LeaveRing0# k. E0 R6 ]  X; ^4 X$ t

1 @$ g$ k. I2 Q4 P* D1 C  T& ?        // 设置驱动器存在标志6 m1 m6 l7 j2 J% A7 G$ i! k
       MOV  btIsDiskExist, 1
/ L) k! u; T3 E& Q0 Y7 x5 X* q5 c; n6 T: v9 O
       // 发送存取端口命令5 q6 r2 R3 \' G  l- A4 F# q
       // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,# r2 g- _4 B- F4 o& m) o/ ]5 Q
       // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令  l* K5 K" ?* g* b/ P  }7 {3 I$ ^
       CALL WaitWhileBusy/ L9 o: L: v- j
       CALL SelectDevice    // 设置主从盘标识% [! u1 l' {% k. V  G  r/ F
       MOV  BL, btAtaCmd      // 发送读取命令0 w; B+ g) y: t. G% F) R" ?3 K
       CALL SendCmd
$ P6 T* u! B6 P5 Z+ q3 Q0 D        CALL WaitWhileBusy
& S0 ?% S8 h# J& S% m5 q$ L
  u' K" u. l2 C; f1 x: W3 Z        // 检查是否出错
7 L. U9 R, E1 C$ J        MOV  DX, dwBaseAddress' _" {: D7 C! Z
       ADD  DX, 7
& J8 X, B! i% T' b9 w* l3 u, k& K: J3 n2 z
       in   AL, DX6 I" C7 Z" ?7 U. E
7 d" |) b* i% o$ J- O
       TEST AL, btBit00
8 v! c$ Q. ^" R! Y9 j( G2 z        JZ   RetrieveInfo   // 没有错误时则读数据
* Z5 Q, Q/ ~+ B% P
+ l" j3 X" b. }( o  D; V        // 如果出错,则进一步尝试使用ATAPI设备命令. h. N3 F( U0 I3 `$ j7 @- E$ T+ i+ P0 [1 @
       CALL WaitWhileBusy! V2 _% k* a: M* F0 N
       CALL SelectDevice" Z3 i$ [- E( l/ u4 q4 C
       MOV  BL, btAtapiCmd% J  m3 g1 q# l3 q( B
       CALL SendCmd
7 z, ]2 H3 c, U1 e+ E- E$ p1 W        CALL WaitWhileBusy5 Y' I* O- _0 B$ ?9 i

4 d% l! J9 }' @        // 检查是否还出错
, x4 [! }) {: R; r5 N" z        MOV  DX, dwBaseAddress+ m0 K7 {* Z- v  y* P
       ADD  DX, 7
8 e* R/ G" v% c9 J        in   AL, DX
+ B% c1 ?5 f' f' q7 g( z7 M        TEST AL, btBit00, P) I; R# _2 V: P- h$ d& e
       JZ   RetrieveInfo   // 没有错误时则读数据
) e+ v' c0 J: w3 O        JMP  LeaveRing0     // 如果还是出错,直接返回
% y+ T7 Z' j0 u( _* C: Y8 d" j4 x* P: x$ l
       // 读取数据& X/ F9 b7 N/ r6 m: D, K
       RetrieveInfo:
0 x* t6 S8 ~2 V; S0 I; g- D" @* Z7 M" U: w9 U/ r) m
       LEA  EDI, wOutDataBuf) a$ c+ M: g7 C0 b& s
       MOV  ECX, 256% U; c  E4 r( S& r2 p7 V7 U
       MOV  DX, dwBaseAddress0 D* H8 @  N5 ?. U$ d3 g8 Y" m
       CLD
  Q* `/ k  H2 l. B* Y$ R+ I5 @7 ~  K! e# C' p, ?0 B
       REP  INSW7 ]( W; U- I+ k. Y$ F. i- R" P
% [! s5 r5 N# I/ B# r* S7 y- K% m' d
       // 退出Ring0代码" N2 g9 ]  a1 H9 B
       LeaveRing0:  o7 i' A& V2 B/ j( T* o  Q9 b
& T9 q: ^0 b4 m2 |
       POPAD1 M* c( x  P1 g3 \$ f
       IRETD
, }( f, @9 c3 B( e$ M3 @* G3 z' Y! w  ]# m
       // 激活Ring0代码9 {0 W& Z4 B; [3 f  T
       EnterRing0:
& X8 {# x8 w' h6 _
% I+ W: H. K* @# z! U& m' Y        // 修改中断门! c1 l0 C( j: @% n7 Y, P
       SIDT FWORD PTR btIDTR1. V! {, g  r$ c( T
       MOV EAX, DWORD PTR btIDTR1 + 02h" {$ E7 X; q  \8 i( T
       ADD EAX, nHookExceptionNo * 08h + 04h' Q* C$ h6 @9 c
       CLI
' j; g  q" E4 k4 S6 q; X4 x8 h8 _  c, f
       // 保存原异常处理例程入口
) W& V9 B: Y) k% \, j        MOV ECX, DWORD PTR [EAX]
% B! b: [8 l( ?/ T0 h. z0 j        MOV CX, WORD PTR [EAX-04h]
; [& B7 @- b  {% g; i        MOV dwOldExceptionHook, ECX5 A, |, G" g5 |7 j. Q

! P% {8 r5 w0 A0 }7 s! x3 X! p        // 指定新入口
) X" J; |  s2 b8 b' S; b" i9 w        LEA EBX, Ring0Proc
6 _4 a! g4 F% v: s4 R0 s0 b        MOV WORD PTR [EAX-04h],BX
# o5 [0 z) P' o3 \, w. V3 Q        SHR EBX, 10h
/ W' _' C7 `3 @  Z        MOV WORD PTR[EAX+02h], BX
! l5 N& P1 r2 K8 b. l6 \( [" U
% k2 ^% q7 i$ P: K& m        // 激活Ring0代码2 n, ]3 z2 r5 w$ {8 C
       INT nHookExceptionNo
' h; P7 Q3 S# m3 G/ x
6 n( ?6 O) R) p( _7 d( |        // 复原入口
: Q4 m7 l6 P! ]5 l& }" X        MOV ECX,dwOldExceptionHook
+ N9 y: ]/ H: k; V8 J1 K6 U4 _' M/ N/ Z        MOV WORD PTR[EAX-04h], CX7 P# B6 b: _. Z3 C- @! o
       SHR ECX,10h0 t. Y# K# @( C! q2 K; @
       MOV WORD PTR[EAX+02h], CX
' H0 ~3 `8 V+ s% y5 V7 i6 H( Z        STI
; Q5 F- d1 ^+ z0 S' |    }/ T/ u5 M& N# {0 u+ \) G
   if(!bIsFirst)
! F, v1 C% j5 N9 _/ A    {
. p( D- v6 i" J- b8 D        bIsIDEExist  = (bool)btIsIDEExist;
4 `' E; Q7 q6 k% U        bIsDiskExist = (bool)btIsDiskExist;
9 _2 J2 _! _. N1 d        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));0 d( \7 J) C% A) X7 ?- o, a  ~% @
   }
( z/ p9 ]* \" V$ o5 _& w9 z}
, G9 _& }' M# u7 T/ d//---------------------------------------------------------------------------
; U) T  m$ h4 Q! a7 a; G$ {. x// 调用方法:9 P/ i' R0 h. m. D' ]) p, e; p
void __fastcall TForm1::Button1Click(TObject *Sender)( D% v* M! G, i
{
+ k: m& u) ^, x2 @0 ^    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);5 a+ t# }1 b; |( `
}
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2025-5-5 04:37 , Processed in 0.016038 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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