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

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

[复制链接]
发表于 2005-5-30 19:22:36 | 显示全部楼层 |阅读模式
  #include <WinIOCtl.h># _9 q9 q6 O5 B4 K; B
#include <stdio.h>  ^2 r. `4 k* Q! C
' K8 S6 Q6 C- t8 A
#pragma inline
4 i: X8 S' t, |//---------------------------------------------------------------------------
; j% s6 X4 w' F) ~3 E' d2 N: b// IDE NT/2000/XP专用变量' B9 o, d' V  L
#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
- |. y2 \$ X- S7 _2 a3 |+ w- @/ f#define DFP_GET_VERSION         SMART_GET_VERSION
$ `+ p, E; ?( O#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
& M: |. {* l5 H0 o5 g7 I( k#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA# y9 E* u7 ^9 \1 @$ }: M& f  F/ M

+ H% _# }  l& M! F( o5 Pconst WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令$ J$ e4 N/ x/ v6 }9 J( F4 S. |
const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
" K, W4 g; W  o) A8 Q# S! U" Z* U" m0 _% p, a# H5 y1 U; E9 I
const int MAX_IDE_DRIVES = 4;3 l1 m9 \! g* O( _0 w

0 Y" s2 S7 }! @* `2 H  `// SCSI专用变量
% U0 [1 H: O0 u1 [& Xconst DWORD FILE_DEVICE_SCSI             = 0x0000001B;
7 ?% K1 Z7 b& `; l0 ^2 m6 N( jconst DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
& ^% I6 f5 L" Y5 d5 Econst DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition' n) |' Q% Z3 [4 I
const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
% k+ W( u; s7 B3 U$ F; N
" K  J8 Y8 w, \typedef struct _SRB_IO_CONTROL" l' l2 \$ S' J( h7 r
{, Y7 V/ _0 T4 h) K2 w# N
   ULONG HeaderLength;; u# V6 r' ^! H1 B
   UCHAR Signature[8];) x3 R& Q6 L8 o' |$ X; ?
   ULONG Timeout;
$ |. z  J$ G' C- r0 c1 p& i' R+ `    ULONG ControlCode;! ]" L6 m1 F) i/ f
   ULONG ReturnCode;" e8 Z' x+ r% f4 I8 x5 e
   ULONG Length;/ f- Q, H; {! ]5 S  b
}SRB_IO_CONTROL, *PSRB_IO_CONTROL;
3 Q; G& C  x6 H4 X9 q- f
. E5 W* y* I5 M8 N4 {// 读取的主函数1 H2 \4 ~: J- W+ S* z6 _4 w
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
1 Y+ W( K  h5 x2 ~9 F3 T6 s. i+ \  `  Q5 [) }
// 辅助函数
: k3 c1 G8 t; d  V- {# k# dchar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);( s- k: Y& [, U' U" X
// NT/2000/XP函数" X$ z5 H+ [: Q2 w3 p, W
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
: O0 a' i+ @9 b$ A: I+ d* Vbool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,7 d9 O0 R9 K& m: `
       PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
1 n& Y6 t+ Z8 H3 w. y9 I/ w4 F' U        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);4 B: H; }0 K6 {; P7 W" @
// Windows 9X函数
/ N7 I, i% x3 wvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);
/ n/ X  s, E# qvoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,! W) y7 Q/ ]# X- A0 {
       BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
& R: o& i, p% X: ?" X
  K8 e1 ~" L6 U) G( N// SCSI读取函数(for NT/2000/XP)
6 G4 F  I8 p0 a% DString __fastcall ReadIDEDriveAsScsiDriveOnNT();; Q& R+ \6 \* {
//---------------------------------------------------------------------------
1 N/ w, K- ^7 ~7 ^' o- C7 {// ReadPhysicalDrive0 J7 {) J  E4 g# [" u. E
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
3 Y# ?: M) @) C- a/ T/ {1 \7 q7 X# `{- j# e. M+ J* ~; n' c
   switch(Win32Platform)+ ~. Z3 j& Z* [8 f
   {! m+ ~" W  Y2 G. I& Q. K
       case VER_PLATFORM_WIN32_WINDOWS:( T. f' L# A! I3 W% J
           ReadPhysicalDriveOnW9X(pSerList, pModeList);9 ]. M3 W  x: M" _5 n% i
           break;0 Z- q, F9 [1 E9 p( O
       case VER_PLATFORM_WIN32_NT:- D) B2 j* Q: A9 W6 m: \
           ReadPhysicalDriveOnNT(pSerList, pModeList);/ B: ]# U! S* \9 p
           break;
1 U+ t* Q- ~0 U- u- x        default:' y- p0 j! q% ~* k2 w) F
           break;% o: C" z" w' K7 _6 w) G0 p
   }
+ y0 d4 D! I* v% ?$ _}
6 v2 g6 e8 q1 @( p//---------------------------------------------------------------------------) R6 l6 Z' B9 M! }2 I4 W
// ConvertToString
6 _  }2 e( k6 h6 \% E) vchar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
3 ?9 }) L: b' T! ?1 W# D# n5 q{
1 c6 F' I' s6 @/ ?  q    static char szResBuf[1024];
/ \$ t* ]; h  U+ v, s; r) D    int nIndex = 0;
( S/ n5 u* k9 F: Z3 i- D$ S; H    int nPosition = 0;" K& A; B0 D8 K# {- b/ y

' L. Z- |& U6 k( b    // Each integer has two characters stored in it backwards$ s9 q) X% d  z: |9 X
   for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)" ~% N9 ^. M4 M
   {
" t% B" h, J9 x5 ?        // Get high BYTE for 1st character2 X. o) C" ~: @8 q# ~  [; h% x" J  h7 X
       szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
& x) v+ g$ R; Z        nPosition++;  P; L9 E4 q; W9 l* v
" p3 P  d' W. c& B6 a
       // Get low BYTE for 2nd character( p; d9 j5 b/ Q4 x8 ~$ y) P
       szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);" Y$ w4 c6 h% W8 o
       nPosition++;
