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

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

[复制链接]
发表于 2005-5-30 19:22:36 | 显示全部楼层 |阅读模式
  #include <WinIOCtl.h>4 Q8 y4 h' C5 |* h
#include <stdio.h>
! E+ [( ?! w" ~1 f& D. _+ |
: y" i3 H+ _6 H#pragma inline$ f7 p- v/ H1 `+ Y% U! U# O
//---------------------------------------------------------------------------
, `* @6 X1 _, F) b6 _; g// IDE NT/2000/XP专用变量
0 Q4 Z. u: i7 M) n/ |( u#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS0 T' p0 O7 y+ p% {) X# B
#define DFP_GET_VERSION         SMART_GET_VERSION
* m- L. g) A6 c8 A#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND- Z" f9 v& A# d/ F9 h! S& d
#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
# W" N# E. S6 {4 h, y* L! y
+ ~" ^2 h- G0 c9 s& Dconst WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令
! t- U6 r- m# N7 V6 ~* g( y  P% Gconst WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
; K8 L0 J: ?' T3 o* r
" S' W- a0 ]; A( [const int MAX_IDE_DRIVES = 4;$ q3 v, t$ h! @) _# |1 I

% |9 {1 x  }9 X6 N// SCSI专用变量
3 x; M# X6 G% J( N2 U! `$ tconst DWORD FILE_DEVICE_SCSI             = 0x0000001B;2 g; ]( y1 t: @& V4 u* U* A
const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);* ]4 D4 Y) u6 y- W3 m
const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
6 ^, j  x' k/ v* o1 v- X! A# Nconst DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
% P# Y$ {! b5 O6 Q8 j& P, ?, H. Y8 n6 k, s  v: S
typedef struct _SRB_IO_CONTROL: s! J6 m) m- ]2 H7 s+ c" I6 d, T
{. C" p4 k# ?) l7 G2 O4 v5 X4 Y; c% l: p
   ULONG HeaderLength;
% F! M! {& o7 ^% a    UCHAR Signature[8];
6 q+ L/ c- ]0 ]+ `! W! @2 G# Q    ULONG Timeout;
6 p+ u+ N/ N( V# i& U    ULONG ControlCode;
1 M4 t" i! B+ d" q# @/ K- a    ULONG ReturnCode;4 I( J) Y- ^1 ]# n" I& P2 U
   ULONG Length;# y6 u* u8 T+ V; }  q7 g
}SRB_IO_CONTROL, *PSRB_IO_CONTROL;
4 T+ _, }5 o+ U( v7 R/ }2 u, n. i+ x: w$ x3 x( E
// 读取的主函数5 @% R& \# O, g; r
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);1 X8 P0 q. [; p

7 R  A$ J+ l" X7 R0 p# h8 F# t// 辅助函数- {0 z7 f) h0 T6 I: q3 k- e
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
6 s4 p4 l3 q$ i: x0 W// NT/2000/XP函数
% Z" ^9 k0 i7 H5 }void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);2 v8 w' K9 h8 t
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,! {+ ~) E& X2 d! V3 ~) [# z' [- V
       PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
1 |2 B- p5 b5 d0 c5 N        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
: s& h9 N2 F* g. C// Windows 9X函数) R+ X( r- S5 u# d" S4 e
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);' {' x, F5 q& W$ A3 R
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
* o2 _) }/ |. Q1 Z* g2 M9 [        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
2 _) N. d) i6 e+ T9 x! M
5 Y2 Q1 W. a0 E// SCSI读取函数(for NT/2000/XP)  @4 |" H  @  y$ g4 X6 h
String __fastcall ReadIDEDriveAsScsiDriveOnNT();4 p9 m! T" L3 h, H9 C5 O7 m
//---------------------------------------------------------------------------; d* ~4 Z5 l! l  W
// ReadPhysicalDrive+ ?* F& J# w8 I6 r6 [  ?
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
  t. D; q# j0 q8 U2 b: W! O{  H, X) V* B( |; H
   switch(Win32Platform)# t0 I# y" d1 i5 D& m
   {" k" D5 v: `7 L6 G0 J
       case VER_PLATFORM_WIN32_WINDOWS:
