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

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

[复制链接]
发表于 2005-5-30 19:22:36 | 显示全部楼层 |阅读模式
  #include <WinIOCtl.h>7 T/ L7 [! R3 X) q4 p7 A5 G% J3 i
#include <stdio.h>
; z$ T' F% I( q5 K$ j! p
, k, {: z, \2 j# J; j4 G9 m1 @#pragma inline
% Z/ A$ l0 [( \' q+ ?) H//---------------------------------------------------------------------------
, m. E: {1 f7 h$ Q1 D- ~# k// IDE NT/2000/XP专用变量
, _3 c2 ]6 |+ P0 d#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
: U4 l) S) _3 F# p% U  g0 r#define DFP_GET_VERSION         SMART_GET_VERSION+ W5 h/ q! C- ]( ]9 q4 h  E9 l. B2 b
#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND9 d1 h; d) {8 G; w1 x) v
#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
+ \" n6 A5 h% @4 O
# [$ ?+ S- ?- s7 Fconst WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令7 T+ B4 B$ @3 P  S6 Z7 n
const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
7 h7 z7 N: v9 ^! L! @
: c5 Q5 j4 a' G* |; s* vconst int MAX_IDE_DRIVES = 4;
3 B: i8 G1 I& F7 w# n. \' N+ S6 }- W6 ^1 ]. D# w% P
// SCSI专用变量
& [; ?" b; u5 S# I7 t' sconst DWORD FILE_DEVICE_SCSI             = 0x0000001B;) r9 o! F( _9 D  S2 n
const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);% X( x( V- r, a0 d
const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
  o, N7 n3 {% z8 X" T5 Q) Fconst DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;7 C0 M; _. k; a/ }! @

" L3 n) s4 x% i. Xtypedef struct _SRB_IO_CONTROL- ]( ?9 z+ r5 l$ Q1 O
{, c- S7 ?9 Y! L3 C
   ULONG HeaderLength;
; g3 q8 e. V4 l' R    UCHAR Signature[8];
4 N5 \  K& K4 j1 X! S    ULONG Timeout;' _8 ]# K/ E8 b! Q7 O4 k
   ULONG ControlCode;5 J" q0 `) V+ z4 [
   ULONG ReturnCode;5 w* `$ ^9 J9 L* U, C
   ULONG Length;* r; l2 V4 }6 B( K5 ?5 N! `
}SRB_IO_CONTROL, *PSRB_IO_CONTROL;
: J& N1 x! }8 u9 G5 m
* C* p8 m. a' k// 读取的主函数5 Y/ h* \5 j7 G, X4 S
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
0 Z$ a" ^# j% J& t9 n9 q) @2 b" O( z5 R- W- ^: D: V1 B, s# y
// 辅助函数
1 Y5 `! l" X3 O4 N& e) Rchar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);% C7 o0 _2 r! y  h1 q
// NT/2000/XP函数2 G. ^' |# m1 H
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
  C4 l% [8 p, x! nbool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
) I4 [" G% `, {7 `) Y        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
( P3 V. f$ I; Z, u! I3 @: o        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
  w* T+ Y( b( k7 l" Q// Windows 9X函数
# w. K/ o, I6 n/ G0 i: |/ _1 U: `2 Fvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);3 c9 _3 D6 `- y7 y" z! H7 U
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,' w, x* J9 i: I
       BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);6 f9 o4 S, i& C: l. ]3 n; O$ {1 P3 ]$ s3 @
9 }. B0 n  O4 u
// SCSI读取函数(for NT/2000/XP)
+ a- ~  E, ?6 n$ f: M$ yString __fastcall ReadIDEDriveAsScsiDriveOnNT();
" {7 w8 R/ T7 {1 Y//---------------------------------------------------------------------------
8 {5 d( T- M2 U$ N" j" k// ReadPhysicalDrive
$ g: r7 i  r. Y, F: O" s4 `void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
3 u$ J  i" q4 u+ B) c4 x{0 b# }/ V( [: O
   switch(Win32Platform); @. X% ]6 x( N; B
   {
% M' N: [- r) j4 ]0 b& W+ q; y; W/ Q        case VER_PLATFORM_WIN32_WINDOWS:9 a4 G, I# b% o( d: W! Y, P3 C& i! Q
           ReadPhysicalDriveOnW9X(pSerList, pModeList);
* q9 z8 A  _$ O            break;
: {* n8 f# H$ i5 V        case VER_PLATFORM_WIN32_NT:5 Z, n: U+ P1 d/ X6 C! c  `
           ReadPhysicalDriveOnNT(pSerList, pModeList);" u* R" W9 l7 T. z$ d
           break;
0 d' v" p7 `2 m. V. n& q1 o        default:* g1 |2 \& \% H- f+ }* }; u( k1 `
           break;8 L& l+ X* i) G: j& q8 s5 C; w, x' T
   }  O/ z+ u4 E& H) n; }
}" F  X4 u3 a" N7 M+ C
//---------------------------------------------------------------------------
2 y1 \8 y2 F2 v& j// ConvertToString
" w5 r7 l4 q0 H" Z% i7 s& uchar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)1 f& c* X0 b- _
{7 F( }  K$ E; y3 r/ G9 H. e, y. S# @
   static char szResBuf[1024];0 U& N) R, r1 i
   int nIndex = 0;
