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

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

[复制链接]
发表于 2005-5-30 19:22:36 | 显示全部楼层 |阅读模式
  #include <WinIOCtl.h>
1 a$ ]3 D& S$ I- U& Q5 u+ \#include <stdio.h>! n4 z2 g4 v; ?# C, N  T9 x2 Y
9 C* y. C1 J$ Z5 O# J5 C
#pragma inline
7 l* G( N% `$ v//---------------------------------------------------------------------------0 _  H" N1 B' q3 M: Y" f
// IDE NT/2000/XP专用变量2 ~% s/ @/ j& u: R# q
#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS2 {4 D/ h; j" }( C
#define DFP_GET_VERSION         SMART_GET_VERSION
( k/ z& ~; J. y7 B, c1 \2 o5 v#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND' r: ^( L+ e8 _; D- Q
#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA0 }7 i, f( T: o4 M
. }) \/ y  ?5 ~7 p. x+ t
const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令
7 E* R6 A% }7 g  P3 V8 Dconst WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令8 R3 y" m  G  a# x9 K

& ^+ S* e6 |* p/ I' r0 Y# ^const int MAX_IDE_DRIVES = 4;0 J* m" w0 [: T) z$ o
$ |. g% P5 S2 B2 T
// SCSI专用变量/ @7 s! c* I# J& y- w- X; u/ P
const DWORD FILE_DEVICE_SCSI             = 0x0000001B;
6 ?% f3 V$ q. F/ sconst DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);  M( I) P( ^* `7 }) Z) d7 I) W! z
const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition& h6 b9 U2 q3 [/ h# G* T
const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;5 P7 i% {! `+ L8 `: U2 }4 e
. `* k+ e, D# `3 h8 l4 s- b! G! x
typedef struct _SRB_IO_CONTROL# v* J' W' b  k0 }# r
{, L5 i8 b9 {1 X5 [" }
   ULONG HeaderLength;
9 e- T5 T6 P; ~; e& D& c* e6 P    UCHAR Signature[8];+ J- c9 G/ x0 {- k
   ULONG Timeout;7 v' z  ~. d  C+ K% e4 J
   ULONG ControlCode;
) e$ m) A; o4 i" {% m    ULONG ReturnCode;
' D. X; h9 T9 ^6 p: k    ULONG Length;
" b7 V* w/ L7 X9 N7 [}SRB_IO_CONTROL, *PSRB_IO_CONTROL;4 e* E6 o: L& i( l- t6 l" |- h
8 F2 ?! ]2 _  [* e2 y( y
// 读取的主函数
7 f9 l% J  G6 N' Z0 ^7 e# t0 n4 uvoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);1 c9 j# W1 u& e, R/ C

* o  e/ ~9 I* o// 辅助函数
5 @' ~2 h5 l! M9 Z1 ~' N# pchar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
- J3 l. q5 a, @8 G, q1 h// NT/2000/XP函数
2 d. H0 |/ o$ H: [1 ~void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
0 ~* p, _6 ~, V, Z6 Zbool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,9 T1 d, @* N2 H, ^
       PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
: ]7 a. [. T1 h; i# X        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);$ _) X- m  Y4 t* Z2 Z6 F" @3 d
// Windows 9X函数
# `6 y( C9 l+ z; i3 Q0 h- W/ Uvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);
( z1 ?; U; T2 ]! u" {  ^+ A: qvoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
" U8 k- i& a5 J6 F        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
9 N, D0 S& L7 x4 u& U, v& F, E" d" r
) ^7 w/ \7 l4 n. P" C; q7 f1 P// SCSI读取函数(for NT/2000/XP)9 B, b, B; W) a. v
String __fastcall ReadIDEDriveAsScsiDriveOnNT();3 m3 \1 y" a$ a! o9 v1 \
//---------------------------------------------------------------------------
. J" ]; ?  Q) z% _4 W8 T! X' H  }: G// ReadPhysicalDrive7 B5 x; k& K! |
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
1 }  d+ f; _  w8 i{
& X6 e4 O9 e% n1 N    switch(Win32Platform)) |& B9 S- C" p0 [* h. x
   {5 y# j3 U! K) `* \9 X
       case VER_PLATFORM_WIN32_WINDOWS:
* I( x7 }" f/ l" ]9 G* C5 B7 ]' c            ReadPhysicalDriveOnW9X(pSerList, pModeList);
: n9 k1 o( }: C. H            break;
2 _" r$ R! ^# @2 {: ?) U        case VER_PLATFORM_WIN32_NT:
& o6 L, ]4 W3 G& i5 t            ReadPhysicalDriveOnNT(pSerList, pModeList);5 {  @- \# ~4 n3 e+ v& s/ p  {/ F
           break;
" H) W6 d- D+ u0 L7 b        default:
/ j4 l8 W3 Q9 d2 ^. [8 G            break;- x5 K6 u- Z' m$ f' R6 `$ i# @+ \
   }, \6 A' S8 x9 C9 @1 u& q+ Y
}! [8 {; l' s3 q! i& Y' A
//---------------------------------------------------------------------------
& |- l- R% o, J* R) s3 [2 G// ConvertToString8 ~  u0 S5 B6 K* M  }0 ^
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)) `0 K! ^; ~* T/ R9 N/ U
{
1 H4 U) o* [1 y2 D& d$ Y" Z    static char szResBuf[1024];
% z2 @, T. R; c6 l+ C  P    int nIndex = 0;
1 _) q% J& ~% C    int nPosition = 0;
0 g$ }6 m3 ]8 |/ @5 c
/ k- S- f0 x! h8 c4 l    // Each integer has two characters stored in it backwards9 ~# \( u2 V% a- d; n, h
   for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
* [! r7 F$ e6 x: `" T  F: f    {
* r- s+ u& i. B' |9 n: R        // Get high BYTE for 1st character
' \0 e9 K0 v% _/ [( D" d        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);; ~2 H" K% [" ]6 T4 ^0 Y, V
       nPosition++;  P& Q- Q& q3 K7 ?" H% b3 z" t
6 p: k  `- d* e" w) g  _! g
       // Get low BYTE for 2nd character
! n- S& e: l3 Q4 ?- j& J' L        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);( x7 L% Y1 D4 o& Z, s8 R' ~
       nPosition++;
$ D+ r2 Q9 R3 R: V0 {5 h1 c    }
* ~( Q/ l% A& L5 b4 C2 m4 K3 g
; H8 g+ Z; Y$ N! r9 f. }7 o3 H. S    // End the string, X$ w8 x6 k9 O5 A& V- |0 {
   szResBuf[nPosition] = '\0';
/ L& r0 ]# _6 F* M/ x/ u" l1 ?- ~, _
   // Cut off the trailing blanks
' H) }* F2 p; D' W) A3 o% n) }# B    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
3 U7 J* F( F5 s        szResBuf[nIndex] = '\0';
) a$ ^* l6 a- m
5 z& e  y! U# R/ u( |5 A- z    return szResBuf;! s3 A- H2 G+ W! i* d7 @
}. U- A3 W; ]2 _: ]
//---------------------------------------------------------------------------1 U& b5 U- V( h) e
// Winndows NT4/2000/XP 代码
) b6 E, |( V7 I0 D' L//---------------------------------------------------------------------------! i2 h8 _" q4 ^( l
// ReadPhysicalDriveOnNT
: R9 o. W( R1 T" }! R0 @+ X; r1 u  mvoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)! n9 R/ G, Q1 {$ i; \8 s
{- N$ n1 Q8 J) y! {6 [* `
   // 输出参数* Y: r' V# G3 d$ F
   BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
: h2 j& E( o; R& H5 |; j3 ~) u, I3 f& z
   for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++), @! q$ b' M. {- _3 m
   {, T0 e- @! n* P2 [
       HANDLE hPhysicalDriveIOCTL;" i) v3 p& [( q! Y: d, o6 a
       char szDriveName[32];* z7 J2 }7 N# D8 s) K0 G* w6 i& t
7 B- W6 f0 R3 W& h4 `0 ~& p
       sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);" I" i8 K3 E0 R( Y* ~( Q. a
       hPhysicalDriveIOCTL = CreateFile(szDriveName,
1 L0 D1 N  m* @( \; Q( ~. `                        GENERIC_READ | GENERIC_WRITE,/ V& ^) Q8 S6 c
                       FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
0 d0 ?* R3 ?& ^/ _% a; \                        OPEN_EXISTING, 0, NULL);
  c: V/ W# J- j7 G
* q  M: }" A% k) `7 x/ T  C8 [0 }% i        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
" E1 o1 S4 G+ l% N; c0 T$ m        {
" W, q( I# J) t5 }' G' J1 n            DWORD dwBytesReturned = 0;! H7 q0 c9 l0 Q& ~
           GETVERSIONOUTPARAMS gvopVersionParams;2 H& }9 h  Z6 Y* B3 n
- D5 x( [& e! {& E* m0 s4 M
           // Get the version, etc of PhysicalDrive IOCTL
( }1 |/ ]/ a  r# X            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));7 u2 j8 q( E4 N* b/ Y9 _6 ~0 e
7 A. R$ b# R# K- c) d
           if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
. `' T7 G. s7 b                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),2 @3 [0 k6 ^) b" ~9 T
                   &dwBytesReturned, NULL))
. R' V% `5 b& ]) C$ ?1 A& E! ^            {
0 X# e( Z* e4 l* R( ?' t0 m                continue;4 {+ R) F+ I1 T
           }
+ o1 R( K2 |2 D7 R; d- }8 Z9 n- l% T# V: \  P9 M
           if(gvopVersionParams.bIDEDeviceMap > 0)
: U7 b9 o' B; L3 u            {5 y) u4 ]0 u. u5 w3 o' l5 `8 }  G
               // IDE or ATAPI IDENTIFY cmd
2 l3 N+ y4 n' s                BYTE btIDCmd = 0;! M0 O" ]+ s: F; U0 O9 i8 N
               SENDCMDINPARAMS InParams;
2 Q4 s: V+ k- V1 f                // Now, get the ID sector for all IDE devices in the system.
, n2 m# _* W4 N9 J# M0 `8 s                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,8 T' }# B, S( D; J
               // otherwise use the IDE_ATA_IDENTIFY command7 B# ^3 R  v8 _0 |8 }2 ~1 d) B7 g
               // 具体所得结果请参考头文件中的说明
% B; p. b) I1 O$ x9 K$ R1 J- ^0 w# Z6 m                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?& N1 h: t* m8 I8 o6 N2 `3 e
                       IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
& H7 e2 a% g: s  v5 L                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));8 f6 u, e5 w7 m4 D8 P5 }) l
               ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));. L" e6 |. W( v3 {& N