* R( F( z% x7 {$ u& f. f! C- {            ReadPhysicalDriveOnW9X(pSerList, pModeList);# G/ Y0 k  i! [
           break;: G5 ^' n, E; q+ ~. u
       case VER_PLATFORM_WIN32_NT:: T8 N* C- L, x) i+ |: u
           ReadPhysicalDriveOnNT(pSerList, pModeList);
! V: d3 A; f; C5 x9 u& ~            break;4 \7 S; V: S9 L, D. i
       default:
2 `  i+ @! K% @- w' d& A6 J            break;
6 k- K" \. e! M, G8 f9 ]. |3 |$ Y0 L    }' R, U- i; p& Z
}
" i" D( p: [+ ?# j' @+ f//---------------------------------------------------------------------------
7 f4 G$ S% V5 G4 G3 ~: k% b// ConvertToString
2 |* q. u( o. \3 F2 [# o  _char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
' U4 w$ A6 t4 t7 h/ v{
0 x  q) a, _: u% v5 A8 A    static char szResBuf[1024];( y$ I' Z0 B" d' p9 ]
   int nIndex = 0;
/ O& j: s$ c3 l$ l( I    int nPosition = 0;2 L) q; k& U+ j2 E
( M4 @  _& v' r, c
   // Each integer has two characters stored in it backwards
2 _3 J2 K# {9 u    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)8 C% l6 {5 w6 G/ F
   {4 O0 R$ u6 c8 G
       // Get high BYTE for 1st character
2 @( N" b0 a* x! ?  ]        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
4 f  B& w( J3 |# w! l8 R        nPosition++;7 J& v- |. E! p! V* w8 l. l3 _
! I6 O1 o4 t* z. O
       // Get low BYTE for 2nd character
0 x' T4 e: Y6 J, i! s7 @        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
1 h/ l$ f( K; d        nPosition++;) v, ?+ M; o) W4 G+ S8 S
   }) H9 o, q. u9 K* f# G5 n) ^

6 }" [* G2 A5 `' w    // End the string
2 w) I* b7 I1 d  K' F    szResBuf[nPosition] = '\0';6 f# \) k" n3 z: o! M3 Q
; I; c" d: _2 k- m# X
   // Cut off the trailing blanks1 i2 f+ ?# @" x
   for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--). v5 N# c9 x# V
       szResBuf[nIndex] = '\0';
& t" e( b7 J9 J" Y$ h- T
# E& c0 v) A( i0 X* G: i    return szResBuf;
, ~4 g, Z, l' z- a}& n3 K/ ^  I) R" ]0 T7 m
//---------------------------------------------------------------------------  C0 f  s: D+ h2 s% w' B
// Winndows NT4/2000/XP 代码
2 n2 C. _# F' R8 S7 k! \* ?7 k+ }//---------------------------------------------------------------------------7 v# T" t5 ?7 S4 h
// ReadPhysicalDriveOnNT
7 J; ~9 K% m# j' Xvoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
0 k; \7 |; C# j. o0 S9 X{
/ r6 y/ v0 z5 `! _    // 输出参数' H- h, M2 v  Y! O
   BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
, P+ Y6 [8 E# y- U
: K% R& `  T: Q5 j5 b& D    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)3 v* X* t) n9 k! ?$ ^
   {
; ^! Y1 P; i8 w0 i6 W! A, \/ {% J        HANDLE hPhysicalDriveIOCTL;6 z4 k+ ]8 F  x" ]6 f  S/ \
       char szDriveName[32];
' T* q& f) v) W/ t8 M5 a- H: r
; D% i- {1 |% j5 o  Z        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
& O, ~5 F1 [) Z) f" a        hPhysicalDriveIOCTL = CreateFile(szDriveName,: `' K9 ~' p; Y9 _) U
                       GENERIC_READ | GENERIC_WRITE,
6 u6 f8 z( _3 S$ U                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,' [5 R; u& H! j/ Y+ o
                       OPEN_EXISTING, 0, NULL);
. P3 ^( o, g8 J7 w7 j" y; l) V5 C: s) C8 j
) m% g/ {( h8 `        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
& q9 n% ?! O7 k0 p& y: N& H+ @3 g# x        {
, F  @- U  v: A9 O# m( q            DWORD dwBytesReturned = 0;
3 n; i1 o3 x- z: e) U3 J            GETVERSIONOUTPARAMS gvopVersionParams;% o' a) D) ^* _( |( }6 ^

( e/ P& w! v4 @2 W7 a. y& Y; G% A            // Get the version, etc of PhysicalDrive IOCTL. `# w! s" z2 ]% l: S' r2 ]$ B, N
           ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
) K7 @) T/ ~* E8 ~# b! X% R7 z% V, L! ?; b( {; K$ @
           if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,( ~. }3 W& u; N* r
                   NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
0 l3 ]# t7 v. S/ `8 U                    &dwBytesReturned, NULL))8 a1 c; M3 g  E# Z  |7 a& U
           {
6 \- p9 i+ R  u; h. u: n% L% R: `: [9 l6 U                continue;. [7 M3 R& ?- i$ M9 z- y. I
           }! H$ \, u7 S1 m! S1 v4 O1 u1 C
, S! q* G4 t: `
           if(gvopVersionParams.bIDEDeviceMap > 0)
! B- z% a4 B: @4 x& K$ q            {( I: ]- h: ?0 c6 Q
               // IDE or ATAPI IDENTIFY cmd
7 w0 |% j3 g4 t& n$ W( @                BYTE btIDCmd = 0;
7 g9 z+ _+ E' B                SENDCMDINPARAMS InParams;0 }, v$ U  o( m$ R
               // Now, get the ID sector for all IDE devices in the system.) A- Y% C: h( F& N8 }
               // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,9 K1 Z7 S. v! ~8 [# Q( `
               // otherwise use the IDE_ATA_IDENTIFY command
% q, X: G/ ^. {7 L3 i                // 具体所得结果请参考头文件中的说明3 {9 i9 G$ B- l/ p) }+ @' L
               btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?6 e8 P* u" U( q5 m
                       IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
& F0 O8 s1 a4 {2 x1 C5 |1 B" m! f                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
: e, N; R# I0 M0 I+ @$ a$ m                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
; X8 S! h3 N$ ?- r/ ]' v  }3 B6 _; T% v* F% E8 Z
               if(DoIdentify(hPhysicalDriveIOCTL,
, r8 W* t! G& i( S" P                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,! z" ]6 D  B; C( K; ^, ^$ K0 Q
                    (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))$ O& t$ p% V- v0 P5 |# b
               {* w; h$ Q: m' h" C% c
                   DWORD dwDiskData[256];! Q6 h6 m# @, x: Y% E
                   USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
" w: p) ^7 p" J3 a' L/ @                    char szSerialNumber[21];
/ n7 D7 v9 t/ Y5 N6 J2 c) y7 L                    char szModelNumber[41];
8 v7 g% d! s  r! ?* @/ e2 m$ p; E  Z5 T' O7 x
                   pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;7 v& K3 X8 r/ ?% n! \2 [
                   for(int i=0; i < 256; i++)3 {2 c9 B5 I+ U* }4 p, J
                       dwDiskData = pIDSector;( w0 b9 ?* A3 ]* J* S# q
                   // 取系列号6 ]3 S1 P3 W' y
                   ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
( a- f: @7 ^1 _- y( k' T                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));" W' F1 g8 ]4 u' j- k* S9 s+ s
# U$ H  D2 A: `2 T: D
                   // 取模型号
$ z7 ?) k1 m' G- J0 c                    ZeroMemory(szModelNumber, sizeof(szModelNumber));
( I2 a/ D4 o6 O                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
6 h+ q0 r; z* }8 ?; M2 J( q! ]/ y/ }7 g
                   pSerList->Add(szSerialNumber);' s7 [; ]2 F5 Y) w7 w; |9 Q: W
                   pModeList->Add(szModelNumber);7 _; ]; ~, k4 S( K, ?- E
               }' @: ?4 j7 b2 y  _8 g! c2 P5 W
           }
6 e1 p; \$ _4 e) A            CloseHandle (hPhysicalDriveIOCTL);( A7 H5 N( n- }9 B, D) U
       }
0 _! U% J6 w. }: l+ d    }
* T4 L$ \% y' d5 f) w/ @}
: ~& v# d+ u; M) j//---------------------------------------------------------------------------
  v# l6 w6 ?$ c7 I0 |/ w// DoIdentify! L1 j4 E3 L5 J
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,9 Y7 T+ y, R' _* s4 H8 W0 R3 s
             PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,3 ^6 J& h* y# |0 |; ?
             PDWORD pdwBytesReturned)& N/ l( R' [9 v
{
" y& I  s! _/ C( q. G  H9 D    // Set up data structures for IDENTIFY command.
3 e7 S, k+ w  I6 k- c. t* p" _+ _( N    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
4 u" W/ B+ P# o2 B  z6 y9 k( c    pSCIP->irDriveRegs.bFeaturesReg = 0;) I; w+ P4 [1 M! x6 F  u$ v% f
   pSCIP->irDriveRegs.bSectorCountReg  = 1;/ V2 k$ d3 \3 Q( F8 ?+ s8 ]
   pSCIP->irDriveRegs.bSectorNumberReg = 1;$ ~" r0 C! W' f( _* _' K8 l
   pSCIP->irDriveRegs.bCylLowReg  = 0;
' ^% e9 e3 A" i6 ^  l2 C- S5 h    pSCIP->irDriveRegs.bCylHighReg = 0;/ s( A: e! B/ N$ z) z/ c1 w- b5 Y
, O. X4 E4 D3 X' J) o  n
   // Compute the drive number.(主盘和从盘所对应的值是不一样的)# D( {, l7 s6 n. t* N3 F
   pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;0 ?% r% H' ?8 H4 U' G" D# y
/ h) @& d; c" w6 a4 x% N) [
   // The command can either be IDE identify or ATAPI identify.# V% T" m: c9 J7 j
   pSCIP->irDriveRegs.bCommandReg = btIDCmd;1 `" P; N& ~5 i3 m- P5 D
   pSCIP->bDriveNumber = btDriveNum;
! Z, D9 U7 `+ z1 @" V' }8 C1 [  y% y    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
) P: r* t1 g! @3 g' b$ l+ W  _
1 K& [3 h4 B6 ^4 W8 L% U# y1 H0 j9 K    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
  W2 T* V( F& N: ?           (LPVOID)pSCIP,0 C9 z% e3 Q3 [" R
          sizeof(SENDCMDINPARAMS) - 1,
- D  \- R3 w& E) g3 M# w4 v: k6 [           (LPVOID)pSCOP,, V: P) V0 R& u  T, @
          sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,+ `$ w' y) E) |/ K
          pdwBytesReturned, NULL);# Y% \" p7 p/ p
}# ]2 F- p6 h& \1 g* {0 j
//---------------------------------------------------------------------------
/ Z7 K' j2 B) K; y- u6 e! B, f// Windows 95/98/ME 代码2 i: _, V* i. C' z# W" c
//---------------------------------------------------------------------------
, U6 N8 X2 l% z/ ~5 j8 E$ n1 }) y// ReadPhysicalDriveOnW9X
1 _/ l9 g( e, I1 n' Fvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)% t3 }, R! S2 m, b& t
{
; F5 ~# `& t: f% F7 }3 V    WORD wOutData[256];. o, Y3 J, z. S9 d
   SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);7 \7 i3 W( z1 ~! F
" q' p* S, X5 M# A% k; {( I
   // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
: f) e+ S( _* f  v) w- y3 I    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以7 E7 u$ W6 B6 K# z5 C2 H1 b. c
   // 避免蓝屏的出现。(期待高人能指出原因)" q2 m5 D8 V2 r' s! \4 b& j. ~
   for(int nDrive = 0; nDrive < 8; nDrive++); Q! v2 o$ ^' Z# |- L/ Z
   {$ h1 i( \) l& @7 U5 i9 u
       WORD dwBaseAddress;/ X2 n) @- W. R
       BYTE btMasterSlave;         // Master Or Slave
