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

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

[复制链接]
发表于 2005-5-30 19:22:36 | 显示全部楼层 |阅读模式
  #include <WinIOCtl.h>+ g& `+ F  G; e# ]# Q
#include <stdio.h>
; }/ V" o; G% Q  o! w! @8 d- O
; S0 p  y/ s5 C# w* y#pragma inline
! s( Q* j+ G9 C6 I1 k, ]: V//---------------------------------------------------------------------------8 Q9 S2 |. h, n
// IDE NT/2000/XP专用变量
9 x2 J4 S7 t+ N3 D$ [#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS* F9 R( P3 d/ S8 ^" x1 m1 k8 p
#define DFP_GET_VERSION         SMART_GET_VERSION
/ R" X" W' v" F#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
( J" i1 P7 f* u8 o#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA" h, |2 A+ Q. G
% S+ A& i: W3 y- E) M
const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令
# J8 P2 [: s9 W, I% j! K+ d$ @- oconst WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
( E4 X2 z, M" H5 p6 i' I9 b- u  _* m3 g" b. E( ?! I$ s
const int MAX_IDE_DRIVES = 4;
) L5 E; D8 k! s# N/ ?% z8 j5 g8 N
// SCSI专用变量
' J1 u* X: H; F& Wconst DWORD FILE_DEVICE_SCSI             = 0x0000001B;) a' v2 n$ a1 X
const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);& p: j7 C/ ^- B! U3 N
const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
$ S# \; C% U$ }' _- V! ^" ?const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;5 \+ L. W5 }2 s2 v5 Q+ ^

" N- d, V* F. i$ H4 {typedef struct _SRB_IO_CONTROL
* P' g: x5 {: ?* b{
& W4 F! \" H: b    ULONG HeaderLength;6 @( G/ r/ p' F" ~. W
   UCHAR Signature[8];, }% S& ^2 X4 B% A9 F* h
   ULONG Timeout;, z; D  ]0 S' K: |
   ULONG ControlCode;
# z% {/ U9 ~4 ?, V/ u2 y# \) y$ l    ULONG ReturnCode;
$ ?+ U5 K, l( @) x( ]    ULONG Length;
6 T  C. p9 D+ ~; T+ y}SRB_IO_CONTROL, *PSRB_IO_CONTROL;
2 ]" a/ {# R) ]1 o0 w/ K7 C7 X' K3 Z# d2 Z$ x7 z4 ]- Y
// 读取的主函数! L, f9 `/ W! g* w8 E3 w+ v8 x/ R
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
% ?2 X1 W& w7 m3 Y+ @5 U9 m7 A
- K8 N( k: s+ y% S: E! o// 辅助函数
% q- K' }$ s/ j- K' X0 j% Mchar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);  o* \% B7 c6 {+ ~
// NT/2000/XP函数
1 w5 \/ P8 L% `) Jvoid __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
6 @- Z9 z& ~" w( V0 C/ B7 y4 Ubool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,3 G9 s) I8 z+ P9 t
       PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
( y5 }, a- k% X, y4 n# _# x: J2 e        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);3 n% G3 D1 W  v) B: |
// Windows 9X函数
+ Y  _# w- h2 ^4 E' }void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);
  f& j8 O" r( U& q4 ]( A% jvoid __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
, B$ ]9 U! X9 `3 p* M) T1 c        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);/ @. m: C" i7 v- M# B& Y

/ ]9 Z2 ?! v; \5 z( m5 Q// SCSI读取函数(for NT/2000/XP)
. ]$ w1 p* l7 Q! N; h/ lString __fastcall ReadIDEDriveAsScsiDriveOnNT();
* [# j7 H, b: f# `1 l9 M+ V$ Y//---------------------------------------------------------------------------
* l$ l0 ^7 X3 ]6 f// ReadPhysicalDrive9 x! G& X5 z5 j9 }9 `" _
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
  j/ p! H5 x7 A$ Z$ q" ]{
, A0 I9 _/ x+ `    switch(Win32Platform)' K6 m" R+ a: m" d2 O
   {
5 p5 ]" o$ }+ c        case VER_PLATFORM_WIN32_WINDOWS:
& }, j. y- |$ y+ [            ReadPhysicalDriveOnW9X(pSerList, pModeList);% V% W. q, E- }' Y* P% E1 k
           break;! p  G& o1 a* `. \
       case VER_PLATFORM_WIN32_NT:
