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

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

[复制链接]
发表于 2005-5-30 19:22:36 | 显示全部楼层 |阅读模式
  #include <WinIOCtl.h>- a2 U* \8 e5 y+ c) [
#include <stdio.h>
0 F; V' I  u1 i% A% `, r
. L% J2 Z! U* r3 |' h( d#pragma inline0 ^# n3 D, H  S, c4 S
//---------------------------------------------------------------------------0 {# c7 @. v' C2 z& D% g
// IDE NT/2000/XP专用变量
4 r2 j5 {7 n& Y6 v# @  d#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS& \  k, h6 v+ o; d, V
#define DFP_GET_VERSION         SMART_GET_VERSION. N& s* i$ }1 Q- s! z) ~  B4 M
#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
# M9 @0 ^4 o7 U. O# Q! @1 t/ c0 }#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA8 u  v3 G+ J( J2 z+ r+ ]& E
6 m7 e" r; a1 S: J
const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令: f- A9 U+ q8 l$ t" e
const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
$ h- x. T: g; E. ~4 K$ M1 l2 j, d
const int MAX_IDE_DRIVES = 4;
4 `) s' _7 m, t, ~
) r7 d7 l0 u& Q/ X: w9 H// SCSI专用变量
9 L1 r* O1 D" @- F9 L4 M1 W/ sconst DWORD FILE_DEVICE_SCSI             = 0x0000001B;
( {! ]3 w2 Y6 K5 c+ D# p* jconst DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
% p2 N; |. n# tconst DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
1 J) e4 O2 K0 o, Xconst DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;  P7 T  i, L' k; [6 y5 E
8 a3 h0 w  ^4 s# F( M6 l
typedef struct _SRB_IO_CONTROL2 K. o& l6 ?- z" |- }; o4 d1 r
{
% e7 O( h. g5 Q- D    ULONG HeaderLength;
" c, }6 ~6 M( y$ D5 h0 ~    UCHAR Signature[8];
: B# J1 W# J9 A9 R. F, \0 a! U" R    ULONG Timeout;- I2 X: A& v4 J9 M: m
   ULONG ControlCode;
  [9 t* m" ~/ d/ l$ @    ULONG ReturnCode;3 s1 U3 K" K/ _6 B
   ULONG Length;
, G  {# m6 E" b6 V3 j% m}SRB_IO_CONTROL, *PSRB_IO_CONTROL;# d: K: @- O4 F- t/ a

. R6 M# \; Y0 i0 ?% X- s// 读取的主函数' y9 P" {1 S5 @
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
3 c0 b! K( |" A, u4 Y2 _' y
5 D$ o7 g5 o- W: k9 q// 辅助函数. d0 E0 n" y" n% a
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);* V: `. {8 `  L1 m9 _5 ~0 {4 {
// NT/2000/XP函数# ?# X' b! H  @5 G. U! J! ^/ [
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);# S- N3 R3 `$ b/ h, W; P5 ^
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
0 p: ^/ o' E9 y5 G" N        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,$ ?3 Y# e% Q- o1 V' ^0 q: n5 E
       BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
8 s5 V' h7 V' g/ w8 _$ b// Windows 9X函数0 P, R% h5 A# E9 ?, m4 c
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);, c. ?. [- |! _) e
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
- r7 M. X) L( H9 J        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);/ Q& \# m6 {1 `0 [" j
% K, p0 R9 m  D
// SCSI读取函数(for NT/2000/XP)
6 j, p2 y/ f, x4 {' N  i6 C6 S( VString __fastcall ReadIDEDriveAsScsiDriveOnNT();
8 r5 m2 U4 |# W//---------------------------------------------------------------------------; q4 G' B  |" Z+ y+ p
// ReadPhysicalDrive
$ K" ]* _3 o5 `- P( M/ `' `; |0 Avoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
! b  C) v! x2 t$ A{
  t$ H" Z/ |0 Y; X" T    switch(Win32Platform)
* `  E& ^. a+ {: S    {
0 V% s8 C. t/ n/ X6 Z6 O* x        case VER_PLATFORM_WIN32_WINDOWS:6 Q8 O* {- K9 n' _
           ReadPhysicalDriveOnW9X(pSerList, pModeList);& G& ?: u% {. \6 G* J# q$ C) }2 R5 V
           break;+ k- `* J( M8 r7 a* \$ E% _1 n
       case VER_PLATFORM_WIN32_NT:- y) C! J( S# v. W- f' t" |
           ReadPhysicalDriveOnNT(pSerList, pModeList);
. T: ]4 j3 ^% C            break;! P; D9 ]! d& @, S4 V( |
       default:
/ ^' {6 e& Y! y; V7 @# w            break;
) A' e' [, D* C    }% j5 `& Q6 ~8 [
}  h2 C* w! v; [, |: i: {# D- f) ^
//---------------------------------------------------------------------------! [6 e% B- r8 K# p! Q; g# x5 d( p
// ConvertToString( a5 Y0 {4 l! @( ]# q1 g
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
& q, i; e/ t6 [# f0 |( N{
0 L/ U# [, w0 ]7 g    static char szResBuf[1024];: u( C* ^% E' N9 {' u
   int nIndex = 0;7 ~9 _% \' g" I) {; c* w6 y" p
   int nPosition = 0;- E' E" \! S; S% |# C/ v. |* z
3 m2 R% X; @2 J# ?
   // Each integer has two characters stored in it backwards
8 H2 {0 }: ~6 `+ N' _    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++), D5 S& T* |* d/ k. |; ~9 o
   {
+ m" k" w2 Z# X4 F5 h% S1 R7 k5 i- {        // Get high BYTE for 1st character
! P$ D* M% v4 o: }2 D        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);: \! I6 u/ b* P. G; n+ g
       nPosition++;
