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

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

[复制链接]
发表于 2005-5-30 19:22:36 | 显示全部楼层 |阅读模式
  #include <WinIOCtl.h>
% k& d: C8 P- X! N! k#include <stdio.h>
+ A4 C0 {) L: }. K
6 o# f  \/ S1 N! @, o3 C#pragma inline4 l6 ?: R1 |' U! q$ o8 M
//---------------------------------------------------------------------------3 u  T1 h% [2 A1 @, V! f
// IDE NT/2000/XP专用变量
* `% `9 }8 L. H( J1 `" \#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS, D% ]: O/ h+ p8 |1 F
#define DFP_GET_VERSION         SMART_GET_VERSION6 L9 i) a% m! U7 _/ ?6 q
#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND4 t3 Y4 Z2 d7 p) I: {$ m
#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
2 z5 q9 j( U6 g" {# A* ]) ]: `: b8 |/ S+ Q% d5 {0 @8 m$ {% I
const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令
/ @7 o6 q& s7 [const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令8 ?; b) u6 {) W7 I# I5 ]" g/ i" h

# ]( q% j+ k! W* s! p8 fconst int MAX_IDE_DRIVES = 4;
, b3 Z8 K- l% i
2 V1 j: y( B( {. }% q8 M: O2 E- Z! n// SCSI专用变量  P# U7 j4 I5 s. K3 m& ?0 q
const DWORD FILE_DEVICE_SCSI             = 0x0000001B;
- G8 M6 g% B' T+ j( a4 R+ i) lconst DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
) z9 x% V& o: Y) y, }const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
+ u8 s8 a7 `' W4 x6 z. G$ A7 a( {const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
7 ^" q0 \, K  U& P
, s+ f4 F; T- H; q3 c4 m( g  Z6 ctypedef struct _SRB_IO_CONTROL
4 e9 S# }' c3 v0 T' O' ^7 Y+ t{- P( B* O$ z1 y. u0 O3 P% Y% ~
   ULONG HeaderLength;
/ y' j2 S# k) ?7 H1 C8 A: i    UCHAR Signature[8];
7 n8 b+ A, ~1 A* F  h6 C; G4 x    ULONG Timeout;. A2 q' P2 O8 c2 `
   ULONG ControlCode;' o( R5 y" Z$ j
   ULONG ReturnCode;& C5 A  J) a7 N4 M+ n1 @3 c
   ULONG Length;
6 i8 {4 b! a# y. a! F3 i+ G}SRB_IO_CONTROL, *PSRB_IO_CONTROL;
/ O! @; i1 n" G6 w8 M  Q- k) l# X! i5 e$ R
// 读取的主函数: E. u. {% W0 p. W1 F3 D& ~  t5 j
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);; g: l% H* N; K9 t
- t' i: X. v) l
// 辅助函数
% P$ j2 F2 K$ `) H' i, i: Ochar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
' Z. e, J. m+ d$ ^% \// NT/2000/XP函数/ {3 U. |2 |! _$ o9 S" @2 l* Q
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
' R2 N; d# ^. l6 E& d  Abool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,. ^2 c# e" E6 Y: s* L) B
       PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,' U2 |% N$ o# G. {/ t6 D; H
       BYTE btDriveNum, PDWORD lpcbBYTEsReturned);* W1 L; u5 n2 D* B- s
// Windows 9X函数4 j1 m8 \; c; W1 _& \7 X  W$ q
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);5 p; d$ d0 `' M: t" p2 s
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
) o; C% f1 G  T) x        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);& T5 V# S8 q1 K7 P1 L4 v

