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

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

[复制链接]
发表于 2005-8-11 11:42:04 | 显示全部楼层 |阅读模式
  1. #include <WinIOCtl.h>' r1 e0 ^+ u( n5 g; ~
  2. #include <stdio.h>
    & l9 @8 H" {3 K* h2 ]" \# t! v

  3. $ I0 D4 v5 k7 [
  4. #pragma inline
    ' a. U2 X4 @) [& r, N" F# {9 y8 S
  5. //---------------------------------------------------------------------------0 {) E( X3 Z1 u1 q
  6. // IDE NT/2000/XP专用变量/ {# a& C' {( Q: F
  7. #define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
    5 N6 h# S+ c  C* o2 H; j8 V
  8. #define DFP_GET_VERSION         SMART_GET_VERSION' @* T4 G5 ?  F! ]* v
  9. #define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND  E* e0 S- {* B" S
  10. #define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
    " o- I" ^, ^$ r# D1 ~$ n. [/ q

  11. * d- C6 f: `( q
  12. const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令& v6 I8 M' |* R4 |+ f+ x
  13. const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令3 T* N% g0 u9 T% t! f
  14. % @( f: a8 m6 X
  15. const int MAX_IDE_DRIVES = 4;
    , p. H' a+ P: B9 ^9 V3 s
  16. ; |% t( K0 n/ [' g
  17. // SCSI专用变量
    # ]% \  V1 W& G7 r7 I# e
  18. const DWORD FILE_DEVICE_SCSI             = 0x0000001B;0 G3 L) c. d  s9 ^  {3 i) k
  19. const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
    " h  |+ C2 u8 t* g
  20. const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
    ; e3 K9 A' Q! Q1 z
  21. const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;, ^' Q2 i- d0 l* K1 K9 ~  b& T
  22. ; D  K- a$ K8 F+ r% X
  23. typedef struct _SRB_IO_CONTROL: B0 }9 w4 Y  D" H! C0 S
  24. {
    9 s& Q3 s( w: I- F7 F1 B# n
  25.    ULONG HeaderLength;
    2 o0 V" j3 S9 {9 o0 X2 g# g: F
  26.    UCHAR Signature[8];6 O6 P2 \; u% W1 o8 l! V+ R  z) B
  27.    ULONG Timeout;) L5 k' L; B( P. \, ?
  28.    ULONG ControlCode;
    : R6 N8 g4 {8 a" E5 E
  29.    ULONG ReturnCode;
    7 q. {1 C9 y) @7 b' X
  30.    ULONG Length;
    1 p! Y- Y. ~, z
  31. }SRB_IO_CONTROL, *PSRB_IO_CONTROL;' h0 T; _' R: V; Y& P+ y  r
  32. ) m; a* T5 c$ {/ b3 D1 J9 e
  33. // 读取的主函数, H3 J4 P. ]/ a2 D% J2 G
  34. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
    $ j' G" T9 L/ Q: z* y
  35. 1 o2 r$ I; g2 @  s1 {( L. _
  36. // 辅助函数7 r/ c& p; k9 ]# t
  37. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
    9 x7 l) G% q6 u$ B7 U: g+ k. I; l
  38. // NT/2000/XP函数
    : C* t. ?2 W2 |5 k. N4 Y4 z% h/ }
  39. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);, g0 W4 N( w: ?5 g# h! _! |8 _. [
  40. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,2 Z  k* r* q% j  z
  41.        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
    ' w* ]0 R9 {* d
  42.        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
    ! s6 c' i2 _# O1 n  W$ |: X; x
  43. // Windows 9X函数
      X4 S% V- r, N
  44. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);8 R% V0 X  |4 U7 D; T( r
  45. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
    1 P& L- t7 w6 j0 j
  46.        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);- p; z4 d& I! w1 H; b8 o% W  t5 W* N; @

  47. : v* f% r" W1 Z3 [. v$ R% w/ E
  48. // SCSI读取函数(for NT/2000/XP)
    ( ~. W1 L* w% v
  49. String __fastcall ReadIDEDriveAsScsiDriveOnNT();
    ! l9 P5 z$ ]2 n" C' R
  50. //---------------------------------------------------------------------------
    # f# O* A2 K! Q8 L
  51. // ReadPhysicalDrive
    " s5 b! Y7 V" q0 ?* r. U
  52. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)6 h' r' m" o- Q# \
  53. {
    / }# h: ?0 l1 O0 q
  54.    switch(Win32Platform)
    ) Q. W; e/ N* W0 t! J  ?7 y/ V  @; U
  55.    {
    + q8 _/ W) ]. x0 x( p+ n
  56.        case VER_PLATFORM_WIN32_WINDOWS:
    6 n5 [4 {% j0 W8 [6 J8 |3 K% y
  57.            ReadPhysicalDriveOnW9X(pSerList, pModeList);
    ! L' D% Q  t+ \# j/ k7 K
  58.            break;
    0 ~0 b8 G( S+ r/ U$ N# x/ H
  59.        case VER_PLATFORM_WIN32_NT:7 m3 f2 o' _# M6 d- H
  60.            ReadPhysicalDriveOnNT(pSerList, pModeList);
    6 E1 v% t) k' Q, b. a$ x, c7 z7 T
  61.            break;' ?( r+ ~7 p: f' g# a4 z/ |  n
  62.        default:
    7 N$ ?% z! s4 P" x! ]
  63.            break;* w- E9 V( F# n' O: y
  64.    }
    ) W9 R2 ]) l9 {" A4 ^8 @
  65. }+ `( N: A) w3 a5 T) l3 K4 u
  66. //---------------------------------------------------------------------------- D9 q4 f2 `, o% G
  67. // ConvertToString5 }) {5 o' [: o5 G
  68. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
    - r2 J2 p3 x1 c
  69. {
    4 Q5 C  h" _  N) N; v& @
  70.    static char szResBuf[1024];
    ; M9 F& d5 Q) W
  71.    int nIndex = 0;7 c% {; J. _# x7 Q4 n4 L) L
  72.    int nPosition = 0;' a5 [$ l1 D* q; d' p) O0 W
  73. 8 t# @1 z% u" W) Z: f
  74.    // Each integer has two characters stored in it backwards
    3 |2 s3 M" `" \# `
  75.    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
    6 A( m& t4 |9 J
  76.    {
    ! n  `: r( `& R7 \. m8 T3 w8 i$ M
  77.        // Get high BYTE for 1st character1 Y& x4 ~4 t7 d. L9 |5 y8 `9 y# P
  78.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);, y, H* _) T+ r, I
  79.        nPosition++;/ W: r# F' _0 K8 h& @7 O; y4 n/ z

  80. ( r9 I# Q  L6 U4 M& h8 b  A* d4 T
  81.        // Get low BYTE for 2nd character
    % n2 f5 Q) D( V( d. T' I) Z+ X
  82.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);) B2 e% g! |+ B+ }
  83.        nPosition++;
    $ Y  s& e& X! ]" y' {- [
  84.    }& M$ V+ W  n, V5 l

  85. , f, N2 e" Z+ ^; g! L6 }" U' M
  86.    // End the string
    & x! m, y- f& i9 ]" f7 A3 a" y
  87.    szResBuf[nPosition] = '\0';0 \$ c6 O! ~7 d+ P

  88. " g2 Q3 Q' l. ]
  89.    // Cut off the trailing blanks
    2 Y# H6 T* x, O" D
  90.    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)& j/ ^+ R+ N$ c2 z, s
  91.        szResBuf[nIndex] = '\0';$ d0 @) T8 {) B! T
  92. 8 K* E* D2 K% h0 Y" I+ t' w
  93.    return szResBuf;
    . e- I4 X% p! W, y2 L
  94. }
    9 X1 z" X0 M8 V% z4 s" X; {
  95. //---------------------------------------------------------------------------
      E9 ?9 x4 R& }8 p4 v1 s* M6 k# x
  96. // Winndows NT4/2000/XP 代码; I( c8 y7 F. h+ F3 O2 m8 q
  97. //---------------------------------------------------------------------------; W' f9 H9 @; |# \: `
  98. // ReadPhysicalDriveOnNT
    - C1 V0 x' b. ?) x. p8 q
  99. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)- s! o3 S1 d7 F. w: {$ l/ V
  100. {
    - o$ c( Q8 k! l8 n
  101.    // 输出参数+ u6 U5 c7 s3 F* B
  102.    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];% U/ |6 A% _, Y; Q
  103. . h1 {4 r: m4 o# G
  104.    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
    , g% l3 n8 H2 z+ i; V
  105.    {
    / R9 X( _$ _; [& }
  106.        HANDLE hPhysicalDriveIOCTL;% w8 W' ^  q$ ~5 f7 l( q0 S
  107.        char szDriveName[32];8 P& L5 T! |+ t8 v
  108. 1 w( _! T' P- e2 V0 |2 W, v8 B$ G4 F+ R6 O
  109.        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
    5 ^# {2 d+ c, `" m7 _9 q
  110.        hPhysicalDriveIOCTL = CreateFile(szDriveName,
    & b' x' n: M( ?, W3 ~
  111.                        GENERIC_READ | GENERIC_WRITE,
    6 G0 g0 v9 E% @9 W
  112.                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
    ! |; P  c- g: s0 Q6 L7 c5 q
  113.                        OPEN_EXISTING, 0, NULL);. r- j7 O; M, x' v
  114. . z! h5 u! z% f, z% |
  115.        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
    4 U- q/ P2 [7 m' F% Y  x
  116.        {
    + s  l) K) X5 Z% w  M9 ]
  117.            DWORD dwBytesReturned = 0;
    - Z" Z$ g6 b% w; A; M. ?% C
  118.            GETVERSIONOUTPARAMS gvopVersionParams;
    ' @7 G) Q/ \( d0 P7 |

  119. ! ]! k* p% `$ e5 d8 O1 i6 t' q
  120.            // Get the version, etc of PhysicalDrive IOCTL5 G' y. |# R7 k
  121.            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));1 F3 C. B' o# `$ x% t$ v

  122. 9 M! W9 i) _" G+ v$ f8 s
  123.            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,3 O# {+ n. w* C0 o
  124.                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),8 G' ?: G, X# N
  125.                    &dwBytesReturned, NULL))
    # Z3 r* l: ?1 X+ p  X8 I4 @6 |
  126.            {$ V% z' g$ {5 a0 q2 {
  127.                continue;
    * ^0 g2 t/ _1 Y1 o. I( x2 V
  128.            }
    % R' F3 W! @1 E

  129. ' ^1 j" s0 V) Y
  130.            if(gvopVersionParams.bIDEDeviceMap > 0)
    ( v4 @( i- [6 H3 J, q& W0 A
  131.            {2 z+ U, G; \# O& @- B0 d% V0 z5 S; n
  132.                // IDE or ATAPI IDENTIFY cmd
    ( \- ^" u' E0 i
  133.                BYTE btIDCmd = 0;5 r1 N2 h- X4 p5 U
  134.                SENDCMDINPARAMS InParams;
    9 [9 }0 I9 ?9 M0 _+ N5 d" {9 D
  135.                // Now, get the ID sector for all IDE devices in the system.
    2 @) F6 y$ G% m# b, D3 c* G/ c
  136.                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
    / H0 X) s% a9 Q; f" Z9 m
  137.                // otherwise use the IDE_ATA_IDENTIFY command
    6 b$ u+ G9 }% W" ]8 ~0 [" F
  138.                // 具体所得结果请参考头文件中的说明
    " i& |) t+ _: D, w# h8 K$ `, n
  139.                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
    ) f/ C  q. K% Q/ h8 q
  140.                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;8 ?" b8 n, u) F
  141.                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
    3 l  Y. d% r! ^6 }/ O
  142.                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));& Q# x0 V. T+ N; J: Z) _( P. b
  143. % k! a: u5 }* `, Y% D7 i4 m" o
  144.                if(DoIdentify(hPhysicalDriveIOCTL,; M! b) Y( T' V5 p4 x3 Q& J
  145.                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,! d  q' s; z" g& R7 Y
  146.                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))( q1 b; P9 o( b$ S! K
  147.                {& j2 J8 O. e. B% `" ]# A3 ?1 J
  148.                    DWORD dwDiskData[256];
    * ~* w, R/ r. ]' a: Q) C9 n
  149.                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件: f6 O' i! k) l( Q( C, v) l1 d
  150.                    char szSerialNumber[21];# G& |4 @- @2 y: a) L, p
  151.                    char szModelNumber[41];: n4 q% s4 x  T% M6 M
  152. # N0 D% W' v3 D2 I1 R
  153.                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;6 b; |3 ~% y( }2 b" I4 V
  154.                    for(int i=0; i < 256; i++)
    & ^3 b9 ^; `; n5 D
  155.                        dwDiskData = pIDSector;1 V/ m6 A9 R+ ]* C0 o5 K7 q9 a
  156.                    // 取系列号  G( o- m5 I, J6 y8 |9 a1 q% S# y
  157.                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
    % z/ E  f4 \" K* i$ f
  158.                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
    ! l! P# Q3 d1 K' m
  159.   R# {8 B$ B. J% |
  160.                    // 取模型号
    ( M0 W' Q2 T6 r, t1 P
  161.                    ZeroMemory(szModelNumber, sizeof(szModelNumber));
    0 n" V. l$ h- v# q- y, g
  162.                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
    , x  `: V, U$ g) Y0 F: D
  163. 7 R3 t' D) D; K- U1 K5 V; }+ R* I
  164.                    pSerList->Add(szSerialNumber);2 h/ C' ~2 }0 b5 i3 L3 D
  165.                    pModeList->Add(szModelNumber);7 [' \" r- e0 O+ [5 L7 M( t+ U& d
  166.                }& n+ q+ l& t1 [) m1 b% k
  167.            }
    5 v8 s/ V" A6 f0 }. P
  168.            CloseHandle (hPhysicalDriveIOCTL);
    ) `8 ^6 c& |/ v' M) R
  169.        }7 q3 H" v% i5 k* |  L, i+ [: Q
  170.    }) A! @- i1 D3 |  ^0 k
  171. }& k) o" C6 r- y2 y" B: i- S# K
  172. //---------------------------------------------------------------------------7 W0 w3 f& D$ v6 `
  173. // DoIdentify1 O, S! W" ^0 V  Y: j0 I2 `" x
  174. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
    2 M) O2 I9 t3 \  t
  175.              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,1 C6 t& e/ G1 y+ s7 _/ D- f
  176.              PDWORD pdwBytesReturned)
    4 A7 Y% W! H# B5 z: g/ O
  177. {; ?5 N* c. j3 B
  178.    // Set up data structures for IDENTIFY command./ i3 x$ N& y; x5 }8 u0 ?5 W- f
  179.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;5 {9 ]* c! I& p( v* E0 V
  180.    pSCIP->irDriveRegs.bFeaturesReg = 0;
    * t) ^8 o+ e- N+ o' E
  181.    pSCIP->irDriveRegs.bSectorCountReg  = 1;) t6 E4 d0 T. r! q# V: z2 z  E9 z
  182.    pSCIP->irDriveRegs.bSectorNumberReg = 1;
    ' L* _* g* ^7 J+ Z
  183.    pSCIP->irDriveRegs.bCylLowReg  = 0;& u& l3 B! i, h9 r
  184.    pSCIP->irDriveRegs.bCylHighReg = 0;! \  w( K9 ~4 D7 P  L& ^: X- Y& E

  185. 5 h4 Y* b* p! d2 u
  186.    // Compute the drive number.(主盘和从盘所对应的值是不一样的)
    ; E/ R5 l( G( W
  187.    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
    , v( s/ b" E0 ~+ O. L
  188. 9 n! G. a0 }; d. s/ i# h
  189.    // The command can either be IDE identify or ATAPI identify.
    7 }% d0 D& m  I1 e, B8 l; N4 |
  190.    pSCIP->irDriveRegs.bCommandReg = btIDCmd;4 g& V; h& u! B8 S7 k; D
  191.    pSCIP->bDriveNumber = btDriveNum;& I8 k/ h2 k! z1 @+ C! V' K* Z
  192.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;4 @. l( `& i& ~5 w6 J6 @, |

  193. ( `* C9 R( _8 K) U
  194.    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,) N- j  ^1 \: j' Z; M) O
  195.           (LPVOID)pSCIP,: e% H2 Q. G. d
  196.           sizeof(SENDCMDINPARAMS) - 1,3 A3 m+ c' x4 u* \# Y& G* U
  197.           (LPVOID)pSCOP,
      ?. L8 X1 X6 u8 G1 n
  198.           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
    + Q, u7 \& p8 T+ O# z# z
  199.           pdwBytesReturned, NULL);
    % h) b& N  K& H+ v9 N
  200. }
    + Y# J7 H& _1 Y. I3 _3 e& e5 L
  201. //---------------------------------------------------------------------------8 d2 H* ~% P% j
  202. // Windows 95/98/ME 代码3 R2 b. m0 h+ L3 K
  203. //---------------------------------------------------------------------------
    8 j" L! V  H5 h  p! A
  204. // ReadPhysicalDriveOnW9X
    % k+ n2 T" S5 N4 y% m3 i
  205. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)
    * K/ k# R, L$ N/ `) V- I- K
  206. {
    $ d7 Y5 s  O: f6 U# f* o
  207.    WORD wOutData[256];
    ' X+ O9 J# u& J& o. s$ a+ p+ E+ z( r
  208.    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);7 k- O; O* ~/ N9 J& [0 [5 m: ^$ p

  209. ; f% N- }( V' n& a
  210.    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
    & L. k! M/ p. K
  211.    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以- u2 e$ q, D7 `7 s9 T
  212.    // 避免蓝屏的出现。(期待高人能指出原因)% g: }9 c- ^  a* o
  213.    for(int nDrive = 0; nDrive < 8; nDrive++)9 ]& ]" K; @2 D! K
  214.    {
    , ]: U2 p6 I# a: K8 Y  l3 N3 W6 X+ D
  215.        WORD dwBaseAddress;0 E" `) P# Y7 r( h+ w2 d  e" L
  216.        BYTE btMasterSlave;         // Master Or Slave2 L$ V. U9 I7 Y4 ~. Q7 }
  217.        bool bIsIDEExist;
    5 g1 z" o9 V7 m& U
  218.        bool IsDiskExist;
    7 @1 g' r+ v& p/ \' O) l2 a3 J" ]

  219. . L/ y/ R4 R* [6 s
  220.        switch(nDrive / 2)
    + \" W) o! s' x% H
  221.        {2 F8 `! k7 X+ w; j7 ]$ [9 Q
  222.            case 0: dwBaseAddress = 0x01F0; break;( d& f- I* E7 O
  223.            case 1: dwBaseAddress = 0x0170; break;. N$ O1 u; ^. L5 r! Q. l* {- A- f
  224.            case 2: dwBaseAddress = 0x01E8; break;
    ' A$ O2 n- e% i' e: N1 v
  225.            case 3: dwBaseAddress = 0x0168; break;
    # Q0 z8 a% W9 f" L
  226.        }
    9 H7 W2 b& |" t" e6 V/ I
  227. # u* R5 V  k. z5 w+ \. |
  228.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
      i9 J3 y" x, O% g  G3 I/ N$ V" [

  229. 4 C7 A/ T" `6 D
  230.        // 进入Ring0% _1 d3 z6 z: w
  231.        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
    4 j7 o, i( e3 U; L% Y% a0 d
  232.                bIsIDEExist, IsDiskExist, wOutData);3 F- Q. {+ U3 u0 [0 A. x+ f& [! @) S
  233.    }, L7 _3 o1 i1 b

  234. 8 v6 U* [. x' s- s- k
  235.    // 开始读取
    " q; @: L, Q% N
  236.    for(int nDrive = 0; nDrive < 8; nDrive++), b) l+ k  W$ t7 n, L3 T2 ?2 n2 A
  237.    {7 L& |) e, `" n' k! j7 e6 k
  238.        WORD dwBaseAddress;5 Z0 s0 C/ u1 @& P7 t, S0 R' F
  239.        BYTE btMasterSlave;         // Master Or Slave  {8 Q5 b+ ^2 ?" d
  240.        bool bIsIDEExist;
    ) D0 n$ Z. u) R$ A
  241.        bool bIsDiskExist;$ }7 t- ~) k- o8 C. V0 m! d* f: u
  242.        switch(nDrive / 2)
    " d- Y' E8 L1 ]( ?7 k. w
  243.        {& U, |' f$ c: S0 x: q' \( k
  244.            case 0: dwBaseAddress = 0x01F0; break;
    # s6 W: `7 o- @( l: |1 @0 l; e, Z
  245.            case 1: dwBaseAddress = 0x0170; break;
    6 a- @( y% c+ \+ }- X1 O) w5 Z9 K
  246.            case 2: dwBaseAddress = 0x01E8; break;+ M$ C9 U: s2 \; _. p( k: m
  247.            case 3: dwBaseAddress = 0x0168; break;, `7 K: q/ o) X, S% C- b
  248.        }
    9 T' I8 |3 G' J5 L3 I/ ]
  249. # Y8 M) y$ \5 ]+ I; q
  250.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
    1 S  c1 t8 q; j; [6 w8 N0 J
  251. ) w$ T+ @- G. ^2 L9 w; I$ j$ i1 a
  252.        // 进入Ring02 {, B$ C7 C/ L( U
  253.        bIsIDEExist  = false;& O" v& a1 ~% A+ l  r
  254.        bIsDiskExist = false;
    ( n/ t/ v$ y) m2 a% r4 ]% s, J
  255.        ZeroMemory(wOutData, sizeof(wOutData));
    8 Z9 a6 y( f4 Q6 Z* Q
  256. : {8 s( n' x  R4 q: V
  257.        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,9 L, c4 z. o. g0 \9 R5 _( \- L+ z
  258.                bIsIDEExist, bIsDiskExist, wOutData);  P8 j$ [. N" Z* E. n) ?. o
  259. " S& `. r( r1 D7 u$ p4 r
  260.        if(bIsIDEExist && bIsDiskExist)
    5 n/ b% O! l6 V) n. c! H
  261.        {
    ) h' O* s+ x! T, K, Y6 @7 e  g! j
  262.            DWORD dwDiskData[256];2 E- Z5 D: a" W8 p# M- N: O! _, E; R
  263.            char  szSerialNumber[21];) V; Y. ?# P6 J' G1 y$ Q
  264.            char  szModelNumber[41];
    8 B6 p+ T( Q7 w
  265. 2 |/ P  G  P2 K" V/ e
  266.            for(int k=0; k < 256; k++)
    4 n6 q2 I4 n% t) j5 l( v% d( ?
  267.                dwDiskData[k] = wOutData[k];$ k6 U5 c8 U, \$ Q# v; f5 k, C
  268. 2 j+ \* v* P8 T1 F4 {# |" k
  269.            // 取系列号  x3 q8 C( c  B  G! z7 U9 y
  270.            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
    : }3 ?1 n7 \/ s( z5 A
  271.            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));+ m) G6 h$ h+ I0 {

  272. / }7 e/ E$ C4 l8 r/ c+ C$ `: |1 ?' m
  273.            // 取模型号
    1 W0 f: _( _$ q
  274.            ZeroMemory(szModelNumber, sizeof(szModelNumber));
    3 z  p3 |5 A/ |3 a9 I
  275.            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));9 \# {; s1 I, \  h. ^8 P4 _

  276. ; ~8 L3 I6 v- J/ P* q" A2 u
  277.            pSerList->Add(szSerialNumber);- Q5 x8 M$ d. Y2 ?
  278.            pModeList->Add(szModelNumber);
    1 y1 X; f- T- ?0 y
  279.        }9 \1 A5 v5 Q) d1 B& _6 J3 D; o
  280.    }3 {9 Q1 F3 Z2 s0 ^
  281.    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
    9 w: h, }6 H9 l( c: W- h$ {9 s
  282. }
    + r$ Y3 C9 o- m5 M( a
  283. //---------------------------------------------------------------------------
    ; @3 X7 \$ k  r5 p! i% V
  284. // ReadPhysicalDriveOnW9X_Ring0()
    ; u0 ~. t4 V8 l/ Y
  285. //! M% P  \$ m# y# y! Z3 ?
  286. // dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
    , r9 F) B+ W, X& ~  b
  287. // btMasterSlave = Master(0xA0) Or Slave(0xB0)/ E& s+ f6 K' H1 z
  288. //---------------------------------------------------------------------------
    ! B! k7 e# o% J% [' q
  289. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,( |# U' ~" w5 I. t
  290.        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)$ H6 Y: G4 B. _
  291. {; ?  ?: B; d/ L3 m) i: B( c
  292.    BYTE  btIDTR1[6];
    3 i4 Y' E2 w; W$ ^; K
  293.    DWORD dwOldExceptionHook;+ y& k" f! _2 J" k1 D
  294.    const int nHookExceptionNo = 5;8 F9 D+ m0 @, \# }. R9 a" L

  295. , c4 [9 @- e& q
  296.    BYTE  btIsIDEExist = 0;
    ( e* y4 e& B& W: }4 ?2 X; Z
  297.    BYTE  btIsDiskExist = 0;; b! a6 {, a- s+ a7 y& H4 Y
  298.    WORD  wOutDataBuf[256];
    * F% T( D- g- @& Z
  299. * u/ X" B$ j$ u+ G1 i
  300.    BYTE  btIsFirst = (BYTE)bIsFirst;
    % [, x# `! B* U# q

  301. ; J" u# X+ Y% @2 K2 T0 L; K
  302.    const BYTE btBit00 = 0x01;
    , N" ]* ~5 b( d, m1 _
  303.    // const BYTE btBit02 = 0x04;  d2 P5 r( ~' n5 f
  304.    const BYTE btBit06 = 0x40;
    # [+ {) o" U$ b* K, h. M& Z
  305.    const BYTE btBit07 = 0x80;
    0 F: S2 y* Z0 i
  306.    // const BYTE btERR  = btBit00;# ]) b% L+ P4 a, j6 h9 A8 @
  307.    const BYTE btBusy = btBit07;( n% H' O' o4 P. d; O( U1 i3 e
  308.    const BYTE btAtaCmd   = 0xEC;
    . ^! R' m. Y4 M' E/ Z) |+ s- K, t0 Z
  309.    const BYTE btAtapiCmd = 0xA1;1 }. d( F1 c9 s( ?6 X

  310. 7 i6 t' @( ^! z1 N: f/ h
  311.    __asm
    , {: t8 a* O& J, c) T
  312.    {: \- O' c# _5 u
  313.        // 必须先执行这条语句& D( j4 P0 Y  G2 c
  314.        JMP EnterRing09 K4 n7 O( @4 v1 x, f( E6 E; p0 m. G

  315. ' p, M( d& H5 e
  316.        // 定义过程
    ) n2 W8 T3 Q" J! h/ K. E& J  t
  317.        // 等待IDE设备直到其不为忙为止
    $ a# ?6 p: B( U; Y, u
  318.        WaitWhileBusy proc" T+ I6 i3 V9 ^9 E' k7 V* c
  319. 5 W& ?" h7 g% h  _: ?
  320.        MOV  EBX, 1000008 |- q4 U' q/ x/ ~# P5 Z8 [3 x
  321.        MOV  DX, dwBaseAddress
    % M/ V& P4 m  z
  322.        ADD  DX, 79 g4 ~# I* s; A$ q5 {, j9 _

  323. ! d9 g3 m( a% W/ p8 U
  324.        LoopWhileBusy:
    2 T$ |1 B6 }7 `" M1 y, `6 D6 {

  325. % M; J( `) Z! V+ G' X
  326.        DEC  EBX6 s: e* N* y6 C# T/ v
  327.        CMP  EBX, 0
    / P9 n( n/ ~) z
  328.        JZ   Timeout1 S- d) O9 X/ j% I6 z* H- _
  329.        in   AL, DX
    % s1 @5 D7 c( i( c. g
  330.        TEST AL, btBusy8 p) ]: W( A+ X2 S0 u( v3 ~) i; q
  331.        JNZ  LoopWhileBusy5 z) o: M$ x( q+ ~4 p0 l
  332.        JMP  DriveReady4 O/ l3 k- X  \2 u" S4 P
  333. ' P, J% r/ F9 d6 \# l/ Z5 g# o
  334.        // 超时,直接退出
    * X/ s, z& X3 {1 v
  335.        Timeout:( L8 [1 Z, m* d* q2 X! j
  336.        JMP  LeaveRing0
    9 R0 B$ V$ E% I
  337.        DriveReady:" e& W8 A+ D4 e& ^0 ?) G
  338.        RET# G. e! j/ v8 C3 \" ~( J1 h2 ]
  339.        ENDP   // End of WaitWhileBusy Procedure& n3 e: Q0 e# x
  340. 9 }; i% ?& r0 i3 B8 l
  341.        // 设置主盘和从盘标志
    6 j! W" _! v8 b. N7 \* {8 J
  342.        SelectDevice proc% K3 z- y& x: P
  343. 9 b. E. @1 c3 H9 J2 e+ ^5 t
  344.        MOV  DX, dwBaseAddress
    , u$ z3 u2 q3 ?, Y/ K8 P
  345.        ADD  DX, 6
    9 ^1 `' i1 F  K7 I: e" e/ {
  346.        MOV  AL, btMasterSlave+ o3 @0 N- _  M! N- g* a6 U
  347. * j0 l6 W4 i# u+ N. y# g
  348.        out  DX, AL
    % U  b/ Z) b: H- u8 \
  349.        RET) d5 B5 U$ F# H/ X2 e
  350. - z& Z+ h' a$ O' l: l. X  x9 Q0 y* t9 W4 O
  351.        ENDP  // End of SelectDevice Procedure
    # @/ u: \2 Q' a/ {$ O
  352. ) s' Y" `0 K0 p$ B  m! _+ m
  353.        // 向IDE设备发送存取指令
    % h9 a+ N9 J% T: p4 L9 z8 r
  354.        SendCmd proc( o2 |+ p/ u+ h" }* N- f  l% a' r
  355. ! u4 }. n5 `: h- o" P
  356.        MOV DX, dwBaseAddress1 _  ?  D9 @, Z, T, E
  357.        ADD DX, 7
    7 r. C* p2 P, P' k" x
  358.        MOV AL, BL // BL是主从盘标识,在过程外设置
    % J: t$ ~6 x' c
  359.        out DX, AL
    8 o+ O/ L; W! v* _1 d
  360.        RET" ~, q- g8 @; j/ ?2 P+ W
  361.        ENDP  // End of SendCmd Procedure' C- F6 o  I# m3 b/ S
  362. ; `5 C/ ]+ c' t$ K3 t* {
  363.        // Ring0代码3 s* |% g5 l% G. m1 x* L! I
  364.        Ring0Proc:( u! Z- S: D; U3 N8 d7 \3 m
  365.        PUSHAD
    ' J- |& {) G2 d) m* j) H+ K- Z" n' ^
  366.        // 查询IDE设备是否存在( f  C# Q4 N$ k0 Z2 u6 Z6 m+ w
  367.        MOV DX, dwBaseAddress
    5 r. t1 L5 y) I4 j/ K
  368.        ADD DX, 7
    1 n+ A8 o% y# G, p& V% t
  369.        in  AL,DX  |9 N+ V7 D  d% O9 v& r
  370. ( r! F# {2 B! R" n% \1 x) g: n
  371.        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
    ! `6 b7 A0 i" K
  372.        CMP AL,0xFF3 i& w$ p7 r; d# V4 w& j
  373.        JZ  LeaveRing0. c7 d  d, Z. J4 `6 A0 N8 N; p8 E& j
  374.        CMP AL, 0x7F' M8 S! U7 Y1 I0 f) `# ^  C* D$ k
  375.        JZ  LeaveRing0
    " g% n! V4 a: U! F& t) @

  376. ! k" Y2 C+ E! s4 g8 I6 y1 f4 x) o
  377.        // 设置IDE设备存在标志7 {! o7 z2 b6 i0 [! x
  378.        MOV btIsIDEExist, 1
    1 _- Z9 W1 w: q! L( W

  379. ( M+ {4 X' @; H- R+ _5 Q
  380.        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面); @( V# d& J  Z1 h0 I3 M
  381.        CALL WaitWhileBusy7 ]9 ^4 ]/ _$ T3 K! Q) w- W5 l) `
  382.        CALL SelectDevice
    $ _* M$ K% t$ }# s* o# l
  383. : C4 w+ I, ~1 y1 m+ n# L4 M
  384.        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
    0 b" `: w. X% C3 X1 I$ D5 j
  385.        CMP  btIsFirst, 1
      X5 `( S3 T! k- \/ h
  386.        JZ   LeaveRing0) C$ ~, g9 }$ _3 j4 g

  387. " A6 g  V- Q+ A! H
  388.        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???6 f$ f4 C, R) G/ x7 g7 [
  389.        CALL WaitWhileBusy
    % F4 h& e, o4 v1 u, N0 d- Z
  390. & X9 k, h4 U7 H: J3 m
  391.        // AL的值等于cBit06时,不存在驱动器,直接返回
    & m2 \$ Y9 E& p- Y1 D% {3 N
  392.        TEST AL, btBit06: j7 E2 A+ r8 J1 ]/ `7 `
  393.        JZ   LeaveRing0
    ! m7 X( S/ O0 y" U( L+ o
  394. 4 D7 l5 D3 ?( [( m: w3 W* B
  395.        // 设置驱动器存在标志! k) W( G7 j1 R3 O
  396.        MOV  btIsDiskExist, 13 h9 n/ A5 ~; ?7 L6 w+ N

  397. 3 K7 V1 c  i) A6 r& w- C
  398.        // 发送存取端口命令* d4 b! U& q. K
  399.        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
    . L5 s1 G5 q1 ^: K' Y
  400.        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令4 J+ I( N5 {1 m) h8 c. n
  401.        CALL WaitWhileBusy
    : M1 E6 N5 }! c  j5 o: |  m
  402.        CALL SelectDevice    // 设置主从盘标识
    9 w/ l" H$ p; a5 i, N
  403.        MOV  BL, btAtaCmd      // 发送读取命令; x- s5 S. X) t! m8 {/ G7 l2 w
  404.        CALL SendCmd$ F7 k8 w+ G  d( @/ s) Q
  405.        CALL WaitWhileBusy
    ; S3 j9 w" O. U( g* z

  406. ; s* k0 w# l9 j% j
  407.        // 检查是否出错( z1 M2 ^; l1 g' h5 O% Y
  408.        MOV  DX, dwBaseAddress
    , E* g" F. C8 r4 O9 o6 d% u1 ^5 E
  409.        ADD  DX, 7
    5 n- b! f1 ^7 l, Y- o% R
  410. " x! h% P/ u/ g9 a* W: |( p) j
  411.        in   AL, DX( A. e9 h, m) ~: ^+ g+ D
  412. ' t; B. }# H/ j+ i) N( E9 ?6 ~6 m
  413.        TEST AL, btBit00
    1 E9 a, y: p, p  h$ l9 t/ `
  414.        JZ   RetrieveInfo   // 没有错误时则读数据
    ! G4 _/ [: W1 e

  415. 6 G7 ~! G1 v& C3 ^
  416.        // 如果出错,则进一步尝试使用ATAPI设备命令2 K8 Y% g% L7 s8 Q7 R8 b- u
  417.        CALL WaitWhileBusy! @8 l, |5 ~. x' g
  418.        CALL SelectDevice
    " C7 {; k1 R2 j- {/ s- ~
  419.        MOV  BL, btAtapiCmd# e) Y4 K) U$ L8 Y
  420.        CALL SendCmd
    8 \1 H7 E6 t- ?/ X
  421.        CALL WaitWhileBusy
    + V: \: [9 h& k# c- m# ^
  422. / G! R- Q4 L' C
  423.        // 检查是否还出错& ^& J2 e) Q# Q  j
  424.        MOV  DX, dwBaseAddress
    5 ?4 r# \7 o* V/ v% I- f
  425.        ADD  DX, 7
    2 c: r7 s" P! @* L- W
  426.        in   AL, DX
    . B. ]7 M" U0 q, Y  |5 ?' S
  427.        TEST AL, btBit00% r/ q  e$ ]" @: b' Z& P+ G
  428.        JZ   RetrieveInfo   // 没有错误时则读数据
    # k0 ~; o, ]$ X8 J. D
  429.        JMP  LeaveRing0     // 如果还是出错,直接返回; }& m) g- G1 T. [0 [" n( N6 A% C& K! ]9 z

  430. ! I9 w8 n/ `, G+ y; F& a
  431.        // 读取数据5 G$ D4 H) E3 t# v8 ^
  432.        RetrieveInfo:
    ) l; i0 v. t' J; p6 k8 a

  433. & I- p2 ?& E3 m
  434.        LEA  EDI, wOutDataBuf! V4 s4 K$ @! l, ]/ f% _9 ]
  435.        MOV  ECX, 256% x, j4 B+ P6 a" z- s! n( S
  436.        MOV  DX, dwBaseAddress$ q0 d+ Z- ~& ~! q4 S
  437.        CLD3 ~& c9 O$ J! r9 C
  438. ( @- N+ ^" O# R0 V% a( v+ V
  439.        REP  INSW$ W# x. k, f4 c$ k- b) R3 K

  440. + V; @) X! q- z1 L% j
  441.        // 退出Ring0代码
    . l# \4 _& {, E7 q) Q( _
  442.        LeaveRing0:
    # Z. m5 \- j, d1 \8 @

  443. ) s0 _& T; t. S+ E! }% {1 q
  444.        POPAD
    / e' u) W* U3 _( @
  445.        IRETD. F: G- v) M# F' n
  446. : n6 m' A- I( S/ H# {9 G- X2 A
  447.        // 激活Ring0代码
    / R2 X2 c# Q+ J: e% x) ?  Q# T- o9 p; i
  448.        EnterRing0:
    % n% R( G- }' f" h
  449. 8 i# j$ F: y1 s" a5 O
  450.        // 修改中断门
    # ?) Z" d7 y$ V, B1 E
  451.        SIDT FWORD PTR btIDTR1
    - m& h5 Z# {& ?- i
  452.        MOV EAX, DWORD PTR btIDTR1 + 02h
    9 ^: p: ?  C# J0 [
  453.        ADD EAX, nHookExceptionNo * 08h + 04h+ C6 b( k1 [  Z" c+ i+ Z
  454.        CLI! |- T6 g1 t7 P& Q

  455. 0 Q( X% K" V& [% {
  456.        // 保存原异常处理例程入口( P; l/ _6 i5 F; c  Z
  457.        MOV ECX, DWORD PTR [EAX]+ @$ n' I: C; a9 \
  458.        MOV CX, WORD PTR [EAX-04h]
    1 A  z2 g6 M1 ~3 W1 j" J$ j
  459.        MOV dwOldExceptionHook, ECX; m5 l! \2 d9 h% v

  460. 7 N6 C- P2 y" ^4 \/ m" [* F7 d9 B) K
  461.        // 指定新入口  O: Y  O9 g! x- A) D" C1 `
  462.        LEA EBX, Ring0Proc
    9 u% O3 ^, v( b0 W
  463.        MOV WORD PTR [EAX-04h],BX
    9 G  s. i  f5 n6 n4 }5 E+ Y7 w9 o6 Q
  464.        SHR EBX, 10h
    0 w( a" Z5 i# s) W+ G, C% M
  465.        MOV WORD PTR[EAX+02h], BX! x" c3 |, i) a: D9 T
  466. 9 K8 x; x. X' E8 b0 q
  467.        // 激活Ring0代码# F/ r) Z0 V/ h7 V1 h4 c/ e  ]
  468.        INT nHookExceptionNo
    " Q7 s3 m& K' R/ P  }( N
  469. ( N7 _& d( E4 t) U
  470.        // 复原入口$ T2 M. }2 w$ E% U3 _
  471.        MOV ECX,dwOldExceptionHook
    2 w0 n/ A/ Y: b( g8 @
  472.        MOV WORD PTR[EAX-04h], CX
    ) ^" Z6 i+ W5 _9 k" Y$ L
  473.        SHR ECX,10h
    6 P+ E2 P8 V9 t! _
  474.        MOV WORD PTR[EAX+02h], CX! X3 J% n/ s. T  ]/ Z
  475.        STI) B. q1 j& G/ T, D( E0 ?  K
  476.    }
    6 t7 d! M; E9 c5 Y4 U! z4 g
  477.    if(!bIsFirst)4 A1 J2 K" p2 r
  478.    {7 Y( E0 h0 w+ _; e) F
  479.        bIsIDEExist  = (bool)btIsIDEExist;
    0 _) Q4 v/ v1 b' A( m, q* ?/ {
  480.        bIsDiskExist = (bool)btIsDiskExist;
    8 R3 ?6 }& G  ~% j) x0 ^0 C
  481.        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));$ v, L9 j# c! ]! c+ I+ w9 j
  482.    }" b: [; i9 Q! u: E
  483. }0 H, K6 V$ V" c
  484. //---------------------------------------------------------------------------
    - A. Q# U+ g; A- y
  485. // 调用方法:7 j/ O7 V! i/ I4 j
  486. void __fastcall TForm1::Button1Click(TObject *Sender), y( ~, P- v4 q7 K+ ?
  487. {
    - ^- [/ O$ y2 N; X8 T! F5 W# @
  488.    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
    4 V8 Q* }% j) `: N: x9 k3 d
  489. }
复制代码
发表于 2005-8-15 01:00:45 | 显示全部楼层
晕乎乎。。。怎么看8 洞阿
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-8-15 06:38 , Processed in 0.018840 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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