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

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

[复制链接]
发表于 2005-5-30 19:22:36 | 显示全部楼层 |阅读模式
  #include <WinIOCtl.h>
- y" m1 d. B. u. f4 n. K#include <stdio.h>
+ o0 ~- t# [* Y
6 W! J3 K4 I6 l2 |/ k#pragma inline; g% h# j: G/ _" }, |
//---------------------------------------------------------------------------4 O; G6 K( g" E% e; R* k
// IDE NT/2000/XP专用变量
# F% H( z1 @+ x' n4 L2 U: v#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
# h: |( J9 n$ I#define DFP_GET_VERSION         SMART_GET_VERSION; @' h3 J3 y! R1 b$ u+ k
#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND* d3 S, Y0 F5 a9 v! O
#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA0 g" {+ I: @7 k
% [: z3 i% y$ n) l) F
const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令
' D' [7 B# z; r, U) pconst WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令$ C& P. E" h0 g. N& c
$ X0 Q! B3 ^+ B& E2 t
const int MAX_IDE_DRIVES = 4;
/ v$ m. c1 b- J* e: @& R
# n8 V& R* V  s8 s// SCSI专用变量
- }. \4 R6 I) n' H- Cconst DWORD FILE_DEVICE_SCSI             = 0x0000001B;
7 f8 ?# {* ?# @& n* Econst DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
  p. y$ x7 Y! X& Q( e* Xconst DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
# C1 h; u/ f$ R! x1 J* t9 f$ ~* @const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;$ O  ~: p2 w1 o

$ C5 l3 f/ s% ftypedef struct _SRB_IO_CONTROL- t* m7 Y! I  `2 w3 l3 o/ ]+ G
{- j1 y7 L& H+ D. Y+ g+ S
   ULONG HeaderLength;
2 b2 P& `- x9 L( y) x6 K; @    UCHAR Signature[8];
$ I6 K5 Q1 `/ N0 n' A5 U7 W( N    ULONG Timeout;9 q+ f. C3 t- ?* }" `3 L$ E8 F
   ULONG ControlCode;
: O; ]' M! F- f  O$ z- y    ULONG ReturnCode;
1 d7 o% z# p0 e% T. D& W: D' B+ X/ j    ULONG Length;; F3 }& u! S! C- j
}SRB_IO_CONTROL, *PSRB_IO_CONTROL;
5 \  U! \% @# N, X  F& a
6 J) \* D- Z5 c+ p4 `/ D' `9 C( ], m// 读取的主函数
- i# q6 c/ r" m( I$ Jvoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
0 }6 U0 C% x' l; S
5 O6 \& ^4 M* M( P$ ~1 f3 i8 ^// 辅助函数: [3 K" q$ a' y3 c" A4 f- ]+ ~
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);; F& C0 B  h: ~6 M$ p- x' K
// NT/2000/XP函数8 U+ l! V: {( p4 T. Y
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
1 s; g( z5 @, }) a- x! q7 zbool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
. G( ~$ X5 X! V( Z# V- {: r6 z        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
* K  u- h; V* f7 S1 |% A( d        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
; B4 c; Y% y0 n6 Q// Windows 9X函数
; e, c" u' F1 F2 ^+ c6 mvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);
8 ?% A5 \, U; j1 h( N; ^. s# _void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,4 m8 V6 L* D9 x9 B4 K* d
       BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);8 j: u3 b! h, W1 p$ ^% }$ k7 z

9 y9 L7 C; r) ~: t: e// SCSI读取函数(for NT/2000/XP), {. C% e5 Z  [2 a% D
String __fastcall ReadIDEDriveAsScsiDriveOnNT();
! x1 h  O3 g0 {( ~8 h$ F//---------------------------------------------------------------------------
. k+ c/ p6 R* c// ReadPhysicalDrive
+ V9 |1 }  T9 u: j2 Qvoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
) @" S9 Q" m, j; l0 _- [9 `% M{
0 |2 L6 w; ?) `' N# m8 D4 m: i    switch(Win32Platform)$ @* T6 Q/ h5 D2 p8 h2 g. x8 u
   {
4 o  f( K' T- r. \        case VER_PLATFORM_WIN32_WINDOWS:4 S2 K( ^/ F1 l! I
           ReadPhysicalDriveOnW9X(pSerList, pModeList);
0 M5 A6 a: m% a3 u- V! V            break;7 L5 P$ r4 K1 P$ y9 j
       case VER_PLATFORM_WIN32_NT:
5 z- {, L6 W3 a  m; y            ReadPhysicalDriveOnNT(pSerList, pModeList);
* q4 `) W0 D6 x! M            break;, Q% K( b; ^8 ]4 h. s
       default:: J; L$ }1 e& X0 }
           break;
4 t7 w; y0 t) Z8 E5 _$ e( w    }
: ~1 ^0 N9 V" g3 O5 a$ t. s}! N8 B) Z9 \* @. o0 M
//---------------------------------------------------------------------------
, Z) b0 z! z' c// ConvertToString
+ `8 W9 h2 d  G# p/ Uchar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)2 z# S# {" L: x9 e
{" A/ ?8 H1 e* ~  z) k/ Q
   static char szResBuf[1024];$ @- Z" V- l! b
   int nIndex = 0;
, L1 a0 l) o0 a1 b2 q; a    int nPosition = 0;
  }, C9 F" V2 C7 p3 I7 ]8 x" |0 W! \
   // Each integer has two characters stored in it backwards
0 x* p& l& w1 X& y0 n! {4 k' m; |    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
+ {' J, X) Q( c1 O9 I* g8 N    {
% R5 ~- V: [) v4 U1 y. o+ l" u        // Get high BYTE for 1st character* w9 Z3 f' `8 {5 b. u4 k" ]1 R
       szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
6 S4 ]0 r6 V& F- @. H        nPosition++;: ~5 s, A8 x7 h' x$ [4 y

/ S) F9 ^" \( B+ f# \6 T' t        // Get low BYTE for 2nd character9 |) c, X  X; Y0 n8 B5 j
       szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
/ U4 Q- r! J$ I" K9 P: O2 v' {        nPosition++;# X) _8 h/ G2 I9 W0 E
   }
% n% Z! k$ w- Y' V
3 t0 L8 ?7 Q. l0 q; X    // End the string
8 `' q$ l* [( j; t0 F& b2 c    szResBuf[nPosition] = '\0';
. Y& }5 [5 w! J9 W. I1 e- x$ `. |+ Z9 j3 ^6 F
   // Cut off the trailing blanks7 |' \- r. ^# `/ p
   for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
( F/ G/ I$ K" G: E" y9 f: I& G        szResBuf[nIndex] = '\0';2 ~7 ^) B% }1 Z4 i9 P

' j$ z+ e$ |7 X0 ~0 t3 @; T, p    return szResBuf;7 f2 s$ G8 b4 H/ L4 D3 H
}
0 a5 }2 D2 ?' Q- l//---------------------------------------------------------------------------$ q, m/ L% o  Y) o  H/ m: d' P
// Winndows NT4/2000/XP 代码7 v3 l" D) K# s& l+ Y# G6 @
//---------------------------------------------------------------------------1 x" ], e/ Z7 X8 x" f3 E$ \  B
// ReadPhysicalDriveOnNT
  [+ X* h- c+ n! M  Lvoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)- m' Y* [& Z  I. x" I* d$ Y6 L
{, R. Q' v7 |) z' b7 V- {, f
   // 输出参数
$ X3 z" J2 G7 _) V% ]  o    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];9 }. _( K/ Q% O& k

; y- X: Z- l( s% g    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)9 g; |/ H4 [. r( H- G
   {
0 z" y' z, V, F- R- o        HANDLE hPhysicalDriveIOCTL;" V3 U5 L* h% t6 F
       char szDriveName[32];1 \0 [2 c0 P6 a

/ A7 s, Q: {$ b- c& a2 E        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
4 w0 j5 l5 d' n' O7 d( y6 W        hPhysicalDriveIOCTL = CreateFile(szDriveName,
) k. H: f( |6 i) `+ J& }* Y( P                        GENERIC_READ | GENERIC_WRITE,6 S0 ?4 p! B, C9 K' k
                       FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,9 [( R! e& t( L; m1 R6 h
                       OPEN_EXISTING, 0, NULL);
4 `& F( ?! U/ d; M! b8 a/ g2 A" v+ v- f: [: l
       if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
1 E6 F- w, ?# ?/ K* @        {5 a5 F( c0 @" Q
           DWORD dwBytesReturned = 0;
. t4 M5 G7 h( }, D  G6 d            GETVERSIONOUTPARAMS gvopVersionParams;) C' L6 _8 O% Q& P! Q
' j: i8 x) O$ f
           // Get the version, etc of PhysicalDrive IOCTL
( o# b* Z, r- O, B5 r            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
' q5 }% y' Y! s+ E5 f
! u. h4 l' A. G0 l9 x5 {            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,9 R( C- @: g2 V1 n
                   NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
9 y, _8 m' I0 `! s                    &dwBytesReturned, NULL))& ^( G0 h/ c4 i% b
           {6 b8 H$ x' a2 [, f3 W+ Q# U" g
               continue;/ i9 V# E8 O9 a  H' E
           }
% Y5 K6 I7 x; z, e. I) W3 |1 ?0 F% E7 s" N
           if(gvopVersionParams.bIDEDeviceMap > 0)
! |+ K% L, _: `9 H3 y4 t1 i            {
$ J+ ?" y7 Q3 I: t                // IDE or ATAPI IDENTIFY cmd8 q, P+ U/ x! m. f
               BYTE btIDCmd = 0;% c: {) @2 b% A) ^3 m+ |3 E+ O: f
               SENDCMDINPARAMS InParams;+ @/ }( ~% @3 u) d' O$ F! D: z) Q
               // Now, get the ID sector for all IDE devices in the system.+ [6 A  m9 K+ w: r
               // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,( @+ r- N( K! u0 u/ {
               // otherwise use the IDE_ATA_IDENTIFY command
2 P2 N' ]9 w6 M! u6 a* s  ?                // 具体所得结果请参考头文件中的说明+ W( |4 e, Z  ~$ s
               btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
+ j' _  g! h6 G" E7 r& ]% R) |                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
. y4 F$ }% L- V  U* a                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));4 S, u! T' E1 C8 V
               ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
  I- m8 z$ ]! n& }- w5 H
  D5 p. V0 l: ]; z" H# y9 e3 X                if(DoIdentify(hPhysicalDriveIOCTL,
7 x& ]. ~" x9 G6 ?! P; v                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,& O; k, k' S( B0 I, ]  Z. x. l4 T8 h
                    (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))6 f# Q5 s, P* N' ~" |3 Z) v
               {
; l9 G+ w4 K3 O" V! s& i' Q                    DWORD dwDiskData[256];
0 _7 h' T/ R" s                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件9 c% N; t) J% \! x" t: b) C9 q( L2 y
                   char szSerialNumber[21];
3 ?5 V. i+ ~( S6 |  K1 g                    char szModelNumber[41];
% z2 f" d+ O) I, p
  G8 `  S  R# ?4 S$ Z                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
$ U; u/ k, }1 u1 e" V' c! v                    for(int i=0; i < 256; i++)
+ k( A# Z8 V0 f- G( [; X" u                        dwDiskData = pIDSector;( H* s6 c; c, d# C/ b1 ^. ^
                   // 取系列号
1 o1 N4 J5 d1 a3 Z$ o                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
1 `5 m' v1 p8 _                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));! h) i& a  n+ ?
; e% D! ]! s; g* p" X
                   // 取模型号$ d; K4 F2 K- ~% R2 Z
                   ZeroMemory(szModelNumber, sizeof(szModelNumber));4 |5 a8 X9 o! y1 T9 W/ W
                   strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));4 s, q' ^! p9 L) S
: y8 \0 p  ]# C  @5 t! y5 @
                   pSerList->Add(szSerialNumber);
( v6 X# f) `' Q  X, f8 F: f                    pModeList->Add(szModelNumber);( M+ w  o: l3 f/ V/ j
               }+ K7 n' I/ N7 ?. q2 c, ?
           }
/ j) r) `# t& S            CloseHandle (hPhysicalDriveIOCTL);
% [7 J7 F: J$ ]3 N  F9 U        }3 u' S2 V! t9 L
   }
$ V2 Y+ @7 }) N1 u% a4 o: K}
; F: j! ?; u: e) ]. S; v- q//---------------------------------------------------------------------------
6 Q  [& T/ J% n// DoIdentify
5 l. m3 u- j* Q# j& Kbool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
' n% v$ o/ X2 W  ~( ?6 x$ h% W" \              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
. `" x& F8 h5 ~              PDWORD pdwBytesReturned)
. d: M8 Y8 h6 i4 {{1 b9 i4 T1 u, @# e1 X; o1 m
   // Set up data structures for IDENTIFY command.
2 @4 U& x& |3 H& }  C7 _    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
  `. C9 L; U& \1 ?5 H& ]2 r    pSCIP->irDriveRegs.bFeaturesReg = 0;/ Y. [/ p( v. g8 x( w
   pSCIP->irDriveRegs.bSectorCountReg  = 1;
5 X. b0 J/ n4 v' n; l( }    pSCIP->irDriveRegs.bSectorNumberReg = 1;( N$ V: G9 s" F
   pSCIP->irDriveRegs.bCylLowReg  = 0;
: C% S8 ]- z$ V, g    pSCIP->irDriveRegs.bCylHighReg = 0;7 s% ~1 u& z' ~: m9 x$ U

0 q2 O+ B4 F: [    // Compute the drive number.(主盘和从盘所对应的值是不一样的)% S/ O7 z0 I' M6 S. {' w' r
   pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
5 }' Z) T/ S. I; D9 T( u* K2 d9 ~$ F; M( {' ?( Q0 H! ?
   // The command can either be IDE identify or ATAPI identify.
( c5 N$ P9 J( O% [    pSCIP->irDriveRegs.bCommandReg = btIDCmd;! H8 M; ~" B+ x, D: O* C( y: t. d
   pSCIP->bDriveNumber = btDriveNum;
2 f! C7 |0 ^3 c% m6 V- u5 Z0 x& J    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
! X9 v& ?$ ?" n3 m
9 m3 M8 |, ], w    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,4 g" V' D' H0 _$ h0 q; G
          (LPVOID)pSCIP,  }7 a7 }; m  _/ t, _$ ?. W7 b
          sizeof(SENDCMDINPARAMS) - 1,; [7 h0 ^7 F0 I& ^; s
          (LPVOID)pSCOP,
) |1 A0 \2 D7 [/ [+ d           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,: a$ t6 k  B, y, X- K  k7 P& t2 b
          pdwBytesReturned, NULL);7 b' b4 k( a6 W3 T, ~
}) e' j# D) \& J. w  W2 d0 e
//---------------------------------------------------------------------------
. Q! o, d+ P" h5 Y// Windows 95/98/ME 代码* g( @: a! _0 h% _' j
//---------------------------------------------------------------------------
; V6 k- y; a' Q/ ]5 [( F& z// ReadPhysicalDriveOnW9X
4 z- }4 Y1 F* \+ h: gvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)% S8 Q  m9 i3 `0 L' \5 j
{
. K; [7 U8 \+ H8 h+ N5 Z9 x5 `    WORD wOutData[256];
! Y5 Y- L  \& z+ ^! J    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);6 i3 Q9 Y) j# e' d

! @. @: }9 q2 L3 E+ y6 w    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。3 u9 O1 j, `5 b% F) W; S  Z5 T
   // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
' w% B  a8 u' m0 D. o0 `3 B    // 避免蓝屏的出现。(期待高人能指出原因). h1 e/ w( G* G5 ?
   for(int nDrive = 0; nDrive < 8; nDrive++)2 G1 N' s9 e4 J6 ]% }
   {, @! m0 @& G1 ~( C2 S2 c9 E8 B
       WORD dwBaseAddress;
* B7 }4 C; H  e2 t3 r* u        BYTE btMasterSlave;         // Master Or Slave
; i: i) |$ R8 t0 y% R7 p4 P9 i6 L" E        bool bIsIDEExist;' k- H3 |. L1 z8 s3 f
       bool IsDiskExist;
' @, N& i" a( g' g7 s3 P
$ @' B2 K6 h# F1 P        switch(nDrive / 2)% q+ H+ j+ T6 I8 j
       {! \$ G, Y, W, Y5 M$ o. m! Z& Q2 m
           case 0: dwBaseAddress = 0x01F0; break;+ W9 S  [& b  t0 v. X. p
           case 1: dwBaseAddress = 0x0170; break;
' C; \5 C3 |7 U" w            case 2: dwBaseAddress = 0x01E8; break;
( T4 s& V) r& O& i$ p( m            case 3: dwBaseAddress = 0x0168; break;* X" E+ A. X& U6 g2 j% |
       }/ q# _5 b# `) K9 m1 i. r& I
6 d0 |& j  s' ?7 X7 n+ |6 h4 e  P, l
       btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);1 V# y- S6 h$ h* s2 L: x1 l

" N+ W& b( i# F1 ?/ l9 y3 T. r+ a# H        // 进入Ring0% r$ g; Z5 S* q1 S4 ^
       ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,$ w2 h; O0 L' X2 w* G
               bIsIDEExist, IsDiskExist, wOutData);/ \5 A: L% l3 \7 g. ^
   }# ?- Z  Q3 U6 `6 y
1 A( r0 X1 o: c. C7 f& D9 i1 B
   // 开始读取0 C+ @+ C3 s4 z( H
   for(int nDrive = 0; nDrive < 8; nDrive++)
& {7 @; h/ R- C& P+ n/ m6 i# @* Y/ u    {& L  y% d% y$ E! w& \
       WORD dwBaseAddress;
2 E9 E2 Z3 l" N1 Y# v# U8 D        BYTE btMasterSlave;         // Master Or Slave8 h  Z, y, C3 |1 Z  L# s
       bool bIsIDEExist;
8 c" x/ {  ?4 V6 c$ I# d. u0 l& ?        bool bIsDiskExist;
$ `. R6 g9 E; f        switch(nDrive / 2)
! g/ x: k& K, q        {6 M' F* {" i2 Q( |0 Y0 t6 L
           case 0: dwBaseAddress = 0x01F0; break;; n0 _) X4 q) _8 K
           case 1: dwBaseAddress = 0x0170; break;
2 h# b! u) ?! z            case 2: dwBaseAddress = 0x01E8; break;
0 R& \+ b7 W# [8 i: n$ D" z2 V) g            case 3: dwBaseAddress = 0x0168; break;
: h6 x4 L) J2 E! w        }7 B6 X: B4 K' c4 E$ F! W5 [

5 b5 {$ S1 G" r$ S( _        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);: y( e* O& |" s2 b% a( }

9 @; p/ T' O9 I7 u. \        // 进入Ring0
0 i/ {5 M2 H5 R1 |        bIsIDEExist  = false;
$ X+ ?( [' ]  s: g. E1 h0 p! u& m* W( O        bIsDiskExist = false;
2 i0 |. O2 y" A( q8 E        ZeroMemory(wOutData, sizeof(wOutData));! R' s) Y/ P( N

+ v4 b) D  l/ a! ?7 g8 g        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,7 X) F( s8 N5 t+ z1 _1 N( S
               bIsIDEExist, bIsDiskExist, wOutData);
! O4 p+ X* D9 x: O
. u) X/ i1 E0 Z/ t. w0 e" x2 Q        if(bIsIDEExist && bIsDiskExist)- \4 a8 L. _. Q" K6 F
       {, N5 w9 S* V* G0 @
           DWORD dwDiskData[256];
; `5 `1 h# S# m& l- N1 F            char  szSerialNumber[21];! E0 z, C. O9 J
           char  szModelNumber[41];8 u' ~2 N4 v/ i/ J6 _- c
8 ^' A4 J6 w1 z% ]
           for(int k=0; k < 256; k++)( Q1 C; d! g3 R7 n
               dwDiskData[k] = wOutData[k];
3 C1 v; N& m2 F  c& q
. w. J7 `+ Z4 s$ P            // 取系列号
+ G5 C) ?# M- K% b            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));6 Y0 N, y" B, j+ A: ]4 W: M6 X
           strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));3 V! y. ]: k7 q3 N

) d- p* {  Q' g            // 取模型号4 z, x' \. l4 e2 X3 o9 t# ^
           ZeroMemory(szModelNumber, sizeof(szModelNumber));- Z" Q* }- V' H! L
           strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));& n# L: ~0 ?# u, H' ~0 i