- p8 x0 e2 h, S& G2 X    int nPosition = 0;
- m2 J* _0 S  W3 ~1 l3 e9 M
; J: w3 q7 L. e1 ]- G    // Each integer has two characters stored in it backwards
& `& F& s- @* D% E/ v( M    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
. O" l! N# Z* D1 L    {' }; U  m( T  n& _  I: Q
       // Get high BYTE for 1st character
8 S! ~1 [+ r2 H0 [  l        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
; m5 _( ?1 _% _9 s+ ]6 ?" T        nPosition++;
" x& p' Z" c' ]" o) U" d" {
2 C; o! ^3 z; C% r. v        // Get low BYTE for 2nd character, \9 ?5 o5 @4 _/ e. l+ f
       szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
4 |( r) e$ d; d0 c! B9 Q3 O        nPosition++;
, C+ @; t! ~, `7 o) V    }
# k& @+ ~% U9 \" Z: j
- v2 [# i9 v* L0 v' Z+ O    // End the string( N* B) b2 P/ p
   szResBuf[nPosition] = '\0';
- Y7 q2 ^9 j; o6 n
( J" K% M% ^. u2 i5 j/ O7 T    // Cut off the trailing blanks
1 [7 g8 \8 p% n) ~$ n    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
- x% |( C& y" \        szResBuf[nIndex] = '\0';
/ q% Z& X! |- x0 j; n) k* O
- W" Z, {! \) a1 Z% z- c' [    return szResBuf;0 M2 J: M0 l+ Q$ M
}
9 v8 ?4 D/ G" W  ]+ D//---------------------------------------------------------------------------4 V$ I2 R2 U$ ]
// Winndows NT4/2000/XP 代码. y  h% Y+ @9 \$ u: |' s
//---------------------------------------------------------------------------! x. D# B0 @2 d' Q" C: s! q1 M
// ReadPhysicalDriveOnNT
0 \& b% R1 }: n- y/ m  ^2 Qvoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)/ L, m5 p+ F9 J% B' e+ V
{
  J2 `' M3 w: c, u( y0 R6 r    // 输出参数) n: A4 i( X+ t6 d& X/ L
   BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
# F; _; ^! O. l( s/ l, d* Y! r7 Y, b, i+ K. f3 m+ p
   for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
* i, r1 O. u4 f& G, L  T7 g3 o( Y. u% u    {* X! [0 e+ ?, s3 H! s) j
       HANDLE hPhysicalDriveIOCTL;2 B6 E; k: G0 h( d# X
       char szDriveName[32];
, S/ s& [) T. A8 ~) J3 a$ ^9 g" C: e0 j1 e/ K+ d9 C- u
       sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);4 S' ]8 G. u7 d1 X
       hPhysicalDriveIOCTL = CreateFile(szDriveName,  {6 P7 h/ Q* G4 |* N
                       GENERIC_READ | GENERIC_WRITE,
; r- l* z% J+ l                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
" a+ q8 [+ T4 x+ M) i4 O                        OPEN_EXISTING, 0, NULL);; e0 m2 _# R9 [" o2 \% z

3 v3 n7 A- {4 ]9 W) j1 j) |        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)! K# z# p6 `! C1 ^4 S; j
       {: N6 I* p& h" J' W1 S( ]5 n
           DWORD dwBytesReturned = 0;1 W; Q* U4 E. m: d
           GETVERSIONOUTPARAMS gvopVersionParams;" f  ]3 _' }" C) R
7 K) y0 o: r/ H: W+ ?" c( z# }
           // Get the version, etc of PhysicalDrive IOCTL+ J- S, I/ {6 J  |' Z, Z
           ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));( J9 J! S- k8 b" H
7 }5 p; c( R5 r3 V, r
           if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
6 F1 l# j- A) i& k/ v                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
+ [7 s( [% Y2 U: O) f                    &dwBytesReturned, NULL))
& `5 v' N1 J$ N* u' ?            {
6 |! s/ O/ ?5 p# x# I% a2 _) m& j                continue;& v# }6 W$ W" E) ]: \
           }
0 n6 ?, _1 c6 y) I8 i# O' X: g4 U3 S. t4 P, X8 M4 B
           if(gvopVersionParams.bIDEDeviceMap > 0)
0 |5 [. R# {" [% _/ s$ P5 ~            {
, Z* z/ T4 T0 d& e$ N8 Q                // IDE or ATAPI IDENTIFY cmd; F, \- A% {* c% Y# _
               BYTE btIDCmd = 0;
: [' `' @8 i7 J8 d9 E4 c% A4 x3 W                SENDCMDINPARAMS InParams;
( L! D5 ]9 ?( Y5 Y0 a                // Now, get the ID sector for all IDE devices in the system.' A; h, c. P1 q) w/ r
               // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,/ b+ ]2 c" Q# J. \5 w
               // otherwise use the IDE_ATA_IDENTIFY command; _2 g/ e  c" V& P! z" Z3 W& y
               // 具体所得结果请参考头文件中的说明1 j/ b( c3 }5 i& H! B$ e, `
               btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
/ d. ?- y8 O8 d5 p& w, A- k( q3 G" y8 u                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
) |6 g6 o$ I. J$ o                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
2 Z" i& Q% ^' Z: Z5 L1 k+ E! [                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
. Q; A/ L& C" E, d* v4 e% N+ ^8 m* p
               if(DoIdentify(hPhysicalDriveIOCTL,3 N4 B8 ?& x; E1 d
                    &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
9 J5 Y( Y3 t: }5 o8 A$ ?                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
( e/ |, J! `- o" H& X. E2 B) X8 h                {, h4 a1 m/ B; h. d
                   DWORD dwDiskData[256];
& H' J( W0 T9 u! C. G9 U                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件8 `8 ^$ `5 G+ z$ U' \. }5 A) ]1 N
                   char szSerialNumber[21];3 H1 C& u( B- R
                   char szModelNumber[41];, Z. d! a( o; s, m7 O5 `
' p  U5 z  t' }" }
                   pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
, k; C  D2 r& [4 t4 r                    for(int i=0; i < 256; i++)$ ]: t# Y$ p- H& `! D2 O) O9 t; H
                       dwDiskData = pIDSector;
( N! n$ U+ W; ~, @" i# z" c6 X                    // 取系列号/ q- P& ?1 r: h
                   ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
- h& V7 l! n/ g. z( f* A. s% b$ P0 Z                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));+ Z1 {( }% c# N: [! z4 X. x
  H" M% Z. o! s4 b* o
                   // 取模型号
) q& Z! Z# F! S4 I2 P2 s8 w/ h                    ZeroMemory(szModelNumber, sizeof(szModelNumber));; h" x$ S+ n. }2 W% I( @$ P3 E! {( ]
                   strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
# Z9 r/ q4 B5 S! l* g
$ @  s7 u, t2 u                    pSerList->Add(szSerialNumber);2 q3 R7 |4 Q3 a* P7 O
                   pModeList->Add(szModelNumber);
4 P: R3 w; M4 S; u6 W' F7 V                }
8 t/ ]' w4 ^& J( _; _            }
6 ^3 }9 d, ^2 f: w) M2 }5 i7 g" w            CloseHandle (hPhysicalDriveIOCTL);& \) c9 s7 y* I, U4 R' f
       }
