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

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

[复制链接]
发表于 2005-5-30 19:22:36 | 显示全部楼层 |阅读模式
  #include <WinIOCtl.h>
/ `0 q5 ?3 f1 X8 y#include <stdio.h>/ U2 V1 r, Z) T, \" f- d3 T
3 v+ T" H: b1 b( A- V8 L4 c9 `
#pragma inline
7 G& T; ?% S6 h( B- l  y//---------------------------------------------------------------------------
- [5 z" i$ [' X// IDE NT/2000/XP专用变量- T9 g2 U+ ]& i) F7 E" J0 A7 v# ]
#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
" t& H" z9 |$ S0 g4 j6 A1 ]#define DFP_GET_VERSION         SMART_GET_VERSION
, ?8 R5 b" I; j: {% U7 @#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND% h: {+ q* W" F7 \* L7 G! }6 P
#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA7 t* C0 e( J; }4 T1 C$ ^

. X' C) A' \. s5 l+ \+ n+ Y* A9 wconst WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令" r- c5 M* F) @* N& U
const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
! g9 R9 ?( N& F8 K
/ W3 i/ b# J: }. _  d* W1 d5 A$ fconst int MAX_IDE_DRIVES = 4;/ i. _' [7 i# n

8 d" h9 H  q- A0 e5 Q" K% }// SCSI专用变量
  d9 k; V, m, f- t$ U1 lconst DWORD FILE_DEVICE_SCSI             = 0x0000001B;
7 T# l1 x7 F* B- N; A* ]8 t  q, econst DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);. t" G, s7 U8 d
const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition: a9 p# j/ F5 g$ H# ^# o. c
const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;* ]  F, e$ y; r! ~7 _
3 K4 L: r7 P% k8 v6 o
typedef struct _SRB_IO_CONTROL' n: i( E, N( t5 H3 t" E) c' f! F
{
# z6 l+ G( b; H2 E, h7 m  z0 I: {    ULONG HeaderLength;( N5 L" E, }  E5 ?# d4 u
   UCHAR Signature[8];) u4 a& N! y! J6 Z$ q' l7 J4 H) ?
   ULONG Timeout;+ \: T4 @+ O6 f5 }
   ULONG ControlCode;; l1 J+ H8 G. `3 t: C
   ULONG ReturnCode;1 v. E: f) z, ]& t) H9 q5 R
   ULONG Length;
' P; k( r) y( i}SRB_IO_CONTROL, *PSRB_IO_CONTROL;# u# N5 `1 R+ Q, G6 n8 W1 b( D

& e- x4 }/ d; q' N6 g* p// 读取的主函数
, b& |( ]8 w" @1 g6 qvoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);3 J1 b: h# \" g
2 v" p% d3 M5 o: H
// 辅助函数
( d. q5 O" u* C! P* v: Y' l( `( pchar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
$ f- S1 K8 i3 Z0 a! @// NT/2000/XP函数
- R- A' u7 r2 |% Fvoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
# [! }( H! o% V+ b9 }: F9 abool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
5 i- G; G' @5 `/ I' g# |! [. h        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
, _4 ?* E( H4 Q# S# Q! C' m8 y        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
) [: m9 t- I8 X/ i// Windows 9X函数) s! p. @( ^2 o- \
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);! ]) P2 ?1 P4 b3 f% E3 a
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
) H, F6 s$ z- O( X1 [; x; n+ @3 e        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);; N8 P0 T( ~7 }1 j( R/ Z& }
3 J0 D! w# ]9 V4 _
// SCSI读取函数(for NT/2000/XP)
9 g9 D& P- {1 k+ i) E% BString __fastcall ReadIDEDriveAsScsiDriveOnNT();
' ]5 J6 E+ k2 B" i- Q; _* {7 G. H//---------------------------------------------------------------------------: P3 N7 |  L) [  g* e
// ReadPhysicalDrive
; v  O) G" N1 p, \1 E6 W; @) Hvoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
2 n6 K0 ?) w0 z/ C8 w& t{$ C: u# j- f( g# ^1 a; f0 a
   switch(Win32Platform)" |2 B6 O6 g. D+ ~
   {7 R7 C6 F( ?( v, l
       case VER_PLATFORM_WIN32_WINDOWS:# |9 ?6 x) m+ k( X/ w2 _
           ReadPhysicalDriveOnW9X(pSerList, pModeList);8 P8 ?% W9 C+ P
           break;. u) |1 x+ W4 ?( S
       case VER_PLATFORM_WIN32_NT:
( [3 f# f! k  {3 f8 ]' L# a% X! O            ReadPhysicalDriveOnNT(pSerList, pModeList);" V1 `1 ~9 u9 Z  S  W9 M% k6 I. e
           break;- x1 {+ n2 }7 p' o7 w9 R. \# s0 F
       default:- \/ l$ U1 \, ~) R  Q2 i! c
           break;
1 }9 p) _- y/ o9 L3 @. W    }3 \* a3 v0 }* Q; |9 Y  H% B* @6 n" _
}
  V' U; _! F  U8 @- C//---------------------------------------------------------------------------& q% I% x) V, M& M3 f: u: d- {