/ j1 u2 M& U1 [7 z! h
           pSerList->Add(szSerialNumber);
' V$ d  J0 T" E1 ~$ p! x9 |            pModeList->Add(szModelNumber);
8 A* R) {" E5 l. M2 c0 m0 I4 s        }! K! U2 C; J) g: O+ _
   }
' G) q$ R+ z( X" C$ ^    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
1 d' x0 I( G" g+ b, x1 C}
& I+ L% t$ c4 Y% Q+ v//---------------------------------------------------------------------------2 h3 K& k. x3 ^! a- c
// ReadPhysicalDriveOnW9X_Ring0()
- e" A' k+ O/ W//
( t% a% g& }% U: p// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h+ ]5 e" o/ h% b* h& t
// btMasterSlave = Master(0xA0) Or Slave(0xB0)* t0 B6 V$ `! `' C% R
//---------------------------------------------------------------------------
8 t- }8 H0 g& }- f, Hvoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,1 n7 N4 ^! o4 ~, o+ O; ^+ o& X4 O
       BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)3 d+ C# a' d& b! ^1 C
{7 b9 R! U0 k0 ^; @$ }
   BYTE  btIDTR1[6];, w% H: Q$ y4 L* O5 O
   DWORD dwOldExceptionHook;
3 D" W9 q& n; q1 w, A    const int nHookExceptionNo = 5;
9 Y9 h% m' f. o9 T- c8 _: H1 D9 |2 K: G) B$ D  c1 V
   BYTE  btIsIDEExist = 0;
