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

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

[复制链接]
发表于 2005-5-30 19:22:36 | 显示全部楼层 |阅读模式
  #include <WinIOCtl.h>
# v# W/ X% a# t2 Y6 E+ T+ p6 X#include <stdio.h>( }9 d4 B/ B4 ^

2 |- h7 L  k$ i#pragma inline) t+ ~  v! e1 W8 t
//---------------------------------------------------------------------------
+ Q0 r2 A0 E! U: G3 d// IDE NT/2000/XP专用变量9 S/ v/ b* p2 I
#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS5 M7 ~1 v3 q0 |% S4 d& @' C2 {% J
#define DFP_GET_VERSION         SMART_GET_VERSION  K; g, ?$ F! ^
#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND8 x% @* h; E9 Z* y1 }
#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
+ h" R  Y% s. ~& d( O. o/ Z9 C) d' D$ ]- _* l9 d0 K
const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令: E6 c2 w7 ^1 f6 Y) w. M7 Z4 l
const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令$ x+ l2 U6 i$ p. b

+ m  G1 e- M4 w+ ?" \1 x" _' bconst int MAX_IDE_DRIVES = 4;. I% Y1 z/ G- q2 y

# G6 |  [8 p0 i5 V$ M9 D- D7 k// SCSI专用变量
2 J0 X2 G: b" E& f1 M3 g9 vconst DWORD FILE_DEVICE_SCSI             = 0x0000001B;
0 }0 H( z. W* zconst DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
" J, }7 P: E$ x+ \. I0 rconst DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition2 k4 V8 m; F) \) `& H
const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
! C* V- V4 J: G6 t
0 X# [7 Q+ ^8 T$ D' Ctypedef struct _SRB_IO_CONTROL
4 ?( Y0 r& T* N1 h& \* ?" V{  ^4 a1 d' |) z/ b, S7 ^# z  B; g
   ULONG HeaderLength;
* C/ X# k3 ^. T3 q: v0 ]% J) T    UCHAR Signature[8];) E2 }0 M* M9 i4 E& z) s! ?: Y1 @6 R
   ULONG Timeout;3 {) Y2 ^$ ^: P1 r: r
   ULONG ControlCode;
; o% g4 c% g1 B) H    ULONG ReturnCode;
2 Y' R" n* v* \4 j4 n    ULONG Length;
% L# w! m( W1 o5 f: f5 \}SRB_IO_CONTROL, *PSRB_IO_CONTROL;
3 R- m( @/ u* I% J4 ^  _
* ~. l. L' I* ~' `$ r7 w// 读取的主函数7 Z0 i* z1 B% T% `% K2 ?5 D
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);  p# `& G1 ]1 _2 j9 @

. w. B# D+ U) e3 v6 A// 辅助函数  a0 ^) N, i) ]9 G! ?! X: h
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);! n8 h/ q" [9 I( Q
// NT/2000/XP函数9 y  z& ~; D& a) g8 _4 W5 b
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);4 C* }8 K& G0 ~, f
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
% P2 o& i+ `/ s; e7 R5 T, O) Q        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
" a* b8 n% s) p6 l        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);- O( N: z9 ?2 S1 m" y
// Windows 9X函数( X7 D/ }/ B) I$ S( ~
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);
( ~4 o7 L9 X! Gvoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
/ V5 n; Y( \. D3 Q        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
7 K0 n' l  ^; x5 u( @
6 W( e1 p5 q) k: c1 X// SCSI读取函数(for NT/2000/XP)% M0 |1 r1 u$ D- v9 M5 p
String __fastcall ReadIDEDriveAsScsiDriveOnNT();
6 r0 `& ?# ?" p0 M//---------------------------------------------------------------------------
9 J% P2 F: \7 U1 T/ ]% j. O// ReadPhysicalDrive& q. `  M0 p% U. n/ }. `
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)$ I" d6 M$ K3 y: l
{
4 y. \4 s" W3 a' U5 b    switch(Win32Platform)2 g0 u, G. \7 M1 I
   {/ _8 n  q6 B4 {, A, P; Q
       case VER_PLATFORM_WIN32_WINDOWS:7 U4 y( h3 M1 [6 A5 }4 ]
           ReadPhysicalDriveOnW9X(pSerList, pModeList);- A& h+ I. X9 f7 F, m
           break;) z/ \( F2 J& u+ }3 C: q$ F' I
       case VER_PLATFORM_WIN32_NT:
4 ]) n" x. i5 M1 R7 K( N( R            ReadPhysicalDriveOnNT(pSerList, pModeList);
; Y# c* m6 K7 y7 g* ]& Z            break;0 C; [3 i2 g! N* m4 W2 M
       default:* k7 t1 G% L( o( q+ p
           break;% \0 E; a$ I% D
   }, R7 Z5 B; ]7 @; F" ?4 U3 Y/ v1 Y! h
}" u, H; {4 t: X7 O2 W
//---------------------------------------------------------------------------
8 N( V0 ~! ?$ f; u' I/ p// ConvertToString
/ o2 J- S% z* X0 V$ s; jchar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)$ {) t, w2 t! t: t- z
{
9 o$ T0 @0 H$ A: a7 _    static char szResBuf[1024];& d, h, H) o0 ?- m
   int nIndex = 0;5 s+ n5 `5 E3 m: N1 D3 B
   int nPosition = 0;
5 U2 D0 y1 V$ e# |* r" {7 j
' t! }+ @, e" l    // Each integer has two characters stored in it backwards; n6 v  l5 ~5 e: q& B. g/ f3 D
   for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
1 H# [- m& @( |9 f, e    {
  F$ _! S- _: D% m8 u        // Get high BYTE for 1st character
. d! d* T8 V' i. l4 k! J9 S        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);2 j: X  h, Q3 X* p; V; B
       nPosition++;+ L) W" k# _# M: f9 N8 u  c

3 Q( k% r0 m4 F" Y5 F8 Z, A/ v  V        // Get low BYTE for 2nd character
. r/ k, D- m1 Y! x; d/ i9 Z        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
# H: d" u5 a+ c: T        nPosition++;9 _" F4 u0 {' p5 ?+ e  M
   }
: H8 |* i* H3 W. t
* H) m1 {/ e, E: w0 J( V. l$ k1 ~    // End the string
) E. _2 u5 n5 w; Q( |2 A    szResBuf[nPosition] = '\0';
0 E. @2 _% Q, I- q0 c( j( Z# j1 G/ H- K0 p4 K$ C5 L* m+ d
   // Cut off the trailing blanks
. c6 f; x6 K% @6 [/ _  k  T    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)2 X8 f3 B$ S2 _- V% U, t# b
       szResBuf[nIndex] = '\0';
2 x# \) W4 S4 R* E1 ]2 i! W/ J6 W
   return szResBuf;) r% x5 e5 Y2 H' E4 `  o% x, O
}
2 l/ A2 M/ l% \//---------------------------------------------------------------------------/ Z7 T3 T: f$ V+ D# {
// Winndows NT4/2000/XP 代码' h' f7 \! k+ U
//---------------------------------------------------------------------------
9 _% s, ]1 v0 b/ q% Y8 T  C// ReadPhysicalDriveOnNT; Z% x) h: A1 |. W- H  J+ @
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)7 Q* g8 s1 n) W9 U% T+ A
{
/ F& l8 Z7 b6 a6 q    // 输出参数
$ ]- {+ j+ K& ~! r- t, i, Y    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];4 Z! f" t) m* ?0 d