! N4 m- G/ K4 [8 x$ J                if(DoIdentify(hPhysicalDriveIOCTL,
$ \7 t3 X7 g, x7 e                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,8 d7 A0 q) h+ H: A
                    (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
4 n  O) T% k$ n# b                {
; t. A$ Q' N4 I2 \6 `& F                    DWORD dwDiskData[256];
( |0 L  c, w* o) @                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
) ]3 I* W$ ?4 x8 M7 V4 j* T                    char szSerialNumber[21];
$ S3 {+ o8 k. N+ ]' R                    char szModelNumber[41];4 d: W+ A% S: x+ m1 R$ Q
2 A6 _5 |1 s$ ~/ g% Y( J  Z
                   pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;' Y; w! b1 [8 J. v: _8 G4 c# B
                   for(int i=0; i < 256; i++)  ^* p8 y5 H% Z3 z3 Q( \0 B$ o
                       dwDiskData = pIDSector;
9 S# C7 H0 c$ {% ]$ t  o3 u" _                    // 取系列号# f3 N% U* s5 |6 q+ k
                   ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
) P* W; w: |2 k8 P8 p% o) J                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
. K* M' @, l0 O$ y/ a% G; E1 T8 q1 B* D% `
                   // 取模型号2 |' a6 M7 `3 v* g  Q6 U& M2 O% p9 @
                   ZeroMemory(szModelNumber, sizeof(szModelNumber));" U8 ~' B. S! E: A
                   strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));" d3 @% W+ j* _, C7 o