// ConvertToString
  L0 \$ o7 @* Uchar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
1 h. b# Z( l+ K{
9 L) M  m5 E& s' [3 C, I# Y: z& F    static char szResBuf[1024];
! ?5 I+ U1 D3 s& J0 i; b" n& Z    int nIndex = 0;2 V: u8 Z% ^# x. T' U& }+ H
   int nPosition = 0;
& h- M% |3 n, K. v& h* H  g& ?, R9 i% y0 Y
   // Each integer has two characters stored in it backwards5 d; Z# v2 K: [) L/ j
   for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)! h. M) X# y7 S3 I
   {
3 l* H5 I* y; x6 a+ U6 }        // Get high BYTE for 1st character
" o( B5 @" R# w& h8 w: H        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);' q" W! s# w1 L) A8 A" Z$ c. a
       nPosition++;
' A3 v( {; }6 g' I( J
% ~5 x0 D: U: N$ A        // Get low BYTE for 2nd character
3 {- H. N4 \# z$ [        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
( n# \+ a  F; n3 b. w        nPosition++;4 u' y1 p. s4 d) v; Y
   }
1 D/ X1 M# N1 h2 q# J7 s( N" B$ {$ ]
+ P- k# K2 w+ w% T    // End the string
5 q7 q' [8 J, Z: d/ p2 G3 b( ]  x2 G    szResBuf[nPosition] = '\0';
, ]) e$ P# {; F* [- o* o; m0 l$ f7 @! I# U. i  ]! U
   // Cut off the trailing blanks
1 b7 `) ~) u9 }  {# O; \3 ]" }; D    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
* I, [" W) z0 x: H$ }        szResBuf[nIndex] = '\0';
  p8 G/ \/ T# F6 Y& F; ^9 V# a$ ^, K: D' U+ a
   return szResBuf;8 Q8 B( B! T4 M4 V+ e$ ~: x
}
! K* C0 {* v. x* H0 q  j: n//---------------------------------------------------------------------------
: `% w- T  E6 }* l- X// Winndows NT4/2000/XP 代码
+ F% i2 p  r% q  [//---------------------------------------------------------------------------- [! |9 G# D5 m* o" `! @% X
// ReadPhysicalDriveOnNT
  Q  Z$ x6 a% W2 c: J# m6 Y. {void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)0 t$ V% Q* T% Q# P9 w  d5 b, p
{$ V9 _+ n! d$ D1 [
   // 输出参数
0 z& U$ _, B5 B    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
- U* n* [* S/ s$ [! J+ W) V8 F# l/ _$ _
   for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)2 q9 ~8 N9 o+ Z0 J7 N0 d. @
   {: b; ~1 v# {1 Z" \) p
       HANDLE hPhysicalDriveIOCTL;
" i8 ^' G: m" X. Y$ Q5 Z& m1 E        char szDriveName[32];
' G% J. T3 z% O, ]1 u
+ T; J+ d4 B/ y" D. g        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);+ \) X: f- i1 o" U8 ~8 k, L5 r' K
       hPhysicalDriveIOCTL = CreateFile(szDriveName,$ ?$ t- T( H; e" ^6 @
                       GENERIC_READ | GENERIC_WRITE,
. m+ I$ N/ S) n7 W! e                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,1 f: S" j$ M3 c: N+ n. X3 M) T( j
                       OPEN_EXISTING, 0, NULL);
/ P! T7 k; l8 [2 w$ q4 a) A. Y3 E6 y9 M9 b, q& }) _9 ]" {
       if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
0 p/ e" W, L" _( r. u3 o4 C" x$ ^' b        {
2 e, [+ b4 Y, B            DWORD dwBytesReturned = 0;
2 Z4 L$ _! B- p. L$ k0 {, n8 c            GETVERSIONOUTPARAMS gvopVersionParams;
. n% I# Y8 y( W/ c! ?& {6 z. [6 w! l8 ]
           // Get the version, etc of PhysicalDrive IOCTL
/ |6 X' a$ I" G/ ~            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
" h  f2 |% `% B9 Y2 u( J2 ~6 r! A
: b" W5 {4 I4 p7 D& i$ N% @            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
7 D9 C% F( X& K0 |9 E                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),0 T. P/ A% L- w6 Q2 T* ~
                   &dwBytesReturned, NULL))
$ z! q- d" s; V1 W$ c  f- `            {9 [, n5 v  b( Y4 `
               continue;
: o' U, ~' P) h) D0 o: {% |            }
% x3 U# r; ]9 \8 w9 i) B& X& @6 r0 \; s6 O
           if(gvopVersionParams.bIDEDeviceMap > 0)
