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

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

[复制链接]
发表于 2005-5-30 19:22:36 | 显示全部楼层 |阅读模式
  #include <WinIOCtl.h>; E; r. t& [: g" _
#include <stdio.h>" G( r) s  h/ |1 o' v6 S+ b7 W& ]7 W
. R6 z* c% B# e  A  t
#pragma inline" T: G9 S& G+ k! _# M2 f) K
//---------------------------------------------------------------------------/ {  A" m1 }5 P8 A
// IDE NT/2000/XP专用变量
& C) `' t9 i" I( M#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
& G9 N; m; z% F) l+ w; i: A#define DFP_GET_VERSION         SMART_GET_VERSION* f) D5 F3 d$ @% f" E" n! t* h
#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
& z& m4 G: X  ~4 e#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
6 v/ M. |0 f) F! x) I, N7 V8 T5 `0 n* [1 |; z, D% }
const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令
8 t) j5 i8 e* B6 P0 \$ }5 j6 \( Kconst WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
8 ?  ?. M! ?7 B1 L2 e$ B0 t% R
* b+ w  [6 m8 v0 q0 dconst int MAX_IDE_DRIVES = 4;1 {, T5 v$ U) G6 H
; N1 x2 }8 T7 k  i  x  A
// SCSI专用变量9 ~& ?5 \+ j, H1 J" s# {
const DWORD FILE_DEVICE_SCSI             = 0x0000001B;
' c( [, o& Y' z5 m; |const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
4 z. h1 U+ q. o/ @  Y' |4 ?1 v# Aconst DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition0 t9 H' {9 V2 `. t' l' ?
const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
( |  ]3 s$ T' x
9 U% ~0 V" l9 |% N2 Rtypedef struct _SRB_IO_CONTROL+ W+ R& ~4 p" H0 U* {
{
( J$ r5 Y8 {: g) ~+ m    ULONG HeaderLength;
; h" x, v. f' F5 T( H+ m    UCHAR Signature[8];+ {/ l, X2 V3 i" {  T9 |( E
   ULONG Timeout;
; ]& u) J; v4 U' \3 j    ULONG ControlCode;
( A( V1 @& G: K7 T$ t- ]% R) ~    ULONG ReturnCode;! s, B2 W6 W6 w' p* d+ y
   ULONG Length;
% J: Q9 }. }% F! c/ i}SRB_IO_CONTROL, *PSRB_IO_CONTROL;
8 U$ B: z* o$ x2 H  L" u
, p6 E- X! l, ~& W6 S// 读取的主函数
+ F) W# D7 M, G0 y& tvoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
! T4 i1 z* A* M$ s( o# L
! E+ Q( ~$ Q3 L; F// 辅助函数& Q. }0 ]) L; m
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);! W9 r9 n! }2 A+ G3 @
// NT/2000/XP函数
& W# W8 \1 E- `7 V% Qvoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
0 `* ~" L. f- Jbool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
5 L2 \2 ]7 w- S$ q( z$ G        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
+ \6 \  F; s. q" C        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);8 L- V# \* B/ T; p) E
// Windows 9X函数
, {& z. B) I2 w4 I1 Evoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);! |) H0 u! G+ v$ E$ f3 w$ x
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,6 T+ {9 W7 t1 z' Q9 k5 J
       BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);1 N- X1 k3 j' S  g; K6 A1 A/ c

6 V4 T% E8 h7 a# D0 M* F6 M( j// SCSI读取函数(for NT/2000/XP)
4 ^* }$ i3 }! f% {# v, r( YString __fastcall ReadIDEDriveAsScsiDriveOnNT();
" G9 i/ M. K! w. X0 X3 G7 g; G//---------------------------------------------------------------------------
7 }+ x* u2 z. E) p; E8 t& e& l// ReadPhysicalDrive+ l2 l9 }( T% K( `5 f6 _5 c& H
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList), U9 j, ~# J: _1 C  `+ c  N
{' _/ A5 j# B% D) l
   switch(Win32Platform)! {% I0 c5 U# g0 b& W7 ?
   {
, F4 \$ v! `% R: y1 V  C        case VER_PLATFORM_WIN32_WINDOWS:
4 D8 }9 p+ A$ {) w8 f& s3 |& p4 y            ReadPhysicalDriveOnW9X(pSerList, pModeList);
# N5 t; @/ k1 g& c0 H            break;
( T2 v/ S8 t+ C) ?% E        case VER_PLATFORM_WIN32_NT:% R: C( [4 s$ A/ H' J
           ReadPhysicalDriveOnNT(pSerList, pModeList);7 a; T" f: `+ a# z- u  b1 X+ V
           break;0 b9 O& Y% X! y/ f8 i
       default:
2 W+ j& M' F+ V# e/ S            break;. w+ y# g, c' ~) S# I! O3 T' g
   }
  v$ `% m# m, T) i8 E}
' Z* U! L! c8 J//---------------------------------------------------------------------------
8 b4 Y& }9 A9 \# |$ }, y* \// ConvertToString& ~; P, r% k, s, J! y% X3 F6 [
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)6 I8 E$ f5 U" q. b, U) O
{
! r# @* m+ z9 G7 @1 K    static char szResBuf[1024];6 C/ I3 R. e8 c2 i( S' ~
   int nIndex = 0;7 Y7 X3 z! a$ h8 b3 v; H# C# [
   int nPosition = 0;
) r/ n7 [" x: }' A
) s! `0 t. s: F    // Each integer has two characters stored in it backwards7 ^0 Q$ f1 v/ y( {: f1 x
   for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++). N* y1 G6 N+ \" L/ K1 ~* }7 X5 l; g
   {
: f9 ]3 N, K- J/ X+ _6 `6 m3 K. s% u+ Y        // Get high BYTE for 1st character
! ^' C( ?& o' B3 [7 Q5 G9 U        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);; o: V& j6 ^0 E
       nPosition++;
6 Z$ D" E! y% Y8 k" V& c( ?) }& ]  b( K$ a9 @" K
       // Get low BYTE for 2nd character/ T: ], a- |1 a& I8 {5 Z# l9 V6 Y! u
       szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
8 E4 L4 Q6 Y8 R) ?% \0 K1 X: W        nPosition++;) e5 Y. `. _1 k. A1 H; i2 |
   }