1 k6 Q2 B/ Q, A0 G
                   pSerList->Add(szSerialNumber);; i( q. \+ [0 T2 I! K
                   pModeList->Add(szModelNumber);
) N, |  f) x+ s8 H9 n; ^$ U" V                }
* W; ~6 M$ H/ A            }
* l6 D# V. j+ n  }" K  ~7 ]            CloseHandle (hPhysicalDriveIOCTL);
! s& l. O/ c# M, ~! ?        }
8 s- U, p" Q; i8 b7 |    }
% `. i" J, M9 _6 n}& U7 r# `; y1 U( `7 c1 z
//---------------------------------------------------------------------------  y) r! V& G' }. e6 [
// DoIdentify
6 `# x& t! L& Qbool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,. p& j. O! |: c% H3 R, }9 `8 O
             PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
! ?. K5 g8 x. q$ t/ y4 ?              PDWORD pdwBytesReturned)# X) |! H3 H3 d* |" f* o
{
* t7 {% @4 z& w8 i. F1 _6 N    // Set up data structures for IDENTIFY command.% v3 @# W. _- [8 S  O; T
   pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
# R/ J& C1 P  \7 w. F! M    pSCIP->irDriveRegs.bFeaturesReg = 0;/ Z# Y9 j* }9 q0 S. o- v) w
   pSCIP->irDriveRegs.bSectorCountReg  = 1;
/ g1 P9 ]0 J+ _" b( |4 T    pSCIP->irDriveRegs.bSectorNumberReg = 1;
' `% W' o) C& s    pSCIP->irDriveRegs.bCylLowReg  = 0;
5 @0 f& }0 ]2 r    pSCIP->irDriveRegs.bCylHighReg = 0;' O6 I* P5 @  {# x/ U" f. G
; U9 x& F3 L6 Y
   // Compute the drive number.(主盘和从盘所对应的值是不一样的)# ?  A) X* `+ R1 H/ \6 t
   pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;/ ?8 N5 D! v8 d2 M! b0 U