7 w  l" T. {/ W" _: s) t    }6 h( K" r5 L! o3 m/ y4 a
}
6 M+ v( @  O. s//---------------------------------------------------------------------------
0 J+ X9 w' r4 a! Y1 W/ ]$ B2 ^// DoIdentify
. Z" a# w7 k5 Q% @bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
/ ]( ?! S& W# O1 L* P  q& h7 e9 u# X              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,7 A9 j/ ?9 Y5 G# e9 b, Z( n
             PDWORD pdwBytesReturned)
9 c, y. B( F. M! e4 m  @  {{6 M8 o! c6 ?- _3 X  Y! u2 @
   // Set up data structures for IDENTIFY command.9 G: V. A8 f/ _( l' R- e& {
   pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
: }* z- v3 @- U% D" ?  E' p    pSCIP->irDriveRegs.bFeaturesReg = 0;; `$ d1 H/ o* L! A. u9 A" k+ O
   pSCIP->irDriveRegs.bSectorCountReg  = 1;
' z1 P" r/ f/ H2 \! {    pSCIP->irDriveRegs.bSectorNumberReg = 1;5 x! J# ]/ k# T' y+ i& ]6 Y  c0 u
   pSCIP->irDriveRegs.bCylLowReg  = 0;! K. C: j; U: m- Q0 i! H
   pSCIP->irDriveRegs.bCylHighReg = 0;* u5 l2 q7 s! R- {- L0 ?
- T! f, g& B  ?7 A) m8 L
   // Compute the drive number.(主盘和从盘所对应的值是不一样的)
3 T* \- E# V) `. c    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;% I, b- i, d3 z: N

* F. b* s; c" u" }+ g    // The command can either be IDE identify or ATAPI identify.
, v9 m% Q( X, i. ^% ^& A1 s: y. D1 _    pSCIP->irDriveRegs.bCommandReg = btIDCmd;5 m/ _  s( B, i
   pSCIP->bDriveNumber = btDriveNum;/ @' ]. l; c" D; d1 D, X4 P, N0 B
   pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
' [2 J9 x' ]" P  M# X; c/ o5 f0 D$ J; i5 M2 U1 z* N
   return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,8 Z- A1 p3 C5 u3 ^
          (LPVOID)pSCIP,' `* t7 j  s+ \
          sizeof(SENDCMDINPARAMS) - 1,
/ m1 ]) b8 q+ {; G- @           (LPVOID)pSCOP,+ D! a# y8 F. W+ P
          sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
4 g, L+ b0 l, o+ S           pdwBytesReturned, NULL);7 d5 O9 y8 C$ a! B
}
, h% I! V! f# E9 f//---------------------------------------------------------------------------
( I  g  v0 I$ L( {0 \+ H, a! C// Windows 95/98/ME 代码' G9 Y  W' w* J
//---------------------------------------------------------------------------
; v# @) G0 x  A+ J8 E// ReadPhysicalDriveOnW9X
4 W0 b5 x& Y1 R+ p% P/ u9 [; Pvoid __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList): g6 L% T+ d( w, F: u- k4 A
{
: l" m! ]+ d/ O( Q5 k, h3 e$ K  P    WORD wOutData[256];- ?' H, J" Q( u  {% M8 m
   SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
: Z1 J2 H0 D, A  q8 s5 u" N
7 [9 j. F9 Y! y    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。; ]7 W0 c* ]- _  u  h7 _/ D* j
   // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以& Q. T# k, r$ W$ ^) W7 ?8 W5 G# L
   // 避免蓝屏的出现。(期待高人能指出原因); v1 q0 h- b: d' T- ~
   for(int nDrive = 0; nDrive < 8; nDrive++)
/ z) k+ V! L2 {& I( g6 F2 R+ s" B5 y7 W6 J    {
9 E' D2 s  l  S1 Q# ]( `9 q; P        WORD dwBaseAddress;
' e% R8 Y* w" u# }) B        BYTE btMasterSlave;         // Master Or Slave
' [' ]: _2 j8 D# K0 x5 J        bool bIsIDEExist;  h) L3 b- l3 g8 U# e' \3 {
       bool IsDiskExist;
  ]4 g! E0 A+ @% @- M( v$ x
, J) G. @; u( b3 L, ^. s8 k        switch(nDrive / 2)
+ f& o* d. H( r! W, m        {# {. @* U. R! x3 T; A) O3 i
           case 0: dwBaseAddress = 0x01F0; break;
2 ^5 h. S) }/ A. s            case 1: dwBaseAddress = 0x0170; break;
# Z4 Q* C8 S; M            case 2: dwBaseAddress = 0x01E8; break;
( I1 F; L. u8 o            case 3: dwBaseAddress = 0x0168; break;  V( h1 R8 \9 _, o2 w
       }+ l# [9 q3 [3 q+ I+ {5 G, S
  a* g5 J3 G  ~0 V' \' \' Y
       btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);$ ]+ v* E  I' L6 ?& W1 c9 E1 Z

4 u% C0 J$ e2 Z" ^3 D. B, G        // 进入Ring0
8 x8 ]7 E3 Q& v" U1 ]6 D, {        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,, d( Z( |: G/ t
               bIsIDEExist, IsDiskExist, wOutData);- s  X# L1 H1 t$ P- w5 F
   }5 z5 u$ n# v$ \! Q, R

! ?: m2 _% t+ x    // 开始读取% m: P9 N; B4 x/ U3 O
   for(int nDrive = 0; nDrive < 8; nDrive++)
& j4 e. V( Z4 S, x" r* v! L    {- I- V3 [# l9 O( a4 ~- X6 m
       WORD dwBaseAddress;
  e* |1 b2 k- X+ s: W        BYTE btMasterSlave;         // Master Or Slave
, ^  H& U( w. H        bool bIsIDEExist;7 y, n/ {& Y" n) f7 z, i% Y
       bool bIsDiskExist;9 q6 \8 u1 O# O1 K0 S; z: e
       switch(nDrive / 2)# h3 A# e! h* J2 J
       {
8 J3 G# E$ S! Y            case 0: dwBaseAddress = 0x01F0; break;
, B. ^7 }+ D$ x: @+ ~6 @; g            case 1: dwBaseAddress = 0x0170; break;
0 _& Q- W3 g/ W5 R1 m# k! w6 \            case 2: dwBaseAddress = 0x01E8; break;6 P3 w# `2 I+ [3 Z
           case 3: dwBaseAddress = 0x0168; break;
1 F/ D7 r6 M6 o" E+ O1 n: g        }
2 |4 [  I2 S. L* J, _+ p8 L
# m( Y: e% T4 y& n6 X1 s9 \+ U        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);- n0 S4 N. y" z( `5 z
  n, S, t5 H, [+ `
       // 进入Ring0
" w/ P/ V9 j; R0 R        bIsIDEExist  = false;  P( K1 t1 f' x: R5 x
       bIsDiskExist = false;
' a6 z$ W4 g" Q. H1 p        ZeroMemory(wOutData, sizeof(wOutData));5 I4 e6 K! h  h+ G* V4 S5 g5 J

" l% P" E$ P2 F        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,# V, @7 Z( r7 b, H/ l- i* ?& n# l# @
               bIsIDEExist, bIsDiskExist, wOutData);( j) S1 D5 l7 n. I8 z# M/ ]

6 H* C% ?# [" K; P$ y* F, @        if(bIsIDEExist && bIsDiskExist)
3 [( A4 z$ O1 h  n  V" r5 d5 g/ t        {
5 A, I/ I5 Q, K9 s- \* X7 X; H            DWORD dwDiskData[256];$ x$ t' e# f( Z5 K, u
           char  szSerialNumber[21];
" ]# p$ O$ y' v- @7 H            char  szModelNumber[41];8 C( {) v) B; `% K! z4 V

9 G. M2 Z" I. J/ o6 K            for(int k=0; k < 256; k++)" l8 w& R( q7 h/ d3 R. K1 n
               dwDiskData[k] = wOutData[k];7 `6 p$ o/ R0 b7 H, v2 n

& E" L$ F+ v: \. @4 ]- `            // 取系列号
4 K$ L* W) F8 y3 d            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));. b+ Z) m8 U  K5 Q
           strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
, E" s* @8 M& I6 l% b- Q* c
. O7 k- H/ _" m. p            // 取模型号& T( ^1 S; z$ Y0 [& [7 g
           ZeroMemory(szModelNumber, sizeof(szModelNumber));, G) q" G+ q& ]
           strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));3 ?1 I5 _; o/ c; y$ C) Z