8 k# a) S$ y! G8 [3 I6 _5 X. R3 B
       // Get low BYTE for 2nd character$ W- T6 t  e+ [9 }
       szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
6 I; a) O9 d; f9 Y: e* Z5 q        nPosition++;
$ l: E; P9 Q) h& \6 o    }
6 S0 U) N; g9 W; @& Z  a( z$ Z. l- |4 F9 ~& i* b8 N2 [2 y
   // End the string' N: I9 f! J2 b2 n% ~' z( i! J
   szResBuf[nPosition] = '\0';6 B" ]' w! k8 t- z1 x* m

- c1 @3 u! ?3 s+ }    // Cut off the trailing blanks# w. |2 c! q3 y9 f- [" r
   for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
# e# k8 b5 k; W        szResBuf[nIndex] = '\0';* l1 }6 i' Y. a) Y0 q. M/ \

, L2 A3 D) L$ t    return szResBuf;. g$ o2 a7 s2 M
}+ ?/ \" ]8 N# i2 V! c4 e  `' X
//---------------------------------------------------------------------------2 {) A; P2 y) @' P5 a
// Winndows NT4/2000/XP 代码
  s) p, b# H0 t. K" @$ i- m//---------------------------------------------------------------------------
% ~% O* h$ }2 G3 m2 ^4 r2 j: a4 `// ReadPhysicalDriveOnNT* e/ c1 C/ K$ |! T5 G* o- G( u9 F
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList). B" G5 I: M$ e) D, F- ]
{5 S0 o$ \" C( Q: A
   // 输出参数" p! S1 u! K: i! v8 b0 |. u
   BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
9 I6 G9 q$ R, G) d, ^! y# N5 Y1 E6 [/ ?, U5 K9 H
   for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
) v; E* e/ W/ l( V    {# h3 h$ l; q8 k
       HANDLE hPhysicalDriveIOCTL;2 q& ^% I, x4 P9 ]! e5 e/ u+ q
       char szDriveName[32];
7 q& C  p- a2 ~& E
9 ?+ P4 s( d) t$ ~        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);: I- V1 c  D; z) o0 J# g
       hPhysicalDriveIOCTL = CreateFile(szDriveName,
* S# r2 p" V; n2 i: s                        GENERIC_READ | GENERIC_WRITE,
3 w  c* U+ o) S% {                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
: `3 b9 i  u4 ~) x& L                        OPEN_EXISTING, 0, NULL);2 W1 t+ H7 N0 [3 i' l
: J, ?& o7 B, D+ ~
       if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE), w( W/ ~( O% k6 d" Z2 T" f  g
       {1 [6 s4 A  p2 v" v' p
           DWORD dwBytesReturned = 0;
. A: y8 B, U/ ?            GETVERSIONOUTPARAMS gvopVersionParams;
; L7 V/ L$ }; M1 s- y
4 i" ~* N& L/ u! w- J5 B            // Get the version, etc of PhysicalDrive IOCTL
' R6 A" Q2 z5 k7 ]0 Q  N            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));! n* q0 M$ H9 m2 w
$ X7 d0 W& W6 y1 N+ k
           if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,+ y3 x+ n% g% @" f2 y" f' _
                   NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),2 ~. J& E! ?& y1 `( u
                   &dwBytesReturned, NULL))
$ n2 s  V* W, ^! j$ i# g8 c            {
0 |4 O9 A; K9 p+ @( X5 z% ^3 q                continue;
- G4 n- p2 ~% ]2 W( Z; D! |6 e            }
. W. C% t; T. h) C, K6 ^4 S7 j  E" a4 v% U% E2 U
           if(gvopVersionParams.bIDEDeviceMap > 0)4 q1 K8 \. [$ g+ d1 U, z) t
           {6 h  H! }- c  Z, q* W# [
               // IDE or ATAPI IDENTIFY cmd
, Y8 b& `0 t2 n8 y! L* C                BYTE btIDCmd = 0;
  o& O& Y4 d/ y7 D7 _+ s9 e  t                SENDCMDINPARAMS InParams;( `/ l4 i0 |- }0 e
               // Now, get the ID sector for all IDE devices in the system.
% d. p) K. M, d# j8 K                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
- u" U. ]. j: ~/ M8 {$ Y                // otherwise use the IDE_ATA_IDENTIFY command1 q9 `- B1 p% u/ H6 e, ?) ~7 J
               // 具体所得结果请参考头文件中的说明
% ^% {* h! P$ p+ h. j                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?+ _1 a0 g' Y6 `) Z+ c* {
                       IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;# N( y2 t8 d4 }% j- Z
               ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
+ S, h: o; e( M2 S) Z' [/ n                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
( s+ z7 s! F5 d. _5 s
$ A4 B  B' a2 i: @7 ^9 G8 C  `                if(DoIdentify(hPhysicalDriveIOCTL,8 L! Z0 W! @, H( V
                    &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,) C& R1 U/ z  w% ~1 @3 p
                    (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))5 H/ M/ C0 Z* i# b
               {* G* _$ g& w% x3 c  X% M, T
                   DWORD dwDiskData[256];; F6 {" j. B/ E5 w# D$ b- ~
                   USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
8 c" O% o7 }0 h+ R# ]% S( d                    char szSerialNumber[21];
* H0 ~5 b  t: Z& n                    char szModelNumber[41];
3 }0 c6 ~8 i/ ~5 O( ?( r% u- |1 j7 u% k! G
                   pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
" N( u) i$ T6 E+ k8 r                    for(int i=0; i < 256; i++)
0 N; `" `. [+ J$ J                        dwDiskData = pIDSector;: U8 o( _7 P" r
                   // 取系列号/ \% G% `0 K6 B& X2 K$ x
                   ZeroMemory(szSerialNumber, sizeof(szSerialNumber));% ]& c& M1 Z, E% y9 G
                   strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
) o. c& |' r6 t1 }, z) h9 r3 L9 R; @5 E
                   // 取模型号
( @$ V9 U: g6 ^                    ZeroMemory(szModelNumber, sizeof(szModelNumber));
, B, h8 i5 T1 F                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));3 P3 h' a  M+ `* o
. {8 }; F5 m! }9 f; d6 {$ G
                   pSerList->Add(szSerialNumber);
! t: n9 V/ f9 T" R                    pModeList->Add(szModelNumber);
. ]8 i( }3 f8 X. P                }7 h2 L9 @; z; I3 D# c" I0 O
           }
' t; N1 I. k  h' L7 Z( q            CloseHandle (hPhysicalDriveIOCTL);
4 {3 D+ y3 ^- b7 k        }
9 t; b' @" b6 H    }  |, m7 t/ [# F* W
}6 {8 o! L5 U; Z( K- F7 y
//---------------------------------------------------------------------------" r4 r% I3 x( d( p$ Q
// DoIdentify
, H& m( h7 M# E, ^7 Z: Dbool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
: D, J$ ~( t/ G, D7 D              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
* }; s+ L- z7 D3 ?7 E              PDWORD pdwBytesReturned)' D3 H0 f1 r% j1 j8 ?: I# \
{, C9 L/ k1 L" W& r1 C
   // Set up data structures for IDENTIFY command.  Q6 g2 ~3 }. U# O& y9 Z
   pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;) ~& _# J8 R0 d! h% F% ?& z- S
   pSCIP->irDriveRegs.bFeaturesReg = 0;
  _6 r% L8 F5 A+ N& e6 m    pSCIP->irDriveRegs.bSectorCountReg  = 1;/ W$ S4 B% p' s
   pSCIP->irDriveRegs.bSectorNumberReg = 1;6 T0 \, D1 X; q$ Y
   pSCIP->irDriveRegs.bCylLowReg  = 0;
+ f/ c" f/ i, z5 T; ~7 M- X    pSCIP->irDriveRegs.bCylHighReg = 0;
! ]( E* ?0 \- L. N
* m% D; J8 y5 p  W5 V9 H, K    // Compute the drive number.(主盘和从盘所对应的值是不一样的)) F! W9 S( [& D3 j" l
   pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
  j, |( _$ X# m# O) _& c9 [) A  s3 }0 [/ _1 Q( f
   // The command can either be IDE identify or ATAPI identify.8 D% p# X1 k6 K1 y' a
   pSCIP->irDriveRegs.bCommandReg = btIDCmd;
; h, B- E: Q' d8 T9 [    pSCIP->bDriveNumber = btDriveNum;
# l" s2 z: l! O/ p& U% _5 ^2 m0 h    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;2 B9 R: K( A: V0 v" g

6 q5 M; t0 ]( r. x    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,( _0 Q8 @7 n4 U/ y  U" Q& |$ g
          (LPVOID)pSCIP,
. [; C& N0 ^( E; [           sizeof(SENDCMDINPARAMS) - 1,: e: O" W; w6 W3 O/ Y" n+ i' y
          (LPVOID)pSCOP,
; }! |6 Q$ |& T% {' o           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
' C. |* e! @5 {/ f4 n" R           pdwBytesReturned, NULL);
% X% g0 Y. M) b, b# G}/ j3 h, u% k1 F7 ], {& @& O
//---------------------------------------------------------------------------2 |: }' Z$ J8 R& j* W( f
// Windows 95/98/ME 代码
8 k+ K! s( x! L% u2 i1 `//---------------------------------------------------------------------------
( f5 }7 A2 e# k1 U/ l& t// ReadPhysicalDriveOnW9X0 c0 M0 V  L# D- Y
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)
9 I9 J- n/ L9 }" l) B7 T{
+ {/ T5 U1 V  \% Y% M# M  h$ s7 k3 p    WORD wOutData[256];" b' y# L. v$ {; U" P2 X
   SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
: j2 s4 x4 x" T( a8 h' s/ r1 U! K8 D- k( y- S
   // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。# f2 V# L, M( V- [1 `
   // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
1 _3 j( E" S% r  P# b0 u7 x    // 避免蓝屏的出现。(期待高人能指出原因)4 u7 k7 q1 T8 Y7 ~
   for(int nDrive = 0; nDrive < 8; nDrive++)
) @  n* `5 V/ d* q8 X    {
% E4 g) c4 M( {        WORD dwBaseAddress;7 R+ V( q- p8 t2 T* w, _
       BYTE btMasterSlave;         // Master Or Slave
( D0 E3 t# Y: `        bool bIsIDEExist;6 L* @. v6 U2 |3 U( D
       bool IsDiskExist;$ u1 H9 V$ j; [# ^% c

$ U! S9 U! z; i: V0 I: Z" J2 M" x        switch(nDrive / 2)" \2 [$ d$ ]( }/ ]6 }  V2 T* @' L  h
       {$ x9 Q/ z0 J1 \7 Z. d
           case 0: dwBaseAddress = 0x01F0; break;! B4 x) B8 D1 \' l, i* U) X7 e
           case 1: dwBaseAddress = 0x0170; break;
# X- p+ U/ B8 a/ y4 L4 z            case 2: dwBaseAddress = 0x01E8; break;
$ L4 I+ F' B' m% U& U+ E            case 3: dwBaseAddress = 0x0168; break;
, S  k; F; d, c4 g+ m3 t. t; w        }
, a" Z* P, ]8 f
: Y% W0 E+ f% j4 @7 p4 r6 h% X* w        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);6 o* ]; S$ ^! W) l+ ~

4 C# T; Q: G& u( s; E        // 进入Ring04 ~. p1 K. j% }( G% \
       ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
: e8 \# |4 q+ Y0 ]                bIsIDEExist, IsDiskExist, wOutData);; g7 ]& k1 A3 G% G  u* K
   }
( A$ [! Z( |6 ~8 {+ u1 P8 q/ T7 n5 F6 @. F+ M1 l9 E
   // 开始读取
- b( x; \( n6 M0 f  f# o    for(int nDrive = 0; nDrive < 8; nDrive++)
& V" p+ P9 e& V- i' j) @! D    {4 ~; M) ~& {5 A' p- k
       WORD dwBaseAddress;
/ g% ~  T- P- R( s% S        BYTE btMasterSlave;         // Master Or Slave4 \$ d6 |& A% `
       bool bIsIDEExist;
% J0 _; l) C0 }4 M5 |5 q& Z, A( x0 Z        bool bIsDiskExist;8 m- H+ d* p8 K6 k9 h8 j
       switch(nDrive / 2)
4 R0 Z- ?& I0 A3 H( k& K0 B        {
% b3 i# U# u$ g1 e$ ~3 z8 T            case 0: dwBaseAddress = 0x01F0; break;2 F) q! t# K( J" {% W/ U
           case 1: dwBaseAddress = 0x0170; break;1 u7 W: }8 Z" j& T6 f8 g
           case 2: dwBaseAddress = 0x01E8; break;# s2 h& @6 P4 y. ?
           case 3: dwBaseAddress = 0x0168; break;' {" W% X4 Q/ |% _
       }1 t. o8 F" p7 A
: L% Q: N% j9 q- R
       btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);5 Y9 Q. B7 N2 Y! x/ U

5 c# H7 f( e& ^: I* Y        // 进入Ring02 g0 K* X8 J- h3 E: u# X
       bIsIDEExist  = false;
4 y0 H+ I6 t; l% Q3 r( q" y7 `        bIsDiskExist = false;7 N) W1 _6 h* E/ o- ^) K  d
       ZeroMemory(wOutData, sizeof(wOutData));4 h( e/ W. \% [2 T4 j7 ~

6 L; [9 k8 F* v        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
; `0 q! j0 c; y  x. ]' X9 T$ v                bIsIDEExist, bIsDiskExist, wOutData);  L: J" X. I7 g( o% n, A- C) u- M5 r
" c7 p+ ]1 B7 L/ t
       if(bIsIDEExist && bIsDiskExist)
1 h; f$ N+ y0 x' E# U; K2 G        {5 w6 Y# r  B* w) R* C3 @1 ]. M
           DWORD dwDiskData[256];
5 {' Z- y: c4 F; w            char  szSerialNumber[21];; v. D! ~( P6 v0 j' _6 C. M
           char  szModelNumber[41];
% s% i3 m$ M: p9 I1 [- ~
% W, d8 a, |  e1 n* Z* c2 C            for(int k=0; k < 256; k++)
. A) M, s( u: `4 L5 y/ k& K                dwDiskData[k] = wOutData[k];
6 @/ J8 }; C# q$ t& q6 q: r' z) ~8 H: ]: r/ ]2 y7 M* R
           // 取系列号
0 }2 V# x9 R% G; y" y% I            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));" T! g4 n4 X2 [; J
           strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));% r7 t$ A3 K( W) |# s$ Q
4 Q# e# e1 H/ x( o$ o% o1 C
           // 取模型号; r* q. c9 A% k. ^7 |" `
           ZeroMemory(szModelNumber, sizeof(szModelNumber));7 ~& T2 a% z% v( C
           strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));3 u: a  B6 D8 x# W; I3 u

# f7 G5 I/ {" ]. k1 {( L; c            pSerList->Add(szSerialNumber);
7 a/ {: u% c. i- y: b            pModeList->Add(szModelNumber);
! o8 N; B; R4 V/ o( x& w        }4 D3 Z1 \6 F1 n9 X
   }& Z; n% z/ {* x  v' \
   SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
* f! U! {" v0 C}8 U5 z; ]5 U1 X) f
//---------------------------------------------------------------------------: X- A% h3 N1 ~  [1 X
// ReadPhysicalDriveOnW9X_Ring0()! M9 F# G' O2 v0 ]! B
//+ Q! m6 |, Z4 H9 T6 c0 L% Z
// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
3 \" J) }" B# @  B) {" H// btMasterSlave = Master(0xA0) Or Slave(0xB0)) l" E6 j7 e5 B# i. ?/ S- [! k- ~' x
//---------------------------------------------------------------------------5 X3 w9 @. w! j0 ^4 ^
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
! ]+ Y! z, X# Z# g: R9 W- H# @- H        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
- b3 M+ Q/ Z' D. P. A$ b! x8 r{
$ U* |8 M$ D+ Y' _3 Y9 b    BYTE  btIDTR1[6];
  \( I* v5 ^* ~9 @    DWORD dwOldExceptionHook;& x* k5 }/ B6 k+ c# q5 H
   const int nHookExceptionNo = 5;
- }% Y" z& s' S5 a
3 ]/ F7 e9 a' B$ p    BYTE  btIsIDEExist = 0;( Y' d; i9 _/ g' ^; \
   BYTE  btIsDiskExist = 0;
9 o% E; l& W8 c7 m2 P( e    WORD  wOutDataBuf[256];% f3 I- o5 ?1 ^2 O* Q8 o7 A

, N8 r1 m! W  e. w1 |' O    BYTE  btIsFirst = (BYTE)bIsFirst;/ y8 w, d  U- a7 V2 C
' \. V1 D3 B) E' J( S# J; e% U
   const BYTE btBit00 = 0x01;
* l7 m: A. a: n, ]2 C: E5 L. y/ j    // const BYTE btBit02 = 0x04;
9 [% E2 C" v6 r( M5 R    const BYTE btBit06 = 0x40;) f5 ?4 H/ m! V
   const BYTE btBit07 = 0x80;
, k! `: W" s1 d# N3 r    // const BYTE btERR  = btBit00;' ~" x4 R# Z* ^* j
   const BYTE btBusy = btBit07;
4 [% s8 _' L# y5 W7 I- h+ O6 p    const BYTE btAtaCmd   = 0xEC;- V* s- W3 U% |* T9 t) n: I
   const BYTE btAtapiCmd = 0xA1;7 G( [' {( u( l+ u2 h6 w9 m

2 Z" V8 E* a, p' L- X- u    __asm1 g: @+ [3 n! V3 I
   {
' L& s$ U! x- K% k        // 必须先执行这条语句5 L! j) T: L. _9 i$ i1 A+ R4 m- X
       JMP EnterRing0. [- v, c. G9 \4 v( v

7 s- ?; L: M' X: a        // 定义过程7 e& `6 g- {  E1 t
       // 等待IDE设备直到其不为忙为止
6 P# L4 n$ h4 Q8 i4 f1 H        WaitWhileBusy proc
; I# H5 x# `" S- E5 m& ^8 _# A9 S" O- {! t, T$ G" c
       MOV  EBX, 100000
, ~" a# I, N" @$ I3 f        MOV  DX, dwBaseAddress
* A9 X- v7 M8 Q; ]% D        ADD  DX, 7
3 v4 c' W) g/ J; Q7 g2 S" H: O9 i& O+ @7 a6 q! s5 V
       LoopWhileBusy:
8 G; ^- g; Y% m9 O% i( Q) }# g0 t! j: g2 u& C) Z
       DEC  EBX
3 \' U! J* S' x: F3 Z4 s. ^        CMP  EBX, 0/ g# g/ d, Z1 ~! L$ F8 E5 m
       JZ   Timeout
0 L8 Z: R/ [$ M- ^        in   AL, DX8 q2 a3 w' [" r
       TEST AL, btBusy
3 u3 Q3 {, q) h. w- H! o- U        JNZ  LoopWhileBusy
1 D; r* S) J! F. X1 s        JMP  DriveReady, @  `- [* m& L8 A9 ~0 }

) A) h+ |0 f: I# I- z6 `        // 超时,直接退出4 l9 I( y0 N* F3 _
       Timeout:
6 k. f! x9 P! c% C        JMP  LeaveRing0& B& [2 |, b2 E+ b# t7 \) M
       DriveReady:8 N6 V' {: G" {) \* X
       RET4 ]" t) Y8 T& w! m* z# N. \4 x
       ENDP   // End of WaitWhileBusy Procedure
# w* E$ C% z! t. [  c! d8 u7 t: X7 e( j' t% ~
       // 设置主盘和从盘标志' g/ g% w- L& J9 L
       SelectDevice proc
- N) @; c" g- X; g8 @: ]
- j9 R2 q8 P* P  T3 ?3 `: O        MOV  DX, dwBaseAddress+ E; S* w  R+ d1 _; }
       ADD  DX, 6, R/ K4 ?, K7 G: e
       MOV  AL, btMasterSlave- `4 S$ W. [( L+ [

! _+ q. A. W  }' Q1 p3 A        out  DX, AL
5 A: X0 p" H/ p4 x        RET
& W+ F) \+ {! e9 G* f4 ^, z% w; M5 N- `( x6 c8 \2 X& {
       ENDP  // End of SelectDevice Procedure' A  g% d8 @' u" L4 N2 G
! R2 |6 ?4 R+ `+ N  y
       // 向IDE设备发送存取指令
+ F. x3 B/ z8 c; f$ J; j# D, b1 ~        SendCmd proc
. k# V% M- |5 e% x) n- o
; a- h! C3 T' H3 i# p        MOV DX, dwBaseAddress" W- h4 W$ ]# P: J
       ADD DX, 7
9 e$ B) s4 I2 }  e0 x        MOV AL, BL // BL是主从盘标识,在过程外设置
+ O3 J5 T  \' S; o: S- D/ I        out DX, AL2 O) Y8 r% _/ r
       RET
$ ?, j0 K* x/ I2 J        ENDP  // End of SendCmd Procedure4 u. X3 Y' p1 O; P# p0 }" Y' ^
# e& z6 r9 \$ U9 K# }
       // Ring0代码2 v. |0 S1 O1 D6 y
       Ring0Proc:6 T; `6 m8 G8 l. I% J; N
       PUSHAD
, l( ~+ j6 L# q8 n5 U        // 查询IDE设备是否存在: H( q' j6 H" ?. {
       MOV DX, dwBaseAddress
' x9 F0 O" F, ~& p* g2 b        ADD DX, 7
" ~+ s0 ]: G, }' ?/ F        in  AL,DX
' B: }$ X! e( W3 |6 P. C# i5 L7 [- N+ Q% j
       // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
1 J5 j$ J' p  B  u        CMP AL,0xFF  t5 T! t0 e3 \  Y% a& m' ^
       JZ  LeaveRing0- Z% y) H$ S3 D5 O+ }% u
       CMP AL, 0x7F1 B$ ]8 H7 L( J- c4 t3 Z
       JZ  LeaveRing0
4 L4 `$ n. K# `9 h  v) ?( P
2 X! d' F7 h% v8 h7 E8 N) Y        // 设置IDE设备存在标志
# e& r" u: `: v: u1 K. g7 o        MOV btIsIDEExist, 1
9 v4 U. M, G4 v7 q% U- Q1 S' T7 ]3 O5 j  D
       // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
  M3 r+ A3 w% g% x( g$ H; Z        CALL WaitWhileBusy
& _& `7 V9 Z' T        CALL SelectDevice
. n# o& g3 d$ ?9 W% n% M
5 h; l/ p9 q5 z* G        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
' b' I" C4 q- N2 t/ O& j- w9 ~        CMP  btIsFirst, 19 n8 ~2 B: O1 w$ Z" f" _  T$ E. M
       JZ   LeaveRing0" a) J4 W3 P. |, t; R
2 h8 O) k! U! }8 w4 Q
       // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
( H7 p. S/ s* X- x/ q2 ?8 H; C. T        CALL WaitWhileBusy& c1 Y& U  d& l

, R% `6 T; v2 ~! ]        // AL的值等于cBit06时,不存在驱动器,直接返回1 D0 G# k4 k6 W+ w4 Z
       TEST AL, btBit060 p+ N7 o# d+ ]: N' f2 m% G# }4 u
       JZ   LeaveRing04 j: u4 v: p6 u; U6 B% c2 ^
6 I( f2 x' Z" I6 L, ]. e* x' p
       // 设置驱动器存在标志
) p# U0 ]  l3 G: w9 R% Y        MOV  btIsDiskExist, 1  W& G! u" q: X" S& d

8 |: l% {2 t) j1 d) C* D        // 发送存取端口命令! z9 \% P* |. G) [$ G7 B
       // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
5 r, N9 E; b! E0 }0 f        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
( T* D. X6 W  J& `9 N; x6 O% A& b' B4 W        CALL WaitWhileBusy
4 k: L! g6 i4 N        CALL SelectDevice    // 设置主从盘标识; A5 X6 C( Y; m+ ^6 ~
       MOV  BL, btAtaCmd      // 发送读取命令8 {0 f* @2 H) L3 k2 d* b
       CALL SendCmd
, R% S# O" v+ M' A        CALL WaitWhileBusy
" k. N" n$ _) _- G& c) b2 w8 n+ z7 \: G, l1 S4 W
       // 检查是否出错
$ I1 @: y% ^3 ]1 t! O+ ]        MOV  DX, dwBaseAddress
  t8 Y9 D& l. {6 o  x0 T        ADD  DX, 7# |) R/ m4 j$ l/ g1 R

0 A5 C# \) l" f        in   AL, DX! ~  h. a5 r: p' o
4 q* _/ l" V& p" d' w. r3 B1 |9 U
       TEST AL, btBit00
; _# o0 T9 c/ V7 x- u: M9 o8 f        JZ   RetrieveInfo   // 没有错误时则读数据  U; B7 ?" Q, }0 g
& I5 q9 f+ T" C! ~. M3 H6 T. M" d
       // 如果出错,则进一步尝试使用ATAPI设备命令
! U5 `2 a. y, t- i& h$ X& r        CALL WaitWhileBusy
) ^3 h' @8 h% C( g1 P        CALL SelectDevice0 D( g. a- z& G- B4 Q& a
       MOV  BL, btAtapiCmd
9 _1 r! k2 W7 m  ~  D2 c% O        CALL SendCmd
( R# M: x$ M( Z3 u& `. x' a        CALL WaitWhileBusy
6 l: S) c# h3 [+ q; ?1 v( r% e  R/ v: I( O
       // 检查是否还出错! L3 `- m, f: ~( ?4 O
       MOV  DX, dwBaseAddress$ q; B1 b5 w; @/ d8 R
       ADD  DX, 7
9 h7 N  b9 O& C1 A. t( y! q        in   AL, DX4 P, _0 B. i( \: P; j6 v( \' |
       TEST AL, btBit007 [. H% x; E* g: h. |: {
       JZ   RetrieveInfo   // 没有错误时则读数据" O5 a% s* e0 }/ T& e8 w
       JMP  LeaveRing0     // 如果还是出错,直接返回
% B& ^" D! L- Q' n) D, V) @2 @2 s: u3 W2 i9 d0 X3 N( W
       // 读取数据
( B# E4 c, H, m/ k        RetrieveInfo:
) C5 n8 u, R% U! r4 d" F2 e- ]) B8 x. U; h  Q  ?% m# s
       LEA  EDI, wOutDataBuf
4 j; t: [0 [+ P& ~4 [% V        MOV  ECX, 256
" @1 V, M" {, @5 m* |        MOV  DX, dwBaseAddress
8 n* H5 Z5 L& b+ `: k+ N+ {% c. H        CLD
7 T; f7 A4 ^6 \9 ?( I8 Z) Q1 y
/ @- z9 g0 R! i/ J        REP  INSW  `# P/ {4 b0 H

6 l: e4 D0 J4 \3 d  J        // 退出Ring0代码
4 u  G+ o0 Y8 s9 P        LeaveRing0:
1 @7 j( |, _' Y4 Z* s2 W1 C+ M; D# F5 h7 B" w* S0 ~( H
       POPAD: [1 O. w1 \" z
       IRETD# H5 a' [$ {+ x* I

! j5 \* i9 X5 u0 c2 g; G        // 激活Ring0代码
+ m. |- o2 e+ I  W- K0 u9 }* X9 \2 c7 U        EnterRing0:
# ?* V) B/ l$ ?3 f8 W
" B: h/ z0 J: B( H        // 修改中断门  U% U' k. k. ?* M' }' w7 \  t1 U
       SIDT FWORD PTR btIDTR1+ u( e/ F/ K, W7 q. y# V& z
       MOV EAX, DWORD PTR btIDTR1 + 02h
9 q2 @5 w; }- q, N, s        ADD EAX, nHookExceptionNo * 08h + 04h; ^7 c1 @6 L- T- m9 N7 B' e1 ]3 J: w, {
       CLI* }. [) _# m6 X4 h" o+ H  ?/ |. Q
3 i) G5 E$ Q; r: b+ F. g% i
       // 保存原异常处理例程入口
' D, h7 J/ ?" R' q- t! E" a        MOV ECX, DWORD PTR [EAX]
5 C$ \( x" U9 V# c: f        MOV CX, WORD PTR [EAX-04h]' m) [& R  c2 d! h
       MOV dwOldExceptionHook, ECX
2 S' [# c9 ?+ n$ N! q0 D/ `
- W! S8 L9 m+ L        // 指定新入口
( T( ~: c$ K1 @& J5 c        LEA EBX, Ring0Proc
. G3 y: j3 G4 a; v* o- ~3 E" N; f# y        MOV WORD PTR [EAX-04h],BX
+ H  N' y4 t  U/ i        SHR EBX, 10h8 |! V8 q6 I9 {
       MOV WORD PTR[EAX+02h], BX% a( O( v: B. g% @

6 a& f! Z2 i! k& X; v3 M$ y9 p; n+ u& Q        // 激活Ring0代码
; }( j* R  C7 v: V& L        INT nHookExceptionNo  w; R8 v% V; e& B* x- G

9 y: \5 Z% z) B7 g4 T        // 复原入口
5 Y8 n' c: [/ B, }- r% I$ h5 L        MOV ECX,dwOldExceptionHook7 V" e9 B1 k5 m! T2 n1 g
       MOV WORD PTR[EAX-04h], CX
* R- m: ^9 k5 B& s' p        SHR ECX,10h
. G, R6 q' r' R        MOV WORD PTR[EAX+02h], CX: \4 Q/ z( o  c2 U  g' `( ~3 G
       STI/ e: r: b9 I( I, V3 `' w5 B
   }. r1 \; W3 @" Q) S
   if(!bIsFirst)
* u0 R. l! F5 q: V$ z    {& U! \8 n$ t' ^! e: B% l
       bIsIDEExist  = (bool)btIsIDEExist;, {2 ]% p+ ]1 H- H5 J: Q% W
       bIsDiskExist = (bool)btIsDiskExist;6 i* Q" B* @! H
       CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));% q2 z" x  L0 [9 J% n
   }
$ n. Y# d  R6 q5 G1 O# i2 f! K}
! ~# }* D. [0 }0 j4 @  ~//---------------------------------------------------------------------------% J9 _' _, J  A6 b- E* ~' n
// 调用方法:
% m( B/ X' [% S8 U/ S1 Hvoid __fastcall TForm1::Button1Click(TObject *Sender), V/ @6 \: h1 e
{
* L+ _% j$ R5 W    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);% {7 ^8 L& v& D  l+ H+ \# x
}
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2025-12-29 20:03 , Processed in 0.022559 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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