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

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

[复制链接]
发表于 2005-5-30 19:22:36 | 显示全部楼层 |阅读模式
  #include <WinIOCtl.h>9 i1 X8 e2 S5 @3 I( ?
#include <stdio.h>7 X( K0 T6 m( U* A

7 |( X& a6 Z# k% r#pragma inline
9 {- t2 c6 w0 O3 N+ B9 o//---------------------------------------------------------------------------
/ h* n3 J  ^; l0 U' B( |) Q// IDE NT/2000/XP专用变量
9 K" Y$ c: ^# X* I7 S# M4 b#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS  q( w% ?9 W9 {- i% ^) F, Y' y: a$ U
#define DFP_GET_VERSION         SMART_GET_VERSION! j  e" M. p4 |$ ~0 w. t% g5 d
#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND, i& a+ S5 n2 M  D& m  h
#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
& @4 E( V$ O! M5 k$ I; G$ Q! m. Q! T1 ]
const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令
6 A6 R7 h- U( J, Q/ aconst WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
9 |% K* a9 K0 M* H/ ]$ V+ B& j/ y1 f2 `8 g
const int MAX_IDE_DRIVES = 4;
0 F# M6 y9 @4 D+ |. u% V, c5 j. ~* |3 {  n& S1 `/ l
// SCSI专用变量7 k. k& G5 X' L: u! |3 d4 q# A- ?6 h
const DWORD FILE_DEVICE_SCSI             = 0x0000001B;' Z3 `+ t4 f: {
const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
& R0 j" O$ [- i! cconst DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
. G' z7 p( k2 w$ k" ~9 ~# \3 yconst DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
+ A3 k1 F4 t! g) E
6 Z" w* `  d% Q1 H% Rtypedef struct _SRB_IO_CONTROL
/ R( @" e' G  ~! O/ m{
4 C+ }0 G% Q( }; U4 _# N    ULONG HeaderLength;
/ e6 x( T$ I- i    UCHAR Signature[8];% c: w# N$ U" B: h$ D. l* |
   ULONG Timeout;- a) r4 j& I8 r9 M# b
   ULONG ControlCode;
. u+ ~# Y' m% ]. m4 \: }    ULONG ReturnCode;4 {" w) ]7 @* ~% ^
   ULONG Length;" I7 q7 G* S. G2 p& V1 ~
}SRB_IO_CONTROL, *PSRB_IO_CONTROL;
! Q" P% N5 [, M9 E" _5 q3 y
) d: x" e: s+ M// 读取的主函数
1 \7 J) }: a2 g5 O6 Wvoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
0 U, E7 Z- t) M& d# n8 s
$ R4 R5 [. X0 B3 H. b// 辅助函数
$ }  B* a; H& T6 P: f1 T7 ?char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
# C1 |1 z3 F6 z6 A// NT/2000/XP函数
# C- \0 U6 B/ @' m- L& Lvoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
3 p7 W$ i  T% ubool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,- J: L7 n1 ^$ T. m: {
       PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
, W+ I1 b2 _5 E% m: P        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
9 o* O  G% t) P& Z/ v! U// Windows 9X函数! F/ z1 Z( k2 ?7 W" x$ H
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);
, r: X- ^' g% Z/ q% L5 h8 Fvoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
4 B; t" q$ u5 |. ?4 u        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
) G+ Y6 t1 h: z9 F1 E  Y3 d- j6 X0 _$ d/ {  e9 Z& [
// SCSI读取函数(for NT/2000/XP)4 c$ E+ S. l% F( v
String __fastcall ReadIDEDriveAsScsiDriveOnNT();8 K. ]. V) F1 c; H" g* r# H
//---------------------------------------------------------------------------
* P7 A4 g' Q5 k4 Y// ReadPhysicalDrive
- y: z% n+ K# b. gvoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
! W+ s% G6 ?" A, A8 P" `) F{# t$ S  g4 ]: ~% Q; p
   switch(Win32Platform): ^1 x5 ^) q3 o) F' O/ d. s
   {
4 A+ w- z7 U) E, k3 X& s& U; l        case VER_PLATFORM_WIN32_WINDOWS:3 V0 Y* m0 \. A. s
           ReadPhysicalDriveOnW9X(pSerList, pModeList);) J0 D8 Q! E: F$ O: ?/ {
           break;: J4 H# I$ x  \0 k
       case VER_PLATFORM_WIN32_NT:
' k( ^  h& \1 ~3 U1 n  `( U! X- L            ReadPhysicalDriveOnNT(pSerList, pModeList);  d4 z( V+ x2 _  p- a& z3 t9 M+ x
           break;3 Y- Z* N7 J: x! H  P
       default:
! Q% `" Z" ~# ?& p! q: ]# H* E5 k2 I            break;
1 p/ N0 Z8 c1 F- @1 O: ^; Y    }6 H9 ?8 p% P, q' Y4 n0 D: s
}5 m' E7 k' ^& ]. r; f
//---------------------------------------------------------------------------
6 R0 s$ \! D( q// ConvertToString
4 }( ]8 Q; Q) h, s6 X6 u9 schar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
; \  ?% ~2 [+ m# p4 R  i/ e5 q{
4 C2 f/ z% G3 Y    static char szResBuf[1024];
6 u7 T  j0 l% x$ n! i) O    int nIndex = 0;' N7 k9 x/ S& E8 }
   int nPosition = 0;  W3 W  E5 d7 {6 @+ q" X2 s

- y4 m  n! ]' [" {4 B    // Each integer has two characters stored in it backwards
& V( `6 Q1 J  h. E) l7 T    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)8 g. B5 A; j2 G; ]8 r' F! h# G
   {
. V( ^5 w) C- W4 m" h1 C! n        // Get high BYTE for 1st character% i" ^0 \1 J; a9 O
       szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);, m6 i3 o  n: C: G1 G7 `
       nPosition++;9 v8 \' {# I5 }- O, z
/ s# x3 l" B8 G# ^7 h+ G' {0 L, L
       // Get low BYTE for 2nd character
9 b0 y, b$ A( ?- n: B        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);; X, I+ p) w% A) z! Z. e
       nPosition++;
3 ~% W8 {( o! Z. R9 i: t    }
8 C! L. k* n' ]8 U$ P/ E! [/ V' p
   // End the string
( q- ^0 e' r+ x' C    szResBuf[nPosition] = '\0';; m. g- Q8 [$ l2 K( x5 Z- q( W( ~
* [" a0 q' e/ m2 F2 q
   // Cut off the trailing blanks' }5 J$ r3 p/ y; w) K7 e7 Z% a
   for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)7 t+ E/ r% W0 j7 G
       szResBuf[nIndex] = '\0';5 @' f/ S3 T( u# m+ H' g" E! x5 @' n
0 a0 C$ m8 Y0 o9 t
   return szResBuf;% E: N# a# ?( z+ w
}
4 m  o1 y  Y5 ?. |//---------------------------------------------------------------------------
: b" k1 T% u! z" g// Winndows NT4/2000/XP 代码: c( m+ y! p, {( g, Q$ h! H
//---------------------------------------------------------------------------
& R9 j" B) W9 Y$ {: q# x$ |* f// ReadPhysicalDriveOnNT! |& z& o( y! y! p$ \- y0 e
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)) I! W9 A( @/ y
{' A+ ^+ J) P: N& l" A
   // 输出参数. E* Q+ c, k" [; i
   BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
' V  F( E* ~+ I# F  q
- X: Z# S) c: G# q, [! p5 ^& K    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
6 C3 g3 o/ e9 ^' H1 S( v5 P  K% w    {
- L: O* n+ V; }# ?: k3 Z        HANDLE hPhysicalDriveIOCTL;
2 Q! V; Q% z) }  f, q  h. Q        char szDriveName[32];) V1 L/ h3 Y0 z5 @6 `. O' l