1 V7 N' W" V: [2 f2 s// SCSI读取函数(for NT/2000/XP)
2 e8 j- i+ l- j4 F" q- @String __fastcall ReadIDEDriveAsScsiDriveOnNT();
4 @: R* V+ o3 `4 v, S//---------------------------------------------------------------------------6 H( Y+ U: q% V3 q5 O% f( w8 ^
// ReadPhysicalDrive
' R( R; E- B) a! L  Xvoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)/ B% k* B; ~* n
{
+ C# d& C2 b8 c: F    switch(Win32Platform)0 j7 d/ A* \, E1 X7 S2 i. c6 C
   {% P3 k5 I3 v' y
       case VER_PLATFORM_WIN32_WINDOWS:5 Y  x5 Y! t0 p5 L  y6 J! a! a4 L! u' O
           ReadPhysicalDriveOnW9X(pSerList, pModeList);( W2 b9 `9 h( \* X1 r% f8 I
           break;
0 T# P5 B- u% I( g' N1 f5 w        case VER_PLATFORM_WIN32_NT:' H! C. J/ o$ ^- m
           ReadPhysicalDriveOnNT(pSerList, pModeList);
7 ~1 v; w. c, }, x            break;( d( d7 u0 y6 Y4 @5 L$ Z1 X+ D
       default:
6 e/ j1 F: L" ]  e( e$ p7 h" i7 v            break;
: _! K4 D& r9 P5 \6 H6 v; Y# k, T6 y+ j    }0 D0 e6 o' G2 i$ W; [
}5 \& z/ ]5 \1 U  J: l! z. G
//---------------------------------------------------------------------------7 g; W/ x* B0 W- M5 Y% C6 O
// ConvertToString
5 M( t6 T* Z4 |3 k% P. j; Lchar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
% y+ \% S8 x! H" w9 S1 V{0 ^5 a% y; |& s: C' ]& r" [
   static char szResBuf[1024];
5 F+ o3 r8 ~+ P7 ]    int nIndex = 0;
7 I9 K' k6 H) d& {# C    int nPosition = 0;2 m- w( [% Z8 H
4 E# r3 t+ X0 M1 b" w6 ]$ p
   // Each integer has two characters stored in it backwards
* t% C: l' l& q# [" C9 }    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
# B) @. G) n' n+ O% M+ e    {
2 @( r7 F! o/ y7 D/ c+ C4 N" |        // Get high BYTE for 1st character
+ b7 j1 [" e8 E, p' L: A        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
% U1 i4 |! u4 _, g7 I        nPosition++;
, w* b" S# C9 e8 T- g' q- ^- L
' e4 a1 T/ `% B8 n5 k4 b7 a        // Get low BYTE for 2nd character: X; ^3 G9 g$ S9 y( \/ X6 G
       szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
/ b# o& |" y' P7 `        nPosition++;
; L7 G( F) n% S+ [; E    }! x0 v# Y( k: U2 l( _

# a2 e: r% M3 q: V    // End the string
& B* W  a0 v( ?" z+ n    szResBuf[nPosition] = '\0';
  ]/ p/ a/ M# v' c0 I6 I3 o  T( I
: h3 J8 F9 m2 Q    // Cut off the trailing blanks
# k* F( `+ q$ u: l    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)7 a; D. O7 h( Z( b$ j7 D2 O
       szResBuf[nIndex] = '\0';6 f1 }% S6 a% n( A$ T4 l' b' r. E8 h
% k6 F! ?. R- T1 y. G
   return szResBuf;
$ N8 a3 `$ ^% w, n6 i}" ^5 k! C) r5 k0 j2 F8 P
//---------------------------------------------------------------------------
4 `  p8 }6 y6 W. q4 g, t6 V// Winndows NT4/2000/XP 代码
. f- }. Z- e4 Q5 {( s9 }//---------------------------------------------------------------------------
2 P5 \, M. o  W) `' s// ReadPhysicalDriveOnNT
. d# ]. e1 L' J# ]void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
' {. w& k5 N# B+ o& R0 T& `8 Z9 E{9 o) ?- @! o5 t& m( q! Z- C6 n( ?* {
   // 输出参数8 P+ g, a) K4 S7 ]. G: V$ L
   BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];# @9 s* x0 G& A- A4 k& d0 N
- S9 l) j7 l4 H: h+ A. g
   for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
5 X+ d5 l( z% _& v2 h5 u    {
6 i$ U4 U5 _# @. C        HANDLE hPhysicalDriveIOCTL;
' P7 A- H  d3 T; `& y        char szDriveName[32];  `# U  M9 m4 z5 H. D
- b  d+ H% I8 i
       sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);& k6 Q, Y9 m& K* F: r
       hPhysicalDriveIOCTL = CreateFile(szDriveName,' [5 |) w7 f1 \( B( @6 w) L! u
                       GENERIC_READ | GENERIC_WRITE,) A% u" B. A9 h! m, b$ U% c
                       FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
! @, v# H" F" r# k3 [  w# ]                        OPEN_EXISTING, 0, NULL);% z+ T0 P+ i- u2 _
, ^$ h( O7 _: k# ~# V7 V+ f9 W0 F
       if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
; W3 \$ N; r$ U4 E& Y        {
. T- I/ N6 J: W' ~. f- i" M5 q            DWORD dwBytesReturned = 0;
7 u: B# B1 T- G- s! S* r            GETVERSIONOUTPARAMS gvopVersionParams;- K3 F; c* Z( m( |7 n3 C! r  d. X

2 ?1 P+ S* I) [2 t            // Get the version, etc of PhysicalDrive IOCTL4 Q7 V, m4 K4 P1 [
           ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
" v/ I7 M3 @/ {& c; S# x2 G. z: b3 @1 i6 {  c1 C* q
           if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
/ I  F- |( Q7 x8 p/ v# }                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),6 Y! S+ O- G8 q
                   &dwBytesReturned, NULL))
, F: f! _$ O/ D7 L5 I6 K5 M8 d            {
9 A+ Q/ t( r1 p- \                continue;9 p: ?) H9 f1 O
           }
" M% `! W5 r# D$ D2 P$ q8 E5 ]
  I+ ]* r) z% O" J' Q            if(gvopVersionParams.bIDEDeviceMap > 0)
" A2 W' R' A4 J$ Q" _: ], q            {
/ C1 |: l! }) B& u                // IDE or ATAPI IDENTIFY cmd8 W: h" Y; t3 n7 w: a2 d+ \
               BYTE btIDCmd = 0;
