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

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

[复制链接]
发表于 2005-5-30 19:22:36 | 显示全部楼层 |阅读模式
  #include <WinIOCtl.h>
: S, d( k0 Z# A) O! f#include <stdio.h>
& v# |2 c2 F6 m. |8 s3 I. J
3 T0 C- v* Y9 {* l) {! c' Q#pragma inline
7 X4 R% G" h( e1 ], z0 M//---------------------------------------------------------------------------# L* i3 D' c* a3 Y
// IDE NT/2000/XP专用变量# `1 B, E' Z5 d# `
#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS2 I1 X% L8 {: u4 V# ]
#define DFP_GET_VERSION         SMART_GET_VERSION! ]% M" s3 {: ~7 w. T7 g; A" k; ]# i! j
#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
1 G9 H5 s" b+ q, U& r& p: N#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
& S- R: C7 z& s9 Y5 o
- K* D3 T- F( k. |/ e7 E  Zconst WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令1 m( t: K% x7 V9 _: K
const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令) n* v/ |4 p4 ^0 e4 t5 ?

; y6 Z! D: T5 M/ I1 f# |const int MAX_IDE_DRIVES = 4;! s2 e  c$ C, B- O, j

" k1 f. x8 ?# y  W) ?// SCSI专用变量8 A' ], z5 k# L5 v
const DWORD FILE_DEVICE_SCSI             = 0x0000001B;0 e0 n2 B! D, ^' r, F
const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);3 i* k) z8 H' l" q
const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition0 w- m; d( [& f4 W$ G
const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;% x0 S: s% ]' [# \: n4 t

, }6 q/ Q# ?% @* ]0 f9 p2 i- Ptypedef struct _SRB_IO_CONTROL
+ G" g6 R( z$ O: |! ?; B( W3 e" r{
. z6 j6 Q+ A$ p6 v    ULONG HeaderLength;  i: @) h( Q4 K3 d( K$ `; e
   UCHAR Signature[8];
4 j$ D8 a& ~; a" v+ I6 n2 w    ULONG Timeout;
9 O8 u2 W) P" W/ F+ ^( ~7 B    ULONG ControlCode;$ D6 G0 o0 K: x; K; E2 |: S, D: |
   ULONG ReturnCode;
6 }" V, A7 ?! t; Y5 S    ULONG Length;% c* g( [& e; |- S$ p1 D: Y/ Z; |
}SRB_IO_CONTROL, *PSRB_IO_CONTROL;
; O% ~0 A% o# q5 U2 G! w- h" n$ J6 X
// 读取的主函数0 o: U: {: |1 x* ~* C
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
% |9 Y  x5 c  ~' [- K; a# a; ?$ s
* j4 [9 `2 ^6 x6 x// 辅助函数; b/ S5 R) u( M. e5 z$ |2 P! h: L
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);7 `4 `$ ]# k& W5 c
// NT/2000/XP函数
. r, V7 e5 d  P5 s$ H1 jvoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);4 \2 H9 P) y# {7 `0 w( a  V; ?
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
. |! D4 K1 R7 T        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,1 S, Q3 ]% V1 e0 z8 `* d+ e6 D
       BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
" G, y* N/ W" P6 y  {* H3 _// Windows 9X函数, j# e" T* W+ U% S0 w4 ]
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);
' [+ h; h9 J7 G3 @' Yvoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
7 s, K, E+ f  Y) `$ R8 D        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
% ]% v  n: ^+ n2 w/ h  H  b$ A* x% ^% X- T; _* k
// SCSI读取函数(for NT/2000/XP)7 l$ |, \1 K& m/ E, Q2 L' J
String __fastcall ReadIDEDriveAsScsiDriveOnNT();
; n  C" |/ i, q7 p( j//---------------------------------------------------------------------------
) a6 l# Y( N+ l6 w// ReadPhysicalDrive
0 j. _1 N; \7 e  O* p+ Q$ \/ [void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
( o/ S5 L, J5 {$ T7 e{( y5 l# \- n3 v0 ?
   switch(Win32Platform)
; n' D' l- x' j1 t6 P- S2 ~    {
2 E0 H; |+ E/ P$ H        case VER_PLATFORM_WIN32_WINDOWS:
' P0 Y3 G  u$ d! ~; |  J: J            ReadPhysicalDriveOnW9X(pSerList, pModeList);
9 T% O$ ~$ p- X3 i8 I            break;) T, R5 E' e1 T+ Y' h% j
       case VER_PLATFORM_WIN32_NT:' O1 F( T/ C  P2 t6 P* u" i3 c1 f
           ReadPhysicalDriveOnNT(pSerList, pModeList);9 a& N' @4 `- \4 F9 m' V$ y
           break;1 T, X" q. g( R! a  ^, C7 k
       default:2 Y4 p8 e) j7 w# \9 G
           break;4 n9 q% U* v! S" c
   }& _, [2 p; \9 [  X% S: H& T
}
: n7 X, r& z) {+ L# K7 a//---------------------------------------------------------------------------/ T. l- n" F8 _! c
// ConvertToString: q7 y% G8 \, m  e- M
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex), h) B) u0 u  W( s8 P
{2 n; f$ o8 b9 [) I: H
   static char szResBuf[1024];3 n9 a# M9 Z5 u8 y  h  U$ S/ \
   int nIndex = 0;( K0 x' O+ ~; C. A1 O
   int nPosition = 0;
2 [7 y( M' A& t+ ]& s+ X7 s7 n, f) s# \
   // Each integer has two characters stored in it backwards* W' W3 P6 C4 i4 `
   for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
" U& A. ]) t( a( ~3 `5 C; c' ]% V    {% D& r* h- O; |4 C" V, H
       // Get high BYTE for 1st character
$ n  S) Q% ]) `/ n, [2 r# B+ n        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);) R9 h) U. U5 |$ e1 I% v+ s
       nPosition++;5 c; U- ]+ ~8 u" j
) m4 }  @" e1 P
       // Get low BYTE for 2nd character
& S  @3 Z& B* _  y* C        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
; j! m: N6 N8 C- g# N! z6 i8 d        nPosition++;
  y, k2 f9 Y$ Q, U% K    }+ I# U  F; i) N) S
8 F6 B! R: `& n: m5 n
   // End the string# z: {! m6 |* b& f7 n
   szResBuf[nPosition] = '\0';
( n4 t/ B% G; C  p9 r" J; e. W+ t
- G& e9 z3 k& y, m! S    // Cut off the trailing blanks2 u( K7 W3 H# s( U2 l6 `0 ~
   for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
4 C& Q& ]9 L6 }4 L; a' J. L        szResBuf[nIndex] = '\0';
+ Q+ O' Z( t9 p7 g$ Q( h
! |6 _7 L( w3 @    return szResBuf;/ o! y( C! n' U
}
9 y1 C& n: X) j9 w//---------------------------------------------------------------------------
; }! e  K# j5 r" r9 }% K( X2 e// Winndows NT4/2000/XP 代码
" c, K5 |: m3 R2 q//---------------------------------------------------------------------------" q' N4 b, B3 Q& Q/ u' t
// ReadPhysicalDriveOnNT! x$ S! d2 J% e2 L4 ]- C
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
$ p: |1 J' P2 w4 @{5 {5 u; Z; Q9 c7 F
   // 输出参数$ M: g: Q' ?7 m1 L: G/ G5 r
   BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];' S$ ~7 A% H4 p8 l/ C; O" l