& y6 C8 x' g7 k* U8 n7 l; B        bool bIsIDEExist;
; j/ {$ r- ~8 E) s1 i        bool IsDiskExist;  C' G7 p/ [  p( \

9 l0 w' }2 R% D6 c8 ]* }, x: `        switch(nDrive / 2)% e( P7 h- a2 o2 H0 W/ m
       {
% P9 r( \% @. x5 b/ t9 F+ E3 M            case 0: dwBaseAddress = 0x01F0; break;
/ A; Q$ a# v( f6 S7 a            case 1: dwBaseAddress = 0x0170; break;1 h( N' t) N& z4 Q! M- J0 c
           case 2: dwBaseAddress = 0x01E8; break;
# Q  L' H. s5 m. j( r# X6 S0 A5 @            case 3: dwBaseAddress = 0x0168; break;/ W$ \- C0 u% S) L' m
       }3 [& A7 e- m9 c+ M0 M1 Z

# @6 w* I! m. F        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);; @4 R/ `( \+ P5 o% r5 c/ T! e! Z9 v8 @

9 c- e- O, j0 o% O        // 进入Ring0% ], u% [" |# N% M8 N
       ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
5 S9 r% ~6 R6 e$ X% }: Z; c/ L* L                bIsIDEExist, IsDiskExist, wOutData);6 k% h3 [1 W/ C  L- s% _
   }8 \+ ?' t) |8 X2 ~. Y0 H5 w