$ W: C* O7 n- F
           pSerList->Add(szSerialNumber);0 a$ ?4 j& _3 j( m7 X1 F
           pModeList->Add(szModelNumber);/ b  d& L- x9 T, p% p
       }
* {( ], K$ f. O    }# E7 c, ?. Q2 w5 X
   SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
+ z- t( j8 w- b; B3 t}* J( A! D# ^- M( Z
//---------------------------------------------------------------------------8 C  c6 G. F' x
// ReadPhysicalDriveOnW9X_Ring0()) x7 n+ t2 F5 I" m0 Z
//+ `8 \5 ^/ B) U) W
// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
( }6 N5 `) o! }// btMasterSlave = Master(0xA0) Or Slave(0xB0)
0 E) Z; x- W( i$ k6 j, a//---------------------------------------------------------------------------
1 w7 s& ]( O" N+ S4 K& svoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
5 Z: n7 s: h1 [/ ^% i: \0 K. o        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData); H, B" E) \6 z; D2 K2 b, i
{
3 [, c0 m* y. z$ j, `    BYTE  btIDTR1[6];/ @2 g# m9 [0 Y8 A
   DWORD dwOldExceptionHook;
' ?( W/ o4 b/ T3 A/ ?    const int nHookExceptionNo = 5;
' G4 c# C& y4 q7 e0 U
' {$ N* ~- q; n$ S& q7 |9 C    BYTE  btIsIDEExist = 0;, z3 u- ^# a! c1 [/ V6 A
   BYTE  btIsDiskExist = 0;
" v  f* z* E- ^. `7 [    WORD  wOutDataBuf[256];
+ W: ^2 h0 \( R& }6 D* I- ?
+ d, D* O2 \% N    BYTE  btIsFirst = (BYTE)bIsFirst;5 t* y+ i8 K1 s: [
+ [! p  ?) `* C2 a  R( X
   const BYTE btBit00 = 0x01;
: K1 P% V3 ]/ R! n; A0 I9 l" \    // const BYTE btBit02 = 0x04;
5 i9 X1 n- W% r+ }    const BYTE btBit06 = 0x40;
* C" C3 [' r2 k- C8 y% Y    const BYTE btBit07 = 0x80;
! }" \" {) o+ Y/ s0 f/ m7 [$ S    // const BYTE btERR  = btBit00;
! {8 E6 X" R/ `% z    const BYTE btBusy = btBit07;& P8 \: c; j* ~; i
   const BYTE btAtaCmd   = 0xEC;
+ ?! L4 J; J/ t    const BYTE btAtapiCmd = 0xA1;) ~3 `1 \) d! p" a3 }
6 `5 M) I1 m. e+ F$ i& S, S
   __asm
