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

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

[复制链接]
发表于 2005-8-11 11:42:04 | 显示全部楼层 |阅读模式
  1. #include <WinIOCtl.h>) s' U: p( H( ^: A
  2. #include <stdio.h>
      D  }6 I: [0 t, D& p4 i2 p6 q. C
  3. 9 x) I1 u4 O$ N/ }' ^3 R# N: L
  4. #pragma inline
    ! U" f  _5 o& v& Y0 I
  5. //---------------------------------------------------------------------------) p& e" M% O& m) f
  6. // IDE NT/2000/XP专用变量( s) Y5 W0 n$ e% Z" Y
  7. #define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS) H) ]' k" L3 D
  8. #define DFP_GET_VERSION         SMART_GET_VERSION
    3 q2 M0 l% K7 _/ ]
  9. #define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
    % f. L# c) |! s2 M
  10. #define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA4 m9 G8 E" C2 g! S! ~

  11. 8 j: T  H. u, F* c, I1 U
  12. const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令
    ( w* K1 c5 C/ a2 ^1 C
  13. const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令. W! G; L1 D$ r6 Z, x% R

  14.   Z  q. r( |" U$ V# J5 i7 b% F
  15. const int MAX_IDE_DRIVES = 4;
    $ X$ W: E% t( C3 j1 V6 O6 T

  16. & V* W9 Z7 i/ ?3 |+ k0 u8 o
  17. // SCSI专用变量
    / Z6 o( r. B; T' C& x2 \
  18. const DWORD FILE_DEVICE_SCSI             = 0x0000001B;
    % ?# `/ U' X2 W, u. H
  19. const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);4 n) l3 T$ y2 B& H; j
  20. const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
    9 X6 V  _# A: V5 r
  21. const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
    7 y# j6 G* s' K

  22. ( v6 K/ C$ @% U, |7 P+ H
  23. typedef struct _SRB_IO_CONTROL
    3 `6 J5 S9 l' T$ ~& y5 x1 f3 q
  24. {
    6 {  u0 M, u) L" n- K) h
  25.    ULONG HeaderLength;  Y' q4 ?( o1 ?; l; [
  26.    UCHAR Signature[8];  ?) r, T% u* b* T( Y
  27.    ULONG Timeout;
    8 r4 X& k& S, z3 a' c
  28.    ULONG ControlCode;7 @7 C' A5 U- {
  29.    ULONG ReturnCode;( l( Z2 F. Y  m8 u
  30.    ULONG Length;
    / ^$ u9 }+ ~0 m" {! K% U
  31. }SRB_IO_CONTROL, *PSRB_IO_CONTROL;
    ; {' v6 \5 N1 _
  32. - I) Z% e) L: M/ B
  33. // 读取的主函数/ m: l" l% |" e% `% j9 k
  34. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
    0 }: W9 p+ V, e- [' B

  35. 0 u% }0 t1 W$ E0 l1 U9 u
  36. // 辅助函数
    5 |% S8 w4 \% n+ }6 x9 s6 s
  37. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);: _. B$ b- a$ {+ l
  38. // NT/2000/XP函数4 ^, w  @, P7 Y% I+ ?2 |+ y9 q
  39. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
    " \, ?" k4 t  A: U( p1 q& |
  40. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,0 |6 g1 J! g. Z( @. a: P+ {  r
  41.        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,! M9 t# C; j# Q5 l6 ]
  42.        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
    / c& r' w) g- H; U* J
  43. // Windows 9X函数% |# R* N$ \3 [. n: ?, B
  44. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);& E5 v) w0 r" n4 @5 C8 I$ v
  45. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
    2 {8 i% ^# |' b8 j; t1 p, V. g
  46.        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);0 P* J8 U3 X5 {1 o- {! E

  47. + E" E0 x, ~2 ~1 M+ c
  48. // SCSI读取函数(for NT/2000/XP)
    # ~8 @$ S2 _9 m4 U" k% l) q
  49. String __fastcall ReadIDEDriveAsScsiDriveOnNT();8 r) d, q; G! g2 ^: p* F& g% y
  50. //---------------------------------------------------------------------------8 w0 a8 w1 e0 M* m5 H6 N" ~$ m$ I
  51. // ReadPhysicalDrive  ^: b! J0 E1 d! {1 }7 {2 u
  52. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
    9 U1 x. ?, M" `* u, f3 I( e
  53. {; y  }  U) n+ ?& G  K- P5 G  H1 k
  54.    switch(Win32Platform)
    # Q* S- x/ a. k# b& a
  55.    {
    4 B1 \: d: q6 g9 C5 q* e
  56.        case VER_PLATFORM_WIN32_WINDOWS:, c3 ?" i7 q7 @3 g0 _! ~" L
  57.            ReadPhysicalDriveOnW9X(pSerList, pModeList);! z' b5 e% a: J& [/ ?  F0 \$ ~3 a
  58.            break;
    3 t; e$ C4 _) }  [' G
  59.        case VER_PLATFORM_WIN32_NT:9 n/ u! M$ ]. i7 S; E
  60.            ReadPhysicalDriveOnNT(pSerList, pModeList);: J  ^# X( L1 }0 |1 \6 ?) I# v
  61.            break;% l5 J/ b" q' a
  62.        default:
      D: M$ B7 G3 b$ M
  63.            break;
    " s, H/ |. H3 u  R
  64.    }
    ! H/ m. N, ~1 f; ]$ }0 L' n1 F7 A  T
  65. }
    + i9 Y: K" P! j2 y' U+ Z
  66. //---------------------------------------------------------------------------9 g) O6 K% J; r4 v  t3 M) ?8 [
  67. // ConvertToString
      L9 L0 u6 s8 l1 J$ F
  68. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)% u! d- N. W7 g- d8 b
  69. {
    6 r! s- c7 _) n4 E
  70.    static char szResBuf[1024];
    1 h. O- G  a) i
  71.    int nIndex = 0;
    7 H( [7 g$ f/ T8 ^
  72.    int nPosition = 0;/ s& y' H) O% x8 w: T2 v8 \
  73. , V4 n& D( g, C# K
  74.    // Each integer has two characters stored in it backwards) n2 Y. ^# }$ [4 O
  75.    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)- R0 T1 h; @, U6 q
  76.    {# Z' w! h% d1 g: a
  77.        // Get high BYTE for 1st character
    0 i! k6 ~2 T# C6 Z
  78.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);) e: I1 T: \! o  B9 l
  79.        nPosition++;; }" I& U9 x8 y2 P9 z* V

  80. 0 k! M: {4 w- V: s1 U0 q
  81.        // Get low BYTE for 2nd character
    0 @5 [5 y2 ]" K1 l' {- \
  82.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
    6 k  R; g% g6 y0 w' z
  83.        nPosition++;* R& Z: v9 |: p$ _" ]4 r3 u
  84.    }
    / Y$ u- e& B6 B& s
  85. 9 O8 i7 O, {. J0 R# b# W, ?
  86.    // End the string
    ! U3 a& e; t' l( y
  87.    szResBuf[nPosition] = '\0';, v: ^  c9 {& E  s7 m
  88. * W# e1 k6 B; k; C
  89.    // Cut off the trailing blanks
    - Z4 _% ^8 v' o% I0 r) `
  90.    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
    $ U/ f" i+ U# d$ Y
  91.        szResBuf[nIndex] = '\0';0 d6 Z) \+ d6 y7 M  h6 Y

  92. 6 m4 K% ]  I' K5 F' ^, y
  93.    return szResBuf;
    5 D* w/ f& h0 X  S6 P5 G/ k  R
  94. }
    , p  }+ o9 V  G: q  w+ N; I6 s: b; l
  95. //---------------------------------------------------------------------------8 Q0 `+ d/ l" I
  96. // Winndows NT4/2000/XP 代码6 S) x- @6 G; \* u
  97. //---------------------------------------------------------------------------
    & W9 U' y2 |' w1 w5 z* B+ \0 {
  98. // ReadPhysicalDriveOnNT  Y5 Z% w( W4 T# \  ]9 q
  99. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)" U# B0 y. m5 H$ q9 Z
  100. {$ h$ i2 u8 `  @: a5 G3 q
  101.    // 输出参数
    2 ^" c) D9 B: S! }
  102.    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];7 ^4 _$ ~) b8 A6 `. q
  103. 6 |2 u- l8 O  L# }, q2 \7 P
  104.    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)* N* D+ S- u/ ?$ @( h! t9 z
  105.    {# r) j: m* W; _
  106.        HANDLE hPhysicalDriveIOCTL;
    6 r: i, }" {2 _8 F
  107.        char szDriveName[32];
      s: q' c4 T, ], o

  108. 2 K1 C' y9 [" L: F9 K; l3 e: b
  109.        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);7 p8 |% @& e6 }1 r
  110.        hPhysicalDriveIOCTL = CreateFile(szDriveName,
    8 l2 x$ y; e4 N4 {# [
  111.                        GENERIC_READ | GENERIC_WRITE,; T& S* ^( p! H" f+ g) }+ l  P
  112.                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,3 \( c! e0 S1 ?) W: J
  113.                        OPEN_EXISTING, 0, NULL);
    ' D: U. X: r' A2 [& l+ x+ f

  114. 8 D0 U1 @7 A) Z) s! f
  115.        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
    ( z5 T; o+ }7 c- C& E$ A! j# z
  116.        {! l# o$ S# M0 I- Y$ r5 K9 w& D8 l# a0 p
  117.            DWORD dwBytesReturned = 0;
    * k7 n* m) a& d+ v* }
  118.            GETVERSIONOUTPARAMS gvopVersionParams;% C4 K% @9 ~, {

  119. 5 h; e# ?: Y7 r9 n
  120.            // Get the version, etc of PhysicalDrive IOCTL( f! o, m' [2 _# ?  H' Y
  121.            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
    " X* m* H3 t, H- [

  122. $ V, N8 h9 Q* E4 k1 o, U. }+ @
  123.            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
    # w' x( u0 c: N0 m1 M
  124.                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
    2 U& u/ h0 x* W  ]8 r$ n# f+ `
  125.                    &dwBytesReturned, NULL))1 Z# r/ U/ _. ^! C% R
  126.            {
    ( w! w4 T0 U; H3 A
  127.                continue;0 I0 @  ]% V# B
  128.            }. N7 i+ X, c6 k2 y
  129. + G- ^1 R3 Q5 O  C
  130.            if(gvopVersionParams.bIDEDeviceMap > 0)5 o( {$ r" d; r5 U/ @, s7 z
  131.            {
    7 F7 k% [$ i" T3 [) e
  132.                // IDE or ATAPI IDENTIFY cmd
    6 W  F- ^4 Z% m2 x/ f  }9 k* [
  133.                BYTE btIDCmd = 0;
    " e! C' k9 L6 x$ q* B0 f
  134.                SENDCMDINPARAMS InParams;
    , ?% S/ x* |9 H5 x4 t1 O
  135.                // Now, get the ID sector for all IDE devices in the system." f7 ^4 P7 Q( \2 ]1 V4 p2 F% g" K2 V
  136.                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
    $ X7 Y4 K9 j( ]0 H. C* O. ?% t
  137.                // otherwise use the IDE_ATA_IDENTIFY command
    6 q* W* b2 @  f' c3 A* g0 u- T9 ]
  138.                // 具体所得结果请参考头文件中的说明
    0 S6 g: `0 U  o  _
  139.                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
    * J! I$ K6 \2 P1 P' A( q  i4 R
  140.                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;$ z; r% y  X2 T2 V% d- ]
  141.                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
    7 B8 ~: n2 @; f0 \. K: B
  142.                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));! A0 @6 O- o, k. t7 D+ B7 f- ]' H
  143. 2 ]3 i6 S, S5 r& l, i0 k6 |. F9 Z
  144.                if(DoIdentify(hPhysicalDriveIOCTL,' I7 ?  z; Z1 _  h4 q% a
  145.                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
    2 O- A2 }0 ?( ], M. S; p2 n
  146.                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
    ( ]' ~, S. d# p7 Z5 Q  D4 v7 z
  147.                {
    & {+ O1 r  b! M5 f/ W# ?
  148.                    DWORD dwDiskData[256];' d! S: ^" a( G& E
  149.                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
    5 c( ^' h9 O5 B: t# b% X
  150.                    char szSerialNumber[21];
    & t: u1 ]% l; ^
  151.                    char szModelNumber[41];: f5 D4 U. o) e

  152. ) v8 t1 T, {0 _# I' F/ I8 \; p! a
  153.                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
    & g9 k+ u2 n6 R
  154.                    for(int i=0; i < 256; i++)$ j( E, \  X4 x& k1 J1 e% ~
  155.                        dwDiskData = pIDSector;
      }4 Z* P0 Q& L; e+ y
  156.                    // 取系列号/ Y; o/ T2 ~7 [( Y2 {
  157.                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
    $ K7 ?/ k9 J1 }- ^" X2 B* I9 A( v
  158.                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));# ]# p, l& P' o$ Y0 }
  159. 1 A8 z6 y$ o; i+ z
  160.                    // 取模型号
    ) W; P& F% _4 \
  161.                    ZeroMemory(szModelNumber, sizeof(szModelNumber));
    * @7 r3 {! L) {( x
  162.                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));4 C$ j1 i4 K6 G

  163. : E& z7 H$ F# c$ {  [1 ^# n
  164.                    pSerList->Add(szSerialNumber);: S$ F* S9 P* Q6 F- i! o
  165.                    pModeList->Add(szModelNumber);4 N) p+ `* {# D7 ]9 p+ D
  166.                }
    6 B& y) i* W8 m! \
  167.            }
      l: V" u5 ?1 ^# q% }
  168.            CloseHandle (hPhysicalDriveIOCTL);
    " Z' Q# n4 k* }9 W2 l
  169.        }9 w1 O& c& M( b. f
  170.    }
    & B6 y+ x0 Q- @
  171. }) A" ?# c- h) n) F7 E' o: I
  172. //---------------------------------------------------------------------------' \& l3 e/ x& F+ _" j
  173. // DoIdentify
    7 Z  @% k8 o: C0 |
  174. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
    - w5 Y. z2 w4 s! g
  175.              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,4 j9 A# U4 p4 ?' z! L% v
  176.              PDWORD pdwBytesReturned)
    - V9 j# k/ F) e9 y2 ]0 d6 Q1 g! g
  177. {
    7 v& i0 r) Y( ]1 M
  178.    // Set up data structures for IDENTIFY command.% S- r) O( y7 o" u" A3 v
  179.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;" B$ h* u0 j# u& l" l: [4 F! N
  180.    pSCIP->irDriveRegs.bFeaturesReg = 0;
    4 Z8 O5 V- G4 a
  181.    pSCIP->irDriveRegs.bSectorCountReg  = 1;& m+ r7 A" b" _, L2 ?
  182.    pSCIP->irDriveRegs.bSectorNumberReg = 1;
    / M- s. u, W4 J3 E
  183.    pSCIP->irDriveRegs.bCylLowReg  = 0;# u$ v( m9 D( S4 h
  184.    pSCIP->irDriveRegs.bCylHighReg = 0;+ ~" O% X8 y6 D" F. `

  185. - [' i+ c3 ~" w9 C1 h. g
  186.    // Compute the drive number.(主盘和从盘所对应的值是不一样的)
    / }6 Q" _- D: f; Z+ o
  187.    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;; v" h" g* K* p
  188. : T. Q' j! J! Z% s8 c+ l
  189.    // The command can either be IDE identify or ATAPI identify.
    0 d' M8 x- I0 R) J8 w, y' V! x  V
  190.    pSCIP->irDriveRegs.bCommandReg = btIDCmd;
    4 j) W. K% v  w! O% E- x
  191.    pSCIP->bDriveNumber = btDriveNum;
    - a5 k/ m) o3 i1 A% N
  192.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;# R4 U4 S$ D! `5 Q. @, Q3 i5 v

  193. * w3 U! A; q# r* q
  194.    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,9 B9 ~9 P5 b, y& W+ W
  195.           (LPVOID)pSCIP,
    , _. [4 o  v# r: v( q6 Z' W. b
  196.           sizeof(SENDCMDINPARAMS) - 1,# g9 e6 u) S/ x$ e
  197.           (LPVOID)pSCOP,: ?3 \( i$ `( T
  198.           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
      k/ \- _, p7 T3 ~+ b9 C& h9 s9 ]
  199.           pdwBytesReturned, NULL);
    " {3 U# f8 R% O1 p. _0 w. K
  200. }: v/ u+ |2 Y. j3 N8 k0 w! b1 \; M
  201. //---------------------------------------------------------------------------9 v/ H  n5 h! n& e3 I! w8 h
  202. // Windows 95/98/ME 代码3 W- H7 @# E5 e" g) p3 T
  203. //---------------------------------------------------------------------------3 b9 m+ L1 H) b; I5 ], s2 I8 W# y* d
  204. // ReadPhysicalDriveOnW9X- L4 s' O8 x. n- [6 }% W
  205. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)
    : |5 Q5 x/ F) S2 Z( R/ n6 h
  206. {0 J1 ]6 F+ [% k# @$ @$ z
  207.    WORD wOutData[256];
    - X/ l6 h5 v4 c' z. S
  208.    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);0 z# J6 r3 J. m( E

  209. 2 E$ _' U3 J4 S6 d5 b' q
  210.    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
    + c  T% M) B) u% p: y$ \( d
  211.    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
    6 C# v5 D$ N  P" d! J
  212.    // 避免蓝屏的出现。(期待高人能指出原因)/ f2 v( k1 T7 ?8 r6 @% ~. D: d
  213.    for(int nDrive = 0; nDrive < 8; nDrive++)/ ]9 b$ A8 D6 E, u
  214.    {  ]0 ], o8 ?8 @: Z' z1 g
  215.        WORD dwBaseAddress;
    2 t$ K/ M* V( N6 u& V
  216.        BYTE btMasterSlave;         // Master Or Slave
    : ?4 b! r, Z0 J$ F/ I
  217.        bool bIsIDEExist;
    + _9 T- _& _) E
  218.        bool IsDiskExist;
    1 L7 e/ h- Q2 y/ Y7 b: y
  219. . [3 D% a8 k# A, C
  220.        switch(nDrive / 2)8 H  c6 `2 t0 D" z- l4 b1 E
  221.        {2 u* i$ M% o2 f9 G+ N; N
  222.            case 0: dwBaseAddress = 0x01F0; break;& I& c/ h5 A! v* V
  223.            case 1: dwBaseAddress = 0x0170; break;. ]* R* S8 A9 [4 X2 \
  224.            case 2: dwBaseAddress = 0x01E8; break;
      Y( w1 y5 t' b" d' p; w  D
  225.            case 3: dwBaseAddress = 0x0168; break;
    , T! Y9 X! B$ N8 Z! z2 \
  226.        }
    1 t2 y5 U; F7 c; C6 K

  227. 5 ^: v( W- c3 U6 |+ C
  228.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
    + e4 Z4 [* Y/ p! R7 e
  229.   d& J5 X* i' _( n' V# C
  230.        // 进入Ring0. L7 f2 y7 K" ]  r6 z: R5 j9 k5 V
  231.        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,/ I  J8 b4 n- X$ i
  232.                bIsIDEExist, IsDiskExist, wOutData);
    9 u0 @* M- K, B( X5 m( m
  233.    }
    3 G! ~, I8 [6 {9 W% A& }
  234. 3 Q4 K1 e# a0 S; [
  235.    // 开始读取
    ( l0 `$ i' f3 n/ M
  236.    for(int nDrive = 0; nDrive < 8; nDrive++)
    0 k( x/ s+ x7 \0 g
  237.    {5 s' ^" W8 A6 ?3 Y; z
  238.        WORD dwBaseAddress;; n& l) g( s) v" c8 V% y, Y+ h4 m
  239.        BYTE btMasterSlave;         // Master Or Slave
    # ^" G2 `$ t7 k& M2 Y* g+ r
  240.        bool bIsIDEExist;4 Y* R' O. u, s0 _
  241.        bool bIsDiskExist;
    - B; s- [8 i" N
  242.        switch(nDrive / 2)4 k+ @3 _! [; P. u9 M; A
  243.        {
    5 k! {* h% ~* f4 q
  244.            case 0: dwBaseAddress = 0x01F0; break;
    + w* L; w: ?* s# Q; ~" w; r. M
  245.            case 1: dwBaseAddress = 0x0170; break;
    5 ?) u/ b! G! V
  246.            case 2: dwBaseAddress = 0x01E8; break;- l" g7 F9 @/ r7 V, m1 k& B
  247.            case 3: dwBaseAddress = 0x0168; break;2 ^# j5 O7 j9 ^$ G2 M; ]% c- t
  248.        }
    2 f# n5 K: `/ M2 J

  249. & p6 C) I" d$ d/ z+ S, @
  250.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);  B2 M2 {8 K. m, L5 _# r; p
  251. 5 \" i% I5 U5 a
  252.        // 进入Ring01 w2 G( P# n6 B* [" P; h& w
  253.        bIsIDEExist  = false;
    : S2 c( X* L1 ]
  254.        bIsDiskExist = false;: d' o" I! r4 \) B+ b7 l7 V
  255.        ZeroMemory(wOutData, sizeof(wOutData));  P2 ?7 o- A( q* A5 w1 Q
  256. + _) g6 D7 ~9 h
  257.        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
    2 Q: T: f1 s! M" W
  258.                bIsIDEExist, bIsDiskExist, wOutData);- q  F+ `. F8 k. p) S' d

  259. % A+ o4 U5 P7 O/ ^# z7 Z) i
  260.        if(bIsIDEExist && bIsDiskExist)
    ! F. [8 X- ?8 ^( ]& a
  261.        {& C, D  [$ w# |" D0 Q1 e3 G
  262.            DWORD dwDiskData[256];8 H. s' m/ h2 W" }; s' B  v8 K( C
  263.            char  szSerialNumber[21];. ~& K% \( r1 ^0 Q9 N1 G' C
  264.            char  szModelNumber[41];' c& b1 Y* c% j8 s

  265. % e6 q+ `, [6 J$ ^( i! s+ M0 T2 l
  266.            for(int k=0; k < 256; k++)
    8 c3 ]* p9 Q5 p% Z' n
  267.                dwDiskData[k] = wOutData[k];
    3 h( i: r. U, H, N0 P
  268. 0 ^6 B" C1 n( i+ ?& _
  269.            // 取系列号
    * ~) h' N' x2 P6 D
  270.            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
    ) }0 J0 N' }' r* m/ }
  271.            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));  S% y7 v  h4 I* R
  272. 7 E2 X5 f. |* N; |2 \) k
  273.            // 取模型号/ C3 T6 h& I: e
  274.            ZeroMemory(szModelNumber, sizeof(szModelNumber));
    ; J& u5 p$ J0 K) U
  275.            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
    ' M6 J! {, }2 S: w
  276. 5 A8 ^6 Y* X6 s4 L' q5 n4 c
  277.            pSerList->Add(szSerialNumber);
    8 X/ A, \6 s' e6 ]: }
  278.            pModeList->Add(szModelNumber);$ C  D/ w6 j. d5 ^% j2 a
  279.        }
    ) d4 Q9 L2 {$ d2 P$ @( T
  280.    }
    ( j. N4 q: w1 e: u0 c8 s/ j# l0 |
  281.    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);  N' a9 u) D$ t8 N( J7 o( i5 P
  282. }4 s& f: _2 q3 e1 o9 g
  283. //---------------------------------------------------------------------------
    4 e9 U/ \" G+ H; T% \8 U
  284. // ReadPhysicalDriveOnW9X_Ring0()/ q/ D* ?3 a4 x2 ~
  285. //; [9 @2 _8 q# W; I9 f; [
  286. // dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h  F' d( Z5 p; V/ t/ E9 g
  287. // btMasterSlave = Master(0xA0) Or Slave(0xB0)6 T2 ^; Y% c5 f" [
  288. //---------------------------------------------------------------------------: u+ R5 c& k5 D' }
  289. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,5 n' I: l! b# D* x  X: a6 i
  290.        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)( Y- W' q2 H4 S: o% J
  291. {) @1 Y% F0 M' A$ ^+ g8 W* U
  292.    BYTE  btIDTR1[6];
    + l4 i7 h( k7 I& c# c
  293.    DWORD dwOldExceptionHook;
    # \  g* x1 x! ^$ K/ H
  294.    const int nHookExceptionNo = 5;
    1 j* {. E- ^% ^% P( Z( l
  295. , w; f( Z* Z: p0 A
  296.    BYTE  btIsIDEExist = 0;4 [; S/ M1 T* _) g. t5 \
  297.    BYTE  btIsDiskExist = 0;. U1 h# ?" t5 v. ]8 B( V1 c) n
  298.    WORD  wOutDataBuf[256];% B  s4 }% J$ l) S3 N; y3 N

  299. % }5 }' Z/ H; p8 H& M  [3 Q# N- D
  300.    BYTE  btIsFirst = (BYTE)bIsFirst;
    * x3 \/ G8 A8 \! f  @. N  p
  301. 7 O3 M0 |: @5 q6 e& }
  302.    const BYTE btBit00 = 0x01;/ J, a9 b, l/ v0 X; h
  303.    // const BYTE btBit02 = 0x04;
    + Y- @; {# ^6 B5 V. m* Z; L
  304.    const BYTE btBit06 = 0x40;
    3 S) l# @; l) [5 {8 x
  305.    const BYTE btBit07 = 0x80;
    + e; n' n  K8 L' W# d9 P
  306.    // const BYTE btERR  = btBit00;
    2 P5 u( i3 T5 o  ^7 j$ \
  307.    const BYTE btBusy = btBit07;
    + M/ o! F  m4 E7 @! g
  308.    const BYTE btAtaCmd   = 0xEC;9 G2 x$ ^) a- i1 q; p  i: M* J
  309.    const BYTE btAtapiCmd = 0xA1;
    ) M# e# Q  F" k7 c+ M( u

  310. 8 m$ i4 ?0 |3 X: a
  311.    __asm9 X4 _/ G: A! S, j& W$ l! O  J
  312.    {1 f# I2 h9 ?( i$ w
  313.        // 必须先执行这条语句
    ( r. f* X, t" Z" H
  314.        JMP EnterRing0
    ( B, J9 f. g1 S( a3 r0 E/ y( N% D
  315. ( u4 c0 i4 F* S  e
  316.        // 定义过程% _  l; G+ N6 S. m! F5 a: D0 E
  317.        // 等待IDE设备直到其不为忙为止
    1 X) k& T0 M/ c8 N
  318.        WaitWhileBusy proc1 x8 w2 X' I/ f
  319. + E# d$ q1 @# a6 ?# C" V! J6 W9 J# B
  320.        MOV  EBX, 1000009 f: z8 m5 M; E/ t5 \# h* M1 W, P7 [
  321.        MOV  DX, dwBaseAddress
    , e: x3 |5 o; |4 M3 V
  322.        ADD  DX, 7
    ' d. {" m1 Y+ h' ]$ A9 f4 x, r6 F' S

  323. ! m# b/ q, y2 ^8 d+ K
  324.        LoopWhileBusy:7 n3 d6 m, d* e- ~$ k5 z

  325. * M+ h5 @( u# t: w" x( S
  326.        DEC  EBX' R) {- _: U' O1 h6 L
  327.        CMP  EBX, 04 J& V+ s* y. C' k* h
  328.        JZ   Timeout
    0 X; }3 R8 i% S! r# v7 o
  329.        in   AL, DX
    + T6 R/ I: C3 t& R
  330.        TEST AL, btBusy
    . `" \/ }( k7 W( j4 n3 N
  331.        JNZ  LoopWhileBusy
    ) j- x# i1 a3 ^, P0 d
  332.        JMP  DriveReady* P# `7 B* R# ^$ \8 ]: o2 y/ K
  333. 5 l& Y. R! _+ _2 V, k
  334.        // 超时,直接退出( j" Q; M4 D8 b$ h+ v
  335.        Timeout:
    ( g% m* L' }$ b! U% t4 K& T
  336.        JMP  LeaveRing0( X9 A$ Y& _, a7 T" ~4 d
  337.        DriveReady:
    & a: l, j" ]0 F4 B  z: J1 j
  338.        RET
    + r7 h. |) c: Q2 B4 N: ?) R
  339.        ENDP   // End of WaitWhileBusy Procedure* Y$ h+ k5 X) @6 F) c6 B2 f

  340. 8 R* P4 W" Y& F  i7 `' c
  341.        // 设置主盘和从盘标志
    : d) m* v- K' s" S8 ?* d. m
  342.        SelectDevice proc2 R* e( n3 x/ b8 y% _2 w7 p0 b0 a
  343. & Y" _: d' M  G: K. ?
  344.        MOV  DX, dwBaseAddress! I: I9 j5 k  {
  345.        ADD  DX, 6  p- D5 M' b1 c  f# H/ A
  346.        MOV  AL, btMasterSlave1 K9 ^7 R2 |. @7 g+ X( |% |$ x' Z! x% i

  347. 5 t3 C' n5 B! z: D" ~4 k  ?1 I
  348.        out  DX, AL
    2 l  B1 Q/ f" Q, {$ r" ?
  349.        RET
    8 T$ y; O& F2 e9 E
  350. 8 E9 a+ J' T, z! G/ W- x. t
  351.        ENDP  // End of SelectDevice Procedure# x" |0 P) G/ y( H9 P6 B

  352. - j2 ~' ~% x9 m6 Z
  353.        // 向IDE设备发送存取指令9 d* t1 Y7 b6 R
  354.        SendCmd proc
    ; Y1 B( t. Q  ~# J0 v8 V
  355. & B+ d; `- I: V1 c9 h2 M
  356.        MOV DX, dwBaseAddress- p( |+ a" u6 m! _( s+ V" V* ?
  357.        ADD DX, 7* s2 k, T7 F4 s4 m+ i6 n
  358.        MOV AL, BL // BL是主从盘标识,在过程外设置
    ) J* V: E' @. h& O5 B) q
  359.        out DX, AL' q6 g5 j7 }* z
  360.        RET+ ?: N7 |4 y+ p( e$ W$ ?% n. I
  361.        ENDP  // End of SendCmd Procedure# f  j& n( Q% ~" M1 w; a! \: [
  362. 1 J: ^: Z' @# S" l3 _# g1 {$ u
  363.        // Ring0代码
      T+ f! `! W! i, T+ q- K; L0 s
  364.        Ring0Proc:
    % K, a' C- i! O3 o) w1 T/ \
  365.        PUSHAD# ]+ u0 v  D/ D
  366.        // 查询IDE设备是否存在
    : h( k7 @2 w1 A8 U& e4 c* D
  367.        MOV DX, dwBaseAddress% u" Q/ \# k6 g3 t
  368.        ADD DX, 7' w+ d) K7 e4 j- i1 s
  369.        in  AL,DX8 J0 }( d) ^. J- V; k

  370. 2 J5 F" [7 [& }# h" v: A1 O
  371.        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
    / k& ~+ J2 A# z2 T) L& [
  372.        CMP AL,0xFF
    # P6 O* I% x7 [# o; V, v' d# V- n
  373.        JZ  LeaveRing0
    1 t8 D) t! b# S* }# S+ j% q# _2 Y1 q
  374.        CMP AL, 0x7F
    5 B3 x2 Z+ \8 z& w: s. E2 P) ^
  375.        JZ  LeaveRing0# K. X* N& R* W% ?' ?
  376. 1 i" r& ?% i) Z/ B) |% G
  377.        // 设置IDE设备存在标志
    6 S2 X: ^) I0 a/ K! t
  378.        MOV btIsIDEExist, 1
    : q. i  m' \3 z: m5 P  f  u
  379. & y( u- O1 \: z, D: }; ^* \
  380.        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)9 y/ M: t4 v! ^
  381.        CALL WaitWhileBusy
    ) y8 [' `% B, K
  382.        CALL SelectDevice2 J9 ?' t$ t4 C2 |  B/ t1 R

  383. / v' K7 @  z+ p# H& o
  384.        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏, h0 e; ^" l7 |; G0 u( x
  385.        CMP  btIsFirst, 1
    ! R. Y  H0 G9 ^
  386.        JZ   LeaveRing03 Z2 M9 y' |/ E; ~% h
  387. : R- F* b: \( r, q* G) S5 B8 [
  388.        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
    4 x& E) `- C; [4 W) e- h# [8 d" b
  389.        CALL WaitWhileBusy/ V- f) F! x" d8 p, A9 h( I
  390. 3 e, y1 X/ o5 D% ]
  391.        // AL的值等于cBit06时,不存在驱动器,直接返回% x0 k' R& X- i, Z6 ]' x
  392.        TEST AL, btBit06
    6 p& e- ~, u; Z- ^% k
  393.        JZ   LeaveRing0, m, |. S' g4 |8 s- |4 }

  394. 9 g0 G2 \6 g; {, K- Y6 y! x) `
  395.        // 设置驱动器存在标志. x1 P9 F3 I) e# f
  396.        MOV  btIsDiskExist, 1- K3 n9 `/ U2 i& ~, q4 C6 T9 ^
  397. ) G" V! k+ v# F7 l$ j& N
  398.        // 发送存取端口命令
    $ [: l2 J( I0 g/ G
  399.        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
    1 N5 m* O1 j8 L. _& M5 z
  400.        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
    : f* L' r& Z9 l0 ~) Y
  401.        CALL WaitWhileBusy/ V5 t. j4 l# \' C" t/ X! r
  402.        CALL SelectDevice    // 设置主从盘标识( w9 \/ L# Z2 h$ I2 X
  403.        MOV  BL, btAtaCmd      // 发送读取命令9 S* f5 ^! _0 p+ v4 c
  404.        CALL SendCmd
    7 G5 o% I2 j4 |+ s  f8 M
  405.        CALL WaitWhileBusy
    % N- M; e# P( {1 `

  406. ! e+ C+ k) z# j  h7 b# D8 J  s
  407.        // 检查是否出错
    - Z% m1 @* v' V( [) r4 ^
  408.        MOV  DX, dwBaseAddress9 Y  B6 X0 ]( Q# D3 B! Z
  409.        ADD  DX, 7- {4 _2 ?: ^9 n) k
  410. % E3 w5 o/ c% H% F0 O* f0 W
  411.        in   AL, DX  f/ b0 p! S+ t) V5 A. q; ~

  412. 4 z% N: |3 J0 o7 g0 f9 e
  413.        TEST AL, btBit00
    - y4 g) D9 R( r/ d* J% G3 y0 j' [
  414.        JZ   RetrieveInfo   // 没有错误时则读数据
    $ K5 {* P5 I. Z8 d

  415. $ U, }& |- Z4 v: R: M
  416.        // 如果出错,则进一步尝试使用ATAPI设备命令* ?+ s. }; i. h- k) M, w
  417.        CALL WaitWhileBusy/ C$ H+ U" y) |# |7 {7 C
  418.        CALL SelectDevice5 x$ y% b( P# G7 w- j0 ?3 u
  419.        MOV  BL, btAtapiCmd
    6 c  ~; R7 N) N5 `; P
  420.        CALL SendCmd7 v+ e( Z/ V. z8 S- I  q! b5 P1 ?
  421.        CALL WaitWhileBusy
    & J5 R+ N1 k  n. J7 z, Q

  422. + `3 O% X5 O1 T; i# U
  423.        // 检查是否还出错
    + L" G) \3 c* p+ ^- |. T
  424.        MOV  DX, dwBaseAddress4 x9 L# d! q0 l2 @/ e
  425.        ADD  DX, 74 u) y5 X) k9 N' ]$ o4 O* h% Z
  426.        in   AL, DX
    % d( ~+ }$ P# H) |- T
  427.        TEST AL, btBit00( t) N5 M8 F  |5 |. p
  428.        JZ   RetrieveInfo   // 没有错误时则读数据0 m# W+ s  Y5 ~4 c$ m( m
  429.        JMP  LeaveRing0     // 如果还是出错,直接返回
    7 H& }4 F6 S6 b' q$ w( W0 g  V

  430. + Y9 G1 `+ m0 i/ l3 Q! Q
  431.        // 读取数据
    & T- a5 y) L$ [' l* U
  432.        RetrieveInfo:. R6 K. ~& N5 {. j0 e  m  p
  433. % ?! Z# H! p6 T: q5 n# L
  434.        LEA  EDI, wOutDataBuf
      {* Y, o$ y9 J0 b2 U- B2 A; p: E
  435.        MOV  ECX, 256- N! d( F: c3 g6 U# Q
  436.        MOV  DX, dwBaseAddress& B: P, ^+ }6 X  s* k: V3 b
  437.        CLD
    ) |- y9 F& k! t/ k' \/ }/ D

  438. # c0 V" F5 I; @; W6 w# @7 |8 O( H
  439.        REP  INSW
    ; P1 f, y+ P: P  i4 T# R/ ^

  440. ; [: J5 v; \  {) ~2 m
  441.        // 退出Ring0代码% ~4 ~0 g5 \5 z# U5 X2 e
  442.        LeaveRing0:
    ) |2 T- P3 ]# v, k
  443.   @" R: p- \, w+ h& h, T
  444.        POPAD5 j9 P- P) y8 D( _. P4 _7 ?+ ]$ e
  445.        IRETD
    & W, d0 x4 [7 I

  446. 3 n1 @" S( s  O( t
  447.        // 激活Ring0代码
    & {* J, Y6 H; C) q3 E" V
  448.        EnterRing0:
    0 |3 f$ n" a. c0 f9 Q

  449. 7 u1 @. _/ J% t
  450.        // 修改中断门3 O0 a+ F1 j6 J3 M/ o
  451.        SIDT FWORD PTR btIDTR1' D1 _* Z# g2 u3 W  {7 p
  452.        MOV EAX, DWORD PTR btIDTR1 + 02h* \$ E" q/ Q, z! z8 Q! W
  453.        ADD EAX, nHookExceptionNo * 08h + 04h% `( p/ c5 J9 _" O3 {
  454.        CLI
    : T% A% p7 b7 ]6 w: G

  455.   ]$ N6 R4 K5 n; j+ ^
  456.        // 保存原异常处理例程入口; ~2 b4 a2 y5 l, H! D5 c" B- r
  457.        MOV ECX, DWORD PTR [EAX]; I& X- }6 j1 S. N
  458.        MOV CX, WORD PTR [EAX-04h]
    ! R/ n8 c. b7 I2 q0 j2 p" d; F
  459.        MOV dwOldExceptionHook, ECX1 w0 l  `6 b) ~3 F0 b

  460. / _. L* {" L* D, M* }, N7 y' V6 s
  461.        // 指定新入口4 g4 [# H6 \9 S9 U$ H6 Q1 b
  462.        LEA EBX, Ring0Proc$ f$ n/ r! k. ~4 m1 \
  463.        MOV WORD PTR [EAX-04h],BX
    ) w* {% B* }5 G9 |& o1 x5 H, E: X
  464.        SHR EBX, 10h
    : U0 R. b8 n! r* a* Y4 ]
  465.        MOV WORD PTR[EAX+02h], BX
    9 v; M7 ^1 E0 z: C+ o2 Q

  466.   O2 y  B0 V$ r, P0 k# R
  467.        // 激活Ring0代码1 _. P+ R5 `0 f4 k
  468.        INT nHookExceptionNo( ]* H  G1 F, n" P% ?* s' A

  469. 0 {9 M0 x2 {$ J; ^1 Z; E
  470.        // 复原入口6 X1 K% [2 b0 Y3 ^/ G# l# `6 u
  471.        MOV ECX,dwOldExceptionHook7 r! ?  L2 [" G" [8 T
  472.        MOV WORD PTR[EAX-04h], CX/ L, \8 T0 p' U7 y! }  q& |( _
  473.        SHR ECX,10h
    4 Q3 `' }( Q9 m$ n
  474.        MOV WORD PTR[EAX+02h], CX8 K" N" e  n  \3 O
  475.        STI1 K8 y  p9 Z/ m' B8 ?) D" X
  476.    }, e" F, A9 f* u- O+ |4 M) j% S
  477.    if(!bIsFirst)( s# V! T# T  r3 H* L& C
  478.    {! P3 a/ y& k& n6 b) G0 E& k
  479.        bIsIDEExist  = (bool)btIsIDEExist;4 |9 p" Q; v7 A- q/ F
  480.        bIsDiskExist = (bool)btIsDiskExist;) Q7 z6 H. U% W/ \, J# `
  481.        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));" j% Q0 W; V( O3 O. }  |/ }) M
  482.    }
    & O' A; f9 R8 I% C, `3 y, z
  483. }
    3 F; D/ q7 h! |2 j# f- m
  484. //---------------------------------------------------------------------------
    + N/ ~) ]( S4 O  q4 |2 B% @
  485. // 调用方法:
    9 c' `8 K: D% i, `
  486. void __fastcall TForm1::Button1Click(TObject *Sender)
    , ]+ |, a# I; Y# A4 `
  487. {
    9 _' S% {+ \' K0 {1 t6 _3 [
  488.    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
    / t- c8 {' k1 I$ G8 q1 x! n
  489. }
复制代码
发表于 2005-8-15 01:00:45 | 显示全部楼层
晕乎乎。。。怎么看8 洞阿
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-5-5 10:25 , Processed in 0.015916 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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