. L) B9 o, F, D6 i+ D/ Q            {
8 F% t+ z0 x* |# C                // IDE or ATAPI IDENTIFY cmd  n6 M' z( F. L
               BYTE btIDCmd = 0;% u& @# m- @- X! k/ a
               SENDCMDINPARAMS InParams;3 B0 Z7 X' `/ W; c
               // Now, get the ID sector for all IDE devices in the system.
. P" w, j: h) h* B0 f0 U# T                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
8 N6 C9 ~7 r' `4 N                // otherwise use the IDE_ATA_IDENTIFY command3 V  Y9 F" n5 S& I$ a2 s
               // 具体所得结果请参考头文件中的说明/ d: J7 U! C9 a# |
               btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?! ?2 F% I9 g+ O8 Q4 J& o
                       IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
9 S/ Q5 x" r( g$ k8 p- S. v                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));1 f* K* S& ?3 g
               ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
1 `. s$ h( H. I! h9 b, |, ~7 ~3 Z' u1 s- `# V- X
               if(DoIdentify(hPhysicalDriveIOCTL,
& e* v0 @+ G% n2 I6 [                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
. V+ ^+ z$ n2 X1 ?) t- L                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
! Q8 J* k5 V6 Y$ [# B" a                {$ i7 m5 p1 m3 y" }- N( G2 F* S
                   DWORD dwDiskData[256];
7 K9 G5 U% _) o  P1 m4 l                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
* o) k) E9 R$ L% Y. ~                    char szSerialNumber[21];
  A' Y0 m9 {1 W1 Z                    char szModelNumber[41];9 w. d5 I; ?3 F9 {8 |( y) C4 t

8 c7 G  v; ]9 O5 B" v# E" |- G                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;$ K+ _$ J2 ?4 F5 x- |) C
                   for(int i=0; i < 256; i++); g6 C* ~! {2 U+ G% C$ G+ {
                       dwDiskData = pIDSector;& M5 ~8 g! F; z
                   // 取系列号7 V6 i4 R- n. e$ i, d3 U
                   ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
0 Y/ n: n7 ~$ ]  s6 v9 {+ s, s) F                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
- G" M) z& h. [7 w2 \
! R2 ^/ ?0 f& D: G/ O                    // 取模型号4 P+ e* j; s. ~$ j- c1 d3 O
                   ZeroMemory(szModelNumber, sizeof(szModelNumber));
: e9 z3 B4 q6 Q6 d                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
1 x( i. A, w' ~7 p  J/ e; v/ ~" l
+ k; k; R  x% b) Z1 h0 f5 C                    pSerList->Add(szSerialNumber);
# [. D: l4 k8 h0 {% o: R1 ^7 K                    pModeList->Add(szModelNumber);1 q8 h" ~7 Q# T6 f
               }& y; M; R+ i4 L
           }3 Q$ h: r" @7 _: Y! d+ U
           CloseHandle (hPhysicalDriveIOCTL);$ M# R: e) Z' L9 b" j' s
       }
% ?- b$ N- [( X4 @    }  z- l& L( R& N
}9 b) I$ l3 e% R) z9 I* r
//---------------------------------------------------------------------------* H2 q* ?" P8 y9 i8 T, o
// DoIdentify/ y# H  x% `( J, f
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,9 C% l/ t* l& R' I, M
             PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,% q+ ~7 r' R8 e) G2 k$ Q: u1 x
             PDWORD pdwBytesReturned)5 r: D. _5 b2 R, ~. f( e' o* @
{6 ~4 k; P" e- Y) F
   // Set up data structures for IDENTIFY command.. C; G" }" V( ^% z
   pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
) ?) C  [; ]! K    pSCIP->irDriveRegs.bFeaturesReg = 0;
7 v) x5 B8 o$ a" G# m    pSCIP->irDriveRegs.bSectorCountReg  = 1;# W* g1 a( l3 ^5 [4 R7 L: u2 n
   pSCIP->irDriveRegs.bSectorNumberReg = 1;, I. a3 V% V7 j" w% H/ [& M
   pSCIP->irDriveRegs.bCylLowReg  = 0;# @! O$ k* Y( f* S/ b2 }1 x
   pSCIP->irDriveRegs.bCylHighReg = 0;
8 q7 J0 D# }; y) d! y/ }. P; h+ u0 I. m" U! D( N' J; S
   // Compute the drive number.(主盘和从盘所对应的值是不一样的)