9 B  v9 R5 J, a: E3 d/ q. c    {2 V7 U5 v( T9 ~. v
       // 必须先执行这条语句. ~, I- y( l( k& k' A% v/ H1 ^: s
       JMP EnterRing0( w4 }. ]) B! T! u) \8 _% q5 o& A

( T2 O  u) E" i- m6 `6 V# Z3 z( d        // 定义过程
9 c$ @* j: p. f- V        // 等待IDE设备直到其不为忙为止8 Z" o0 o: G' S5 z+ f& C
       WaitWhileBusy proc+ M8 U  I+ E% ^( X4 h7 `# v# P

( ^1 @! Q6 t7 @        MOV  EBX, 100000
2 ?6 s( @& ?: W2 c        MOV  DX, dwBaseAddress( o5 u' E; w& h+ @8 D0 v
       ADD  DX, 7
6 j# h! ^9 {$ U* u* }" E- R
% e; F. Y* q- w3 Q" H" W+ D        LoopWhileBusy:( H7 [: u- U. z2 k

: _9 r- ?* H1 g$ l, f# m- F        DEC  EBX
. G6 f" y6 \& ^. t" I  y( m        CMP  EBX, 0' T; U* k$ B/ K! e0 M4 ?* e" _
       JZ   Timeout
) e. o' t/ ^3 o  V+ \: z        in   AL, DX3 e  C0 y3 F4 l/ V7 X
       TEST AL, btBusy
- {, M# ^2 z5 x: Z% R        JNZ  LoopWhileBusy
3 |1 m8 b/ R4 M, X; S+ ?# v        JMP  DriveReady9 x  t, ]6 f% r$ S, X& D+ [
9 k  t, o' ]* R: A8 j/ ~
       // 超时,直接退出" U3 S' ~4 r% ], E
       Timeout:
) j9 T0 n- w' s& {0 B: o( A        JMP  LeaveRing08 m0 A4 J) v3 M( O
       DriveReady:4 A" Q& f2 t7 u! C3 o- h2 c0 X6 c
       RET
8 S& z6 V) e. [        ENDP   // End of WaitWhileBusy Procedure
1 @( u( P+ `3 b
! A+ U1 P" M* F1 n, i6 Z        // 设置主盘和从盘标志
! Y+ T" s! z% D& Q6 j        SelectDevice proc. A$ R* l+ X4 Z  f+ X+ R

4 |) i; F+ K9 ^9 Y" D        MOV  DX, dwBaseAddress" F  G& q: ~, g5 ?* F: L$ E
       ADD  DX, 6* {! D5 X& N  q, A6 T
       MOV  AL, btMasterSlave
* F/ L% W3 U4 @7 V; J& T
! C. V- R" {; P        out  DX, AL
4 V: M" Z8 I, J5 k4 O7 D        RET- @0 b2 M; _% T8 c
. W# Y( _+ g  o3 Y
       ENDP  // End of SelectDevice Procedure- A- C, N# Y  o& Q
* O2 b3 V" O: V1 B+ T
       // 向IDE设备发送存取指令' h+ m3 |$ E5 X: A# G! C) p2 t7 Q2 t9 d
       SendCmd proc9 z; j* `; p% f5 ]0 d
. k# c0 ^; Z3 j" h0 m1 i
       MOV DX, dwBaseAddress0 f$ P0 P( \. H7 d7 T! F! i
       ADD DX, 7* R$ ?' d" P6 W
       MOV AL, BL // BL是主从盘标识,在过程外设置2 e" j! E( h7 b, n5 {$ e' ?
       out DX, AL
7 D0 M$ s5 A- ?9 Y        RET
) @- u) e3 ?' u( `( \        ENDP  // End of SendCmd Procedure6 P" D  e& _9 n7 Z- s" ^3 Z, a
: Z; R$ m, g0 b
       // Ring0代码
6 J7 }* P/ O+ _6 Q8 c* e( Z# X8 [        Ring0Proc:
9 o$ m7 N+ u- }# n4 I        PUSHAD
1 p) S- M) T% o$ ~        // 查询IDE设备是否存在
9 m) C. r$ l! O5 r3 i  k        MOV DX, dwBaseAddress5 w2 A3 r# I  _- F* F2 F
       ADD DX, 78 ]( L2 v' {! }3 H. x7 H
       in  AL,DX/ Y0 ]0 {! U' a: K  o) @- m. p7 l
+ T2 q$ M; R+ C& c
       // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
) j7 |3 w- H0 L6 H        CMP AL,0xFF
6 C0 ?9 s# \, \6 ^        JZ  LeaveRing05 G# {- E5 }: {$ e9 P7 D) f- T/ a
       CMP AL, 0x7F
