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

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

[复制链接]
发表于 2005-5-30 19:22:36 | 显示全部楼层 |阅读模式
  #include <WinIOCtl.h>
9 ]5 W# _) w2 @#include <stdio.h>2 ~3 l5 q( n$ ?
9 h* w! L' U+ v' z5 |9 y2 e
#pragma inline+ q+ |, f1 O( g4 z: l
//---------------------------------------------------------------------------
- w5 U" y9 @9 _! l8 A0 \// IDE NT/2000/XP专用变量
! A3 i) o2 @7 I  ~9 k" Y) Z4 Z5 J#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
. j! `  s6 g2 ^( C#define DFP_GET_VERSION         SMART_GET_VERSION, N6 @' F9 S# `
#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
- N* z" P( L& M; Q6 h1 _#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
1 T+ Y  \0 i. H" a- l! }6 F) V& G3 @$ n& e
const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令
& d+ |; Q2 w( oconst WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令2 y) ?  Q8 Q3 m  y, H$ c

6 O$ K  g/ `4 B8 G, {const int MAX_IDE_DRIVES = 4;
+ A, H9 B4 k& M9 V1 w" G) U
4 {9 t9 ?( q! r) Y0 w// SCSI专用变量
: |" D" \2 y# \const DWORD FILE_DEVICE_SCSI             = 0x0000001B;( ^  {- }, ^  ]* R+ k3 Z& Q" \$ U
const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
* B- V" W  t( B; u* i( v% C7 Pconst DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition0 l3 R+ t/ [* e) W5 f8 w. l
const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
* r9 @( b! T6 ]; K7 a' y$ P0 R# u3 c% J# [+ o; X
typedef struct _SRB_IO_CONTROL$ ?: u% J& y9 l5 C  C& b/ Q( p
{
# f+ z+ S) z2 w) S; _+ j& [    ULONG HeaderLength;
, M. I* X, r3 O/ X& x    UCHAR Signature[8];
% `: Z: R% R: k8 h    ULONG Timeout;
8 r1 t: i# q& R  |" l; y    ULONG ControlCode;
% \! o, R( E6 |0 O4 M    ULONG ReturnCode;
2 |4 p% V, b% |/ [. v* _+ |! L    ULONG Length;
8 O; M+ b8 K, {}SRB_IO_CONTROL, *PSRB_IO_CONTROL;" _; ^" X; m) \* p! ]- N# ^  e

, K4 E8 h& |8 Q$ d, Z8 _* r// 读取的主函数! U6 e' I) r, N6 \; h
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
4 m. R& i3 ]2 k$ C  Z. E. v0 W% a# Y+ f! {4 c
// 辅助函数
" Z" D- T! m/ ^( m$ w; E0 \" ^5 qchar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);7 C$ i8 N- ~+ k8 ^# f
// NT/2000/XP函数
* |) X/ i6 f$ x' @  s3 R: [void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
* q& _( X2 |+ gbool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,3 ?: ?. g: i: ~: v$ a  L$ |# t
       PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,* n5 S9 u; ~; ^& G  @6 \
       BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
* ?% Q  D. r2 V0 V// Windows 9X函数
$ w5 t' ]. K& ?- ?void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);
, \2 C- x6 p; J) E- [void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
4 M7 L' S% ]. N4 v( e        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
2 C/ K( R6 {. ]  i+ q& k
6 ^8 T9 _; R+ V( q! R// SCSI读取函数(for NT/2000/XP)
1 w% f: d- E. W. W; uString __fastcall ReadIDEDriveAsScsiDriveOnNT();# U/ V0 `+ ^' U
//---------------------------------------------------------------------------2 b$ d# f. E0 J7 }" q
// ReadPhysicalDrive
  v5 u5 \6 W1 @; h/ Y8 n/ b9 Ovoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
' T) E5 K9 u& @{6 `' ]. q4 ]  L- D( s
   switch(Win32Platform)
0 v/ N, }) f$ d: X, ]    {
3 ^+ Z+ G8 G/ R* J+ A5 ~        case VER_PLATFORM_WIN32_WINDOWS:3 o- u" z0 S7 m4 _
           ReadPhysicalDriveOnW9X(pSerList, pModeList);
1 E$ q! I5 c( n# ^  s) s' a            break;# q' x) {( V" Z' x; u" X$ D
       case VER_PLATFORM_WIN32_NT:8 M  x$ c# E: ^' V. I
           ReadPhysicalDriveOnNT(pSerList, pModeList);
4 S' U$ u# m( R/ h) A            break;
( X) J9 S$ r4 O- Z: V        default:
# H, {& R0 [5 u' O% U1 S            break;
: a) c3 a; F* |; x% V- _    }
: c# q  U1 [5 \}
8 |& J& z8 k5 s  |" F//---------------------------------------------------------------------------+ Y2 D' ~" L* t0 k7 f, l
// ConvertToString" E/ ]3 I( j# C- G; G; ~) I
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)* z: r5 x  n; Y+ S, k% l) ]
{
8 W+ i2 f% M: e9 Y: @: A( N    static char szResBuf[1024];6 R) a* Q# C% K
   int nIndex = 0;
$ K0 e, x7 t( s3 t' u! f% @0 W7 s    int nPosition = 0;, _/ J1 H  X1 J0 Y
8 H* I3 I* \% N2 Y, z' v
   // Each integer has two characters stored in it backwards
3 o7 Y0 x; X) F; {# k- n. s( {    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
+ a2 B: @7 x4 o    {' Y# x5 }* @( n
       // Get high BYTE for 1st character: F1 S/ J$ W+ T2 ~
       szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
  w$ l4 e: l$ |3 g        nPosition++;$ f, p8 Z! b& r1 w
! M) v" \: j% Z( f6 w1 o
       // Get low BYTE for 2nd character" g3 k+ j. q% d& P% v, X1 q0 C9 @8 w
       szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
& G( b' p# B# d( e" p! s* y. U        nPosition++;% l' q% ^. _; s; Z8 m% [/ W  z! G
   }
  }) ?- ^) \9 M& Z- P  X  J4 w3 K