" ^: @2 C' J* j4 |: i            ReadPhysicalDriveOnNT(pSerList, pModeList);+ j  Z8 y% x" N1 b* J1 d7 `% R8 j
           break;' ?0 q, k' E& b/ r3 m
       default:" ~) R0 U: ?) _1 B" d
           break;
3 c/ ]. y7 F3 ?1 C" c4 I+ b+ A, K  t    }
/ Y6 v$ q$ t/ }3 y}
2 ]9 f$ Z  i; b0 W//---------------------------------------------------------------------------/ v7 a: T2 ?: A% F9 ^4 k
// ConvertToString
8 e3 ~8 q! x+ K% _! P$ ichar *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)% j! k6 x1 {2 D4 U- s! i
{
5 T  j6 ~% T5 N    static char szResBuf[1024];
) Q/ H( p8 V% ~1 p+ g9 I2 _4 L    int nIndex = 0;
+ n5 W5 Q# }* G, `; L4 t6 c    int nPosition = 0;
3 r, }% |! J! ]. Z% [- Q0 K4 Q! m+ ?+ {  f' ^7 P3 q0 ]
   // Each integer has two characters stored in it backwards
6 [, J, |, ?: D! \2 G9 H    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
" Z: F! U4 k1 C8 A! O    {
5 I6 G  C  d" S8 v1 z. _, a9 ~& O        // Get high BYTE for 1st character
/ z# l% T7 M/ t/ M2 i4 {        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);) x3 J2 a% ^7 ?- s- I: ~
       nPosition++;
5 c1 ]! u: J) a2 z" b3 g( f/ O
' K8 V. X. {0 e8 r        // Get low BYTE for 2nd character, J0 H1 q3 \6 M
       szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);0 z. c# H8 B! P# a/ K7 ]' `$ p
       nPosition++;! r/ {3 w* }) p; d' X& o
   }
$ l: c# V* Y/ f6 o" J# `5 Y) E: p) d/ N7 k
   // End the string+ v* |# C& l6 Y! Q2 N
   szResBuf[nPosition] = '\0';
! z* [8 U* U6 P9 }9 C0 ~# a  c. O- A# u
   // Cut off the trailing blanks* g  }0 o/ w0 |  T
   for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)# P4 i3 o2 d" N' o) m+ e" `3 _
       szResBuf[nIndex] = '\0';3 P& @, W* M4 E- b& p8 k; h
' h7 c" Q2 X8 i, N
   return szResBuf;$ y! O3 F7 k. P- C4 \* K! G: F$ Y* `6 M
}
: W; b- t& }. p1 I- b5 P//---------------------------------------------------------------------------$ x" o' S: E6 r1 f% a8 @& h; A
// Winndows NT4/2000/XP 代码$ F* n; G! f, r9 ?$ x: O+ X
//---------------------------------------------------------------------------
) Z) E, q  h1 @  b// ReadPhysicalDriveOnNT
& t1 `  r) G9 M$ T' _5 u) ?void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
' b' u3 q5 P2 W& @{
& L; Q$ x6 ^0 T( O8 R6 U5 F; J    // 输出参数
, C% O) u  h  T  i& X- J    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];- R2 h3 x; g" @9 \

2 C, b7 I0 y+ U( L% h$ i    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)/ w$ M! Q5 q1 ^+ S- h6 V
   {
( s  f- Z' x2 j  U# x* X  ^        HANDLE hPhysicalDriveIOCTL;0 @) ^; M7 z2 f9 \; ?+ J, m2 X
       char szDriveName[32];
, v- h7 W# F3 X0 ^& |7 Q
! {+ D! v6 a- E7 B0 r. h7 Z" p        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);, C1 @& C, ?) ^' z  Q" O; o
       hPhysicalDriveIOCTL = CreateFile(szDriveName,
1 k  ]1 j2 K  v                        GENERIC_READ | GENERIC_WRITE,
' u, H4 R( H  p( v5 n7 C: ]/ m                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
  D7 `+ K7 @3 y/ Q1 V                        OPEN_EXISTING, 0, NULL);1 u9 N! q& D( p4 R( G+ _  u% g

6 J/ s0 h' D/ R* y) x& d        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)9 ]; l+ F& u& c/ v
       {
$ Q8 @6 a+ R/ p" P  Q            DWORD dwBytesReturned = 0;  l" m8 P8 a+ B" N" v
           GETVERSIONOUTPARAMS gvopVersionParams;
2 W; J* P3 @$ H& p/ S  r% D; ]% U
* ?& {! F8 |& c) S, `0 [& \            // Get the version, etc of PhysicalDrive IOCTL
7 m1 s3 E9 ]7 {  u5 W  L            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));( r1 h4 g% L" X) E8 o$ r

6 L" i3 O/ v6 j5 Y" m6 ?            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
+ H' w8 |; A9 i                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
2 T& r5 P( b- f; y  c                    &dwBytesReturned, NULL))
" n+ m* N( e% m  h+ Z            {
1 \+ d5 @" l7 L5 \: y                continue;" l  T1 J9 R$ O8 k7 _3 |# q
           }) l/ e* |# F6 @/ S: S  X
