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

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

[复制链接]
发表于 2005-5-30 19:22:36 | 显示全部楼层 |阅读模式
  #include <WinIOCtl.h>: t4 Y( @* e3 ?
#include <stdio.h>6 J- p5 I* B% E$ g

& Y& |- N5 U* ]0 Q" V8 Q& ?! E- ~5 a#pragma inline) [6 p( D- [/ F) |  m
//---------------------------------------------------------------------------
6 O4 o! ]( V' m2 ~0 p. y- @// IDE NT/2000/XP专用变量
! F' k  E6 {5 Y' {! @: F#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS2 j9 C5 }8 q( S- n  ^
#define DFP_GET_VERSION         SMART_GET_VERSION0 x$ ~" K6 W% S1 K" S6 Y
#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
, K' N, F* G8 a* [3 ^#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
. ~6 z( {. z" ~& K# _% u3 |. F! \' x4 t
const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令6 N4 q" j' @& w
const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令# A* D) E' E2 ]/ Y

% W& U% @1 m  u8 Zconst int MAX_IDE_DRIVES = 4;
+ O/ ]( D; _; r3 W2 B  v5 S8 _
4 ?% U- _4 ]0 m, A$ z5 p// SCSI专用变量7 ]% g7 g/ C6 X% z' ^7 k, W# f4 K
const DWORD FILE_DEVICE_SCSI             = 0x0000001B;! C; C8 S9 _* ~+ q
const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);& ~4 U' |9 T" f! I' e
const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition- u  `  b' S7 m
const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;6 G2 e4 j& b7 L, f4 H% c

& O- b5 E( P3 g9 o/ C7 `( k0 n9 Vtypedef struct _SRB_IO_CONTROL
! D) B; t* h- z( B! P' O# J{  Q5 n4 ?8 `- I" T; H! r1 X: c
   ULONG HeaderLength;
7 b5 h) {" {2 h" W    UCHAR Signature[8];
. s: q+ {3 G6 n& |! Y3 L6 N  |    ULONG Timeout;. w$ X& A8 X9 U+ {6 n. T1 Q
   ULONG ControlCode;
; C2 j. L6 r" s- [( {$ r' a1 f5 p    ULONG ReturnCode;
, |" q5 [/ N0 l2 z/ A9 e9 G; B& L    ULONG Length;
1 P* J: Q( r! u4 X- G}SRB_IO_CONTROL, *PSRB_IO_CONTROL;4 z. `; l- A2 r

2 B: z  X, G8 Y$ r0 M( d$ }// 读取的主函数2 l4 t0 p$ \$ N) o2 ?
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);6 ^; n% L, q8 J# W# Q* N
/ h; V0 Z0 P2 w  H# Q( W' F
// 辅助函数6 W! M8 v+ c" B3 \
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);7 {. U  I% q$ i
// NT/2000/XP函数
" a6 O0 T( O* l4 k* ?5 Dvoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
- a6 j: M: L5 \! O+ g" {# Rbool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,4 @$ h) [3 G8 f
       PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
- W; W, \9 A+ j! H- k7 _* b1 W' M        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);5 t' ~3 X$ h% k9 {+ l
// Windows 9X函数
5 V' v8 d, U7 F' N& F% Gvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);
4 S- \' h9 Q  F- Rvoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,8 j1 ?; \/ Q# y+ O5 ~2 U, M
       BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
# l) O* }4 B$ }
6 e0 x( j' q9 [& K1 [- _6 ^// SCSI读取函数(for NT/2000/XP)
: F. s: V3 \: Z9 B' DString __fastcall ReadIDEDriveAsScsiDriveOnNT();
3 O3 y- ~. ]  K+ P# j//---------------------------------------------------------------------------
, S. i; B4 [9 g0 @// ReadPhysicalDrive# K" l9 F9 G# t  u
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)  Y6 U$ z( h1 D% T
{
- _$ T, G3 P( O3 l$ h( h" E    switch(Win32Platform)5 |: O9 i/ y: k* m8 M- J% {6 W% y6 R
   {
3 g- Z7 _/ u/ d3 p8 t        case VER_PLATFORM_WIN32_WINDOWS:
8 R: |/ v5 r6 \- [. `. d1 |            ReadPhysicalDriveOnW9X(pSerList, pModeList);
$ m+ Q' u: Y2 n            break;6 _( M& W: K! c0 f* l3 t* W
       case VER_PLATFORM_WIN32_NT:  o& e# g7 c7 ~( w1 H- N# `
           ReadPhysicalDriveOnNT(pSerList, pModeList);
* ^8 {3 o3 q& I1 M            break;2 [; n7 E1 {/ O' [0 ]. @7 D
       default:7 o: }, x; H2 n2 |3 f) ]
           break;
  M' S$ t8 F% ^0 x( r% S- Z3 B    }
9 a  j% n8 ^- `: u}$ s1 O4 v3 x: K+ ^
//---------------------------------------------------------------------------% c" U& {) Z% L* Z& t3 W" \( f, a
// ConvertToString4 Z- j% |5 v% M, v4 K; H1 M
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex): s; `6 S# [% H( n, R6 r
{! D) q/ g' E& \& l2 g; W, x' _
   static char szResBuf[1024];
+ _9 K/ U- M- \. I. @( s    int nIndex = 0;, v6 _& W& [  b7 T* S
   int nPosition = 0;: q- p2 [0 v7 U5 y# U
$ m6 q) [7 b: r) V2 M  H/ S
   // Each integer has two characters stored in it backwards2 C: O2 m) N" m' R( v9 X( B
   for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)9 i7 D5 d0 s: v5 K; V+ L* E  K
   {' e3 T; @0 {) D6 s/ p0 i
       // Get high BYTE for 1st character( x) E1 D, K! G* K% l% I
       szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
1 x- Q9 ], g8 F( `        nPosition++;
9 x/ [2 H. k- M, X9 t# w$ |! H5 g& v; _/ U  i
       // Get low BYTE for 2nd character3 [/ e/ t5 v+ F* g2 g) B
       szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
' j& m3 m$ b* ^/ Z! w        nPosition++;
, U; S, S5 ]5 T: Q- u    }  K! x% F2 ]0 z
$ P/ I) q7 w- M. @# E" Q" H
   // End the string2 W- x( s' p0 a% ~
   szResBuf[nPosition] = '\0';
+ S2 L8 S5 _$ E0 s" u
& m8 ^; n# d5 B1 A, W1 `    // Cut off the trailing blanks# N! Q" U& g1 E; b5 `
   for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)  P$ v0 Y' t! N" I8 R7 H
       szResBuf[nIndex] = '\0';# T2 q6 ?+ k* X0 B7 V$ m
# r5 E* u5 k1 t, ]  ]
   return szResBuf;& y, m0 Q! j6 P$ [! l
}7 J7 s9 Y: M7 x& ~
//---------------------------------------------------------------------------. q6 L3 n6 ?  i# C2 Y0 L
// Winndows NT4/2000/XP 代码
( t: T+ o( \9 c; \$ k//---------------------------------------------------------------------------
9 R0 b- D( r2 D. B// ReadPhysicalDriveOnNT
, \" ]% Y* d8 Fvoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
  i% d/ t# d! h5 w{5 m% q$ @7 [" ?
   // 输出参数, o! N# T  ]* L; }8 E/ H
   BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
/ h, G. H9 `( u6 ?5 |+ \- D  G/ Y3 |
   for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
1 p8 v4 C* K4 j5 D0 m& {    {/ R8 ^+ c$ `) s; \
       HANDLE hPhysicalDriveIOCTL;" [- A& ]5 y) j% e. s' W
       char szDriveName[32];: s+ ]3 N: X: B( c0 Z# A

) N" k( i7 `4 f  X1 t        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);! z  Q! Y  i7 X
       hPhysicalDriveIOCTL = CreateFile(szDriveName,; k- |3 q( H/ U% N( e# a$ D
                       GENERIC_READ | GENERIC_WRITE,0 j" q4 h- B' W
                       FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+ q* {& {/ y0 `3 A6 W( R                        OPEN_EXISTING, 0, NULL);
5 d. G  U$ V/ t9 ?$ j6 }1 y  n
1 R" q; X# [. O: D' D3 W+ _" D1 u7 b        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
0 u/ y0 z; T3 _+ @1 g5 V/ u: O        {6 |1 ?. F) j8 X7 H
           DWORD dwBytesReturned = 0;& n4 {2 I! ^% V' \) u
           GETVERSIONOUTPARAMS gvopVersionParams;
  U% w" z4 N; ?* e, D. s3 i7 J7 |. I0 b1 @+ N. K2 \' |
           // Get the version, etc of PhysicalDrive IOCTL
% o7 e% A; A% W1 e            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));1 \  x4 b4 f" f: z+ b" @5 ~( ~
4 ~3 ?' l! A  |2 _- l4 n/ u# a
           if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
& G5 X: U! ]3 G. c7 _                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),8 X7 I( u" S- Y
                   &dwBytesReturned, NULL))& Y  X8 ]( g, x# `0 _
           {
# v* Y. \) W0 r' k: k; @                continue;
* }; A/ u. J9 F2 X; e3 v9 F+ l            }
& d, s6 \5 i! p* A) S: H" w
! P) X0 ~4 Q. W7 f            if(gvopVersionParams.bIDEDeviceMap > 0)$ E& u8 Z5 E6 S% w# P6 j. ?9 p
           {+ `( Q7 Q* j7 U4 G% E" q0 K3 }/ r) G/ q
               // IDE or ATAPI IDENTIFY cmd
' [, `/ n9 T+ V# v5 x. u: q# ?" i                BYTE btIDCmd = 0;
8 T  H1 u2 t- A- g2 l# c. ]! L/ A5 m2 d                SENDCMDINPARAMS InParams;* N* ?- Y' a( G
               // Now, get the ID sector for all IDE devices in the system.
/ u6 w, e3 a1 Y0 l6 j+ {' A                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,, X9 L4 u' I1 ^
               // otherwise use the IDE_ATA_IDENTIFY command
# h; F& }4 ]. F& T# @                // 具体所得结果请参考头文件中的说明% w$ c2 ?! I9 [. D# D, Q0 Q7 e
               btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
5 d; ~1 r, p) p  ^! N                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
( m# \! j- u' a8 ?                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));! `% K9 b, e& Z; |( N+ ^5 a
               ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
' W/ J# l$ T+ H: w! {+ U0 k& Y& E1 _/ y' y; _+ B5 G) x
               if(DoIdentify(hPhysicalDriveIOCTL,
1 s# Z7 m, R! A# X/ m                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
  M" k1 J/ S/ Y7 ], `9 a                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))2 B* q' `" }. h
               {
5 [# O# F( r+ J6 J                    DWORD dwDiskData[256];
0 m5 c  C7 a4 {* G" i                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件- ~. [" }2 c- u
                   char szSerialNumber[21];
5 n- [1 x+ j+ G3 [                    char szModelNumber[41];8 i5 o/ O$ y: M8 m' |1 T
1 M( _2 |- }1 w2 B9 o
                   pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;1 U2 K7 P) U' M' g5 ^, X2 O
                   for(int i=0; i < 256; i++)6 E  J$ W# Y- Z  c2 W) o% y: h
                       dwDiskData = pIDSector;, N4 I6 m9 Z$ W3 z2 J. c$ ?" @
                   // 取系列号
. ]9 b1 }0 H# \) H" J! s7 U                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
: G/ Z3 X8 Q, S- ?/ Q1 l2 S' H                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));% o: [* v. v. D4 |% D% d1 \  i

: O! X, [" _+ P( k9 q5 I7 \2 i4 b% U                    // 取模型号/ n( Y) o; n) x  h& i) L- |9 o3 c
                   ZeroMemory(szModelNumber, sizeof(szModelNumber));# Q/ h8 R5 v* `7 N1 `6 O
                   strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));! z* E+ k# Q, q( D( @; o

1 o2 r$ f( y3 U) l- Q" y                    pSerList->Add(szSerialNumber);
& H) x! K' ?9 K! V                    pModeList->Add(szModelNumber);& Z" b3 V: |5 p. F' r
               }5 {4 ~& x# K% y" H1 ]0 H+ L5 z
           }; M' S6 `* ]0 F' s7 i* W8 Q! C/ N1 S
           CloseHandle (hPhysicalDriveIOCTL);0 m. j* x. U8 q. j" `. {# i3 p6 m: g
       }
3 C  ~$ C- b/ F8 u" t4 ^+ L    }
) z! R2 S. S4 C3 f- p4 }}
. Z! r" S( k& w1 o& P//---------------------------------------------------------------------------. f, i* n0 f/ S
// DoIdentify# w/ F7 R' E8 I3 Y2 a; e0 g
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,) T- _5 f8 u7 V4 M0 d
             PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
0 n) H1 H! y. l6 k              PDWORD pdwBytesReturned)' W: J/ t5 W3 E. c% {' e# c( h# F  X
{3 v0 f1 H; x0 o# S4 Q  U+ I2 n
   // Set up data structures for IDENTIFY command.
6 Z0 C5 {6 p9 i    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
/ |5 q, I$ n0 z$ K    pSCIP->irDriveRegs.bFeaturesReg = 0;9 H+ U, ^7 b4 w/ V) F( I2 M2 R
   pSCIP->irDriveRegs.bSectorCountReg  = 1;5 @# Q0 \# m, y
   pSCIP->irDriveRegs.bSectorNumberReg = 1;3 u  ^2 z) H- j! W3 ~. H" G( i$ c
   pSCIP->irDriveRegs.bCylLowReg  = 0;% u4 J0 b9 T" z5 m6 s" _' h
   pSCIP->irDriveRegs.bCylHighReg = 0;3 q- X8 ^: w# R, ?- ]- C
, j, f6 L$ M0 F
   // Compute the drive number.(主盘和从盘所对应的值是不一样的): g5 Z0 K5 z! i' |: L# }) a  i
   pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
6 F  [6 |5 J" d: s* h0 u+ p
0 }, h: k8 P& _    // The command can either be IDE identify or ATAPI identify.
" a. \( M$ k3 J) H9 R    pSCIP->irDriveRegs.bCommandReg = btIDCmd;
8 @! h* V- D8 ]6 S1 v& Z' k8 T6 j    pSCIP->bDriveNumber = btDriveNum;7 E$ S7 U' n6 A% X. ]" C: J$ z# y& p
   pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;; Q, \/ d7 _- j2 p& c/ C: {4 I, ]

- f) s9 Z/ R7 C6 g! X    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,( @* ]5 [$ `; I- e  |. d% a
          (LPVOID)pSCIP,  S( e; `* O3 K; l
          sizeof(SENDCMDINPARAMS) - 1,% |" Q6 j1 {: x% J9 O& J8 }
          (LPVOID)pSCOP,
9 \1 I7 @5 P- ^/ x) ?           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
- o9 M# \: S9 |$ Y5 e2 k           pdwBytesReturned, NULL);% {3 }5 }' y* ~/ Q6 L0 W7 {
}
. g. b. t7 T  u: N$ W# e//---------------------------------------------------------------------------% k; i7 f0 D! P# X3 J9 b1 H# z
// Windows 95/98/ME 代码$ V2 V' ~; T+ v( v! r
//---------------------------------------------------------------------------
! e1 {! B: t3 d$ h// ReadPhysicalDriveOnW9X6 D( e$ g8 Z4 ?  I! z; F9 G2 P
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)$ Z/ O- D0 \- }( X' W1 @( U
{
' B: B% a) m8 Y9 Q. Z$ C! ^6 q0 j    WORD wOutData[256];
9 ~9 x% P3 c- E! G9 e    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);1 O4 V5 O+ P2 O7 A# H2 N
+ ~, M& a, r$ w/ _4 z6 M$ W, d9 D
   // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。, I, h' q; i+ h9 t9 A# I% C' D" o' w
   // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
4 S% l4 ~0 }* b" h/ `    // 避免蓝屏的出现。(期待高人能指出原因)! O0 c/ B# o+ W+ {! Z
   for(int nDrive = 0; nDrive < 8; nDrive++)- W4 Z% t1 m' x* `: E
   {
% n7 v3 O- \, ~0 U        WORD dwBaseAddress;
9 u8 Z& }" S. I3 [% l) \; z        BYTE btMasterSlave;         // Master Or Slave
% K2 ]- j; k1 p7 z        bool bIsIDEExist;% w/ T& L  @% l
       bool IsDiskExist;