5 }  a7 n! V8 b* k    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)/ }& P7 T* x5 u' D. o
   {
7 u( `1 S, V  W) A) n% @        HANDLE hPhysicalDriveIOCTL;- a  C- `8 A# y
       char szDriveName[32];; h6 M" O/ W+ x  N
' f3 k* Y4 m; m) y, O6 e9 Q
       sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);* B8 E) t( N/ }4 m: Z
       hPhysicalDriveIOCTL = CreateFile(szDriveName,0 L- f2 r" }1 Z' m, S% i
                       GENERIC_READ | GENERIC_WRITE,9 J7 @6 h; }) [' Z
                       FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,. n( G+ F  Y8 @, M) v1 i1 ^
                       OPEN_EXISTING, 0, NULL);
3 E- w  V- o# \0 G, ~- h6 x$ \% Z' C. Z: P
       if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
' ?1 W$ ^% L$ N+ l- i        {
* f$ ?2 h5 M" @/ l6 i            DWORD dwBytesReturned = 0;7 O5 w8 ?* W! \2 ?
           GETVERSIONOUTPARAMS gvopVersionParams;
: I0 k- Z8 ?! {3 P" B' h8 Y' n, g0 f+ s: @4 `$ `$ o: W
           // Get the version, etc of PhysicalDrive IOCTL* v! [0 D  J; Y  @8 ^. e3 |- i
           ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
; N, m% l* w5 Q* z, s$ d1 S8 D% k% m, L: h. x) Q6 N) T
           if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,' e( i/ z/ A+ i! w) P
                   NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