2 \2 n. H( \0 H    // End the string
$ d: l& q* \) Q% A: N4 @4 C4 E    szResBuf[nPosition] = '\0';
9 {7 t, v7 l* F6 u1 I* @! c0 g7 M/ F" z4 S% M
   // Cut off the trailing blanks" v# _7 I/ O( `% l; k5 ~4 B
   for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)- Z6 E) {8 D4 H) [- o& B9 I/ d* v% ^
       szResBuf[nIndex] = '\0';
6 W) b/ O, H- b( M  D/ D
6 `. g  d9 \# g& K% ~! Y    return szResBuf;8 z  u" C; r. ]$ h( P" ~) l
}
4 W: X# e2 y7 C+ R) \8 Z//---------------------------------------------------------------------------
) I: ^7 ^% P) ]' U7 ~$ R$ B// Winndows NT4/2000/XP 代码
3 G" ^2 A0 |# `5 d//---------------------------------------------------------------------------# J$ N/ l  j) d- N+ M
// ReadPhysicalDriveOnNT  m4 S  D- O! S& ~, p) V2 r
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
+ r# m) s5 F/ t" C' ]4 c+ m! K. v{: D6 Y8 l& C; d# N" t
   // 输出参数9 i/ ?  v1 L% x+ \
   BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];0 b; i; {& x8 [5 u, C

1 v( v6 h( f6 s% s    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
  o1 _+ h) F) \* P! e- I    {! s. z: ?3 M$ u7 A/ J
       HANDLE hPhysicalDriveIOCTL;
! {  d/ T; X* e& z2 M7 o2 X        char szDriveName[32];
# J4 `+ Q- x" |
0 Y5 Q9 P$ M- T" o0 B( w( O        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
2 s8 G" K- Y( Z9 _2 A, a        hPhysicalDriveIOCTL = CreateFile(szDriveName,
) I7 \: Q: ^' J5 c4 O1 y, a                        GENERIC_READ | GENERIC_WRITE,, O! j1 Q( B# u3 u
                       FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
* j+ [  s7 \5 o7 t( v                        OPEN_EXISTING, 0, NULL);) h+ z' _0 z8 L" ]7 P7 B1 W

# q4 P6 m6 S0 a8 R% M( w) g& x7 T        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
, O% z4 r' K, g; h$ X# w        {
) r6 [% ~6 L4 O. N  z; u: M            DWORD dwBytesReturned = 0;
7 W) y- W& z8 B2 W            GETVERSIONOUTPARAMS gvopVersionParams;
1 `/ s0 w  k2 y& l. T' F) S
, K/ F) {4 ~8 f' f            // Get the version, etc of PhysicalDrive IOCTL
6 b% z  [2 c, X$ ^) Z$ ^! q            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
: f# g" i8 W7 a( h& `
# p/ T' a' s, E$ F3 q8 O) H% V            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,  C# b- h* i* S! _1 Q6 W
                   NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),& [% E- T5 M0 X6 Q
                   &dwBytesReturned, NULL))! e8 c& A' q4 G
           {
4 d3 m" E4 a3 r: t" M/ X                continue;) w3 A* `2 k8 r3 Y1 f2 [2 u& I
           }
5 [! s' u. N) b- L, k6 n% I6 L: y: V  L2 [# v6 @4 R, D
           if(gvopVersionParams.bIDEDeviceMap > 0)$ t, G  q  I8 M* C) {# ?/ v- B
           {
9 _# N( `8 v: L) }                // IDE or ATAPI IDENTIFY cmd
' H; g, a( n3 |+ Z* W                BYTE btIDCmd = 0;
) E2 g" O* E2 ^) o8 a                SENDCMDINPARAMS InParams;
' l; S+ e6 i* U                // Now, get the ID sector for all IDE devices in the system.
' H0 G% z/ U, O! v                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
2 f. \/ y! {! L( u  z+ V                // otherwise use the IDE_ATA_IDENTIFY command  I5 l$ T; ^  x, \; ?
               // 具体所得结果请参考头文件中的说明! o2 _4 O: V0 r
               btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?3 z, {# D2 L+ G* y2 t, x5 ?/ _
                       IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;# b# M% f8 z8 }" w
               ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
' k! Z$ ~" |/ d$ g                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));& Y: H1 Q0 b$ e5 v4 s) t- A
' ^) H3 s: Y7 }
               if(DoIdentify(hPhysicalDriveIOCTL,$ f' y  ?% d# @% n) `, W
                    &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
5 ]6 {% W9 O6 A                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
" a2 V; L4 }0 w                {2 C! {1 e8 p* R" a! l5 n8 B" H( ~6 Z
                   DWORD dwDiskData[256];
. V, f* K; t1 U1 }1 p1 h" G( h! ?                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
: W0 }- F( R2 l* g" G& _                    char szSerialNumber[21];
2 w% j# M  I: V                    char szModelNumber[41];6 u6 E, @# o, p+ G0 }4 M
3 D9 X- z/ V  D) U6 w! K' T) v
                   pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;& |) F! ]& O5 l5 D- b
                   for(int i=0; i < 256; i++)
9 G! V9 G) p$ ~                        dwDiskData = pIDSector;
; o, v: P$ N, T$ n3 S& \* o7 ^                    // 取系列号- I: `5 Q" `7 D2 `& d
                   ZeroMemory(szSerialNumber, sizeof(szSerialNumber));) I) d% f. @  P! m& e' Y
                   strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));% f5 l* Y4 |: n3 n