: z8 t$ e0 w3 Q3 _) z+ [! l    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;: i, q9 Y( w8 E+ B3 w* U  m+ B

! c" e0 c1 ?/ O: K, ]  }) \5 a    // The command can either be IDE identify or ATAPI identify.
+ T0 i6 N, n  ~/ D: k0 D    pSCIP->irDriveRegs.bCommandReg = btIDCmd;
) p, R. V+ _1 S& d2 L- `# o    pSCIP->bDriveNumber = btDriveNum;# w# `5 k+ W/ T4 f* o- u
   pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;# p+ X" L0 O( ~6 {
- s9 ~" p9 t/ z6 J  D' m+ w
   return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
( ~, B8 a7 @" W8 Z* J6 y           (LPVOID)pSCIP,7 O% G4 z2 c& m' u
          sizeof(SENDCMDINPARAMS) - 1,6 L4 ~! w3 t3 o  X
          (LPVOID)pSCOP,9 k2 e3 f6 O2 z; c
          sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
, ?* z& ]7 x, ]! `& ?1 \           pdwBytesReturned, NULL);  X: E% j& [1 w- ?1 @
}- e5 O- V' B% c0 R+ E9 E9 N5 e
//---------------------------------------------------------------------------1 A, R9 E' |9 A7 {; J: }
// Windows 95/98/ME 代码
4 b  z5 J. X( [0 e3 S//---------------------------------------------------------------------------: t6 U5 B  C1 q$ V6 [! [+ u
// ReadPhysicalDriveOnW9X% [) d9 ]0 h) Z
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)' V6 j( {: B" p! i. H' E) X, r' w
{
( ~7 h" R8 D& J  G, w, ~    WORD wOutData[256];
. j% H) H4 \( W. M    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);2 o2 |% X8 b( m# I! D" {

. A! i4 S. e* C, Q6 B3 V5 k    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
7 I- J8 h% k: f2 R; ?& t3 ]1 v    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以8 W8 J+ n' Q7 \! F: v! t, L4 ]
   // 避免蓝屏的出现。(期待高人能指出原因); J. M5 q. J* T( r' D
   for(int nDrive = 0; nDrive < 8; nDrive++)3 ^6 W( g" _! [( |/ B6 j5 m
   {
. Y* K: ]/ X* ?, |        WORD dwBaseAddress;
. j3 S2 `0 I; V# n        BYTE btMasterSlave;         // Master Or Slave
$ D! e: x4 K/ _        bool bIsIDEExist;
8 ^5 u- ]% W6 ]: W# m( y" G# {" i        bool IsDiskExist;
" H; _) P/ }& I# j& R
& t" V7 D5 [) Q5 K) J. z; C$ n9 W        switch(nDrive / 2)
- C; ~) y: L$ [: u1 r/ n0 x/ G/ G        {3 T6 d- j4 j+ h2 X% B2 t* r
           case 0: dwBaseAddress = 0x01F0; break;4 r2 i& A: M4 p7 I
           case 1: dwBaseAddress = 0x0170; break;% R6 v; n. z" }0 Z1 Y
           case 2: dwBaseAddress = 0x01E8; break;0 I  e( D( A" P
           case 3: dwBaseAddress = 0x0168; break;
" X# ^' l0 X- Y        }
( i7 n  m7 g  j+ n+ f5 k6 s1 r4 ~- n+ A% {  |) W% T
       btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);) P: _! H9 F! z; b( v# }) H

, j4 w% ]8 T5 F/ W1 n. f, [        // 进入Ring0
  u9 d- q7 y3 A        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,6 h3 s  v# b, R  F
               bIsIDEExist, IsDiskExist, wOutData);' y9 k( A7 N; {
   }# [7 c( m; r* O0 s# Z% R

, Y+ W1 T' D4 e2 w' F! a    // 开始读取
2 Z# c: z( k- `& V3 S. \    for(int nDrive = 0; nDrive < 8; nDrive++)$ o8 l7 n* U! j' J: r$ i
   {# l: k5 u% f: {8 ~4 k- D
       WORD dwBaseAddress;& B' x8 e0 n# u" K/ }6 M* ~3 ?3 H# [
       BYTE btMasterSlave;         // Master Or Slave* Z* p! ]8 l% `+ r3 {. }
       bool bIsIDEExist;8 T. k# y" d) ]. c
       bool bIsDiskExist;
2 R% [2 j  F- `: g( r& A        switch(nDrive / 2)% T6 A& ?- Z1 A! A
       {  d( c; }% w. d" D
           case 0: dwBaseAddress = 0x01F0; break;
3 c* @) Q6 r- ^5 z+ t3 r. s            case 1: dwBaseAddress = 0x0170; break;! ?  V7 ~. C* L1 N
           case 2: dwBaseAddress = 0x01E8; break;
% ?' k, T1 N" X& o  F/ t; Z8 k* k: Z            case 3: dwBaseAddress = 0x0168; break;
5 C& O4 @9 o* U6 P. g) e4 x( o/ e        }2 }. q& ^+ T( O0 q
. H; W& Z/ n) z- w' _# T" g; [
       btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);. {/ D9 T0 U4 R' `

0 x. d$ Y/ C" b3 O  T! a        // 进入Ring03 F6 g6 k: B( G* V) Y: E
       bIsIDEExist  = false;
9 R  W* r0 R: `$ Y! f        bIsDiskExist = false;/ d9 `4 h+ h% g! ?
       ZeroMemory(wOutData, sizeof(wOutData));
. C, |9 s3 n) I3 f8 d0 c. s; ], [3 L1 ^3 q4 g' T
       ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,1 G9 D3 e' E# ]! P0 N
               bIsIDEExist, bIsDiskExist, wOutData);
  f& n& _8 ?9 X7 j; I5 V  I
% n9 q. C5 Y( g3 n0 d        if(bIsIDEExist && bIsDiskExist)
' ?" M, C+ V1 [$ N% E' r5 ]: |        {
/ O0 a2 {- ?1 W  I            DWORD dwDiskData[256];1 `3 x) T- A" V. ~. N! g
           char  szSerialNumber[21];
6 G; P  Z3 ~3 G* e8 p" }            char  szModelNumber[41];
- h+ J% v& f! P* X+ x5 f. B' v0 s) ~% R
           for(int k=0; k < 256; k++)7 b: x% P  z  f8 u
               dwDiskData[k] = wOutData[k];: h# Y4 @2 R3 m, N, V' Y& d9 [
  B* P1 D' w2 ?6 h, y5 U
           // 取系列号. C  y; D# a% j
           ZeroMemory(szSerialNumber, sizeof(szSerialNumber));% P7 N7 z* O4 w% j3 z
           strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
% h$ M7 }" C; f, n5 e& y) j2 `, z8 \8 X: Y$ F1 t2 Y; e+ r' A5 M
           // 取模型号3 q2 }3 P, r1 L3 r) M
           ZeroMemory(szModelNumber, sizeof(szModelNumber));
. T* c7 ]) l5 S! y- O            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
  h2 R/ _3 A* M+ \+ v& S% Z% j4 K) |! h# y/ r3 Y" }$ q: u
           pSerList->Add(szSerialNumber);- T* Y+ H& h9 x) m/ P  r
           pModeList->Add(szModelNumber);