( t6 \2 ?8 D; C8 x
! W7 B. y. c7 R# m5 j. ~    // End the string! A4 @+ `0 I+ |
   szResBuf[nPosition] = '\0';
( g& ?* x3 [, u/ C/ T, p! S6 o* T/ k$ J2 f# n9 I$ B. p5 }3 [
   // Cut off the trailing blanks
: F- v# B, T: e3 Q8 h    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
5 ]3 s' Y1 k- W! c        szResBuf[nIndex] = '\0';: h7 ~# E6 E9 ~) ^' g

5 F: D8 f6 j( Z7 x8 A# K/ e    return szResBuf;
% t# `" }6 Q  r9 e" v( ]7 j6 j& Q# C}# H% F( C  r' ]4 l9 }3 f4 v1 @
//---------------------------------------------------------------------------
! o1 K& R0 g; H) J9 ?' U// Winndows NT4/2000/XP 代码8 ^1 `7 I! @3 W7 ]5 q
//---------------------------------------------------------------------------. o7 m9 w/ O! w' T& Y8 d
// ReadPhysicalDriveOnNT
5 e( }! [) y+ ovoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)* u, s3 Z) \5 `: m7 ]( |4 U* F/ A8 f
{+ H  F! h% J2 s+ ]. N: l
   // 输出参数7 i! ?3 q  u$ G# J7 L  v
   BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
; [6 y5 A6 |8 H- X, w, V! }
* v! \9 c, J9 m! j" K/ ~9 i6 ~8 z    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
8 M0 t6 o2 J6 w4 T* H    {
/ h# B" K( [; o3 U% s0 z        HANDLE hPhysicalDriveIOCTL;
* B6 {2 h( O/ c5 |( R+ Z- G        char szDriveName[32];
  p; x% |- A2 U6 W8 ^2 H
" ~' k+ i- [! [! E& k; c1 `        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);$ \! s3 s  Y" d4 U; V
       hPhysicalDriveIOCTL = CreateFile(szDriveName,
; R+ V) I6 w1 E                        GENERIC_READ | GENERIC_WRITE,
" O; s8 ?8 D2 V- D2 P                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
6 v8 C: a! B9 t* e; t; t3 J6 g                        OPEN_EXISTING, 0, NULL);
: u! l& L0 l  F* U; O% ?. I) S% Y0 |, H7 w6 _8 \$ y8 z
       if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
/ n6 V, F. n& b( h7 ?9 R2 W: y        {: [' z' A- \) m! N& R5 @
           DWORD dwBytesReturned = 0;# U! q- A0 B1 U, v* G4 ~6 p
           GETVERSIONOUTPARAMS gvopVersionParams;
4 u0 V- h9 x4 g# ~+ T+ K. P9 O/ m* G  B  @4 J
           // Get the version, etc of PhysicalDrive IOCTL
2 D# ^- p. s! F; J            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
2 P* @. ]- {9 ~. y7 ^  }3 n/ j
( W) W$ B8 h* V# p            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
7 ?$ ~0 a' C0 C                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
2 a5 o; Q- }2 |. s                    &dwBytesReturned, NULL))$ A+ S+ C/ \* I& H
           {7 R/ v* _) S& s$ _5 x6 o
               continue;9 j; F7 y1 x# j% l9 R  W* Z" c
           }