8 s  z5 G4 a6 F
                   // 取模型号; H6 x) C) Y2 I6 d5 ~0 p. j
                   ZeroMemory(szModelNumber, sizeof(szModelNumber));
! r9 e6 ^0 _2 R0 Y! K  [                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
+ z0 z6 J7 ]2 }! f9 o: S  c
2 k# p0 h. ^) I                    pSerList->Add(szSerialNumber);5 i, ^8 N& \# P: f1 X: O
                   pModeList->Add(szModelNumber);( f4 q4 O  ~- ^7 F' c1 O
               }5 n: d/ Y# |/ S# F7 V
           }
6 K, Y" s2 S) x            CloseHandle (hPhysicalDriveIOCTL);
7 Q+ K9 I$ b, l9 Z! H. _2 t        }( y0 `0 U4 j0 F5 A  k9 ^. a
   }
9 s# }; |( R0 _) V+ Q9 l% t}
! L2 H) [+ d4 S/ g0 |//---------------------------------------------------------------------------' w/ K; ^- J7 w
// DoIdentify
+ L/ c) H* W) h7 abool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,* C, j3 z$ [+ T
             PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
. d( E6 p" S% `. X$ \0 E              PDWORD pdwBytesReturned)
" T$ I5 ~, Y% V{
; E0 p3 K  Z- H! ]) R( W6 e3 F: c    // Set up data structures for IDENTIFY command.; R2 G( d* u3 W2 ]3 K
   pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
, g) ^% A( V$ [" a: H    pSCIP->irDriveRegs.bFeaturesReg = 0;
# J8 T; g6 R7 W$ G; u; {' Z" i    pSCIP->irDriveRegs.bSectorCountReg  = 1;3 t5 q, d# u  A* i( x  v
   pSCIP->irDriveRegs.bSectorNumberReg = 1;
, h) K. X+ W1 P( _9 K! Y! o    pSCIP->irDriveRegs.bCylLowReg  = 0;
2 K7 S  \' {0 c    pSCIP->irDriveRegs.bCylHighReg = 0;9 [8 P1 d; A& _

9 Y  v. ]' Q8 O! P8 F7 p8 N* o2 o    // Compute the drive number.(主盘和从盘所对应的值是不一样的)
% J$ |9 S3 K  X$ ]& i0 K# m# ]    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
; l0 c0 M" @1 h' L9 @
4 W0 k* n6 r6 c0 r; n    // The command can either be IDE identify or ATAPI identify.& l) b/ U  V5 P. {0 f! \1 u1 u
   pSCIP->irDriveRegs.bCommandReg = btIDCmd;