8 a" F  {/ Y# l1 x4 e& p3 h( O        JZ  LeaveRing0' X# h7 n4 L" \3 s: k! Z& ^

, `; G9 T  e5 F4 u8 q5 u3 [        // 设置IDE设备存在标志# O# r% y2 F  K7 v5 l0 n
       MOV btIsIDEExist, 16 u, Q; o. w" n2 I7 w: `1 @

2 h! r8 D7 P2 J1 {        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)6 t2 I/ i; D6 e& ]8 o
       CALL WaitWhileBusy) A, [* f$ b- U8 Q
       CALL SelectDevice! J" o) j% |1 E. E% Y7 j
3 A9 x' G! C  e+ c) y5 ?8 H
       // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏$ a$ x9 [5 M1 m9 F/ L7 y
       CMP  btIsFirst, 1
/ @+ ]' Q- k/ g3 k/ q0 ^; R        JZ   LeaveRing0
1 ^; r. o( a3 v, H( M' h- {7 y; s4 w  l/ o: f
       // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
9 u( _. f: h4 W3 M) F1 J        CALL WaitWhileBusy0 H6 @2 K% V" m8 k6 n4 f
6 K: N6 {: h2 F& U% j; {
       // AL的值等于cBit06时,不存在驱动器,直接返回
$ ]! h2 I+ F+ F" G        TEST AL, btBit06
6 j+ F6 b) p  T9 u1 K& ^        JZ   LeaveRing0* F0 G& ~' l, }$ p4 J8 B; F: `

; r- v( B. g! V# e* A        // 设置驱动器存在标志
$ Z+ c6 r' W& n        MOV  btIsDiskExist, 1
' X* `( S! n* W5 Y% z* E9 ~; O" w1 a( @- Y9 B7 [- x& V
       // 发送存取端口命令1 x, V" R" j0 J6 W% Y# r5 w
       // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,% T2 ]. z0 _. X* j8 P
       // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令* b1 R: q7 F9 ^9 R& M- W8 [6 m
       CALL WaitWhileBusy
. }$ b3 q& D- {# n% W5 h        CALL SelectDevice    // 设置主从盘标识3 X/ [2 \3 y3 {3 m6 p- O
       MOV  BL, btAtaCmd      // 发送读取命令0 l- {0 I& R8 y% @5 V
       CALL SendCmd3 j1 b4 P5 |# l7 z  l
       CALL WaitWhileBusy
3 ?5 a7 \7 F6 K" o0 P# O1 m0 A0 c' C2 I' {3 v5 d, }
       // 检查是否出错) A) _( D7 S9 Q+ t+ `
       MOV  DX, dwBaseAddress  k- N- x  ~3 z9 o. A" D( z9 o
       ADD  DX, 7
# {3 W, X6 ]1 C* c/ H  }+ s8 `3 c/ F% f6 ]* V2 ]
       in   AL, DX& o6 ]# ^4 G  V6 H) J" p: v

+ }$ u& m. F7 o# R& k5 P$ d        TEST AL, btBit00
6 U; `& J( s2 P: v3 G3 T3 y        JZ   RetrieveInfo   // 没有错误时则读数据/ {8 D) q4 }" l. o/ ]3 A
% X- T3 K+ l& N  ?$ g" ]1 C' j
       // 如果出错,则进一步尝试使用ATAPI设备命令
, I3 r" G$ p. J+ X1 S+ K        CALL WaitWhileBusy
! d  H% Q6 U) K! [8 Z# R5 {        CALL SelectDevice
+ e; k+ `+ G+ Q3 F        MOV  BL, btAtapiCmd
6 ?& \; P2 a" t& Q; w( v* {# s        CALL SendCmd# G( m8 ]7 q3 [8 n# i7 x! q
       CALL WaitWhileBusy$ c8 Z; U' G0 L: l' \- i
2 R0 ^* y' i- a6 P3 Z% T
       // 检查是否还出错
. e# R9 s$ J: W/ }* Q        MOV  DX, dwBaseAddress
% a: W: Z7 d" ^( H( t( b        ADD  DX, 7
; u% ]' G5 ^  ~        in   AL, DX
+ ~" u$ R; u/ x  n+ ]        TEST AL, btBit00
. Q7 y6 z, G0 J9 p! O; R        JZ   RetrieveInfo   // 没有错误时则读数据
. o& H1 R! O8 [) l' c- b0 p; ~: T/ |. u        JMP  LeaveRing0     // 如果还是出错,直接返回
) k7 z0 ^/ n" f. ^  U' y1 U
/ k) G; Y4 q- ~# {' M        // 读取数据
- \/ ]6 C3 i9 C1 Q        RetrieveInfo:9 A1 I) S3 K. M: U

