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

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

[复制链接]
发表于 2005-5-30 19:22:36 | 显示全部楼层 |阅读模式
  #include <WinIOCtl.h>& m! K. M* {; l0 K1 u5 v% u
#include <stdio.h>& f" v* q/ ~3 Y8 s5 O; {7 X4 \
. F( T1 N' W8 Y: N0 c; j
#pragma inline
$ e$ L  `: B5 O, t//---------------------------------------------------------------------------2 d+ H7 ^% t3 s; @( t
// IDE NT/2000/XP专用变量
; X. j9 J! u: n% `! m7 X! U+ T#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
9 E3 K4 L7 h" G. }8 e. n3 G. K$ Y#define DFP_GET_VERSION         SMART_GET_VERSION
# Y2 E. k$ A$ D+ Q+ |3 l7 u#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND/ L6 c5 P+ ^3 T  e' ~
#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA: ^! L, c7 S, y+ V" `4 B/ X
4 \/ |* f( h- I- }9 B
const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令
0 y2 B2 `! e% A/ h2 v9 A! k; rconst WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令; J# l4 M  x& f* i7 [

0 `/ `! L/ A% J4 G1 v/ X; A. [% |const int MAX_IDE_DRIVES = 4;1 g) x. |( W# i5 K$ R0 A
1 M8 o4 `( q9 {( ^6 j/ k; Q! {
// SCSI专用变量4 n& f& M! h4 k0 F$ [5 |, j/ F
const DWORD FILE_DEVICE_SCSI             = 0x0000001B;
( c8 z2 d; v' w! J! m/ U# b0 mconst DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);( Y+ h, H4 \" l8 c3 U+ M
const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition  D: i  z% J2 i
const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
7 J$ f, E( I! p7 H8 }9 [! `8 p* j
' @! u$ U8 ~5 P6 ^5 E" D2 c  G3 gtypedef struct _SRB_IO_CONTROL4 }  G2 |$ z3 L
{
4 s! L# _" Q2 a; U    ULONG HeaderLength;
+ y  T  I! b5 s! ]1 F    UCHAR Signature[8];
. k0 M- g2 {  G7 D3 o# l    ULONG Timeout;
$ B9 t  I8 V: a2 O# v. p1 ]: `% W    ULONG ControlCode;
3 h. i" v% S' _4 ~, }    ULONG ReturnCode;4 o2 `/ R8 ]9 n" J/ Y1 l' A2 b8 o# `
   ULONG Length;
+ V8 D. N1 l- j, o}SRB_IO_CONTROL, *PSRB_IO_CONTROL;
. Y- m3 A& H1 L+ D$ H5 m- }" f
# j8 ?& q  E" \2 f9 C( t// 读取的主函数% M$ i, s: X7 A
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);6 i2 A9 n6 _& g, H# s

  G% t+ ?& u  A$ u; ]// 辅助函数( }6 G/ Q$ H! p" _4 ?/ j
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
- {9 e# Y. @; ?  D; ~9 M# g9 L4 T# V// NT/2000/XP函数
1 y: {2 U" R) k3 U" l( cvoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
+ e+ N& I/ f2 ?  ]bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
8 f# h! w1 X3 r, G5 M        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
/ v0 G  Z5 G/ B+ X! t8 S  M        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
9 f7 _, q+ K( c* d- E# d// Windows 9X函数: y, O/ `, a% u; Q
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);
- C9 O3 {5 V" p/ }- G2 G6 R/ {void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,3 j  }  C" o( g; x% k9 A: E" \
       BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);# A) e( D/ G2 y

4 D* [# B$ }7 W' n+ @// SCSI读取函数(for NT/2000/XP)% Y. E/ W! c  b! l1 w
String __fastcall ReadIDEDriveAsScsiDriveOnNT();
, ?: F% p' Z' P8 N5 |//---------------------------------------------------------------------------
4 t# L* ^* z8 E1 G' D  c// ReadPhysicalDrive
: t, c" t# |* c+ vvoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
4 ~# ]2 S' [/ o% r$ s. H+ b{; g7 N1 M' V2 }" |4 Z/ g
   switch(Win32Platform)) p; V) n7 m, \6 }: x0 n
   {
  C+ O" m6 F5 G( l- f        case VER_PLATFORM_WIN32_WINDOWS:
7 ]. y' I8 j7 {4 j. z            ReadPhysicalDriveOnW9X(pSerList, pModeList);
1 D% B+ j3 ~( F' C            break;
0 x- w" X) j: K        case VER_PLATFORM_WIN32_NT:' X( t' ^! t8 Q: u) H5 H4 Q
           ReadPhysicalDriveOnNT(pSerList, pModeList);( Z9 ~4 o; X" O# L. _' x
           break;
" `( I- S0 J, w7 ^; k        default:
* `8 A, \+ k* d* n/ O            break;$ k, S1 H( ?1 E4 `$ M' p% z
   }" C4 T) R/ A6 i( W' Z! X
}
8 H5 W7 p. l4 ~; E. \//---------------------------------------------------------------------------
7 A% a2 E/ ]( I& H0 M0 A// ConvertToString' p8 H! l7 W" G/ _5 g/ b: |: ?
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)' X- J7 F1 s4 {* B  X
{2 ?6 g, D' @: b9 k$ N$ J
   static char szResBuf[1024];
+ A% r4 ]# H7 Y3 h6 i" P: @    int nIndex = 0;
( c% m- k' N3 I/ U0 {6 e    int nPosition = 0;9 u- c4 ]% C; \
' P# G4 m# \7 |
   // Each integer has two characters stored in it backwards
) a* c) S6 t/ p/ g( n/ h1 \: G    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
9 Y! w. e/ D6 l0 ?* `9 x    {
# b7 D+ N2 K1 Y; L3 y+ \        // Get high BYTE for 1st character
* d$ d% X# S& F( z$ b. b        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);" l2 v$ q' h- O# Q5 p2 c* q
       nPosition++;
) k2 p! s$ k, R: n) a* p
  Y7 S5 p# K4 j( x        // Get low BYTE for 2nd character8 N+ S. o7 G' O8 g3 \5 J
       szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);! y9 ?6 s; Z8 [0 h+ @3 ?9 g
       nPosition++;& Z' J2 `- D! U& t) w! r
   }$ N( r# Z8 ~3 A% O
* \8 U% _8 H9 X3 @, \3 A: {
   // End the string) |4 }* p' s3 i3 X3 l
   szResBuf[nPosition] = '\0';& z! T1 j: |! Z2 @
" }+ w' b' B7 T2 d
   // Cut off the trailing blanks
' Z' K# H1 S! I2 q    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--), X2 t) c) H: g3 V. y3 Z
       szResBuf[nIndex] = '\0';, T- O' a% g: q2 B
& ?' N0 N; K+ `/ E8 q% C
   return szResBuf;
( j4 {: J$ @6 ^4 C}
# {8 m! z+ {; S  `9 ~//---------------------------------------------------------------------------3 d8 K* J' }; ~0 y
// Winndows NT4/2000/XP 代码1 I  b, F9 I3 e9 W
//---------------------------------------------------------------------------( O2 W# q* v% @) e% J' e
// ReadPhysicalDriveOnNT
, H$ S- y, p8 h) ?/ Q# S5 ?void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
" Q( h9 ]; i8 f% U% `  y7 a{: A7 e. h) @* e7 D/ @0 X; ?3 C; f- F
   // 输出参数3 T5 W' [) s# ~/ X. J' k
   BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];+ l* w! h0 s+ u' }3 v
1 h. C! r! a! n2 P
   for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)- r  k% F0 C9 j7 Q0 }; j
   {& |, \5 ]" ^1 ]6 l
       HANDLE hPhysicalDriveIOCTL;& ]7 ?6 n; Z, P& a  p, [8 |" @
       char szDriveName[32];
1 b( a/ R0 L4 V. S: b
7 M3 r+ X9 m% a# q9 V3 h/ v        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);' U+ }4 o3 a* u: ?7 y
       hPhysicalDriveIOCTL = CreateFile(szDriveName,: E# I5 F8 y1 [0 |9 X- m
                       GENERIC_READ | GENERIC_WRITE,
2 D7 L4 t/ p7 I) E4 d                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
: y6 w, l8 ~+ B6 V/ o                        OPEN_EXISTING, 0, NULL);
. C! P4 v; G* A! U; @0 @: b6 g! i  y$ I# C6 {
       if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
* `( Y7 P9 l8 v1 |        {
! m: i8 c7 ^$ t: ]            DWORD dwBytesReturned = 0;
! q7 k9 q5 `. X            GETVERSIONOUTPARAMS gvopVersionParams;" S+ A4 b7 _/ R% E0 d* M) e

& u4 ?$ M; e( g. m# X+ z            // Get the version, etc of PhysicalDrive IOCTL7 k- K6 s4 w" U' I
           ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
5 t- z- P% ^# a4 c9 @5 g  ]6 S
9 y- @  I9 G8 P            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,# Z8 ^+ I7 T* n3 Z+ v1 X8 R
                   NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),& T- [9 ?3 ~. m. e3 |
                   &dwBytesReturned, NULL))1 g3 ^5 ^+ _5 ~% {) S4 [" y
           {1 `+ J) _# h( a( F7 G
               continue;! N8 [3 v3 C/ N% h  u% M1 Y+ T$ n
           }8 i, W/ n( \: a2 r: g8 N# G
+ P2 r5 `1 {2 m
           if(gvopVersionParams.bIDEDeviceMap > 0)
) e* r/ ?, A8 `" w, v3 M* ~- L            {
6 ^0 ^8 v  m/ i                // IDE or ATAPI IDENTIFY cmd3 j# F. t# }* }1 K3 O
               BYTE btIDCmd = 0;
( F  _8 F6 N" H% i                SENDCMDINPARAMS InParams;3 z' T, |+ ~. V* ^0 j/ E$ a* R: N3 ]
               // Now, get the ID sector for all IDE devices in the system.
. ]& Z% u+ c7 X7 v. P                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,, e. z: r6 Y6 u1 D
               // otherwise use the IDE_ATA_IDENTIFY command
" m$ q4 V; e# `( K# c. k                // 具体所得结果请参考头文件中的说明
+ R3 s& _/ V0 y$ b: c                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?  _# w8 j1 o: R0 Y9 U
                       IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
6 g3 S+ i/ P' D) V# m( [                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));/ k7 ?% Y" k. q6 h+ r# T3 x- k
               ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
0 c$ n* j' w* F+ {! E' e+ Y. f* R
               if(DoIdentify(hPhysicalDriveIOCTL,
- a7 W' p+ b4 m! C                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,* C9 [! t8 w# M( `& v$ _; ]& b
                    (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))% Z8 ?8 m4 d6 c* G
               {
6 p6 F3 i5 `% o1 v" Q7 s: d0 |                    DWORD dwDiskData[256];' P+ e2 ]# y: ?- Q0 ?& g
                   USHORT *pIDSector; // 对应结构IDSECTOR,见头文件: d* W  |$ w6 ]4 K; D
                   char szSerialNumber[21];" W7 Z0 Y: ^% o* E' I" S
                   char szModelNumber[41];3 j( f2 L7 P: o
  W6 `% \- y$ m7 d
                   pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;6 H+ ?1 T4 ^4 j+ l3 D
                   for(int i=0; i < 256; i++)$ c; N6 x3 |" x3 I
                       dwDiskData = pIDSector;3 f8 W* N, h: j' o: C
                   // 取系列号
1 Q6 ^: Z: x) o                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));+ p! z; g0 d5 s1 W1 D
                   strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
  j& o' O# G  {, J. ~4 ^" n; ^, L- R+ A, Q+ {# r
                   // 取模型号
8 v& v% l6 j. A$ I% F1 W) k                    ZeroMemory(szModelNumber, sizeof(szModelNumber));. `' o2 X4 D) C+ y5 Y
                   strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
. N8 I4 p! f- M! V- h
8 `7 J, f1 l0 C( `, y8 _5 K                    pSerList->Add(szSerialNumber);) p% Q! A: ?2 P+ z( Y
                   pModeList->Add(szModelNumber);3 l; G7 K: ^0 M. U* w' l
               }0 F3 x  X" o" S
           }
3 r0 z: c3 e9 r8 j            CloseHandle (hPhysicalDriveIOCTL);
( L& r/ M! @" ~        }4 ^) I" O* G: p  X# A
   }9 y7 s3 n8 R( L. c$ k# Z
}
. J% C( n& b/ i9 [! j6 l//---------------------------------------------------------------------------
& Q5 I4 z! Z9 y( D/ q+ z  Z2 {0 ^// DoIdentify
8 q: J7 N' L6 h- ?$ Hbool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,: S: s. r4 D7 U  X
             PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
7 ?: J2 Y" R- H. V1 i: r  l              PDWORD pdwBytesReturned), O8 n% h8 Q* B$ n2 @  [5 P
{) S: E: I; p! ~9 a/ m9 X% p& p
   // Set up data structures for IDENTIFY command.' l( k' Z1 p8 I! j; n3 q
   pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;3 j# e5 H$ q( \6 ^* q
   pSCIP->irDriveRegs.bFeaturesReg = 0;
( a! U& O; ~, C! Q+ ?    pSCIP->irDriveRegs.bSectorCountReg  = 1;
! M3 x. ~6 @6 q1 t5 P8 J" ~5 l- k2 j0 ~    pSCIP->irDriveRegs.bSectorNumberReg = 1;) x0 \! s% ~9 R6 D* n( I
   pSCIP->irDriveRegs.bCylLowReg  = 0;
* I* Z6 ?: \% h  J, Y4 s    pSCIP->irDriveRegs.bCylHighReg = 0;
( G& h0 q6 ]; `5 v: d: K# L9 a; I, ]! l# {1 i
   // Compute the drive number.(主盘和从盘所对应的值是不一样的)6 t& V1 n6 p! q) h
   pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;: v$ i3 U$ F* }, b9 s4 C0 H: [

* O* O: M% T' U+ g    // The command can either be IDE identify or ATAPI identify.
3 P2 h6 g; t4 ^! k$ g1 B- C    pSCIP->irDriveRegs.bCommandReg = btIDCmd;7 `4 C, I7 q, R
   pSCIP->bDriveNumber = btDriveNum;7 i9 v! |/ b$ \' r
   pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
8 \) i: h8 R! d0 n2 w8 [7 h+ \' ?0 U
   return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
! V2 X+ S/ O  v( S7 e           (LPVOID)pSCIP,+ P# C8 N& t% p. R! w
          sizeof(SENDCMDINPARAMS) - 1,
& D8 P9 r+ U! R/ K' J           (LPVOID)pSCOP,; b1 [8 x! Z- f- g- R6 D2 [
          sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
& I0 q( w/ h6 R           pdwBytesReturned, NULL);
& |, P3 Q2 t* W- M& j- M}* u; i; n$ W5 w. u) ~
//---------------------------------------------------------------------------) i! {* Q" K9 z& J
// Windows 95/98/ME 代码( i# J* ]2 R& \: v. a9 A8 U
//---------------------------------------------------------------------------
* |% v% h8 x" r: p8 K// ReadPhysicalDriveOnW9X( Z* H/ S  O2 H& u
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)4 E6 I7 X+ f* C+ B) _2 U
{
; l+ @( Y! W5 {: _8 ?" B    WORD wOutData[256];/ ?+ |" E  q) {2 O/ R. u
   SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);6 v: H7 |8 M9 c) v+ A8 c# i- ~
) O. K* c! S' A- J  j. M% l
   // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。4 m) f; d2 W- L9 C
   // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以+ M& Y; y7 F, L+ g  |
   // 避免蓝屏的出现。(期待高人能指出原因)" }1 @. u# j) x- B* V
   for(int nDrive = 0; nDrive < 8; nDrive++)
- Z8 O! S4 O, Z9 `    {/ l6 R; _' {+ Z- y
       WORD dwBaseAddress;! H8 A6 v" `' Q) c3 \
       BYTE btMasterSlave;         // Master Or Slave
1 z9 @4 S: C0 b6 x        bool bIsIDEExist;; i0 M' Y2 ?& l/ Q* R8 G
       bool IsDiskExist;+ k( |7 Q3 l+ K

1 E8 l( B: H( _( V1 [/ s# W0 e        switch(nDrive / 2)
& a6 x. m0 x: Y& t  C1 F. Z1 }4 N        {
9 L$ W; Y) \, [' ^+ ^5 B. L            case 0: dwBaseAddress = 0x01F0; break;5 r2 {5 d; I0 W  d/ O( @
           case 1: dwBaseAddress = 0x0170; break;
8 X; w4 ?5 @* J1 n9 R3 B! ?, n' E+ `            case 2: dwBaseAddress = 0x01E8; break;
; Z, o  c" u# G; N3 G            case 3: dwBaseAddress = 0x0168; break;
( G" ?* d5 Y7 h* g" ]3 p# n        }
& |1 i, v" ?$ \( S: g/ {, `& Y6 P  z' h! s1 K
       btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
2 u9 w* _9 W5 `) X5 R  H2 `' |: d0 R8 W* C. L5 r0 |/ h
       // 进入Ring0
  J) J3 f0 u5 c/ C        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,+ O6 V5 @& ?" [0 m
               bIsIDEExist, IsDiskExist, wOutData);
/ S7 r7 H% ^0 k9 ~    }1 u: }. \* z  O  E, u0 `2 A
  Y+ P& S7 ?# H* v7 K
   // 开始读取8 [/ v$ U: Z/ N( T9 s1 ?
   for(int nDrive = 0; nDrive < 8; nDrive++)
1 {# |5 U( K7 ?& ~' y  }    {$ T3 {8 G7 O: Q" Q! V# e. c
       WORD dwBaseAddress;# b% Y6 X4 K: j+ H
       BYTE btMasterSlave;         // Master Or Slave7 p5 `7 ]" j- a- j
       bool bIsIDEExist;+ r* v4 A! c3 {
       bool bIsDiskExist;
2 c4 F. [; C5 p/ D1 K        switch(nDrive / 2)
! C# h5 N5 T, l        {( ]; F/ b$ `, y0 h
           case 0: dwBaseAddress = 0x01F0; break;
1 z& ]3 S. J, i* \, k9 V            case 1: dwBaseAddress = 0x0170; break;
! M+ c2 j" W4 F" a! _            case 2: dwBaseAddress = 0x01E8; break;$ ~2 c# p  i( I. _
           case 3: dwBaseAddress = 0x0168; break;3 e$ a' z) |: \/ W5 F
       }
+ L5 w, f2 b7 m5 P. E" T/ }7 R8 L9 c6 ?* u8 j4 ]( _: P% X; x; d
       btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);7 u6 E% D: ?3 k% F% ?5 O

% r8 N7 c8 |  i  j1 }        // 进入Ring0
9 [6 L. D9 A/ \: ]$ D& Q! ?) S* H        bIsIDEExist  = false;
+ @$ u4 O1 m' F" _4 F/ Z        bIsDiskExist = false;# w3 l! ?+ A4 `
       ZeroMemory(wOutData, sizeof(wOutData));