8 e! G! _2 @- c9 [8 }& ?" ]    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++); K+ ?! y2 {2 n- w
   {
; T0 |/ w$ J+ m        HANDLE hPhysicalDriveIOCTL;; k$ d" O: G: P3 S+ K- ]5 i: |7 ~
       char szDriveName[32];( a, |) i8 D( V* ]$ ^* L0 z/ w
# b; T( }4 D# H9 d" u
       sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
% X+ Y7 M# u& X+ |/ F/ S% C$ ?! R% H        hPhysicalDriveIOCTL = CreateFile(szDriveName,- X; ]9 U, b: s% p) o9 C5 u, t3 B
                       GENERIC_READ | GENERIC_WRITE,3 s8 h# n3 b2 l8 q+ [- @
                       FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
: |: Y- e! ?& `+ _; Y                        OPEN_EXISTING, 0, NULL);
* `+ }5 j. _" G! B7 t" b" y. f9 b; c2 ]0 U/ `+ k
       if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)$ U9 O4 h# j5 A" b+ I3 v( P/ B
       {# ?# o$ K3 ?2 V& }; g6 w
           DWORD dwBytesReturned = 0;" r3 t4 D6 D5 W/ j3 H) }
           GETVERSIONOUTPARAMS gvopVersionParams;
( M  r. C. F" V6 D
: I, V2 a1 G& t0 a! I2 X            // Get the version, etc of PhysicalDrive IOCTL8 R" f5 V# q- m0 K: [) h
           ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
" n  ?! c% q% N! Y, u. G/ I$ d4 W7 t" T$ z) f2 {
           if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
  L  t1 j! e6 ~1 G/ o                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
8 S9 ^7 Y' E) l) ~" X1 u# i; g                    &dwBytesReturned, NULL))# P. ~0 e. ^3 q# v6 r+ S; ^4 a- e
           {3 S! C0 G. d0 Z
               continue;5 s: G9 k5 A( X4 N6 e3 q
           }$ Y. r$ ~$ g  U2 w
7 R* ]% M6 S6 U: L6 r$ g0 p6 m$ x
           if(gvopVersionParams.bIDEDeviceMap > 0)5 I' z" @' L" n  b# |# d9 }
           {
+ s. p& A# _, z/ T5 l                // IDE or ATAPI IDENTIFY cmd" M* }8 ?" {5 X* M" b$ A2 n
               BYTE btIDCmd = 0;2 ^* \. d2 ]! l* m/ g3 m7 N
               SENDCMDINPARAMS InParams;+ `  ]  E1 o) s6 p
               // Now, get the ID sector for all IDE devices in the system., f! Z  \$ _9 S% P
               // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,- ~- R, h, r3 ^1 m
               // otherwise use the IDE_ATA_IDENTIFY command
* X/ b$ u' O8 Y- A5 ^5 h- g                // 具体所得结果请参考头文件中的说明
" o" i/ T7 a, D- g1 T  G                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
( v6 f7 ?8 j8 O( [, z/ }0 S                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;$ `- N8 ^0 S9 o0 j
               ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
4 t4 Z- L. h' r                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
3 Q4 _5 c+ @7 w3 L# }# P; E. S" R5 Q; I& C
               if(DoIdentify(hPhysicalDriveIOCTL,
1 i9 h( q$ {% B% l' z2 o                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
& j$ n1 b) f) q5 \, p                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))4 C* I: o9 y0 W+ u" c+ e
               {
0 S3 b3 Q. v2 C2 A4 @. I- n2 V; J& S                    DWORD dwDiskData[256];8 q6 s5 s, r7 b" I' F" }4 }
                   USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
- J6 e- f8 m# [5 _3 `                    char szSerialNumber[21];
( g9 {# B" _% h: s8 \/ V1 l# K6 T2 b                    char szModelNumber[41];1 E5 t6 H# k0 e0 x0 u; m

2 v/ d: x7 ~% O+ h6 A' j+ c                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;8 e# m( _, `4 N: A+ x
                   for(int i=0; i < 256; i++). p7 \. P0 t6 m2 X
                       dwDiskData = pIDSector;3 i# f1 E6 M1 i9 f2 g
                   // 取系列号" G& ?. [5 Y, Q
                   ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
4 o6 Y& o. G0 I                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
4 ^: _3 @8 {, z3 I1 a, z: {9 t' R) C2 {% Z
                   // 取模型号, m7 d9 X5 g3 |( M6 F% c
                   ZeroMemory(szModelNumber, sizeof(szModelNumber));$ O; p( B/ y: g5 F3 V
                   strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));: T1 R. w. U2 Q' N7 X

& \) M4 W. @% p, _" U                    pSerList->Add(szSerialNumber);
0 c5 S8 R* B) F3 c4 W- {                    pModeList->Add(szModelNumber);
) \  T8 i. U1 U; I! T0 Q. ]                }' ~) l6 y0 L& Y" s9 O, @2 L
           }