0 i0 `1 m. F, A- L9 ?3 T. m0 {                    &dwBytesReturned, NULL)); Y' c" w8 C+ {
           {9 W. ]  Q! ?" w4 l
               continue;
4 _4 M  }+ a+ S( n            }0 U. P' R" ^# W' x

* T* t. D0 F& `1 e            if(gvopVersionParams.bIDEDeviceMap > 0)
" h3 i" q) E  |            {
6 h) u) d0 u8 ^" c                // IDE or ATAPI IDENTIFY cmd
* _' j# u2 H" j1 `                BYTE btIDCmd = 0;9 P, @9 M$ v6 e
               SENDCMDINPARAMS InParams;
* |. Z* k' M# \' n# e( e# R- e( Z                // Now, get the ID sector for all IDE devices in the system.
9 z( X$ h! n  M0 j: _8 ~                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,/ Z3 ]$ d4 M* k- {1 ^3 O3 q$ ~
               // otherwise use the IDE_ATA_IDENTIFY command5 E5 K# z' w; g1 f
               // 具体所得结果请参考头文件中的说明
: T' s0 U! o0 q" f                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
. v4 Q4 k' Y5 N8 Y                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;4 \0 B0 ~. d1 S, J
               ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
! W4 X  m2 H: n) n0 U                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
, l0 f2 h+ e. {' I1 T0 n9 j/ ^4 _4 ?/ `& h
               if(DoIdentify(hPhysicalDriveIOCTL,
4 t4 {5 Q/ t) h% L                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,: y) T! R/ v; f' M2 L
                    (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
7 T0 a1 T8 v4 V' \6 z/ F3 f                {
+ b. F: g  a; D; \' s3 F                    DWORD dwDiskData[256];! B( d* x* _+ E7 X' i8 J# X9 h
                   USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
/ U- h) {3 T' L' n0 R; f6 E                    char szSerialNumber[21];+ N) q8 k5 Y7 B4 S; r. f
                   char szModelNumber[41];) A" p/ y$ [5 k5 `

' b' u8 @* r: X2 w. a* q) m                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;1 h: c8 Y3 f) W3 e! S
                   for(int i=0; i < 256; i++). q6 z/ E, Z# S" r& C
                       dwDiskData = pIDSector;
. Q3 @  c0 t, \- e9 Q                    // 取系列号
  F' Y4 a3 ~5 V* [                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));; W" N! S4 e# V+ E- S  y
                   strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));' u5 B) h1 L/ G
: z, V' H8 F5 [# `
                   // 取模型号* q" I  O; _' A0 d% y$ r
                   ZeroMemory(szModelNumber, sizeof(szModelNumber));
( l7 S+ Z3 X3 e' v                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));  O' }5 [0 L8 l0 V  L; i8 I. ~
% B/ _* u% t' b. d6 _6 u  o
                   pSerList->Add(szSerialNumber);
* }# v, T: K* o3 y                    pModeList->Add(szModelNumber);
+ T) A1 u7 j! S                }7 w- n' w0 x5 `  I5 C  A
           }8 M, I0 J/ M" G' H
           CloseHandle (hPhysicalDriveIOCTL);
1 K$ C. u) C' x' x, q  p4 o' ]        }
8 f0 ^  F9 ^# R. ~    }
& [3 j# R8 Z& M1 U; [: g( \7 V* N}3 P) o- p" A" b$ t) |* [
//---------------------------------------------------------------------------6 U( c+ G- T0 T/ i6 U. q6 W
// DoIdentify
! _9 e8 u+ U$ K- F; J7 k! ?bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,! y6 y3 p  K6 @; i4 B
             PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,0 f  y* g$ m5 u: R$ b9 A
             PDWORD pdwBytesReturned)
( g+ d8 U5 l0 y) K' |( i7 L{, j  F) q% K% T4 ^6 A
   // Set up data structures for IDENTIFY command.9 B6 s' T. C* j0 X. u
   pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
" I) [  C' V/ u- o  E    pSCIP->irDriveRegs.bFeaturesReg = 0;. i/ x. D/ `  w3 }( G1 d
   pSCIP->irDriveRegs.bSectorCountReg  = 1;( A! z" F* s- x8 O
   pSCIP->irDriveRegs.bSectorNumberReg = 1;
' \* {1 Q+ X& @; ]& O( m    pSCIP->irDriveRegs.bCylLowReg  = 0;/ Q6 w' y  t7 Q- V+ W- ]7 {7 `
   pSCIP->irDriveRegs.bCylHighReg = 0;
0 `( {9 _2 H: r+ s3 e0 i2 I) C* z5 y4 Q$ f9 k' {, V( Z  d
   // Compute the drive number.(主盘和从盘所对应的值是不一样的)  v+ g$ [) r! E! H& j
   pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;) }# x& y) F" ]2 L1 U" w/ Z4 s3 b