, x! T* S4 G0 U4 ]) t* h' j- O
   // The command can either be IDE identify or ATAPI identify.! ?/ Z) d7 J% i% U- h' f$ {; M
   pSCIP->irDriveRegs.bCommandReg = btIDCmd;6 l* h- p' e$ o2 G* W- A7 x
   pSCIP->bDriveNumber = btDriveNum;
  G# {3 F9 C* `    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;; {! b8 {: S4 R

" q2 N- }# C- B* g3 w    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
3 I  o% O$ Y8 U1 x  ]           (LPVOID)pSCIP,
, ?0 |" b& x  U5 t( g           sizeof(SENDCMDINPARAMS) - 1,- k  O: L" h" ~" H$ V; E
          (LPVOID)pSCOP,
+ N4 l# B: t( L8 ?           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
5 \9 I  y, G6 e4 W+ R2 H           pdwBytesReturned, NULL);* O  f" d6 X+ p2 P
}
# j% V! C7 n, a4 V$ w+ ^# m: D//---------------------------------------------------------------------------& c6 Y4 j) t: G- H, B: L
// Windows 95/98/ME 代码" r! B  u; R3 @+ q% X4 N2 P) {" m9 b
//---------------------------------------------------------------------------) m- z0 }2 A1 ?. y( f, t/ T
// ReadPhysicalDriveOnW9X
* Y. K6 H# {: F) Q# G; I7 nvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList): f7 `- L: Y- d( ?
{8 P  T& C2 M& x( M# l( j
   WORD wOutData[256];
% E( {) G, Z4 _0 o4 W8 }    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
$ l6 H! P+ u& I: }) f& W# A2 [- T% }, _* R+ E
   // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。( M( H3 q3 q- z/ ?$ x
   // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以0 @9 y9 K8 k  B) R- _# {
   // 避免蓝屏的出现。(期待高人能指出原因)8 k. K  O8 L! ^/ K- P* ^* V3 H2 Y
   for(int nDrive = 0; nDrive < 8; nDrive++)
4 @( A4 W0 Q0 N) _4 K) G8 }4 A    {0 \, T3 L0 `2 c2 @
       WORD dwBaseAddress;
- Q8 w8 l4 t; S" O) w1 v6 c: f2 z& A        BYTE btMasterSlave;         // Master Or Slave6 E" e( @; }5 k0 i4 U
       bool bIsIDEExist;$ J% E- a' P9 z% Q8 v" u
       bool IsDiskExist;
  ]! E5 M# Y% k/ q* o1 X! r$ y9 G4 p3 |
       switch(nDrive / 2): A+ e! k- |0 o
       {
" N$ T! Y8 U! O* W0 ^            case 0: dwBaseAddress = 0x01F0; break;* P- P. Z3 j" Q
           case 1: dwBaseAddress = 0x0170; break;
# @1 e9 d" y0 U! F            case 2: dwBaseAddress = 0x01E8; break;
0 Y  A! i1 F$ [- V( \0 I% o            case 3: dwBaseAddress = 0x0168; break;
9 l" C3 V% O# Y9 l2 d        }, I' |& U1 }. I6 f

# S  l: e# U! ^- {        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);# g! v5 e4 D6 h
/ H  V' n5 m9 Y/ e
       // 进入Ring0
! s& @' E+ {5 y) t# S9 ~8 J        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
$ s( ]2 m; {; c. m& g  g                bIsIDEExist, IsDiskExist, wOutData);
4 q0 E. \$ S; K- u/ ?) u0 c" r, R$ T    }7 K( J$ z, ^& ^8 V

8 W6 s$ p( |4 I0 ~5 g    // 开始读取
7 O" y7 `0 d3 K3 b0 w& x    for(int nDrive = 0; nDrive < 8; nDrive++)
  P7 m" D* _, n7 r8 H. p7 Q: o    {' L0 q1 D3 L8 R' u3 t2 E
       WORD dwBaseAddress;
" h8 |. S6 o% K2 v" o) V/ v        BYTE btMasterSlave;         // Master Or Slave# ?& k  w# E) G6 N' B
       bool bIsIDEExist;
: {) S; g( ]5 w6 P+ ]4 L' F5 A8 W        bool bIsDiskExist;
# p* i$ ?, k0 B6 F6 |  q& k; l        switch(nDrive / 2)6 R3 [" T, I+ V- H) q! k! e7 ?
       {
, Q5 C6 @& v4 @, E" o            case 0: dwBaseAddress = 0x01F0; break;$ a  `9 L8 O8 r
           case 1: dwBaseAddress = 0x0170; break;+ y# n* F; a  y/ |$ d$ q9 B
           case 2: dwBaseAddress = 0x01E8; break;
: D7 c* Q* w' g' B0 e            case 3: dwBaseAddress = 0x0168; break;
5 z7 Z+ x- J# H/ t. x2 h' b7 j8 ~        }
4 u+ G' @3 D1 R! m, m) Q  Z+ r; ^8 ~5 e
       btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
, c8 Z9 B3 Q) w  t. J; M$ h1 V/ j  x3 j8 L3 S' W% @( \
       // 进入Ring04 x9 z6 [3 }* i" H2 q% U( q7 I
       bIsIDEExist  = false;