" J6 T% z7 H5 y+ v* q6 R            CloseHandle (hPhysicalDriveIOCTL);2 X4 S. J7 `/ ?; b/ F1 M
       }2 F. c7 _5 j7 [  h( o8 ^
   }* w) g! M, s# @0 T# i- _1 B
}6 e3 E2 P; _% j7 o+ W
//---------------------------------------------------------------------------
0 j( J& B5 H5 `+ n7 u8 l' t9 ^// DoIdentify/ {8 S% {# t+ {$ P% m3 @2 K' o
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
6 H2 J" t$ O8 I$ o' A% W: J              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
  E! m" c/ L: s* K1 A1 H5 `              PDWORD pdwBytesReturned)
8 A; D: d# A6 C( Q1 n) W{, C* y( t. f2 j8 ^( i
   // Set up data structures for IDENTIFY command.
7 c) c7 G, w( ^2 ~& u! {1 |    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
4 n6 C. c1 O* ~" q+ d" b    pSCIP->irDriveRegs.bFeaturesReg = 0;( Y% F5 E6 p) N7 S" ^2 p
   pSCIP->irDriveRegs.bSectorCountReg  = 1;
' {' T1 a* H2 j. d/ n" ^    pSCIP->irDriveRegs.bSectorNumberReg = 1;
2 e8 `  `( I6 h" [    pSCIP->irDriveRegs.bCylLowReg  = 0;$ D7 o3 q3 k/ p: {$ N+ m
   pSCIP->irDriveRegs.bCylHighReg = 0;) J! }* @! i% A( p% E
8 e# T9 }0 e( O0 F
   // Compute the drive number.(主盘和从盘所对应的值是不一样的)' g' ]. P8 L5 J5 q& Y6 s, g0 s1 \
   pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
* `$ m- g& x5 H" j$ h/ `; L. ?) w) b! S% M% X1 N+ Z2 w
   // The command can either be IDE identify or ATAPI identify.& E5 z: n% A2 @3 ]1 C
   pSCIP->irDriveRegs.bCommandReg = btIDCmd;1 H, F0 U; o! c, z0 A7 K
   pSCIP->bDriveNumber = btDriveNum;: s4 W, d: @1 ?
   pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