' t4 F% X# h! o* n& }7 x2 k
   // The command can either be IDE identify or ATAPI identify.. Q9 B: K- G* v  }% Q% o/ P
   pSCIP->irDriveRegs.bCommandReg = btIDCmd;
1 M: t0 C* n" E' u; W: B& ]    pSCIP->bDriveNumber = btDriveNum;
  u# ?- [2 m" `  Y2 D8 y9 b" {    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
; d5 |6 F) f7 ?* s: c& I- k2 {* n/ R. D: G6 x7 A2 t% L2 M# c
   return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
" M4 s/ T% T; U) M3 M           (LPVOID)pSCIP,
/ K$ L2 B; f: u8 X           sizeof(SENDCMDINPARAMS) - 1,
/ h0 ?6 C) W: n" _, L  N" @           (LPVOID)pSCOP,
' g' q2 Z0 Z4 B" Q; T           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
7 Y: {2 G) L* v  R, ~( R- D% r           pdwBytesReturned, NULL);6 Y- f7 k2 c% Z( ~( o! q
}
: W6 U- K3 w( i% K% M5 }//---------------------------------------------------------------------------$ \8 q9 C6 C: Y* x- m: L& I
// Windows 95/98/ME 代码' B1 Y( _1 C$ H2 h
//---------------------------------------------------------------------------
' \) L7 v: ]) L// ReadPhysicalDriveOnW9X% d$ `) u' ^9 i" F0 X
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)
  P6 F0 T4 s! V# w{* ]6 j  I& q+ ?, C4 J% f; G
   WORD wOutData[256];
# m8 ]. {% g4 X4 K8 s    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
/ u) W4 I2 \1 U: }+ F
( h* u" b4 K/ z* A    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。+ G$ q' q/ }! n( O7 t
   // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以& l' t! {2 r# T2 ^! }2 j
   // 避免蓝屏的出现。(期待高人能指出原因)! u- ]% m0 h$ U
   for(int nDrive = 0; nDrive < 8; nDrive++)
/ }* R, K, R7 v1 R0 M. E4 S+ ]    {" s3 r2 h7 d% ^! V0 p
       WORD dwBaseAddress;
+ `% o7 ], Z. |- A/ e2 P# y0 ]! n        BYTE btMasterSlave;         // Master Or Slave" X$ T+ R' r  X
       bool bIsIDEExist;# E! o2 t  E2 Y5 I8 Q- v" B
       bool IsDiskExist;% t1 V3 v& j* U! b' f: U

3 \+ Z6 m3 ?& f/ l2 q        switch(nDrive / 2)  m1 j  _  M" n) f0 K0 l& ]7 F) ^
       {$ @  W3 A9 l) c# S4 |
           case 0: dwBaseAddress = 0x01F0; break;
, q; I# ?  v- x- j9 T            case 1: dwBaseAddress = 0x0170; break;
% P# l. ]) ^( A3 B  f: o  F' V            case 2: dwBaseAddress = 0x01E8; break;. I/ A0 u9 Z' d
           case 3: dwBaseAddress = 0x0168; break;
  S! ^$ Q+ D) l5 ^, t        }
0 `/ F/ Q  K- n. Z. R. f+ S
+ C0 o% s1 p+ x- Q        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
+ h% c( C1 |# |/ R' a- @( x- l" |* t! V8 h* G  j
       // 进入Ring0
0 Z# [5 J* ?1 ]4 b1 S        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
, s7 E4 O8 ^- P# l* C2 S                bIsIDEExist, IsDiskExist, wOutData);
+ X5 \0 e/ ]* j$ _, A$ v4 I5 j& I    }
8 ]$ N& I9 w% M" L0 y9 r4 |: S3 L2 `3 q6 ?+ q3 J: o/ L
   // 开始读取
9 w" L; J& l. }# f1 x0 ?7 Z    for(int nDrive = 0; nDrive < 8; nDrive++)
5 I* K  F2 O: v    {6 p) D; H4 M  Q; o
       WORD dwBaseAddress;" S% H$ `' Y( N3 e% Z
       BYTE btMasterSlave;         // Master Or Slave
0 E: E. i& j' j% M" _! g1 E- R        bool bIsIDEExist;! B) `$ |- ?$ K1 B
       bool bIsDiskExist;) s8 P& A' ~! E6 N
       switch(nDrive / 2); x# o# Z( i) C2 U
       {
4 q4 v9 k7 M' ^9 l1 B            case 0: dwBaseAddress = 0x01F0; break;- g4 h) Q( M9 }% _& C
           case 1: dwBaseAddress = 0x0170; break;( \$ w# p+ {  E
           case 2: dwBaseAddress = 0x01E8; break;
% t6 Z3 l. \) J# Q2 J            case 3: dwBaseAddress = 0x0168; break;% f( u" d/ Y) H. j% H( \9 W* \
       }