$ h  ?! t0 Y7 f0 M! y        bIsDiskExist = false;
$ A* K6 Q# w) m* `" ~6 k) P# ^        ZeroMemory(wOutData, sizeof(wOutData));
7 P7 e# ~" K5 o( h* j* }6 @+ P- c3 j9 o+ g
       ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
) W" K- Z6 w( c3 ]* |                bIsIDEExist, bIsDiskExist, wOutData);! @# W! k$ I. C0 i
# f9 m; X1 C6 x6 r5 ~
       if(bIsIDEExist && bIsDiskExist)
4 @3 z: f6 H. O9 M. N0 a        {
) |/ m/ ^# @5 L4 w' ^3 V9 H            DWORD dwDiskData[256];
/ i6 u* S4 m$ M; V! I) e% Z. L$ E6 M  ]            char  szSerialNumber[21];
) s/ X- c: z5 P6 M/ E            char  szModelNumber[41];
+ X+ W2 _; m  s5 b, v- ~; J2 F6 s/ F7 T$ T/ n  C2 e  F3 A% h
           for(int k=0; k < 256; k++): n% K  I( O8 w1 Z# Q) p3 h
               dwDiskData[k] = wOutData[k];
) }( [3 n6 ]% b) G+ }: ~8 O. V  Y- s! v
2 _9 s: `+ s, d6 @            // 取系列号1 k+ L) h9 L( V& t& G/ v' B) e
           ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
' `* b8 t7 ~8 N6 W  r* S            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));' }4 f: V+ e2 ^
4 V$ G3 `; O) N" w- V3 k  A6 Q: p
           // 取模型号
# U# X$ `0 H/ M+ @; R/ s            ZeroMemory(szModelNumber, sizeof(szModelNumber));
8 {/ H$ @: j# g* V# K            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));; v" O, {8 i, P7 ^, i& d( ]

8 l% h: ^5 S4 J, ]  R. N% v* M            pSerList->Add(szSerialNumber);
7 f, k) H: w2 F0 k6 \, \' y            pModeList->Add(szModelNumber);
( q* s: k/ [- M- y" F        }
  n' K1 r) e) h$ U    }6 C" H, j8 M! x6 `4 Y
   SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
. |5 g6 C1 n- u& ^4 i. Z}: M* Y1 x- \9 x8 N
//---------------------------------------------------------------------------
0 P) S% T8 a$ o# y7 S// ReadPhysicalDriveOnW9X_Ring0()3 h1 X0 ?9 a3 g7 t
//
+ [3 \' I6 X  Y* {$ o// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h; s2 P" g6 q" d8 v" x; e& s
// btMasterSlave = Master(0xA0) Or Slave(0xB0)
3 @4 x& v+ d/ w7 @4 X2 X' Y//---------------------------------------------------------------------------' m3 n, I& j& M! r
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress," v. F0 e, i* ?6 L& B
       BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
- z6 k$ z" b- Y+ B0 `, G' g{
0 K' [( x8 O* m7 I' `    BYTE  btIDTR1[6];# @$ A+ t  v) @. b: Y3 v
   DWORD dwOldExceptionHook;) a3 v4 L0 C( y
   const int nHookExceptionNo = 5;+ f! \" F8 P8 M; a

, ^7 z. I5 v& C* H5 D6 m( D    BYTE  btIsIDEExist = 0;
* E& j: p& ]# H& r0 m    BYTE  btIsDiskExist = 0;  `# Z. e& h- G- |& b5 d# w/ Y
   WORD  wOutDataBuf[256];$ X9 Q# H# M( X) O; _, [2 h0 I

- f! o0 ?' b! I    BYTE  btIsFirst = (BYTE)bIsFirst;
4 \# a/ l: `% f8 p8 o+ |
9 B9 ~  R* S# `% \3 N2 j    const BYTE btBit00 = 0x01;" d- p2 h. o- e0 `9 s4 `1 A
   // const BYTE btBit02 = 0x04;
, ]1 T5 w5 h+ s* E2 e" q    const BYTE btBit06 = 0x40;1 S( h8 s/ k. B5 ?, y  D8 r' g
   const BYTE btBit07 = 0x80;