- \! j- \8 {% U3 Z  Q- Q7 c6 t1 \0 h/ u  K
           if(gvopVersionParams.bIDEDeviceMap > 0)0 o) Q' I6 {# i/ |. F5 g# f
           {
0 ?4 e0 L* n$ X* N                // IDE or ATAPI IDENTIFY cmd3 Z3 v& i! _3 X8 c) l- D
               BYTE btIDCmd = 0;
3 \9 a) t: K) V+ e! I* {                SENDCMDINPARAMS InParams;
) F6 K* A4 d+ W1 V7 z5 u                // Now, get the ID sector for all IDE devices in the system.
# d" x7 W  ]2 o$ \5 x! O0 y5 P                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
) U- O+ z. Y+ z$ W/ D                // otherwise use the IDE_ATA_IDENTIFY command( p8 U4 a1 R- a1 G4 O0 K* C, x
               // 具体所得结果请参考头文件中的说明
  f+ s/ a# U0 C) x9 `                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?4 g( D* s& s) U) c! K$ Q
                       IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;( B5 @4 f  c" \/ }1 u
               ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
4 }/ x# [7 D0 P$ M                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
& Y0 s. j2 M/ ?; q9 y- ^0 w; a3 N  f9 a$ C8 U
               if(DoIdentify(hPhysicalDriveIOCTL,
( K2 I& b) N* v0 {0 j. x! X4 S                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,7 x' t" G3 A: a/ I' A6 U% Z! G
                    (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
5 F! W/ c) h5 X7 O  R# N                {
+ w( l: \4 Q2 c& a6 o                    DWORD dwDiskData[256];
: I0 H+ C8 W. ]5 ?0 S, B                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件/ S/ a' r) K. k4 T
                   char szSerialNumber[21];2 j7 ~' q- e, ?3 x0 A
                   char szModelNumber[41];- ?7 `# l3 v$ x# W+ I' \9 H) z

1 h! I* }: u% T, k5 E                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
' W6 ^& B% j' Q0 y: v- M( Y                    for(int i=0; i < 256; i++)8 E8 @' K) A' q) g
                       dwDiskData = pIDSector;
0 C2 y7 n( v) d                    // 取系列号
6 H5 x; D" H, A& a5 w7 y& |  |( ?                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
5 r$ ^/ @; ^! f1 h/ r( E                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));) H& Z* x+ E; g! ^/ V8 f! i3 }! O
7 ]6 E, q. @* j5 J
                   // 取模型号) X; o6 Q% \  D5 b+ f4 C, `9 k
                   ZeroMemory(szModelNumber, sizeof(szModelNumber));6 o+ @  ?, }$ j* E" Z4 E+ K/ m$ H) ?
                   strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
# ~' P  U+ G( `3 L5 Y
0 m* T' D7 V2 y: h9 _" o3 i                    pSerList->Add(szSerialNumber);
* S  R0 i; F% F  X( v& S6 [                    pModeList->Add(szModelNumber);( j6 S- q* _, {
               }; U) V( ]* T: m' A9 r
           }
" S1 ?# u5 ?1 A3 b4 ?/ X1 M3 C            CloseHandle (hPhysicalDriveIOCTL);, M% P' u9 l# m5 L
       }* l1 \5 g% A  n" M3 {
   }
# W. k9 v: `# E* I}# h& l! G8 J8 }. w  g% c
//---------------------------------------------------------------------------
0 J8 w5 t. n6 P7 Q// DoIdentify5 r) R9 E1 F6 z: Y2 Q
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,+ Q5 |* a2 _2 r5 X9 u. U
             PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
% ~/ n: r# ~2 ], b- S' @              PDWORD pdwBytesReturned)
' c0 u. d2 @* \! a{
9 e. k, i) ^( ^$ s' }2 f# N. P9 c    // Set up data structures for IDENTIFY command.2 X0 ?' F  p$ ?, [
   pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;$ D6 Z1 t3 E( n4 v# R
   pSCIP->irDriveRegs.bFeaturesReg = 0;
' W. M$ `5 \6 E# i4 M! ]    pSCIP->irDriveRegs.bSectorCountReg  = 1;9 U( k* |  \% U4 k* r7 R: R
   pSCIP->irDriveRegs.bSectorNumberReg = 1;
! n0 V# B6 o- Y0 b    pSCIP->irDriveRegs.bCylLowReg  = 0;
' r& r: P# o- J4 ~) Y    pSCIP->irDriveRegs.bCylHighReg = 0;; y$ `! y  n8 [# i
$ F" G( m, N2 L' I- b+ ~  h3 l8 p8 J
   // Compute the drive number.(主盘和从盘所对应的值是不一样的)
+ P, c: E, l; b. k    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;4 d$ E8 Y% E2 M" [. R7 D& r% z
* [+ l' b$ J: s  A( N/ s
   // The command can either be IDE identify or ATAPI identify., ]6 i) \! B# F1 n' S3 S  b# T2 i
   pSCIP->irDriveRegs.bCommandReg = btIDCmd;& s. w" {$ {8 l( H/ k9 S
   pSCIP->bDriveNumber = btDriveNum;# f2 `- b0 V7 D: J6 Z7 H
   pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
, R4 |1 ]3 E- m/ Y9 J. _
9 Q, W6 C: {/ I. e" C$ {$ f    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,- q4 P) d7 d+ H4 W7 K# N) F
          (LPVOID)pSCIP,6 X- x$ \7 d! o+ ^7 w
          sizeof(SENDCMDINPARAMS) - 1,1 Q+ v9 m; M$ a( R+ I
          (LPVOID)pSCOP,
2 l; G* i( h; Q: |) X' b6 F  R4 b           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,! D  M$ j/ u+ U3 |' V1 |
          pdwBytesReturned, NULL);" G7 o+ Q9 B) w
}
& ?& i7 |# q" q. p+ ?* O4 J//---------------------------------------------------------------------------
: D+ x$ b: t% Q! Y  M7 d// Windows 95/98/ME 代码
, Z! r+ B6 G7 ^//---------------------------------------------------------------------------/ f) a9 X( C3 `3 S1 s
// ReadPhysicalDriveOnW9X
$ a5 r5 p* N  D1 `/ ~void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)) t  F. V  T9 b* i  O; f! p) ~
{
5 G5 B' \7 S$ |6 D" x) c  V    WORD wOutData[256];5 t2 j( G+ j) F6 f* t  b. v
   SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
& k7 s$ y/ U) w, G
9 D* @$ K# T2 t6 Z! @- w    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。0 ^1 F( V5 n- S8 e
   // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以; T$ n$ G4 K2 y. f% T" P8 \& f
   // 避免蓝屏的出现。(期待高人能指出原因)
9 s  `* \- m- g0 U) p/ C* U# A    for(int nDrive = 0; nDrive < 8; nDrive++)1 ~9 ?5 T0 G) a
   {
% f: H& j0 s5 I3 R& @! M8 {: D        WORD dwBaseAddress;
+ L$ {9 s# v& g& H' p        BYTE btMasterSlave;         // Master Or Slave
: T9 r: X3 `# C' k+ p        bool bIsIDEExist;3 U1 p3 A- j' n
       bool IsDiskExist;
- D4 q5 H% A0 P6 G. Y2 m; J6 ]  X% T$ z/ a8 n
       switch(nDrive / 2)
1 ]0 v3 W( \& A% L! k        {) A8 T  t- g" Z' }" x/ E; I
           case 0: dwBaseAddress = 0x01F0; break;
0 \1 \5 ^% `- ^% L% I: x. X3 d            case 1: dwBaseAddress = 0x0170; break;* Z3 @) s4 `8 [/ v8 P: @4 Y
           case 2: dwBaseAddress = 0x01E8; break;
/ Y" @( O& x- s' `- Z) F) b" m            case 3: dwBaseAddress = 0x0168; break;
  A- x5 S$ {7 S5 S( |4 E        }
; S% [; o8 `1 W4 f! T4 a" k2 B+ S) Q6 P/ e- p
       btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);9 G5 n% a" V+ K' ?: X) Z
( \; |8 w1 m4 h" H
       // 进入Ring0
3 L" i9 z/ [. Y# y8 G+ m  R        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,' X7 Z4 e! w7 M
               bIsIDEExist, IsDiskExist, wOutData);5 E/ E9 F( t% P8 e& G, ^
   }
6 i5 U. T/ U, e6 x( Y/ L1 Z: w$ k" n% M2 p. S3 \" [
   // 开始读取' I1 Q" y$ ~" m8 t! u
   for(int nDrive = 0; nDrive < 8; nDrive++)$ e$ B, ~# H) [- K
   {
+ U0 C, Q- X$ u2 V9 e" P) U  `        WORD dwBaseAddress;4 N5 A4 m0 I% u: F' d. W
       BYTE btMasterSlave;         // Master Or Slave
; q3 p3 l6 I- K# Q$ i: f9 b        bool bIsIDEExist;
! R2 ]4 d/ \4 w9 k( i1 X: \        bool bIsDiskExist;1 F/ c5 l7 J% o
       switch(nDrive / 2)
, ?) [- j, p  \% F3 e. S( v  k. a3 q# ]        {
9 \: K, t8 u& q            case 0: dwBaseAddress = 0x01F0; break;
; D$ x9 ^$ V' }1 N            case 1: dwBaseAddress = 0x0170; break;2 Q9 F) l: r. i
           case 2: dwBaseAddress = 0x01E8; break;* l- ~+ S* D( g. _7 z$ W1 h5 q4 @
           case 3: dwBaseAddress = 0x0168; break;- r" Q. E0 S) [+ ?) V
       }# F3 \: r" ]) a5 Q

- N  u  L  O$ u) F3 k: M        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);" W) a) T" p+ w0 T

8 V( v0 h* c* x        // 进入Ring0
, q; j3 e& z5 C& j* P9 B        bIsIDEExist  = false;. O0 J' u1 ~1 R
       bIsDiskExist = false;
* k& l4 Q% P0 v/ H0 {- {% U! h8 m        ZeroMemory(wOutData, sizeof(wOutData));
! v2 Q0 A% j* P8 S7 y+ S
) I- n9 B, k! h% ~# E        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,0 d/ S6 q  e: Q$ A
               bIsIDEExist, bIsDiskExist, wOutData);; m; ]2 a, n/ J% U! f+ F
, c5 d& ?' W; S6 e, O; d- D
       if(bIsIDEExist && bIsDiskExist)1 D( [5 k8 o' `2 T( P$ I
       {
( C5 [! B5 B" Y" h. z( o            DWORD dwDiskData[256];
/ v8 W6 ^7 n  c3 {; k1 q6 h2 A' Y            char  szSerialNumber[21];
3 L6 f2 h* i3 h& g            char  szModelNumber[41];$ y: ]3 t% M8 V! |
: h! t/ K3 |6 v4 V0 ~3 v
           for(int k=0; k < 256; k++)& {/ Y2 k  Q% K, \8 ?& R/ @
               dwDiskData[k] = wOutData[k];
; X! H1 o3 g9 b0 E* o7 N
! t- k( U/ P: @8 L" U( ~9 H) s            // 取系列号
6 Z, B, E; \' x7 Z% S4 G            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
) G, k! E5 Y( f# P$ x* e            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
( R# N4 r8 N( z; W2 O1 a
/ b7 y9 a9 R8 @0 L4 F3 J- a            // 取模型号* R- E8 a4 l' f" y& p6 T
           ZeroMemory(szModelNumber, sizeof(szModelNumber));
6 @' O" T; Y* F8 ]            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));, _5 C# ]; J: T, O0 u# t* ^9 G
8 i- P" i3 D+ g: S7 b" I
           pSerList->Add(szSerialNumber);
3 v: C/ |4 [: N            pModeList->Add(szModelNumber);
8 {+ S- h3 W4 T6 I0 h+ ?3 i        }. _! e& |0 e+ {6 ^% K1 G
   }! N, M) K3 {9 c2 n
   SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
& K- F# T1 V2 Y% S/ `7 K}
3 A! e* e% D1 Y& J$ w9 {- S//---------------------------------------------------------------------------
) i! `. Z& E: m% R$ f// ReadPhysicalDriveOnW9X_Ring0()
# k* _" d+ k2 }+ G' C( I1 t8 g//
+ N0 H8 @4 o& |4 q% z, s4 W// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h9 n3 R! N7 W* U: A6 f
// btMasterSlave = Master(0xA0) Or Slave(0xB0)0 z& v3 {; S) a) {! a
//---------------------------------------------------------------------------9 h' W7 y8 v/ U; _3 j
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
1 _8 d" o: i1 m        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)) L+ [' ~, u, z' h( t( ]
{) ^# r, Q  P" \9 @- s1 e
   BYTE  btIDTR1[6];0 l+ n1 `5 Q$ c
   DWORD dwOldExceptionHook;
0 f. Y/ \' q0 `( `9 g    const int nHookExceptionNo = 5;
( y: x8 J& d) n" i6 ]8 q
# Y8 f% \. Z6 K$ B* q    BYTE  btIsIDEExist = 0;
3 r% g  i! K/ S- ]' K4 v' Y    BYTE  btIsDiskExist = 0;
: A' X7 s' `8 q. S" J6 l    WORD  wOutDataBuf[256];; d- d. ]4 e; L% v! @0 r
1 o, b  a8 Q& u" U
   BYTE  btIsFirst = (BYTE)bIsFirst;
3 v) x1 Z" T2 H4 Q- u- @' H- c: A' b& W
   const BYTE btBit00 = 0x01;2 i& k! B9 W- s. y+ N, a3 K- c
   // const BYTE btBit02 = 0x04;' P( Q- _; X6 r" N3 l% f$ \% X
   const BYTE btBit06 = 0x40;
+ v& c6 \3 A- w0 M+ e/ u    const BYTE btBit07 = 0x80;
. F! b0 P$ m% `  Y- U! e1 J    // const BYTE btERR  = btBit00;
4 H- [% V- O# R! o) V2 O    const BYTE btBusy = btBit07;/ p8 B9 S. v* d4 ~
   const BYTE btAtaCmd   = 0xEC;/ Z" R7 }% H  `- V7 D6 r
   const BYTE btAtapiCmd = 0xA1;
& L9 y/ X1 H( x+ b. D" I. z2 q
9 f" J9 u9 v. R  M5 G/ D* a    __asm# [2 P) H  t. e! m
   {) J  ^$ z1 x9 B
       // 必须先执行这条语句( k2 Z' j& K9 Z/ L7 m5 ]) y5 j
       JMP EnterRing0
  ]8 D6 \) N& A5 N& T2 D% z% k6 D
       // 定义过程5 {/ A( e1 i. g- z0 F& ?5 d
       // 等待IDE设备直到其不为忙为止
0 }! l( B) ~! K( p/ }- ^8 b0 Y' [# `: g        WaitWhileBusy proc9 B$ s- D( d; _9 B& h/ e1 R2 l

4 |4 v8 R$ _. c" F$ u4 }6 x( ]        MOV  EBX, 100000' I" ]* R$ V* ?
       MOV  DX, dwBaseAddress
- Y2 S3 |# j; M& k$ y+ a/ v        ADD  DX, 7
$ W) _% Z" X6 V* R' P0 A( U( i$ V* ~
       LoopWhileBusy:
, B7 y* e  k( \% S- r) s5 p
' A' Y- b6 J& N2 N" O        DEC  EBX
+ V, k4 \5 D: K' y4 R+ {; y* L        CMP  EBX, 0
5 ?& t, y2 c. t, f* S5 U$ J$ V$ a        JZ   Timeout
' i, r. O; O: P2 K        in   AL, DX: Y6 |7 w+ A- o2 ~- V5 ?0 X
       TEST AL, btBusy. D. X1 k/ o/ L9 o
       JNZ  LoopWhileBusy
/ h1 M6 @5 N; D- c5 X        JMP  DriveReady- G9 K; u# o9 |$ |; S8 \

) `0 b1 \! h) P        // 超时,直接退出
2 f  x4 g+ i/ P' D        Timeout:3 e  X; c* W, w7 q/ o
       JMP  LeaveRing02 p) w3 F) Z3 Y" N1 v( @+ e
       DriveReady:0 A+ p, B  o8 W4 R% Z
       RET
) E2 W% `3 _/ k/ K* K        ENDP   // End of WaitWhileBusy Procedure, @: Q: W  f; q" U  }: F$ M! W
3 A; e* T) T% s  n
       // 设置主盘和从盘标志1 D& `7 E# w' b* h  r# w
       SelectDevice proc
' z0 M8 S) X) h4 y& M2 p  p8 k1 g+ |5 v- x1 j0 |
       MOV  DX, dwBaseAddress6 x- ?6 E, w9 u0 A# ?0 Z
       ADD  DX, 6: T1 @. W9 V! `" Y0 `- d
       MOV  AL, btMasterSlave
$ K4 c& j9 ?! _. G$ X  y- R( e: a; {, r1 @0 d
       out  DX, AL
/ Y1 |( p5 I, F$ y( p6 Z        RET
# b0 h2 _9 x2 S& m4 Q" ]
& W$ U4 k& z- n        ENDP  // End of SelectDevice Procedure
: Z6 d6 f3 O- M2 Z" o& N: k; z# Z: C+ E6 I3 G0 ]' I7 u
       // 向IDE设备发送存取指令
" M# E! g$ X8 ^+ R        SendCmd proc
/ [$ |5 B# z3 ]2 B  L$ y3 S6 ~! k: R0 K
       MOV DX, dwBaseAddress
! J1 [  M' c9 m& U        ADD DX, 7  R! \/ r: r# l8 Q# R  t/ D
       MOV AL, BL // BL是主从盘标识,在过程外设置0 u* |& m; `5 B  V$ X+ _1 o
       out DX, AL
2 b6 Y) N3 e2 I7 k' O; v: Y        RET* u$ k$ h5 B8 _$ o, u. ~
       ENDP  // End of SendCmd Procedure3 y3 Q7 Q" W9 _% c
! i# @: A" @4 g. ?! e$ C
       // Ring0代码; [' ], k0 E, M: \
       Ring0Proc:$ g" e; Y/ j; T5 j( A
       PUSHAD
5 Y% S  \, Q9 p3 N+ x9 l- M5 U$ ^        // 查询IDE设备是否存在
5 e- O% Z5 A. C, j- ]6 b- f9 X& g        MOV DX, dwBaseAddress
$ {/ x  U  T4 @" t8 c        ADD DX, 7
* V# s; C1 I) a, P6 ?, F- G        in  AL,DX
( a! k% t7 D9 H% l
9 x0 X. o  o$ r# F  |5 h# j( X  A        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回4 P; V% L6 F! r+ b$ m6 |
       CMP AL,0xFF
/ n0 M# Q* q/ E. S7 e# y3 h1 j        JZ  LeaveRing0% y* H& [2 `* ?- z9 N& U& ]# l
       CMP AL, 0x7F# k9 J! b! n1 K6 k  h4 }8 Y$ }
       JZ  LeaveRing0
; t5 ?/ _9 Q" E2 m
* i& O, G6 F. E/ s        // 设置IDE设备存在标志; \6 {$ j0 f7 J- b
       MOV btIsIDEExist, 1: h3 c6 V8 m4 R4 M4 r0 `
5 o1 T3 ~2 u+ l$ H, t
       // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)) ^8 ~' O! p( |
       CALL WaitWhileBusy; @; ]! }# ?6 }/ R. K1 v
       CALL SelectDevice
  I4 q, I! n" b/ B6 U7 T3 V: d( r) x/ U. Z
       // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
' m2 A2 z) m7 }2 D        CMP  btIsFirst, 1( N) B, M+ C" D' @, o
       JZ   LeaveRing0$ q" j" q6 }) s: f, q* K* B! C
) b+ i2 o! R! V/ M# z  _- c
       // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
5 |; J# ~2 z: `" ~        CALL WaitWhileBusy
3 L  p+ D; r/ Q1 S: ^5 i7 Q- q* ~; J" _6 x1 J6 r( r
       // AL的值等于cBit06时,不存在驱动器,直接返回
5 m0 P+ F0 S: x( b        TEST AL, btBit06) Z  y. }! K' _) b$ B. S+ N
       JZ   LeaveRing0! F) b- l1 u3 n3 t; t9 ^- [
$ J" S( S  b' U: r; P$ U) Z+ V
       // 设置驱动器存在标志
. M2 L& L& A9 \% Z) x2 g* S2 ?        MOV  btIsDiskExist, 1
- U" Z/ I" h" q: g
9 d! c9 f4 H3 v# X# a) I3 ?        // 发送存取端口命令' J7 ]: q7 [8 r3 r. n9 X; I5 f
       // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
' D" A6 y2 x8 u- I. C/ {        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
+ K8 N7 _5 @  [$ U6 \2 M/ \        CALL WaitWhileBusy
. [. C! o' z2 B        CALL SelectDevice    // 设置主从盘标识: h" G. v7 o9 Y5 B  S- g* f
       MOV  BL, btAtaCmd      // 发送读取命令
' j/ S9 ?! C$ H" f) L! A# W        CALL SendCmd
0 s& g+ I' D/ X$ {) {: V/ V        CALL WaitWhileBusy
1 B+ _1 d! F, P/ K
( J9 j/ x5 X2 h! ~( W9 [: n; {        // 检查是否出错
9 x: B# L/ @2 |6 v; _9 }2 I) S+ O        MOV  DX, dwBaseAddress, ~. A; W- [+ |/ H2 J4 V& F& J
       ADD  DX, 7
% g- w& j# z0 V. S, C- M; j% c
( s( S3 h. `8 f" g& i: m        in   AL, DX
# _8 D! Z, ~9 F# O
! z. N( x! D, w/ y0 }        TEST AL, btBit00% P# g' |9 a1 l; m
       JZ   RetrieveInfo   // 没有错误时则读数据+ |/ \- H! G' C$ M, x, a& o
: A; F; X+ {" I6 L* G/ w
       // 如果出错,则进一步尝试使用ATAPI设备命令, Y/ ~  r: Q3 m2 _+ c, U8 C
       CALL WaitWhileBusy
' g- Q1 z' ]3 I; j2 X; I! J7 ~; t        CALL SelectDevice
7 Y9 r8 m% _- e; [' l        MOV  BL, btAtapiCmd
& h4 m5 N# u+ ^% ^4 h( s0 Z        CALL SendCmd9 \  c  d& v2 m2 C% ^  ~  X
       CALL WaitWhileBusy& N' @& E7 @* Y! c* X7 G

* C& Y# h( f- ?4 M5 U        // 检查是否还出错. K4 i5 f4 U& x8 `$ ^
       MOV  DX, dwBaseAddress& A8 u: z3 L; b. Z) w1 Z& t
       ADD  DX, 7! {5 K( [' D( e: g7 P
       in   AL, DX" K. O6 x; \7 e% {
       TEST AL, btBit00) [" H& Y. J; G; w$ m7 v
       JZ   RetrieveInfo   // 没有错误时则读数据: `# i9 Q' {6 C: E) F
       JMP  LeaveRing0     // 如果还是出错,直接返回/ K2 r  ~9 T- D' _. ~' R0 R/ O- s- Q8 M

& l% j+ [2 d( v        // 读取数据: @4 f+ b; |" d) X6 j( R7 v/ d
       RetrieveInfo:
* t5 `% [. W0 j8 g% N9 I6 E* i1 O
! {& E; ?9 S  e) Y0 i/ X4 I        LEA  EDI, wOutDataBuf* B4 ^/ [: q' ?5 h$ A
       MOV  ECX, 256/ ?8 N; W& X$ o9 M0 N
       MOV  DX, dwBaseAddress
4 J& r. H( d/ U" ?        CLD
/ i+ A7 G0 ?, |; s! R: v7 D+ @
2 H. z! u% P6 L" H4 x7 i. p        REP  INSW
! q7 l4 o8 \1 I7 @. E# K+ N2 B- Q( R7 r. V" f' N9 N/ p) g
       // 退出Ring0代码: `. _) Q9 o! b3 Y
       LeaveRing0:
0 T) g# n. N+ a$ v
) E" T+ j3 o* q" B' J        POPAD
4 f; Q* M: ^) [% _- v        IRETD
7 j. Q4 p, _& z. v% h& S/ F* y6 A& K! Q1 h' t2 f
       // 激活Ring0代码
0 L8 Y0 {( p6 k! I! ^        EnterRing0:
4 Q0 S, ^% D& w9 Y* C; H
1 _2 k1 m4 c" ]        // 修改中断门
$ [; Z; u9 p' s0 N4 K, }# ]* u        SIDT FWORD PTR btIDTR1
7 A9 [! N, l* v  c        MOV EAX, DWORD PTR btIDTR1 + 02h5 \- K9 z  T) t
       ADD EAX, nHookExceptionNo * 08h + 04h+ G  ]2 X: N" G4 ?) R" V$ Z6 g5 v+ z
       CLI
7 V/ f2 |" L$ r! n1 i% O' X6 q0 g7 w2 k( ]$ s: W+ W3 ?( i* O! F9 u( s
       // 保存原异常处理例程入口
* W0 V8 `) `+ }/ A. E! X  P        MOV ECX, DWORD PTR [EAX]) i4 ~1 @' ~8 d- @& d* W' A( F' J
       MOV CX, WORD PTR [EAX-04h]
- n+ s: \" `# I9 q/ L' w        MOV dwOldExceptionHook, ECX% R7 n# D% Y; B1 i/ C- }
: p! Y/ ?- {- {. k
       // 指定新入口  F  U( ~# D- ]6 P9 l
       LEA EBX, Ring0Proc; y: Q: Z) u' h, o4 E6 r+ E. P
       MOV WORD PTR [EAX-04h],BX- z* N# z$ q& _3 D' C4 N+ h
       SHR EBX, 10h
* i, Q5 Y+ u0 _- r2 D9 u4 c        MOV WORD PTR[EAX+02h], BX
/ @! F& Y1 d8 a6 }) I6 T% a$ o$ X! y7 ?! _$ q) l" |6 h( R+ o5 B
       // 激活Ring0代码
5 _# S+ e7 x9 e. P# N2 R6 R        INT nHookExceptionNo: F6 u% k  e0 w  I: G
) H  K$ t3 r0 ?9 R1 m% c
       // 复原入口4 W% h$ p9 I! z
       MOV ECX,dwOldExceptionHook2 B6 D* p2 G( A2 I& c
       MOV WORD PTR[EAX-04h], CX
2 y; x; j, g  L0 w        SHR ECX,10h* X( o1 _* {7 n, \
       MOV WORD PTR[EAX+02h], CX- r, u5 ]" W3 u" O/ H4 ]
       STI0 D, C. V1 g, F( ]
   }- P8 w6 n: r  }* O+ \
   if(!bIsFirst)
# E% ~( y8 J! b& Y" L1 G    {
. s8 e9 V  u* Q+ |. W, J9 P        bIsIDEExist  = (bool)btIsIDEExist;$ m0 z( G% \2 G
       bIsDiskExist = (bool)btIsDiskExist;
6 P2 z5 w3 `9 x- y  L3 b8 f" p        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));3 q! ^" G; l# F2 q
   }
+ m4 p/ k# v/ n/ O7 H0 [2 _7 n" @9 K}4 c( y# \6 P5 S( |/ I/ i! y
//---------------------------------------------------------------------------9 f, {0 c2 C! \8 G
// 调用方法:
' k3 I" w4 k6 u& x9 z2 R, X5 [! Uvoid __fastcall TForm1::Button1Click(TObject *Sender)
% B/ J" K6 W$ p% X) y) z{' V, L& J& r. B: M7 {" `1 h! Q% m: X
   ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);2 l2 n! U0 q) b  ?5 ^
}
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2025-8-9 01:36 , Processed in 0.035653 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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