2 n2 u1 \8 S/ W$ p  V; F' L" n6 i9 o1 R% B5 o
       btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);4 x' C/ C+ Z7 \) r2 \/ A% a

$ h& G2 d% P; Q9 L' x        // 进入Ring0* F3 N* @' x, \
       bIsIDEExist  = false;
; w: E* N/ H) G& L9 c- l        bIsDiskExist = false;
; e8 t( Z4 T7 r, g        ZeroMemory(wOutData, sizeof(wOutData));  ]1 i+ d0 A% F

' ^$ m  J, m" s        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,7 O3 a: }; G2 j. x( _# K. J4 w
               bIsIDEExist, bIsDiskExist, wOutData);
6 r8 r' L& m6 m5 L
7 i5 F! J: d7 J5 x  ]9 n7 O. Y  I        if(bIsIDEExist && bIsDiskExist)* g' i' s# H2 c4 i. n' ]6 d9 A. m
       {, h& _" ^* \  ]8 ^; `- D; J
           DWORD dwDiskData[256];
) Q" k0 _; j" C4 }7 a% P            char  szSerialNumber[21];/ i( Q4 Q/ ?7 I/ p5 O; P
           char  szModelNumber[41];
! M, S. i& _: c: S6 K. t! d1 h6 _# G  ~4 R
           for(int k=0; k < 256; k++)
, \" q/ s3 s$ j: o                dwDiskData[k] = wOutData[k];
, W% H* `/ L, |+ k9 n$ j2 S% p* C
           // 取系列号3 O6 M. {$ o2 z0 X/ W( q1 B( f; _  I
           ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
- p/ k2 p2 v- }, `8 z+ x            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
0 B0 q. Z6 P  u7 m, v7 c3 Y( _( y
3 N# z& f. T9 h' F            // 取模型号
) Q6 _% `3 w4 Y            ZeroMemory(szModelNumber, sizeof(szModelNumber));
3 x& P. s4 q6 [0 [# Y7 ]            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));/ z" q' Q* ^# V: Z* [; G; r

  ^# c. Y) C$ c  L- N6 W7 F# h            pSerList->Add(szSerialNumber);6 X# @( T$ R  s* g
           pModeList->Add(szModelNumber);
$ B5 e' {& m1 _9 B- b4 f) z( h        }
' g& O8 D8 t# C    }
+ O' }7 G5 b5 Z; a2 L    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
* C: L; Z5 a. v  ~3 o7 N}
* j% v% l$ A1 f( {7 q% z- S: q//---------------------------------------------------------------------------
$ \6 S3 X! Q9 \( X7 t// ReadPhysicalDriveOnW9X_Ring0()
1 A- \6 b; U: J8 d3 I//
) W. j. r! l% \% ~! g5 _) g* c. ?// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
7 ^* U$ l$ |3 Q// btMasterSlave = Master(0xA0) Or Slave(0xB0)
4 m, W& N9 ]% p//---------------------------------------------------------------------------0 k, l! B! g% s6 Z8 Y$ p
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
5 W) G- F! x! l9 {# ]) a% o        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)2 }% P( J8 s; U, P- U6 l& N
{. }$ g. I. k! M- w- j
   BYTE  btIDTR1[6];+ N) c/ Q& |9 @6 q3 K) I
   DWORD dwOldExceptionHook;
+ L6 ~8 X9 A! @    const int nHookExceptionNo = 5;
5 x4 S8 ], U% _( `1 L# |
9 w7 ^% t+ _; @, m* {4 n    BYTE  btIsIDEExist = 0;! j; d( @5 o2 D
   BYTE  btIsDiskExist = 0;9 M9 U, T. g/ t  R( _9 m
   WORD  wOutDataBuf[256];0 j- ^+ E$ [0 L) C9 V9 Q

1 @  n; a2 ~, k! C8 l, e    BYTE  btIsFirst = (BYTE)bIsFirst;# W7 M! u) G' A2 o

& H3 C6 K- P$ D3 i" s8 W/ a3 f1 \    const BYTE btBit00 = 0x01;
9 O3 P0 D! {: N' S    // const BYTE btBit02 = 0x04;, L, ]3 x2 G. `3 J
   const BYTE btBit06 = 0x40;' N& d) {/ T+ j- N# }6 m* U
   const BYTE btBit07 = 0x80;5 z5 X8 j" r% X/ e) u; i
   // const BYTE btERR  = btBit00;+ d& o7 h2 T8 k' n& m# X8 z$ o
   const BYTE btBusy = btBit07;
- y: }1 s6 O6 v! }! h* m& q! a# g    const BYTE btAtaCmd   = 0xEC;
9 B1 H% V% V) c+ W6 o+ p0 V    const BYTE btAtapiCmd = 0xA1;% @) M( r5 T% d& @/ q, X& x8 N. E
6 ?3 W( a* J* L7 Q
   __asm4 u- g7 g- e* G; m* P- Y7 J
   {& B1 u: m( }, m2 e
       // 必须先执行这条语句
. b. b! S2 @) G) y; {        JMP EnterRing0
5 F2 @1 j9 e; q" a$ M+ j) p  u% y0 X  P& U7 ~+ K
       // 定义过程
8 J) I4 U& i) ?        // 等待IDE设备直到其不为忙为止
7 c9 Z3 J- Y, v/ d7 j        WaitWhileBusy proc* V3 c3 x0 `: {: r& E7 S% O! c3 y, J

% b7 `" f$ l' f/ n7 D        MOV  EBX, 100000
# y* F( O2 N7 @1 U; w$ K$ j        MOV  DX, dwBaseAddress
- A( k3 i2 N0 @$ v& O* Q7 J        ADD  DX, 7
. T( B, g3 X) ]' m4 i+ n; [
  J7 x" C- p) X6 \! |        LoopWhileBusy:) v* A7 Z1 l0 }* V
) V. `! v8 j4 ^! p  v1 w
       DEC  EBX
0 s; u. ?" K  {- Q  j& p7 N& d        CMP  EBX, 0; |4 T  `$ n: l5 L  j) }# x
       JZ   Timeout