7 ~: }5 f3 r9 b( n9 H$ S; F( b- ^( F! h    }
/ J8 i& E, F  p+ M
) _( |3 A6 I$ s$ m    // End the string7 l& S: z- k1 g" O
   szResBuf[nPosition] = '\0';
& t4 }1 g0 Q+ T1 s1 t/ o1 u9 b0 F, q2 q& b2 w5 e5 f% p
   // Cut off the trailing blanks
6 J7 ^# N& H6 g+ I" h, H    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
9 a  z, ^+ ^! x4 g. c+ A% x        szResBuf[nIndex] = '\0';
3 Z4 M, X% @* b, c& l; F
2 V) Y/ _( b+ D% I% U' z* M" b: N7 F    return szResBuf;
, o9 S8 T9 a* o}
1 F. w& n( M- O7 v, r//---------------------------------------------------------------------------- r% h& ^7 x5 f& _0 m) Y( ]9 E
// Winndows NT4/2000/XP 代码
- R5 ?) L% \5 h! ?0 i  _//---------------------------------------------------------------------------
$ V% J( {, G! M$ Q- F7 A+ y// ReadPhysicalDriveOnNT7 @2 c8 A' r& o1 ^* W: x( H
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
/ @  @6 c3 V$ K) X+ b{. n4 i% I5 O; b4 a" M  Y
   // 输出参数0 g9 m: {" p8 \% X7 z0 |
   BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
2 ^8 q2 C/ F2 |) q
5 T9 q3 L3 j% h    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)* S" t- R5 C& t; K! i7 {" y  z6 g
   {1 `: v6 E% m3 c' D
       HANDLE hPhysicalDriveIOCTL;
, e3 H. R+ o2 a' B  c- F8 b5 J7 v: C        char szDriveName[32];2 R% L6 ]3 x! h
% \. B; p# x7 T% b5 T" L: R
       sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
6 g, r! B" }! t" I' c        hPhysicalDriveIOCTL = CreateFile(szDriveName,
- q9 w* \  p9 j$ ?( ~/ I3 s) @, R4 r                        GENERIC_READ | GENERIC_WRITE,
& R* E) u: O3 M7 p6 p% u                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,/ y3 }: L1 {9 B; j2 Z+ S
                       OPEN_EXISTING, 0, NULL);- s7 C5 R" G& x

8 a9 Y; a; k9 I# Z8 h, D        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
9 k8 o$ y/ B/ W9 P/ I        {
2 c! B  h0 R5 p            DWORD dwBytesReturned = 0;
5 t: ]& q6 `8 s; w$ A1 ~- w            GETVERSIONOUTPARAMS gvopVersionParams;
6 {% q0 g( R( u' S& `5 @3 T: t& X! V
% B( o. W- A5 l# A( z4 Z  t            // Get the version, etc of PhysicalDrive IOCTL
% f8 G( A$ a3 Q! [6 R) G            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));4 c0 j' x3 q9 r! u$ h7 H0 H

2 H4 W0 Y; c4 B; n% {; B* i" K3 s            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,2 }( O4 n& s/ R6 {: s
                   NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),6 x* _' J7 ^0 o" ]# D& s5 E5 t
                   &dwBytesReturned, NULL))# \$ Q$ Q' F' U& w& X
           {
3 |# [; H- y; ^3 G" A+ h                continue;
% `) f- O7 {* J6 q2 U! `            }
/ N. ]2 o% U0 F" `- O$ r0 j: q- L
           if(gvopVersionParams.bIDEDeviceMap > 0)  l8 A/ S/ _5 Z9 P. J6 t
           {
2 Z4 r; h5 J& x2 I9 d* w                // IDE or ATAPI IDENTIFY cmd8 M) R6 V1 C/ c$ H; k
               BYTE btIDCmd = 0;6 f4 p, F3 o$ {9 ?
               SENDCMDINPARAMS InParams;$ I9 ~( }! T* p( Q0 J: L
               // Now, get the ID sector for all IDE devices in the system.
* K  r- ?9 Y7 Y                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,$ S+ @) Y$ Q4 F& n7 r0 K
               // otherwise use the IDE_ATA_IDENTIFY command0 R2 C' J! b! K, \8 B
               // 具体所得结果请参考头文件中的说明
' l+ q0 R8 V$ H2 w& d: g9 k$ ]$ U                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?) {; L" z1 \; n* V
                       IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;8 ?4 h. m$ K1 L& `  A
               ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));& D/ n& q/ c1 z7 _8 M- S* Q7 S( c
               ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));, ], _& |7 ~4 f4 }( G/ d

% B" ~7 {7 h* F; P                if(DoIdentify(hPhysicalDriveIOCTL,
8 t! h, [: H" c5 H                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,4 _7 O7 {- C* Z" u" j, g
                    (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
( H, q- N6 U& U7 U                {
" \$ `" r' E/ e. Q                    DWORD dwDiskData[256];
$ x0 Z/ e- P1 C& a3 I                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件, V  e3 H9 r( J" g. {/ e
                   char szSerialNumber[21];
. {5 r1 t4 Y9 B6 s                    char szModelNumber[41];
$ R/ [, ^& H' R6 {$ }) O: f; c' |( m- N: Y
                   pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;# E+ d  a1 M/ X9 `9 \
                   for(int i=0; i < 256; i++)
1 f4 V3 ~/ t( U1 G% z: e1 D' M                        dwDiskData = pIDSector;8 {* K# q: |, e, }( W
                   // 取系列号5 a8 Q* O6 ^3 \- p- k
                   ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
& T4 x4 _, \1 c) u; `2 _                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
8 j2 x$ x) ]8 y$ e# {
6 g7 V- v* h: [                    // 取模型号. G! `: y3 o) S: D
                   ZeroMemory(szModelNumber, sizeof(szModelNumber));
! {5 _, _0 {7 y% d0 s! @" Q                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
' ]5 \2 o5 n5 v: s; |- y( F' P
. T; H4 ^7 W, ?- D                    pSerList->Add(szSerialNumber);
3 }$ L0 s+ V7 j% P" Z0 }                    pModeList->Add(szModelNumber);
% O/ X0 `, z' h0 l3 [. `) ]: k, z                }! ?) W! I7 B: n) O
           }$ N" e; p; h: [9 [
           CloseHandle (hPhysicalDriveIOCTL);
: o9 V3 o5 _# [2 g, b9 [/ A        }
4 |, G1 N9 U! l    }
. V4 c0 E4 i/ @9 ^1 w  r% K" S}  F4 T- l  b; L+ ^0 a' \: m5 R6 ^6 P
//---------------------------------------------------------------------------
! g2 n7 [9 e3 Q0 G) D// DoIdentify+ ^7 C* z. }, q4 ^) P
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
5 s! Z, |4 y  v8 s" C              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,6 U$ U, _3 ]% p" t$ G2 {- H
             PDWORD pdwBytesReturned)3 T4 ~- M4 j8 q7 W# i& L- w8 {' A
{
8 {- P3 s8 v7 {+ L    // Set up data structures for IDENTIFY command.9 Y8 K& b" Y4 L% y/ B" M
   pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;4 N$ \1 ~* s  n" h" |: s
   pSCIP->irDriveRegs.bFeaturesReg = 0;
% j$ j4 Q; J$ g; [7 T7 q" N' ?    pSCIP->irDriveRegs.bSectorCountReg  = 1;
9 E: J5 j$ [) Y' d) e1 q7 B    pSCIP->irDriveRegs.bSectorNumberReg = 1;# J6 v* D. i& _& s; i. w1 Z* @
   pSCIP->irDriveRegs.bCylLowReg  = 0;
% f' G) ~+ Z3 e  H( l    pSCIP->irDriveRegs.bCylHighReg = 0;5 c6 K3 S6 O  E
' g& F. t$ u; N9 U; K8 h7 V
   // Compute the drive number.(主盘和从盘所对应的值是不一样的)' h/ ?7 Q( r0 ^+ F3 l+ s
   pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;7 r( ^! t  e# M2 ]5 C1 N6 W

3 j( P2 p/ \1 n0 x' _2 j) n    // The command can either be IDE identify or ATAPI identify.
8 E$ B' B" h" u, n! N: M    pSCIP->irDriveRegs.bCommandReg = btIDCmd;
) b5 E  i: K' a1 Y) H$ H    pSCIP->bDriveNumber = btDriveNum;: o5 {' Q  W8 K6 w
   pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
, I- C* [, ^! z8 ?" b) V! l8 Q  N* n6 m9 F0 j
   return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,; H$ d; }3 V4 B: m3 I
          (LPVOID)pSCIP,$ y; Z- R. q; k+ V& N
          sizeof(SENDCMDINPARAMS) - 1,* ?& r* K7 j7 L
          (LPVOID)pSCOP,
; [6 a. d$ e) s: [" ?3 I* d' [           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
0 s4 _* Q* u. F/ N" z: E. s           pdwBytesReturned, NULL);
; J8 f! c: U; W; `7 M: h* \}# ~& B- E: K: b  E7 k
//---------------------------------------------------------------------------" N3 u% g# w2 O$ V6 o1 N" S
// Windows 95/98/ME 代码
3 }9 @$ |: J8 x/ J5 ?//---------------------------------------------------------------------------! `/ M) k& ]' U7 B$ @
// ReadPhysicalDriveOnW9X
! j+ f0 Z- b$ [void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)
( K- W9 {9 u) k{
. M& W) m5 }9 }4 ~    WORD wOutData[256];7 l# k4 r2 D! F' b5 v0 X( Z" H! I
   SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);; X& Y, J4 D/ D$ [  W' @7 ~# [

- i1 y2 u; g5 C# S6 E1 ^+ ]5 E    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。+ u) _) Q2 n1 r2 N- C
   // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以6 M: L" u3 ~: _2 C+ w5 x
   // 避免蓝屏的出现。(期待高人能指出原因)9 t7 S1 h- N& y) B" W
   for(int nDrive = 0; nDrive < 8; nDrive++)
+ Q( {2 w6 ^: A* T    {+ a* l- Z& X. h5 W
       WORD dwBaseAddress;
( H+ c3 `9 _+ c, a        BYTE btMasterSlave;         // Master Or Slave
+ ?, E0 B  \% `        bool bIsIDEExist;0 j& s1 j( c/ g* m
       bool IsDiskExist;
8 w( C! M7 H# [$ x
1 K0 f" @" u1 D& o4 f        switch(nDrive / 2)
0 a9 U& C4 c6 r/ g8 E; J        {
+ m: a+ `. ~) ]* m% z  O            case 0: dwBaseAddress = 0x01F0; break;
: h! l6 Y  H. l$ \7 r/ y: ~" o6 C5 b. @            case 1: dwBaseAddress = 0x0170; break;) ?3 V- t! [- A, }9 M( O" g* h
           case 2: dwBaseAddress = 0x01E8; break;6 {  c0 X3 ]: D
           case 3: dwBaseAddress = 0x0168; break;
% D$ x8 W- M, w2 h  h        }( n9 `, Q+ z: }0 g
" @% q" j4 w) o' b/ a- C
       btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
: h' Q/ u& p& G2 W, H, x* ]' }9 A3 u. b
       // 进入Ring0
  u2 Q# S0 Q1 ]8 ^, y, V0 K        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,+ {# x+ S, k; l3 F1 P6 X3 I
               bIsIDEExist, IsDiskExist, wOutData);
% m: z  r" _9 j: T& ^( H    }
$ c3 w8 T4 _# ]% r3 u3 z/ V9 v) N0 r% j+ O4 p
   // 开始读取1 J, y; Z( }8 a+ r/ g- v4 J! P
   for(int nDrive = 0; nDrive < 8; nDrive++)
: [# n2 k4 b& \3 \: c$ X    {2 E/ P5 Y' v. ~' y& P
       WORD dwBaseAddress;: y& J/ s" Y6 ^: p
       BYTE btMasterSlave;         // Master Or Slave" g+ l! N! m( {( s# C# _
       bool bIsIDEExist;
, y" o  @2 i5 `) h        bool bIsDiskExist;2 f9 @& M6 y/ X$ }& J0 v6 }
       switch(nDrive / 2)
) N, k9 G( E6 Z        {
+ ?1 d+ }6 a  {8 w- G$ O3 T  _6 t            case 0: dwBaseAddress = 0x01F0; break;
# ]% t- [  X# c. |$ H, a0 d/ X6 M            case 1: dwBaseAddress = 0x0170; break;
7 Y- q) y. i* G, d8 r* b            case 2: dwBaseAddress = 0x01E8; break;* J7 R( {+ ?) ]3 V% a- O. Q+ |; R
           case 3: dwBaseAddress = 0x0168; break;
9 G2 E4 X- e/ D& C        }8 S: F8 N! n8 f9 r( j  z  b9 W
2 W* Q8 Q6 E1 f% y) i6 t# y, B
       btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);0 Q1 T( L7 K4 e" t
- m8 L! k# l- M  Y6 r
       // 进入Ring0
- W9 t8 I+ `+ I5 G3 I, ?        bIsIDEExist  = false;0 ]. a" S" f- M; I" h" K' r, e
       bIsDiskExist = false;& \( A& d! n4 g) T0 T+ _8 a
       ZeroMemory(wOutData, sizeof(wOutData));  I0 a1 N2 \5 m; x

7 I3 B* \; ]2 ^6 \        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,2 j& {9 `* |: l' t: B
               bIsIDEExist, bIsDiskExist, wOutData);, ]1 p# Q) F' z# b& t4 |( y# [" o
+ q7 Z. t5 i& Z
       if(bIsIDEExist && bIsDiskExist)
4 z% U/ T# X: A$ n. e        {
5 `; Q7 ~7 J$ ~( ~5 `1 g            DWORD dwDiskData[256];
. ?" W6 m, Y6 ?0 Y. V( u            char  szSerialNumber[21];3 V% c1 q* g9 ?" ?8 V4 i7 ~4 L
           char  szModelNumber[41];
! z$ c% ^0 i. T5 P/ b2 D, T0 |
: L1 \8 ^1 T/ [; y# ]: n# B            for(int k=0; k < 256; k++)& D2 w% \- e" G. @$ M; g3 S" Y
               dwDiskData[k] = wOutData[k];  e1 k+ G+ T9 l' _  B6 e1 R
$ H/ e1 d/ Z) e
           // 取系列号
  R% _1 \# G5 G. k' m1 `            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));5 x0 T0 @1 W  A4 _! P) _
           strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));8 v6 O% e* }& U+ C9 b

, G- y# R+ A3 p1 ^& d9 i            // 取模型号
( P( c; Q9 B* e8 \$ @            ZeroMemory(szModelNumber, sizeof(szModelNumber));
: k2 M/ ^" ?/ i6 o( J+ ]8 S! m            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));6 r" a; v  x% n% p# q

$ w( p# r1 w) H/ O- Y            pSerList->Add(szSerialNumber);: ~, D: G' P$ Y% s
           pModeList->Add(szModelNumber);
) q/ g. \, X* H% }' f$ z0 t        }6 m  ?* K; ^6 t) ~
   }
/ ~5 u7 K! u/ G) v    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);, G8 T1 J; a4 _) s: f
}
: \7 R# Y4 k& O# s- Y& l//---------------------------------------------------------------------------6 |0 }/ h) S9 L" i
// ReadPhysicalDriveOnW9X_Ring0()
- v( e$ Q) ?2 r: D//$ l, d' n5 t  l; y6 [
// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h4 G- A( u( Q' }/ U) X- R
// btMasterSlave = Master(0xA0) Or Slave(0xB0)' ~; e; `# {& R; @. |
//---------------------------------------------------------------------------
: S# L+ _' [/ r: {void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
+ O; p; j' C2 f3 h- p2 I3 f        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)3 D9 l& m) F$ {4 |( o% I7 \
{
4 L. K" u5 m! a  f    BYTE  btIDTR1[6];+ N) r! F1 Z# r, T3 P
   DWORD dwOldExceptionHook;