* B# t9 b$ u  Y                SENDCMDINPARAMS InParams;) X5 }% e+ I  p. J
               // Now, get the ID sector for all IDE devices in the system.$ m( n; Z/ e3 b5 e
               // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
3 q) X2 }# }6 v7 f, O) K( u                // otherwise use the IDE_ATA_IDENTIFY command) }7 f! i1 g( [7 |
               // 具体所得结果请参考头文件中的说明
+ F% p8 O2 b# [8 }, k                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
5 V& Y. L0 L, p: o% d" c                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;( Q! [5 i: h: y1 y- T
               ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
$ M9 h* w: D( e' j+ v& C                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));( [! b3 F- H/ w( Q
2 W! v, `9 I6 r3 s
               if(DoIdentify(hPhysicalDriveIOCTL,8 X1 i+ Y& b. ^  l6 x
                    &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
: Y, u2 H, x9 }: G8 }  M                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
$ V- C$ v' b" a$ f5 r( }" b                {
  m$ u  D/ X, ?* j: j: X                    DWORD dwDiskData[256];: c; Y* F$ c; J+ o
                   USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
  b4 ?0 b. c6 T                    char szSerialNumber[21];
4 v3 c1 P0 n& Z                    char szModelNumber[41];
. ]' l: e2 t# @
% q# {2 e8 v6 B, ?. w1 A                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
$ V7 p8 U. ]" u9 P- r" t                    for(int i=0; i < 256; i++)
4 T7 o2 p9 h* a/ o                        dwDiskData = pIDSector;0 I8 F: G5 N/ V5 m  q
                   // 取系列号9 z, n+ S& R0 |5 q
                   ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
+ E1 ?, s+ T6 q% d+ f                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));% C4 R) T* G% r' ]4 y& B
& \0 o" C3 S( x7 ^$ g9 I5 i& k5 f
                   // 取模型号% e- d$ L8 E  R8 h, w
                   ZeroMemory(szModelNumber, sizeof(szModelNumber));
2 @- ]$ n* l+ q7 i                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
* A% B1 {4 q6 h" J4 C
: @% F; J$ n3 L1 A1 L                    pSerList->Add(szSerialNumber);
$ K+ I! q7 a8 K% s3 I3 X# |                    pModeList->Add(szModelNumber);
; S+ F$ ?. h+ L' E7 q: A( T                }
  X, ]& w6 w6 y6 ]( h! g* K            }
( M! I: _  u3 e2 n; M$ L            CloseHandle (hPhysicalDriveIOCTL);7 G: n, k; _  ^4 V; c; }+ H
       }
2 C3 c( S5 g7 K" ?4 d    }
. b& y+ P% |" Q3 C3 o}
, {6 a, y5 a. v2 Q7 _2 m//---------------------------------------------------------------------------
+ J' q8 a% \1 f: u// DoIdentify" Q1 t& ~6 Z% ^! x  ~5 |
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
- ^; a, Q, o; h% b! ?; C+ T              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
4 R8 e- N" t; k5 u# ]7 R              PDWORD pdwBytesReturned)
2 K1 w6 U0 h  O% `5 b* z& i4 r# V, H{. Q4 K3 @$ b9 P' ?; x3 y, O
   // Set up data structures for IDENTIFY command.1 X) H" U' l. J( d7 H1 m  R
   pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;3 d+ s' S+ n; B/ @! p. ]/ y% E
   pSCIP->irDriveRegs.bFeaturesReg = 0;
# _3 D; k4 |" Q5 H/ [, D% m    pSCIP->irDriveRegs.bSectorCountReg  = 1;
8 w$ `6 r- t* [" P7 l  @- v    pSCIP->irDriveRegs.bSectorNumberReg = 1;/ X# }) n' L0 w  G$ n  D: S6 r8 y
   pSCIP->irDriveRegs.bCylLowReg  = 0;. O% E  b3 _! W, k$ Y
   pSCIP->irDriveRegs.bCylHighReg = 0;
' U9 ^  o/ b9 W" ^& s8 ^4 }& l/ u! `. n
   // Compute the drive number.(主盘和从盘所对应的值是不一样的)& y. S) g* N5 i# F
   pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
' T% G! R2 D& t5 m; G: }1 z3 V/ _5 ]/ i( z
   // The command can either be IDE identify or ATAPI identify.
: U  r9 `& ^4 M) x9 e2 ~    pSCIP->irDriveRegs.bCommandReg = btIDCmd;- ~& r7 c8 }! i/ \3 l- i9 W
   pSCIP->bDriveNumber = btDriveNum;
* {: c- Q, H+ f. m; \5 K5 Q' ^! e    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;9 B! V: c) z! ~. c4 n7 j- B
5 u5 D4 T6 L: e* P4 T
   return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
  L- ]# a: A% E# ?           (LPVOID)pSCIP,0 |& o( b- h% L1 |) o2 }! }9 E4 W, _
          sizeof(SENDCMDINPARAMS) - 1,
3 }) V" S3 b+ K% f& B           (LPVOID)pSCOP,
% j) x% O7 d0 d+ O. t8 D           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
2 s0 p8 f* t/ Q, R' r           pdwBytesReturned, NULL);
) |- {/ [1 y4 V7 }3 p1 s}; L. |7 M1 |. h
//---------------------------------------------------------------------------. g( R8 V5 E+ |" S
// Windows 95/98/ME 代码
. D: r/ b$ A0 e* _1 n5 \1 B//---------------------------------------------------------------------------
2 b) P7 T. n. {8 M9 p- Z# y* q! K0 T// ReadPhysicalDriveOnW9X# U4 S. @6 Y& [6 q' Z! x
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)" v+ s) J( \* C, a$ K$ ?
{
" W1 S9 i; g. m! L$ Q8 c; a    WORD wOutData[256];
+ p/ b- e4 _# d) o    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
/ g/ }4 t9 g+ \
+ C- o* F8 W$ J# w. [+ s    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
+ X! M0 H! j. ^$ q! J    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
/ q* k$ F- n9 J9 j; w; f, s    // 避免蓝屏的出现。(期待高人能指出原因); G% r) e( |! S" F/ }/ N
   for(int nDrive = 0; nDrive < 8; nDrive++)
4 |4 V, k9 |; E- s# O. G, U    {% k* f& v0 M0 }% h9 o
       WORD dwBaseAddress;+ ~$ p. D! t: H1 C
       BYTE btMasterSlave;         // Master Or Slave
8 v- i& D* c( z% K% k        bool bIsIDEExist;
+ }$ s9 W7 [! o( a3 P$ c        bool IsDiskExist;
+ i' N9 \/ i0 R; y; c4 ?, O+ M* d9 d6 Q, i8 m0 _
       switch(nDrive / 2)
0 e  l  i1 D- m# G        {
, E; d+ c" m0 {4 `1 I' ]: ~0 H0 H            case 0: dwBaseAddress = 0x01F0; break;1 n$ x& B( R. E( ^
           case 1: dwBaseAddress = 0x0170; break;! `/ ~+ \: ^# Y; |, ^0 u# Z( R0 D5 B
           case 2: dwBaseAddress = 0x01E8; break;
* T0 W7 X2 i* i0 `0 l            case 3: dwBaseAddress = 0x0168; break;
5 o0 Y- I5 B1 k1 \) Q- p        }
9 y( ]- _6 X8 L" e( k) F# C
& R, q: u' ]$ G; a# t! |        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);5 Q0 V# ^* p2 o1 c; s
$ c4 I$ s; V& W
       // 进入Ring0