9 t: [+ a7 r4 b' ~% h  F! {
           if(gvopVersionParams.bIDEDeviceMap > 0). X) Y* z8 `5 ]! h" P8 v* A
           {! G4 W, ~! Z. o, t
               // IDE or ATAPI IDENTIFY cmd
% L: Z, k6 ?9 u6 g6 U: |/ B                BYTE btIDCmd = 0;
9 g- J8 B/ N5 s- E6 h                SENDCMDINPARAMS InParams;
' k5 Z) J5 D( U( b6 ^, {: T( {                // Now, get the ID sector for all IDE devices in the system.
$ d. s1 ?9 M- b% M5 |                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,+ V' `% F3 b# e9 B9 F
               // otherwise use the IDE_ATA_IDENTIFY command- {; N2 M% c# |
               // 具体所得结果请参考头文件中的说明
, \8 _, D( ]# K; {                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
( q9 {+ w) S# k! |* @" X                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;- l; G* ?; k3 E$ G. i
               ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));2 L) V# q% r8 O. v. x+ S2 K
               ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
9 Q" c" z9 D9 @5 u* m0 `& y
8 {4 Y+ {8 ?* N: I; f+ g1 L& D3 g' D% `                if(DoIdentify(hPhysicalDriveIOCTL,
9 N% R$ o" P- e6 }7 q$ Z                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,! _% F1 k) V# M8 g  |8 C9 d
                    (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
/ D! \2 ^& i9 e! y/ q8 h- M                {
8 _! e9 T3 S( H7 h                    DWORD dwDiskData[256];
9 j+ F& f, ]# O6 _0 ^                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
: V, m' b, W+ F# `3 `                    char szSerialNumber[21];
* \" i1 g6 E" z% {( W9 r                    char szModelNumber[41];% ]. Y" N3 q+ w& V0 i) K3 T
+ A& ?) T" }/ v
                   pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;% @4 l( [' y' i1 o, [' {% ^
                   for(int i=0; i < 256; i++)' D) F8 H8 R% p  e& g
                       dwDiskData = pIDSector;
7 b0 l' z4 s; N8 z2 s- [2 D                    // 取系列号0 b0 F8 T# }( F
                   ZeroMemory(szSerialNumber, sizeof(szSerialNumber));3 M4 q9 |; Y7 C0 J2 U$ T
                   strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));. }7 |1 Z& ?7 y- v7 V, N, j2 l
* i. C: U6 g- E, r8 {  H# [$ K& c
                   // 取模型号
% R% L) f7 T, U" M5 h/ o                    ZeroMemory(szModelNumber, sizeof(szModelNumber));# n: D/ k: e8 v4 j& B5 c
                   strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));, p8 }! o: Y% s; c& |+ A7 D
  \! m6 z: a( A7 q6 F8 [
                   pSerList->Add(szSerialNumber);
5 [! _6 c6 Y0 ~                    pModeList->Add(szModelNumber);( W! M. |; Y/ g+ k0 e# r
               }% z6 q  T' G  G6 n" R# X/ z0 H
           }
( t! V$ ~- n4 a  \            CloseHandle (hPhysicalDriveIOCTL);
' c# \- p" S# H: q" f        }: r6 I! O/ I" h) b- ~( o
   }
3 j4 b/ m, U# w; z, C}
) t+ g& N/ J& I& f$ W# }//---------------------------------------------------------------------------3 ~6 ~% ]/ ]  L8 ], q; L5 ]) `
// DoIdentify
  J" m2 N9 P! J8 G" a, ^' jbool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
, N8 |6 b3 \9 z2 J              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
4 g3 k+ n# C: Q* @6 o9 c! S              PDWORD pdwBytesReturned)% a& g( a8 Z! p" ?- D9 f7 W
{
7 z: N* A- k* @9 L) h! g6 P    // Set up data structures for IDENTIFY command.
' X. x& f) q; U: R4 y; ]    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;' Z7 g- l1 r; a# ?$ D" _# J
   pSCIP->irDriveRegs.bFeaturesReg = 0;
5 z! B) k+ C' z) p1 T1 A; m7 O8 W    pSCIP->irDriveRegs.bSectorCountReg  = 1;% [  J  n: t5 N4 C
   pSCIP->irDriveRegs.bSectorNumberReg = 1;
. R% g  _) p' z& X5 A! y    pSCIP->irDriveRegs.bCylLowReg  = 0;
' \6 M# ^- H4 U$ D    pSCIP->irDriveRegs.bCylHighReg = 0;
0 X) O% b8 X* e8 V
4 \5 K4 X+ l* A: l2 O1 [    // Compute the drive number.(主盘和从盘所对应的值是不一样的). L' |  t$ j- U' I' _' S1 x
   pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;8 ~% J% u) L4 C2 w% B4 O2 H2 ^0 K

  E5 S3 ?* h( w3 W    // The command can either be IDE identify or ATAPI identify.
: [1 {( U" p3 Y9 R9 h    pSCIP->irDriveRegs.bCommandReg = btIDCmd;
: I/ V4 g1 o" C2 g0 \& e# T    pSCIP->bDriveNumber = btDriveNum;% U( R0 [7 G1 h
   pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
0 y1 s3 |$ Q8 V; u" P; i) O/ M9 z: o  ^3 x! U( |$ h7 V
   return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
& H* l/ T0 s) L           (LPVOID)pSCIP,
  i$ }% g3 P' L           sizeof(SENDCMDINPARAMS) - 1,
9 U! k/ i# z# m9 F& i0 f/ s$ ?           (LPVOID)pSCOP,
' X) x2 r/ P3 z9 A2 |2 m8 W           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
1 F- a3 m. U5 O* I7 T( [) m/ |           pdwBytesReturned, NULL);' r6 E( y( |- j5 r4 V
}
1 O- ?. H" L  P' `$ ]- M/ d% p2 g' m//---------------------------------------------------------------------------
7 C, l$ N' y+ H9 R+ L2 Y! ~- z: s// Windows 95/98/ME 代码4 E4 K  z4 C9 n
//---------------------------------------------------------------------------
2 Q: |  {0 I5 {0 A4 z// ReadPhysicalDriveOnW9X$ I4 c8 A# n) L3 v
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)
+ Y0 n8 E8 E3 K. g& T{6 P+ u& {( o9 \/ {
   WORD wOutData[256];7 Z, r/ g6 L% Z( C6 i6 [8 N) c# e
   SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);, E3 F1 o) Z( c9 l, m
! r; m( R) k3 P0 n. S8 K7 @! l
   // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。+ \+ t/ H3 a" C' N7 `
   // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以" Y# V) @' k* a* h! o; t
   // 避免蓝屏的出现。(期待高人能指出原因)9 X, R# C2 u' ?1 p
   for(int nDrive = 0; nDrive < 8; nDrive++)
( d2 V; [! I( s! d* y% E    {
) f  H4 o' z: m- Q: V        WORD dwBaseAddress;/ L: G. m# P# ^; Z3 |- ~
       BYTE btMasterSlave;         // Master Or Slave
: X- ]1 U+ V$ Q* P/ }, g% Z        bool bIsIDEExist;* P' ?' k3 e& G4 \& d6 {+ w
       bool IsDiskExist;
& |0 y% V3 F0 \3 Z# ?$ i: f
6 ^9 h0 \% u6 U2 Q3 e        switch(nDrive / 2)# w& Q! K* J+ ]1 A
       {
" A7 ~% {& w, q+ x6 v3 o            case 0: dwBaseAddress = 0x01F0; break;$ f5 |% O" F+ l, ^) V2 V; ?: Z4 i4 j
           case 1: dwBaseAddress = 0x0170; break;  R6 @+ r0 \& c6 I$ u
           case 2: dwBaseAddress = 0x01E8; break;
+ h! F3 i; a, t$ o/ w            case 3: dwBaseAddress = 0x0168; break;' _( R) A, C' Z) E% ]% P* Y
       }$ [( P0 r2 o( B: A

  f+ W, b' _* ?/ H+ G        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
* b: J9 O1 J0 b4 g$ I7 u* C( `  F0 g! g- J! J3 I
       // 进入Ring0% n* x/ J6 m; P2 O
       ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,- m8 g8 b% ?( P  _+ d
               bIsIDEExist, IsDiskExist, wOutData);
0 f' f- P, }' P5 L9 Z( u. y    }
' ~, n8 {# D4 \1 x9 k5 q2 |% l6 {
   // 开始读取
7 X, l9 k0 V+ b5 ^    for(int nDrive = 0; nDrive < 8; nDrive++)8 |9 a8 \2 }* P* D
   {1 R- S3 l4 e/ n* `$ Y3 b
       WORD dwBaseAddress;. Y% |( N! z+ r) }7 J
       BYTE btMasterSlave;         // Master Or Slave  P" m2 Z" |, d5 l% b
       bool bIsIDEExist;0 F1 S9 P& ^% _, C6 |7 ^% l5 D
       bool bIsDiskExist;
9 q( L$ A4 j" V) P: a- \        switch(nDrive / 2)
+ t' J9 P3 Y; S, U. \. P        {! ?# g1 c- V' L
           case 0: dwBaseAddress = 0x01F0; break;; T( Y6 }) u' j/ ?% k! D* f" H
           case 1: dwBaseAddress = 0x0170; break;
% H1 {  G# u. S% h) R2 R0 V! l            case 2: dwBaseAddress = 0x01E8; break;
5 v5 l; o: s/ K; |! j5 B            case 3: dwBaseAddress = 0x0168; break;
' y1 i# i$ R4 X. [3 \        }  q4 x) |" ^* r( o) m9 h. e8 E
9 ^. j! N' Q0 w6 A& u* Z
       btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
* O! Q; Q, ~. m/ N( K
0 R* \3 w. D( ]1 o* E5 a/ y; Q        // 进入Ring0! p. ?, {( C. M% s' d1 G+ _' k2 p
       bIsIDEExist  = false;
2 ^( ]$ d- ?5 ~        bIsDiskExist = false;: C; |  e3 j* I& C* {
       ZeroMemory(wOutData, sizeof(wOutData));
+ Y9 i7 v# _* M2 v8 y0 {# |/ ?5 @* I4 f! ^
       ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,- j+ N& y) ?2 v
               bIsIDEExist, bIsDiskExist, wOutData);
2 i2 \+ F! s4 a
' ]! ~. v  G$ P/ a2 N9 ]# h& E" e* w        if(bIsIDEExist && bIsDiskExist)
' ]  c5 i& ~  s% {5 L. L/ X        {& C9 Z; O2 g8 t$ G+ H2 b4 O; B
           DWORD dwDiskData[256];
" e* p0 m9 @- S            char  szSerialNumber[21];% y4 z7 s% }3 ]# Q4 L
           char  szModelNumber[41];; A' K% m6 z" U8 f7 ]
; C" [0 B& O% n  L8 V4 P0 c
           for(int k=0; k < 256; k++)
" ^# Q) b! v( `: d) K  F$ u                dwDiskData[k] = wOutData[k];" z. I/ e# K, r! \( I) I
% ?! z7 D% G7 t) Y- \" @6 W
           // 取系列号
6 {$ ^" ~( }5 Q+ Z            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
/ @) s8 s% t0 e4 Z( Y            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));2 |& N5 g% d7 F3 d) ?

: w' x+ D" A6 i) u- V6 a9 f% ?4 j            // 取模型号
* F( E/ o) w8 H0 J0 X            ZeroMemory(szModelNumber, sizeof(szModelNumber));
1 g( \8 u( E0 |            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
& m* _' _3 x6 i. \
/ v5 H7 X) J% q, J4 B- P            pSerList->Add(szSerialNumber);
# e" p5 E/ @  K0 c- E7 o            pModeList->Add(szModelNumber);
0 v. F1 y5 G" Q3 Y  [        }
) r$ e* c2 y$ A5 v; A1 W/ Z7 ^1 `    }9 u) t6 p. w; H5 b1 [
   SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);2 K9 V$ |+ ^$ g" g' C# o
}
5 y. |0 D- m, b/ h& P2 K//---------------------------------------------------------------------------: F/ Z( y, R# U6 Y7 _5 V
// ReadPhysicalDriveOnW9X_Ring0()* ?0 K2 |) X# ~
//* w# E( V# c- {. T
// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h* L& W8 S$ s, ~! R" Q$ l
// btMasterSlave = Master(0xA0) Or Slave(0xB0)& m- o- f0 ^% C( m5 E
//---------------------------------------------------------------------------" k, ^0 [8 g0 Z! O( b& Q
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,/ i6 Y! p- [+ ?  W
       BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
4 u# a$ q# r0 t{. w" @. t1 w8 p% M
   BYTE  btIDTR1[6];2 u9 n/ Z. H  ~4 ~) j
   DWORD dwOldExceptionHook;
! B( T* E2 z! A, c: X    const int nHookExceptionNo = 5;
8 b: S/ }, ^; e
1 g8 T1 ~' ^- I4 q  J; X' [7 G    BYTE  btIsIDEExist = 0;
5 }- P$ v% l* K    BYTE  btIsDiskExist = 0;( T& M$ g/ _+ }0 Z
   WORD  wOutDataBuf[256];6 t" O& c( s$ W8 b

. O( @6 j# w& }/ u    BYTE  btIsFirst = (BYTE)bIsFirst;
4 p, U# t0 B% t/ k- @! b( M: o& W" m) s' Y: d' Z7 [2 o( |& Y
   const BYTE btBit00 = 0x01;' O9 Q. ~  G) K8 I
   // const BYTE btBit02 = 0x04;& ~6 i+ {: d. u/ ~
   const BYTE btBit06 = 0x40;
7 S# @3 l1 _; i" \* z    const BYTE btBit07 = 0x80;$ h( ~  y* ]4 S) Q
   // const BYTE btERR  = btBit00;
+ @) x3 s0 d+ o, P2 {    const BYTE btBusy = btBit07;3 @6 u) y' \. P
   const BYTE btAtaCmd   = 0xEC;& A+ @& @5 y" |- s, ?8 V
   const BYTE btAtapiCmd = 0xA1;  W1 {9 S) }6 D" D! V% _+ a

! k/ h% Y, G! e5 z) s& u' w0 f    __asm
/ n' P- B* [( w, G: H    {7 L8 ]* E5 h8 S
       // 必须先执行这条语句
) ^. r- J; u4 ]1 g: B1 \6 N7 b$ Z        JMP EnterRing0% y6 `8 N, s4 b2 G, k$ Z

) f0 M' D/ F6 N/ B1 @! P0 Z. j        // 定义过程
  [: H0 `$ h5 G2 A+ s        // 等待IDE设备直到其不为忙为止  Q7 U+ r5 o. L( f' w
       WaitWhileBusy proc
  e% y4 @- E/ @: G; F: A9 @
; x9 w! @$ p! o9 x' O        MOV  EBX, 100000/ b* i1 L! l+ S5 z6 m
       MOV  DX, dwBaseAddress
3 c$ ?9 J+ q- |3 {        ADD  DX, 7
7 t9 \* Z# X' ^( P4 r. [
6 J( G; o' K6 _7 c        LoopWhileBusy:
2 f2 @$ o& \" @5 |+ z5 S; g$ L; x7 ~/ P* a
       DEC  EBX9 O; U/ B& R0 {# `$ j# d8 h1 Z* O
       CMP  EBX, 0
+ d+ `4 D1 z% O" s: J% R7 l  h        JZ   Timeout
( y; D( E+ ?/ f        in   AL, DX
1 u' v* s( N: W" {        TEST AL, btBusy
8 `0 n9 U2 k, V8 T1 X0 v$ ?1 V        JNZ  LoopWhileBusy5 Z% k& ]8 L2 \
       JMP  DriveReady) Y. W$ ~  x% u9 ^# R

" I5 S# K5 l3 o        // 超时,直接退出
  u4 {" q: u# b1 W& o        Timeout:
! e9 n/ y: c! {+ R9 i! @# j" M        JMP  LeaveRing0
* W' Q  ^) h% J3 @1 W( D& T        DriveReady:
. r9 i+ X! \6 }# F0 P        RET) I8 E/ [1 e5 O# K" `
       ENDP   // End of WaitWhileBusy Procedure
0 k7 v6 w0 ]9 e* ?' M; x
+ ]4 q# p( W2 b1 M# p6 T8 E        // 设置主盘和从盘标志
. ~6 K, D: H0 f: y6 X# N* M        SelectDevice proc, J7 Y* U/ a5 ~5 e7 R% c
7 C9 O& p; P- r. }
       MOV  DX, dwBaseAddress
, \' w" @6 l. d' v0 e        ADD  DX, 6
# ]# [4 X# _  x        MOV  AL, btMasterSlave
4 R6 z9 Q! ]7 M& R8 J. V. Q, r; @2 C0 S# z
       out  DX, AL! s4 l1 `0 F2 B9 h* [. ]
       RET
) v" f1 a4 U# F& n7 D, S3 h
8 d' R4 i# W+ l  B        ENDP  // End of SelectDevice Procedure, p+ ^0 O1 q8 g% O1 F
2 {" ?0 Z4 H4 V" k
       // 向IDE设备发送存取指令) F2 f* a" g" C) o" M! D  {% _& v
       SendCmd proc' Y( s; j* \" V+ ?3 m

* `& w$ T: [3 l7 S+ ~        MOV DX, dwBaseAddress$ R8 u. \" P, ~7 C0 g
       ADD DX, 7# K  y' \8 g! w4 Q+ ?/ Y) v2 I, i
       MOV AL, BL // BL是主从盘标识,在过程外设置- b; E+ p9 f2 ~: ?3 w
       out DX, AL
, m5 _. f" V* {7 R, @        RET
8 U4 u$ p+ m+ H( g# V' t        ENDP  // End of SendCmd Procedure
* l) {) H, B- q' g; y; w1 D1 X& i
" B  u1 _. C9 \5 ^4 j* ~8 T        // Ring0代码( X; Q: t% A1 q( [
       Ring0Proc:
4 W; F1 L! U7 c$ F        PUSHAD6 `  e9 @! B* |- \1 A! F
       // 查询IDE设备是否存在
, b/ T/ J; l0 l/ l7 I) x        MOV DX, dwBaseAddress
$ O1 d: M* r% [5 q        ADD DX, 7( A6 i+ W% r- T# e
       in  AL,DX# `  e$ [; p( i' r# R; Y) M+ Z
9 m1 e3 V) K, k3 l  G
       // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
9 v. E+ Q, R' P  f* K1 m3 {        CMP AL,0xFF
# m  s* b% n$ l; E        JZ  LeaveRing0) {3 S4 N. I0 ?1 M3 m; h0 ]. \$ }0 O! J
       CMP AL, 0x7F
6 p7 f. U* n0 a2 l( E- ?" k        JZ  LeaveRing0
0 D  }8 V! q1 s* E6 D
8 i/ @1 T4 s; Q( d: a4 C- ~1 B        // 设置IDE设备存在标志
. d! Q$ n& K! L; K        MOV btIsIDEExist, 16 f/ H0 r1 s" k0 y

. I; o0 P' E2 g+ Z# `6 V. {        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
* ^* V/ u1 x7 ^+ d' K9 b$ s        CALL WaitWhileBusy
4 V; b6 ^/ i7 `/ i$ L& v) w        CALL SelectDevice" ~$ u6 j, l$ R' I
4 Y% Z$ h4 d1 Y5 W/ X, p
       // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏' ^3 E4 [# `- ~( E" ]
       CMP  btIsFirst, 1
9 T3 W* u. _* m6 _        JZ   LeaveRing0  c# w& M' M7 X2 C+ g
% q+ A3 b" G( }- V8 u: J2 z6 F
       // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
5 ^9 s2 ?; T* p$ L8 O$ S        CALL WaitWhileBusy
/ J; ]1 K6 }0 M9 }% I
( L( v0 J& K2 o* ^9 b7 Y% x        // AL的值等于cBit06时,不存在驱动器,直接返回1 T% V- l% I# b$ G, Q9 r0 L! h& F
       TEST AL, btBit06. m+ R7 H+ c. S  J* v
       JZ   LeaveRing0  W5 x/ Y; C$ ~
% B. I" e" r2 Q: \4 M( \' E4 k
       // 设置驱动器存在标志7 c9 ~; {& J1 T0 B
       MOV  btIsDiskExist, 1+ l6 _% |" x/ C
3 ?+ @! G" X/ e! C* i% l
       // 发送存取端口命令# i$ B  K- Z  l# v6 b" u' O9 e
       // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,; f3 ]2 ^9 ?+ \
       // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
; F. j4 R7 V% }/ }* T3 M: p        CALL WaitWhileBusy: ?: g, Y: x, z3 c- ~5 U1 i
       CALL SelectDevice    // 设置主从盘标识/ B# g+ A! e( @, b& f  e! H
       MOV  BL, btAtaCmd      // 发送读取命令. P3 A7 b$ E4 q- C; D  P
       CALL SendCmd7 k% Z, i" y1 W; z1 {9 D% }
       CALL WaitWhileBusy) x5 p9 U2 y% ~8 t6 X& `

% V1 f; m. T5 E$ M  f4 F        // 检查是否出错1 c4 [# {4 R7 H# w. s. }& @  L  x) p( T
       MOV  DX, dwBaseAddress
$ S" |  s# K; n# ~; L" I        ADD  DX, 70 z; [  a" v  M) x! G/ O6 c
3 x- _. h. N8 W0 H5 x# N/ ]' N
       in   AL, DX* x  a* F( ~% T% D" K" p- _% C

" G. a" T' S  F2 @        TEST AL, btBit00
3 ^0 A3 {0 K* F% B0 M4 l3 n! n8 E. _        JZ   RetrieveInfo   // 没有错误时则读数据" }9 a9 S; `! h0 b5 ]: r. n

5 `- L1 A4 G5 Y( z) _5 g        // 如果出错,则进一步尝试使用ATAPI设备命令4 _; l7 n! u' o2 p- V
       CALL WaitWhileBusy. U7 p2 b3 M4 O5 S( i
       CALL SelectDevice
9 _* l( m1 Y  e( y" _8 ?+ U        MOV  BL, btAtapiCmd5 D: J5 y! X# J- c) U4 }0 G
       CALL SendCmd
; t) K8 E0 A4 w        CALL WaitWhileBusy7 F3 c5 u" f8 F* k

- d- Q5 X2 I$ ~; V! q# X- |        // 检查是否还出错
- Y4 Q- ~. P" t& P7 W: v        MOV  DX, dwBaseAddress
; `# S" k0 M5 e  Q4 {; f7 ?        ADD  DX, 7
$ v- q, F# r3 F        in   AL, DX
1 j* j. I% p. g2 `% v) y6 A0 r9 q        TEST AL, btBit00
2 ~0 v6 J. f* Y5 ~0 R        JZ   RetrieveInfo   // 没有错误时则读数据
! X$ Y( R' C# I/ i$ Q        JMP  LeaveRing0     // 如果还是出错,直接返回* W) K6 U1 j: k# E9 h; v

6 j3 j  _3 ?! \- x0 ^7 E4 l        // 读取数据3 E1 U5 O$ C1 z) E
       RetrieveInfo:
  D# B7 \) |: h2 e3 s
4 K2 N( z5 C% [3 ?6 I        LEA  EDI, wOutDataBuf
* s, @2 n6 O$ @2 R! L        MOV  ECX, 256
  h' A* E; D1 z* y8 n% b6 y% S        MOV  DX, dwBaseAddress
  ?  |, N+ Y9 w2 L        CLD' U/ e* X7 k+ g. n2 K

1 P2 E# s# m3 N  y' r        REP  INSW
1 R9 z) b( C$ t, i6 c2 _* j8 r% \5 v5 t% h- e( E( L
       // 退出Ring0代码0 X" Z, S3 {. ~, P
       LeaveRing0:+ s. ~7 w* b: b

& i* N5 {+ p' j        POPAD: s3 `/ s+ {- m: Q6 P" o
       IRETD8 K/ i( X3 s' @+ ]; ^# U( s3 h
1 Z4 R/ W  `1 Q
       // 激活Ring0代码
/ N1 O3 f% h& y        EnterRing0:& S5 v& s# z( L& ~8 j
4 v7 z( n. [  G: Z
       // 修改中断门! Z3 j" R) n/ X- C) n, {- ~
       SIDT FWORD PTR btIDTR1
8 r  T! }9 l* }, V' ~: e        MOV EAX, DWORD PTR btIDTR1 + 02h. O( [* q1 |1 n) E* K
       ADD EAX, nHookExceptionNo * 08h + 04h( D& @3 N/ k* {9 W. p% r
       CLI
: m+ M% y, Q2 e. q
8 l* G  K1 Z* g! H$ o        // 保存原异常处理例程入口# I* C+ j9 I; a' k- O& j
       MOV ECX, DWORD PTR [EAX]
  W: t8 X# u, e* A* ~) Q$ L+ y; W        MOV CX, WORD PTR [EAX-04h]
  {& h7 T! n$ l        MOV dwOldExceptionHook, ECX8 v# m% k! d- A: R" o! C6 B
4 h& s, r+ r1 Z, o! M$ z
       // 指定新入口& h) C% z' C0 `8 X/ G" ?9 N
       LEA EBX, Ring0Proc
+ x. j' S# i2 F6 i3 {        MOV WORD PTR [EAX-04h],BX: ~$ Y; t3 l) u$ C* [2 {
       SHR EBX, 10h
' Q+ u4 O) `7 M) p        MOV WORD PTR[EAX+02h], BX, m) Q- m- ~) s. k4 B+ o
5 O4 }. Z% D5 G+ T4 b5 H" A
       // 激活Ring0代码
3 v3 s9 }( W' z! i        INT nHookExceptionNo# ~3 h, e: L  I/ q$ T2 f8 u% U" {
6 E" Y0 b  Y8 U* H. ^! I1 F" w$ r% u
       // 复原入口- r. o) {1 e  h$ z
       MOV ECX,dwOldExceptionHook" L% @/ Y; i1 k
       MOV WORD PTR[EAX-04h], CX
( l& u/ m9 P- }; e; y9 e        SHR ECX,10h: `: V- n6 Q  ]" E  i, R: n! D! v5 B
       MOV WORD PTR[EAX+02h], CX/ U8 k$ z+ Q' L3 C  N7 X
       STI% X2 x$ h" J$ q4 m0 N7 g
   }
. J  |& C* [- ]( i. E    if(!bIsFirst)
8 E& U1 ?2 s+ U0 i: C- |) s7 C    {" V4 b3 E3 K$ b# R" A
       bIsIDEExist  = (bool)btIsIDEExist;( ~6 b0 T- t! |  }: j" W
       bIsDiskExist = (bool)btIsDiskExist;
  L5 X% m; K# e- s7 {. W        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));: u9 P" P7 y3 C) Y4 C5 U/ d2 Z
   }
1 w. U$ l6 q: |$ w}1 N2 Y5 b2 J6 |9 G. ]
//---------------------------------------------------------------------------" j: F# O% s$ h1 ~
// 调用方法:
# ~5 @/ v1 O4 q. zvoid __fastcall TForm1::Button1Click(TObject *Sender)
* y# _) N3 h1 p- I{
. b" B! ~, B4 B$ E4 [7 j    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);4 Z6 M6 A+ I2 l' C6 n; L6 }' ~
}
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2025-9-30 10:59 , Processed in 0.036726 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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