& K/ f/ q" k+ }( L  N0 D        }
+ X8 l& w, f1 j% S" ~. x    }
' w- i9 R! U/ n6 A# D    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
/ u* p: K4 y! d7 ]: j4 f& ]/ K}' g+ c1 D: ]6 x2 X
//---------------------------------------------------------------------------& k4 z: a6 ]6 U3 i# `4 A( i9 E
// ReadPhysicalDriveOnW9X_Ring0()
7 \0 a- H  O8 l//2 W# V' r, }6 [( G) u( w
// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
  Y  z; F  h5 G, l/ }5 r2 g// btMasterSlave = Master(0xA0) Or Slave(0xB0)# s  ]) w+ L& P
//---------------------------------------------------------------------------
5 A2 d7 O4 d% n; J( B- O2 ovoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,0 P! j7 L& B) b
       BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
- \6 F2 E0 r/ O  `" x{
1 @7 f+ I% m; P# z    BYTE  btIDTR1[6];
1 i5 P, t6 ^0 Z- Y    DWORD dwOldExceptionHook;
4 G- _3 |' N& I% B3 f; K; d    const int nHookExceptionNo = 5;
1 T: \: Y) I( Z* |. k& |# n  h* y: O' Q
   BYTE  btIsIDEExist = 0;! g2 u, }0 v, l, p% l- N9 ]" f0 p0 E
   BYTE  btIsDiskExist = 0;
5 x& V; e  r/ J$ s9 M/ v8 }6 S    WORD  wOutDataBuf[256];
1 V4 ^% s( f  q2 L) U! w3 Z' }' {7 G5 }0 E7 v& ?
   BYTE  btIsFirst = (BYTE)bIsFirst;7 L, g1 U; K1 n& {; D

+ D7 R0 [( ]+ q- l! J    const BYTE btBit00 = 0x01;
/ ?+ J- X, r$ d; T0 s! z( c0 [    // const BYTE btBit02 = 0x04;
) S; B- ~: l- {) Y    const BYTE btBit06 = 0x40;
  N8 W: A" D( g    const BYTE btBit07 = 0x80;7 h) W% `' ^  v
   // const BYTE btERR  = btBit00;% D2 Q# X" B  d5 d: m$ S$ w2 V
   const BYTE btBusy = btBit07;
) x; S' G6 t7 l    const BYTE btAtaCmd   = 0xEC;
/ [9 }: Z# {" R5 M/ k    const BYTE btAtapiCmd = 0xA1;
7 Y8 R' r# H, r: g
8 C4 u' x% u: [2 W5 R    __asm
. ?. b$ [) m* }! i( |    {+ S6 b% L$ Z# n, c9 E
       // 必须先执行这条语句
1 n2 c. R" k0 k3 S        JMP EnterRing0
; H2 \( \! R' m; v
% R0 F$ }+ {8 t/ ?0 A+ D        // 定义过程: A$ q8 x7 j) p; w% h  z
       // 等待IDE设备直到其不为忙为止
: d, G' e! _1 M3 ]        WaitWhileBusy proc0 k  G4 [# ^9 _
. G! T0 Q2 p4 Z3 @" s
       MOV  EBX, 100000% r) \8 G, K4 h! W9 D$ S3 h3 _" f7 u
       MOV  DX, dwBaseAddress; @1 C& ^3 Q; U& s: t
       ADD  DX, 7
9 j5 u! A' Q! }! T( U, [
  G: [+ i6 H( P) c: L; p* Q        LoopWhileBusy:% ]9 A$ Q" H* z. k

1 \8 W% l8 H$ u$ Y+ h        DEC  EBX
: m7 z* j( z' S: {( O        CMP  EBX, 0
, ]' @; p. A' ]        JZ   Timeout
/ n& R8 V# a' R1 c) \        in   AL, DX
1 h# i% i6 k6 x6 i) b; q+ z  c2 {        TEST AL, btBusy
; g  b' {% u2 |& t& n8 z8 ~        JNZ  LoopWhileBusy
4 q$ K0 a1 S1 T- ]        JMP  DriveReady- c0 q4 P5 S& z  n3 _! Q9 R" J
6 N  K) k1 `& T
       // 超时,直接退出
6 k8 d8 U5 a% y, j+ \* F        Timeout:3 K% V* ]7 }5 g2 n
       JMP  LeaveRing0% [* K. I: c- ?" w: a& m
       DriveReady:7 E  G- p; l2 @* f" G
       RET
: q: M/ G# P  ^2 [( ]; b        ENDP   // End of WaitWhileBusy Procedure
6 R) \" i; d/ f7 K% E( Q+ X% ~0 S: |. r
       // 设置主盘和从盘标志
& g# I( R3 R: M8 d- S        SelectDevice proc
1 [0 b0 H3 r/ `$ }& m# P1 n6 m7 C2 T/ ^' O$ o$ e
       MOV  DX, dwBaseAddress2 |. Z, v3 Y7 v, L, l! b" J
       ADD  DX, 6