. w$ v& x1 H, A5 K# [    const int nHookExceptionNo = 5;
6 g+ |/ z  B# f9 H9 M& R" s& k
  |  |1 f7 p! B# h# d    BYTE  btIsIDEExist = 0;
% b8 t+ K  t& b- Z* f    BYTE  btIsDiskExist = 0;
, |2 V% E+ f9 A! Y: D; T    WORD  wOutDataBuf[256];
" h; c# V; W: L) {' _( e$ w9 H2 ?7 _' \  M2 S3 {" M
   BYTE  btIsFirst = (BYTE)bIsFirst;
5 x; X' Q. s2 D) a: G! a+ b. }0 J2 _9 R
3 w7 f4 `) R$ e    const BYTE btBit00 = 0x01;
) t: Y2 y" V+ c5 x" Y7 i' y/ ?- J) m    // const BYTE btBit02 = 0x04;3 k5 Y' y* Q6 d- Y" P! h
   const BYTE btBit06 = 0x40;
4 J# o0 I$ P+ ^7 w$ Q    const BYTE btBit07 = 0x80;- j, L9 G: I! w% _
   // const BYTE btERR  = btBit00;
( c% ~+ l" t4 U3 |' M  u    const BYTE btBusy = btBit07;
6 V$ }( O* R& i; }% |    const BYTE btAtaCmd   = 0xEC;) S1 ~' |& ?1 v4 J2 F
   const BYTE btAtapiCmd = 0xA1;/ O! m. J6 Y0 Y5 `