$ j" Y* w' }0 r: d7 E        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,) G4 O/ {/ ?) ]/ T4 ]3 L& o
               bIsIDEExist, IsDiskExist, wOutData);
/ C; a) k4 Q; v' I) E4 t    }% ~1 P. c+ |0 f

' {  [' D. C  W+ Q    // 开始读取
; M8 k) _' p2 w  R    for(int nDrive = 0; nDrive < 8; nDrive++)( R& u- }9 T5 M. j' e6 Z
   {
: n- @+ B$ ^8 \0 n        WORD dwBaseAddress;( L' r! D) U* r; Z* Q( p3 w
       BYTE btMasterSlave;         // Master Or Slave; Y3 v5 Y# r% @- @7 ]; E
       bool bIsIDEExist;
- O9 X7 ]5 z5 Y6 v& E& B. P        bool bIsDiskExist;& s: F+ Z  B0 T
       switch(nDrive / 2)
8 O8 c; m2 d7 p) M' k        {
( a3 j9 C: a8 |0 i) y& s8 ~/ A            case 0: dwBaseAddress = 0x01F0; break;
$ T. o* [: M& X3 }9 r. {            case 1: dwBaseAddress = 0x0170; break;2 O; [( D6 S) z
           case 2: dwBaseAddress = 0x01E8; break;/ [4 S5 Q9 b! r3 s0 \) B
           case 3: dwBaseAddress = 0x0168; break;
2 }' R$ A2 [! k, S8 H4 b. C/ N        }
" t  v7 b' W# W  O6 L6 E, q8 i7 J$ ^5 g4 T
       btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
2 R9 l3 ~$ H# ?) L( [7 V# E' h* {, ]* Z( y( w
       // 进入Ring0
+ X% c3 y4 b4 u$ b/ W        bIsIDEExist  = false;
1 T8 `, R% `; I6 X5 \. x        bIsDiskExist = false;
; F% b: P2 H  |; k6 y  ]! @        ZeroMemory(wOutData, sizeof(wOutData));
: g) r7 c/ M4 V. h0 k0 h; g- A
: c6 r0 {0 y& _0 V$ B  o6 Y        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
; C% V$ j& y% \( B" H                bIsIDEExist, bIsDiskExist, wOutData);6 z8 _6 V  l' H5 W- l$ W

: S, `. N; [( g% |        if(bIsIDEExist && bIsDiskExist)
5 T( s# P' |2 L1 o* a        {6 C3 x# A! A7 b% \7 B
           DWORD dwDiskData[256];
8 y7 p& L$ {  k& g! I            char  szSerialNumber[21];5 F1 L" M" e0 R! h: s
           char  szModelNumber[41];
, X3 h1 n# }' S, r  w+ v3 Z9 J' L* ~1 ~
           for(int k=0; k < 256; k++)4 `. M3 e) @1 T  w( w
               dwDiskData[k] = wOutData[k];' a) n+ G6 V4 f, q4 k$ s4 j$ e2 |/ }
- Q; `5 G- n3 r2 T( c. S7 ~
           // 取系列号6 s" Q7 I$ W' p4 |. c$ Q9 J/ o
           ZeroMemory(szSerialNumber, sizeof(szSerialNumber));2 {2 P& W, Q3 |: @6 o0 b
           strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
/ A! q' K; S3 f- f% j" \1 G
* Y4 z3 a$ n8 X7 m  G- c* o+ w' N            // 取模型号& y+ k' @9 c+ [8 p. M" _
           ZeroMemory(szModelNumber, sizeof(szModelNumber));
' P! j+ B1 U# R7 T* V# ?2 ^% d            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
' H1 X5 f0 g* N  i$ o
1 G$ l( B+ Y& t/ ]9 C/ \& r            pSerList->Add(szSerialNumber);6 t: s) v* M% x6 K7 F
           pModeList->Add(szModelNumber);
0 G7 D% {- ?6 p2 S$ m# ~# j7 N" f        }
; a3 T( }- e! |: A' c. |6 l$ m* t    }/ K! \2 Q/ U3 F! G- S& P7 Z3 V
   SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
; F5 L5 J7 J9 R4 I; w: Q}- T( c& U7 g2 {: Q. h
//---------------------------------------------------------------------------# P9 D. i& C3 v
// ReadPhysicalDriveOnW9X_Ring0()
: T5 T% _1 w1 p# D//9 }: u1 [0 l7 z& g5 B
// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h4 D- s7 ]5 `4 L) T5 |: r, t
// btMasterSlave = Master(0xA0) Or Slave(0xB0)
9 x. P" }& {9 b& {//---------------------------------------------------------------------------! S0 f, ^# g7 u! y) y0 V' H" E2 a
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
, n, M. Q9 M" d8 \        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
5 F% s2 N- m" }) ]! r. X{
7 i0 a# U9 d2 k6 F    BYTE  btIDTR1[6];* P! V" t" \% ^1 H9 h
   DWORD dwOldExceptionHook;. ^& |( {# y5 ]; ?1 z6 o. N
   const int nHookExceptionNo = 5;
; y, O' F& g& I2 H) ~
' x$ d3 g$ D1 P8 ~: N9 o    BYTE  btIsIDEExist = 0;9 C6 a: f0 J4 n- i% x
   BYTE  btIsDiskExist = 0;
9 U! Z% l' L. J$ t5 c4 x; W% o    WORD  wOutDataBuf[256];
8 n1 d9 `% J4 a% ?
' G- D8 K! u4 J7 i! U: \    BYTE  btIsFirst = (BYTE)bIsFirst;
+ e) }0 f" W: ^6 J1 t! _/ P
3 A9 k9 A+ t: p5 x/ Y    const BYTE btBit00 = 0x01;
" q6 W: i3 [: h& O3 I  a+ j& A    // const BYTE btBit02 = 0x04;; ?* S3 E7 }3 I4 G: @4 J' W0 |
   const BYTE btBit06 = 0x40;
, t: g: T/ N  q& n0 g    const BYTE btBit07 = 0x80;4 x$ D0 t6 `' {4 N/ @
   // const BYTE btERR  = btBit00;* p$ K: g% V4 Y; V
   const BYTE btBusy = btBit07;" S( U2 y! l: e9 x
   const BYTE btAtaCmd   = 0xEC;" r6 x2 W6 ]" H9 _0 U
   const BYTE btAtapiCmd = 0xA1;  f0 l. v/ [) G5 U/ u2 P* I

4 h4 }; h! `/ c    __asm1 L; e6 p! N; K# I  Q
   {0 k2 u+ s+ J2 t# w- x3 P
       // 必须先执行这条语句
8 |' L) j/ Y( Y# Q; @" }  z- S        JMP EnterRing0, H. ?0 f( U( d4 J5 n3 Q
  d; Z* Z  F% n" R
       // 定义过程( |% a. u" {# R9 J( w7 \
       // 等待IDE设备直到其不为忙为止
" S2 m" {' ]! P5 ^: I0 G: G) n        WaitWhileBusy proc$ A7 p/ y  L; n( c) g6 V' D
. y2 c% o$ t/ B5 g$ h
       MOV  EBX, 100000/ O: ]' R' }* p8 A) G8 [
       MOV  DX, dwBaseAddress
2 b: f8 I1 I' H5 k6 i        ADD  DX, 7- k5 u0 n% ^0 }* q2 C6 ?2 V
6 S6 t4 m# B. |" p6 r6 b- i& Q9 q3 Z
       LoopWhileBusy:( k" M8 q! M# V! g  k
2 a4 w: Y7 e0 ~' B' l
       DEC  EBX
% U% g9 a. ]1 T1 r$ t        CMP  EBX, 0
* v3 z( X6 B1 h: z  k( V8 n7 T, L        JZ   Timeout0 P4 |% I5 @# R: p) ?" |
       in   AL, DX
0 {& T, s& {. m        TEST AL, btBusy) J# @3 B. S8 m: K+ t
       JNZ  LoopWhileBusy
+ P+ o7 l; q3 Y# B. t7 h        JMP  DriveReady
% n8 N7 c( B- b6 J/ y& W( j/ K2 w8 ]& E& b" t0 D
       // 超时,直接退出% t: ~3 Q- F. y( X  O; S
       Timeout:, t0 x6 r+ J; i% f) ?$ P
       JMP  LeaveRing0$ Q' D6 r7 E! a- y7 n
       DriveReady:
6 P' `0 V! m1 Q- l; \& T        RET
' \2 Z0 `; J% z7 `" D# t        ENDP   // End of WaitWhileBusy Procedure
) N6 L5 ^, {8 Y! X' H+ N: m& @- q  V  z; L2 s' E$ l6 j3 R7 u
       // 设置主盘和从盘标志
" W3 l4 e6 U* c7 x        SelectDevice proc4 B- `( y" k' {  e7 p# q4 ?; v' s

4 w# F: t3 h5 G2 ~( u        MOV  DX, dwBaseAddress
& h. M1 Y) l% |# S; _0 b% j7 N; h: Y        ADD  DX, 6
+ f1 O8 `. `* q  Q# [' Y! r        MOV  AL, btMasterSlave$ v% W5 g" F) R: b2 f! s" i7 F

. V2 _( o; P8 A: O% w; v        out  DX, AL7 y3 X% c$ F) r0 ^
       RET) {/ H4 }5 y1 X6 S+ i