. P* b) Z$ T" `% {; b7 B  b        in   AL, DX7 N; P. \3 V4 M
       TEST AL, btBusy
" L5 T& D9 ~; \5 ]: X' }        JNZ  LoopWhileBusy
) [: E; t1 y. D, w. j: Q        JMP  DriveReady! ^0 P# p. j' U4 S

5 `/ |5 I3 d0 x& W  y; g1 Y        // 超时,直接退出
# s6 {5 X1 j3 F. D+ \8 f        Timeout:
3 J3 J# i$ A& E7 l/ H0 a        JMP  LeaveRing0
* ]0 L! O0 O9 U4 P& k- o. P2 d' c4 R        DriveReady:
, n0 S( _- h2 m) b        RET
9 J2 v3 P; M3 h        ENDP   // End of WaitWhileBusy Procedure$ Q# }0 R/ l8 g6 {8 M$ n0 [/ _  ]5 S
9 F/ p4 M7 [4 T4 `  A' \
       // 设置主盘和从盘标志
6 g$ G+ E# ~" x+ J! o, M        SelectDevice proc  M% e8 L: Z7 R( Z5 [, Q! i' ?5 g4 E
+ w% V5 X/ T. Z& y
       MOV  DX, dwBaseAddress
& b0 K4 `) T! q6 \        ADD  DX, 6
4 T' i, A4 f4 L3 q" z0 }        MOV  AL, btMasterSlave3 P) }3 E9 {' K# u- w1 X& v

; A0 Q$ j: k7 Y9 o        out  DX, AL
6 [- D2 P' J2 C7 Y6 h        RET' u9 C& G% U+ L" Y, f7 L

2 z9 Y! ^) O! b# F, v        ENDP  // End of SelectDevice Procedure
2 j6 M( B2 R; L6 L% X8 Z( H$ H" l
       // 向IDE设备发送存取指令$ E8 {; ?4 K1 s. ^) T
       SendCmd proc: U; A- C8 T9 g" m7 v

; L6 d% Q) E) l& ?& ?% @* x        MOV DX, dwBaseAddress
# A0 S  M% s* D# |( u  }        ADD DX, 7
1 l2 O, {3 G0 s" {: ~        MOV AL, BL // BL是主从盘标识,在过程外设置4 _/ ]# U. B5 c! S
       out DX, AL
% ~& y6 M- U+ D- L- p0 a        RET) c/ k9 p, e0 o' F. e
       ENDP  // End of SendCmd Procedure" d/ b6 I& B0 Y$ g% I

' \/ ~6 p) c8 \6 D/ V        // Ring0代码0 o9 S  @+ ]0 B0 E" L2 u8 Y
       Ring0Proc:
8 N1 D* {$ P4 O# a        PUSHAD
7 V; S: O2 ^8 }& W        // 查询IDE设备是否存在
1 u+ b4 ]0 m4 K, u        MOV DX, dwBaseAddress
# f4 K) [8 }5 K  @. [' M) Q: l        ADD DX, 7/ v" ^, c5 U: a$ y
       in  AL,DX- }% a4 d) p8 U+ ^' I5 P

( X8 `8 I6 R; o7 d) ~        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
0 r  M* ~5 z' [- D2 @6 Y" i        CMP AL,0xFF
) O0 b/ ]& v9 R2 ]        JZ  LeaveRing0: P$ X" J! d' Q! C: q. s; q' T
       CMP AL, 0x7F" I1 z5 {! S. L+ ~' I
       JZ  LeaveRing0