9 e# E( x( u! Y5 U
0 l) @1 b( z2 y/ F    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
' n6 l9 {# I* d" N- a! W% m4 y2 R1 }           (LPVOID)pSCIP,
, V. {- C9 |: n- ~: u! F           sizeof(SENDCMDINPARAMS) - 1,
& ]2 E" c. r: y' k$ S+ S           (LPVOID)pSCOP,
/ b* d3 r8 X' |           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,# x+ f, I" D; l3 v( j
          pdwBytesReturned, NULL);/ w1 g( g* D1 ~
}% F' B% Y) b/ Y0 h. m" ^1 T
//---------------------------------------------------------------------------
: x3 q$ Z, S  z  W$ J+ i4 j2 T// Windows 95/98/ME 代码
* p" T" @$ d1 F8 {& W2 D//---------------------------------------------------------------------------+ M" A3 N! }; z3 r. l# U( Q
// ReadPhysicalDriveOnW9X) _: n4 d+ A+ m  a/ ~2 k8 k- A
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)" D2 Q! h4 }* D
{
! M( u3 I# _8 w    WORD wOutData[256];; ^7 R1 a+ B# }, `' j
   SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
# B8 e5 o, X+ m' ]4 e# Y
5 D( ]$ s6 S1 n' o9 j+ @    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。) \& M  B3 O: Q& E( {/ [
   // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以9 W( r, x0 B2 F
   // 避免蓝屏的出现。(期待高人能指出原因)' }4 q! X* h2 u# \/ K" }+ z; P0 E/ Y
   for(int nDrive = 0; nDrive < 8; nDrive++)# F3 u# y* Q+ U$ ^
   {
- U; B4 O- O* Y6 ]  P" j8 s  J. c9 B        WORD dwBaseAddress;
; i) v$ \, p# b        BYTE btMasterSlave;         // Master Or Slave
8 N4 q4 Y& Z0 A* p( V7 a        bool bIsIDEExist;! \' ~8 V2 M6 w# S, b9 \
       bool IsDiskExist;6 `& V$ ~1 U1 F7 M% y
. g7 U& L* a2 [/ h$ X
       switch(nDrive / 2)2 j8 Z2 k; G5 H. n5 p8 y! ?
       {* [. t- s0 \) u: D: I
           case 0: dwBaseAddress = 0x01F0; break;
, |6 g9 [  f* x) c& D; d( P$ o            case 1: dwBaseAddress = 0x0170; break;
8 e! @" K; l# M$ E- e            case 2: dwBaseAddress = 0x01E8; break;
% ?* M6 t0 q" R( f+ m" n! W            case 3: dwBaseAddress = 0x0168; break;
1 H8 T6 b7 N) ~# T* W2 Q/ L0 l        }
/ O  a: R1 s' W! J' C6 d  f: G1 T6 Q- B: q
       btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
3 x3 F6 _  d" v, J( Q  @3 J; O# r
# D# v! Q3 O+ t. _1 W) x        // 进入Ring0+ n. w" E9 B* h
       ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
& t0 {8 j. f. C1 N  k* j+ ^                bIsIDEExist, IsDiskExist, wOutData);
& ?2 y2 A* a) h    }! h+ u6 d; C4 x( Z7 e2 R
: k, R. l5 n9 R6 F* q& J
   // 开始读取) S! g9 [  N- I- b: ]
   for(int nDrive = 0; nDrive < 8; nDrive++)
7 }* p6 `. l: k( D  e$ b; v/ S    {
+ O0 I3 z6 I& y        WORD dwBaseAddress;
7 d) g+ Q0 h/ g, n1 R2 j        BYTE btMasterSlave;         // Master Or Slave
* ?% H9 R* R+ u        bool bIsIDEExist;- {5 Q2 M- u, e; B
       bool bIsDiskExist;- z4 |' T* H  w$ P
       switch(nDrive / 2)
, R- P, @( i% n' _& k% O5 h3 q        {9 z) X7 a! N% ?2 Z, ^: ?" A
           case 0: dwBaseAddress = 0x01F0; break;
2 e5 L" x0 s7 L            case 1: dwBaseAddress = 0x0170; break;
! _6 G" ^/ |/ v; p+ h3 G            case 2: dwBaseAddress = 0x01E8; break;  `4 X3 Z9 h, l" @$ H. q
           case 3: dwBaseAddress = 0x0168; break;
4 O" y( B% g" ]        }
, J) H, K' V4 `3 N1 z9 O
3 B: j/ S& z  g4 R4 [        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
  B) o4 e3 o6 v* q& H