. g6 u$ |/ l; P% D
   __asm* [8 i( `" `1 ^3 |0 I
   {
* L7 e. [4 c) _; N& u' q        // 必须先执行这条语句
0 N: y1 s& N% b        JMP EnterRing0
1 ?1 \, I0 y$ X5 {" C
3 u  u$ j0 }$ }9 m% ^2 M* ~' {4 _3 t) T( w        // 定义过程& i. P2 ]5 H- q  K; k/ X9 p
       // 等待IDE设备直到其不为忙为止
0 F$ j; ?. ~7 k- `: t        WaitWhileBusy proc
! _6 r* A$ @- w0 L1 ~& G5 c, p' R8 j$ a1 x, ?2 }5 w- T5 `- g
       MOV  EBX, 100000
* C6 p* s+ H7 ?& N: q; E        MOV  DX, dwBaseAddress: N7 o, {1 |6 ]4 C; @
       ADD  DX, 74 e! V2 F$ B  S! Q; v
  {9 |; U. P% W  d) O3 R: J
       LoopWhileBusy:
6 T- g3 V6 k# q0 S
! s) q" U( J& R% B        DEC  EBX
5 M6 D) m+ x$ j1 X  x5 G        CMP  EBX, 0, V* S+ z$ `! _6 @+ G4 R
       JZ   Timeout5 ^2 H6 l" \: i( ~8 }, y6 \
       in   AL, DX- [. ]2 F: W1 I7 S
       TEST AL, btBusy8 Z: \7 I% s3 M, z
       JNZ  LoopWhileBusy
. j8 M5 t# ~* S1 U' y        JMP  DriveReady
& O7 \. {' i  v- f
# ^: ]. R1 s- B% q* x. C6 w        // 超时,直接退出8 ~1 j" H: k( i. z, [- j
       Timeout:
3 L* ~, T5 x6 b% f5 Y; P, Y- v        JMP  LeaveRing0
7 c' C) B4 i% J        DriveReady:3 s% n% L2 R! X. c5 \" _! v
       RET8 a3 s1 R  s& [) A, J& U0 Q! \
       ENDP   // End of WaitWhileBusy Procedure
& l6 ^; c- V' i2 W9 r* D7 Q/ o) C0 E1 g: G" |
       // 设置主盘和从盘标志! _* C/ v: f. {) \( j! H8 C
       SelectDevice proc
3 _: a; t$ ]) J9 J  d& C" P1 a+ B) D8 c2 m: e$ P
       MOV  DX, dwBaseAddress" U& T  Z- L! ?8 J" x
       ADD  DX, 6
6 @+ D/ ?5 `6 R; f7 Q" A  W        MOV  AL, btMasterSlave
8 B6 r% o4 j; b; n3 b5 j/ i( x+ I3 t. B% ]/ ~
       out  DX, AL: s; z/ Z$ A9 L6 I3 f; ?
       RET