2 W/ l" p9 g3 Q: e& a$ q' `
6 f  o. R0 x1 s        switch(nDrive / 2)
( u# y" u, M. s; D0 y0 |        {) d) N% E/ F2 I* a! t& o
           case 0: dwBaseAddress = 0x01F0; break;9 X4 E8 `8 a" X. \. |
           case 1: dwBaseAddress = 0x0170; break;8 n# {7 y+ P1 Q; J
           case 2: dwBaseAddress = 0x01E8; break;: T% B1 Z: u3 p9 N. |& ^( J
           case 3: dwBaseAddress = 0x0168; break;* F9 s' T+ x0 G7 Q4 e
       }5 J% Q+ B4 n; o
; c) k6 A3 v. X
       btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
3 q! |' w) }3 G+ b
1 u6 W4 Q1 C" ^) Y        // 进入Ring0
. }- S: U" D- K7 o$ W        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,- }  a$ m) U) L. _7 P
               bIsIDEExist, IsDiskExist, wOutData);, U4 c, C7 P( v# N/ b* M; w
   }6 g* j8 ~5 O% y% F
9 Y  c0 \, \" a) N+ a
   // 开始读取
* |8 W& t( O2 w2 ~  u9 V6 |    for(int nDrive = 0; nDrive < 8; nDrive++)
% M. n7 m  t7 L    {4 u) ?! v$ ]% z
       WORD dwBaseAddress;
. ~. F9 h7 B+ m0 P( Y% H5 H+ Y6 W        BYTE btMasterSlave;         // Master Or Slave
5 q/ {5 k$ X5 u. G5 F5 F- L        bool bIsIDEExist;
( D$ v: ?% ?" F" U        bool bIsDiskExist;; [, D4 c! p; L7 i) D. v
       switch(nDrive / 2)
! K. a) e) [$ ]0 p+ h! g7 o        {
1 y9 m! f" d: z8 {  h. f            case 0: dwBaseAddress = 0x01F0; break;
! ~& a0 H% |9 a& B            case 1: dwBaseAddress = 0x0170; break;, f; m' L. T. b
           case 2: dwBaseAddress = 0x01E8; break;8 {: R" \0 [. @. I. k* G
           case 3: dwBaseAddress = 0x0168; break;
1 I+ L1 L- h  {+ Z        }
. Y) G- R- E$ W8 |1 U2 v; [+ Z
* O1 G$ ?. i* `; V/ A& ?        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
4 A. U- ^1 `) U. X1 v7 ]+ P* a# N% c6 D) J7 y# g
       // 进入Ring0
8 ?! `- p/ J/ b+ R/ ]        bIsIDEExist  = false;
+ b+ e6 V4 s* \2 E        bIsDiskExist = false;6 ^1 g9 q$ s; v; g  G  ~
       ZeroMemory(wOutData, sizeof(wOutData));0 @* Z( i  I/ f: P: E( K
& |+ |! ?. q4 r( C( q$ Q; K
       ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
  M3 r! O; u* h7 Z. p, o3 \                bIsIDEExist, bIsDiskExist, wOutData);0 G8 q( _  P7 t9 t0 m3 U* ^
' D& V; u1 @( ?" {
       if(bIsIDEExist && bIsDiskExist)
8 |! U# n9 R. A7 R8 p6 X0 Z" }( _        {, E8 d; N$ M0 Q7 f8 y
           DWORD dwDiskData[256];9 V9 r0 f( q4 N  Z
           char  szSerialNumber[21];
+ I* W2 }# }! S            char  szModelNumber[41];) _4 u0 i2 @+ m$ W+ R  `/ `+ v4 @' k

$ B9 {) q( Q+ l4 _9 g            for(int k=0; k < 256; k++)$ [! w& X5 u0 K/ G: P
               dwDiskData[k] = wOutData[k];$ a- K- |& q& [# c3 E( Y
# g0 @* a$ A7 z$ t% Z% c" p; T9 k2 g
           // 取系列号
9 }) A, k# T$ n8 B            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
# s  b3 n' _8 L$ l% T  K            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));2 b6 E. E$ t8 y1 j7 I! o

# V; ?: r: E/ [! s# W) d            // 取模型号
$ y: ]2 }! {9 {+ p7 s            ZeroMemory(szModelNumber, sizeof(szModelNumber));& |* Q, W8 @/ w5 K
           strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
7 Q: j0 }) ^# n3 y
; z0 z& }% N5 v( P1 G            pSerList->Add(szSerialNumber);
- D0 ^# }. X3 l: B            pModeList->Add(szModelNumber);; g8 A% _0 @0 e
       }& K) K5 y* X: X' F3 a
   }- O' W8 G! w; z# d
   SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);1 l9 `, c2 Z! C. V3 J" Y5 @
}
6 b* b* @4 Z% J' C# {& I* H/ W! G//---------------------------------------------------------------------------3 x: z8 w5 n; M# Z
// ReadPhysicalDriveOnW9X_Ring0()( }. G; l* y. N$ j- [8 M/ D* O
//
" N6 |2 }' D6 @0 X4 u, S- o// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h: S7 n7 }( K% U. ]
// btMasterSlave = Master(0xA0) Or Slave(0xB0)
0 C# m7 ^) w0 p" z//---------------------------------------------------------------------------+ s( T. m8 }$ l  f
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
: ]3 H# B0 s% ^        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
$ I( Y5 ]. c7 L8 Y7 ~# k3 x5 U, Y{$ U9 i& ~5 `) ^/ v/ H$ [
   BYTE  btIDTR1[6];1 @, O! q8 ?7 k$ Y, a) |$ I
   DWORD dwOldExceptionHook;1 L# L, S' k! X1 T! l
   const int nHookExceptionNo = 5;6 q/ }; }; b! v3 q5 w
