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

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

[复制链接]
发表于 2005-5-30 19:22:36 | 显示全部楼层 |阅读模式
  #include <WinIOCtl.h>: `$ p% t4 J/ n( A. {- V
#include <stdio.h>! ]# R; V" R* }0 X
+ q, w! d5 E6 V
#pragma inline
1 v8 o# M( k4 ~! @//---------------------------------------------------------------------------
% e$ ]6 L  a7 p: m" Z, a, C// IDE NT/2000/XP专用变量, v8 e7 U7 F+ \3 d+ Y
#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS* P. T# c4 s. Y5 k8 U2 ~- L5 i
#define DFP_GET_VERSION         SMART_GET_VERSION
  M& u8 ^: n6 |0 c( z' b! p#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND7 Z/ l5 R, D" z1 q4 E
#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA! L$ j! {+ D  g* d; H) V6 |

' F$ e+ z( k5 l. d' {8 b% yconst WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令! g: l! {4 V1 H6 N
const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令) k/ D5 V) N, k0 x9 @4 Z: b% q* R
7 t% W9 X* J6 f4 s7 ?( S/ ?: j
const int MAX_IDE_DRIVES = 4;8 i* Y0 w4 ?/ |  R& Q

0 ?) C+ ^* q8 g: n" [4 [; x% h// SCSI专用变量
. p5 U' O/ _$ U! n$ Bconst DWORD FILE_DEVICE_SCSI             = 0x0000001B;, ?" }. m: I# {9 |/ s
const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
3 e- k6 {; T  Q% Y7 Jconst DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition* _5 s! m7 Y3 ]& b; {
const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
* T1 U* s, e, q- b& G  {& M& k% }! ^0 X' g6 }! w
typedef struct _SRB_IO_CONTROL" V1 k0 G+ J  D& x& c" V
{
0 h# U3 q" U- v' l7 l3 [    ULONG HeaderLength;" G$ ^, }4 w1 D
   UCHAR Signature[8];
! j. A, b5 M1 A    ULONG Timeout;3 s$ Z7 O- K. r/ g3 N; j( w5 A
   ULONG ControlCode;
' s% ~- ?# _; U3 U3 v7 z7 Q    ULONG ReturnCode;% W4 ^2 z; F  |& X2 s: T5 n9 ~
   ULONG Length;
  e9 B8 a$ }3 Q$ U2 [9 @/ J5 N. s}SRB_IO_CONTROL, *PSRB_IO_CONTROL;
- [, b+ V8 ^! J$ U% L/ B: M* u3 u) \- \" `7 _. L* @
// 读取的主函数
4 \" m: ~0 c5 R/ K8 Yvoid __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
& P8 j7 c4 ]- _! [& O  s# `: |4 r; I- j
// 辅助函数
$ U1 Y! f7 h+ Q0 m0 Q) J( bchar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);3 j. |  z1 t. a9 x) J
// NT/2000/XP函数0 e/ d& ]; q) Z/ ^$ R# E3 k, p
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);! S! z; _3 o/ ]5 O) s
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
7 T- v4 H8 J; Q% y( t  b$ X        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,8 u4 t' X# g# f1 d" }
       BYTE btDriveNum, PDWORD lpcbBYTEsReturned);' Q( G8 q8 j- n  W, E, v6 w
// Windows 9X函数/ R/ \" Y! O6 ]6 o% ^% x
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);4 E; |) l5 d) T% ?& h: P$ k
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,4 D9 g* @& _5 |3 ]$ `9 h5 r
       BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);- c* O' Q$ k' I5 o

# f3 A7 X) ~$ h2 C5 O; g/ `// SCSI读取函数(for NT/2000/XP)
8 e$ \8 H- ~' Q1 R  a1 cString __fastcall ReadIDEDriveAsScsiDriveOnNT();3 y9 {& C* X) j  W" J6 z! K1 Z0 r
//---------------------------------------------------------------------------. ^  E% w0 U6 ?# |+ E" [7 N
// ReadPhysicalDrive) ?" y; I9 d6 \& W2 o7 r
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)4 K# o. F7 D9 X5 l  C2 ?
{
7 _  y- ?' Y2 b" U( C+ j    switch(Win32Platform)
& p" V: ~9 [* t$ u8 z/ @    {% }" V6 A4 R% K6 t+ p4 ^) k
       case VER_PLATFORM_WIN32_WINDOWS:
/ K2 T! X+ a+ D, o& `. R+ ^            ReadPhysicalDriveOnW9X(pSerList, pModeList);
$ \$ D6 p' ?8 A# ^/ m8 {            break;
9 z5 I+ Y& u0 B% J7 X        case VER_PLATFORM_WIN32_NT:$ P2 L( ?  c* W, x4 Z" F/ t
           ReadPhysicalDriveOnNT(pSerList, pModeList);9 k0 s& E( M9 z' m$ V6 @8 ^# k
           break;
% r# r$ k$ x2 G+ I& g5 J+ e        default:
. ]  U- C1 w& y3 K  t; U4 c1 f            break;; _! A; V3 f& E7 y
   }
) d* J9 k7 F3 C6 p1 V! |}8 T9 N8 y* J  E2 _4 v8 X
//---------------------------------------------------------------------------) o  n! b2 A; n: k! ~
// ConvertToString% D  b7 d6 R9 }8 i, _  ^
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
& L3 H% t1 f$ \7 [) O6 W5 q+ C; ]{
2 s  Q( }& Y! ?( p9 ^" g    static char szResBuf[1024];4 I6 @. ]% ]0 F7 V0 J, H
   int nIndex = 0;& r& N6 ]& l) J, ], [
   int nPosition = 0;
5 x3 u, C) [4 p( \% Z3 r$ J  G" L: Y' ?7 c8 w- R
   // Each integer has two characters stored in it backwards) I- J/ ?  f5 l1 `, F" j6 ]
   for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)6 r# \; ~( y% l7 v
   {
8 N- s( r/ v# q4 r& W3 l3 U        // Get high BYTE for 1st character# O- x7 `+ X5 s$ Q# A' T' P8 F3 L
       szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);# z$ E2 f% I0 G3 u% x4 v* K( X
       nPosition++;
, Y, h- Z" N5 Z, [, E+ d6 Z) }  }9 K$ |* T; }0 u3 [
       // Get low BYTE for 2nd character
1 O3 T8 q2 v# o6 f( a; Z. o        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);/ N% M$ `1 C7 v2 k0 V, ?
       nPosition++;" n- o: [# N' U+ s& z
   }
# m, w/ J# \* e) P# O
2 m% a9 \# j& L: X/ x3 r    // End the string1 o! X$ G4 e7 [3 q- S
   szResBuf[nPosition] = '\0';