4 H0 M2 U" {# v9 `( c- j! A& g8 r! E        // 进入Ring01 |4 }: ^% ^- V5 D3 H' T1 x% J
       bIsIDEExist  = false;
3 M# t- T6 @2 o3 b2 p        bIsDiskExist = false;  P  O9 }  K; s
       ZeroMemory(wOutData, sizeof(wOutData));
9 y" g* U6 v+ Y* E7 M7 R
2 r; f! O7 J; [3 Z# o        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,0 o8 D) ]3 R1 y( T6 V8 A+ x  h- _
               bIsIDEExist, bIsDiskExist, wOutData);7 n$ j9 N" }. r' \4 h" w( b
: Z+ ?+ k+ h& \3 \7 ~4 D
       if(bIsIDEExist && bIsDiskExist)
+ A* `; Y8 U3 ]$ d% m" d        {" I% z2 r# h) a) W, }
           DWORD dwDiskData[256];+ _& @( `( X' M. Y+ {% Q8 h8 R% Z0 S
           char  szSerialNumber[21];- N9 ]3 V& a- a% V
           char  szModelNumber[41];  _+ A2 I  S/ G0 O

, D0 G9 t1 e  D5 C1 U            for(int k=0; k < 256; k++)6 M& h0 x% F# |! v
               dwDiskData[k] = wOutData[k];8 ^; _6 I3 s. n1 c7 M) w& X: G7 y
% _& H- N6 i5 s
           // 取系列号
8 x! u( _0 I5 |# i            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));$ f& Y5 P. s) R: ^6 j4 Y5 B
           strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
( M* x3 _" f5 l- D, z$ n- d
! W3 h# w4 l7 q            // 取模型号
+ D9 Q& h2 |0 x$ G2 h            ZeroMemory(szModelNumber, sizeof(szModelNumber));
4 g6 _  {3 Q  {5 @. _            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
$ Z- Y5 x- Q7 X4 v- I3 r% v
  g$ d6 J% K) {; K- Y            pSerList->Add(szSerialNumber);& f6 P, r9 h* k
           pModeList->Add(szModelNumber);
6 T, @4 n" I* t: w) N        }
9 A5 N% {9 A, z    }
7 V( }0 }2 z7 t3 K. c4 Q$ M    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);/ t; _' P* S0 B6 K" T( C# i! j
}5 z, f/ Y! X# \5 b
//---------------------------------------------------------------------------
" f2 G- ^  X; I3 j6 I3 m// ReadPhysicalDriveOnW9X_Ring0()
7 L: T4 U9 z4 m  }" _//
. V; y% ?/ i& j; H/ `// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
, N2 Y- U. L* P2 c. ~// btMasterSlave = Master(0xA0) Or Slave(0xB0)
& D, g& y0 I1 I7 {//---------------------------------------------------------------------------) d/ G/ Y% \. d5 J
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
, k% \9 W6 j" y8 w' v$ u! z" e6 K' S        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
: k: h  {( E$ R$ S  A9 X{- v# |4 F' z# o5 u7 Q
   BYTE  btIDTR1[6];
7 G% D$ t. }# X0 [; z4 m, }    DWORD dwOldExceptionHook;  N: T+ l% E+ }) Q3 b
   const int nHookExceptionNo = 5;9 s4 d) {( z0 E" H, H, M* ]5 S

" R1 P/ h2 A$ ~    BYTE  btIsIDEExist = 0;
6 S9 q$ F* Y* P* Q6 c$ _  \1 Y: k    BYTE  btIsDiskExist = 0;
# T8 b' ~' o3 x# [' i1 M    WORD  wOutDataBuf[256];& `+ x) J: C# O9 g4 L0 l( _

6 K; B6 `4 r) z6 Z7 l- U    BYTE  btIsFirst = (BYTE)bIsFirst;
5 E3 r: g% r) g: [: t& H8 S% A0 W+ m% q: c' n2 L0 Y
   const BYTE btBit00 = 0x01;
7 I7 Z' V1 f) w2 R7 D- x/ P    // const BYTE btBit02 = 0x04;
- E3 f# K: O( W    const BYTE btBit06 = 0x40;
: `# O8 G. {* K6 d# }! l* w7 j" W    const BYTE btBit07 = 0x80;
" [, a( X! U/ y' [/ D' N' g2 e    // const BYTE btERR  = btBit00;
7 J  S& c! |" y6 e    const BYTE btBusy = btBit07;
2 P- O2 ^8 _  G( N    const BYTE btAtaCmd   = 0xEC;
3 Z0 X6 h7 z7 V) N% i% l- L    const BYTE btAtapiCmd = 0xA1;1 q7 I" e$ O' f, E1 V' ~' T