! R" W  ?, f# n# m, h
/ P  h" N$ c- N2 G# e, ]        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
% y+ n1 j; c9 z- g3 S  c7 Y6 s  C, g# U                bIsIDEExist, bIsDiskExist, wOutData);
, j) C5 V3 f9 ?% x! e' I- ]/ x# l2 C0 }( l
       if(bIsIDEExist && bIsDiskExist); F& [. p& s' ?' u% p/ O- K
       {& N3 u) \1 m  j4 T6 O
           DWORD dwDiskData[256];
6 d* s6 {* J. w) u9 A            char  szSerialNumber[21];* H; H; X- I9 o4 {5 P6 i
           char  szModelNumber[41];
% ]8 O& t/ {( ^' F+ Z9 H. [! {+ u& N- S4 @
           for(int k=0; k < 256; k++)) N' }: S: _0 L
               dwDiskData[k] = wOutData[k];
+ Z: D0 b. i5 N2 _% S0 F+ L# q' A( V4 n6 u
           // 取系列号
0 N" P5 i3 T# f$ r* R            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
" j: m9 u" W0 h7 X& b2 W# Q+ i            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
8 B  e7 Q' v' M9 @: I( M7 z
! s5 o6 |# l5 C% w            // 取模型号: W% `/ X! B; [: Y
           ZeroMemory(szModelNumber, sizeof(szModelNumber));2 S/ j9 [1 ]- M- }8 R& e
           strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));9 U& N, D  F8 y