' q1 ~4 j/ D- K
   BYTE  btIsIDEExist = 0;
, U" G$ o% c7 S# _# D' p    BYTE  btIsDiskExist = 0;
+ [5 S/ w/ L# l    WORD  wOutDataBuf[256];& w& o- ^' L. Y1 ^! C0 N/ t
7 B, e( g  O8 C: w# H2 L% p
   BYTE  btIsFirst = (BYTE)bIsFirst;
4 R( t& @' o- t3 ^1 K" H/ m+ i1 h% X/ J' N$ _/ _
   const BYTE btBit00 = 0x01;9 W, g: t( `! h
   // const BYTE btBit02 = 0x04;  _) ^: i# T" E! [1 `: t$ n, M
   const BYTE btBit06 = 0x40;
9 Y3 l3 a/ d  f* `3 z+ `' T8 T    const BYTE btBit07 = 0x80;; Y) t4 t2 M. W2 `% T
   // const BYTE btERR  = btBit00;; Z* h: C9 q5 h, K
   const BYTE btBusy = btBit07;
# y+ a& t* L" A9 p* X    const BYTE btAtaCmd   = 0xEC;1 F, X9 _, k/ Z# P# H
   const BYTE btAtapiCmd = 0xA1;
4 G& d' ~% L9 @
8 H8 \, c! N: o1 ~" m. p6 w2 T, i    __asm
. J7 z, X' x1 W( j1 h    {
- V& ^8 W$ @& K6 f$ e2 t! W7 j% n' ^        // 必须先执行这条语句3 x) L8 F8 C) q7 l1 z
       JMP EnterRing0
# z$ M" K# j! I/ t' t" ^2 i9 E6 g6 f; K. u; a& c0 J
       // 定义过程
2 O3 ~4 D; ~& q% Q) v        // 等待IDE设备直到其不为忙为止0 r6 }/ X' z: ^5 R
       WaitWhileBusy proc2 j9 U4 [  C) i
" X% K( z1 p* S
       MOV  EBX, 100000: |9 o9 B' f6 U" w) u( X
       MOV  DX, dwBaseAddress
! r8 K1 E+ z# w: T2 N        ADD  DX, 7" a2 _: s- ]/ R& I, t# f& i
1 j6 A$ n' [: }* Q) n' i
       LoopWhileBusy:2 O. P. W& Y, G( W
9 a8 d2 ?5 O, g8 B/ [
       DEC  EBX
4 f2 ]' x4 _+ _2 m; z% D        CMP  EBX, 0
+ ~! n' n$ z2 ^& [; d, d        JZ   Timeout( @. {1 y* ]% H2 i
       in   AL, DX% |: W$ [" G3 ^4 |$ P
       TEST AL, btBusy
, L( h9 _) y: f4 e7 g        JNZ  LoopWhileBusy% b' q+ O& n4 M5 I# U
       JMP  DriveReady
: s- T3 E) z- R2 P! e- u* G2 G# q  x1 N* y
       // 超时,直接退出
& E4 Z; U  A2 |* x( a% L; f) L        Timeout:
! e* |! E* @: Z. m        JMP  LeaveRing0
1 w* K/ U7 t, H  @. i3 c5 M& K        DriveReady:
+ _+ x" Y5 Q! M9 G% ?        RET
% ?' Q3 G) p# N1 c, o) k3 A9 ]. Z        ENDP   // End of WaitWhileBusy Procedure# O3 ?6 C4 X( f  F% {

# N4 q/ u8 s2 {        // 设置主盘和从盘标志
) [- A3 v/ v8 w! X5 l, ?        SelectDevice proc
; V* @# g) O0 U0 M5 Y# d# x# w" s% E, [5 ?: v: F/ n1 |9 o
       MOV  DX, dwBaseAddress9 \/ _/ G/ \4 C9 t* u
       ADD  DX, 6
4 E+ c- i1 }5 V2 l" U1 A7 A* O        MOV  AL, btMasterSlave) l& Q% M! U: g" ]1 z) _# A0 [
( U+ m9 G4 O3 c6 @2 w" E5 O
       out  DX, AL
' L3 a/ P$ Z  o* u9 M4 j        RET
* }3 H  i! Y9 G
+ W- t2 m1 |" j  N- G) Q, [7 P4 h$ r        ENDP  // End of SelectDevice Procedure% |/ }1 S: `6 g4 g2 L1 Q8 s
3 W6 L7 E7 \+ K7 x! y7 E
       // 向IDE设备发送存取指令( B& {' k& o( Y
       SendCmd proc9 A+ P9 y5 |$ S- K; P2 j( {

# i0 V8 a0 n& t1 @$ A) _3 e        MOV DX, dwBaseAddress& O# p# i, u; k1 h
       ADD DX, 7' k% c4 K; G: j2 ~# R  x
       MOV AL, BL // BL是主从盘标识,在过程外设置. z$ p* D/ E! I- |: T8 j
       out DX, AL7 Y5 Z! l( Z  V0 {) o  O
       RET: x8 g* ]' z6 g( G
       ENDP  // End of SendCmd Procedure$ |# X- S( }4 F: J, }5 i

0 L+ C5 r& s0 C. Z9 `- q  ?0 W        // Ring0代码! i) s0 ~! Q& k5 Q
       Ring0Proc:6 h1 `, w6 R& F5 w% [1 Y
       PUSHAD
. e8 w+ a5 w6 U9 {0 W8 C3 R( [. D        // 查询IDE设备是否存在
  C5 _9 i& i, i7 u        MOV DX, dwBaseAddress
: F3 Z/ l7 |7 B9 Y        ADD DX, 7# T' k8 Y5 S& u4 Z7 `4 |* \- @
       in  AL,DX
5 D  \$ [: ~- O" B! B4 i$ T& ?  U
       // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
- `3 s3 O$ C! K. P        CMP AL,0xFF- n( w+ ~1 i1 i
       JZ  LeaveRing0! o, ~! \5 L' o0 F: o
       CMP AL, 0x7F1 F# w1 j, \' \) `2 ]2 N
       JZ  LeaveRing0
& M- k. I8 U7 W1 P, l: d; ]) v! u6 j; ^6 T
       // 设置IDE设备存在标志
4 n% E3 I- A  r- f! N  e        MOV btIsIDEExist, 1
/ M) J- v1 V7 c: t  t& D
) `! ?/ E- P+ u2 Y" [' M6 `        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)' f$ x! W# u! T5 A0 q$ ^
       CALL WaitWhileBusy1 }# @' |' f" V4 Y* y  M. Z& K
       CALL SelectDevice
& d4 M/ S7 `+ E9 ?( n' C! ?; D7 l# K1 Q1 f: D
       // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
. B& e9 k) b! r& d+ ~4 z$ k% w+ p+ n        CMP  btIsFirst, 1
2 ]2 m* ?' F% D0 k3 s- m        JZ   LeaveRing05 Y1 q' d! C2 ]) N
) M) s' z% d) d" d
       // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
9 s" O2 _! h. r        CALL WaitWhileBusy
8 |: F. t: |$ [0 a) U% }0 `- C) s1 y
       // AL的值等于cBit06时,不存在驱动器,直接返回9 f4 m) k& o8 \6 |6 q
       TEST AL, btBit06