' r! K" T% N, c7 M' S    pSCIP->bDriveNumber = btDriveNum;
1 q' g4 h! F! Y9 f/ w    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
9 Y4 S% \3 ]5 ~; \/ X7 u' [$ Z. W& r
% D, v, W' G6 E    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
4 s) P- K) |& T0 E: h" {           (LPVOID)pSCIP,) ~3 @! H  H/ `
          sizeof(SENDCMDINPARAMS) - 1,
6 o0 o$ ?/ B# Q4 W( p7 F* O- ]           (LPVOID)pSCOP,2 I9 I) y9 c% t6 R0 ~
          sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
6 t7 W, _! u) {7 Y/ U. m! R           pdwBytesReturned, NULL);
7 O" M  A( u* g7 t}
. ?: w; P: e4 m2 ]3 N& F//---------------------------------------------------------------------------. U3 J! H8 _; m% |6 r4 a' q
// Windows 95/98/ME 代码
) ~6 g+ ?, l% ^7 C6 h//---------------------------------------------------------------------------
: O0 w" u0 G% |" _; b// ReadPhysicalDriveOnW9X
$ j# @  M4 p" Z- V6 _void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)
8 R( H& ]6 c+ r4 }{! ^) w* x- ]$ ]1 `* X7 b5 f3 N
   WORD wOutData[256];
1 k& d. B; ~$ O$ L" {    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);) C6 Z% n, y6 J  l6 L+ g
8 m$ k: T: F+ L) j" X
   // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
5 f( A5 v0 A' \9 N    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以0 w9 {, o* t" j* ~
   // 避免蓝屏的出现。(期待高人能指出原因)* n/ L8 y6 ]# N
   for(int nDrive = 0; nDrive < 8; nDrive++)
( c( U2 v" y! s* e& H# P; B  c! T    {  G% E, a0 Q/ A4 S1 i
       WORD dwBaseAddress;
- U$ \# \( I$ x        BYTE btMasterSlave;         // Master Or Slave0 n, ^7 H  P5 O8 l) f' H
       bool bIsIDEExist;* d& _7 K  h) C1 R: Y
       bool IsDiskExist;4 p: @; x7 j! j( b- c* V

( r9 \8 y  c8 j, `        switch(nDrive / 2)0 x9 N3 x: ~# @
       {
0 j# w: n* r( G4 Q6 l            case 0: dwBaseAddress = 0x01F0; break;2 J. g; n2 K* X# Z% a* g5 o2 T
           case 1: dwBaseAddress = 0x0170; break;
7 W5 E7 y, l3 z" n            case 2: dwBaseAddress = 0x01E8; break;
" @; w+ D3 t( M# q4 Z) |3 v            case 3: dwBaseAddress = 0x0168; break;" d+ d4 }+ i/ W% k
       }1 ?. @3 A5 V+ S; Y& j7 P/ q% @& n( J6 ^

! q5 A: R) L+ s5 E+ g+ Q        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
9 q* h: d$ S2 V- g; ?' J1 D  @) y  j1 J3 z# f4 I6 i9 {
       // 进入Ring0
& u+ G4 q) g. W" j        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,7 W& y* t) T0 {0 e5 B' b3 W
               bIsIDEExist, IsDiskExist, wOutData);
, |% W+ _5 Z, H7 Q' t9 v3 P. f    }" d3 s: W, z2 w$ J
0 ?' @, m% M3 w. v/ o: F1 E
   // 开始读取