. d8 y9 `. D, |+ v' k4 ^    __asm
- |6 V" v! s$ P+ I2 {9 x    {
5 u1 @! r4 ^+ Q; I1 M* k        // 必须先执行这条语句
& Z4 Z5 F6 ?( \! ^9 M# m9 n        JMP EnterRing0
: A  s2 Z  Z' j, _) v- a1 D
  o2 Z% l% W# k4 o; L        // 定义过程
* y/ Z) D8 k5 f! X( `" e        // 等待IDE设备直到其不为忙为止; U# ~  `8 {- P
       WaitWhileBusy proc6 I; v7 {) t0 r* f+ ?
! e4 f1 r& g+ M1 \% b
       MOV  EBX, 100000
  M9 R+ F2 `3 q0 c3 h        MOV  DX, dwBaseAddress
- q2 [$ k( f1 f' R+ `) }        ADD  DX, 7
$ E  w+ U, a4 x4 c" n, u5 G3 {3 h0 w/ q2 G) G0 N; H% s6 ~" N
       LoopWhileBusy:; T3 J+ O3 w, w

1 C( e8 _5 c2 b  ~        DEC  EBX1 W0 Y5 x6 m4 m
       CMP  EBX, 0
  E6 a7 Q/ n" `9 Z  D8 e8 @; C        JZ   Timeout
' d$ E' Q# c# {) }, a; M) N- d7 ~        in   AL, DX
0 g! M' T: k* j- A' M7 Y, ~. [% m        TEST AL, btBusy( }+ i$ s, Q, O% u
       JNZ  LoopWhileBusy
$ _2 y; p6 u% ]% X" d5 z        JMP  DriveReady
. p: d  Y* U% X  M- `- T$ R) o3 f6 [& E' S. S: d, W) `6 n
       // 超时,直接退出
3 ?1 }% I' Y8 C% e* _  F6 K# W( G  Z        Timeout:9 S( T) N& K+ ^& A1 Z9 _/ m: `% Q5 s
       JMP  LeaveRing0
1 X1 a$ t$ t& [. v        DriveReady:3 Y, Y* F* b9 T& X- l) y- p
       RET% l' L$ Y# `* H) B/ Y/ ^( x4 c4 X
       ENDP   // End of WaitWhileBusy Procedure+ P! ]- e' h3 ?4 m0 q0 Y

- d# w0 h! f7 ]        // 设置主盘和从盘标志$ ^: g+ H% k8 k0 q* W. H1 Y$ d
       SelectDevice proc6 Z- ^  a8 t2 ^# p8 P# {2 ]  s
0 ?+ E5 `- c  E: P
       MOV  DX, dwBaseAddress2 o9 ~/ M9 @4 r3 u! \
       ADD  DX, 63 k; g7 ~# P7 N6 w: w
       MOV  AL, btMasterSlave
9 v, {+ U1 K- \- V. g& X% R3 E. D* f* V3 ?9 r! j
       out  DX, AL
3 Y' S( a, Q$ R% Y        RET
1 I' x& w* N9 A7 S! o- a% Z$ U3 _, Y  ^0 f" [* Q& I7 q
       ENDP  // End of SelectDevice Procedure' x1 q( d7 V- M" \& _0 m

- l1 Q  w, o' S; H, y! J; X1 A* V8 Q        // 向IDE设备发送存取指令# w( }& o; ^! n+ H) h( T
       SendCmd proc
+ y& k+ _0 z8 |7 a, [: u2 w1 B
1 e( t% r6 A& \$ G        MOV DX, dwBaseAddress
* A4 K3 y  n/ ~+ O        ADD DX, 7
9 z# l& z% `1 ~        MOV AL, BL // BL是主从盘标识,在过程外设置
5 n# e* W  U' Z/ `& M1 V        out DX, AL
8 |0 g2 v" P+ @$ o+ {. ?- e( Q        RET6 G( D# H5 k; u- g+ W# Z
       ENDP  // End of SendCmd Procedure/ G4 U$ \( _. Y# `  C

) v. Q6 y* X8 a+ I        // Ring0代码8 W* s. M- L# [8 |9 U  U
       Ring0Proc:
+ F1 S; L8 ?1 g8 O! j- `        PUSHAD
  e8 ]; Y7 _- H9 ^        // 查询IDE设备是否存在
! C- x! l0 G4 Q1 N* M& w        MOV DX, dwBaseAddress
8 o- C, N; U$ C2 Q, P2 i        ADD DX, 7. ]  `7 U, z7 _8 h3 G
       in  AL,DX; k0 V2 C! @, c* g4 i6 s# j