1 E" X" j2 I% y* j& |& g* \        ENDP  // End of SelectDevice Procedure
7 A  F( q4 x( v. T: v: R* L( k4 W! z  H+ m: y$ ^) n
       // 向IDE设备发送存取指令
  m2 Y8 \1 r  G0 J, h  C5 k# _        SendCmd proc. u1 g9 X8 z# t# q2 a

  w$ j' ]( p" p9 Z) I        MOV DX, dwBaseAddress
6 q4 V/ X9 U4 @0 K        ADD DX, 7
3 [' e9 L. {& W  v        MOV AL, BL // BL是主从盘标识,在过程外设置
9 e% }# ^" L- g6 t2 R        out DX, AL: a# p" l& ?7 z7 Q* H
       RET) y" `8 d* s, @/ e& b' h1 D
       ENDP  // End of SendCmd Procedure
; n& d6 q& D9 l$ q& m, ^. S( ?( S# i0 i, L9 a$ R
       // Ring0代码4 l, w! U. T2 _3 h0 U8 ~
       Ring0Proc:
" q! @/ u4 G7 X5 \) @! z* b4 K        PUSHAD
( r- s, |  e2 E" P* C8 s" A* J! [! c        // 查询IDE设备是否存在
5 d5 A0 u/ `; }% P% p3 a" v- j        MOV DX, dwBaseAddress* h( N& T, I3 c: B1 ?
       ADD DX, 7, p9 F% G3 G. y
       in  AL,DX
/ N. s* c) Z6 w8 `, q* F+ }9 f
# Y* H5 [2 C) ]        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回2 V8 W  D( X2 u! f
       CMP AL,0xFF% Z8 r# b: X3 G) i( Z
       JZ  LeaveRing0
/ T% [8 @2 S/ e! j! j: I; D: f        CMP AL, 0x7F5 Q$ H& i/ A" ]3 M2 D
       JZ  LeaveRing0) z2 y# P2 h6 g# d( B( \

; f1 X5 D( c  |& y) H        // 设置IDE设备存在标志
5 i/ f2 u2 R! }; u# B0 L- @        MOV btIsIDEExist, 1
; M8 L* s/ N' j8 ?5 J% P) C) K. \. t% o' X9 [. B& N" v
       // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面), G9 i# Y5 V' }, j
       CALL WaitWhileBusy. U9 q+ m" J7 z( O2 N/ t2 }% E" H
       CALL SelectDevice( R1 b0 V2 b3 O0 f9 y8 j0 k; @2 U8 ~
5 I. d) {! c4 P4 K" R. @* D; v' ^
       // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏$ [! R0 B5 e: m* @
       CMP  btIsFirst, 1
% }3 n: f; f% @  b: ?* [        JZ   LeaveRing0" v7 s( B7 O3 }
( l; |: _% B- Y7 n) s
       // 第一次调用时,如果执行这行语句会导致蓝屏,Why???6 Z8 ~" w: O  s) E& i" w
       CALL WaitWhileBusy3 ?1 ^' Z( S; F6 i
. ~2 b# u- ]; U3 A& F. Q3 M
       // AL的值等于cBit06时,不存在驱动器,直接返回
0 K" S0 }& z7 @9 {1 Z2 F# I5 M        TEST AL, btBit06  h4 B8 Q, Q7 S* B4 U
       JZ   LeaveRing0$ D" h/ v, p. n1 W/ W  g  T

, u9 U3 d& A- S  N3 k: e) V" D        // 设置驱动器存在标志. ?: |* s" U, I8 \
       MOV  btIsDiskExist, 1" P. y4 Z' f4 v  t

( P4 j  S1 g2 b9 z- d5 M        // 发送存取端口命令
& V9 [5 U* T& i+ u% O4 ], c        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
5 _0 y) ~4 L1 h' Y+ O* a        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令5 b6 @4 Z6 T" |/ M
       CALL WaitWhileBusy! G, r3 o4 `. f/ H$ h( j  F0 v
       CALL SelectDevice    // 设置主从盘标识
" y5 y) ~$ b" t, Q5 m% R- n9 q9 l        MOV  BL, btAtaCmd      // 发送读取命令
$ U% B  N( J1 ?7 M6 E6 w& S  U        CALL SendCmd
8 Q! r% V0 j/ L+ G; Q        CALL WaitWhileBusy
( E% v4 Z0 F2 y; `% |3 i* H+ L+ b2 F! u0 N% q# _# k+ _
       // 检查是否出错+ ~1 \4 B7 y9 g. [6 k; q5 I
       MOV  DX, dwBaseAddress  C6 _+ C$ Y$ s5 X# c3 k7 U6 |0 Z
       ADD  DX, 79 J4 Y  U, x6 x2 Q& ]5 z- \$ q  ~
- ]/ a. @0 i$ t# U6 V
       in   AL, DX& X: Z. Q* S0 B0 H$ {* D# F
% \) [7 u$ i- }2 Q8 V8 l* b% f
       TEST AL, btBit00
8 L; M1 b2 k3 {- {$ c8 Y% I- o3 j        JZ   RetrieveInfo   // 没有错误时则读数据
( p- T! q4 N4 h" V3 G# y3 w% N8 c: t1 ^: C! D. D: J
       // 如果出错,则进一步尝试使用ATAPI设备命令
7 s8 l& U& b# @. p        CALL WaitWhileBusy
+ K3 \/ M9 D* k, e3 X6 `1 ~" A        CALL SelectDevice
/ b- [. J1 u) ^' j4 A        MOV  BL, btAtapiCmd& [. d1 K9 b, ^
       CALL SendCmd
& L3 p8 @! b- \+ p4 B# b: B        CALL WaitWhileBusy
: Y+ l& z- F/ y+ ?
4 K- j/ q0 x0 W4 I$ l        // 检查是否还出错- X( l6 g) |* c! _! n
       MOV  DX, dwBaseAddress3 o* V- f  K; N3 D: H3 }
       ADD  DX, 7
. D. S) r% |" x/ r        in   AL, DX/ T& h* O$ U# a, L5 O
       TEST AL, btBit00$ ]! P8 S# M4 ^) o
       JZ   RetrieveInfo   // 没有错误时则读数据7 C& Z+ ^* l% Q: ^
       JMP  LeaveRing0     // 如果还是出错,直接返回
2 x4 K5 z6 d9 J! j1 K4 _* e  r$ b: E; ?& K( P0 s
       // 读取数据/ w6 D7 B: G- H3 A( `$ N$ e7 J3 p
       RetrieveInfo:2 f2 k7 L. t- N! Z' o
; W: x: \% }5 }6 m# q9 q8 t. ]
       LEA  EDI, wOutDataBuf
  R, V7 \5 z/ ]0 Z( Q        MOV  ECX, 256: j+ `6 B/ j7 D/ G6 J: l0 g0 f
       MOV  DX, dwBaseAddress
$ O( D: w# K: a; `- S; O        CLD. G% u' M: [% b+ c4 W
: r7 k( Q: b/ p& z! [
       REP  INSW/ `# |" r1 ]& W$ w+ S- F
- P4 G2 b8 U3 o2 p0 Q* P& v. ~
       // 退出Ring0代码
# b; a- D8 Q4 V- l2 P        LeaveRing0:
6 z% q- P. g2 b( I$ ^8 s1 P( {  v; Q( |, t, \/ P
       POPAD$ Y5 m6 L6 d" z# ^3 M0 C
       IRETD8 k- }; z% |9 }& ^& I* G- [
& }* T: q2 V9 ?, q" O2 f
       // 激活Ring0代码
$ @0 w: n/ K% h5 {- C$ ~% P        EnterRing0:  D$ D& {1 k" W) e
) g: i+ C6 l! P1 f
       // 修改中断门  Z5 k' Z( b7 F
       SIDT FWORD PTR btIDTR1
) e# f8 N* V) r) t6 w& v        MOV EAX, DWORD PTR btIDTR1 + 02h) x- W( q$ d3 ~  e7 W8 Q6 N
       ADD EAX, nHookExceptionNo * 08h + 04h
1 P$ j% N1 |& V        CLI% x0 O& h- R' W7 @* w# d  e: Q

( q- L% @$ }0 Y4 y1 g5 X        // 保存原异常处理例程入口4 x3 ?. {6 e* e- j, x0 A1 M
       MOV ECX, DWORD PTR [EAX]
! M* _1 N$ I! D        MOV CX, WORD PTR [EAX-04h]" C/ ~" t" s8 V1 t" q2 R9 Z
       MOV dwOldExceptionHook, ECX
) T: G0 D  S  G
  H8 S' C5 F1 Q. V% L        // 指定新入口/ U& H( ~% d7 f/ I" A
       LEA EBX, Ring0Proc5 M/ I  `0 F6 f1 m
       MOV WORD PTR [EAX-04h],BX: o% B) d9 Q/ w# n
       SHR EBX, 10h6 E. ~; ]2 K5 y) ~8 ^
       MOV WORD PTR[EAX+02h], BX
* B: ~3 Y) g7 Y2 g2 O* V; |. E1 n( a8 E  r$ o. u$ h5 q* j
       // 激活Ring0代码8 J# G7 a) P" a9 l( _
       INT nHookExceptionNo
4 f; O! r7 \9 S1 N
8 H$ D: g/ B' y$ ?7 u        // 复原入口% O+ i' S1 L2 v! a  h/ Q
       MOV ECX,dwOldExceptionHook
4 b. A' k# e. s0 D        MOV WORD PTR[EAX-04h], CX
0 r: a5 Q( h1 K* I+ e        SHR ECX,10h" z  O1 M% t6 _8 J' A4 y' f
       MOV WORD PTR[EAX+02h], CX4 w) B2 t; C& r& l$ r0 Z: L1 e7 {
       STI
( v3 q9 `* n1 v    }
' \0 m: {* w7 v1 E2 i+ P    if(!bIsFirst)
5 \2 G: P' L  E) h1 B" o* i* @    {' Y0 g! ~& o: C6 s4 T% B
       bIsIDEExist  = (bool)btIsIDEExist;
/ g+ E" u; N2 d        bIsDiskExist = (bool)btIsDiskExist;
! F! ~( ^8 ?7 M" n$ b/ L7 p/ @- _9 ~        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
2 q+ _4 }  A/ L" P6 V% ~    }
! I$ t  h1 O3 n2 s9 c}
* ~- M& @3 f" F- e4 x  K//---------------------------------------------------------------------------
5 z9 p- f: s) K& l6 b3 g// 调用方法:3 {9 ~" a: b" X4 T1 N1 }4 E
void __fastcall TForm1::Button1Click(TObject *Sender)
1 i8 _; N6 ~5 E" _+ O% W/ y{
2 A$ q) C7 u, J* G    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
6 E8 t5 l7 n7 B; j}
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-6-18 09:08 , Processed in 0.019434 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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