9 c1 e* c) z& G0 g, a! z7 T# V    for(int nDrive = 0; nDrive < 8; nDrive++)
7 `- R2 w, k, h+ Z" T1 w    {8 g- G7 k7 \" w" G- }$ D1 L
       WORD dwBaseAddress;
" t$ [3 }# A7 K8 W        BYTE btMasterSlave;         // Master Or Slave; k) O" l3 W' n  Z
       bool bIsIDEExist;- S& z1 Z1 J" @& O
       bool bIsDiskExist;/ r7 d' ?1 O+ Q$ H, H
       switch(nDrive / 2)6 [8 d/ }) a# H" ]: ?, B5 }0 `
       {
; n2 N: E8 o8 Y            case 0: dwBaseAddress = 0x01F0; break;" s6 H* a8 ?3 a' v) T2 t6 L2 a
           case 1: dwBaseAddress = 0x0170; break;- ^1 i; G- k5 J6 J9 X& @
           case 2: dwBaseAddress = 0x01E8; break;3 T& t# S0 n, @7 h4 |! ^
           case 3: dwBaseAddress = 0x0168; break;
. p+ Q: _! F" @( J+ j        }! _" w2 a* D4 \5 X, N9 t

! x9 V1 B8 \. S        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
: T, j0 E7 [  `, F; z& ?' Y0 k; M! H" i+ ?( X# W2 \
       // 进入Ring0) S4 e( S$ l6 x# P% O8 ~; ]7 P
       bIsIDEExist  = false;
2 J* ?6 m7 x6 h        bIsDiskExist = false;
: A* B  d" `0 K  _+ S        ZeroMemory(wOutData, sizeof(wOutData));
# q9 H* ?* H3 B: f
8 m( [+ V7 `2 ?, ?0 ]        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
2 E- S/ b, g$ D1 d& d                bIsIDEExist, bIsDiskExist, wOutData);
7 p5 Q- ?( K( @$ z% P% N: v
7 o- ?) U3 J9 m  }% j$ I) l5 ?        if(bIsIDEExist && bIsDiskExist)" Q5 u5 N6 [2 W; n5 f
       {
7 U* m- Y/ p! v5 t+ W( G            DWORD dwDiskData[256];
0 Y, _9 @* f' m2 N. D            char  szSerialNumber[21];$ Y# B" Z# [! ~  s
           char  szModelNumber[41];7 K+ ^. x: H$ `3 ]2 @* e- K! r

8 p& K0 K% I/ P3 d  B7 J! H            for(int k=0; k < 256; k++)
3 ]% X% i& G% }& P/ l* c, G                dwDiskData[k] = wOutData[k];
1 w2 J- M+ X8 P) e3 a" p) b$ p
5 ~2 h0 [2 c: y  ?0 `* ?6 [            // 取系列号# {) e4 S) ?7 o
           ZeroMemory(szSerialNumber, sizeof(szSerialNumber));; G" I' n/ M( F
           strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
) K6 t! X! `# a! R( H$ W8 F+ u
" ?: O$ C# t6 [1 g' \            // 取模型号0 r. g6 g' i8 ~" w, r% Z) y, Z3 _
           ZeroMemory(szModelNumber, sizeof(szModelNumber));' D! b6 n. `. h! O8 O2 m
           strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));/ @3 ]% t$ |8 ~; J) U

, v0 ^% E# M' h( R% z( @" O            pSerList->Add(szSerialNumber);
8 b- o0 g$ g* B# H6 c* q( i            pModeList->Add(szModelNumber);) y8 I  z- a. M
       }