' ~/ l! J" a. N1 {' Z# W# B        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回. S$ R5 Y- Q" s8 k$ _
       CMP AL,0xFF
% H7 p8 d* l: M6 b, g        JZ  LeaveRing0
4 X; H( j* t+ e5 H& c        CMP AL, 0x7F
8 }% ]7 K" r1 h- a        JZ  LeaveRing0
$ T& p9 p0 W, [
# U( ?9 H. s" E5 m8 ]( R5 s; |        // 设置IDE设备存在标志' @0 E: B/ K# B) v/ X, K
       MOV btIsIDEExist, 1( X% K* b$ O& W0 _2 G

( Q* f9 y. i/ w; a- f        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)9 ?6 ^3 g+ e1 q5 O! A
       CALL WaitWhileBusy
, n0 R4 {2 B3 Y: J( `5 K        CALL SelectDevice
0 ^2 ~5 ~: [! v$ i0 W* l. M/ @
; s+ R* ^! j, r/ N9 }        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
. y# ]+ @$ Z1 ^$ }2 l        CMP  btIsFirst, 1
$ h4 @, k. A/ }: E0 k( |4 d* a        JZ   LeaveRing06 j" N* E& C& \1 v8 g% q
7 F3 b( v( l% }9 I) Y( W
       // 第一次调用时,如果执行这行语句会导致蓝屏,Why???9 o* f/ r2 ~/ f. V
       CALL WaitWhileBusy' i+ G7 j! V9 ^$ K: ?! H' ~

8 B" R0 l% `5 B6 Z" e0 U3 M" {        // AL的值等于cBit06时,不存在驱动器,直接返回: q8 U+ L/ q& X) C& K( ~# M! ?
       TEST AL, btBit06. j( G# f: m7 I$ g+ ^/ s
       JZ   LeaveRing0) D3 Y" O. Z: {

. g& S4 ?2 f& ]        // 设置驱动器存在标志
9 g4 K- F- S& e6 v" E1 v5 _+ U        MOV  btIsDiskExist, 1( Y+ S6 n: ]1 o; D+ R1 o" C

/ X6 _- \5 A4 E( a        // 发送存取端口命令+ L9 o2 \- X: d* X" D
       // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,% I! H/ w# u5 P
       // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
2 j% R. e/ b% d. ?: ]9 R0 A& f2 E3 ^        CALL WaitWhileBusy  y, H2 `# ~% @" J* C3 r" o
       CALL SelectDevice    // 设置主从盘标识
, T8 W' r/ o! M- K0 [8 K        MOV  BL, btAtaCmd      // 发送读取命令% G5 f  T, ?" w& Q* T* Y
       CALL SendCmd9 m$ b/ z# Z: O2 m4 l& d+ z
       CALL WaitWhileBusy
* Z8 b2 ?' X" \- c0 G& J1 a/ T, ?/ n& x
       // 检查是否出错
0 \3 g5 i) ^4 T3 o- P& q        MOV  DX, dwBaseAddress0 Y& [8 N5 N% T$ A- K
       ADD  DX, 7% `) U1 w: A5 m

, [0 n$ E5 M+ H* M3 v) P5 ~        in   AL, DX
5 j( ]9 y* Z, ]% r  ]" V8 S  e" c& H# E9 n) |
       TEST AL, btBit00
9 f, B% C1 Q8 \, U* h' I' Q# u        JZ   RetrieveInfo   // 没有错误时则读数据# C( a! V% E" G; l! d  v
/ [5 w, K! h8 g' [+ O  j
       // 如果出错,则进一步尝试使用ATAPI设备命令
( y9 v( E' p. J* O8 N        CALL WaitWhileBusy
& N( j4 l& y3 w6 f$ Y- V( b$ T        CALL SelectDevice
" L3 ~- X2 I, c+ t  |+ w        MOV  BL, btAtapiCmd, R* q3 B7 h3 X, _
       CALL SendCmd
7 i/ f- j, s) O4 I% S/ V, D. D        CALL WaitWhileBusy
7 Y5 _$ \# k3 i8 f" e" D
2 V1 k' E1 I; u1 V        // 检查是否还出错
( X9 O0 Q- a$ {5 [9 Y/ H6 {        MOV  DX, dwBaseAddress6 j  H& d/ i5 y( r2 Y' k1 o
       ADD  DX, 71 O' c) k) ~9 Y! \6 Y& }6 B3 e& i
       in   AL, DX# t& Z& U& O4 W2 p, z' V
       TEST AL, btBit00
( h  M  A& P' r1 e  d% C" R. |        JZ   RetrieveInfo   // 没有错误时则读数据9 I. |* {% b, E& S# @
       JMP  LeaveRing0     // 如果还是出错,直接返回
  ?$ I% A/ M. {" y; M
6 ^! B, {3 b& h( S: h# r( a        // 读取数据
; w' h9 ^5 d8 t# M        RetrieveInfo:3 a6 V& X+ Q/ ]. f' I6 I6 G

/ c6 z; ^) p" v3 Y9 C        LEA  EDI, wOutDataBuf+ `& ?0 a( ~, s" z  V3 s& N
       MOV  ECX, 2567 E0 m; u5 p1 I9 L( u9 K' _6 L( B
       MOV  DX, dwBaseAddress& [# q  J1 g3 I/ q  Y, b9 q  r$ p% L
       CLD7 d6 N( V* }9 z4 F1 ~8 A% u4 G# L
; Y- v9 X3 {5 l$ o6 w
       REP  INSW
" ~# ?; c2 p  A/ d7 g0 k5 c# y6 K4 J" S
       // 退出Ring0代码( {! i  r! T; l9 |2 Q5 U1 Y" E7 ^
       LeaveRing0:
3 m4 A! e7 o. R& d  |/ |7 j+ b4 S" Z) k/ ~1 d& C2 [
       POPAD
2 ?- _) l" g# N, @$ x        IRETD7 Q# ^) m+ I# u9 ?. [; l" ?6 N

3 C/ l6 y( [8 H        // 激活Ring0代码
+ V+ L% T% x; f  F* A        EnterRing0:
  c3 V/ G+ ]/ h; K  {# `
" Y% y0 v5 @+ o        // 修改中断门
1 v* v* {: U; H+ `" g        SIDT FWORD PTR btIDTR1
6 w0 ^! N' I: f        MOV EAX, DWORD PTR btIDTR1 + 02h7 }2 E4 @- r( \9 Y4 M
       ADD EAX, nHookExceptionNo * 08h + 04h$ _7 ]! y2 Z. I( e  t: ~
       CLI
9 k+ `7 }5 n; u% W7 O! z3 z9 \" y  k' u& J% b% j
       // 保存原异常处理例程入口; |+ H- ?9 Z  P2 Q& W5 I  L, @
       MOV ECX, DWORD PTR [EAX]5 q" P2 P0 ]5 g$ D
       MOV CX, WORD PTR [EAX-04h]
1 B; S4 B& Q6 X5 A* A$ `9 N        MOV dwOldExceptionHook, ECX
  a( W* \2 Z2 `$ e9 j/ t$ u8 @) _/ c( w9 {/ E
       // 指定新入口1 s" p3 e5 W5 b4 y
       LEA EBX, Ring0Proc
& D! j, A  K# j! @, C  z        MOV WORD PTR [EAX-04h],BX
% }  J; T8 Y  S; J- ?, O        SHR EBX, 10h' U3 E+ s- F! l; e  i- G
       MOV WORD PTR[EAX+02h], BX
  b+ S# D/ M5 g& E6 i+ Z) E( m% K1 P- L: n: ~9 }  n
       // 激活Ring0代码
' k" n2 z7 l: @4 h$ ]2 _+ H        INT nHookExceptionNo7 i# `; X9 c& n& u1 J2 N% Q. c7 b
- B( r3 t+ ]) k! d* z7 p7 ~
       // 复原入口
1 W+ d1 d% K' r1 W        MOV ECX,dwOldExceptionHook
) k: f' o( x8 |" d0 B" l% e        MOV WORD PTR[EAX-04h], CX* k$ k8 B9 d/ c# Z) `% e
       SHR ECX,10h
+ ?2 j, L' a8 o/ X/ o4 T& ]' A        MOV WORD PTR[EAX+02h], CX  {5 N' k0 ]% {" v$ q
       STI8 \/ n% e0 w" H& r
   }+ \! ^- M& r/ ?, c  k+ p: W
   if(!bIsFirst)
8 u& C. Y; i, f. p6 j9 x3 }    {
/ N0 E; [1 U+ C# I  y$ K        bIsIDEExist  = (bool)btIsIDEExist;
* [5 k- |4 q9 t        bIsDiskExist = (bool)btIsDiskExist;
: L" [7 Z4 O5 i4 A        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
1 v4 f7 Q  l% j2 S( o" c    }
) J0 h2 _3 ^0 Q1 m9 h}* o6 e3 r3 H7 z
//---------------------------------------------------------------------------
! Z. f! P, q$ v0 @+ a// 调用方法:6 i8 S. n1 x% h  f! Y- X% m7 K
void __fastcall TForm1::Button1Click(TObject *Sender)2 v) f, ~  G* h3 n$ S( L# ^
{
2 w4 b& L+ z+ i+ e; g- g    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);  E; F; n, K+ y6 p/ a, H& {6 H" q
}
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-6-18 09:02 , Processed in 0.020225 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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