/ H& C9 y3 P* u5 f4 X        LEA  EDI, wOutDataBuf
1 {$ N2 ~% K- s# l        MOV  ECX, 256
* y, U& D8 G4 s        MOV  DX, dwBaseAddress3 _3 X( g% z( j* @" T" w' m
       CLD) \' |' r5 y/ ]+ P* ?2 t

" V5 z4 j" }3 g( d" z1 r# f$ c        REP  INSW
7 S6 S6 Q( |) ]( d7 t! a4 t: W, f/ l# \
       // 退出Ring0代码
" N! `1 l" n% o7 c6 }$ x: L        LeaveRing0:
" i( h1 W* v, Z6 M/ A0 J" D8 ?7 ?9 w1 H# _2 F. ?/ m! |1 I* \
       POPAD: Z" f* Q/ B$ \' E  m9 N# o2 n( U+ @8 q
       IRETD$ \, ^* r2 Q: _3 J' D# r& W9 A

! R  B1 q% |: ^8 S; f3 y. O# s        // 激活Ring0代码% `, D% ~( Q- B- E% c: d+ ~
       EnterRing0:
* F2 L( K# m/ A+ m
& t8 y5 O- [4 J2 s3 R        // 修改中断门8 X; e( t) \( }: ^  G& K
       SIDT FWORD PTR btIDTR1/ e8 O' L1 X! [  C1 {% d
       MOV EAX, DWORD PTR btIDTR1 + 02h' k: I) v. Q; u  S
       ADD EAX, nHookExceptionNo * 08h + 04h
/ J/ O  e. _4 K2 j        CLI% r; a9 S/ p- N/ }, b' r
4 z/ G+ F4 z0 M3 U7 c8 y- ?- @
       // 保存原异常处理例程入口- x( J2 R8 m/ n. ]. Z
       MOV ECX, DWORD PTR [EAX]5 l) p2 X3 l# w1 l3 b% A6 p
       MOV CX, WORD PTR [EAX-04h]