/ y, R0 n7 X! E5 b0 m8 Y# H) H$ v3 P- \5 l/ D: V6 }9 f$ f" n
       // 设置IDE设备存在标志7 R; B* i  E  o3 Q6 U; a
       MOV btIsIDEExist, 1, N$ n- h4 M3 {
  d% p: O  F+ s- D' T
       // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面). g' v* I; g# a. V$ L8 [( Q- G
       CALL WaitWhileBusy4 ~0 |7 ?! n1 W
       CALL SelectDevice, @2 a# n8 x  q7 q+ U2 n1 \
9 G: W. X! I; J  o
       // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏3 ?( a) }3 e; w  Q! i- _
       CMP  btIsFirst, 1
/ K  T1 f: M' |        JZ   LeaveRing0
. J9 E" u9 Q) j1 B# R( D) R5 g0 |) z) J) s+ c1 W
       // 第一次调用时,如果执行这行语句会导致蓝屏,Why???& W6 [3 Z! O3 D  i8 E; f
       CALL WaitWhileBusy
/ i# A6 h! j. Q: d
  D3 h: @3 T8 N, s7 ^        // AL的值等于cBit06时,不存在驱动器,直接返回3 P" Q3 Y/ X6 R) A. a
       TEST AL, btBit06+ i0 v2 G+ p1 y9 n( B, ]) {
       JZ   LeaveRing0
( I+ S$ h2 ]- [! T0 F+ t; I
; J$ }) n) D$ V5 x, }" u        // 设置驱动器存在标志
$ R' A! s2 ]" N6 l1 Y. m        MOV  btIsDiskExist, 1; s! Y; h" L6 T% i) r

/ U' w, K9 K, T. m2 p( z* c        // 发送存取端口命令
8 w6 m- s! o9 F4 b        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,6 }: g1 y6 l% }- ]# P4 x
       // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令6 n  U. U' H  H: @7 x& W0 D: j
       CALL WaitWhileBusy5 p4 s" G& h" H+ L& H6 g) \
       CALL SelectDevice    // 设置主从盘标识3 [  N4 P; q/ B+ s
       MOV  BL, btAtaCmd      // 发送读取命令. l* b* W- X) J5 V, O
       CALL SendCmd# {' f% k- [  z$ S# o: n" J
       CALL WaitWhileBusy
- u  s, i& `  l- U$ v$ s' w2 |/ {1 f- t. B& ?6 a
       // 检查是否出错- [3 n6 @5 B3 u/ C( c. a
       MOV  DX, dwBaseAddress6 A1 C) s  F* r6 }+ q
       ADD  DX, 7
, a$ d+ P' i, H3 z
, ^  C" M: T, c) w7 C        in   AL, DX
5 B/ P/ |4 o2 K: N, T1 [
0 J; w+ ^% H6 i$ V) `$ i        TEST AL, btBit00
8 i; F% c  P% P# u        JZ   RetrieveInfo   // 没有错误时则读数据
. i6 N5 \& D( i5 O6 N1 b; h) ~( ^: d6 ]1 T' d+ N
       // 如果出错,则进一步尝试使用ATAPI设备命令
+ Q. P' R1 K- R& t        CALL WaitWhileBusy( y, i. E7 s+ T2 \9 R! A' c0 W
       CALL SelectDevice
" M2 M/ F; v# F/ k7 z        MOV  BL, btAtapiCmd1 u$ ~1 k' Z% @+ L; Z/ G' n
       CALL SendCmd( ]! g$ N: Q+ j6 a
       CALL WaitWhileBusy