0 f; m; r  d' B# J+ ~8 C' X1 \1 I& E" ~0 t7 J
       ENDP  // End of SelectDevice Procedure
5 K7 E) X+ H  M6 g9 w: N
+ Y$ {* ~& X9 n" U, b& \; H1 }        // 向IDE设备发送存取指令
- @8 T: v% c( u* t" S8 ]$ S# c        SendCmd proc
2 M- U1 x4 t6 o: o( ]6 u. ~# ]- Y6 D  l8 a5 c# m
       MOV DX, dwBaseAddress$ P: V) G/ l3 _# r& W7 g7 R
       ADD DX, 7
8 Y5 @4 C8 Y; Q% h! v9 M; c% b        MOV AL, BL // BL是主从盘标识,在过程外设置
' [: E2 L* U7 b        out DX, AL2 t, L+ b( A8 c5 a/ h0 w7 V
       RET
7 S4 g8 S) F" I7 K! g        ENDP  // End of SendCmd Procedure
. m& R* B: m5 a2 @
9 G2 p5 D# c" ]: `        // Ring0代码5 |, J8 A8 g) K% ~+ P- _" u) c
       Ring0Proc:
8 e1 b2 d, h9 q# g        PUSHAD/ J% h' Z0 }( C1 h# A4 }
       // 查询IDE设备是否存在