! p( `6 U* c5 z7 ^6 g7 `. H* t0 x' j6 i8 B0 v7 R5 n6 m( |4 T; g
   // Cut off the trailing blanks
- E0 C( i3 G9 }6 ~6 A  s    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)9 F( V  `' ^$ r% z( U% [
       szResBuf[nIndex] = '\0';
' L+ V) ~8 y: N& L. R. j5 H
( f6 Y7 x, }* p# d$ P$ u    return szResBuf;
3 q* {) P8 I" }  ]; o}
/ [& T- ~: t, H; j& l' e$ T7 ?/ S" K4 Y//---------------------------------------------------------------------------+ X1 |  Z2 i; t$ G( a  }: i" j
// Winndows NT4/2000/XP 代码
" Z7 D. X. A: x7 ~4 a2 A+ @, [//---------------------------------------------------------------------------% w+ j( k# k, U8 o. T7 Y3 `$ \
// ReadPhysicalDriveOnNT
$ s# {- U7 i9 [" v4 S- jvoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)1 n6 i9 L- m/ b: q0 @* t" j3 N0 G0 f4 Z
{( L# N2 L: L& c- Q; G# z
   // 输出参数
5 p2 E0 `# q8 @0 M7 ]    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];* m5 n3 }6 f# m! K0 `. Q

' P9 L5 g7 r- ^7 j. ^1 |( u    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++): v1 p3 @* W# g( y
   {. l& A9 Z1 q4 c; M2 F0 j3 h
       HANDLE hPhysicalDriveIOCTL;5 g3 w& x" r9 w  X1 c
       char szDriveName[32];' r4 {* `  a; g6 N7 J5 @2 g
# P7 w' M# ^/ R5 @1 k0 M+ ~( {
       sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);9 n: z: V1 u& P
       hPhysicalDriveIOCTL = CreateFile(szDriveName,
; y7 D; ?/ K/ e2 N' t                        GENERIC_READ | GENERIC_WRITE,% a: q$ S, [2 e
                       FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,4 D5 {$ h9 z3 m& d$ ^& B+ A! T8 [
                       OPEN_EXISTING, 0, NULL);
. R4 b3 t% J3 L1 }2 l2 z, j( S9 g* o% C# q" n+ l
       if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
+ `+ o9 w" |: j# N2 K        {) q, A1 X7 W1 K' {- y
           DWORD dwBytesReturned = 0;
  \! ?. N# w! x6 N3 F* d5 F            GETVERSIONOUTPARAMS gvopVersionParams;
7 {, Q+ ?. O1 ]3 a, f( }4 j* X3 |, v% a; |4 u. z9 _3 |* A+ `
           // Get the version, etc of PhysicalDrive IOCTL" P$ A0 S9 |# i% v
           ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
* f6 B: u& Y: P; f3 |. D, X( t2 B! H
           if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,' `4 e/ ]" Q7 m( k* A5 f
                   NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),) H6 [$ I+ H2 i% O: c
                   &dwBytesReturned, NULL))5 @! t! m  z8 ~" ~8 x
           {
- U8 Y/ N6 x8 A/ H; c: v                continue;
1 Y+ t: ^* S5 O            }
5 {; u8 ]$ o5 L. |, ~" }
4 e& I* b/ d# I* a            if(gvopVersionParams.bIDEDeviceMap > 0)
! P7 a* l- W& e0 l0 ?            {# |9 `3 f; z, x; ~4 z; d
               // IDE or ATAPI IDENTIFY cmd
4 j3 n- R3 S$ _# F/ c$ ^9 Y4 b% ~                BYTE btIDCmd = 0;
' a3 J' v9 _& w- y5 a& X6 z, v, q                SENDCMDINPARAMS InParams;
% A6 ~' d% a: R  y3 m* p                // Now, get the ID sector for all IDE devices in the system.
8 C+ x) }' U: W9 }" n2 b  j7 F                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,: O! o( Y) J7 K: \2 r5 ^* u
               // otherwise use the IDE_ATA_IDENTIFY command5 A5 t) _4 I; p* z2 f
               // 具体所得结果请参考头文件中的说明) I8 z- K; i3 I7 N- B& `  j, O* ]
               btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
- ^  d* ~, ~, @4 ~                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;: M4 z9 P- P( {  q2 Y( C7 Y
               ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
" ?' x* X- a* b/ q+ L/ i                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
6 U5 J8 l8 z/ Q+ h& [0 p5 z- s1 q  Q
               if(DoIdentify(hPhysicalDriveIOCTL,; D+ q% }/ d5 P! @* H( K
                    &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
$ T5 c% u: `" T9 H! d( Z                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))  ]6 v, R2 ?* h% y2 c% D
               {% [( h9 B" C% }
                   DWORD dwDiskData[256];
5 w* d, P: A3 @& v                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
7 i; A0 S& `, Y4 M; s0 v5 C                    char szSerialNumber[21];' {5 d, j/ A, e# i5 [: L% Q# W
                   char szModelNumber[41];
  ?- `- s+ ]1 D" a$ V' D* [" ?, E
, U" \$ c- V) g4 u' Y                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;2 g2 F6 G& d$ |# l8 A' h" d
                   for(int i=0; i < 256; i++)
9 H7 k! O( I8 u                        dwDiskData = pIDSector;3 Q/ C. R: n& @# A" c
                   // 取系列号
5 y% A8 f. t- t1 w3 A                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));& s, K! i  j1 w. k& v0 d- L
                   strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));8 m; ]3 r9 J- \# k8 w" ~3 Z

) g" s! S+ ]7 }' w/ n9 j1 j                    // 取模型号3 [+ j4 S* P* G' o- r" ^! r0 e; i3 \& d
                   ZeroMemory(szModelNumber, sizeof(szModelNumber));
0 M% O8 P, y6 r6 C' `                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));! U& `1 ], v2 j
9 h; F& B, s9 H
                   pSerList->Add(szSerialNumber);
# A/ M& j* y  h& Y! H+ P: J& Y                    pModeList->Add(szModelNumber);
: b& F  b& h2 \5 W                }4 N+ ^) L4 ?1 p9 E5 x
           }
8 @2 d0 l$ p0 u% C! Y7 H            CloseHandle (hPhysicalDriveIOCTL);! k2 H: V3 G/ P8 }1 K/ X# d
       }+ Y" t/ q4 t" y4 U
   }6 w7 M8 C' [4 Q" K
}
) U% L' `5 F1 N# r) ]* H//---------------------------------------------------------------------------
! D- e2 b8 g' S; t- @* r( J// DoIdentify
2 X4 W* A8 c; {  o5 Q: sbool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,* y3 C: |  ^* I& ?* M3 w
             PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
% ?1 B( ^' B! ~4 N              PDWORD pdwBytesReturned)
2 ?5 S( Q8 \7 U- l# w# S5 ^{
* K, I# ~" R* X    // Set up data structures for IDENTIFY command.
+ _8 p1 {0 m! F3 I" z& @    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;3 `" p; u' o- A5 w" O
   pSCIP->irDriveRegs.bFeaturesReg = 0;( \5 N' K) g3 l+ J  d/ c* ?5 ^  F
   pSCIP->irDriveRegs.bSectorCountReg  = 1;! _" |  K( ^' ?# [* U5 |7 S
   pSCIP->irDriveRegs.bSectorNumberReg = 1;( e% w& P- I5 \/ }: s
   pSCIP->irDriveRegs.bCylLowReg  = 0;
; h+ u* D0 N8 _1 T9 d; `    pSCIP->irDriveRegs.bCylHighReg = 0;
# f6 _. w- ^6 O. ~
2 w+ Z( ~# ]- A7 A& A4 ?4 C. x    // Compute the drive number.(主盘和从盘所对应的值是不一样的)$ Z4 L8 ~4 A' f/ r
   pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
. F$ B/ e5 S9 F
' j7 Q. a* T! u5 X8 e7 H    // The command can either be IDE identify or ATAPI identify.
5 P* N# o% S& w/ }: O2 c    pSCIP->irDriveRegs.bCommandReg = btIDCmd;
' k# H! l1 g5 Q" Q    pSCIP->bDriveNumber = btDriveNum;
1 C0 Z+ x/ T$ c    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
! S. p7 @3 `& q) u" d$ |2 V$ w% b8 {2 Q( z  ?6 b1 Y4 O7 w
   return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,$ ]  ~8 f& |' L( x- j( W1 Y
          (LPVOID)pSCIP,
0 g; _' D" a: J8 s$ t0 p           sizeof(SENDCMDINPARAMS) - 1,& d, C; d/ y* q5 ?" J8 X
          (LPVOID)pSCOP,
! e1 p9 Z7 F5 F           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,+ T/ u( n& a0 R# X2 d( E
          pdwBytesReturned, NULL);
/ Q. Q5 t' k$ r' h}$ ~$ o4 |3 P6 d% n, R2 k. d1 Y
//---------------------------------------------------------------------------1 W: D& @( n( k1 Z* l
// Windows 95/98/ME 代码
9 O: u1 Y* J  D7 Z- J% F5 L$ M% a//---------------------------------------------------------------------------
" A3 {* D1 x# O// ReadPhysicalDriveOnW9X7 [0 ~2 o* S$ i" }. Z8 D
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)
  @$ \  `$ G" O5 R! l{$ _' \  v8 J8 m/ v  E+ _
   WORD wOutData[256];' j3 @! l- ^/ t5 `9 d# y
   SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
# @/ Q  |! J, A# Q/ v8 B* d# n% l
3 V3 m3 x4 N3 x0 a  I& m9 F    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。% s( S( X1 X9 _, ~( ^0 s
   // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以% x. l& O! F9 s- t8 A! ]! [
   // 避免蓝屏的出现。(期待高人能指出原因)
# Q# ^. y  A9 A9 l7 G# Q7 E    for(int nDrive = 0; nDrive < 8; nDrive++)
) D5 F6 M3 B- t- g0 N7 x0 N# q0 U4 [    {
, s: v- U& l  A: b2 k3 D+ P( n        WORD dwBaseAddress;# a* K, F+ l* h" g1 @3 K; y
       BYTE btMasterSlave;         // Master Or Slave
' l) o4 C. V9 e3 O4 ]        bool bIsIDEExist;
! R! o% j& K! X- `+ _( [        bool IsDiskExist;* U' _0 B2 X- y1 y  ^

" y0 P2 J& e* t" z9 j  G        switch(nDrive / 2)
- @+ H$ k  s8 g6 E9 i+ Q( d! t        {% t! c8 t: K( @: `% N2 e
           case 0: dwBaseAddress = 0x01F0; break;
- t% c. B0 D) _2 V! ?7 \            case 1: dwBaseAddress = 0x0170; break;* @. y1 l, v5 g0 N0 U* n4 R7 a  L: }
           case 2: dwBaseAddress = 0x01E8; break;" ~7 d: j/ h- [
           case 3: dwBaseAddress = 0x0168; break;3 `* O  ]5 [( J9 ]) t, ^
       }
4 O; ]- b; f$ ?8 u* |( k: w6 P8 _. t' |( x
       btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);! B7 @' P+ b- H" I' [6 r

3 q0 P. `( Y' j: G        // 进入Ring0
; {2 p( ?- O! n5 t" x$ t4 Y        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave," _+ f# ]+ b4 f8 c
               bIsIDEExist, IsDiskExist, wOutData);
; V! I; \* j0 R, P, U9 O    }- P+ U6 Y: T( q8 [- |: t
: r$ L, G3 U  n
   // 开始读取
& o; |$ p: F- n# l* Y! I& j    for(int nDrive = 0; nDrive < 8; nDrive++)  s1 ^/ \4 X, U5 }
   {
/ H$ \# [' j" x        WORD dwBaseAddress;
. ?8 y2 h# V6 i) u$ `1 w2 H; s0 t* c+ E        BYTE btMasterSlave;         // Master Or Slave9 f. F! [+ O8 v7 [
       bool bIsIDEExist;& Y8 Z1 F, {/ E8 ?& K
       bool bIsDiskExist;  X; M8 N1 L. p; E' h" x
       switch(nDrive / 2)! F# I3 v$ s! M5 m; y4 ]' N
       {8 d& W# v. [4 H5 q! W
           case 0: dwBaseAddress = 0x01F0; break;5 V( S# V& o7 A5 a7 w
           case 1: dwBaseAddress = 0x0170; break;
# [; ]6 T$ B$ p4 S, e3 G% L- `5 q            case 2: dwBaseAddress = 0x01E8; break;
7 i$ u. o6 Q; q( X9 }4 `- l            case 3: dwBaseAddress = 0x0168; break;* n" e; V! ~& u8 B$ X3 X
       }% j) f! B. D. z* [$ N" w! P/ D

; J# R& j6 K* C* D7 @4 }        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
1 z5 ^4 v7 L* M6 J5 m1 X( f, v  T6 W% a' A) m5 k0 z. H
       // 进入Ring0
. h* F1 w" d& e& x  H1 |        bIsIDEExist  = false;# Z3 W, ?. t( v
       bIsDiskExist = false;1 o# a( I, O% e1 L
       ZeroMemory(wOutData, sizeof(wOutData));0 b3 ^, W+ s9 W! }' `+ ^+ T% e
3 J6 Q5 _4 _$ F' |* _8 D% e
       ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
7 f7 C9 S& v$ m$ U) Q' l                bIsIDEExist, bIsDiskExist, wOutData);7 N2 d7 d" F' [4 z5 D8 J, t
; R8 }* ?. w" ]: [2 [# j
       if(bIsIDEExist && bIsDiskExist)/ W* ?: p/ {8 A! h% {5 r9 ^7 ~
       {
% b( `7 h! f2 _4 j            DWORD dwDiskData[256];6 a" I  P! H+ ]1 E/ M' L
           char  szSerialNumber[21];
. }4 V4 o' h, ^5 R            char  szModelNumber[41];
" v: l1 g0 k9 h4 r# D5 ~2 H+ q! z' X) ]. @4 {) c$ z
           for(int k=0; k < 256; k++)3 t3 U. @% L  n- Q. H5 F8 ?
               dwDiskData[k] = wOutData[k];
- D' c; w1 g4 v7 F0 C" t! f
6 e3 b* _8 x! p6 u3 W' E  _            // 取系列号
5 y9 a9 d  p( b7 b+ i# S            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));! G: O% @! U' O" f6 m5 Q; G9 U& ]
           strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
9 }$ h- w8 \- }* ]3 w" M; K* b3 F8 U3 Y2 A4 L5 N  z& j
           // 取模型号
5 _4 ]8 b6 c# i/ ~" S& ~            ZeroMemory(szModelNumber, sizeof(szModelNumber));
* g. a* D) U6 O            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));3 @+ y6 ]4 f  ]+ A+ x! G+ K  V
7 }4 M1 v5 H: G7 i# s$ ~
           pSerList->Add(szSerialNumber);
- X9 I: v' Z! u" d! u; s; D  D            pModeList->Add(szModelNumber);
7 [- C+ t2 _. r, X        }
+ n% T& B% V2 \3 w1 |  D  s5 m: ?. S    }  z  h+ ?* H$ N2 c3 i. R- |
   SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);+ y  ]& J: I- |9 o# i
}
, [( q* ^- u- k; Z! P//---------------------------------------------------------------------------+ H- P7 x8 P9 r- r7 r+ `/ v
// ReadPhysicalDriveOnW9X_Ring0()
# g/ i9 A- N8 t/ S' m//; k4 d8 T; f$ m
// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h9 n2 r, s# }: B+ H
// btMasterSlave = Master(0xA0) Or Slave(0xB0)- x% q+ q0 }! h1 X  Z  Y3 a2 L* n) ?
//---------------------------------------------------------------------------6 z& T/ b3 i0 a
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
* {1 M, ?+ e/ [        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
0 k# ?# P: ^( Q; j, U. b{
% K* C& a) R2 H/ z3 V- B6 N    BYTE  btIDTR1[6];
7 t7 Z' n. Y0 ]3 s4 T9 K: _    DWORD dwOldExceptionHook;. \( L! @0 u0 `
   const int nHookExceptionNo = 5;
0 K- i4 i1 u3 v/ a7 m, v6 m
' N' k$ I: w, b! Z    BYTE  btIsIDEExist = 0;2 u3 }/ c$ q0 ]4 e- g" C
   BYTE  btIsDiskExist = 0;
. \- N+ I9 w: G1 U! D& g; Z    WORD  wOutDataBuf[256];) {# T+ ^4 ^+ _1 n

  c9 M/ s7 a0 C, x3 J3 _    BYTE  btIsFirst = (BYTE)bIsFirst;
$ o8 A0 B! R0 r# b: Q  y( Y5 r1 K5 M* [, h* t& R2 I& E
   const BYTE btBit00 = 0x01;
! @8 V7 A% V: |% o    // const BYTE btBit02 = 0x04;
* d, l; g$ I4 M5 q  A9 M5 Z& k, m! X3 H    const BYTE btBit06 = 0x40;
$ H2 x/ N9 K8 R    const BYTE btBit07 = 0x80;
% T: Y1 A3 j( w    // const BYTE btERR  = btBit00;
1 x9 _$ H  ?3 K. y1 M2 [    const BYTE btBusy = btBit07;- r  E. _9 G1 J2 p6 W, \8 \' a
   const BYTE btAtaCmd   = 0xEC;) n+ i# F  W1 p& a
   const BYTE btAtapiCmd = 0xA1;) r9 C1 R# J  m& ]/ \# t5 E3 Z' Y9 T

% V, ^- `: |* Y+ l' S5 N5 s    __asm
( ~- G3 q2 ^7 D7 i    {! o6 k9 F3 _4 z' g& d2 ~3 L
       // 必须先执行这条语句$ T6 p6 J9 a4 a. i9 P. m( w" c
       JMP EnterRing0% ~7 E1 v7 ]( |7 f: r' n4 ?
3 F. R$ o: |( ?7 \- ?' b9 t
       // 定义过程
6 ~1 D: \3 c1 N7 u9 y# l% P" c        // 等待IDE设备直到其不为忙为止
& ]; |/ W% H  c/ k        WaitWhileBusy proc
& H! N. [9 i+ b, l8 B1 R* J2 [' }: u9 Q3 U8 D
       MOV  EBX, 100000
6 b4 @! b8 J0 b5 Z' g; [        MOV  DX, dwBaseAddress3 K" M+ |4 P% h3 N* J5 j- ]3 i
       ADD  DX, 7
: T0 Y1 d5 ?9 E% w( s+ f' o( U0 z9 U; t, i! s* h0 Q2 v9 l
       LoopWhileBusy:0 E7 j0 F% T7 A& p+ x9 S

1 Y6 t& {- M2 X; S! ]( e        DEC  EBX$ Z' ]: U; i( w! h
       CMP  EBX, 00 \! N- u/ @# v2 N. T
       JZ   Timeout
4 c; G9 v. F( D: w' I) Z) x& b+ v        in   AL, DX. ?# J/ q: S/ Y+ F$ f. M
       TEST AL, btBusy8 |1 B) F( {6 s, n. G7 b
       JNZ  LoopWhileBusy: b, W; G0 |: M: i1 t
       JMP  DriveReady
; J  ]; q1 T3 `9 \
0 i: G/ Y% l2 ^  U3 V: o+ n        // 超时,直接退出1 b( c. ^; z/ Y' l& ~
       Timeout:/ E5 r8 K' F6 l7 ]% m
       JMP  LeaveRing0, `$ \9 m' o. [* {
       DriveReady:0 c2 \" e" P( h1 X
       RET
( @, h! J# r' U0 |' d/ B) ]        ENDP   // End of WaitWhileBusy Procedure. g& N  m  }( a! c/ m

% t" t$ ]7 h  {# y7 D        // 设置主盘和从盘标志! ~" b# x) Z8 k& F* y
       SelectDevice proc; D2 D/ H" L+ b/ T1 |8 j  \

- G! o. _; b* s, I        MOV  DX, dwBaseAddress& ]) w; M+ U+ O+ O) @6 g7 Z1 _
       ADD  DX, 69 C( Y8 W; O# ^0 K9 O/ ]; F
       MOV  AL, btMasterSlave
2 h2 U! m# \" v) U  a
! o$ y) ~! O: _$ d8 J        out  DX, AL
) d' c* M4 \! x1 [. |/ B$ I9 X        RET
1 ]9 E+ Y6 b4 S" Y9 d$ A" t
) A; g! {6 D* o) q) ?* ]2 y3 w        ENDP  // End of SelectDevice Procedure" P) X7 [2 s* y  z; x) e
  U8 j6 H( A( _/ j, a# Z- W
       // 向IDE设备发送存取指令4 c4 ~* L% R$ ?" f
       SendCmd proc
6 t6 L. k. N5 e4 Q; w0 g3 u- A; h3 k& K" ?; j
       MOV DX, dwBaseAddress
+ U4 c  ?; q0 u3 H; X        ADD DX, 7
7 r: q: J) ^7 E! u+ U8 d        MOV AL, BL // BL是主从盘标识,在过程外设置, S; [' ^4 n" d: ~* y% F# ~1 {* z
       out DX, AL: O7 A9 Q6 w+ I& M
       RET
; _% c7 W7 O7 Z7 ~& t& m        ENDP  // End of SendCmd Procedure
1 W$ \# T. ^0 E/ Q1 s- \+ L" ~2 E
/ \6 |( y! s* e4 h9 E( I        // Ring0代码
0 A% ^" F0 R* ~) V5 W/ l' U  L        Ring0Proc:- x4 h; k; i% i+ Y
       PUSHAD, b% S6 G! e4 t  Z. v
       // 查询IDE设备是否存在1 k  w2 y5 W1 u+ }% V
       MOV DX, dwBaseAddress
/ e& A: Z1 g0 s. q1 p; L9 s* u7 n        ADD DX, 7* A% I) O2 j, f
       in  AL,DX- [$ ]- c% H8 I7 i& C. Q

0 [: a- T9 D, x' Q, j; i% b1 S        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
2 \( E7 B( j4 R2 F& C6 U        CMP AL,0xFF
$ N. ?5 z- z2 h6 p$ j        JZ  LeaveRing0
9 _! x4 B6 s4 b+ z; G- _        CMP AL, 0x7F6 N) M3 D+ V8 j7 a: A. J& g7 }
       JZ  LeaveRing0
5 b! X. ]6 _" [  k
1 q* n' Q% ^7 K9 h- _- C  a        // 设置IDE设备存在标志$ P6 E: l* ^( J" ^6 [$ q
       MOV btIsIDEExist, 1
! e! N$ e$ _6 b3 ]7 k& X' k( s1 w, |1 P& P1 @
       // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)* A1 i6 U6 y7 w9 f) G+ U
       CALL WaitWhileBusy
* y* D6 o# N9 N        CALL SelectDevice: }( z+ r- `. a* e9 _
! F' Q$ K' c, j( q
       // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏% ^9 O/ {- h0 a, k" `; _3 c0 K
       CMP  btIsFirst, 16 r8 @0 R5 L. J4 g4 ], b
       JZ   LeaveRing0
( Q1 n" h1 z- U0 j
3 z9 t7 @( a, R; O. M) w: Q, r        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
* ?3 u2 o& s: D% [% j        CALL WaitWhileBusy
8 Y6 @9 U# `0 X1 h% b, r# o) [, I. k/ x
       // AL的值等于cBit06时,不存在驱动器,直接返回
- b/ Q, @+ o9 j3 a, `- Y        TEST AL, btBit06
1 X8 T# o/ S5 @- w8 r        JZ   LeaveRing07 A( \* l" N3 p4 D7 X0 Q9 H% K; l

' m: b! x3 s3 G) H7 j; |        // 设置驱动器存在标志. e+ B: f4 @% I, G# X- k  H
       MOV  btIsDiskExist, 1( N" g7 e8 A- }2 }5 }% ~

& y- T, M, q1 j) M! }& ~7 v; P        // 发送存取端口命令
7 n( Y5 ]1 k5 R8 l  C+ t        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,8 B# r7 u0 F+ z9 F: ?+ O; y
       // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令. h$ x  }1 a7 A3 R; W* i
       CALL WaitWhileBusy
, X( R. B, g! m( o& b        CALL SelectDevice    // 设置主从盘标识
# ~  l! E- J0 g8 z) M; ^/ o        MOV  BL, btAtaCmd      // 发送读取命令
# q0 v* J9 ?; i9 S        CALL SendCmd( y& T2 M% x" `
       CALL WaitWhileBusy
9 ?4 J& v7 e2 H4 w8 c, H4 D9 M  v' b4 W& i& A7 `9 f, y& F8 t
       // 检查是否出错3 X( Z9 Y; U  S2 Z+ W
       MOV  DX, dwBaseAddress! T8 _* ~: C' N' t3 }% P
       ADD  DX, 7
! Q3 N* R: H) f5 U7 |! J3 E
$ Q: x2 o2 x, i3 h# F( c, N; ^) \0 Y        in   AL, DX
7 S' h0 g; z4 X# l7 J% N7 c) Q1 T4 Q( F2 r; A2 J
       TEST AL, btBit00
( `& T+ C% k9 i0 }# c4 }; Y5 @        JZ   RetrieveInfo   // 没有错误时则读数据
, p" ?% d; ?) L, k0 I3 G7 e0 t2 M5 i4 u2 p; H3 f0 T- b, L9 S
       // 如果出错,则进一步尝试使用ATAPI设备命令
' k4 f' J# [5 y5 L4 ^6 v        CALL WaitWhileBusy# H0 v+ }' ]5 a& u  d3 b4 C
       CALL SelectDevice/ ~9 T4 A. F" t6 O
       MOV  BL, btAtapiCmd
2 K) l: H6 f9 q+ a+ T0 y6 b& j        CALL SendCmd# [! y, A& c4 u2 Q8 R& \
       CALL WaitWhileBusy# S8 T* J3 d! V9 z* x/ L
4 V6 m1 ^% V1 A$ t1 Q
       // 检查是否还出错$ S1 i0 R' W' @" a, c
       MOV  DX, dwBaseAddress/ L8 d1 c* \) |4 w
       ADD  DX, 7
* s# v8 p- f; m" l; {& Q. d& ?        in   AL, DX
. _) M1 ~  r% y3 [% A0 R$ V& M        TEST AL, btBit00
  |1 s9 \" z: g8 K, f( z        JZ   RetrieveInfo   // 没有错误时则读数据$ [" p2 k3 z; t. ]6 b; D+ G
       JMP  LeaveRing0     // 如果还是出错,直接返回
3 b4 T# j6 ~3 w. d" K  P
, J* H0 f6 Q5 y, G3 M8 ?' B, ?5 g        // 读取数据+ T. A0 E! n% E* Y+ _9 Q
       RetrieveInfo:* ]! n% g" ], p& ]

( D* d. y# z8 g" Z4 d( R        LEA  EDI, wOutDataBuf
+ t& V  X. x: R        MOV  ECX, 256
* b9 U- v! T% D, s. H$ H        MOV  DX, dwBaseAddress4 o( e% Y+ `, q2 t0 n" r* ~
       CLD- E, p* X! |3 Z/ i: L  M3 I

7 a& f: ?8 u3 U1 [: L* X        REP  INSW
( v1 L# {4 B: A$ W+ a
' b0 t: A+ ]) f, _7 o- S/ ]1 U        // 退出Ring0代码0 t4 U* h3 r+ r# e
       LeaveRing0:
$ e  d3 X% R5 L& G3 M% V0 S
' E3 D* R# [5 n- J        POPAD2 ~4 R& O, Q# p5 S. E8 `
       IRETD
# O, t5 L+ b# V) e( ?) w) ?' ~( L5 @+ y2 Z" B
       // 激活Ring0代码+ y# X  I+ [5 |6 E! V, Y% Z  j# d
       EnterRing0:
& W, @8 N# ^6 S8 O- E# F" I, A+ l5 }1 a& p3 U1 [/ i2 H, a
       // 修改中断门
* E3 z6 i+ \6 V        SIDT FWORD PTR btIDTR14 S2 j' Z7 Y& r2 [+ c
       MOV EAX, DWORD PTR btIDTR1 + 02h4 {. x2 G) R0 Q; p
       ADD EAX, nHookExceptionNo * 08h + 04h
" j" m+ {6 Y1 ^3 B        CLI
" M! Q2 E& a- A* X2 ]1 f, }$ |- s. _2 J
       // 保存原异常处理例程入口, }5 C8 L& r# B2 k
       MOV ECX, DWORD PTR [EAX]
, c6 H" Y9 X# i: _        MOV CX, WORD PTR [EAX-04h]% b) H$ U7 ?2 b/ {. W
       MOV dwOldExceptionHook, ECX" j+ x! C6 N- o7 d9 o

5 d4 Y) w  w/ e( g7 y: Y# c        // 指定新入口) D) N, M  D3 K- {: @. n5 S) o
       LEA EBX, Ring0Proc4 m& B0 L6 W1 x# z
       MOV WORD PTR [EAX-04h],BX4 Z. O6 O; @3 S( C+ C
       SHR EBX, 10h3 s# C) M0 d- u, x" R' [
       MOV WORD PTR[EAX+02h], BX
8 i$ U8 o) W2 S9 |% l
5 L  y7 w: ]  K$ B( [9 T( g9 x        // 激活Ring0代码
3 Q; s% B/ W2 ~% N; H' `0 K* L        INT nHookExceptionNo
! m; z. M6 s' }" p
8 g3 r$ {3 B2 t" k! ]! ^4 b1 T7 L        // 复原入口2 d# \) `9 s: t* v' D: d  z
       MOV ECX,dwOldExceptionHook- a2 |! o/ B% o( h8 V
       MOV WORD PTR[EAX-04h], CX2 O5 @3 o$ ~- n" Z0 s- l5 u2 t. Q7 t
       SHR ECX,10h1 o7 b2 `) B) ^; V  \
       MOV WORD PTR[EAX+02h], CX
# A# t" e( p9 n+ k1 z        STI* `  Z8 g6 [8 @7 J+ q$ E
   }
/ m& h. r% U% M; h+ U% h2 _    if(!bIsFirst)" o. R0 S9 `) @2 l3 G8 z) @# ^9 O
   {3 H. j, ?* c" ?$ I; T, }1 t2 w! u
       bIsIDEExist  = (bool)btIsIDEExist;6 u" L4 _+ }7 S/ F4 r+ y. H
       bIsDiskExist = (bool)btIsDiskExist;
5 l: N! {6 E: F; {# {        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
! s7 F1 c- \  @; w3 w  I6 Z    }
! R) |* m( n! w! c" ]! ^3 n  x}
4 X" w( s3 Y- M+ i+ s2 q0 M//---------------------------------------------------------------------------
' ^" [1 f8 v( s6 x! n; I// 调用方法:
9 h2 _* H2 ?) K2 Qvoid __fastcall TForm1::Button1Click(TObject *Sender)7 y& v7 |2 h4 U$ P2 p6 V
{
: g  U6 ^  Q2 a+ b0 P  Q    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);& m. h# U" M" v: M' o' [; L# k
}
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-8-14 00:08 , Processed in 0.019775 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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