$ a, d; w/ }( I" Q8 k    // const BYTE btERR  = btBit00;# Z+ d( F  B% J1 {+ A
   const BYTE btBusy = btBit07;
. k) ~. P0 Y; L* ?    const BYTE btAtaCmd   = 0xEC;
+ u. ^: V: u0 r( K    const BYTE btAtapiCmd = 0xA1;! R' Q( r2 t" J, d

  ~( V$ k& ~: }' w& A    __asm; {6 Y* K: F1 s% ?& M* e0 _- i7 d
   {
  q$ a$ x2 h5 H& ~        // 必须先执行这条语句
3 H9 i, C7 @0 b' e        JMP EnterRing0
- G" p9 n: L9 F* Q' y
. n- Y0 s5 s5 P/ l% D        // 定义过程
$ N$ y. U0 h) V8 n# R        // 等待IDE设备直到其不为忙为止% Q: r; Y4 N" o& }! d
       WaitWhileBusy proc" ~8 F# Q' i* b, M' D. [

5 [) z) F4 c* `# S$ A' b1 o3 I* }! G        MOV  EBX, 100000
/ h/ Y) t& j* c# v7 T        MOV  DX, dwBaseAddress7 A, }# J/ b% D8 S
       ADD  DX, 7" C- r7 {3 m5 j: D/ a1 R

) f. Q) g$ K/ h9 t        LoopWhileBusy:# z! l; S; V& `3 K3 m

' w" J. Q; ^  j        DEC  EBX
8 y) `9 I% n  N6 j# @+ _        CMP  EBX, 08 ~& k. N3 C! i$ J1 H+ A3 D
       JZ   Timeout
, Z* Y9 `, `) g! K: T  R        in   AL, DX* P# M$ n' P; w$ D6 d! ~2 P
       TEST AL, btBusy
. l" l8 |& l4 Z; A) I- }* V) P        JNZ  LoopWhileBusy+ X1 w3 ^1 r, R' c7 f
       JMP  DriveReady( [" I$ e- {) ?- Z
8 n9 M$ s) S3 X3 s9 P/ t. a1 r
       // 超时,直接退出5 t! y' z: T* T+ f8 j
       Timeout:
' V3 P# B6 m+ r( B* T, N        JMP  LeaveRing0/ b' |( w9 b& i% Y2 }0 C( l" K3 f
       DriveReady:
" p; x; [7 j( A- b& H        RET
+ S9 O3 r# X% a' N  `1 W5 C        ENDP   // End of WaitWhileBusy Procedure
# w% [  B2 w# w) |+ k2 E+ z
, T, @5 x1 X* }* ?! \1 w7 W& _4 h3 p        // 设置主盘和从盘标志9 t7 S- q6 b5 ]
       SelectDevice proc) B) o+ t+ P5 z1 D# `) Z

$ U1 B- m& ^+ I; x% S( h& i' A        MOV  DX, dwBaseAddress
+ y  i, k  z+ R- F: u/ Z        ADD  DX, 6$ H% V- z/ c! C; s8 q* T+ f; W5 V
       MOV  AL, btMasterSlave
0 _, A: s) X; o" D& s! `4 G! `
1 x; ~& t1 E- y4 X4 i        out  DX, AL
# Q2 Z# e% R) F: l9 T7 o/ K6 ]        RET5 Y# h( j( \4 E+ e

$ K; z# t& f* [) i1 J4 h        ENDP  // End of SelectDevice Procedure
+ F8 X, s7 T/ [: |& U) }9 t$ {6 U* k% D, c) n- ~0 j
       // 向IDE设备发送存取指令
- @4 |! K: t/ R+ V        SendCmd proc5 z% \2 o5 R* v3 }+ w1 N4 }
# d+ z: [0 z- `5 f2 X
       MOV DX, dwBaseAddress; {* `- I, Q* w' y
       ADD DX, 7, S/ C0 l* ^7 N% J5 J, l
       MOV AL, BL // BL是主从盘标识,在过程外设置
& N: L$ w2 d: ^# |0 g        out DX, AL- p+ I& Q$ M% Z6 p& J6 h/ _* ?; W7 [
       RET
/ W* m2 E9 |! x+ F! h, P        ENDP  // End of SendCmd Procedure# R* v# R4 c  P  v

' P2 ?8 N* o# S        // Ring0代码
" o5 {1 v, |$ z% k8 R        Ring0Proc:" `$ D3 }  X4 E3 r0 b' d' I
       PUSHAD! s! l- u1 R8 E
       // 查询IDE设备是否存在9 x: g0 x" v0 D% f& R
       MOV DX, dwBaseAddress