1 h) \  |$ r  D9 [( y    BYTE  btIsDiskExist = 0;$ L" e* n3 W; x( a5 |3 D
   WORD  wOutDataBuf[256];% S$ V; C7 M$ Z% i* L- |: I) V3 {

! {5 k( H  q4 Q* G1 k    BYTE  btIsFirst = (BYTE)bIsFirst;
* j& C* P+ M5 J9 l4 D8 ~% [+ J, }2 r! B! @, r
   const BYTE btBit00 = 0x01;* V, E# E/ I: s% C. R$ Y& X
   // const BYTE btBit02 = 0x04;' g& u8 C% y3 J5 g
   const BYTE btBit06 = 0x40;
* v5 y& _9 D1 w. H+ w6 p    const BYTE btBit07 = 0x80;
' X/ ?: B. w  B5 x# y    // const BYTE btERR  = btBit00;! X0 D  b6 h2 H, Y# @( W- q" Q* G
   const BYTE btBusy = btBit07;- g7 [4 Y3 b% I1 R5 X3 M+ o
   const BYTE btAtaCmd   = 0xEC;- l% s+ E! M# n) G
   const BYTE btAtapiCmd = 0xA1;- V: P# m2 N. A5 @1 Q/ B7 ?
4 k2 b# T1 n# n* t# u" ^
   __asm
* i0 r" }* W; k/ A5 K    {
* x3 ~+ ?! ?* [( X  K. v0 j; {" l        // 必须先执行这条语句
: I0 c: q& X* q        JMP EnterRing0
& N# Z/ S2 M, a. d3 [1 P8 {7 i( h0 Z& i7 w9 t0 q% d
       // 定义过程( z6 r9 d- k# o4 u! u3 z& L/ ?
       // 等待IDE设备直到其不为忙为止( y( R+ X5 ~- Z5 Y! s6 g* p. ]! M
       WaitWhileBusy proc1 U) `% y7 R- Y& C! ^* K$ X- P
2 Y7 I' X0 m7 L/ N9 x4 |# m  L
       MOV  EBX, 100000: |( Y5 p- E+ V
       MOV  DX, dwBaseAddress+ ^  U' A7 y' K8 w" b8 N
       ADD  DX, 76 T4 f  w/ h4 w

9 l8 G( O# t" C        LoopWhileBusy:$ N: L* b  \0 A2 E
3 ~0 Q+ {$ _  x8 b9 [
       DEC  EBX2 f3 |2 G8 W& L6 z: x
       CMP  EBX, 0
) j3 }! \* Y$ @: {% |0 @5 x        JZ   Timeout
& T8 f& v- X, q! v        in   AL, DX
. y" N. X. g5 g4 N( T' c        TEST AL, btBusy
" v" b8 G1 x$ O' ~8 Q: z& ?" z        JNZ  LoopWhileBusy
7 L1 n; v  N6 w% F' b. z" g/ Y8 d+ S4 o        JMP  DriveReady! V+ [3 b+ n; }/ ~: p: }$ t8 _

% {2 ~- T& n# z* l        // 超时,直接退出% Q' o# E# P5 S2 }* L% d
       Timeout:
1 ]3 M/ f! T$ W: f        JMP  LeaveRing0' |( t6 \* E1 }# L
       DriveReady:
; W7 j1 w7 f4 \        RET9 A& ^' e, b$ y  V, b
       ENDP   // End of WaitWhileBusy Procedure1 j1 ?8 }1 a$ ^9 u/ F% j/ R, f
2 j1 ~* t4 A5 b9 ^
       // 设置主盘和从盘标志
% H+ B0 r7 R, E( j% Q        SelectDevice proc' A& [! b0 v  v# H% J
9 ?% [, c) @' K3 ?
       MOV  DX, dwBaseAddress
; [" G* q! H& c* y- Y& j        ADD  DX, 6/ l$ W% c5 i* O# |
       MOV  AL, btMasterSlave) G2 U/ {( n' Y5 J2 `% X% t8 M0 ?  }! E
( Z2 I$ M/ G9 e; _9 I4 z% {
       out  DX, AL" B& e7 \5 ^5 a- \) }) E0 l0 X7 R
       RET9 k. |0 C: F( w" s: y5 e
# H% O8 c9 O0 @/ D9 q+ S
       ENDP  // End of SelectDevice Procedure  {8 f) T/ k6 z# V0 m
2 d- `( @0 ^, K- g7 @4 O( ~+ o$ X* f) {
       // 向IDE设备发送存取指令1 C8 G0 x4 @' T. A8 J+ O
       SendCmd proc
8 M0 K% N: _8 ?! k, ?( g
3 C% H, q, p! U8 Z) f2 f        MOV DX, dwBaseAddress: S& q; P7 p1 t: ~# b) q
       ADD DX, 7
: G% |0 x6 _( q( k9 _        MOV AL, BL // BL是主从盘标识,在过程外设置
2 c5 G7 ^1 L, b        out DX, AL! A, e7 K) L# W+ t
       RET# t: Q" b4 _% ~
       ENDP  // End of SendCmd Procedure! h% _4 k' F- ~) f
2 u+ q* X' V* Z: C5 ^, _1 X, c
       // Ring0代码
; r2 h6 I% K) @; D( ~/ E+ G* P        Ring0Proc:
8 S6 \4 v1 r( p! I* Z        PUSHAD; t" O$ _/ c: z7 S' w
       // 查询IDE设备是否存在* ]8 i% _% }" O8 _2 _' V: o
       MOV DX, dwBaseAddress
& p% D% L. U4 d, R1 o. M. ~        ADD DX, 7
0 I% w- d" M' x. |' D# P$ i4 R        in  AL,DX$ g6 ?1 P) g7 `

( n6 g. W/ ]* q, J; V        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回9 t( t2 ]7 e+ L+ U
       CMP AL,0xFF
9 Q( Y2 `( r- L        JZ  LeaveRing0) K: }% z  u: j; S
       CMP AL, 0x7F- a  ~) f7 D# y
       JZ  LeaveRing08 T/ }7 k/ i7 L' M

+ c  ?2 V9 d9 `7 T. j        // 设置IDE设备存在标志% X/ X& q. n/ `3 |# R: E
       MOV btIsIDEExist, 1
; J0 t& L, A; D8 \# G8 o+ ~$ E# D0 {2 n6 B( W% c! W: j3 ]9 s0 s* E
       // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)' C' ?2 |6 ^; O# [! i
       CALL WaitWhileBusy
) q) j% K! e1 J( P* x1 L; J        CALL SelectDevice% k& `- K* S& t6 e
: v" Z$ B& X8 b+ h2 F7 p8 d8 i3 T
       // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
# S& y* V; x; K, |        CMP  btIsFirst, 1
# H) |8 Q) ]# H7 m8 Q* T        JZ   LeaveRing0
5 V6 H% V% H! k' G; t) e' c# ~: t" _: y9 m( }$ y7 Z7 P8 ?
       // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
/ K: }7 p3 S) N- M. L+ @        CALL WaitWhileBusy& p  I1 m% S3 {! K: h( u2 Z

! b" Q2 ?- u5 O  j9 X        // AL的值等于cBit06时,不存在驱动器,直接返回
2 E; f* G/ l( r/ }' K" [6 s        TEST AL, btBit06, \7 W3 }* v; O% G: g! }
       JZ   LeaveRing0
6 h- Z' t9 w2 f$ R) b4 K4 w  P. a. S1 m2 _
       // 设置驱动器存在标志$ J. d# y1 _) r+ p3 [
       MOV  btIsDiskExist, 1
0 }. \$ F6 X/ [' v4 c$ y5 p. `" ^# B9 A. S- s7 m5 g: l
       // 发送存取端口命令! U: ?6 l  O, e# b& a
       // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,  H- X0 H/ F% h$ s! G3 X: a
       // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
  }7 D6 R. Y7 q8 h9 G        CALL WaitWhileBusy% Y- D: n# ~8 N% Z; ?
       CALL SelectDevice    // 设置主从盘标识
  |# z4 |6 p& ^( A, ?8 x9 t        MOV  BL, btAtaCmd      // 发送读取命令
* K% C$ J! I! p% [  r$ Q        CALL SendCmd" }6 N. s* x1 Z/ h4 Y  h& D" H
       CALL WaitWhileBusy/ K  g; Y/ ?& @. {
7 d  `1 _9 f7 J: N7 ^) [
       // 检查是否出错, L1 c! G  g6 t5 r3 ~" ^8 r* }
       MOV  DX, dwBaseAddress
9 r* u  x* O* _2 R0 G+ D  Q* n        ADD  DX, 7
$ Y# o' ?( _/ \$ J) k6 u3 E4 u5 x, X/ O& P- @. y. U3 m* i4 r
       in   AL, DX% f6 d7 x; c. q. Y  c* ~

6 M! k& v% G2 n, ?4 w7 T        TEST AL, btBit00% T. }" n! j# X
       JZ   RetrieveInfo   // 没有错误时则读数据
3 x4 o+ X; j4 n4 C) e( E/ @) B2 G# z5 B# [4 N
       // 如果出错,则进一步尝试使用ATAPI设备命令
+ w- M! N( Q. A, d- V7 E        CALL WaitWhileBusy
& U8 E' _  p4 s8 r, I3 s        CALL SelectDevice
% R; L) S* d" h' g0 K! C; `/ `        MOV  BL, btAtapiCmd% c% G7 a/ n/ J! u) |' \" h/ x
       CALL SendCmd
: h* e9 h0 h* g        CALL WaitWhileBusy. d, @% f' r+ ?0 @# a" l) B! k
6 M# n& ]7 Z$ W* `
       // 检查是否还出错
+ o; s2 i7 c. H6 e7 _6 @        MOV  DX, dwBaseAddress
  o: d- D. D( j# q4 ?8 ~/ P) j  f        ADD  DX, 7, W6 U$ Q4 }9 A/ Z/ |. w$ W+ u
       in   AL, DX
, t8 K& q' q! T4 Q* e        TEST AL, btBit00
8 ?& }* K% k% c+ w; j        JZ   RetrieveInfo   // 没有错误时则读数据
4 J! `$ ~4 p) z0 }' j" `        JMP  LeaveRing0     // 如果还是出错,直接返回
- }; A1 b' F; ]0 U5 c: t- J+ D2 O3 i- [$ }
       // 读取数据
4 T5 z* \: ?0 e5 Q' m9 X. J% V        RetrieveInfo:  A5 q# r! L2 E3 i

1 K/ ]1 W! ?# b        LEA  EDI, wOutDataBuf
7 H: v: M" J9 b9 S        MOV  ECX, 256
  q) Y/ r. M+ ]' Y# T! L% n- [        MOV  DX, dwBaseAddress
. v. f4 s1 s% {& E- ~) D" ~        CLD' [4 M# H  @' M* o' _- ?, E4 z, z
' z$ H, G5 H0 V4 V# M
       REP  INSW
4 h6 `5 Q( B5 c8 z7 C
/ `3 u2 O$ r2 I4 a; W' Z        // 退出Ring0代码" V+ c! ]  _. Q1 d
       LeaveRing0:
1 f; |5 T2 Q7 C, f# k
6 B1 [- a/ M! ]) L9 K        POPAD
7 q& N5 G& w4 B' L. h9 ~; \        IRETD
* F5 [: o/ z' y4 `' m0 r; H9 Y3 _  y) d( M2 d* v5 ^
       // 激活Ring0代码
1 B: n; N- K# L2 x  N        EnterRing0:! x# f9 b  C1 {/ Z0 O
& H+ d: x: d9 w5 d1 B
       // 修改中断门
+ F4 v8 c, t% S( x& L        SIDT FWORD PTR btIDTR1
7 v$ U( u0 z( }# Y3 v- i) h        MOV EAX, DWORD PTR btIDTR1 + 02h
9 \% s) o5 A6 K+ u$ }        ADD EAX, nHookExceptionNo * 08h + 04h% Q7 Q# j6 V9 F
       CLI9 l. {4 n, p' M1 O

' D, j& g3 x3 |( n+ m1 A        // 保存原异常处理例程入口5 T; _  F# r* W: J8 T
       MOV ECX, DWORD PTR [EAX]* Q5 M' V& W$ q1 t1 ?/ |5 P
       MOV CX, WORD PTR [EAX-04h]
: ~! t& V# K; T7 B7 W) l        MOV dwOldExceptionHook, ECX
" a. q: p1 k: ~" F. Y/ [; n* E  I" c5 V- \) D* n/ q2 }# r
       // 指定新入口
  A1 M3 N' ^2 }! g        LEA EBX, Ring0Proc
% M9 Z8 k' j& r0 u' E, J8 e        MOV WORD PTR [EAX-04h],BX
; ~# M8 g7 f' I, _. g" x        SHR EBX, 10h4 q, s# \% g; A, P6 R) R7 p' ?
       MOV WORD PTR[EAX+02h], BX: _: I4 }/ R4 ^: N
' ]3 u' ~  R: D: o
       // 激活Ring0代码
7 u9 m' {& ~3 j! z1 Z+ d+ R+ \; a        INT nHookExceptionNo( e+ _* s; X$ F

0 F. y# G+ }! U2 c0 o8 M2 o+ u        // 复原入口
( G0 y& h" T  `) n# K        MOV ECX,dwOldExceptionHook
" y% x! ]& m6 {% \2 R3 }        MOV WORD PTR[EAX-04h], CX; v; Q: q6 j: X( Q4 A5 l
       SHR ECX,10h
( Y! @: Q2 v2 g        MOV WORD PTR[EAX+02h], CX* H! ?: i7 n, p9 X6 V0 I& T/ {# x, P
       STI, X8 c" H5 l& ^6 C4 V+ @
   }
2 C2 ^5 v5 y8 j2 n. c. b( ]+ E    if(!bIsFirst)
. P# D) ?# ^/ v1 ~    {6 v/ g& D- u  B9 C, o/ v; f/ Y  N& C8 b
       bIsIDEExist  = (bool)btIsIDEExist;
/ b- ^5 D1 M$ r+ F  c# L7 z2 j0 G! B        bIsDiskExist = (bool)btIsDiskExist;2 t: i; [3 z3 _. n# i
       CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));$ h* }+ }' z  [/ J
   }
. R5 n. {6 @" I" T1 ^+ d3 ^}
; D# ], o; d: ~1 v$ |9 c//---------------------------------------------------------------------------" ?5 H2 e4 C- z# }" [/ K! B
// 调用方法:
4 G+ H5 w1 N' w1 svoid __fastcall TForm1::Button1Click(TObject *Sender)" Z: v0 ^2 L: _( b3 c
{! l# d! p' C% |
   ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
4 X8 D+ C1 u" }; a8 k}
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-5-2 08:57 , Processed in 0.021515 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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