0 K# E1 N7 ?+ C2 [8 [' f; z$ V$ y        MOV dwOldExceptionHook, ECX
' K/ M2 ~) Y8 J; K: _& J, [6 I; v! u6 i
       // 指定新入口
. z4 O& y; U! V( @  L% {- S7 M        LEA EBX, Ring0Proc
1 L5 U) ]5 b) n* D        MOV WORD PTR [EAX-04h],BX4 B: j8 l1 G- }* W
       SHR EBX, 10h
% _. K  V$ a, \) M9 [        MOV WORD PTR[EAX+02h], BX
0 y, k8 X) `  d8 q' O/ b, W( ]6 [2 M1 a* ]/ R5 y1 \  s
       // 激活Ring0代码, H; m9 F' N- _
       INT nHookExceptionNo
" r0 b1 J) X) G3 p: ^& V/ _4 a7 U8 Q4 n4 ]
       // 复原入口
3 z1 |# X8 H# x6 e$ z        MOV ECX,dwOldExceptionHook
7 x6 m' |- S$ j* k        MOV WORD PTR[EAX-04h], CX
, x: P; p# o! S  W1 W        SHR ECX,10h* ]& `. x! Z% a5 v2 o  p9 X: u
       MOV WORD PTR[EAX+02h], CX
( l/ ?& Q2 `+ y/ l7 Y        STI- J$ i, h+ `( b* D, Q2 e8 z
   }7 I: h' _* Q; |/ o4 V' h
   if(!bIsFirst)
' [7 p" f+ j. z- `4 V6 ~2 ~5 f    {) `7 p, l" p/ h$ d- V. \) v5 V
       bIsIDEExist  = (bool)btIsIDEExist;
3 Q9 E  b2 b. [# q( Y        bIsDiskExist = (bool)btIsDiskExist;0 l  b4 s; J/ Y; T
       CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));5 [# |) s0 o" A) r( Y, @
   }- k( F- j: D5 B  W* t
}
5 m- `* q6 W8 @- }' a$ N//---------------------------------------------------------------------------
, k5 e& ]" f7 G: W// 调用方法:
% k4 `0 j5 m- t; ^) J. ?  |- ^+ u3 `- pvoid __fastcall TForm1::Button1Click(TObject *Sender)7 o8 I( y1 c7 F6 H
{& d' d, {  {, d8 i% Z
   ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
$ `; R  o4 v# u* |}
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2025-6-19 08:33 , Processed in 0.017566 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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