* n& |6 i3 I- P5 L9 i& t        ADD DX, 7
/ [/ O: Y5 L. z9 c8 [2 b& p+ t, y        in  AL,DX$ j6 f& W1 I& x0 D0 R* o
0 T* y0 c; l) n: V$ U& L
       // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回2 [9 Y7 T8 d# z5 M9 Q
       CMP AL,0xFF. K1 G/ a- y% N) S) f% z9 |- d
       JZ  LeaveRing0
) m3 l- I2 v* |        CMP AL, 0x7F. l7 A" m( R/ D% K1 C" e* L' \
       JZ  LeaveRing0
" i! h7 w9 J! p; X- F* p" Q
( ~/ A; i' X1 ^8 X3 m0 t        // 设置IDE设备存在标志
, M+ f- ^' M3 |( v0 f! G2 A- b0 G        MOV btIsIDEExist, 1
3 u: F0 u. ^. E/ ?0 {/ p& K8 t1 u/ g6 Q6 b
       // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
. }6 \# U7 a) T$ |2 K/ X        CALL WaitWhileBusy
: f5 U( {5 O2 t! y4 f        CALL SelectDevice
' F. c3 G% x( i0 i! M8 p# i* d8 y  A$ g0 \. }, N9 U
       // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
- \, z) H6 R0 t  m0 f" N        CMP  btIsFirst, 15 p# ]4 d. d1 o( S
       JZ   LeaveRing0
" b: s% E/ v# q) m4 r8 s: d0 r8 V9 Q  t- N
       // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
2 g) b$ H8 k: u+ |. u8 H% L. l0 j% U4 n        CALL WaitWhileBusy" E( v* m; P7 U

6 U/ V7 ?& H6 z& I  z; [  S        // AL的值等于cBit06时,不存在驱动器,直接返回
  K  O9 h# M7 s1 L  R& v! @2 d, p" c        TEST AL, btBit067 _+ J2 d; g: S$ K% ]! Q% \2 H
       JZ   LeaveRing0
' ~" b' G9 D0 U8 }* l3 Y& m2 N$ j8 U% [1 e" L
       // 设置驱动器存在标志! A8 Z1 F* `' p( v$ P
       MOV  btIsDiskExist, 1
! a5 D3 d( G4 ?7 a; o/ o7 C$ ~' j6 p7 E' X. H$ c5 N: G
       // 发送存取端口命令$ ?( Z0 G' k. V- B/ i& Y  \
       // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
; J) Z' ^5 h& }5 H7 @7 v        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令# ?* ^6 V4 p) U9 x: C& G
       CALL WaitWhileBusy
! b* |  \- Z3 @$ r5 x        CALL SelectDevice    // 设置主从盘标识' D+ N: g) O9 M& R2 f
       MOV  BL, btAtaCmd      // 发送读取命令1 Q. O$ a& y/ [3 n% k
       CALL SendCmd/ `3 _: S& q0 j- I
       CALL WaitWhileBusy) {# ?% ~) [) \# }
' p9 \4 H8 B0 V' P9 |4 J
       // 检查是否出错1 z: z/ J' L4 d
       MOV  DX, dwBaseAddress; u& r" u, w  z/ F; d7 d  S
       ADD  DX, 7
0 B  ?8 K' o$ w' u2 K, ]6 U
  i9 V1 p2 V  @- Y5 u1 I        in   AL, DX& g; V  M4 u& u* U7 O( M9 P% ?( c
- O& B3 @, I% l% S! Q5 b
       TEST AL, btBit00
! l# k# D+ x' _* W! \  K) t5 w* e        JZ   RetrieveInfo   // 没有错误时则读数据
  ^6 p8 T& C3 p
9 R1 i4 @3 o" v, h# _$ g4 J. }        // 如果出错,则进一步尝试使用ATAPI设备命令: f4 [& N4 h, h1 E4 |- v
       CALL WaitWhileBusy- v8 P* A3 R  J# u: {
       CALL SelectDevice
* G  O/ P% v5 T3 }        MOV  BL, btAtapiCmd
7 M$ B! B- C8 e) }; S6 r5 i" I& X        CALL SendCmd. }' @: h7 C7 r8 |( x, M/ L. M, y
       CALL WaitWhileBusy/ g1 |" q& F5 G9 P; v1 g

2 {$ d; B7 t, C% o6 g5 {+ J; z/ t        // 检查是否还出错
$ l$ u. C3 }& T$ P5 |( u9 ]        MOV  DX, dwBaseAddress
7 v  Q+ g. F! T  z0 j        ADD  DX, 7
6 F% V% }7 d1 B( A+ N/ G; P        in   AL, DX
1 O" Q' s+ x$ D/ `# E) ^        TEST AL, btBit00! z6 `) ]+ z/ A
       JZ   RetrieveInfo   // 没有错误时则读数据7 g% h/ x( U9 M( Y0 ]
       JMP  LeaveRing0     // 如果还是出错,直接返回4 ]2 r' ]0 Q! j  w) D! U

+ [; Z8 e( G+ Y0 l0 c        // 读取数据
" {4 P/ I2 |/ {- f        RetrieveInfo:8 L5 A) f: i4 }; W5 W' @( X
7 x: u: c4 T1 q+ z, T9 S
       LEA  EDI, wOutDataBuf- f. D* j% A! h* w$ ~
       MOV  ECX, 256$ q4 {! Y9 Y  O" w
       MOV  DX, dwBaseAddress
* H  ?4 y& \; W. p3 E! G/ X( Z0 U        CLD
6 G/ Q4 d& }. t5 l  u6 u" j
* o+ t/ w6 _' R6 Q        REP  INSW
5 v4 T( _& R1 N. `, f; p+ {7 T+ O! x4 V% b
       // 退出Ring0代码- q* B$ J, L1 |# Z
       LeaveRing0:' S3 h- @" I. f, V! c; U

, u" r. Q. w( t5 Y" y" _" G4 m        POPAD/ W3 n4 c" Y3 |/ `, r. n
       IRETD4 o2 v* b' l0 K3 C$ [5 s, ~  o1 ?1 x) E

1 t1 c$ D' m# l( l1 T$ y        // 激活Ring0代码/ G7 s- A( X5 [
       EnterRing0:# Z( |: W$ E" ?; y# l  E: A( S4 |

7 z0 d  W& P- D9 G6 _& ~' i        // 修改中断门  V' [% o5 C0 ^( y, M1 M
       SIDT FWORD PTR btIDTR1
6 o3 v* Y( T% Q8 _' S6 T        MOV EAX, DWORD PTR btIDTR1 + 02h% N8 W% j( w, Y6 I
       ADD EAX, nHookExceptionNo * 08h + 04h( i4 H/ g$ ~6 Q) p
       CLI
: j8 j( ]. U8 ?& `" `; Y1 w. y# v8 K' |
       // 保存原异常处理例程入口" ^2 q% u+ p# w7 [8 W  T1 `
       MOV ECX, DWORD PTR [EAX]
( X9 w2 g: C# [        MOV CX, WORD PTR [EAX-04h], p7 j* ~' s, A0 c: U: K; d) R5 [4 ]: I
       MOV dwOldExceptionHook, ECX3 ]2 I0 p7 X3 o
% E( c/ W8 C; W3 V2 k8 |: N" |+ d
       // 指定新入口/ ~1 u& e5 Z0 Y- g5 W+ K0 P7 O+ B; i9 S
       LEA EBX, Ring0Proc
1 A# n; p( t8 B( V' X4 N        MOV WORD PTR [EAX-04h],BX' @( u. i) ~7 C5 I% R: y
       SHR EBX, 10h9 S( i" L, N2 M" ?/ u! n' m; j3 E
       MOV WORD PTR[EAX+02h], BX
* V9 T/ d9 k8 @5 \0 z+ _0 h5 g8 |, H% t  u& ]
       // 激活Ring0代码
( B( H; ~# r3 I( b; o        INT nHookExceptionNo" J. v4 e. f) Z
, e0 ~) `. U, n4 L
       // 复原入口; I2 h0 ]/ g/ _( Q9 A4 n8 q' V3 E
       MOV ECX,dwOldExceptionHook
4 e: `4 l, x3 s" u9 }; A        MOV WORD PTR[EAX-04h], CX
  [! R6 X" k) W; ^0 r5 o        SHR ECX,10h
% M8 W4 w, q% X" C  m' l2 i& i8 c        MOV WORD PTR[EAX+02h], CX" z, G7 f% k+ b0 g
       STI
+ t5 c: l. q5 L- t: ]2 I0 a    }3 Q# I+ ~( ^6 |/ W! C
   if(!bIsFirst)
* C' Q+ F7 A4 ~' [0 F    {
+ B& _7 I" u6 Z        bIsIDEExist  = (bool)btIsIDEExist;+ q0 k& t5 m6 J" L! U! q% ^. S: a
       bIsDiskExist = (bool)btIsDiskExist;
! f) t5 {& E5 \  e/ r# C8 v- w9 K        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
$ E" W! M, _; x! B& d! H    }  V1 n- h7 t9 n
}
$ J* L% n) a: @/ R$ V+ ]5 ~3 W//---------------------------------------------------------------------------0 L  X9 Z; T, ^3 h
// 调用方法:
. c3 N' I. D: z* v1 i" F9 ^8 D. c$ m+ Mvoid __fastcall TForm1::Button1Click(TObject *Sender)# n3 O- }+ s; F5 I7 I$ A" d
{) u& ^% U. H# z! z/ j7 p
   ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);/ Q" I" H' H6 w# b+ z
}
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-8-14 00:06 , Processed in 0.019612 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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