$ `' f8 @; e8 _8 k5 S8 m+ q( w        JZ   LeaveRing0
: b* V* k! P) G1 ^
$ ^7 {( P% m9 u1 K$ I2 i( W        // 设置驱动器存在标志5 k% w: W9 @6 [$ n+ I5 X1 C
       MOV  btIsDiskExist, 1
, x1 R" I$ e/ w8 Z8 a5 N
( k" T. F3 U- t3 P- Q' M        // 发送存取端口命令
" t/ M2 D. E7 Z- L. t& F6 n        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,0 U$ D- v* u% y0 o
       // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令5 C$ |& H" }- v, X9 M5 K
       CALL WaitWhileBusy1 f' h# y) s1 C
       CALL SelectDevice    // 设置主从盘标识' N+ K5 n  l! b, H3 A
       MOV  BL, btAtaCmd      // 发送读取命令
5 }2 e. t4 J% t        CALL SendCmd
0 S1 p5 Z, \: ?8 h        CALL WaitWhileBusy0 e, \# D  i* w( ?: Y" o
$ z8 G# a; `( C/ o7 X
       // 检查是否出错
( O2 v# {* ]& _0 E0 K- G        MOV  DX, dwBaseAddress% |8 K8 }2 y4 l5 p7 V+ c
       ADD  DX, 7
9 b: X! x6 T) \. a$ h: x. ~+ d1 _1 b9 g, k: ^
       in   AL, DX9 R7 {+ q+ s; [- q) o
/ r5 N: S( o( x, }2 |1 J* ~) \* P8 ^
       TEST AL, btBit006 ]" i- B& O2 y) h
       JZ   RetrieveInfo   // 没有错误时则读数据
+ ?5 q% x9 }2 q4 E1 O- ]9 c
2 x" g8 I+ Z) }, C$ x. ^        // 如果出错,则进一步尝试使用ATAPI设备命令
, i9 s1 @4 ]" b5 s; }  Q3 J  I        CALL WaitWhileBusy1 p% P# b7 \4 Y/ t+ H" d1 F
       CALL SelectDevice1 J" o! M$ L) g; T( c% J
       MOV  BL, btAtapiCmd2 C# F3 q) ]7 L9 e$ j
       CALL SendCmd% F3 R# b" _8 a+ h3 f
       CALL WaitWhileBusy