( O7 l# G, s2 j! V0 _, x        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);" A# ^. t" ]1 e6 E# J4 ?
       hPhysicalDriveIOCTL = CreateFile(szDriveName,- L; [" c  x: l* I
                       GENERIC_READ | GENERIC_WRITE,: |; J' U" \' ^! E1 i! P4 R5 I- y
                       FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,! f; m$ |# c! p
                       OPEN_EXISTING, 0, NULL);& u4 H2 G% ?* t& C* k4 I  `: V; A( k

3 B6 i5 _3 s6 Z, f1 b3 f        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
+ y  ]8 J' N# b* T3 ?        {& }3 t3 g# z1 j% J
           DWORD dwBytesReturned = 0;! C+ y3 Y  R( p6 C; _& g  t
           GETVERSIONOUTPARAMS gvopVersionParams;
8 O7 H3 c+ ]0 t4 m" \; u
0 Q, N9 _6 g& K" J  N            // Get the version, etc of PhysicalDrive IOCTL+ e* N7 J; |2 F1 w* y5 a
           ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
' u( g# Y% X$ W4 t  q, V$ L* D7 n, B; {# y4 H8 ^% \
           if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
2 N, m9 x% O  r" p& g# N                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),* o! M9 S. d; \7 l! O
                   &dwBytesReturned, NULL))0 [  M6 ~0 S8 W
           {9 o7 E: n3 I" \
               continue;2 v* i; W/ q% I) b/ k1 ~/ l$ k
           }
9 M" Q# p! \6 q5 e5 X
1 C% J; V& h/ d' ?            if(gvopVersionParams.bIDEDeviceMap > 0); d+ Y! c( {! |4 ]$ w5 i: w% T
           {2 E3 b7 d+ d* z# w! C4 l
               // IDE or ATAPI IDENTIFY cmd
. i- R; I8 U8 x% V6 z$ E$ n                BYTE btIDCmd = 0;* a" \7 j- [* W8 m
               SENDCMDINPARAMS InParams;  X  {& h0 Z/ e
               // Now, get the ID sector for all IDE devices in the system.
( a" u% O: e- l# U( L                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,1 b! B1 |' I% A  {
               // otherwise use the IDE_ATA_IDENTIFY command
8 V  Q9 ?/ @. Y) E                // 具体所得结果请参考头文件中的说明) d6 R5 u' L) G/ j$ y
               btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
: ?* `& \% B0 Y9 E, {! ?8 D& B                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
9 E! F& ]* _9 e                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));# T' F" Z3 T6 t% Z/ x& o  E9 W* C
               ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
) G6 F$ o7 c- W4 y8 p0 P6 C) N
0 W/ ^9 j, a4 M8 c; Q" t: V                if(DoIdentify(hPhysicalDriveIOCTL,
% N: @  L: a0 l                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,& ]$ A7 @3 _1 D" l! M
                    (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
8 m1 u8 P' V( A( O" N/ d% o8 C5 u                {
& r, x$ [2 h6 u# }% S$ r/ R                    DWORD dwDiskData[256];
1 ^+ L, W  n/ ~- V8 V                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件& h# h/ K+ \3 U  Y  b
                   char szSerialNumber[21];
9 M6 q9 o+ |7 Q                    char szModelNumber[41];% l. A0 ?# z' r. [

) H/ U- m1 B: l3 D) t2 l* }; P                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;0 X8 O! l+ r* B4 h
                   for(int i=0; i < 256; i++)7 a, [# `9 ?9 z# G& o9 J: J5 Y
                       dwDiskData = pIDSector;$ [' Z; p0 C; h( r+ y; J
                   // 取系列号6 i$ T. J( Z& h8 o* H7 V
                   ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
  o5 _4 H( m( h3 y9 g  r                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));( `; n9 |& k' H% G! q9 v7 }' ~
3 v7 ~# `( n$ f/ A" l& A5 j! C7 a! a
                   // 取模型号1 o- P5 h' f) q2 X% t3 _
                   ZeroMemory(szModelNumber, sizeof(szModelNumber));; k9 R! x+ f* g% b
                   strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));, `2 ?- S& v1 V# R- \. ]
; Y) {! |  f( S# m
                   pSerList->Add(szSerialNumber);
4 t0 t; e  d4 ?3 b5 S3 v                    pModeList->Add(szModelNumber);' U* J; U  o2 C8 i/ I& [
               }
6 x$ n- m: }) I- q/ ^* l            }. Y1 V+ v* l  }( F! D3 w
           CloseHandle (hPhysicalDriveIOCTL);6 d5 X6 @4 X( u8 [7 U. Q( u
       }
8 d7 @& v! u1 e: v) G    }( C4 C3 ^4 F' G1 H4 Z( g" ^
}1 c6 k/ l( i  H
//---------------------------------------------------------------------------
! z- M2 }5 a$ I, t// DoIdentify* ]2 R: M( |) E8 u
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
3 `6 Y: J- c+ Q! o0 B' S- L4 @1 B              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,  D  o/ z! S% J8 W! a3 A% `
             PDWORD pdwBytesReturned)
7 V8 d6 h6 G6 d3 b# F- l{
3 w9 q  k- f# C0 a4 A    // Set up data structures for IDENTIFY command.
. c0 R4 V5 r: C) P    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;- C$ F0 `& a. S( d7 g) b$ c
   pSCIP->irDriveRegs.bFeaturesReg = 0;
, T7 e% g/ |7 t7 a4 n4 ?; H( }& `    pSCIP->irDriveRegs.bSectorCountReg  = 1;
0 _7 Q2 x( l* \    pSCIP->irDriveRegs.bSectorNumberReg = 1;, T% F2 J0 V; a. B
   pSCIP->irDriveRegs.bCylLowReg  = 0;
9 b4 ~7 p( t7 Z+ a    pSCIP->irDriveRegs.bCylHighReg = 0;
9 Y9 d' o$ P/ x( R% r# n
+ C& A/ a6 O% t8 r# p- u. d    // Compute the drive number.(主盘和从盘所对应的值是不一样的)! k. O2 ^4 ?# N/ }; A; H/ {
   pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
3 |, ~5 X& G/ }* T) D4 l) l9 A8 y, I! P% d
   // The command can either be IDE identify or ATAPI identify.