0 D/ O) C6 q( |! Y# f
   // 开始读取
2 {0 y4 a( r  }5 b' x) w( o    for(int nDrive = 0; nDrive < 8; nDrive++)
* {9 e7 G5 U9 C' |: q3 X7 n    {" v) c' g0 z. c2 y5 n. f
       WORD dwBaseAddress;
$ c& L, r  C, q4 \$ Z4 l1 m        BYTE btMasterSlave;         // Master Or Slave
; F# @* Y5 ^) a, |  s; A, @3 I8 g        bool bIsIDEExist;
- u6 l- z3 u! m* V. s  ~        bool bIsDiskExist;" h" g1 P" _  x  `
       switch(nDrive / 2)) d/ t( z2 c' I7 ]) f
       {
' l) u  b) [8 j+ c$ G            case 0: dwBaseAddress = 0x01F0; break;
3 V0 @3 t1 b5 R            case 1: dwBaseAddress = 0x0170; break;; X2 J5 k  B1 p1 `
           case 2: dwBaseAddress = 0x01E8; break;* W( a. U" @6 T
           case 3: dwBaseAddress = 0x0168; break;9 u0 e9 ]: R) X3 x% G0 `
       }" L! B1 n# H) j
  h( C6 V+ V, c; X& D
       btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);$ \9 N( l: ]2 t/ {8 k
5 q! u  E$ ^# m  R
       // 进入Ring03 Y$ {' m$ j9 s) l/ S. z! E
       bIsIDEExist  = false;1 b" e/ E7 \+ R
       bIsDiskExist = false;
* S) `9 B& c5 {; ?" x+ U        ZeroMemory(wOutData, sizeof(wOutData));4 E& `3 ^! x6 D% Z: J; r( q

+ a6 U, \  S" Y1 Y3 @        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
+ z1 [  X/ |4 H                bIsIDEExist, bIsDiskExist, wOutData);2 R" J$ n2 r3 P5 p$ z$ H0 g+ ?

# t1 p7 f$ F9 k1 |: y, X7 _& }" g+ w        if(bIsIDEExist && bIsDiskExist)
2 J3 X! R( O! N+ W/ {        {
0 p2 `9 p% Y, b9 l7 x$ K* b: s            DWORD dwDiskData[256];: Z) ~! ^8 ]! a' \0 @
           char  szSerialNumber[21];
; C( N, `; |, [+ t" e8 A            char  szModelNumber[41];' `5 h$ Z  h) a! j9 |9 c1 c

2 b6 h. E& B% M! z2 T            for(int k=0; k < 256; k++): _& C( Z4 e! [: s+ W0 V: Z
               dwDiskData[k] = wOutData[k];3 K" s" A# A6 ]' u! D7 j: t

$ N$ ?: T' H3 i2 z6 w8 _! n            // 取系列号
' E! I) B0 N5 y1 Y  _            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));+ O* @+ m. n3 J6 i* r1 V  o
           strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
. t1 D, Y/ I& {, ^& _7 ?) z- U' l% D, e
           // 取模型号
4 b* A3 G( @4 M            ZeroMemory(szModelNumber, sizeof(szModelNumber));2 H4 C0 w" g9 v7 b4 }
           strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));8 g: B5 N, l8 K8 T6 B+ ?$ _

' {  o% A: h2 x. u* N% a  `7 ^            pSerList->Add(szSerialNumber);2 M! Q' ~! w7 T) M. m# x
           pModeList->Add(szModelNumber);3 n, p* Z4 A0 T$ F$ f
       }
* ?+ ?6 u  i4 r+ O- j4 X    }, @; q6 D: {8 i. c7 w
   SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);3 E' r3 j1 N' _" n% b
}$ y- D4 s! R# i7 t
//---------------------------------------------------------------------------
4 C# D/ @. T( k( r9 c' B: S// ReadPhysicalDriveOnW9X_Ring0()
. g) N$ W( u" i1 q7 E, k) E8 a//: E) L" B' w0 b& N. B# K5 p* {
// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h$ f& x% e. T+ j
// btMasterSlave = Master(0xA0) Or Slave(0xB0)7 w+ e: W" F  T) J' \" U% ~
//---------------------------------------------------------------------------
' W6 H$ l. P3 T( z6 evoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,; F6 T% W0 N6 [1 r4 r
       BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
- _8 _( h+ L. J3 l6 Q{& ?, v( o  v. V7 `, P( |; C
   BYTE  btIDTR1[6];
% ?* S, A3 \5 j, L$ w# h    DWORD dwOldExceptionHook;
3 K' [' j* J  [4 f1 }, O! Q4 y$ U3 d    const int nHookExceptionNo = 5;5 U5 V# j* X+ W( O+ T

# @$ d8 L2 T  ?) [% ]# Z    BYTE  btIsIDEExist = 0;1 l$ S0 i7 g# h5 u; J  X& C. f! S
   BYTE  btIsDiskExist = 0;- }6 z( R3 H$ Q: T
   WORD  wOutDataBuf[256];$ ^4 H5 s/ j% D7 E  v0 Z. g

2 i9 j3 T1 t& w) {) B    BYTE  btIsFirst = (BYTE)bIsFirst;# V4 a9 W- s* |
, ]3 t" q, {: y# s6 Y
   const BYTE btBit00 = 0x01;" ?% F% D/ h% r. j) Z
   // const BYTE btBit02 = 0x04;
9 c" @' `, J0 W2 [8 c    const BYTE btBit06 = 0x40;4 m1 Q. q- D6 x9 y$ N6 l4 X
   const BYTE btBit07 = 0x80;
& r$ I/ y: x& r( h& G    // const BYTE btERR  = btBit00;- ?. ?! ]* n/ a" d+ _' {" }$ b2 `
   const BYTE btBusy = btBit07;
, |9 I& V7 \) E7 D8 J' ^, B6 Y    const BYTE btAtaCmd   = 0xEC;
7 a  Y) }" p  ]/ Q6 R5 a* t    const BYTE btAtapiCmd = 0xA1;
; T. F" w' S8 `/ }5 n" `& q: |
   __asm6 w% w$ ?% |3 v4 `, T# {. l
   {
7 E% \8 P' R; f        // 必须先执行这条语句" v, z- Y5 ^6 g/ i- O9 U7 J1 L
       JMP EnterRing0* w8 O$ w8 S2 f* I* _& E

) b7 _( j, m: T' |. f        // 定义过程
) g+ R* q; w3 m( d" M: Y        // 等待IDE设备直到其不为忙为止
+ {6 a5 Q# T4 V% Y# D" E        WaitWhileBusy proc( S8 q0 u9 V' g, r$ i

2 X- y7 M. `6 F# ~$ s0 T        MOV  EBX, 100000
4 @9 i$ j' S! ~% E* b5 o        MOV  DX, dwBaseAddress) I6 R' c9 W! z3 q
       ADD  DX, 79 s2 f% [1 }( u# H
, n; ^! K8 E8 r. J
       LoopWhileBusy:0 }0 ^" d, T) o' y1 ^

3 l5 H: n, H' b% ^2 v7 V" @        DEC  EBX2 |) K( I% X+ C) M! |0 {$ E6 ^. \
       CMP  EBX, 07 R8 N$ C  Y$ ~: S) f) [! I5 Q- W# l
       JZ   Timeout
+ p0 L& i; }5 z7 ^/ ?1 r        in   AL, DX
. e& ]# x6 r' H* y, f        TEST AL, btBusy
& d3 u9 M) G% X        JNZ  LoopWhileBusy
2 N* _* a* B7 W$ T4 d9 E1 Q/ Z        JMP  DriveReady
2 H5 [8 A+ b7 m% ?2 C  U
! X- w( W& O  o" I9 ~7 Z& J        // 超时,直接退出
& s' s! {, ]4 P: v! p/ U  s        Timeout:* Q. I. g7 O! X) d, J
       JMP  LeaveRing0
- m$ f" a2 \- T% y        DriveReady:
& X  v7 Q, {$ z* E9 x: N( P( [        RET
% b* _; ]. z& m7 @8 S& l4 ?        ENDP   // End of WaitWhileBusy Procedure1 ]; |; U/ L) W4 b4 y. C/ N+ c4 B

1 t) ^2 H4 G. z6 r        // 设置主盘和从盘标志
; S  |6 E7 E3 q5 L9 J3 [# O        SelectDevice proc4 S4 j( d" X7 o- _2 R

# _: C9 R2 e/ M5 t: J$ ^        MOV  DX, dwBaseAddress
* C/ v, K# _5 Y9 H, R3 J# |/ M: B2 V        ADD  DX, 67 z8 E/ E8 \, |& K
       MOV  AL, btMasterSlave* H! d5 W# e. v1 U5 _  h
3 W- r4 J- c' \& q- b
       out  DX, AL
7 M: d4 Y7 i, ~' O        RET. a) i! k' b3 {; J8 u: r

' C5 d7 p) ?0 Q4 |8 D3 y# c        ENDP  // End of SelectDevice Procedure* z& z( L4 ]! N
6 l! |  ?; M. y0 ~5 U; M
       // 向IDE设备发送存取指令+ c) }' d% b( R% n5 r# y) \7 k
       SendCmd proc: a- ^9 d! b* C
7 l8 w/ ?! @0 ]
       MOV DX, dwBaseAddress7 E/ X% a- j  h* X: G
       ADD DX, 71 H, {1 }" A) l  u- Q; _5 _2 a
       MOV AL, BL // BL是主从盘标识,在过程外设置
$ \# w8 d# [* o) J" w  M1 z6 R        out DX, AL
, g# A" ~9 G, f4 F" z2 o# B        RET2 K9 Z- I7 N! o$ q- c
       ENDP  // End of SendCmd Procedure
1 n. u) n+ U5 Z; w- N# W9 i+ F2 [$ I, F$ O+ W3 ^
       // Ring0代码& S6 j5 Y, H. N
       Ring0Proc:0 T$ R. h. T1 k1 d: W: w
       PUSHAD' W8 _' p* t- J. n
       // 查询IDE设备是否存在3 p. N1 e- W3 C3 g/ [5 @
       MOV DX, dwBaseAddress
, p8 ~3 O' ]: P& C* X! p        ADD DX, 72 v9 P9 m( j; t3 g9 D1 G
       in  AL,DX
+ P3 t& E7 K  C. @3 F* \7 [8 v7 M. }6 j  ?* P# z9 W- ^
       // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
6 Q+ r/ x& k& E9 \- g4 b. z        CMP AL,0xFF
; x% M% F( f' b9 ?2 V        JZ  LeaveRing0# g# _, J1 o7 ^7 N
       CMP AL, 0x7F
9 }1 k3 n* J  {6 h+ Q2 _/ M7 u        JZ  LeaveRing06 o) `+ y3 H3 G- D) c1 _

- D* H3 B& I$ F7 n. T2 o1 v2 ^        // 设置IDE设备存在标志& U) y& S  K0 ~: X
       MOV btIsIDEExist, 1
$ F6 X0 }0 f5 H5 h! U, h* z
, j* U) g; M0 U; R        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
1 R) y" }" o% u        CALL WaitWhileBusy% y& |$ ?: c$ f6 l
       CALL SelectDevice; h( q' o5 {1 W( E, G
: n. o2 c, }5 ?) J. g# o: s$ i
       // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏3 u* |( |5 g. w# w+ r' l
       CMP  btIsFirst, 1+ |6 S& o' e4 Q6 G. T+ {' R% {
       JZ   LeaveRing0
+ ^' f& {" R# v$ t% ^4 y' s; V" B) `3 a" ], W( L: x& e* Y" H( i4 h
       // 第一次调用时,如果执行这行语句会导致蓝屏,Why???3 n4 J1 @, E  ]7 w, t5 y  y
       CALL WaitWhileBusy9 G% Y- D3 O% y4 g* a
7 Z  L; t; K  ^& \7 u( R
       // AL的值等于cBit06时,不存在驱动器,直接返回. ~( r0 ?6 K% E- q  g& j+ l8 M
       TEST AL, btBit06
" T* w, c" j. o5 a4 P        JZ   LeaveRing0
" z% i2 m( q! J2 s2 B4 \; u! R' q
6 ~6 I! P  `& Q        // 设置驱动器存在标志
  \0 N1 J6 V- K# B! ]1 ~        MOV  btIsDiskExist, 16 r0 L# D# o0 h( c0 b9 u2 O# i
8 l$ J! \8 }2 c8 S: L
       // 发送存取端口命令
2 Z8 }8 c* k  e& H4 \7 e, A/ ?1 j        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
; l' R- d7 X- |, D/ T1 D- V! ~* A/ I        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令& J- Y- i* p! P2 w" H
       CALL WaitWhileBusy3 m7 ]2 c: ~2 f/ u( D  s7 M
       CALL SelectDevice    // 设置主从盘标识) w) q9 ]' \: r1 \
       MOV  BL, btAtaCmd      // 发送读取命令
% o/ g- ]8 K. S6 x1 W, _        CALL SendCmd+ J  b3 k; p2 R
       CALL WaitWhileBusy
8 E% K: q  o( u6 v, ^, n6 v0 _' Y
2 D$ E6 r8 y3 _! {4 ~        // 检查是否出错
9 |4 e9 n+ Z/ q# d& \2 i( X6 H; A        MOV  DX, dwBaseAddress" q% h  j  G1 o+ _* c, R
       ADD  DX, 70 T' c, |) K4 T, w' L

# I' e8 P" n( Z# l        in   AL, DX
$ ~* G1 p# T7 g# k8 ^( o* B# F1 E$ ^$ S2 l
       TEST AL, btBit00
8 E! g8 z0 r/ x9 D9 M3 P& a        JZ   RetrieveInfo   // 没有错误时则读数据
& [6 O0 D4 o: b% A
6 S1 B4 |, F) C/ m! `        // 如果出错,则进一步尝试使用ATAPI设备命令
6 v. I$ E, J' i/ J6 a        CALL WaitWhileBusy! z# \7 D# ?5 \% \
       CALL SelectDevice& n  Z6 T0 A7 \+ d& w( s4 o9 M
       MOV  BL, btAtapiCmd0 T$ [' a) @0 z2 J) X) O
       CALL SendCmd8 S1 I; W3 S! u0 \8 ?: C
       CALL WaitWhileBusy+ b( O; X! ]) o! ?

$ F* ~" z) w9 Y1 C        // 检查是否还出错: N! P1 g3 o$ u
       MOV  DX, dwBaseAddress: T0 G  v: S& |$ F) B, f# x
       ADD  DX, 7
% N8 S# y" a$ e: h6 E  [        in   AL, DX! A& f2 F; S) K3 {1 G- n; r
       TEST AL, btBit00
; r3 D2 G. Q& t4 V, P2 }. z! w' T' V        JZ   RetrieveInfo   // 没有错误时则读数据
9 q8 Q7 [" V1 Z$ O- ~        JMP  LeaveRing0     // 如果还是出错,直接返回
0 Y, G' v. }+ G
+ b5 |3 v6 m  m1 G3 W& v" _, |5 n# |0 z        // 读取数据; b, A7 i$ h- v4 Q
       RetrieveInfo:  n# U0 y' C& F  n6 d
, W/ B9 g! D; D* }! }# c
       LEA  EDI, wOutDataBuf
" F2 h: w. z0 S* f' \        MOV  ECX, 256
% E; ^' a! K( n3 `        MOV  DX, dwBaseAddress
5 n1 @& z$ L. B2 Y; m        CLD" A5 p6 C% y2 O' x

& J( u$ B/ i/ L6 K8 B        REP  INSW3 a, W+ K  V  P5 K( H) M! {

! Z0 Z+ {  e" t  c        // 退出Ring0代码
$ |+ D6 H3 M3 P7 ~; v1 W        LeaveRing0:
0 `2 v* L# e: c- z( F6 d& |0 `. h. c7 q0 f% W
       POPAD3 z0 l$ {- n: w* H* r: T
       IRETD" F8 F7 b8 O! v9 J4 E& J6 L7 `

! g1 f! b. b5 H  i0 w$ S) g+ y        // 激活Ring0代码4 y9 l+ n- S- Y+ B3 s2 K1 C4 {* X
       EnterRing0:
0 o( Z+ M& b- _$ z9 u$ y
4 N5 N, E6 O4 S' u        // 修改中断门- y  ~- }; E9 F, V2 j
       SIDT FWORD PTR btIDTR1; Y: o4 K, }6 f8 C- m6 o$ ?. M
       MOV EAX, DWORD PTR btIDTR1 + 02h( M1 e4 \' G6 J( p! `
       ADD EAX, nHookExceptionNo * 08h + 04h7 C4 _! d! ?- l) v( N3 G0 V0 D4 B
       CLI; l+ n; w9 P4 y4 b0 N

* z+ b! J0 A- M4 R; e8 k  |$ R        // 保存原异常处理例程入口5 v* W- D0 h: t/ o* j
       MOV ECX, DWORD PTR [EAX]
2 z2 x0 ?' w0 a; N3 @& d; N& \        MOV CX, WORD PTR [EAX-04h]
& a0 e" O- u/ J7 e        MOV dwOldExceptionHook, ECX
3 n6 `7 k9 P& k, {1 R$ L( @1 t+ p+ T; \# N
       // 指定新入口. g. B  C; Q- ]; ^6 Q6 T, a8 Z
       LEA EBX, Ring0Proc
( ?5 J4 _( X, o, E, S) \: y) O  d0 ~        MOV WORD PTR [EAX-04h],BX
6 L9 @$ B% ]. {" `9 ]        SHR EBX, 10h
; J) Y0 {( j8 `        MOV WORD PTR[EAX+02h], BX& ]  o! p0 n% T4 g, n+ ?5 y

: d9 G, d; I7 U* w  l) i        // 激活Ring0代码6 N; k. U3 N+ v
       INT nHookExceptionNo
3 {8 m& ^- ~, H1 L' [' @0 D
& Z* o; V1 Y5 N+ C) A4 m        // 复原入口* \( o( r  M7 M' O
       MOV ECX,dwOldExceptionHook& G) _  Y* ~% Z
       MOV WORD PTR[EAX-04h], CX0 Y# f5 r' `. f$ [
       SHR ECX,10h' ]9 J- m& D+ J# C6 _3 W* U0 Q
       MOV WORD PTR[EAX+02h], CX
$ Q6 d, z) B6 E( r        STI
% P; D) G- ^( H9 t& ?# w    }0 I( J6 ^2 Q% p% z9 i
   if(!bIsFirst)/ F+ r1 a1 d/ G( J! H2 y1 Q1 o0 Y
   {
5 Z( R9 r% v6 p6 X        bIsIDEExist  = (bool)btIsIDEExist;
- k  N- U6 D  b! l        bIsDiskExist = (bool)btIsDiskExist;: X2 v5 n  x# S9 M( }8 `
       CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
8 Z3 _0 ~+ c4 J6 m& T    }
: l4 Y& j* d$ q8 {* p- G3 V( x+ E5 g; p0 [" H}
: u: h2 w' H2 A% y. K//---------------------------------------------------------------------------7 \2 c3 e( z7 I! n7 f2 C( }+ L' E$ y
// 调用方法:
2 Z% l1 g( w& Ivoid __fastcall TForm1::Button1Click(TObject *Sender)
: k* I3 |* c& ~7 U, g{; w" I3 s7 X1 f$ q1 n# A, r1 w  S& R
   ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
, v! Z5 g# Y) \- T}
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2025-11-15 13:04 , Processed in 0.019907 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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