找回密码
 注册
搜索
查看: 5168|回复: 1

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

[复制链接]
发表于 2005-8-11 11:42:04 | 显示全部楼层 |阅读模式
  1. #include <WinIOCtl.h>
    & g! K+ {7 a% t3 K' k7 }! r
  2. #include <stdio.h>. f/ v; {( V, \# I

  3. ; F; R5 E( A) s
  4. #pragma inline
    " E+ t+ v# g0 p
  5. //---------------------------------------------------------------------------
    % R- Z' m6 P% X! Y# ?7 u
  6. // IDE NT/2000/XP专用变量
    3 m5 @6 J4 G$ N" N: q
  7. #define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
    $ m! w, T1 O+ S, z+ k% Q
  8. #define DFP_GET_VERSION         SMART_GET_VERSION
    % M3 ^) ]' x5 U2 w% U% V
  9. #define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
    " O, a  d$ Q- {' J, S7 R' q/ m
  10. #define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
    - i1 v; ^7 ^5 ~6 k' T  O( |  @

  11. ( f$ \$ Y$ @8 w
  12. const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令
    ) [2 x& Z0 H6 d& b
  13. const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令" o0 c& b4 C3 }& O0 ]$ _
  14. ( }, i- c2 }$ ~+ x0 q: y* |; x' Y
  15. const int MAX_IDE_DRIVES = 4;
    9 x) f) Z7 E# g( F1 h
  16. 2 |  ~, ^8 G& S
  17. // SCSI专用变量; N6 j: f8 |- f; m3 f+ C
  18. const DWORD FILE_DEVICE_SCSI             = 0x0000001B;' ]# L: c2 {; A
  19. const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);; E, T- m4 Y5 P6 [/ p! B! o7 ]( w  j
  20. const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
      b) V2 f8 q8 p
  21. const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;  m: a9 j/ r1 U) }6 Y" [
  22. / B+ j& S3 g. w% p9 y8 }. ~
  23. typedef struct _SRB_IO_CONTROL
    6 _: e- d3 @0 c0 l2 n' k
  24. {4 ?, k# I# o1 a
  25.    ULONG HeaderLength;2 b, V* H  N( \; K" B! i, R# b* a
  26.    UCHAR Signature[8];
    " M8 s! h) ^& i
  27.    ULONG Timeout;+ x) |. t" Q" ~/ _* j
  28.    ULONG ControlCode;) p  v( ^6 D, V( n  c8 z' n, J* m) C$ t
  29.    ULONG ReturnCode;* E, o* i! T0 t7 o, X/ E7 _) A) [
  30.    ULONG Length;  T4 x! O% u4 V: Q$ T/ s
  31. }SRB_IO_CONTROL, *PSRB_IO_CONTROL;
    ; _: p' X/ ?, ~6 ]9 ^

  32. ; ~7 e. V' z5 b# ?, G% f$ U
  33. // 读取的主函数
    " ^8 u. y# r( [8 Z
  34. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
    & s# F0 E, q' [
  35. " R3 q: n0 n0 C2 _! K5 s8 {; o
  36. // 辅助函数1 _( a+ v% }7 K& U" C$ R( {
  37. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
    4 f, \+ H' M: u
  38. // NT/2000/XP函数
    3 J; D/ o0 j  Q( h& Q* h! f
  39. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
    8 u6 D: P6 Y' N  a  d
  40. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
    ' ]# S8 ?; g  Q/ h
  41.        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
    9 X- ]  W+ q, e( n
  42.        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);; J! O) f, k+ O
  43. // Windows 9X函数
    6 N% I8 p5 A9 L2 B! t4 w! y
  44. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);
    / ?, ~( f. v: ?; Z# e1 i; ^
  45. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
    1 p- X  Q1 g+ q! g' @8 S: l. q
  46.        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
    8 R5 q# P: }  i. t& i0 a5 v# X

  47. 1 X6 g+ _6 D; }7 r* N0 O  B
  48. // SCSI读取函数(for NT/2000/XP)
    2 Z7 d6 }! f" r" Q- r5 `" E& S
  49. String __fastcall ReadIDEDriveAsScsiDriveOnNT();
    % N6 Y* C9 z* ]% b: \
  50. //---------------------------------------------------------------------------
    % y. W  x5 ^( f. w  P: \. f; b
  51. // ReadPhysicalDrive  K) L3 z) b: x, b2 W8 }
  52. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
    + i  _, T; ]" r
  53. {0 m' B2 j5 L+ `% F! Q/ _2 \
  54.    switch(Win32Platform)
    ; H" x  o6 R! @5 ]  `- N. s
  55.    {
    / y% j" ^& `/ T% n  g
  56.        case VER_PLATFORM_WIN32_WINDOWS:( I. r# @  t! T+ G1 E8 F& U
  57.            ReadPhysicalDriveOnW9X(pSerList, pModeList);
    , W9 _: y) L, X* e
  58.            break;0 Q) c. J2 x: P& U* T8 A( I# g
  59.        case VER_PLATFORM_WIN32_NT:( w# `, e) E4 E+ S, O4 e1 @
  60.            ReadPhysicalDriveOnNT(pSerList, pModeList);+ }" C4 p, O4 g$ U
  61.            break;
    ; R  B- R, n0 o( _6 n4 c7 |
  62.        default:2 N) e; @( y- [
  63.            break;
    ' o  L% Z3 W- N9 R% d
  64.    }
    2 q' Y1 e6 Q' W1 A
  65. }
    2 h# j, A1 P' s2 F! D$ V% }$ Y& w
  66. //---------------------------------------------------------------------------+ A% {. A7 ^; S8 c% O# j
  67. // ConvertToString8 R. S" B# J% K( j& q9 C
  68. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)( v) s/ l9 K+ D* K' E! I
  69. {' T/ O1 Z) T# C5 [. U
  70.    static char szResBuf[1024];8 U( R0 _+ y/ t5 a7 F
  71.    int nIndex = 0;
    ! e0 N( h+ B0 p$ w- m
  72.    int nPosition = 0;& ~0 n: }1 r1 t, L: _

  73. 2 B0 z* M5 ~7 I, R% P# W  O# L$ W
  74.    // Each integer has two characters stored in it backwards" ~* @4 }% ^( _3 i* x6 r
  75.    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++); \% {' c3 p( A0 }0 e* f
  76.    {
    ' K3 U/ m; D# h% q9 n* H
  77.        // Get high BYTE for 1st character
    - Z: R9 y$ T: y4 z3 N! p
  78.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
    9 |8 o- f' C/ c  L$ K$ w) o
  79.        nPosition++;
    # z% j" R0 h/ ?
  80. ; u3 E8 N& m- y8 B* U
  81.        // Get low BYTE for 2nd character
    & F5 J, y% `5 R+ @! N6 Z
  82.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
    / s$ T& h- l1 }7 X) L$ q$ A
  83.        nPosition++;
    ) ]% B+ q5 o9 t$ r
  84.    }1 Y( ~" ~  Z( L

  85. * h; q; t! Y9 g- t
  86.    // End the string# Z: Q' \* ~/ g4 ], p! i$ k
  87.    szResBuf[nPosition] = '\0';
    4 P6 `0 o; V: |+ Y) c) b
  88. , f! ]) ~1 y( t) N& \* u. o4 ~- a# n' z
  89.    // Cut off the trailing blanks6 h% P) {0 u6 u
  90.    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)$ L9 G0 n$ T8 T0 m" P9 h
  91.        szResBuf[nIndex] = '\0';
    1 V. x) r* v- I" [! X
  92. 9 G/ w8 Z3 ^( Q/ q: \: a
  93.    return szResBuf;& `  v7 O. H3 o* o9 c% H) v
  94. }
    ) ~1 ~, ?& k3 C8 B% a
  95. //---------------------------------------------------------------------------5 y7 N! F" t( |. T5 }2 |2 T
  96. // Winndows NT4/2000/XP 代码
    1 \: ]; C% D5 B' L% G
  97. //---------------------------------------------------------------------------- c: c: k. a. `6 @* p' a! f8 I
  98. // ReadPhysicalDriveOnNT3 C+ C0 D* z* X  y4 l' ]/ R
  99. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)0 l5 m( u9 K6 x0 i: T, V3 f# C/ v
  100. {& e2 S) G0 S# t5 i' k2 f7 k
  101.    // 输出参数
    1 x( l8 [+ k, ]" C; V5 W
  102.    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];" f) d& p5 H( z
  103. / e3 T% c& {7 o' m
  104.    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++): D9 J4 F; ?/ @
  105.    {
    # c! F# m, l2 d, V) j% `3 n
  106.        HANDLE hPhysicalDriveIOCTL;( }7 O5 Y8 @; D- o1 @* \
  107.        char szDriveName[32];# s& ^7 A( _) ]* `! |

  108. 3 _( M( p$ G; K9 h5 e/ F* t
  109.        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);& W% m& A6 v. x, K
  110.        hPhysicalDriveIOCTL = CreateFile(szDriveName,
    ' }3 T+ h4 c! H
  111.                        GENERIC_READ | GENERIC_WRITE,( n- i. O7 W/ q, \( _; V
  112.                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
    + V5 d% K' y- @3 x1 ]' P
  113.                        OPEN_EXISTING, 0, NULL);/ Y  r8 N$ I) ?# P. Z3 b

  114. 0 \+ Z" m* v3 Y6 M
  115.        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)) B, T" U( B4 F7 Q5 g
  116.        {4 ]/ @5 w% g4 C7 R
  117.            DWORD dwBytesReturned = 0;/ h7 G; }) H* ~1 I, z" Z+ {
  118.            GETVERSIONOUTPARAMS gvopVersionParams;. o4 J) D& I3 h0 J7 Z  k. M

  119. 7 A. l2 \  U& U# \$ |3 J( ~+ L
  120.            // Get the version, etc of PhysicalDrive IOCTL
    # v1 _* G( R) H1 l
  121.            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));3 o2 p: ~! q# J" b9 z9 U+ \" f1 Y

  122. ! G: z4 o/ s6 f( _9 {4 V
  123.            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
    + L& c) o$ K  z4 A  c( E
  124.                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
    0 e+ p: i7 c3 D( s( q) ]
  125.                    &dwBytesReturned, NULL))2 g, R+ q8 l0 t1 b1 u! v9 T+ N/ |) [
  126.            {
    3 ^: ?; i9 ^( q' y5 L/ e- Q$ ~
  127.                continue;
    + D: @. E) i- d- A. L
  128.            }
    ) q1 e' D* X, r6 h) I4 E

  129. # a. Z" `8 P. k
  130.            if(gvopVersionParams.bIDEDeviceMap > 0)! q  }$ y; k! \* T
  131.            {1 L/ Y& n( u1 y/ I6 c8 L( \, j
  132.                // IDE or ATAPI IDENTIFY cmd
    - A: u* ~# v- `+ Q; Z; v3 _
  133.                BYTE btIDCmd = 0;) r; \; j8 S% j4 G; b( ]" T. @  u
  134.                SENDCMDINPARAMS InParams;/ m! q1 T& [& B# o, b
  135.                // Now, get the ID sector for all IDE devices in the system.3 z6 D+ U* e6 b9 M  `* y
  136.                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
    3 N/ W+ I! n% [
  137.                // otherwise use the IDE_ATA_IDENTIFY command
    , \& J0 F# b" x% {/ A
  138.                // 具体所得结果请参考头文件中的说明! h8 B) t5 v3 {
  139.                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?' a. \/ o) y7 g; F- d8 g- a
  140.                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
    / L* ~4 }0 o, c. P
  141.                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
    * C* \- U4 b- b# T
  142.                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
    ' {0 W9 n; ^, j. G! G
  143. # }" h6 V! t$ C! s. X. }% ?
  144.                if(DoIdentify(hPhysicalDriveIOCTL,
    8 U8 P. O' [4 X; w& l- o
  145.                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
    ) d* {$ L" D6 Y( v7 J9 v
  146.                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
    - Q' a- y& L% b6 E/ f
  147.                {& q1 N- _( C3 A2 S5 V: [
  148.                    DWORD dwDiskData[256];
    7 f, d, d1 h' B( c
  149.                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
    / n( }8 x$ W  g8 q3 M& Y( ~
  150.                    char szSerialNumber[21];! D7 {1 [  E- `; O" P2 U1 C! M6 h
  151.                    char szModelNumber[41];+ u) f/ c" h" X) m+ R* P7 e/ {) h/ l7 G

  152. $ D: Q5 e& Y9 V3 c9 v
  153.                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
    6 g! f+ T: ]; X3 N4 B% q
  154.                    for(int i=0; i < 256; i++)$ N( B4 j5 x. p, R7 Z
  155.                        dwDiskData = pIDSector;" C4 f6 M0 j1 \9 e8 V$ `8 S8 q3 g
  156.                    // 取系列号5 E- f3 p  B) E  l) X
  157.                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));, a6 o1 F1 {) J* n+ y
  158.                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
    + z( [/ K% C, E0 f* x' V, F

  159. 1 j  L, Y0 x1 C3 f5 R
  160.                    // 取模型号
    2 D- E8 r! ~$ t$ S2 c# q
  161.                    ZeroMemory(szModelNumber, sizeof(szModelNumber));! A. k6 w) M" V4 w( ^9 l5 @4 q
  162.                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));- L' O# A0 k: M/ o  c3 Z( Z
  163. 2 j% o  f( N6 e# g  a4 K
  164.                    pSerList->Add(szSerialNumber);
    : Y$ j% b% ^. J, y6 w' r
  165.                    pModeList->Add(szModelNumber);
    % O1 D" H# F$ N9 P
  166.                }
    : z" G( e* F& I5 P" {
  167.            }
    ) p( T* {$ z! E8 v3 H$ u
  168.            CloseHandle (hPhysicalDriveIOCTL);( [( H# ?4 r6 G% B) r* \
  169.        }
    % J3 ]& J$ H. u( _3 L7 G
  170.    }
    ) J0 b! K; G* i. x. L) I+ M
  171. }' P+ t3 Z" r. T; [. R: I
  172. //---------------------------------------------------------------------------
    8 J' r1 a! F$ v( z
  173. // DoIdentify
    " W# F6 T) y3 u2 a
  174. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
    , \+ S, [1 q$ I
  175.              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,: R& O* E) ^: P$ r0 c+ ~( f
  176.              PDWORD pdwBytesReturned)4 L7 r! s1 y! ?) e
  177. {9 C0 m) P4 M: E+ }9 `& h) i) T
  178.    // Set up data structures for IDENTIFY command.
    * o7 r6 K1 K8 N3 G
  179.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;" U5 |8 K, r$ p: c0 M+ w
  180.    pSCIP->irDriveRegs.bFeaturesReg = 0;2 M8 g: e6 s1 |2 Q
  181.    pSCIP->irDriveRegs.bSectorCountReg  = 1;3 X' y$ R) a3 v# `- y
  182.    pSCIP->irDriveRegs.bSectorNumberReg = 1;
    + A2 S  V8 i% k7 J( t8 ]  \6 }
  183.    pSCIP->irDriveRegs.bCylLowReg  = 0;
    * @6 [$ @% A% W% {
  184.    pSCIP->irDriveRegs.bCylHighReg = 0;
    9 E1 @! _; l: \( Z/ v

  185. 2 e0 Y+ L3 \- I) v+ i- S) n  U
  186.    // Compute the drive number.(主盘和从盘所对应的值是不一样的)- X" R# d9 p' ^) z9 y/ F; K
  187.    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
    8 a5 S- Y& y1 n5 h
  188. ) N, O' B; {- y, t; o
  189.    // The command can either be IDE identify or ATAPI identify.# _2 {' F5 n5 |8 T  Q
  190.    pSCIP->irDriveRegs.bCommandReg = btIDCmd;
    ; ^9 Y  N" `8 w+ ^  E, ~
  191.    pSCIP->bDriveNumber = btDriveNum;  n$ _" g6 F: m% r. S
  192.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;; @2 g0 c+ @0 u, d- c
  193. $ i  k8 h5 q3 v0 ^9 C. C1 S
  194.    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,' T4 z% |! k9 N% i; R- v( `
  195.           (LPVOID)pSCIP,
    ) u+ i# k: N8 X( O6 V- T* X
  196.           sizeof(SENDCMDINPARAMS) - 1,
    ) P+ z- M6 v" h9 _2 V+ p
  197.           (LPVOID)pSCOP,
    2 E$ l3 {" l1 t) F  z0 Z" p
  198.           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
    1 D' \& {' c4 x7 Q0 `7 ]: w$ C
  199.           pdwBytesReturned, NULL);. E: ?2 T" [9 x, r" O3 n
  200. }
    . }* N; R9 R; f& e: ]; P5 d' g# _
  201. //---------------------------------------------------------------------------9 Z3 ?  \( ^8 z" P
  202. // Windows 95/98/ME 代码
    $ [, x* k9 w6 ?! Y) v! [* q
  203. //---------------------------------------------------------------------------
    4 n! G  B( T# s+ d8 X, u
  204. // ReadPhysicalDriveOnW9X% W, {/ N4 u3 i9 W
  205. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)! r+ z# j8 M$ K' r6 _% ]
  206. {# ]& z  M2 c; W# B2 b) t0 }' [; p- C4 O
  207.    WORD wOutData[256];
      j4 Y8 T) r7 A# T2 `& I/ j& s
  208.    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);& X# A( T+ F6 g$ }6 A

  209. " q6 ~' v$ ]/ h. ^% O2 [: M# J5 s
  210.    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
    4 ]1 x, z. F4 N- {
  211.    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以+ n4 L2 q9 C' ]4 ^2 K, r& h
  212.    // 避免蓝屏的出现。(期待高人能指出原因)
    * K2 {1 v+ x3 d' ~" @8 c$ w4 S2 |
  213.    for(int nDrive = 0; nDrive < 8; nDrive++)$ [* ], v" x3 a( v1 y: P# T9 e
  214.    {
    " A  E" H" S# W& _* M
  215.        WORD dwBaseAddress;& p2 x) Z3 F; s! i% [0 {$ ~- }# v
  216.        BYTE btMasterSlave;         // Master Or Slave* R3 j$ q; K& L" ?0 y5 d3 {& J
  217.        bool bIsIDEExist;" @9 ~/ g7 Z$ Z; v" t( M* }9 G7 `& m
  218.        bool IsDiskExist;6 ]6 m9 \5 [0 g; I: j

  219. ) ~4 W4 f: o! i' F" h7 g8 [
  220.        switch(nDrive / 2)8 C- c2 y7 }! Q3 L0 |% l! f0 E
  221.        {- e' S6 c4 l% i, l
  222.            case 0: dwBaseAddress = 0x01F0; break;
    1 ]0 Y! _5 o( A; m
  223.            case 1: dwBaseAddress = 0x0170; break;5 p" f+ G& _; x4 S1 f* {7 b
  224.            case 2: dwBaseAddress = 0x01E8; break;+ c( Z' C/ r& g  u! l) n' M8 L1 @
  225.            case 3: dwBaseAddress = 0x0168; break;) S5 i5 |% v# Z  g
  226.        }! U7 F+ D5 R* ~
  227. , B1 y  z1 |5 Z6 T7 T4 v
  228.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
    . Q; L6 \: Y- v" E! w& R
  229. / _  K7 g0 p2 J/ w4 s4 ^
  230.        // 进入Ring0/ u9 g/ Z' b6 D2 {
  231.        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
    6 F* s& Z, k' ~; E/ f. q! I) K
  232.                bIsIDEExist, IsDiskExist, wOutData);
    8 G, ~! u6 H5 t* k5 q4 |
  233.    }
    ( B3 X- G1 Z% [8 ]2 L  }' i- {" V4 M

  234. % S7 G; G# R7 F; Y4 d
  235.    // 开始读取
    & O8 b( R& l2 r- |* |
  236.    for(int nDrive = 0; nDrive < 8; nDrive++)
    0 P( _; O2 w8 z" H. r, A
  237.    {
    * r* O6 d4 d% E& r6 v
  238.        WORD dwBaseAddress;. M2 [( @% [; l
  239.        BYTE btMasterSlave;         // Master Or Slave
    ) J7 @& [4 @$ U) |7 x
  240.        bool bIsIDEExist;' g. M! l. _9 l: X% s) T
  241.        bool bIsDiskExist;
    3 C9 l! b: _8 A2 k& V3 F$ y7 ^
  242.        switch(nDrive / 2)* y# J7 i, Y2 P6 ~% P
  243.        {, D; G, g) c, d% i$ ^7 j' j
  244.            case 0: dwBaseAddress = 0x01F0; break;) v& B" A) a) K' B
  245.            case 1: dwBaseAddress = 0x0170; break;% I6 n' F) |) Y' z& W9 }3 {4 p  ]2 I
  246.            case 2: dwBaseAddress = 0x01E8; break;7 r! \5 C7 V$ k. k/ C. w
  247.            case 3: dwBaseAddress = 0x0168; break;; K5 a* N" M8 t' n& B9 u& ?
  248.        }
    9 N' C5 Y) ~4 d4 V! {2 d

  249.   y) [8 ~# f, P3 ~
  250.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
    ; ]( L% b, L% T  c1 x

  251. 1 a% S1 u/ r+ A$ R
  252.        // 进入Ring0
    7 t) k, w, q+ m- X
  253.        bIsIDEExist  = false;
      @" ]7 ]% Q: \; _7 @
  254.        bIsDiskExist = false;
    + O) h( z/ \8 U& @7 V
  255.        ZeroMemory(wOutData, sizeof(wOutData));
    1 k8 l7 B) D8 ~, v4 g

  256. ! {* ~! N* x- F
  257.        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,3 q* H7 x, j  `8 w0 G; j" N2 C
  258.                bIsIDEExist, bIsDiskExist, wOutData);5 U$ i8 ]1 y4 B5 f8 W3 f4 C
  259. # J& C4 B, p9 d7 j3 V' i" x
  260.        if(bIsIDEExist && bIsDiskExist)/ T3 V9 N& N" [- H6 d
  261.        {9 P: K! c. V! A3 w
  262.            DWORD dwDiskData[256];
    1 x* X$ P( N3 E) j
  263.            char  szSerialNumber[21];- W$ D) j" ~- l6 g
  264.            char  szModelNumber[41];
    # m' b& n" \" {( [1 g! ?
  265. 4 B: h+ t7 I& {7 M
  266.            for(int k=0; k < 256; k++)8 ?( j- ^* T1 C( y8 r+ |8 y
  267.                dwDiskData[k] = wOutData[k];
    1 T6 p2 t& P' C* O2 x2 t
  268. $ E, G1 L2 q) i2 F
  269.            // 取系列号3 n6 ?0 d, V* ?/ v
  270.            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));# r8 r; s; V& C9 L9 V2 U7 e
  271.            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
      B7 h3 Y. V7 F- @
  272. 0 f9 J& y6 l% L: N6 s3 e7 i, ?! m
  273.            // 取模型号/ z' b# a* y6 }! ^' t. O
  274.            ZeroMemory(szModelNumber, sizeof(szModelNumber));
    & E# x: B' j6 d- o
  275.            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));2 s! @! p% q+ ]. I( V5 j4 m. I
  276. % R0 r# s* q9 j! n5 a
  277.            pSerList->Add(szSerialNumber);" E! q" r# ^) q3 A& `
  278.            pModeList->Add(szModelNumber);
    6 Z' x- h& R, z* t- h
  279.        }1 w& M$ A* r8 ]/ D. }+ l- g! `7 [
  280.    }1 P; `/ U$ w0 |
  281.    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
    * g: V# w1 e( Q
  282. }
      I3 o$ h. h& F& V' x
  283. //---------------------------------------------------------------------------+ j9 @' [, {( z% K" n/ l% u
  284. // ReadPhysicalDriveOnW9X_Ring0()
    ( O! W) r( D$ L. v7 s* \
  285. //
    ' D* ]& d9 s0 [2 \- p  s# ]
  286. // dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h( ]# Y( L5 J* ]+ y
  287. // btMasterSlave = Master(0xA0) Or Slave(0xB0)
    # K- c9 J8 e6 @5 o0 D- g
  288. //---------------------------------------------------------------------------
    # B: i: r" d3 u8 x
  289. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
    . I6 b4 K- y2 l/ E/ i6 P$ s$ F
  290.        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)* }6 D  v0 ^" M
  291. {8 f* |( |/ T# t/ t0 J- H% a% z4 H
  292.    BYTE  btIDTR1[6];3 j+ L0 m7 s% M+ @
  293.    DWORD dwOldExceptionHook;4 y$ V- o  [/ Y* r6 V
  294.    const int nHookExceptionNo = 5;( G2 X7 e" e4 v$ ]  _( l

  295. : X: T; K& D* t* x" A
  296.    BYTE  btIsIDEExist = 0;
    : P. v# s; ]8 n/ Y9 O
  297.    BYTE  btIsDiskExist = 0;# j+ n& g4 ^. D. h: R8 _1 C+ i
  298.    WORD  wOutDataBuf[256];
    7 J( q* X7 C, v: h" p7 i. ]7 {1 ?, g

  299. 7 y( L1 H9 D) K' X, f1 o" V
  300.    BYTE  btIsFirst = (BYTE)bIsFirst;, l9 }/ ?- H- }
  301. 5 {' o+ \2 p4 F3 r4 g& i
  302.    const BYTE btBit00 = 0x01;) d  a0 l. R$ d9 L* B8 x
  303.    // const BYTE btBit02 = 0x04;
    4 L1 w4 q! \. _
  304.    const BYTE btBit06 = 0x40;
    2 r+ A& ^" y2 p
  305.    const BYTE btBit07 = 0x80;
    - j. `; Y* r9 Z3 {- C  S6 S
  306.    // const BYTE btERR  = btBit00;
    - g- d) K- y  z+ b6 X; K
  307.    const BYTE btBusy = btBit07;: ]1 Y( ^( Z% y2 n; V4 ?
  308.    const BYTE btAtaCmd   = 0xEC;
    6 `4 @6 a% y7 b* s# c7 ^
  309.    const BYTE btAtapiCmd = 0xA1;
    : h, ?; r0 J8 Y2 V; [. G% l3 W
  310. 2 W! o  C) o/ \2 L9 t; a  z
  311.    __asm; p' _& b, o) V
  312.    {% W- B0 z+ l+ }! \. K
  313.        // 必须先执行这条语句+ \% |9 _7 j+ {+ T) }4 T  x; T
  314.        JMP EnterRing04 l. n0 C9 o* m( r' c( M3 C& t

  315. 5 w1 m5 w# D( L: @1 N
  316.        // 定义过程
    + Y, F0 j3 E) j9 S
  317.        // 等待IDE设备直到其不为忙为止
    $ H& c8 v/ K2 i+ v8 O& l
  318.        WaitWhileBusy proc
    ; G! C9 V9 e7 X1 \/ }

  319. + }. |9 K2 W$ J5 w9 w
  320.        MOV  EBX, 100000
    4 k. D8 c3 Z- l7 ]" }
  321.        MOV  DX, dwBaseAddress) u1 G, ]3 v2 o) ~9 c/ s# E
  322.        ADD  DX, 76 _1 J0 I9 Q" L

  323. 3 }% B' U- L9 P  b" E
  324.        LoopWhileBusy:
    . ?. b# c. v  e' ]1 H: ^
  325. ) f; X. s% ?+ g, k# L1 e: m+ H
  326.        DEC  EBX
    7 V* U3 n& d$ x
  327.        CMP  EBX, 0
    2 s) C2 }' Q  l+ i
  328.        JZ   Timeout: K8 R& A7 _1 ]/ K
  329.        in   AL, DX' T3 l/ ?* f  \  }4 s
  330.        TEST AL, btBusy7 t) ~& a% C* G' _' f$ b) ?4 C
  331.        JNZ  LoopWhileBusy
    ) e9 t8 |0 S1 w* ?4 u" I
  332.        JMP  DriveReady
    * i* e% R+ R9 ]" O0 W
  333. ; b  r; ]4 R) t9 X; ?7 M  }
  334.        // 超时,直接退出" E* b: l2 n. s8 A4 |
  335.        Timeout:$ w9 h! \- `8 Z7 L; p7 r
  336.        JMP  LeaveRing01 l) k$ \* O! d/ N
  337.        DriveReady:
    ! f; {4 u- V% C/ r* L  _6 T
  338.        RET9 E1 V5 E8 T$ y; U- L% q! F
  339.        ENDP   // End of WaitWhileBusy Procedure
    ) Y9 o. n1 t8 q  v, S/ D4 Z) g* M

  340. ; m! ]  C) H1 k. l, n7 w" G- u
  341.        // 设置主盘和从盘标志1 g2 f/ i1 ~  ~3 d. l5 l0 I  U1 l
  342.        SelectDevice proc- I/ L8 C) Z; M, z

  343. 3 I+ h+ _9 O2 C' O( |
  344.        MOV  DX, dwBaseAddress
    0 f7 j8 ?) B7 g! _' i: S
  345.        ADD  DX, 6
    - Y. {& p5 z9 i: Y
  346.        MOV  AL, btMasterSlave" l; N! m6 T1 X; K" I2 j, d( L
  347. ' ?* R# C; A5 E
  348.        out  DX, AL
    5 a1 ?. S( Q, y' E+ ~! S& n
  349.        RET: y* ~1 h# t8 s5 I- _2 I
  350. " H  o! R$ y: ?
  351.        ENDP  // End of SelectDevice Procedure" ^( W" m$ a$ S8 t% B
  352. $ S+ f- E9 Y% g+ o
  353.        // 向IDE设备发送存取指令
    : y6 J$ F0 D+ a" r% e! Y6 Y! T
  354.        SendCmd proc' E. s, `; g8 F$ \$ a$ t

  355. " w( e8 _( U, S* S! i$ I
  356.        MOV DX, dwBaseAddress* X& |( I4 ?2 J/ C7 e
  357.        ADD DX, 7
    ) V  G" |, b0 M2 x0 N3 B" z4 C, C
  358.        MOV AL, BL // BL是主从盘标识,在过程外设置
    5 P9 }- s" A! y: b2 x
  359.        out DX, AL
    ! J) m6 e  Y$ a7 `, p  z1 n
  360.        RET4 W5 y( Z6 r& v) \; H6 Z$ K$ {: I0 g
  361.        ENDP  // End of SendCmd Procedure- F/ o3 e1 O  A. V" ]' W

  362. 5 a" |8 x! G% R+ [  n" S" J
  363.        // Ring0代码% N0 E& L% ]+ g' a3 l  S
  364.        Ring0Proc:  {. n! f: x3 T: G! M3 W
  365.        PUSHAD
    0 G1 q' r% {. `" @6 ^
  366.        // 查询IDE设备是否存在& i* {9 h* Z9 a% F
  367.        MOV DX, dwBaseAddress
    : {0 ?( c, r- T2 ?7 V5 A0 P
  368.        ADD DX, 7
    ) b& l1 f/ J; H- U
  369.        in  AL,DX+ i; r& E4 ^' A( V0 J

  370. 2 A  ]; d; v6 K! x
  371.        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回' |5 F: F/ Y5 ]* B; n; A8 v
  372.        CMP AL,0xFF. e) p5 {! d4 e- ^
  373.        JZ  LeaveRing0- J6 Z3 u) @) I
  374.        CMP AL, 0x7F
    2 D" L/ e# l% H9 c
  375.        JZ  LeaveRing02 j/ C2 X8 j; \% O2 @' Q/ {

  376. : p3 j* v* `. F
  377.        // 设置IDE设备存在标志% B( J* d8 U: q+ a% d/ j
  378.        MOV btIsIDEExist, 1& w& c5 u1 |1 O% ~/ r

  379. 4 `& V+ n" D6 t' N+ T/ A$ x. B5 n
  380.        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
    : \- V0 X8 s* J$ T% u/ {7 W0 R
  381.        CALL WaitWhileBusy+ @3 k% L8 S7 U2 Z
  382.        CALL SelectDevice9 x9 {1 W1 B% q6 \5 b( _$ H& d4 c& ^

  383. ! W6 G5 \6 D- O+ |4 Q. e4 R+ a
  384.        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏+ m+ R- a% G" \, a
  385.        CMP  btIsFirst, 1" i2 [9 P. m  I  E% R
  386.        JZ   LeaveRing0
      H' S# k! Y' ^
  387. ; ~% u" [8 b) O' ^1 w
  388.        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
    2 t$ N1 O* K( z
  389.        CALL WaitWhileBusy
    ) t5 K! \# y' m3 Y! V  Y( f* h

  390. 5 o* ?/ V- U' [, x
  391.        // AL的值等于cBit06时,不存在驱动器,直接返回( P) p" l3 b) n% y( B; ]% |
  392.        TEST AL, btBit06
    ; H- b! g- F6 J, B* `
  393.        JZ   LeaveRing04 J  v# ]& W  ^- `5 I( J" Z% ?
  394. 7 O3 E4 b# P, J. j
  395.        // 设置驱动器存在标志
    ( H& a: @2 D. Y. ]" U
  396.        MOV  btIsDiskExist, 1  }% |; k: k  N, b
  397. * ~5 \, |( Y$ C3 I; J; x/ n  j* x
  398.        // 发送存取端口命令
    ! U2 [. |, M; `6 Q
  399.        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,* }" u% |1 V  a. f
  400.        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
    4 H; P9 a2 P2 z+ A' V
  401.        CALL WaitWhileBusy
    , V; N7 ~% L. J3 t$ M
  402.        CALL SelectDevice    // 设置主从盘标识
    8 G6 m5 v4 Z7 J! ]
  403.        MOV  BL, btAtaCmd      // 发送读取命令, A" C2 I0 O5 P
  404.        CALL SendCmd( f1 D4 R: g' S& r! o; }% M5 Z; ]0 l+ f
  405.        CALL WaitWhileBusy% c8 z, n: i& }2 `/ G) E

  406. - {; w* y1 ^+ j7 j3 a
  407.        // 检查是否出错$ [: G# I8 |# K" Y3 P3 c
  408.        MOV  DX, dwBaseAddress: {$ B: M4 I, \) u# A9 r! @2 L
  409.        ADD  DX, 7* j) }% R7 g; I+ b

  410. 1 _4 b& R# z, k1 H, {5 y
  411.        in   AL, DX3 O  a) _) p4 X( P& V7 g' x3 w9 q
  412. ( I' X9 U# ^: \/ O1 E+ u7 ]
  413.        TEST AL, btBit00
    ' ~( B$ ~8 e/ i' a8 B
  414.        JZ   RetrieveInfo   // 没有错误时则读数据& M  ^( F4 r1 @: b* O) J3 g
  415. ; V& l% N& w+ {; s
  416.        // 如果出错,则进一步尝试使用ATAPI设备命令
    $ w' P" n) D; Q0 h. ?9 X* T- a! K
  417.        CALL WaitWhileBusy  f: H, a6 e* w6 G
  418.        CALL SelectDevice
      a& E" F- g0 |0 l! ~! l
  419.        MOV  BL, btAtapiCmd
    ) y% C, ?7 B: n( p! w
  420.        CALL SendCmd
    * R- y/ D' t: |3 P  ?
  421.        CALL WaitWhileBusy
    . L5 ^" ^: ^" @" i
  422. 4 D- I7 A! C; M
  423.        // 检查是否还出错4 }8 {9 h0 A$ C% T, ?( e5 G# M! T
  424.        MOV  DX, dwBaseAddress2 q5 H& Q' y& G* [: m
  425.        ADD  DX, 7
      a& S$ i, J8 A; W9 U. J) i6 Q, n
  426.        in   AL, DX/ Q8 [9 J+ j$ w% H
  427.        TEST AL, btBit00
    * i. ?1 j9 h- o9 X% H" D
  428.        JZ   RetrieveInfo   // 没有错误时则读数据
    / D- p5 F- B+ k# ~5 u
  429.        JMP  LeaveRing0     // 如果还是出错,直接返回, L$ i, J9 Y! b) e( M: F1 c# s
  430. & v7 O! P' Q7 G  s* u  h
  431.        // 读取数据8 d+ x7 r# x8 \/ p6 ?' P: F
  432.        RetrieveInfo:2 S- d7 `$ O( I- {& g9 s3 n
  433. % ~( O. D0 F4 _1 T
  434.        LEA  EDI, wOutDataBuf
    / t# \  f2 ~5 K
  435.        MOV  ECX, 256
      }+ W& A7 V- w
  436.        MOV  DX, dwBaseAddress( y; z& a4 Y. y1 @' K
  437.        CLD
    6 w  @$ c* }% Z- }/ t* H6 U6 V  e
  438. " Q7 T, {+ J) F% z( R
  439.        REP  INSW
    $ F8 f& |" s& W9 x9 d# s
  440. " h, o6 V, w4 n3 G
  441.        // 退出Ring0代码
    / P3 X# b) E  V
  442.        LeaveRing0:6 {8 B8 [  j. |! g, o5 ]$ v; }5 e

  443. * d, U6 t* O8 O% g/ M/ l  t- S
  444.        POPAD
    / [% j/ [6 s; l% }: Z
  445.        IRETD
    % y4 t$ J3 d/ D$ m8 U
  446.   N) x1 D2 m( Z6 F$ B7 L8 _2 e
  447.        // 激活Ring0代码
    2 y1 P1 s$ V3 v
  448.        EnterRing0:3 M6 ]( G, n( W, F

  449. 1 Z+ n" ]1 ]& j3 X+ Q
  450.        // 修改中断门) ^) ?% @+ Z3 ~9 {1 n: d6 K
  451.        SIDT FWORD PTR btIDTR1
    4 j8 ]5 a: j+ {2 W5 [
  452.        MOV EAX, DWORD PTR btIDTR1 + 02h; F% `, v7 w+ K, H
  453.        ADD EAX, nHookExceptionNo * 08h + 04h
    7 x7 L( a3 N2 m0 n6 ?# h3 X
  454.        CLI
    8 R, m' @( z8 F

  455. 5 r9 I3 r8 p2 E% r$ U% T$ t
  456.        // 保存原异常处理例程入口3 H: w' |3 C: f( S2 j- K% E
  457.        MOV ECX, DWORD PTR [EAX]
    / a, h9 o7 m+ S" s
  458.        MOV CX, WORD PTR [EAX-04h]1 z3 Y; [; Y( {6 @0 j% _9 w
  459.        MOV dwOldExceptionHook, ECX; {5 `+ x/ F+ w2 Z- j
  460. + s4 I1 A5 F0 P
  461.        // 指定新入口8 B# N: I/ M4 }$ D+ q1 b5 f8 X/ W
  462.        LEA EBX, Ring0Proc, Z2 c9 u  ?5 |, l8 E: N% H4 U
  463.        MOV WORD PTR [EAX-04h],BX
    ; k, a6 h1 k- U0 e/ y( s2 o* F
  464.        SHR EBX, 10h* v' J# R5 h! l
  465.        MOV WORD PTR[EAX+02h], BX
    . P1 C4 [; R8 G  s! x- N
  466. - z1 C* |) s/ v5 v& C
  467.        // 激活Ring0代码
    9 y2 O, C, j2 w. }4 y
  468.        INT nHookExceptionNo8 n  S+ h2 b5 D" [* f+ x

  469. 3 B4 H, `9 x' g- q
  470.        // 复原入口, y. D9 _' }& \+ {( T
  471.        MOV ECX,dwOldExceptionHook
    ! f! b0 j' k  e6 u# M/ Z
  472.        MOV WORD PTR[EAX-04h], CX" `" w& {, u1 Q9 e$ g4 a
  473.        SHR ECX,10h
    % }  ]3 |* M' t- M% _8 k
  474.        MOV WORD PTR[EAX+02h], CX) }& u% S9 o; h' R- I6 K
  475.        STI4 d. D% I( g( [/ G4 i$ I* L
  476.    }
    - K7 L& F3 ^1 n1 U
  477.    if(!bIsFirst)
    / k7 \# U& z. t1 Z
  478.    {& s9 H& c' `$ U& P2 E: g( H
  479.        bIsIDEExist  = (bool)btIsIDEExist;
    4 P, n3 S3 g. o& {) `( v* C
  480.        bIsDiskExist = (bool)btIsDiskExist;# _( Q0 O% b% p0 l6 B6 G
  481.        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
    % s$ k9 V+ g: c2 `; ]0 x$ k4 G
  482.    }
    5 Y  M, y3 g! z! E
  483. }
    , J# A9 {2 Z' s. U8 N
  484. //---------------------------------------------------------------------------
    3 _8 U% f" }4 Y) m& S" X
  485. // 调用方法:
    2 g3 h: E5 m5 _- ?
  486. void __fastcall TForm1::Button1Click(TObject *Sender)
    9 q5 D9 d4 H. ]$ i. f7 n2 Y4 l, W
  487. {
    ' J1 D) J" A0 q! u4 T/ u6 ^: y* R
  488.    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);  S# t4 e  Q. a3 x4 R
  489. }
复制代码
发表于 2005-8-15 01:00:45 | 显示全部楼层
晕乎乎。。。怎么看8 洞阿
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-8-13 21:31 , Processed in 0.019912 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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