% _/ S" t3 m2 {$ O& |  U7 P    }
) \, v0 |! a7 ]    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
% N, l  W9 p7 e+ r4 h5 Z( K}2 D4 }2 G1 [" f9 q; }0 H
//---------------------------------------------------------------------------7 \4 j4 X6 \% \
// ReadPhysicalDriveOnW9X_Ring0()4 ]6 F$ h* y, `9 A2 O' d/ B
//+ X4 [2 I* Q" y! W0 B' W+ H
// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
3 Q! N* n) X6 x' k1 o// btMasterSlave = Master(0xA0) Or Slave(0xB0)8 X" A5 b+ T5 i9 Z
//---------------------------------------------------------------------------5 J7 f. M+ j& T4 M7 q( f
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,/ @5 Q* m2 N" }1 v8 i
       BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)7 P& O. H+ S' O! B
{. e+ g8 b0 b( C- N. \- G# S/ [
   BYTE  btIDTR1[6];* d( b0 o+ h: B
   DWORD dwOldExceptionHook;. z- q7 i" E) f+ K% Z% d7 i* }
   const int nHookExceptionNo = 5;" {+ l# ]1 E  p& S7 j7 g0 `8 W

7 p3 O! N, r. ~6 P8 J    BYTE  btIsIDEExist = 0;+ K) \2 ^8 ?' W+ H- M+ d) G4 k9 Y* j
   BYTE  btIsDiskExist = 0;. i( N( d% W0 A/ c0 ]
   WORD  wOutDataBuf[256];, p$ `8 m2 }) B1 M. I0 e  R# _
, M) l: I( n) M! V5 Q( i  f
   BYTE  btIsFirst = (BYTE)bIsFirst;
2 {7 n! T. C( H. Z, ^/ {! o  Q
* K5 p, C" g* z: M+ |* ^/ ]& N    const BYTE btBit00 = 0x01;) P+ ]$ i5 ^. W  k* M# {, a
   // const BYTE btBit02 = 0x04;
& N! K& _, z: `0 x  r+ H    const BYTE btBit06 = 0x40;! b' {) K* ]' h6 u
   const BYTE btBit07 = 0x80;  z$ v0 o5 ^( I5 g
   // const BYTE btERR  = btBit00;% G& ~2 O& A/ r# e) |
   const BYTE btBusy = btBit07;
2 T- o* F* t# d  t" `0 H6 e    const BYTE btAtaCmd   = 0xEC;
5 a  a& \$ F. [: b    const BYTE btAtapiCmd = 0xA1;5 t8 _" ~- E$ x  B' ?

$ p( ^9 l3 \# Y/ }) T6 Z    __asm8 x/ d5 ?( c( O/ z3 a9 ^# [
   {( l  i7 \  X; U' O& L! y
       // 必须先执行这条语句
4 \9 v5 K7 E% d3 J, K5 \% N/ |- f2 B% {        JMP EnterRing0$ x- \5 s8 L! j# D
' X4 U1 |; e, _' r# L6 f+ R/ T% V/ _
       // 定义过程
, ?8 c* x" x+ R4 W% p$ G( N        // 等待IDE设备直到其不为忙为止
  @- O2 T( @9 d" s  s        WaitWhileBusy proc
- a8 a0 W  R1 J1 N9 Y; R  {
: Y: i! g: Y; O8 u8 l        MOV  EBX, 100000
/ q' Z& D+ ]- W* x: d$ }! T  \  a: S        MOV  DX, dwBaseAddress2 ^! K0 N/ W, C  S
       ADD  DX, 7; C, K: m& G0 L0 x
& Q: ~  Q. U, Z0 G9 r
       LoopWhileBusy:
, |0 l3 |2 X& m3 B* E5 `+ U
4 s. q  T+ [: Y6 S" d        DEC  EBX$ f. O( d3 S- g
       CMP  EBX, 00 {; o+ g/ z+ @' J5 A
       JZ   Timeout
9 P' a) i6 R$ X7 D. x' `- ?        in   AL, DX& D: B: n8 N, \8 c: }5 b
       TEST AL, btBusy
' z9 T4 z+ Y" E" w# s+ C; J        JNZ  LoopWhileBusy
" T) m6 m4 @8 m# y& A' w        JMP  DriveReady/ m3 y) M' k8 T% ]7 {
5 n" W. C) j* {& ?3 l
       // 超时,直接退出
  z& l8 Q, o4 Z        Timeout:
: t1 |; @4 r$ w: J+ R1 E2 P        JMP  LeaveRing0
$ z" @- j2 v1 c' {  v' A# b1 V        DriveReady:
3 o! U' K# f7 a# k        RET
1 X& O& e( [8 p0 q        ENDP   // End of WaitWhileBusy Procedure% T; b1 g( \, F( O$ q$ S, B

( H# G2 c  J$ n5 O/ o+ c8 n# u        // 设置主盘和从盘标志9 w' H) ~. X; H! F2 |1 u
       SelectDevice proc
% a7 J$ ]$ d5 z- e' w* F9 {5 L  O. r  _9 `! w
       MOV  DX, dwBaseAddress
6 J8 \& V1 e! |% W6 w, W( F, _" V. j        ADD  DX, 6
) ]0 [' _/ D1 Y" k( _& p3 s        MOV  AL, btMasterSlave5 ?* b) C$ I( W$ r( l5 E. |+ i& ^
: D  E: M% A+ w. ~6 A
       out  DX, AL* z( s% w4 M" f  K
       RET
; _# z5 L; Y5 m
' }; c5 Z) A/ P5 V# }- a        ENDP  // End of SelectDevice Procedure, r& Z3 B$ V4 T
5 D1 C8 x5 I1 |: u6 q4 Y
       // 向IDE设备发送存取指令
( t0 x( P( U5 y6 L( k3 }" @% |        SendCmd proc! s+ ]3 O! L" C2 q, d; h
4 W/ p, v4 i( r, R. ~0 N
       MOV DX, dwBaseAddress( d1 ?& A3 z' Q4 T9 e+ M
       ADD DX, 7. d: E" C: }9 W, w
       MOV AL, BL // BL是主从盘标识,在过程外设置* ^9 w2 m$ c& B
       out DX, AL
3 e7 O" c" n: U# L1 y' b" O+ H6 w: g        RET
! J. w8 P: d  O7 `        ENDP  // End of SendCmd Procedure4 Z# R  O; u. z" P
( r6 \% [* N2 y  {. H: ~8 Y
       // Ring0代码" R  i6 f7 _+ X! y; P
       Ring0Proc:  u  O  }( O& T4 P5 G5 v
       PUSHAD
% _6 r0 ^7 ~9 Y$ B5 e+ W        // 查询IDE设备是否存在% Z" i2 M5 ^" n) Y& N8 }
       MOV DX, dwBaseAddress+ d, G. p) U* e) ]) S
       ADD DX, 7
5 I( p8 t8 H9 h4 K  T/ M- d4 Y        in  AL,DX
2 I/ L7 M4 c8 G9 z+ T  _7 d5 g6 Z, o5 K" ^3 ]
       // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回2 m/ o( C3 v9 k, |8 E
       CMP AL,0xFF5 b; x1 z- r8 x5 l7 n9 k' {
       JZ  LeaveRing07 v! @) q* n0 s2 O8 g9 v
       CMP AL, 0x7F5 ^* M( a/ R1 y) w
       JZ  LeaveRing0
* w0 R% g: n' p; Z2 d/ k7 J1 D0 W9 F/ N
       // 设置IDE设备存在标志5 ^% w& G) ~) Y4 a
       MOV btIsIDEExist, 1
9 i) |* n- @& e# ~1 Y+ c8 V5 Q
9 `$ E- |% H) v: B, r6 Z# U        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
; Y; p, q7 o$ C; w5 I# O        CALL WaitWhileBusy' J- a3 ]8 @5 \3 E
       CALL SelectDevice3 @+ ?" ]2 A  l7 M+ R
0 d6 w" x" o; o7 ?7 }# ?
       // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
& b# Q4 @8 ~6 S. c; e        CMP  btIsFirst, 1
+ n0 v: o, N6 l: c  W, P        JZ   LeaveRing03 m$ H/ F$ Y5 v$ n

4 K) f7 Z! c$ p; T  q7 X8 m& r" @        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???3 W) E, M7 ^  W  P' _  b& [5 l
       CALL WaitWhileBusy$ J) ^/ l  B, Q' R

7 F+ Y8 k. C. x  [0 C% B/ [        // AL的值等于cBit06时,不存在驱动器,直接返回
8 o* m7 M; }! ]& Q        TEST AL, btBit06
$ [( ~1 v9 j$ {4 p  n: R' f5 A* B        JZ   LeaveRing0
3 i; A  |$ p; D- F$ s. k1 s
! [3 B3 @  z/ A        // 设置驱动器存在标志$ @/ }+ t$ G2 q7 J% G/ f
       MOV  btIsDiskExist, 1) C# j" M' R7 {4 c9 U9 F

: s& z: w& Y$ P, _9 ?3 j3 N2 e# A        // 发送存取端口命令
1 w. m. }$ o* w; I4 o5 s* Q        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,- z- _! p' B6 Z4 H1 l" f
       // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令. K$ y) ~1 x8 y. O2 j# k
       CALL WaitWhileBusy8 |0 y+ {: y, V1 s
       CALL SelectDevice    // 设置主从盘标识- ?; q* d! n  _  `5 v8 @  M5 r/ @
       MOV  BL, btAtaCmd      // 发送读取命令
* O% v6 s  G7 ~$ n; J8 v; n        CALL SendCmd8 V3 N% x& ?9 |5 A
       CALL WaitWhileBusy
2 |  {  ~- P  }3 {" e0 Z1 H+ Q) G3 b3 |* w# }6 y! @% E/ R' X
       // 检查是否出错/ e% g& @9 k* D
       MOV  DX, dwBaseAddress
, K3 r+ ^' R7 Q1 ~8 g9 m- A        ADD  DX, 7( m% l/ m5 }" m  F
. H: y! Q1 O$ p9 Y
       in   AL, DX0 |) o/ V% b, i+ m: v& ^. u
/ q6 h3 x$ a$ D8 V
       TEST AL, btBit00
$ U4 p# m9 b3 {3 T2 j' `) B- ]        JZ   RetrieveInfo   // 没有错误时则读数据
% Z8 q2 L5 V7 O4 X8 s7 N
1 }% F* Z( q; n. x$ K) G        // 如果出错,则进一步尝试使用ATAPI设备命令
/ K7 H2 P# e: v2 }! ~! _$ w& y        CALL WaitWhileBusy
7 f2 L: \4 `! o1 j6 l6 V        CALL SelectDevice: B& g( S. ~; y8 s$ o  q5 L
       MOV  BL, btAtapiCmd
  M% D5 M* }$ [5 m' g3 ^) T        CALL SendCmd. z2 G2 q+ B8 T
       CALL WaitWhileBusy; e4 u$ z, B8 m+ [

9 t. i, Y& i9 G- ^$ a! W        // 检查是否还出错
5 O' _; k+ h5 \2 m/ @% T        MOV  DX, dwBaseAddress, j* Z2 z0 R5 j2 D3 b; j
       ADD  DX, 7
, Y( H- V+ i+ a4 k        in   AL, DX
! \% f. @$ J' P& ?. }4 O) d        TEST AL, btBit00$ @. O% z- \: P& M
       JZ   RetrieveInfo   // 没有错误时则读数据4 a, W- i( @+ Z; H" o# N
       JMP  LeaveRing0     // 如果还是出错,直接返回% [) r* e+ g% S: t/ s* y6 X

0 x6 N' N& U+ K3 i; h        // 读取数据
& u5 _1 v3 k) I1 n- W        RetrieveInfo:3 S4 O1 y' x1 V) F( {, _% A2 ?

7 p" b  B: Z# K! h/ ~: y2 b4 z        LEA  EDI, wOutDataBuf
  A$ F% A2 U" w' V; j: n        MOV  ECX, 256  Y8 p2 o! u5 T6 f/ f" o% C
       MOV  DX, dwBaseAddress
# j+ p! a8 z! |! O1 X( j& x        CLD
2 M  A7 f$ i, [3 }, Y) p2 C% b5 W  G" g2 r) X# p8 v
       REP  INSW& t2 \" ^: N3 n( D: X

' t, _0 X  m  c- Z        // 退出Ring0代码2 C7 h1 X7 D) s& I
       LeaveRing0:6 Z, Z+ F7 n2 r$ C  ~7 Z; u" F

5 L# Y: @& U( G( W" h1 r! @        POPAD: V/ m. s9 p6 T* K3 Y' p" f
       IRETD
  \! F6 K1 i9 V1 R/ R5 ?: r/ X$ x2 l7 |. n" o
       // 激活Ring0代码
8 _( f, h6 m0 a6 w        EnterRing0:
" ~& t* S# l! v! v) s; j3 b
4 {& j1 N5 o" i" Y4 W, Z* S" Q- q        // 修改中断门
$ f& V) _9 c+ t; C7 `, A, G; {. O        SIDT FWORD PTR btIDTR1
9 P. |: Q6 F9 K* w/ q- u+ B        MOV EAX, DWORD PTR btIDTR1 + 02h
( o: R  u8 E& P& `7 |2 G        ADD EAX, nHookExceptionNo * 08h + 04h7 J6 @( H6 C! O, k/ ~# T
       CLI
& j# S6 v' x2 t1 M7 J5 Y/ |, {" }) F7 a7 \# Q9 W; l
       // 保存原异常处理例程入口
) B+ r! W. L* `  X- s& n: t: h- V        MOV ECX, DWORD PTR [EAX]8 M, b- C# Y$ N! R
       MOV CX, WORD PTR [EAX-04h], z! {  k7 L5 _, Q' P- W
       MOV dwOldExceptionHook, ECX
" \# P1 J- f" t
( t( F: _4 X0 B7 `  X        // 指定新入口1 O! b( a# {3 ~$ G. M: Y! Y# Y
       LEA EBX, Ring0Proc
1 p3 O& P. H& s! `; e! V4 _% \        MOV WORD PTR [EAX-04h],BX) r1 G3 {" D' {8 s: t
       SHR EBX, 10h/ X, A. W+ V9 v, q
       MOV WORD PTR[EAX+02h], BX
$ x, _% [- r/ s1 }7 `1 @% N
2 b& ?, O2 T8 ^7 {        // 激活Ring0代码
1 p1 k1 a4 a4 b" e' a+ v$ k4 n. q        INT nHookExceptionNo
" A: v6 u1 m, P) G" D; }7 Q9 J! x/ J0 {& V+ a3 h2 s
       // 复原入口4 z' F3 x) q" c+ a* [: a" b
       MOV ECX,dwOldExceptionHook
! c' ~+ |# o3 H" h, _2 T( }* H        MOV WORD PTR[EAX-04h], CX# O6 k$ I% @6 K! }8 M" c
       SHR ECX,10h
  _0 c9 l9 c3 z* c2 u; ^$ d        MOV WORD PTR[EAX+02h], CX. P6 @- A8 ]' v9 R/ C, M' k$ _# O6 f
       STI* ^* D4 i) e" L# G
   }
% H/ E/ r; R5 x( ^/ y% x    if(!bIsFirst)
, q; D2 v8 u" `2 W    {3 {4 |% X- F) M# H+ M% [
       bIsIDEExist  = (bool)btIsIDEExist;
3 I& k' U% n& v6 t# s; M1 ?7 F        bIsDiskExist = (bool)btIsDiskExist;
: H# G4 c) N) C3 P. s- o' A4 k        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
. p0 u$ h2 c$ I4 X9 S& t' G. X    }
  k* M6 i1 X+ {9 G3 T* W. P: v/ S}
4 ?3 l5 y1 ~: z, ]6 P  f//---------------------------------------------------------------------------
7 q  b* q, T8 ]& T// 调用方法:: i2 f% O7 b( h# R0 {* g; O
void __fastcall TForm1::Button1Click(TObject *Sender)3 J8 m& r. C; Z
{
& w* D+ I. x, H5 S4 S. B5 Z$ H    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
: |% V$ d5 n! R% t9 k}
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-8-13 22:51 , Processed in 0.024827 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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