' b5 B' s# ~5 i3 X& L6 `        MOV DX, dwBaseAddress
/ y7 ]( r7 Z3 T: H7 e        ADD DX, 7  K( ^1 F; G& s+ F
       in  AL,DX. p: D3 l0 U" y+ C3 O# M. R

4 P( h7 w, w: f6 {* y- ?        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回  G# y( W0 M) ]. i$ U
       CMP AL,0xFF9 K& _6 l) z9 a5 P' H
       JZ  LeaveRing0$ A+ z8 i& i9 g; u: O0 ^
       CMP AL, 0x7F
7 O9 \$ N) C+ M  P9 S4 L        JZ  LeaveRing08 i" y- l. H' s( q5 f
. c- ^0 K. f- ^% Z
       // 设置IDE设备存在标志
. _  X+ c1 w( j4 q% \/ _. [" B: c        MOV btIsIDEExist, 1& K% Z1 P$ ]% B+ u9 {, ]

) W  }: S' |; D5 D9 I! E- Y        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
7 l$ @5 g# D- E8 g6 N7 x        CALL WaitWhileBusy
) E3 [! r4 ^* p5 a        CALL SelectDevice
  [) C, }; ?0 D% {! S- y1 ^
( H" t) b! U6 i        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
5 a  y- k6 m5 o. K, m        CMP  btIsFirst, 1
( z$ [& u; q) |- h7 a5 i: O/ U  f        JZ   LeaveRing0
. F6 C9 P" G8 A$ Q, T+ ^/ o* S' S; P( s( {
       // 第一次调用时,如果执行这行语句会导致蓝屏,Why???2 [* ?, ^% S7 e2 {5 W
       CALL WaitWhileBusy) E3 \# F) t1 K  V' c% z

) k5 ~+ X0 ^8 K0 w$ r. g0 T        // AL的值等于cBit06时,不存在驱动器,直接返回& Y- Q( R+ k3 q* I' g
       TEST AL, btBit062 h& \' ~% R  Q7 `) {* o* m
       JZ   LeaveRing0
1 N2 W$ n% b. N' L9 Y% H2 @9 f7 Q/ A; n8 T$ }
       // 设置驱动器存在标志' B0 e0 m3 _; ?1 b# R
       MOV  btIsDiskExist, 1/ n4 j1 s) y! ?2 |, ?) ^6 s