0 V$ z; C$ _5 ?+ I3 ?        MOV  AL, btMasterSlave5 l/ p9 N# z- T6 Q2 ^; I

  F6 y4 S7 Z- U: v& ?        out  DX, AL& P2 H* }  i% `2 c
       RET5 p0 D0 [: H) @- q9 B; _

" u7 I  i# G: y* X4 M. H        ENDP  // End of SelectDevice Procedure
7 d! {5 f: C1 L9 D* X" ?1 t( |: k9 y1 K0 E0 z& l
       // 向IDE设备发送存取指令: G  Z0 L, \8 p9 V: o( ]# X
       SendCmd proc
) d% l) e( `  l6 A1 [' F1 n. ^+ I1 ^7 q4 K2 A7 N4 D* j$ F
       MOV DX, dwBaseAddress" s2 a: q) g: n6 ?+ t
       ADD DX, 7
3 `* B3 y* G- ~( P3 V! V( P        MOV AL, BL // BL是主从盘标识,在过程外设置
% ?& M6 {  c" Q- h        out DX, AL
# q+ j5 _+ T; M1 J        RET
# R( p, Z. @# s/ Q! I; m6 Z/ T        ENDP  // End of SendCmd Procedure- G6 J9 O  H" y

! q; \# |) J/ u+ \- s        // Ring0代码
0 r3 [& u2 z& ^6 `2 P. B        Ring0Proc:
1 p( ?4 ^6 m  U, U# K        PUSHAD
7 u, h1 P" N4 m% `2 i        // 查询IDE设备是否存在
9 z' y0 j- W3 ~" h" U* o        MOV DX, dwBaseAddress
* t- ^% X: G, |8 p% v: O        ADD DX, 7* X. B7 [: r& [9 i* F
       in  AL,DX
7 c9 N! C" F- z$ G0 ?+ e& l- j; g  o1 _$ W. s9 D$ ~: b% s
       // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回' t, d. K( B8 P& V
       CMP AL,0xFF8 Y- V; m0 d0 |% N0 K
       JZ  LeaveRing03 M# u* p) l- m! @! n
       CMP AL, 0x7F
3 A# k5 V/ g( o. E" U$ u: N- k9 M        JZ  LeaveRing0
( |& D( Q* N5 [; O! ^/ `+ x! Q" i6 a/ E9 S( E# ?' B# f
       // 设置IDE设备存在标志
: K8 L3 \3 z, U1 ^        MOV btIsIDEExist, 1
' A  k% }' _7 X
& b# i+ h# l% _% w6 u9 J6 A        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)/ V/ D$ x, U- \
       CALL WaitWhileBusy
# m) L% {% q+ Z5 Z0 Y, V        CALL SelectDevice
& w* j% g  x' z# T
4 O# Z) [0 @% U( K4 g; E4 o" f0 \7 }        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏; V6 l/ d0 g. S- F, o7 T( N* q
       CMP  btIsFirst, 1  D& r% A. T3 j. I  m5 [+ t5 u
       JZ   LeaveRing0  W# g- L( h, W3 n8 x
3 v9 N3 K3 I. z/ Z" Q9 g- Z$ g
       // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
. D' M0 E; U6 v2 f7 q9 k6 \. K        CALL WaitWhileBusy$ b' s# C2 k- }. F
0 \2 O) J/ V& ~" b' e
       // AL的值等于cBit06时,不存在驱动器,直接返回
) S4 M7 Q3 t  _        TEST AL, btBit06
0 U. v$ v8 h+ b        JZ   LeaveRing0
" Y7 V/ s# ?1 l+ c) a6 L: ~
7 z! E5 t* Z0 l2 c1 I& L6 ?4 X) d        // 设置驱动器存在标志: h2 f9 R# [+ O, C5 z& C- I
       MOV  btIsDiskExist, 12 b$ ]% i, f! V; A! Z  \2 i& \
5 g/ v, {  n3 K: V- ]. E2 m
       // 发送存取端口命令
5 L9 a, I0 {* W, z9 f        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,* I& ?+ @" s* F% L
       // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
: w- E' C) C, K6 C2 b1 @        CALL WaitWhileBusy4 G. X( u# u5 ?' |' ?4 X9 c2 }
       CALL SelectDevice    // 设置主从盘标识) t! h3 N3 h8 |/ u7 `. I; B6 v* W
       MOV  BL, btAtaCmd      // 发送读取命令
7 _( B8 G' n: q  a5 l; v. C        CALL SendCmd
. R9 n: n& E& n7 E& d. g3 C" O0 v        CALL WaitWhileBusy
  ^* Z1 K  K, R! k, z$ Y$ R( x9 S! h3 w5 l/ L
       // 检查是否出错
- y/ E7 W5 D! {  p        MOV  DX, dwBaseAddress
9 y2 E% i7 v4 |4 v6 C        ADD  DX, 7; x. E+ r# w9 k$ K3 }% {

- N! P( T% p7 v; {/ |- q        in   AL, DX3 i) b; \" p) J9 F' b4 n& Q% b+ i
" h1 U) `" H. a: p) x
       TEST AL, btBit00, ]/ i6 {; n( y. p
       JZ   RetrieveInfo   // 没有错误时则读数据% N' {' D' I4 i( \  u: n& Y* ?0 M; _

. q" `" J! U4 B$ ?  S6 X, H) T+ J        // 如果出错,则进一步尝试使用ATAPI设备命令' ^; }# j  a3 x8 v# y! j; H
       CALL WaitWhileBusy
- @! T( K! y+ Z. b% \        CALL SelectDevice
; L" I8 D. g  J" ^+ M        MOV  BL, btAtapiCmd
- l8 U/ J; _" G' {9 o! A# x' a7 L        CALL SendCmd3 h6 {4 C/ ~4 m. m
       CALL WaitWhileBusy5 |) K: c1 Q9 P" P, K/ x5 C/ M* z9 [
; {6 u3 \) w' n* z
       // 检查是否还出错
% F: B8 a& v( c4 M) ^! d- k0 U* _9 p        MOV  DX, dwBaseAddress2 i2 T( z% [2 Y+ a( |! _/ }
       ADD  DX, 7
2 T' ^# R9 u2 H3 S5 u2 P( B1 ^        in   AL, DX
  u0 V3 ~% c# u4 l$ d# G! u! U        TEST AL, btBit00( f9 S; `3 [% T) ^
       JZ   RetrieveInfo   // 没有错误时则读数据
3 L$ m: U6 N+ i& j) W2 G! b        JMP  LeaveRing0     // 如果还是出错,直接返回
9 x  g$ I; Y4 U7 ?# {7 U( r5 b, e. V1 w- f7 U
       // 读取数据7 c, w- {/ o6 ]9 x- \
       RetrieveInfo:- Z- `; X4 Q- g+ ]$ M

2 ]' F, J6 U: F0 j: z" G( [        LEA  EDI, wOutDataBuf
! [* x( A+ x9 J! x, y( G" c        MOV  ECX, 256
/ H1 e. Q2 e% ]; @- Y        MOV  DX, dwBaseAddress  C, ~' P8 w- c+ L/ ?7 ]( X1 _
       CLD
% r2 x1 Z: P; t1 r4 D- @1 ~$ m- Y- Y6 Y1 K& c) k
       REP  INSW
) E1 R/ |) d9 A/ D& J1 u6 S4 \. C" m+ E5 Q/ R- M
       // 退出Ring0代码4 M' }; R  k, A- f
       LeaveRing0:- `. w! M8 V4 Q

+ \$ j7 d# X7 r# D6 e1 s6 v0 G7 M% q        POPAD
) O2 W. X) f4 d/ L+ R: w        IRETD
2 \; g3 V$ h( l+ [0 w$ }+ f: e" A" ?( `$ A+ Y$ z. K" Q" V
       // 激活Ring0代码( x3 e* J1 T+ ]% _9 b6 Z
       EnterRing0:4 i& G8 U& [  ?

5 t( F* d+ a! c6 B  H  ~% S% \        // 修改中断门
8 l# P% Z# ?$ z        SIDT FWORD PTR btIDTR14 J. T0 t& I& e
       MOV EAX, DWORD PTR btIDTR1 + 02h6 c2 D) D0 S3 c2 U# E1 ]4 e
       ADD EAX, nHookExceptionNo * 08h + 04h
% @1 Z) |6 N* _" ^6 a7 L9 @' B4 |        CLI, s' y; S4 q* @& T# q4 F, {

3 F% z2 f6 V5 n, e; Y1 p        // 保存原异常处理例程入口
5 K. A" Q' N: j' ?8 _$ N        MOV ECX, DWORD PTR [EAX]0 a: ?& I" f0 Y+ @' Y- c& I6 f
       MOV CX, WORD PTR [EAX-04h]
! S9 K! e; P, A- ?$ E% V        MOV dwOldExceptionHook, ECX7 x- W& t8 P/ x

0 a: B0 H+ |$ t, ]4 D        // 指定新入口
" m/ l1 u6 y7 N8 {! _, _$ y        LEA EBX, Ring0Proc
6 `/ L9 }1 h6 H. x; x        MOV WORD PTR [EAX-04h],BX- I/ J- V& U# q+ [) j
       SHR EBX, 10h
  {# K/ f1 n1 v        MOV WORD PTR[EAX+02h], BX! C, n, ]% k( r. }

5 i+ H* ~+ D. x) g+ X        // 激活Ring0代码
3 L$ v4 Y8 u4 u, ^1 A4 v        INT nHookExceptionNo2 J6 P, n4 F& C

7 `1 f0 g9 m) v9 @* m2 i- I        // 复原入口. A' ~, W) j9 Z/ x) Z$ u
       MOV ECX,dwOldExceptionHook  l: ^& ^6 |" Z1 t
       MOV WORD PTR[EAX-04h], CX
: @3 N3 f! |- m: n2 x/ b        SHR ECX,10h5 [8 G% I+ s' |! U. Y% a8 k. j6 W
       MOV WORD PTR[EAX+02h], CX
* o' F& ]( J+ g0 ^3 M' D        STI2 a0 [9 ?( m, H4 \5 [, C9 r& ~9 }
   }% x# N& G- R. y2 X
   if(!bIsFirst)
3 {: H: G1 }9 [1 i1 Z7 e" L    {6 a* P5 R0 e; d( C% m8 a) G, F
       bIsIDEExist  = (bool)btIsIDEExist;
& m4 i1 k9 @1 [: u# I        bIsDiskExist = (bool)btIsDiskExist;
8 D& f8 k( x+ e9 Y2 O        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
. N0 J6 Z/ p& O4 e1 E  z    }: V- m7 N' K' S$ k
}
+ b& U. y( t9 X; b5 A: Q//---------------------------------------------------------------------------9 a. [/ F: ?/ ]
// 调用方法:
! Q( L3 j% O% pvoid __fastcall TForm1::Button1Click(TObject *Sender)1 I: P4 J1 ~' v- ]! b3 ~
{
9 {8 I! b" p6 S! J    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);# R3 a! g5 l$ l& f* R
}
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

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

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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