/ n" F2 }% j6 h! n# y( l0 B  o+ q+ w* G8 P3 n  }1 x
       // 检查是否还出错" C3 r: R5 l% c8 B% W/ p9 A
       MOV  DX, dwBaseAddress
' w4 U$ y8 c$ G, m* N) z        ADD  DX, 7' V3 q+ v( ?! s/ G
       in   AL, DX4 Y* y# }* _3 c- O9 c  Y" U  R
       TEST AL, btBit00
( r; P$ ~8 W- o        JZ   RetrieveInfo   // 没有错误时则读数据/ F9 l4 [0 Z4 y6 B! Z4 _
       JMP  LeaveRing0     // 如果还是出错,直接返回
1 n6 b0 |7 a/ n/ k/ v" p+ U7 _4 v) U: T, U2 n; N% M
       // 读取数据
' N. z8 v+ ]$ _2 b  l        RetrieveInfo:6 F- S8 l5 S5 @

/ V2 G# f6 E1 b4 S5 l        LEA  EDI, wOutDataBuf
/ t' c; Y, W# }- ^! T1 A        MOV  ECX, 256
5 f3 g. `: P) M' w" @4 h4 ]( J% M        MOV  DX, dwBaseAddress
0 _  G( m8 H1 o) f8 {$ X( ]5 ], n- W        CLD
5 I( J2 _# |0 @  A! E. V  M. J9 o( O1 |$ h# `, b
       REP  INSW4 p$ z: B& [6 [! ~
8 v9 Z" _: r# @3 v4 l8 W6 e/ u
       // 退出Ring0代码
- b$ f& ?8 u: t1 J9 }+ n2 Y% K        LeaveRing0:
6 i  U5 E# T5 W8 `7 Y/ n3 ]  S
       POPAD
8 Q. Z1 z# N% H& E" N        IRETD5 J. n. R1 A* }$ V  O+ E. g+ J/ B

. H# P9 ?5 n: @# H6 }        // 激活Ring0代码
3 o* g* V; f; L( g' }, i* I. {) a* y; u* N        EnterRing0:! i; N) r. n! r8 D( z

7 D' Y# m+ Z0 Y( H        // 修改中断门: ?. r" N6 g1 q! k2 F8 c& u; L
       SIDT FWORD PTR btIDTR1
- q) @" C2 r& y1 }3 x        MOV EAX, DWORD PTR btIDTR1 + 02h( u9 m5 c, \' Y3 g
       ADD EAX, nHookExceptionNo * 08h + 04h
9 J% W' s8 O: S0 \# ]# h        CLI4 Y& w/ h( h! d% C/ H. w$ I% V. E
6 V# I# g* K# G2 [$ ^
       // 保存原异常处理例程入口
' T% U3 C# P- T5 I1 q        MOV ECX, DWORD PTR [EAX]
: m8 p  w# p4 s# J( o" c: q        MOV CX, WORD PTR [EAX-04h]
) w/ O* b/ P; U& [( j1 c3 r0 j        MOV dwOldExceptionHook, ECX
" f. ~: o. g; O% ]! \0 K) d+ H9 d* p
       // 指定新入口
) x+ A+ a3 p7 p/ Y- V+ o' x( `        LEA EBX, Ring0Proc; |# q. o8 S8 X+ D( D& n& u* o# H
       MOV WORD PTR [EAX-04h],BX/ f- d2 q0 t8 m% Q# O7 ?& I4 ~
       SHR EBX, 10h4 ~: e# }; w2 f+ l/ T
       MOV WORD PTR[EAX+02h], BX: F. b, q8 L3 ?# R! Z- X" T

$ J; U$ d. @) ?        // 激活Ring0代码
7 r: C% k# j# S: ?* y        INT nHookExceptionNo' z; M  Z* `7 B/ |  v

; q) J  I+ y3 m) Z8 [        // 复原入口8 l& v% g- x5 d5 O
       MOV ECX,dwOldExceptionHook
4 O9 Y* d; R& g* \        MOV WORD PTR[EAX-04h], CX
: L4 k# y3 M4 [- g3 N" L( c3 ?3 ]- R        SHR ECX,10h/ [# Y" e% D7 u5 e
       MOV WORD PTR[EAX+02h], CX8 w% ?# h# @& M
       STI
% f5 L3 b0 e# z" ~1 b. d) \7 A    }7 p" T# x6 m2 ^" f9 `3 S$ ], }
   if(!bIsFirst). j: Y5 o- i  ^+ M
   {
4 k7 `( M+ D" [' E) N        bIsIDEExist  = (bool)btIsIDEExist;
7 }3 |( z3 e6 Z, J: n5 Y# U        bIsDiskExist = (bool)btIsDiskExist;
8 \% N6 v0 ~; |7 Q. f( c        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
* }$ ~8 |7 [. L    }
# A1 n  R  R) Q8 c' f}
9 T1 |+ T' L# ?, ?- Z5 E" S4 ]//---------------------------------------------------------------------------) k+ P. l/ i7 X, v, n
// 调用方法:
# `$ r5 F6 ?" _/ w# |+ d( Evoid __fastcall TForm1::Button1Click(TObject *Sender)9 M; D) X! P' |3 @& O& ^! b( a
{# A  m8 M+ O+ Z4 y4 [2 D
   ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);; Z- x, d+ I7 t- f: h
}
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

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

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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