. m* b) c" ^: |! i1 G- E
           pSerList->Add(szSerialNumber);1 f; Q* q/ o! O+ M0 ~( }9 [
           pModeList->Add(szModelNumber);0 U4 V3 w, _/ m: U( ^% s5 \
       }) j: |6 f) y4 ?6 j+ `1 F
   }
( m! b6 t/ g. d5 o    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
& o+ q5 X) }+ M6 p. Q5 B$ W}
  m! `, K5 n7 V: y1 d, {. n1 l//---------------------------------------------------------------------------
8 l1 S1 C% K- |7 C4 |+ i// ReadPhysicalDriveOnW9X_Ring0()
, U/ Q6 r1 S' |" [$ K9 ]) a//
5 m" y( a! {: c4 t7 |: o// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
* r1 _: \# x; h& l// btMasterSlave = Master(0xA0) Or Slave(0xB0)
* t- s) m0 A( S6 k! h1 H: Y//---------------------------------------------------------------------------
6 ^% w: M  R8 v, C+ y5 }6 mvoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,, m# I1 q1 O% b+ R4 d/ ^
       BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
( m4 C& H: G' j& y% W! F  y: f{. _1 r  ]9 y4 y9 ]% Y/ ~- w% D! q
   BYTE  btIDTR1[6];. _0 [- Q/ ?' W5 v2 S
   DWORD dwOldExceptionHook;: H$ C2 ~5 K2 d- a
   const int nHookExceptionNo = 5;% l$ d2 w  r( n

: U- R/ g5 X2 h+ u9 t    BYTE  btIsIDEExist = 0;/ ?. ~, G6 {' @& f
   BYTE  btIsDiskExist = 0;: n( R0 o, `9 ?
   WORD  wOutDataBuf[256];
; T  T6 x) m9 n9 t2 U. C4 ^
0 G5 l! e3 F" d3 R- \# b    BYTE  btIsFirst = (BYTE)bIsFirst;
/ A* `! N5 K' V! n9 e
. y0 _) k( z; R; O$ C; g0 X    const BYTE btBit00 = 0x01;
& s. x; c; N9 }5 ?    // const BYTE btBit02 = 0x04;
# y9 D# O# @5 f1 v9 Z* x    const BYTE btBit06 = 0x40;
/ |* Y; X/ `% [9 ~    const BYTE btBit07 = 0x80;% f9 u) o2 m- R4 |! V
   // const BYTE btERR  = btBit00;
8 f* e1 g% f0 H+ r0 ~9 }    const BYTE btBusy = btBit07;2 c; `3 n4 f# ~
   const BYTE btAtaCmd   = 0xEC;4 O2 o9 x( F, m6 i4 q/ Q# t3 |
   const BYTE btAtapiCmd = 0xA1;
0 z& O; O. w/ _# U1 L! ^
# Y$ l6 [' [8 b4 Y! x2 F: e    __asm) Y% G# a* o* p* n$ l: l
   {' L2 @1 b' n2 E$ B
       // 必须先执行这条语句
' H1 N0 H( L- V# S$ ?  l        JMP EnterRing0! w! d& Y* \0 F* c+ O7 o

; z, q$ {9 E$ O- T! {1 e, R1 {6 a        // 定义过程
5 ~* U' k% H+ Q" S3 T* n5 t+ |        // 等待IDE设备直到其不为忙为止8 n7 K) R2 T4 A  E0 C" I$ A
       WaitWhileBusy proc
- [% U2 Z  `. O" ]- j
& {, C* e% [, ~) ~) I        MOV  EBX, 100000/ @& }, \0 e! O! v0 O! y
       MOV  DX, dwBaseAddress" T  p4 J) p* J6 l2 O& O# w
       ADD  DX, 7, Y' `7 P% d0 v% Y, G9 L$ O" p& K

: |* J. ^, G0 ~! V; \' A        LoopWhileBusy:
" u1 b5 m" D0 l+ c3 n% Q  I8 A1 p- t1 X' V
       DEC  EBX
6 @2 h" V5 X% i: Q; s. U! b; i        CMP  EBX, 00 p, G. u# m( k" P% ?8 i
       JZ   Timeout
' C4 B% f3 [, R7 H3 @" c        in   AL, DX: m, }( \1 u8 @6 e+ I" r- m1 i
       TEST AL, btBusy
2 J" C% V4 B6 B        JNZ  LoopWhileBusy
+ j- |! |5 v$ F6 h6 L        JMP  DriveReady
/ v2 A% r2 L+ w" K, j* D8 A/ N
! M- |9 U/ t1 N) s        // 超时,直接退出' p0 n' e# g& S/ y* G. T6 g7 y$ A
       Timeout:, l: W  o$ W, F  ~2 w8 t  y
       JMP  LeaveRing0
& a! D6 l& V7 w; B        DriveReady:
2 k, O9 l7 K* C6 j/ c        RET. s" h; w. {% Q6 i
       ENDP   // End of WaitWhileBusy Procedure
; \6 Z- a- N9 C- `; P/ k/ D* a$ D7 x4 s1 K5 @5 u
       // 设置主盘和从盘标志: m  B$ ]8 _5 S" W; @6 s4 J
       SelectDevice proc1 V% P$ Q  W" M1 S) R/ c4 u
0 y6 d# i; W% ]+ q3 f( ]$ O
       MOV  DX, dwBaseAddress
; x2 G+ q* ^: L( C: Q. w  s9 Q, v        ADD  DX, 61 s- i' `7 \5 S5 ^  P
       MOV  AL, btMasterSlave0 }, ]0 R! j1 N: M" c& v+ h
; u) ]  ~3 ~7 ^# {7 D
       out  DX, AL. @0 a) s# ?/ J
       RET& f4 ^% ~+ g# n' Z3 O
0 v1 W, h4 R: z/ |1 F8 Y
       ENDP  // End of SelectDevice Procedure4 N9 J) K7 w2 |+ E7 [8 ?

3 t! I, {: |5 e/ |2 R0 L  r2 f7 e        // 向IDE设备发送存取指令
3 ~) R, B! p+ O; o# y        SendCmd proc" m! u6 @: c& v( q" z

' P1 n- n' A- h- X" \) L; }5 n        MOV DX, dwBaseAddress
$ M, W0 a  b& I" d' x3 S        ADD DX, 7
, O" o8 b7 j- M4 B/ n0 D        MOV AL, BL // BL是主从盘标识,在过程外设置
$ O8 u+ d9 q% E; ^6 K$ g) |        out DX, AL
- L3 X: b1 {1 T9 `) O6 N" Q        RET2 R# H, N. k" W* W- Y2 R5 b* O
       ENDP  // End of SendCmd Procedure' _" ]# F  N- \1 A  {) n- y

1 G6 g9 K1 v; V/ r, ]        // Ring0代码
. s$ ^. C9 G# N: M9 m: X! l8 W        Ring0Proc:
  N4 k  c) c3 ]  g" M) l        PUSHAD
" I1 I- W$ P. v& M( Z( r5 X! L        // 查询IDE设备是否存在
: y9 c  ?- z2 s6 g        MOV DX, dwBaseAddress$ A4 A# b% n6 c* T) L; X
       ADD DX, 7& F8 y1 Z5 g( N5 m3 u- T. u* y  r& b
       in  AL,DX
; B: [; j  `4 {; i+ e1 F" @" z( ]+ T- t* L3 n  T
       // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
; l' b& D; Q0 u- G        CMP AL,0xFF/ p) j& Z2 \5 S) c# G. a' Y6 A
       JZ  LeaveRing0
; D$ H2 I7 M1 W& k; j        CMP AL, 0x7F$ R! F7 }" _+ F7 M+ q; Q. L9 Y8 d
       JZ  LeaveRing0
( F( G  {+ H2 j  p$ C4 T$ u2 W- K5 |4 |6 U' `# r1 e- s% e5 L3 G1 @
       // 设置IDE设备存在标志
+ H/ _2 {1 |3 o        MOV btIsIDEExist, 1  I* f. M! ]* |' }* I
! R6 {* a( `5 R7 s3 n, E; _
       // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
, I3 {# k, Z5 {; y        CALL WaitWhileBusy4 m4 }6 }6 b% T3 M8 Q) O
       CALL SelectDevice
' f/ s$ x4 d4 z3 T. O2 }  J" X7 _) z9 K2 o$ o
       // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏6 H6 c2 o) Y! b- C
       CMP  btIsFirst, 1
6 _9 e9 w2 r& |0 _        JZ   LeaveRing0
* d; p1 }  ]3 B; r% o! M6 X
2 A3 V. y3 w( J3 Y: ~        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
- Z6 Q! S' |, \+ e( v        CALL WaitWhileBusy
) u5 X, I) Q  A
, O- _- {0 F% Y6 l5 T        // AL的值等于cBit06时,不存在驱动器,直接返回
6 A! e4 W4 ]9 Y+ {) U        TEST AL, btBit06
# m% U, Y; U1 j/ x6 T( q$ }4 B1 Q        JZ   LeaveRing0
. [+ a/ n% r4 l4 o. _; Z* \. Z* z3 J9 A. _
       // 设置驱动器存在标志
( E! o7 G: a# b# Y% E$ }& e        MOV  btIsDiskExist, 1- ?' Y8 ?$ q! m6 M* I, W1 O

0 b1 R) n0 w+ t7 I9 D1 [) h, }1 F        // 发送存取端口命令
) F: L7 ^( ]) u- Z7 ]2 ?5 x& M        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
* @+ j9 P( }5 v' v        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令, K$ W1 B8 p) m  a9 u- N8 r% d
       CALL WaitWhileBusy8 r# X' \$ p" v2 f  N1 p8 d+ N8 z
       CALL SelectDevice    // 设置主从盘标识( J) @9 L4 J1 m! a5 c9 T
       MOV  BL, btAtaCmd      // 发送读取命令' {) T- x: ~/ T* F
       CALL SendCmd
) |& u$ a; T. a& W: {' e        CALL WaitWhileBusy0 |3 N4 d, C* M" ~6 }: o- a2 q1 n

$ w# a% m2 O0 c/ t( M        // 检查是否出错  a$ t; C9 R. j' ~& z
       MOV  DX, dwBaseAddress
# M& ^8 ~: d: ^7 k# F        ADD  DX, 7
1 |3 t( E$ d) I
, B5 V% O: C0 G" V6 m0 {        in   AL, DX% {7 ^3 H( K/ c
: K' g& s5 d. ?& O
       TEST AL, btBit007 e; j% [! Y" q+ e
       JZ   RetrieveInfo   // 没有错误时则读数据, P/ F6 c+ d. V$ G

' n# i. |' T, F1 C* S  F' A. f        // 如果出错,则进一步尝试使用ATAPI设备命令
- A% A" I/ a. |* I3 A        CALL WaitWhileBusy
) ^. y" ^( K0 j0 G0 G' o2 d# A        CALL SelectDevice
7 F& X" E, n' o7 N9 o+ R# i7 r5 l% x        MOV  BL, btAtapiCmd. |& y0 E$ m4 F+ s% n
       CALL SendCmd8 T8 Y& D' x# p  ~( l  `
       CALL WaitWhileBusy0 T- j2 G% l% @' f- Y
" g; ]7 X/ V- ~  R* d2 l9 _
       // 检查是否还出错: d/ T4 S) v% ?+ Q; O
       MOV  DX, dwBaseAddress) z0 s* V- n/ f* P/ Z
       ADD  DX, 7* C9 X9 G% s; G1 D: [
       in   AL, DX) P* l+ i0 Q  {! r* T% o6 P
       TEST AL, btBit006 m7 }0 c: z# h* T% r+ k( c3 H: v
       JZ   RetrieveInfo   // 没有错误时则读数据
* F$ y" V/ m7 K8 R8 Q        JMP  LeaveRing0     // 如果还是出错,直接返回
' H! a3 A9 L9 J1 [' f0 p8 W$ Q5 P; ~( r( U3 N0 S0 i, ~
       // 读取数据/ G% O, f0 S3 H- `8 |, b( c6 i
       RetrieveInfo:
1 J+ x! A+ I4 E; O. ]& E% {5 |. h' g+ _9 H' [
       LEA  EDI, wOutDataBuf
/ s# |4 z! G3 }% A! n. Q2 z! Y' h        MOV  ECX, 256. Z4 L1 d9 a* w$ ^4 d# `+ |) ]
       MOV  DX, dwBaseAddress  H1 ]# u8 b! W$ _8 `; s9 {' @
       CLD
" s  }! V! O3 {: C( n6 c  n
3 {4 T1 H0 y$ I& s, ^# \        REP  INSW/ b' Q9 f+ @8 Q

/ M5 |7 p* l- d0 B  R* x4 ~: ?# V        // 退出Ring0代码$ w- _& q! o- K( B7 R
       LeaveRing0:: J+ d; s7 @- w) c" T

6 K  _+ [5 [, M' b5 _8 D! i( ^        POPAD! ^) ?2 g& N8 o% m1 E* ~4 a9 e
       IRETD% H  V% D; S  ?$ r1 J: C" `; `

  v$ Y% z+ y" E# B- |# ]( V/ [, N        // 激活Ring0代码
, C. H8 \% g" _        EnterRing0:
0 V4 \" Y" q9 j& O5 i
' w7 D8 f1 z2 I8 w        // 修改中断门
6 k) R! m) g1 F        SIDT FWORD PTR btIDTR1
( |6 b9 ?- d9 k/ ^; j) ?: P        MOV EAX, DWORD PTR btIDTR1 + 02h* _8 i1 ^0 C0 ~* b$ P& d- H
       ADD EAX, nHookExceptionNo * 08h + 04h
: s3 K+ L) u; ]% }* L4 R! y: B. H        CLI
3 G1 l/ Q5 E7 m( L* K3 u
; q1 V3 _( e2 S1 [# Z, U        // 保存原异常处理例程入口
5 i  U! `% m9 p# }& `8 T+ z        MOV ECX, DWORD PTR [EAX]
3 ^; z2 s4 M3 l# K: Y/ j' n        MOV CX, WORD PTR [EAX-04h]1 j; u9 d4 r' K2 q. ?
       MOV dwOldExceptionHook, ECX
1 W7 `1 v" N. L8 D+ B4 W# P/ q
" r  i# v, e0 A6 p+ e$ l$ w        // 指定新入口
: c: H! k$ ?. I        LEA EBX, Ring0Proc% O! O- _& [9 \. C
       MOV WORD PTR [EAX-04h],BX
6 M2 U1 O. D& \0 s% e        SHR EBX, 10h
7 X" C8 D) x! a9 a        MOV WORD PTR[EAX+02h], BX6 K: f5 Z" _1 _/ Q. ?3 p# O: ]4 h2 P
) y# O3 O, d# z+ @# _% d/ a+ l
       // 激活Ring0代码2 O9 C# B% _% r) F
       INT nHookExceptionNo, H3 S! e- \/ R( G

3 a9 X& M" L1 o6 g2 L; l" t        // 复原入口0 A7 Q5 @/ u. s1 z% X: q
       MOV ECX,dwOldExceptionHook
6 z4 d$ Y, i# }3 e  C4 N        MOV WORD PTR[EAX-04h], CX6 N& D8 _/ l9 m" y
       SHR ECX,10h
. d! h0 e2 [# W, D% w" C        MOV WORD PTR[EAX+02h], CX
  Q* u; ]0 }7 m) O) M, I/ k# f        STI* ?  i0 S4 ?1 G5 L9 `
   }, F$ ?8 i% H9 ~# C
   if(!bIsFirst)
8 ?) ~% `- O0 h% |    {
+ Z5 c; d6 O( Z, }* k: H        bIsIDEExist  = (bool)btIsIDEExist;
1 Q: K7 {3 M0 d; w) Z" G! r* {. T        bIsDiskExist = (bool)btIsDiskExist;
: \# R7 Q( O$ B2 ~        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
& a0 M: s+ I  n! X, q" Z6 _, W    }" u/ W9 H- S4 S: p/ Z. z8 f4 E
}
9 d1 H) E8 H* F; s* _9 q& G5 e//---------------------------------------------------------------------------5 B' ^# z. T. y' E
// 调用方法:* F& g2 R/ [+ _7 K
void __fastcall TForm1::Button1Click(TObject *Sender)
3 }# ~' V) r* p/ G{
2 E" ^: M; W. p* Q" _    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
6 y# z. J2 u9 o3 C  p+ x5 S}
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-5-2 10:19 , Processed in 0.024384 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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