2 ?  \5 K, |6 @0 z8 i    pSCIP->irDriveRegs.bCommandReg = btIDCmd;
* ~2 u% t. I. T3 e0 w' ^    pSCIP->bDriveNumber = btDriveNum;
6 w. \8 Z, p7 [/ O    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;( b/ r0 L0 w$ Q/ O; e

! r1 Y; ^9 N1 q. l6 ?  e- u    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
' X5 R1 X7 g: b7 _4 {           (LPVOID)pSCIP,0 u+ o& u8 \' c2 i2 ]
          sizeof(SENDCMDINPARAMS) - 1,8 D( N# X% y* r5 m9 x1 F, a
          (LPVOID)pSCOP,6 y0 `8 _+ }0 |% N8 r1 _+ I1 N
          sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
- a$ q- }8 k1 i9 D8 r           pdwBytesReturned, NULL);8 E0 F3 y  t9 q, n
}* M) m" B% z# g$ y  I2 f. c9 s
//---------------------------------------------------------------------------
% F( H# P* L$ X; }+ E+ F7 N// Windows 95/98/ME 代码
% Z: z& O8 W) y//---------------------------------------------------------------------------8 K) O$ d; a9 q4 x8 G
// ReadPhysicalDriveOnW9X$ k# u" p9 S5 d) O' k1 o( t
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)8 C, q" Z6 u$ l( R
{
$ ^( x8 U! k: t$ g    WORD wOutData[256];
2 a7 ^  L7 |6 o    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
) }! _' c) g- X
, A% ?- ^3 P5 q3 P/ k    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。5 F, q' x, T5 T) b0 Q, s
   // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以  d2 j, G4 k+ e; T- v# i+ @6 c% r% ]
   // 避免蓝屏的出现。(期待高人能指出原因)8 j0 a/ M6 x$ c
   for(int nDrive = 0; nDrive < 8; nDrive++)
" v  m$ k( c& ^6 }/ L, F* o    {
& q* `0 y" C1 @  q" l. ~        WORD dwBaseAddress;
% R* ^. N2 P6 r5 l% a        BYTE btMasterSlave;         // Master Or Slave
+ s5 L% A4 r* C1 S' G% U; g  u        bool bIsIDEExist;
5 d& E2 E0 C* y8 {% m$ z        bool IsDiskExist;
, |! ^5 L# x6 Q4 R/ ]5 ?! ?# s
7 C% ~* n8 D7 |3 F8 B1 i) ?( G        switch(nDrive / 2)2 N0 _( @: n# J+ E" M
       {
  d  `2 X6 r- m" P2 O$ Y: K            case 0: dwBaseAddress = 0x01F0; break;
! S6 ]  @5 o8 v' {1 w# u( e            case 1: dwBaseAddress = 0x0170; break;
7 S# b4 u% S6 t2 S. n9 O& N            case 2: dwBaseAddress = 0x01E8; break;5 R: y/ V' x: L) e4 l7 ^2 Z
           case 3: dwBaseAddress = 0x0168; break;  R# s  T. T1 R
       }4 e6 u% a( N1 K+ _! P' h
$ D# G8 L7 n0 a+ A, p/ S, n
       btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
5 g. q" a: O5 H( |' L5 w
; \" y) c- I! N        // 进入Ring0
8 n. F# a) _' _        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,, H0 n4 J. q* P! y
               bIsIDEExist, IsDiskExist, wOutData);& m1 T$ Q( q3 B9 @* R* E
   }# u; N+ O. v0 A$ l

1 a' v" g6 r- J. ^    // 开始读取
% Z3 `% X/ e& i2 M    for(int nDrive = 0; nDrive < 8; nDrive++)
6 d4 g# y8 Z! L) C% Y    {
9 O9 Z  `: x6 g" f% w' i$ N( v4 h        WORD dwBaseAddress;$ t9 [: T) y3 i# ]: v+ U
       BYTE btMasterSlave;         // Master Or Slave
* J& u9 N. A. s# M  X* Y- O! E        bool bIsIDEExist;
$ d# ~0 W" w+ S. s; I( N+ K7 e        bool bIsDiskExist;  N9 u8 f' N8 N- S- P7 V1 u% m
       switch(nDrive / 2)' z8 G5 p; C! p/ s1 S0 _2 J
       {
" F; l2 S# L1 `7 ]. B/ E! K            case 0: dwBaseAddress = 0x01F0; break;
: g$ c- Q: \. Z/ r            case 1: dwBaseAddress = 0x0170; break;
4 `3 A' z( H6 I( s$ W9 b            case 2: dwBaseAddress = 0x01E8; break;# z) j  C% n/ Y0 X( d
           case 3: dwBaseAddress = 0x0168; break;
) ~: g- \; H5 h$ W9 {2 L        }( F9 _+ j2 U9 m

( g: R  Q; X! n        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
4 F1 p0 a( K  Z1 w4 L  C! W% w( l& h6 _5 F0 U
       // 进入Ring0
/ ~( }& [) {- {  l) v) A        bIsIDEExist  = false;
! G9 d7 d. w  Q" ^4 m* r) t        bIsDiskExist = false;& ~; p# Y- P9 C$ A
       ZeroMemory(wOutData, sizeof(wOutData));4 W0 d, _! ~, E  |( R8 X0 |: d

. t. z4 `/ y+ G7 `6 p2 {        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,% I4 K; {. v. b
               bIsIDEExist, bIsDiskExist, wOutData);
5 K% S$ H+ [/ S% J4 E2 R9 B- A: @2 a1 n6 G. v0 m) c" R
       if(bIsIDEExist && bIsDiskExist)
, R( P1 |6 l& ], D6 c        {
: [+ j8 @2 v- N& q+ Q  g0 O# U+ G            DWORD dwDiskData[256];
+ u; r, }5 h2 S% d0 S& T            char  szSerialNumber[21];
- c; V2 R- I! U. N/ @. m            char  szModelNumber[41];
4 _% G: Q' F2 ?1 w, {
0 N( t  h3 [  S( `- {+ C            for(int k=0; k < 256; k++)
2 h- {( ^( \" ?+ K. Q& b, F                dwDiskData[k] = wOutData[k];/ h- `0 C- p! G' H3 y0 k

% Y# j, i2 g4 M& J" K1 G            // 取系列号
5 x! J+ n) q: Y2 `; _            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
+ o0 c0 p' u' _& H" q            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
4 L& x$ h* ?2 L+ B. `2 m; i+ o1 H5 W. O
           // 取模型号
! a' }* j: V) z* o) h- {            ZeroMemory(szModelNumber, sizeof(szModelNumber));
" j$ Z% N/ N! i" f8 R            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
$ N# a3 a" C' U0 `' k; j- g, K: Q+ P: ~7 y; x& K
           pSerList->Add(szSerialNumber);3 F5 L) p2 O8 Z' ]: L8 t; C
           pModeList->Add(szModelNumber);
& Y0 p# I/ [5 O1 T% q4 v        }
7 n) O* p9 Q- J8 u, ]3 H% m, f, {    }
* |: D" \5 n6 b    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
) y9 @( w! ]( T}) n  Z% x+ w! `4 L4 [
//---------------------------------------------------------------------------
( I# a! p! f. g/ @// ReadPhysicalDriveOnW9X_Ring0()
* Y: |' E. s% K//  n* S5 T- Y1 W4 D% w( q& a
// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h+ q" Q: m4 W0 ]' _
// btMasterSlave = Master(0xA0) Or Slave(0xB0)
6 U5 |4 g# g8 q( A0 \//---------------------------------------------------------------------------  x8 c5 q" Z% x0 q* b2 m( g8 U
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,& q5 [/ l% U- |' m
       BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
, z& ]7 R: ]: a' O, {/ k{
" a1 Q% B9 X5 q0 P  V2 I! O, q    BYTE  btIDTR1[6];
0 @* v7 ]( m7 L& P' {  r- W8 s# v    DWORD dwOldExceptionHook;  Z& Y- r+ ~, t8 b( ^3 H
   const int nHookExceptionNo = 5;' ]% N3 k9 x% ]  \  _$ v% S7 w6 l

. W8 S( J  {% X6 D    BYTE  btIsIDEExist = 0;. Q7 r( V+ M8 u+ t+ a8 a
   BYTE  btIsDiskExist = 0;5 T/ X  z9 T/ c$ ?0 \6 M+ E
   WORD  wOutDataBuf[256];
2 P3 i6 t6 F5 ?0 J; h5 O2 o% J8 j5 C/ U) x
   BYTE  btIsFirst = (BYTE)bIsFirst;
# a/ E" e8 U6 n5 r$ W
  q1 K4 X+ _& }  R, _0 x  L    const BYTE btBit00 = 0x01;; m1 A9 m# j3 y% c4 b+ E3 i
   // const BYTE btBit02 = 0x04;
0 `; @; U# _6 z3 F* F1 @    const BYTE btBit06 = 0x40;1 p7 s: }% ~5 c
   const BYTE btBit07 = 0x80;! o, F$ u& i. {0 z9 q6 x
   // const BYTE btERR  = btBit00;
2 t% l0 p- Q8 c7 y1 p8 L    const BYTE btBusy = btBit07;6 M9 `8 ]# F; }
   const BYTE btAtaCmd   = 0xEC;
8 K$ U9 C# d9 y8 |  w! T3 w    const BYTE btAtapiCmd = 0xA1;
9 r# O8 I% f* n+ [/ q2 n
3 U) c$ A0 J9 R* I7 s    __asm, I) j7 y, Z2 r! B) i' ~
   {
. w! |# R$ M. D        // 必须先执行这条语句9 t" Z4 ]8 u6 B+ p2 B
       JMP EnterRing0  z( t$ f3 H( G) ]" o

2 C% F, F& F# O$ N% B  e+ |# G        // 定义过程
4 |/ O1 B( l5 Y. b3 I        // 等待IDE设备直到其不为忙为止! \' B' p1 u6 U7 V7 _9 _# i$ N
       WaitWhileBusy proc$ f. c9 ~. L  U9 J7 z# ]

" l0 ^& H3 w  ]4 i) V) y% t        MOV  EBX, 100000
, j0 Q* c) R( g! E        MOV  DX, dwBaseAddress! Q& J. G7 [+ K& F- {5 t+ A
       ADD  DX, 73 z" L( f  H& S2 n- z
2 B' [. ?3 T8 k7 E! T  x
       LoopWhileBusy:
% T' ?5 g1 ]- ?: d* g9 S6 g( L6 e5 d/ a" o$ }9 V
       DEC  EBX" N: ^3 w7 q8 q9 B3 O; D' a' G. p
       CMP  EBX, 0
& r& p  k$ E; \/ i* B        JZ   Timeout) G" T; i$ @. j! Z4 B& ?9 c
       in   AL, DX
* T; m. l0 [% @3 Y        TEST AL, btBusy
& {4 |3 m. y/ T+ c3 h        JNZ  LoopWhileBusy  T5 h2 j9 d8 e1 G+ h8 H3 o( W
       JMP  DriveReady) Q! h- x/ p9 k# e: n
- T# {+ \; V+ m; V: Y2 x" f/ U) o8 M: l
       // 超时,直接退出; f( L0 G$ C0 `; V( B
       Timeout:/ }# G6 C3 e0 C4 C; L' `8 z
       JMP  LeaveRing0& i( M9 K* R* e* C& N3 f5 F. {$ A$ p
       DriveReady:
0 i2 _9 q* x" ^7 o        RET
  ]; Y+ {+ N3 n: l6 n5 X' b$ X        ENDP   // End of WaitWhileBusy Procedure
, o6 ?+ M& }' l0 r- L2 C; M2 C" K$ R
       // 设置主盘和从盘标志( H: S  Y' K8 {& {* L
       SelectDevice proc
, I  x; X- |& z8 e9 ]; u2 p# Q$ S3 e. |
       MOV  DX, dwBaseAddress, ]/ V* `0 h) @: K! N" N7 j+ k
       ADD  DX, 6% U+ j2 a1 a: ]" e0 _2 `( C
       MOV  AL, btMasterSlave" C" m* g. E/ `& X1 x" J2 T
8 k$ @" y$ i* {
       out  DX, AL( _" \1 N* m3 x- ]9 s! `6 d& Q+ x7 n
       RET4 W, g* d* @7 W6 {

+ q5 m  e3 h3 _5 S        ENDP  // End of SelectDevice Procedure
, H( k7 `  ^1 N6 a4 Y* C9 O- N2 B- k. S/ N
       // 向IDE设备发送存取指令& V$ |5 m9 g- D5 J# k: e# c2 ~
       SendCmd proc3 _5 K1 H8 N6 C9 O

) p) @  Z( A  x! R5 {        MOV DX, dwBaseAddress
1 H* w  U3 j' \, `6 q/ U. @! M        ADD DX, 7
% q& M; `1 ]" k  @% ~' v2 i1 [        MOV AL, BL // BL是主从盘标识,在过程外设置% k( h* T! f3 J4 `) i: R0 B
       out DX, AL
6 ^- a* w+ r; R' e5 J1 K' e; `        RET) |# t3 m1 R. R0 `! |4 p' o
       ENDP  // End of SendCmd Procedure
. W. O. t3 t7 S/ E2 Y# M! o& e1 r2 S7 X2 i
       // Ring0代码, S5 {# P. n7 x$ W
       Ring0Proc:- G: l/ z7 z' v* b& o
       PUSHAD8 J# J& m+ C% w# o
       // 查询IDE设备是否存在; Q9 t; x' B% `5 M
       MOV DX, dwBaseAddress4 ?$ y; N* o! i
       ADD DX, 7
, x* U6 h! d1 @        in  AL,DX6 a& h4 `, T2 y! t* I& d1 b/ N
) U# R3 \9 r1 n1 x& a
       // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回, [6 m+ ~1 \, e' o  B
       CMP AL,0xFF3 z' {  j, s- m" P( O6 s0 h
       JZ  LeaveRing0
1 {8 W4 G: S3 Q' f        CMP AL, 0x7F/ F6 c6 `" G! [& U% l- j; I  f' K
       JZ  LeaveRing0/ e. r9 G; I7 \

' k1 V4 V9 j) ]$ Q. h        // 设置IDE设备存在标志
9 k$ T( k) Z& Q' ?  U5 v9 L8 w+ E        MOV btIsIDEExist, 1
' X' \2 {; [2 {) Q# V, y* |7 U2 J  U. E) F
       // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
4 e; a2 S. R* U2 ]6 s. w        CALL WaitWhileBusy' f, q( R( |$ {; q7 f1 O+ F
       CALL SelectDevice9 b1 s7 t8 t  ^  ^+ A

4 ]3 K: t2 y, d7 z, d9 @        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏, z0 [& b( @4 B4 V
       CMP  btIsFirst, 1% A4 c4 i% H# O4 y5 a& t
       JZ   LeaveRing05 f; I2 y4 P+ d5 A

3 s$ T. G: g* r3 A5 m9 J9 R6 z$ Y        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???! Y' |- h0 z3 B+ b/ h# U+ S/ {
       CALL WaitWhileBusy' ^# e# ~$ C! Z. N# h
0 d1 V" I5 Y0 A1 q
       // AL的值等于cBit06时,不存在驱动器,直接返回
# H# u# T' g0 O! Q! d        TEST AL, btBit06
* p; M* I' d5 c        JZ   LeaveRing0# k+ o$ D  v+ T* }! x
, D9 w. f: g% y
       // 设置驱动器存在标志8 D, `0 s# m' K( F
       MOV  btIsDiskExist, 18 o3 P, v# d# p/ k5 L' z3 {# p, J
* H0 {% c9 C, p7 F4 _0 B' c- i2 @
       // 发送存取端口命令5 r5 ]$ a7 [1 Q# T6 r  `  r8 w
       // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
& Y) S- i# Y3 O4 h, G% O* u        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
0 T) ~, C& n4 u7 c# w9 k5 q        CALL WaitWhileBusy2 j% m! x/ }9 A4 B: X: N& f
       CALL SelectDevice    // 设置主从盘标识
$ V, I9 n% x8 t7 @* O1 t        MOV  BL, btAtaCmd      // 发送读取命令
/ o; g1 X+ x' q) W. f# r2 g+ @& U        CALL SendCmd
7 S4 p& `& x0 s. N0 S* {; t4 X3 b        CALL WaitWhileBusy
5 s, g8 i$ V3 t/ |6 _5 b2 e: {  G! V8 _3 D, f
       // 检查是否出错" {& i. w1 y" @! V0 A
       MOV  DX, dwBaseAddress* {; A& c7 b/ f4 p/ C% |) n
       ADD  DX, 7
0 E6 J9 N" E3 }0 m; Y
; n3 W& w4 J) {        in   AL, DX
& T/ _# h. ?9 U/ f9 ~
! Z8 X: b) ?8 T& l) o  U* l7 I        TEST AL, btBit00. z4 e. l! q4 a, o  d
       JZ   RetrieveInfo   // 没有错误时则读数据
4 A' V, D' n" o9 S0 w! k  i
3 M5 W5 S: H6 E- O! z        // 如果出错,则进一步尝试使用ATAPI设备命令
7 M1 Y+ j- z( x' U        CALL WaitWhileBusy
! E0 g8 \$ E% _2 X, U# b' a        CALL SelectDevice
& `$ Z) L) A0 q* B8 O" R4 _        MOV  BL, btAtapiCmd
! z! ^6 Q  c0 o5 f3 e        CALL SendCmd* p" s4 E( [' [! O$ y  z# v
       CALL WaitWhileBusy
* o3 k# A( b! w+ I+ i0 R/ z% S4 S3 J: j; N
       // 检查是否还出错4 a1 o0 I$ \2 S
       MOV  DX, dwBaseAddress
/ H& g6 h0 y/ o2 x1 W0 ~        ADD  DX, 7
0 ]& F& K! G/ O! ~+ g. P( Y3 k        in   AL, DX
& z7 l5 {4 H7 F3 x; f# w' A) E        TEST AL, btBit00! ?/ \# h* i3 N5 m6 T4 I  r) O9 u
       JZ   RetrieveInfo   // 没有错误时则读数据
4 \! e0 A8 S- y" h        JMP  LeaveRing0     // 如果还是出错,直接返回
5 y7 K9 d3 @) g1 f
# F0 Y  {) P7 C/ p& N( r        // 读取数据2 w. a3 K( X) w. B. W- C
       RetrieveInfo:
9 S2 b+ i7 a) r  M: y5 @* d
: t. }2 R! X# l% Y% W9 g. R- B        LEA  EDI, wOutDataBuf8 g2 S2 h5 t3 I" u! P# c
       MOV  ECX, 256
- R( |; r  }. ]( M+ E        MOV  DX, dwBaseAddress2 c( F* c+ C5 @( E0 A/ J8 f! I
       CLD
4 A5 u( I1 A  u! Z1 z, Q7 i! ?
. j. r+ ?* N' e' o        REP  INSW
$ ~& a' |# Y: R( Z9 [2 C$ B0 a: t+ Y* F% {' \+ `) A% g
       // 退出Ring0代码
, S; L+ ?/ C, E! T! `- ~- z$ x8 d        LeaveRing0:
/ }2 @  j0 X* s; d7 p
! L/ z' [5 g3 ?; s        POPAD9 u+ P4 t  @7 o; ~
       IRETD
9 x0 I1 d( n2 C4 b7 {8 G- L' b0 M1 Q& F; ]
       // 激活Ring0代码1 [4 V# F% s  S0 v' p; \$ @& |) i
       EnterRing0:; g8 F! g- H  M! u( L0 ]* w5 e

7 Q- A7 c1 f% D3 V        // 修改中断门! k8 w3 l* G2 v" ~- B
       SIDT FWORD PTR btIDTR1
) U' f" c) O6 H& x. M        MOV EAX, DWORD PTR btIDTR1 + 02h
% j+ [$ _: e! \+ E7 |) ^  Q        ADD EAX, nHookExceptionNo * 08h + 04h
  D, ~& @& `1 `) K. u4 r        CLI, O8 h" T! W0 j* Y2 |4 L" z3 e

/ `' v4 S% m  X% I        // 保存原异常处理例程入口
- k& F: r; t  e: K* H6 T        MOV ECX, DWORD PTR [EAX]
2 o# w9 W, q( h        MOV CX, WORD PTR [EAX-04h]
+ I. T0 x+ Y! V, l" P( ?, v5 n        MOV dwOldExceptionHook, ECX
$ W; Z- p- j" ^: [/ v& ~! G5 w  W- s; {0 n, `
       // 指定新入口8 ?. I' z5 j8 r& \
       LEA EBX, Ring0Proc# y) [, x: g6 Y
       MOV WORD PTR [EAX-04h],BX
" Y' B+ c$ }% r& D" x* n/ t        SHR EBX, 10h0 d3 l2 y2 [4 n
       MOV WORD PTR[EAX+02h], BX) q: Q+ _+ e& e6 \7 P: @

4 M5 i0 `* B3 [2 r, Z( N        // 激活Ring0代码: X* G+ z6 G7 g5 {
       INT nHookExceptionNo
( g/ ?( k; ~4 {. a4 W# D; m: A3 K; ^2 F
       // 复原入口$ J4 a" e' ?$ W- N4 ~4 `" w4 a
       MOV ECX,dwOldExceptionHook
% c( R- W3 x& T" d# }        MOV WORD PTR[EAX-04h], CX
8 O) o3 `" A; U        SHR ECX,10h8 O3 X" o& C8 X. q+ d& f& z- f
       MOV WORD PTR[EAX+02h], CX
3 h% p) b$ M( U) A- M- {8 o        STI* V: K% P. A- z
   }0 Y: B  g* W: m$ Q8 j4 U6 t
   if(!bIsFirst)/ U0 K8 f- p: U5 u# R
   {4 ~/ {1 c! W! B2 H, d
       bIsIDEExist  = (bool)btIsIDEExist;
7 y" B- K; F% k5 w. s4 a        bIsDiskExist = (bool)btIsDiskExist;: F; B0 |/ s: e( n9 P
       CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));! ~9 N+ g- u" j9 L3 Q/ b
   }) H. q1 x9 ^% P- n" y- T
}
5 n9 K2 `% `# g/ j. B8 n! {//---------------------------------------------------------------------------
- s1 ]. D& f- ^2 d" ~. c* x// 调用方法:
5 I( [' z+ V4 vvoid __fastcall TForm1::Button1Click(TObject *Sender)* f/ ^2 q  y/ C, \! U: n; @
{  O% ^0 {9 u0 r7 O3 p
   ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
, I& U. o0 V* z/ e}
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2025-6-19 14:25 , Processed in 0.016774 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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