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

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

[复制链接]
发表于 2005-8-11 11:42:04 | 显示全部楼层 |阅读模式
  1. #include <WinIOCtl.h>1 t, t8 U$ N& B* c
  2. #include <stdio.h>
    3 a% V+ C9 V# N2 Y$ x: b9 F" w

  3. & [5 O4 k7 q- `4 U
  4. #pragma inline
    . S: f: i% U2 n5 A
  5. //---------------------------------------------------------------------------% F8 l5 }$ y! e
  6. // IDE NT/2000/XP专用变量
    / X1 k6 w- Y. P1 }* f
  7. #define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS+ R% u, F3 q% W( o3 k
  8. #define DFP_GET_VERSION         SMART_GET_VERSION
    0 Y3 M$ c* `" n& m
  9. #define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
    * t! G6 m' O2 z6 F& O) W
  10. #define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
    / B* N: ]( A/ Q* K4 L7 ?9 C) |8 X
  11. ) z' H" l1 O; S
  12. const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令
    3 r0 J; Z8 p& W  H  }* x! w
  13. const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令, M* \( V, H* @9 K. b$ J& y7 y

  14. / B) }+ X8 c, ]+ {1 I+ q, t9 i' N
  15. const int MAX_IDE_DRIVES = 4;7 a/ h6 a* Y$ A: R0 T

  16. . w$ ?3 A0 s! g# F" v
  17. // SCSI专用变量, V5 [& F( b; `
  18. const DWORD FILE_DEVICE_SCSI             = 0x0000001B;0 F! u* ~7 {  I
  19. const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
    % S& \1 ?6 D# W- n' Q0 S
  20. const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition: i  ~/ t8 ?1 i5 J7 M' b3 ?% W
  21. const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;4 N$ l9 @  A# t0 N4 I( h; F4 o8 `

  22. ; A; E3 m# W2 z
  23. typedef struct _SRB_IO_CONTROL
    . }; V  b9 q8 W/ F" o/ q0 G
  24. {* C  y! D3 {# y$ ?+ p
  25.    ULONG HeaderLength;9 e( D. s9 J. u
  26.    UCHAR Signature[8];
    ! X' ^' S0 f( m" o) L+ m. \8 e! ?
  27.    ULONG Timeout;
    4 X% L# J2 W1 H2 N; H1 G
  28.    ULONG ControlCode;
    7 _0 b+ d$ Z+ g
  29.    ULONG ReturnCode;
    / ~1 p8 _% u! n+ X- C
  30.    ULONG Length;
      H  E/ j* u2 _0 J% d% K6 r
  31. }SRB_IO_CONTROL, *PSRB_IO_CONTROL;) R3 Z$ n. k  D- z
  32. 9 ~( C9 ]; y5 v
  33. // 读取的主函数
    + G- m" t' D0 q* F9 X" B2 A
  34. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
    7 s9 a0 {( j! A% i( `8 ?
  35. " F7 ]  t( d0 h
  36. // 辅助函数
    , G: |$ Z. z' A" b
  37. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
    1 ~; y. p' }+ V' G7 G+ @& {( ]
  38. // NT/2000/XP函数
    . o6 I* r8 [1 E, ^
  39. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
      b0 ^% i% E- L+ K
  40. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
    ) v! I8 H$ s* D9 d/ Q8 _+ Q, v! ?
  41.        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,$ c! V. T5 l# q* q
  42.        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);* U  s$ V! I8 [, f- P- j
  43. // Windows 9X函数- [. p. H7 X+ {! p8 i: K. h2 ^
  44. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);+ x, X- `" y' ]4 [5 }+ q) i
  45. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
    & c! c2 s% L0 s. v2 j# T& R
  46.        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);! y1 Q8 n, g$ B* K) D' \6 d
  47. : `+ q# [& c8 ]
  48. // SCSI读取函数(for NT/2000/XP)7 y' u6 R4 W$ E. j9 Z
  49. String __fastcall ReadIDEDriveAsScsiDriveOnNT();
    - I3 Z: V) {1 |0 m, `
  50. //---------------------------------------------------------------------------' S4 Y$ K; I! H
  51. // ReadPhysicalDrive
    + S; H# O9 N$ o0 c' e7 R
  52. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
    & H0 D; M' j+ j" R: j
  53. {
    + F$ n! p+ j! m4 S
  54.    switch(Win32Platform)
    3 s  X# K8 Q+ b# x/ E- K$ D' j
  55.    {4 J7 Q  ?( {$ P- ]; E" m2 R
  56.        case VER_PLATFORM_WIN32_WINDOWS:5 z: _- i. b: n; W+ i
  57.            ReadPhysicalDriveOnW9X(pSerList, pModeList);& g: a/ o* u8 [- ]0 S
  58.            break;
    # Z8 L8 X; e) o4 _: H! q2 w8 W0 L! P
  59.        case VER_PLATFORM_WIN32_NT:. }0 i% D# _5 B- g. r5 E
  60.            ReadPhysicalDriveOnNT(pSerList, pModeList);
    9 B8 }% g7 v/ N
  61.            break;
    1 L: c; l, ]4 T" F& V7 F
  62.        default:
    & H& c; {- b# l4 [
  63.            break;# M8 R2 V6 P) W% k
  64.    }
    : z, w5 H( y7 s  n& K$ r% {  C  J
  65. }
    $ h0 p7 k- ?% q
  66. //---------------------------------------------------------------------------
    - j) M& ?$ s' ~( H. b
  67. // ConvertToString  [9 V1 G  U( w& Q
  68. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)7 L& L2 b8 |2 M* K/ `4 R3 e
  69. {: ~, M1 l2 h9 N' h9 d1 Q+ t3 ?
  70.    static char szResBuf[1024];
    / z- J! U# g! _  J% Z+ B
  71.    int nIndex = 0;
    * |. @/ V1 v, M+ u% Q- k7 M
  72.    int nPosition = 0;; _/ B: i7 T% ?4 C$ C
  73. ) @1 b; H+ B2 C/ Y& k) F
  74.    // Each integer has two characters stored in it backwards
    ( U4 f8 {, U* L: }, P( T7 C
  75.    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++), Y2 B9 l3 U5 ?0 Y- i2 m: J6 k
  76.    {
      _" P. W, e4 t: K0 {4 c/ a
  77.        // Get high BYTE for 1st character
    - `: Y5 K; [; B( H& f6 _0 O
  78.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);: t& i) U. S( ~0 ?9 ?/ g( p" N
  79.        nPosition++;7 Q- J: m& a7 A, R1 t1 a

  80. & R* V$ n; O: a& g8 [% w  o. m
  81.        // Get low BYTE for 2nd character) I- [  g$ \) J! I
  82.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
    $ L6 W- o) P0 H6 Y" m
  83.        nPosition++;
    1 C6 r8 e" h/ R8 i. y) _
  84.    }
    9 y  ?6 h9 ^  T7 o# A" Y

  85. ' L9 K1 W% b4 W: i
  86.    // End the string' X! H$ Z8 {3 [4 Z* Y
  87.    szResBuf[nPosition] = '\0';
    + V2 {4 l% P$ T

  88. . _; c" O# }" z+ {7 M, b8 ]: k
  89.    // Cut off the trailing blanks1 i  w3 X3 o6 w; p8 i- N
  90.    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
    7 `' o% b# Y! o* z
  91.        szResBuf[nIndex] = '\0';) ^8 G3 F  W% M& O, U2 [9 m
  92. $ V; d+ ]0 B  j/ N2 H
  93.    return szResBuf;
    ; _  D7 B# j% ?3 B4 q
  94. }( E3 o8 ^! i9 U3 Q  ^$ [3 F1 A
  95. //---------------------------------------------------------------------------
    ( P/ Z0 D8 Z- \1 j' H
  96. // Winndows NT4/2000/XP 代码
    ; x* S  y4 t$ e. o
  97. //---------------------------------------------------------------------------8 V# o+ ~! o* a$ N2 u" \
  98. // ReadPhysicalDriveOnNT
    - O% a" N5 Y* N$ H6 Q3 k( ]2 _% J: Z! d
  99. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)- n( ?. O( Z1 K
  100. {
    2 d' \3 C. L* Y9 }" s4 z
  101.    // 输出参数& z! C% C" p6 j9 p1 P
  102.    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];6 H0 Z; C& N" ?0 F

  103. ( w7 W# ?* n4 C
  104.    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
    ; g9 e, S1 M% R% ~: v2 |3 [1 `/ s
  105.    {
    7 g' ^  Y1 z; o8 t
  106.        HANDLE hPhysicalDriveIOCTL;
    ( q" ~8 g% C2 L6 u8 \7 O7 L; [
  107.        char szDriveName[32];& f, P( R, B1 V

  108. 3 l) e4 `' j3 a* Q3 m8 d
  109.        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);& s& C) A- E/ x# w
  110.        hPhysicalDriveIOCTL = CreateFile(szDriveName,
    ) d; B; ^$ T( S( s
  111.                        GENERIC_READ | GENERIC_WRITE,
    ( o/ |' V' E+ Z6 Y- H
  112.                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
    . @8 R) X+ B$ k2 A; i& \- m, ~
  113.                        OPEN_EXISTING, 0, NULL);
    3 K) C8 }) f) G

  114. ( T  w1 Y* F4 }4 x# A4 N
  115.        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE), h/ e( u4 L2 o1 }8 i" Q
  116.        {
    ( N1 e6 E9 z4 `
  117.            DWORD dwBytesReturned = 0;
    0 K% Z6 \  @, m/ Z( U
  118.            GETVERSIONOUTPARAMS gvopVersionParams;, m0 V7 U2 n5 P/ G
  119.   S7 K- X0 p7 R) r
  120.            // Get the version, etc of PhysicalDrive IOCTL
    ' Z% f- _1 ?  U3 o( H% z
  121.            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));% m5 |! [0 t* b) V

  122. 5 O; \, [, [& z6 u. A
  123.            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
    % p- u) i6 E/ O% ]# g8 b
  124.                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),5 w' Z8 b$ Z2 Z( O2 f1 d( A
  125.                    &dwBytesReturned, NULL))
    : T2 F2 I6 d; t) g" T% ?
  126.            {: \; a! I5 C' r, j1 f! Q( }
  127.                continue;0 S% h  w3 R* D" V  @. L
  128.            }8 P( v4 u- d. T8 H

  129. ; V. Y3 z- e" q& c
  130.            if(gvopVersionParams.bIDEDeviceMap > 0)
    6 f' C4 }( r) }8 ?& z% U! f
  131.            {* @$ i2 V# j# v9 w0 E" o
  132.                // IDE or ATAPI IDENTIFY cmd
    ! e) y+ ]; ?+ Z& s6 f0 K
  133.                BYTE btIDCmd = 0;+ ^& [, U: g- t1 Q1 s! y9 j% s
  134.                SENDCMDINPARAMS InParams;3 B/ x$ g1 s' w6 d5 G$ Q+ W3 q
  135.                // Now, get the ID sector for all IDE devices in the system.
    8 Z8 m& }+ w  `2 [! U
  136.                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,9 I7 }: H* b  Q. [0 }. K
  137.                // otherwise use the IDE_ATA_IDENTIFY command
    ' s7 w  n+ Q3 e( C# L8 T
  138.                // 具体所得结果请参考头文件中的说明
    ' R  |" s0 z& |: A4 X
  139.                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
    7 E- B  d( V  g. H& y/ d  ]) P2 ?
  140.                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
      |* u3 g% S7 B' \% I( Y, _" k+ n, ?$ j
  141.                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));3 G: Z7 w4 |! G) ?
  142.                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
    ; p# b2 k6 Y7 _- H. n( q
  143. + q9 {: H( A" B5 J% c3 k9 V
  144.                if(DoIdentify(hPhysicalDriveIOCTL,
    ! k0 K; b7 K) l& w
  145.                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
    9 q5 u  K/ K1 X1 G0 {
  146.                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))) Q; x+ E4 P2 C: R
  147.                {# b. |2 w# l/ @9 M
  148.                    DWORD dwDiskData[256];. L; |1 W: R' u
  149.                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件4 u, c4 }0 g1 q8 @- E# f# u+ i
  150.                    char szSerialNumber[21];
    / b9 E; \* ]+ U1 u3 ?
  151.                    char szModelNumber[41];, @8 M9 h7 k( v, R7 c. ?
  152. , Z& R( {0 k: d
  153.                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
    & @9 v7 J: k- [% Y( S
  154.                    for(int i=0; i < 256; i++). f  j) N" j1 \& ]/ K
  155.                        dwDiskData = pIDSector;
    1 ?2 |( S" [) E, J/ W' A
  156.                    // 取系列号4 z* S6 L3 Q6 c# S# c
  157.                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));5 t  P, @% H6 Q0 q' H0 s
  158.                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
    ; H( O# f" Q: a# Z4 c& V" w- H$ w

  159. / ?/ V7 d; t  V# d! q, P7 `) }
  160.                    // 取模型号
    ) ^7 C) j: f2 o2 @  y7 m
  161.                    ZeroMemory(szModelNumber, sizeof(szModelNumber));. z* A" }& P4 ~& C5 G9 N4 c- P
  162.                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));4 c- C& f9 Q4 \7 }* g% x$ p7 d8 J
  163.   o% a4 ], q0 Y8 }$ m" @
  164.                    pSerList->Add(szSerialNumber);; A+ b8 N! _; V1 c
  165.                    pModeList->Add(szModelNumber);
    7 X! g, L) P8 @% l
  166.                }
    # Y2 ^2 u1 A) q7 X0 ]
  167.            }+ q2 @+ p: k; O  C5 G  j
  168.            CloseHandle (hPhysicalDriveIOCTL);- n& N. Z+ w+ s
  169.        }
    0 p0 c# z# ?# I, p
  170.    }& o$ T, M% l8 s
  171. }! q" x, j5 Q" `5 E  u8 Y
  172. //---------------------------------------------------------------------------
    9 N; c9 x$ ]% p' Y* E! O" E- m8 m4 n
  173. // DoIdentify3 n0 `6 H8 p7 o4 Y( Q9 J* e
  174. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
    ) f  M* ^5 Z! A7 [7 r% E
  175.              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,9 W: r3 {' d* U, f
  176.              PDWORD pdwBytesReturned)
    8 Y* a' G8 N1 q
  177. {" S& U/ q$ g5 z8 E# @
  178.    // Set up data structures for IDENTIFY command.& O$ a& Y8 M) d
  179.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
    % [  K8 X. w9 c1 {3 O0 k$ H5 p* D
  180.    pSCIP->irDriveRegs.bFeaturesReg = 0;
    0 s" z* D# u4 V$ W
  181.    pSCIP->irDriveRegs.bSectorCountReg  = 1;
    8 v  H* g/ w7 H4 l: V% a. F+ G
  182.    pSCIP->irDriveRegs.bSectorNumberReg = 1;
    * S$ v9 M, O. h$ @0 E3 U
  183.    pSCIP->irDriveRegs.bCylLowReg  = 0;( i+ U3 {" n% L; c0 S: ~
  184.    pSCIP->irDriveRegs.bCylHighReg = 0;3 l5 a3 i9 l8 ]' H& z
  185. + ~2 e! d- D6 \. [* Y9 M4 p
  186.    // Compute the drive number.(主盘和从盘所对应的值是不一样的)
    8 A9 c' D# c6 g6 Y% q+ V9 U
  187.    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;4 f' g, N8 ]8 ~
  188. $ ?, d" T2 D0 S' Q& k
  189.    // The command can either be IDE identify or ATAPI identify.) R2 m% }3 N" N$ D  [
  190.    pSCIP->irDriveRegs.bCommandReg = btIDCmd;
    9 ^1 c2 ]8 p1 J  Y* ?2 v* G
  191.    pSCIP->bDriveNumber = btDriveNum;$ r% s( i! H4 ?0 S
  192.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
    * s( p$ u& u& s

  193. + H3 ~" \  Q( e; N! S: t1 a& U
  194.    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
    - r& U/ h* e5 l4 C& D4 a* P% `
  195.           (LPVOID)pSCIP,
    ( V+ g' I7 H( v, n- a& |' S
  196.           sizeof(SENDCMDINPARAMS) - 1,
    & k$ i$ ]4 _$ N, m% _4 ]
  197.           (LPVOID)pSCOP,
    . _, O( z7 Q# E; H+ A  C! {
  198.           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,' j5 b- y: @% g+ {, E
  199.           pdwBytesReturned, NULL);
    / E$ C7 h6 a1 G1 z, {
  200. }
    ( b! K$ N7 a% Y& W/ [
  201. //---------------------------------------------------------------------------
    9 u. }# T  E. v$ e$ z. i
  202. // Windows 95/98/ME 代码5 J4 ~7 t' u, ^0 q3 Y
  203. //---------------------------------------------------------------------------7 d# ?4 y* U7 W$ G2 g
  204. // ReadPhysicalDriveOnW9X
    & v2 x, N' P4 d) h+ ^
  205. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)
    " S+ M7 p2 l4 X8 \
  206. {
    & Q& y! \: `$ t1 j, M$ D
  207.    WORD wOutData[256];, g9 J) Q" J+ {$ E: c5 v8 J
  208.    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);; T- i# E6 U  P: r7 i$ S. L4 s
  209. 2 k* b; @  A4 p' d8 O
  210.    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
    # W  @( }  M1 X+ i( I9 K
  211.    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
    8 h; F: [8 u! o6 C. i- b( O
  212.    // 避免蓝屏的出现。(期待高人能指出原因)
    & M5 `& X2 G; w0 D8 u8 x
  213.    for(int nDrive = 0; nDrive < 8; nDrive++)( y1 `( m+ Z/ u7 R# {+ i' i% M
  214.    {5 x2 m2 b7 M% }* ~4 a/ K7 l3 E
  215.        WORD dwBaseAddress;" X: k, \! f4 I1 B$ X* U! l
  216.        BYTE btMasterSlave;         // Master Or Slave
    2 I# u# D0 j6 K5 x* @5 M4 X. j
  217.        bool bIsIDEExist;
    / [# x, D' B2 m
  218.        bool IsDiskExist;
    ; B% O: J( y5 l$ F! \

  219. 9 f2 D/ j" P6 m# \8 {
  220.        switch(nDrive / 2)) O5 e9 f1 O9 Q2 O/ Q
  221.        {
    # j- w" w' ?* w% U' m5 W- I4 ]
  222.            case 0: dwBaseAddress = 0x01F0; break;
    # A4 H% U6 t$ f6 R4 d7 D; U
  223.            case 1: dwBaseAddress = 0x0170; break;# Z" Y, z. \: h$ f2 `9 n8 x
  224.            case 2: dwBaseAddress = 0x01E8; break;
    / K2 q" v& k2 F6 V
  225.            case 3: dwBaseAddress = 0x0168; break;
      J; O, I4 _% [/ y1 z
  226.        }! a" K% m0 w' O
  227. 3 t) c' k/ R) w7 L6 H
  228.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
    , y, d' f0 q  K& h

  229. 1 N0 O/ s. S/ d6 |5 |) w
  230.        // 进入Ring08 ]" [! p  y9 O9 M  k# C' g: R) c7 l
  231.        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,5 N+ ~1 d7 r1 u* y8 ?* l& }& ?
  232.                bIsIDEExist, IsDiskExist, wOutData);0 ]6 b1 k9 j1 c( ^, d1 m2 s. Z
  233.    }8 U/ _3 r  f* _; H

  234. % A7 }* o8 I* O  Y, C% d
  235.    // 开始读取# X1 W( L+ l% e' ~' l
  236.    for(int nDrive = 0; nDrive < 8; nDrive++)
    ' I4 h' H, g( l  r; H" q) d: N: d
  237.    {
    0 D9 H! Z/ @! {4 [) R
  238.        WORD dwBaseAddress;
    : R* F5 D. W. Y/ Y
  239.        BYTE btMasterSlave;         // Master Or Slave
    9 T/ k( c* n! G# U: Q1 u
  240.        bool bIsIDEExist;
    / K( U' H4 I- H8 T& Z5 U  m( t8 C. d
  241.        bool bIsDiskExist;
    7 A( ], M& a# h9 s
  242.        switch(nDrive / 2)
    4 y) D. q5 g- H* \4 o- Q' U
  243.        {/ ^, F7 d2 w! c7 |' d
  244.            case 0: dwBaseAddress = 0x01F0; break;3 _( A; @- c1 p1 W
  245.            case 1: dwBaseAddress = 0x0170; break;
    9 x9 I: f5 j* }8 {+ X  ?" W
  246.            case 2: dwBaseAddress = 0x01E8; break;
    # y( W% c1 a2 X( f8 m% i1 c/ j
  247.            case 3: dwBaseAddress = 0x0168; break;
    9 ~8 F+ S4 S; O- w
  248.        }3 \- e# A* ^: v+ T+ Z8 V- L
  249. : m( z5 w" T8 `; T3 B
  250.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);+ d6 R- s  c* v; `- b" N

  251. 0 {, W0 i6 ^) P- \
  252.        // 进入Ring0
    4 t, `- H2 k3 ]
  253.        bIsIDEExist  = false;
    + ?6 p& k% x/ x6 [
  254.        bIsDiskExist = false;
    . D# ]$ @- {/ L' @2 `, U" f
  255.        ZeroMemory(wOutData, sizeof(wOutData));
    3 j& D, C% ]7 E$ X  o& `; L, `* O

  256. 5 Y* J) K0 `* @6 A
  257.        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,) X. ?! T) l; n; \
  258.                bIsIDEExist, bIsDiskExist, wOutData);& ^7 d. e6 A0 l2 U, O' k6 T
  259. : C9 s, U& m5 j1 H3 M4 C4 x& M8 Z
  260.        if(bIsIDEExist && bIsDiskExist)
    + j+ P. n# n* R8 A
  261.        {) @& l* {* V8 G0 S% K6 g, `
  262.            DWORD dwDiskData[256];
    , H3 p' |7 v  w
  263.            char  szSerialNumber[21];
    3 e& C' `6 |5 x
  264.            char  szModelNumber[41];
    + ?! z! Z7 f! P3 B/ {
  265. & C' F$ P0 D. V$ q
  266.            for(int k=0; k < 256; k++)
    8 l. I" ~1 Y  z1 v7 |0 {; R. r" v
  267.                dwDiskData[k] = wOutData[k];
    % N/ W, u" U; O) d4 l
  268. ) V+ z; C) u. L( z
  269.            // 取系列号
    ! C' w2 s5 }# ?4 u2 H
  270.            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
    / @4 r- J7 _$ b3 r. Q3 l; G5 I
  271.            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
    - Y1 z* O) [, G  L+ f5 c$ w, u

  272. ! w7 @! t) T/ y: n$ K$ Z
  273.            // 取模型号
    5 F* W1 M: M& d4 x
  274.            ZeroMemory(szModelNumber, sizeof(szModelNumber));
    4 R3 n5 [1 C  _* P7 t0 u! \: L5 E4 u
  275.            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
    ) \+ X3 {& ^+ Q3 B2 _2 U4 }

  276. 5 \* u5 K! ^& E4 i2 T6 Q4 S) n
  277.            pSerList->Add(szSerialNumber);# G" ~* G1 S& F& d2 c5 V  ?
  278.            pModeList->Add(szModelNumber);# s" ]% K; b3 f: H
  279.        }
    " @# X: U; M0 }+ D8 l' Q
  280.    }' e. r7 z) M) ?
  281.    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
    8 _. j5 i5 _3 p6 ]; _
  282. }/ T' ?- A! U$ U  z
  283. //---------------------------------------------------------------------------
    ( `# i/ Z0 H  T
  284. // ReadPhysicalDriveOnW9X_Ring0()/ ~9 w# M- X# F5 S% v
  285. //
    + H5 m" O- d$ z8 b" w, t
  286. // dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
    ' F6 J4 m! g# O- H8 e
  287. // btMasterSlave = Master(0xA0) Or Slave(0xB0)
    % Y# ]; \) v7 _( C+ H
  288. //---------------------------------------------------------------------------  U1 J2 D! W# u# _0 s
  289. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,6 N8 m# Z& V! |$ {& c7 u
  290.        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
    0 R! L# g5 ^4 H7 z5 a* u
  291. {; t" O9 x0 `  U% V, L
  292.    BYTE  btIDTR1[6];% |5 ?! r9 b$ `- K! M2 S3 z
  293.    DWORD dwOldExceptionHook;
    " ]; p7 e+ K, o* S& s  O+ z( H# l
  294.    const int nHookExceptionNo = 5;, x7 k% i6 H$ B: q- l9 c
  295. ! ~! C0 h; ~- X: K9 K5 U+ V
  296.    BYTE  btIsIDEExist = 0;
    ) \4 C4 M* x/ j% [5 l
  297.    BYTE  btIsDiskExist = 0;
      M6 a6 e, B8 F* O2 N5 `
  298.    WORD  wOutDataBuf[256];) N- q' y/ S/ i5 b: Q

  299. 4 J# v; b( Z7 F3 X8 O
  300.    BYTE  btIsFirst = (BYTE)bIsFirst;% s+ {* E1 n2 C3 P2 |& Z
  301. & _) f  B5 w; ?7 U0 |( i1 D
  302.    const BYTE btBit00 = 0x01;
    ! |  L  r- _: R7 U8 h6 e
  303.    // const BYTE btBit02 = 0x04;$ l9 c+ O' {5 A8 ^; E/ a0 w
  304.    const BYTE btBit06 = 0x40;2 F% ^( X2 V% q. g" j# {/ ]5 w" @
  305.    const BYTE btBit07 = 0x80;! V3 _7 @( v* ~8 w' D4 i# a
  306.    // const BYTE btERR  = btBit00;1 Z8 D! p+ V2 Y6 r0 A: m, u
  307.    const BYTE btBusy = btBit07;
    # f, K( e( A. S; G. P* |& z
  308.    const BYTE btAtaCmd   = 0xEC;
    * E3 }$ y, n$ o, z6 g
  309.    const BYTE btAtapiCmd = 0xA1;! b* x% R/ [( V

  310. 8 K; ~5 z' E1 _  B7 W
  311.    __asm5 M8 J" ~+ \& f  l, y5 }8 x) B* }
  312.    {
    + J. G# P0 f/ @2 A/ ^2 `
  313.        // 必须先执行这条语句
    ( u% p/ J/ `/ a
  314.        JMP EnterRing0
    ( P, i# h6 r% b2 l# ~, g
  315.   z3 C( F/ f7 X+ u6 B
  316.        // 定义过程
    , P5 D7 H3 ~: C' F1 g" ^: B' g0 H
  317.        // 等待IDE设备直到其不为忙为止
    2 b! \) v2 o9 \  K5 G; @1 Q, d
  318.        WaitWhileBusy proc  D7 o8 ^8 V8 A# I7 c
  319. 8 O- D# r9 U; m& Z: _
  320.        MOV  EBX, 100000/ {2 H6 B' W- N1 N1 W8 b1 B
  321.        MOV  DX, dwBaseAddress
    - ^1 n6 X" i  ^! y
  322.        ADD  DX, 7& n* e2 N% i4 h

  323. $ p; ~' e& ^$ E) d# u' g* [
  324.        LoopWhileBusy:+ g3 f/ X) E; _1 H% a* j$ z4 r

  325. 7 a& b* n# }1 p1 y& |- W% P" `
  326.        DEC  EBX
    ( I0 E+ V: G0 |/ x; [% m! y  O: p
  327.        CMP  EBX, 03 X+ i; g" C7 F0 @8 Y
  328.        JZ   Timeout
    ( _7 U1 X1 Z  t, E6 S! v0 e$ K
  329.        in   AL, DX; M6 e  \/ }) b* b& u% r3 o7 e
  330.        TEST AL, btBusy: x4 `! Z% o0 N+ n$ ^
  331.        JNZ  LoopWhileBusy+ l6 H2 U6 U: c4 k" y8 U2 @0 r
  332.        JMP  DriveReady* [( i+ H2 V0 w& j& l1 K/ p

  333. 2 \& @# k5 R+ P* h3 ~
  334.        // 超时,直接退出
    2 f# o. g$ C/ n4 W9 f7 v
  335.        Timeout:
    3 w8 C% c& k: E( Q; u
  336.        JMP  LeaveRing04 Q; ~8 ?: D  R6 t% y5 C+ U
  337.        DriveReady:4 ], g: b- }" v/ `; ?
  338.        RET* z9 f% z  N$ r, ?1 N
  339.        ENDP   // End of WaitWhileBusy Procedure
    4 A9 e3 R3 G' J2 [* o

  340. : F# V. @* d' i+ d" F# n) y
  341.        // 设置主盘和从盘标志9 C' n4 }+ @1 u8 a
  342.        SelectDevice proc
    3 i. |6 u) B5 k: f! @# K

  343. - c: l2 V+ R. S
  344.        MOV  DX, dwBaseAddress
    0 @/ `% l) G+ ^1 A
  345.        ADD  DX, 6
    6 v! U" u. e/ v
  346.        MOV  AL, btMasterSlave# ?: h+ `/ G' O7 b

  347. 3 ~% |  v/ X+ o& S3 ]; ?2 a
  348.        out  DX, AL. [; H# W' p, o- D
  349.        RET/ o  z& W0 f! E; G% N2 B
  350. ( ~5 m( a8 d5 n4 P0 B" y
  351.        ENDP  // End of SelectDevice Procedure$ a2 O  H3 |3 v2 a* p6 O* h3 s
  352. ; Z; L, p1 l  v1 ^7 x  l7 `
  353.        // 向IDE设备发送存取指令( T, }/ l1 B1 @8 J  E1 l1 c
  354.        SendCmd proc" f3 @9 h7 m$ {% ~! T4 c' z
  355. # _. [' z3 o" ~, g9 r4 ]
  356.        MOV DX, dwBaseAddress, |9 D/ `! }# m0 q' D' }
  357.        ADD DX, 74 ~& B6 M. j* s: Y3 \$ C" _( g
  358.        MOV AL, BL // BL是主从盘标识,在过程外设置
      n$ H; h& O. \# p& v. G) Z  w6 f* @
  359.        out DX, AL
    7 s+ Y9 \' R0 t
  360.        RET
    9 B& v3 C7 K" F/ W
  361.        ENDP  // End of SendCmd Procedure
    4 I0 o' H0 ]) `1 s& m& Z  ^

  362. + ^8 ]7 Z  W( ?2 y3 H$ N
  363.        // Ring0代码
    $ b  r4 V  @) E" n- m- ^7 v- c
  364.        Ring0Proc:; {7 a" h2 [' S! ^' W
  365.        PUSHAD+ Q: n+ [- T* A7 c$ C# N
  366.        // 查询IDE设备是否存在4 k  e! O: S, t+ e& ~
  367.        MOV DX, dwBaseAddress: x8 z, d! `" l. x) c" Q- M5 D
  368.        ADD DX, 7
    / K/ Z2 F8 @' s0 P* m
  369.        in  AL,DX+ x5 W+ G( y+ P7 L) S3 R
  370. 4 P6 f; }0 G) M4 }, B# ^+ m- E
  371.        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回% L. ~( z7 R$ `' J, @
  372.        CMP AL,0xFF' U3 @/ Y& ~' G- [0 B9 k
  373.        JZ  LeaveRing0
    , S' S" B; u0 ]# `
  374.        CMP AL, 0x7F: O+ v5 x5 @; p# }. e
  375.        JZ  LeaveRing0
    ! v+ \1 s- i3 I

  376. . C5 P" {) M! h- |
  377.        // 设置IDE设备存在标志
    : C9 ]; F* g5 i2 H6 O
  378.        MOV btIsIDEExist, 1* w2 X) i% F; K
  379. * Z$ A( j4 O: ~
  380.        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
    $ y* E( g' J5 e0 w, x/ _
  381.        CALL WaitWhileBusy! r$ r; T8 I1 Y$ I. q
  382.        CALL SelectDevice9 }) \- A9 [) W7 s) N0 Y3 ?# j

  383. & L3 j* N1 @6 r2 Q7 b& v
  384.        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
    7 ~# V# Z' q5 e4 d2 `' I: Y5 S
  385.        CMP  btIsFirst, 14 Z/ x& ?8 M: V0 ^, c0 k& X
  386.        JZ   LeaveRing0
    , @) S! w9 Q$ ?+ A

  387. 1 e0 L. D: b" R
  388.        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
    ' c9 ~! c# @1 a5 N3 f
  389.        CALL WaitWhileBusy
    " W5 n0 h- R9 i8 f
  390. 9 X' S+ M# w9 ?# `2 t; ^+ @8 C4 \# a
  391.        // AL的值等于cBit06时,不存在驱动器,直接返回8 k- G, Z: @1 n; K5 {* B
  392.        TEST AL, btBit067 w2 n/ N1 h: l& N4 Q9 i& w" S
  393.        JZ   LeaveRing0
    9 ^9 H( E; x0 P
  394. 9 B' H, @) R2 ]0 K% P* }6 V
  395.        // 设置驱动器存在标志
    ( l8 \- [9 n3 S+ C
  396.        MOV  btIsDiskExist, 15 E8 y! m; L* h# k+ C  _! h0 B2 b/ x
  397. , B1 \, t" U: G" e
  398.        // 发送存取端口命令
    ) N- F/ C2 j& S1 U
  399.        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,9 {  i+ H( Q6 R; _5 E; P
  400.        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
    0 Y4 ?' K/ ]- R
  401.        CALL WaitWhileBusy2 I) m9 u* b  G( s6 s9 F7 ^1 s  ?2 K- p
  402.        CALL SelectDevice    // 设置主从盘标识
    3 ?0 n$ a1 f; W) _& W  z9 W& I( H
  403.        MOV  BL, btAtaCmd      // 发送读取命令- A, K8 V. B& a; `' |
  404.        CALL SendCmd
    + C$ ?0 n9 g* P7 e& ^! ]. T
  405.        CALL WaitWhileBusy
    : e$ B* s  Q4 Q! n5 l- V. L. x

  406. ) x) n) K8 `7 S# ^) P' {' w% Q
  407.        // 检查是否出错
    8 e' Z* X- o8 n, d! F$ E# _( Z6 l
  408.        MOV  DX, dwBaseAddress" Z1 h4 \% ~, r- M
  409.        ADD  DX, 7- i5 t5 E/ K; T8 e7 X/ B6 f
  410. 3 T2 M8 R* g* I3 [& T" r$ J1 c
  411.        in   AL, DX. Q4 }: L, R( I9 Y) K& X9 T
  412. 4 M* L" M9 K* H) g- k
  413.        TEST AL, btBit00
      Z  W4 t" v/ W6 m( G
  414.        JZ   RetrieveInfo   // 没有错误时则读数据
    8 y& j. E& e. M3 f& X9 z
  415. - ~: w: W3 g. Y( ]$ @3 \. a
  416.        // 如果出错,则进一步尝试使用ATAPI设备命令6 h2 L! j* d2 z
  417.        CALL WaitWhileBusy2 G4 M6 ?9 |* N+ V
  418.        CALL SelectDevice5 D" K  E/ ?3 R+ o$ c- x8 q' z
  419.        MOV  BL, btAtapiCmd6 B5 Y% z  q! k. m! t3 p
  420.        CALL SendCmd
    0 K  m0 C$ o0 Z; X: h
  421.        CALL WaitWhileBusy2 b5 Z. g! a$ ?0 y: u2 y
  422. $ ?, [( H) j; e( n
  423.        // 检查是否还出错
    # m2 q6 n( X: E; Q
  424.        MOV  DX, dwBaseAddress
      y( J, \) V1 Z0 D
  425.        ADD  DX, 7
    9 `( @. l* c) k4 k& s9 j& ]
  426.        in   AL, DX  t2 r  f9 [3 Z3 a8 Y" _/ `
  427.        TEST AL, btBit00
    9 E+ y6 C/ D1 [4 I! a
  428.        JZ   RetrieveInfo   // 没有错误时则读数据
    $ w  \. `2 a6 ]' _& Z
  429.        JMP  LeaveRing0     // 如果还是出错,直接返回. _0 _0 |3 r# n5 g: K
  430. 7 g9 R4 e9 _/ E! `" h* y1 @0 k
  431.        // 读取数据* g6 T& b+ v8 d+ x2 M5 f
  432.        RetrieveInfo:
    : p. [" P$ }: ]4 `2 H
  433. - x. p6 n2 N  `$ M
  434.        LEA  EDI, wOutDataBuf( y4 {! N& X" p; q" B( ?
  435.        MOV  ECX, 2568 p+ L7 h8 S3 E6 t
  436.        MOV  DX, dwBaseAddress* A& v( y. U. W5 r  {) j  Z( s8 T
  437.        CLD+ X) G6 H9 B# k

  438. & |! I5 @, G) _2 d& \0 {  ]/ ]
  439.        REP  INSW
    - c) `: G% u) x% S# b: |# J1 a

  440.   t0 s2 f7 [+ q
  441.        // 退出Ring0代码7 L! ~, x6 T4 s1 G. F
  442.        LeaveRing0:+ m1 S" c( [- `" _$ ]! a& l5 B+ m

  443. 5 G) i' R* d; c6 x
  444.        POPAD, x. E; U$ h- U$ ~; A
  445.        IRETD
      o+ U# m! Z8 V+ @0 @
  446. / W/ Y3 D+ H- J$ e2 k  R% E. J8 ^
  447.        // 激活Ring0代码) N" i; N, o# I. u+ i
  448.        EnterRing0:
    # ^7 C8 f9 y6 }
  449. 0 {; x& I. h4 D& P, B6 C: {5 Q7 D
  450.        // 修改中断门; v+ c2 G0 W1 c+ F& D; t6 g
  451.        SIDT FWORD PTR btIDTR1
    6 ^& o/ M( ?  ^; W3 H  ?" E1 B
  452.        MOV EAX, DWORD PTR btIDTR1 + 02h
    # P! W5 B% d" A% i# e
  453.        ADD EAX, nHookExceptionNo * 08h + 04h
    6 O/ x. w% p; e, g+ s
  454.        CLI
    9 I5 v) C- H; i2 f. R! i% o+ B: E

  455. " I3 M1 O& S6 b6 e1 `
  456.        // 保存原异常处理例程入口! ?. e+ f3 u- @' U$ f. u  n2 y
  457.        MOV ECX, DWORD PTR [EAX]
    . Y; D; {' ]4 J0 ^
  458.        MOV CX, WORD PTR [EAX-04h]
      Z' U5 P" F; s4 q* }. E( q. m, o
  459.        MOV dwOldExceptionHook, ECX; t7 T' [0 ]. j: X5 E7 m. l

  460. , i/ k, d$ D! ?8 z+ R3 S" w/ o4 m
  461.        // 指定新入口5 E5 b* ?: X, D- e; R
  462.        LEA EBX, Ring0Proc
    2 G( r$ ~0 K0 X
  463.        MOV WORD PTR [EAX-04h],BX
    & f$ \0 y/ m3 ~/ l5 V4 [! q8 _7 J
  464.        SHR EBX, 10h
    8 a" }. m- k/ @/ x* _  H  v
  465.        MOV WORD PTR[EAX+02h], BX
    7 r/ M" {5 a" B+ H3 h# r- x

  466. 1 [* z8 |1 k8 h! H4 X3 c
  467.        // 激活Ring0代码! l* c% v/ j2 J# F6 H3 N3 A
  468.        INT nHookExceptionNo
    % {9 n0 |9 I/ r9 J# Y

  469. # V4 D4 `* O& F* _- q. X' b+ Q
  470.        // 复原入口- F) T# l: \% s+ j  H7 h9 g+ R
  471.        MOV ECX,dwOldExceptionHook
    ! j. N2 Z! \! @7 E& f, F' x
  472.        MOV WORD PTR[EAX-04h], CX
    . ]& ^6 F  ~1 k6 @& g/ A
  473.        SHR ECX,10h
    # V4 b" m5 n% [  s0 r2 R
  474.        MOV WORD PTR[EAX+02h], CX
    ( L) w' L* q  W9 |' t; \+ r9 D
  475.        STI
    9 E4 J0 V, r9 G" N% R" n4 Z- C
  476.    }
    / k" I& a! k; v5 s2 \
  477.    if(!bIsFirst)
    0 s( V7 d9 u! D" }7 [( y0 s/ _& [) ^
  478.    {8 p+ v9 ^6 _- y! T
  479.        bIsIDEExist  = (bool)btIsIDEExist;+ @% W7 {4 w3 V) Z$ {& V0 K3 [
  480.        bIsDiskExist = (bool)btIsDiskExist;! ]) s2 h5 @9 I3 }
  481.        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));$ G3 f' X: }% N+ Q. f2 l
  482.    }& q4 w% k- `9 s, ?/ T/ b; G
  483. }; n2 C6 m4 K& d
  484. //---------------------------------------------------------------------------  ?& ^7 u) T- X; f4 J* p2 h) j' {
  485. // 调用方法:0 c2 p/ c: u0 P; Z* `0 X" g2 I
  486. void __fastcall TForm1::Button1Click(TObject *Sender)  l7 \9 n/ W3 C% p- y
  487. {7 r" `( _: Y+ F/ B* W
  488.    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
    ) Q6 P/ q: ~2 e2 N$ V; z( @
  489. }
复制代码
发表于 2005-8-15 01:00:45 | 显示全部楼层
晕乎乎。。。怎么看8 洞阿
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-8-9 07:11 , Processed in 0.035814 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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