! n) ~' y, g3 G
       // 发送存取端口命令
, b, S/ G5 E  L$ j; h0 V. }        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,8 Z+ p, A& p& }( [: L9 j
       // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
' _+ d) w) h! d( L# _; P& e: _; c        CALL WaitWhileBusy- ]! T! D5 _; k- P1 P
       CALL SelectDevice    // 设置主从盘标识6 ]2 Z! H, \) s9 P+ Y% u% y9 u
       MOV  BL, btAtaCmd      // 发送读取命令
# H% k* g& {! }4 O' e2 @        CALL SendCmd6 a+ c& S8 u0 _4 O. k; }* L
       CALL WaitWhileBusy- H; h& r7 U' \/ @9 z& a
* y9 I4 X, u. {, g- {
       // 检查是否出错6 @1 n* a4 E8 n$ R- Q2 P
       MOV  DX, dwBaseAddress
& }& C$ L2 H: Y; J4 D7 u. x" Z7 p        ADD  DX, 7: N$ @# r4 E: T& x& k& L1 t8 f$ L
- ~- F8 c2 x- w* G9 V
       in   AL, DX
( k' E+ M! I- r5 |+ ^$ `5 t+ O- V% F  T7 ]- t; Y
       TEST AL, btBit00
: n9 _- R6 l5 S( J3 h' {/ I0 |        JZ   RetrieveInfo   // 没有错误时则读数据
+ F. A1 f) x+ t4 p% T6 @
/ d, ?" ?' I7 y" k( F- O        // 如果出错,则进一步尝试使用ATAPI设备命令. y* s- @( O8 j9 {
       CALL WaitWhileBusy
) o6 Z6 Y0 H3 b0 J* v& w% b9 h: B        CALL SelectDevice  D5 U4 Q- @; _4 {* _0 _
       MOV  BL, btAtapiCmd
, ?+ v$ }  U, o9 {& O! \' t        CALL SendCmd8 h1 z! l" d1 ^; l. ?0 h" Y
       CALL WaitWhileBusy
7 D3 A9 j0 \( ]) F/ Z4 m' Q" w% ^+ P3 G& m/ _
       // 检查是否还出错6 L0 e: x% I  {2 T) I3 u9 W
       MOV  DX, dwBaseAddress
5 s' K2 e4 n6 X$ q2 ]( F        ADD  DX, 7
+ v( ^6 v! D3 T1 _        in   AL, DX" S/ e" P' Y+ w! v8 j  n
       TEST AL, btBit00
+ g7 I8 ^' {# {1 I# D6 f& p& r        JZ   RetrieveInfo   // 没有错误时则读数据
' [# |' F! v# q6 w- x& I# ^% P/ ~  J        JMP  LeaveRing0     // 如果还是出错,直接返回- L; K, b  P" W9 k" L2 ]' X: {) |
) Z8 K( j9 A4 z' N
       // 读取数据
, @$ {  B" S' ?1 ~, F        RetrieveInfo:( ^# I; e# P1 ]3 D# r* Z$ }
0 i4 g% E/ P6 A4 S) m2 w
       LEA  EDI, wOutDataBuf& _0 Z6 m* y# d& J3 s4 j
       MOV  ECX, 256& x2 k5 \) I" v
       MOV  DX, dwBaseAddress$ w1 X4 d; F6 S/ u* F3 b# m: _
       CLD
# _0 j* Y2 c; B. w9 @/ F6 L2 m+ H* I( E; J% h/ m5 Z9 v# {5 Y* W& j
       REP  INSW/ Q( ?. n% }" M! Y' V

$ N; A* e' S' X, W        // 退出Ring0代码& T! l; R" `' b) ^" n
       LeaveRing0:1 e1 _; `: ]  X& `* W3 j) X. [

) J3 v* _4 Z7 ~7 h        POPAD
# k' C4 B+ J3 \7 g- U8 u$ k  e        IRETD+ ]5 O/ [( _4 H% [7 S! C

6 M* H; B# e  I: C7 m  q        // 激活Ring0代码( A9 B* T6 v+ H1 [" ^/ l
       EnterRing0:
2 z1 ], q& ~! W( N8 N+ G
8 e! _% S' f9 ~+ _' A2 g/ _        // 修改中断门
' E/ \7 i9 ?) W        SIDT FWORD PTR btIDTR13 F, Z$ y. P# `* g( U* L0 B) c" J- F
       MOV EAX, DWORD PTR btIDTR1 + 02h
& u$ q+ w% h) i7 n# P# _' S* E        ADD EAX, nHookExceptionNo * 08h + 04h0 s% g$ X$ O  [( K* a
       CLI
+ n7 d) M4 P5 h) `- y4 C( s6 M
8 L4 q2 I8 a0 J( N$ N        // 保存原异常处理例程入口
8 h$ F3 X3 g4 ?' {) R        MOV ECX, DWORD PTR [EAX]
  ^4 e# l# F6 k/ U        MOV CX, WORD PTR [EAX-04h]
" X9 ~/ K4 d9 `3 Y        MOV dwOldExceptionHook, ECX- V: d8 u  ^# e+ D4 V2 I