6 ?7 {8 p, o, J; E0 q+ I& e
4 Y2 p: ]* k+ ~+ t7 [$ g( I        // 检查是否还出错$ {+ w( V; }; X" j) ^: {
       MOV  DX, dwBaseAddress
( M* v! \4 d1 G2 ?# c        ADD  DX, 7
) c( [2 h8 X* ]# t. A4 c' r1 f        in   AL, DX. y' X7 B" y1 s) Y! A
       TEST AL, btBit00' }$ j% V0 k+ }, |2 Y
       JZ   RetrieveInfo   // 没有错误时则读数据& `& ^7 C6 Q; f5 Z0 {" I6 R6 ]7 r
       JMP  LeaveRing0     // 如果还是出错,直接返回0 ^' }- }( L/ m: B1 h" _% j. D, l9 e
0 L3 \( L  A0 |) D4 I
       // 读取数据
3 t* b6 v( p" S        RetrieveInfo:
+ k0 H' \( i0 ^' T% h2 x6 M( j2 }4 w4 Y% V5 T0 o$ Z, W) K  O0 ~
       LEA  EDI, wOutDataBuf
, [; h+ J7 b% B  ]1 T        MOV  ECX, 2560 t- `, k+ }: m. w; r
       MOV  DX, dwBaseAddress
! V% P* Z0 ?; y% l% I7 n# |        CLD
5 l& m7 E( p9 G
! m+ [7 o# Y5 [# _$ Z1 h  }% _% ]8 n        REP  INSW3 t  b6 J& ~7 h
$ [- R6 N  Y2 ]6 ~( n8 b
       // 退出Ring0代码
4 s. ^2 t) f- \        LeaveRing0:
3 M) q2 Z8 C# T$ U- Z( D8 e' R2 R* B- C6 g, n0 ~" z/ o2 b
       POPAD
& \8 U8 k: M3 G8 p/ A        IRETD# @: f' H0 }) Y, ~7 E

( I5 [* s8 V0 n; {, [        // 激活Ring0代码! a0 X" m& w  I: p6 B# k
       EnterRing0:' H) ^" h$ u6 C* w( _1 K! _9 P6 B
. K( B" m' T& Z
       // 修改中断门
2 K. B; h+ D$ |& c, n+ _. q8 S0 t        SIDT FWORD PTR btIDTR14 U) J* t" w; k9 H
       MOV EAX, DWORD PTR btIDTR1 + 02h
* I' N4 o1 Y6 I" r) [) \        ADD EAX, nHookExceptionNo * 08h + 04h
' y' x% X% b0 H, T( \        CLI
7 r- k2 G3 F# C% H2 q0 H  }/ E% n
+ _: ^% f3 f9 X3 u, h        // 保存原异常处理例程入口# t+ R; b5 T+ r
       MOV ECX, DWORD PTR [EAX]4 I4 Z3 V% P6 r" {
       MOV CX, WORD PTR [EAX-04h]
8 c) J1 O5 K" m! q% N! A  Q        MOV dwOldExceptionHook, ECX
& Q7 g; ^& c* B) @( o8 L) }4 @# _# C: {% c$ l% t) {
       // 指定新入口1 t/ q: L: b, N+ j- b" d) M3 ?1 K
       LEA EBX, Ring0Proc
6 Y3 H. |" p* N7 H  _) H        MOV WORD PTR [EAX-04h],BX- y  p7 a$ n8 s- ~. `
       SHR EBX, 10h4 M* T4 [) B6 n$ F$ n- {4 w
       MOV WORD PTR[EAX+02h], BX1 }1 l/ @* \' M% ^
( z) Y6 k" H# |
       // 激活Ring0代码
8 f( A0 |5 t1 j* S% y2 H; y( A        INT nHookExceptionNo6 h5 E5 x& M; k% P1 C
1 o# j- V& j# j$ {9 P
       // 复原入口4 {) O; I/ L8 Z
       MOV ECX,dwOldExceptionHook4 x( T. b0 L  {, ]
       MOV WORD PTR[EAX-04h], CX" {6 }( w+ o$ w: R* w
       SHR ECX,10h# r' e7 v0 q: E, R( D0 r
       MOV WORD PTR[EAX+02h], CX& l: m% q4 O4 i, i# [
       STI* q$ ^- i0 I6 N; [
   }2 a) h5 D1 J& A5 r6 y
   if(!bIsFirst)
8 i( a( }6 E# b' ^  e    {
) a0 y- m/ W7 V( }! |        bIsIDEExist  = (bool)btIsIDEExist;
$ q. e- F% n1 c        bIsDiskExist = (bool)btIsDiskExist;5 N* b' w( s0 C2 o/ v
       CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));+ c8 P" @) t6 W7 k9 P2 C
   }( _& U; \0 P& U: U+ |
}! r; Y, F/ E! x9 i) d8 v
//---------------------------------------------------------------------------
/ m+ Y& ^5 ~4 g' f4 `// 调用方法:
5 X6 a5 D/ r0 ^+ q* x7 }; ivoid __fastcall TForm1::Button1Click(TObject *Sender)
% s$ _) L. L7 q( h2 s) u, P{/ M# x2 y. L0 ]9 i9 e. Q: K
   ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);% k8 Q! v7 n- y* E" a5 X
}
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2025-9-30 13:11 , Processed in 0.038468 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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