! L$ t8 ^( B( ~) P. w5 F7 ]        // 指定新入口6 e4 E* ^& z8 \/ s
       LEA EBX, Ring0Proc
& a0 j) c4 |& e0 t4 p# `        MOV WORD PTR [EAX-04h],BX8 k" O& C4 z% O6 [# C' G
       SHR EBX, 10h3 `7 D7 N+ ]' }% O2 Z5 s' I4 ]& P$ f
       MOV WORD PTR[EAX+02h], BX
8 P  J; `1 `- g; A$ j- ^1 r" B+ ?; Q* V7 v+ [; S" R& _& d
       // 激活Ring0代码
9 A6 c3 @  A; `% i        INT nHookExceptionNo  s( K0 {0 P. d3 Y) h2 s
6 r% S1 x9 P3 Y9 s1 z
       // 复原入口
! r1 v$ w+ V3 e: u. K0 V        MOV ECX,dwOldExceptionHook3 `! l7 m) U& N* |) s: L  |; B8 O
       MOV WORD PTR[EAX-04h], CX- G3 g  Z/ {$ e4 }5 Y
       SHR ECX,10h. `" V3 j' P* C& ~6 L
       MOV WORD PTR[EAX+02h], CX! r, N- u0 M. I6 j3 E' V" q
       STI8 O4 `- x0 X+ `: |* k* W- w2 Q
   }; i) y4 w3 S$ c* x. h7 l5 V
   if(!bIsFirst)
$ Z$ {9 x3 _0 ]    {
2 Q0 I& A8 u( I6 r' o        bIsIDEExist  = (bool)btIsIDEExist;. s' u) }- k# l! d
       bIsDiskExist = (bool)btIsDiskExist;
! v( t- [( R) ?) e        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));3 ~5 z! W6 D+ t
   }
7 Y8 {# N6 K  F: V1 V. E9 j$ h}+ U$ p. O0 z0 k3 T+ F; }5 b# T1 g
//---------------------------------------------------------------------------
% @" B# r% D, @// 调用方法:
* m/ p) a9 {8 b8 |/ ~+ Z1 u) q" bvoid __fastcall TForm1::Button1Click(TObject *Sender)
2 s5 b( r' r6 u{
$ c& v9 W2 ?$ H6 s1 }* q- K    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);% n9 L; m, w' M! G
}
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

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

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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