找回密码
 注册
查看: 5205|回复: 1

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

[复制链接]
发表于 2005-8-11 11:42:04 | 显示全部楼层 |阅读模式
  1. #include <WinIOCtl.h>* n# i5 V  B/ }! H
  2. #include <stdio.h>1 V3 {  e1 l6 y+ [  V# i, h& n

  3. . h, a; d3 ~, |. B& M) l
  4. #pragma inline
    ( u7 M9 l8 o+ S0 k8 R  S
  5. //---------------------------------------------------------------------------
    # ~7 X$ a+ y. a6 [
  6. // IDE NT/2000/XP专用变量
    $ j* f, T6 S1 t1 y1 ^
  7. #define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS. c0 e( g$ T3 b1 c
  8. #define DFP_GET_VERSION         SMART_GET_VERSION2 c* Y" |( b( n7 I- X( C+ m7 P, ?2 j
  9. #define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
    2 U* S* v2 K5 k  j9 b  E
  10. #define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA# m" r% B% E8 ^; ]5 j

  11. # O& c* J  X! c( s
  12. const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令
    # Q# H9 @( E2 h! a0 p
  13. const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
    5 q9 E0 d7 w) h' y, D% A
  14. / B4 W8 b2 J- Q* a( L7 s# e
  15. const int MAX_IDE_DRIVES = 4;+ F9 x5 s% a7 I9 }
  16. * o. B9 F0 X3 [
  17. // SCSI专用变量8 d. H' @5 ?7 l: ~
  18. const DWORD FILE_DEVICE_SCSI             = 0x0000001B;
    : d! k7 g- Z. V% c( A
  19. const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
    ! I1 I& J' @+ Q( b2 \
  20. const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition$ x( b$ ?6 B: L& F* P
  21. const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
    ! j( w' j7 M3 W2 y

  22. 9 p4 U. |- }8 ]) g0 r
  23. typedef struct _SRB_IO_CONTROL  L: I6 L. ^  W/ t9 b' R$ w
  24. {
    $ i3 y  @- Q" U
  25.    ULONG HeaderLength;
    9 Z. T9 m- z3 B+ d  s5 F. m
  26.    UCHAR Signature[8];, J( P* c% A6 d
  27.    ULONG Timeout;4 |; ~0 z7 }% _; D: `% C' b$ T
  28.    ULONG ControlCode;* u( q( m$ @) v1 B
  29.    ULONG ReturnCode;
    7 g/ F) p8 q8 N" F5 L0 e7 X
  30.    ULONG Length;3 a) Y8 B2 E; J' u3 h) I& t; B
  31. }SRB_IO_CONTROL, *PSRB_IO_CONTROL;
    2 q7 Y5 C9 T* h6 i, @
  32. $ }* P) ~/ S; o7 F6 K7 C, I% B
  33. // 读取的主函数: i  X3 ~) R+ `9 t9 W" ]. c
  34. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);4 ^4 F" m4 o/ ?4 S- G$ ?1 ?* u+ K

  35. . t; M& j0 j) w8 N' i3 H
  36. // 辅助函数$ y2 l- Q9 x( z  a6 R( ^
  37. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
    - e- [" j/ S$ l+ R2 m/ F! l1 M
  38. // NT/2000/XP函数& s2 x$ A# e6 S0 e" k
  39. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
      B* W) P. X1 H/ _. {# J
  40. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
    % V3 v; B+ l- Q7 M* r" T# [
  41.        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,5 t( M/ ^; v" c0 L, T
  42.        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
      A* S- r7 G0 `% ~
  43. // Windows 9X函数
    5 F9 g* d7 R  m! n
  44. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);) }* [: s* x7 K+ @% C$ d2 Q. ~3 F/ q. ?
  45. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress," }4 O9 x7 o" t$ T% h2 t3 W6 U
  46.        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
    ( |* x- o$ ]7 }- S3 y: m% F

  47. 2 w/ |# m: F5 ~" p$ g8 _# _
  48. // SCSI读取函数(for NT/2000/XP)
    % d, g; J; C0 C. m% r' N
  49. String __fastcall ReadIDEDriveAsScsiDriveOnNT();
    7 C  I, q$ A% x6 A& N
  50. //---------------------------------------------------------------------------8 ~# B" C$ }) c6 D+ Z% [& m$ J2 }
  51. // ReadPhysicalDrive) \6 {8 ]+ a0 }  W+ Y
  52. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
    , C: ~! m( F3 Y9 x% S# N
  53. {
    7 e+ Q2 \! U7 }1 J6 g# h1 Q& h7 @, G
  54.    switch(Win32Platform)
    1 ~& ~, k  Z' {3 l
  55.    {$ h3 H0 D( ~/ z
  56.        case VER_PLATFORM_WIN32_WINDOWS:
    % N9 _: N: D  X# h4 q) e6 p
  57.            ReadPhysicalDriveOnW9X(pSerList, pModeList);) i3 s/ b. u9 C0 _/ W( w: n9 z( m
  58.            break;
    ' D/ v$ X% s1 }5 J
  59.        case VER_PLATFORM_WIN32_NT:3 e, l$ s  {  @* P3 j7 J( N
  60.            ReadPhysicalDriveOnNT(pSerList, pModeList);6 D: {/ h$ a2 }7 J( S, Z/ X
  61.            break;8 w+ r4 `# S/ p$ P
  62.        default:
    ! t2 D! |! {! S; {
  63.            break;
    0 B' k3 L7 C. ^. B
  64.    }
    . M( c, N  C9 F* \5 r- {
  65. }
    3 B4 g$ o, f3 G5 ?8 N# Q
  66. //---------------------------------------------------------------------------9 ]- e- n' a' x: W4 K5 S
  67. // ConvertToString
    / d; D3 [8 b; H5 f
  68. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
    6 ^9 N+ w! r' h3 v
  69. {4 o7 F% ?, {; t: e
  70.    static char szResBuf[1024];
    / U9 H- q- u1 _- i/ f
  71.    int nIndex = 0;
    5 q, l( q# S+ W' z2 S4 J
  72.    int nPosition = 0;$ d0 g* B% M- t$ {
  73. ( |* @  t+ y3 t6 G
  74.    // Each integer has two characters stored in it backwards
    ( S0 T3 b0 o% c7 d  l1 P# n0 D! A. _
  75.    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
    % A3 d+ o: ^/ M- l$ k9 O
  76.    {
    3 O# B; t! ~5 A1 s! Y4 d8 R& A5 C! h
  77.        // Get high BYTE for 1st character
    # v. x: }8 L, |' g. n) F
  78.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);0 ~' ?5 O, @  U
  79.        nPosition++;
    * m+ f7 C' T( s9 @6 f5 I+ o5 y
  80. 1 I% K6 I/ U: s$ `
  81.        // Get low BYTE for 2nd character
    9 t8 o# z$ ^$ f$ M5 h! G
  82.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
    ; ~  e. k4 z' y& q/ _2 P$ l0 B0 t
  83.        nPosition++;
    1 }1 A$ G' ~5 ]9 G2 n
  84.    }" p, v- I, O& b+ I0 u5 b; m
  85. - N% q7 j9 G, J6 q+ i" L, A0 C
  86.    // End the string" x* T3 ^! z: m+ W/ t; h
  87.    szResBuf[nPosition] = '\0';
    3 W. e$ M. ?/ v7 {. ^; g
  88. " v6 w* ^' E9 u8 {7 B
  89.    // Cut off the trailing blanks
    3 S* x0 {2 V6 `( s+ Y  n+ H
  90.    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
    $ P8 \9 O0 W, y5 E  I
  91.        szResBuf[nIndex] = '\0';
    3 _3 L1 x" {- E2 {4 s& G
  92. 5 [2 h* \! H8 U" A
  93.    return szResBuf;/ m) K1 ?- t+ l# |* P- V
  94. }
      u( j! d  T' A+ s7 }7 i3 U
  95. //---------------------------------------------------------------------------
    ) u7 e% y" A* J# }9 ]
  96. // Winndows NT4/2000/XP 代码' u  }" @  O1 C/ g3 X" E
  97. //---------------------------------------------------------------------------0 c: W& s& z/ _$ p- o
  98. // ReadPhysicalDriveOnNT; ]# `- J# Z( V6 G9 Q6 F
  99. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)* F9 r. k2 a- c  q, N
  100. {
    " _3 e7 K& x) a" x* S
  101.    // 输出参数* _3 {. V* v( [
  102.    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
    8 |* ?. L5 ]4 W6 s% d& i
  103. 4 q+ a3 p( p% D1 o2 @' K
  104.    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)- X! Q+ c( J4 f! }6 a
  105.    {
    $ \" c  f# o- ^7 a* e5 H* o3 l7 R% _% z
  106.        HANDLE hPhysicalDriveIOCTL;! s0 k; A* j1 t' y. f
  107.        char szDriveName[32];6 Y2 K3 [$ j/ p: i

  108. ' h+ K, l: a; |* D" x* a
  109.        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
    * _! ^0 g' I+ w. k0 [* a- R
  110.        hPhysicalDriveIOCTL = CreateFile(szDriveName,) o7 D' @# Q; b6 [
  111.                        GENERIC_READ | GENERIC_WRITE,1 P, u* n& L% s9 S$ f$ }
  112.                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,. {7 m& |7 r1 s+ u
  113.                        OPEN_EXISTING, 0, NULL);
    8 ]& Y) o8 Y5 P% \( p: u

  114. $ t+ F% b" s2 U: {( D
  115.        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)6 \4 t/ ~) ~) G4 s2 W- l1 V
  116.        {
    3 O/ `! E, |8 R3 l
  117.            DWORD dwBytesReturned = 0;
    ( n) a- c# M3 j& v* K7 y
  118.            GETVERSIONOUTPARAMS gvopVersionParams;
    5 `9 O# t3 }0 _

  119. 0 E9 R! ?# T7 _# p9 t7 Q
  120.            // Get the version, etc of PhysicalDrive IOCTL
    0 q+ @: G' ?+ N; x7 r3 s/ X
  121.            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));( I$ p  g' o, V+ W6 r

  122. " M* ~; t1 v5 T2 ?8 g% w& K) @
  123.            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,2 o- p5 X+ t. O. r  G7 p+ b. \
  124.                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
    3 S% H/ ~2 T) [* |0 v) A
  125.                    &dwBytesReturned, NULL))/ w  T: a6 l* H3 t9 U
  126.            {
    , g3 x: n# }  w% T
  127.                continue;+ u" C7 t$ n" ^2 {' i' Y
  128.            }
    ! i" T- I; W4 Z) u
  129. : b1 t: [2 j! H1 V7 c4 O6 w
  130.            if(gvopVersionParams.bIDEDeviceMap > 0)& K8 N% E' [. p: x5 R3 m
  131.            {
    ( k* z% ]5 [- l: m4 r8 [( D
  132.                // IDE or ATAPI IDENTIFY cmd6 C( b* @5 y  I' s/ N! i. u& ^/ c0 ~0 }" x
  133.                BYTE btIDCmd = 0;% z( k) I" X$ Z- I/ Z/ @
  134.                SENDCMDINPARAMS InParams;9 q" w* J/ |1 H5 R, E# L
  135.                // Now, get the ID sector for all IDE devices in the system.0 x2 Y. E! A% F, U2 L" x7 `
  136.                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
    % U( W. H7 |8 n9 p1 i# y
  137.                // otherwise use the IDE_ATA_IDENTIFY command
    1 \9 w- d9 S2 Y
  138.                // 具体所得结果请参考头文件中的说明3 g0 g3 d9 R, j7 Z
  139.                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?9 J4 A7 `$ @/ E9 N
  140.                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
      |3 L- u% r+ N2 R2 C
  141.                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
    - `7 _7 i( |* {  i
  142.                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
    $ L) `$ F4 ?+ u

  143. ; [6 \/ j$ _/ k0 u& ?
  144.                if(DoIdentify(hPhysicalDriveIOCTL,
    ( V% Y; W1 H$ A3 x; X8 ~" c" g
  145.                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,1 _  O. v2 n. P+ ^4 s4 _2 U& s
  146.                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))( |7 a9 I2 i7 V4 k7 W
  147.                {
    ) V# Y8 m0 H/ u& ~
  148.                    DWORD dwDiskData[256];8 f* b* u4 d6 l0 d! T" r- X$ w1 v
  149.                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
    . `' n6 d; W4 J6 H7 i' g
  150.                    char szSerialNumber[21];$ M/ o5 x8 r$ ]; c
  151.                    char szModelNumber[41];
    $ [3 ~8 s- K8 t  U
  152. 3 M3 a( _  ?( V" V
  153.                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;+ f6 r( Y2 j# H5 `
  154.                    for(int i=0; i < 256; i++)  W! F$ c( x) Y8 }
  155.                        dwDiskData = pIDSector;1 H. Y( a: u% T7 @/ M
  156.                    // 取系列号3 L) j4 ]% \& i! ~, e" R/ I! P+ w3 y( h# C
  157.                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
    7 g+ }! L0 R! n
  158.                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
    4 Q* [* Y. A1 b7 b1 N  q
  159. * F' n3 w1 I0 I
  160.                    // 取模型号! R, U1 b( j% j3 S
  161.                    ZeroMemory(szModelNumber, sizeof(szModelNumber));! G- o+ d3 @& V5 w7 c( ]
  162.                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
    & D8 z8 g  B2 D0 O+ w

  163. 2 x/ J9 k! J/ M5 C
  164.                    pSerList->Add(szSerialNumber);
    $ R$ y- w3 b3 a% Z. L
  165.                    pModeList->Add(szModelNumber);
    % T; U$ r- J9 _& x8 J
  166.                }
    1 F6 V2 K" d7 H9 z- u/ J( D
  167.            }6 @  C( i- Q% l  A/ `" ?
  168.            CloseHandle (hPhysicalDriveIOCTL);3 l7 T' V, W$ d% h, m, R$ q8 _& M
  169.        }
    ! ~2 [6 `& e* L! q7 F
  170.    }. |. p- @) x- A0 C
  171. }) ]6 Z7 K: m7 a" ~0 h3 M  _
  172. //---------------------------------------------------------------------------) ^# ?7 U( d# p/ z; U4 T2 d
  173. // DoIdentify
    ! `* b+ X! W6 W" j+ p  `
  174. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,. W+ W* o) C4 k: E- ], j3 s* E+ S
  175.              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,( ~" ?) n5 M! l8 f  X
  176.              PDWORD pdwBytesReturned)
    - ]& G6 ^- t9 s) g( X
  177. {. B% b' A: W: k8 E
  178.    // Set up data structures for IDENTIFY command.
    + I; [( O3 j7 S1 G, T% I. Z# ]# w
  179.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;$ j5 H+ d" X# M
  180.    pSCIP->irDriveRegs.bFeaturesReg = 0;
    9 t3 u+ q1 \1 M# @
  181.    pSCIP->irDriveRegs.bSectorCountReg  = 1;# W3 _7 J) M' P& z# O' v
  182.    pSCIP->irDriveRegs.bSectorNumberReg = 1;
    . k8 w! T3 w4 w8 l9 z
  183.    pSCIP->irDriveRegs.bCylLowReg  = 0;; T! s/ h: c4 C8 g/ X0 G
  184.    pSCIP->irDriveRegs.bCylHighReg = 0;
    / [3 o+ {( Y9 s# A, Y, @
  185. ; s9 S/ T$ Z2 j5 g7 n* Y- C: ?
  186.    // Compute the drive number.(主盘和从盘所对应的值是不一样的)
    0 |( }/ H1 _4 Z$ f  f; I
  187.    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
    4 |" F, u% j2 c8 V4 {6 V+ C
  188. - }1 D" X: W2 M" l% r1 a/ t
  189.    // The command can either be IDE identify or ATAPI identify.2 y8 A; q, p  u) y8 k! A& X) K' u6 p
  190.    pSCIP->irDriveRegs.bCommandReg = btIDCmd;
    2 `4 l* m  X/ C
  191.    pSCIP->bDriveNumber = btDriveNum;/ Y6 G, j4 W& P$ v- W4 U
  192.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
    * W0 Y) l9 z! t1 ]; t
  193. ( ]& I5 i( O9 n  b; j1 z
  194.    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,  _$ S% H2 i) R1 q( C3 \) ?, V4 B
  195.           (LPVOID)pSCIP,
    7 D0 i- X( n- t
  196.           sizeof(SENDCMDINPARAMS) - 1,1 H5 y+ O8 i6 U* R& K* ?) L
  197.           (LPVOID)pSCOP,
    3 ~- {/ n' Q8 T, O$ S
  198.           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
    . a- ]7 a" j: K
  199.           pdwBytesReturned, NULL);4 \- O$ {3 a* I9 r- {, F
  200. }) G' B; g7 r% |
  201. //---------------------------------------------------------------------------
    5 ]1 ^: x) ]; u1 \* d
  202. // Windows 95/98/ME 代码; N2 K8 F$ r$ A$ E% }
  203. //---------------------------------------------------------------------------
    ) d; ?/ j$ y2 n5 s& q! y
  204. // ReadPhysicalDriveOnW9X  E+ x& }( f8 @1 [5 x( t/ Z: p
  205. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)) t/ @) D0 @9 {4 x  l7 X8 \+ F
  206. {
    9 X5 U- ?" c& `. V
  207.    WORD wOutData[256];* d# {7 ~- J- l1 h0 P8 b
  208.    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);. l+ ^$ o9 h  E6 q- |  c$ S* S

  209. # C) {) }6 w( {& G
  210.    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
    , J- H  i5 f5 [3 d% t
  211.    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
    # ?- C( h# W1 w, [4 Q1 N
  212.    // 避免蓝屏的出现。(期待高人能指出原因)
    : d# z% \( H7 _- I5 D
  213.    for(int nDrive = 0; nDrive < 8; nDrive++)
    - D' c& j( Y; U2 Z0 i; W3 Q
  214.    {5 k$ b: \( J4 \! t3 ~9 B' Q3 f" N1 ~
  215.        WORD dwBaseAddress;
    . B' L- b2 [9 @+ M+ r( o; h$ [
  216.        BYTE btMasterSlave;         // Master Or Slave3 w/ G+ z7 _- S4 B& K3 U- u
  217.        bool bIsIDEExist;
    ' @, l6 e6 z9 S
  218.        bool IsDiskExist;" |! }) P& u% A# _0 Z# x% A4 C

  219. 3 n! Q; _) H2 L
  220.        switch(nDrive / 2)! S4 O3 I  \2 C4 K4 J7 Q
  221.        {
    * y  R( d# h5 f5 M/ e# i$ C6 ^
  222.            case 0: dwBaseAddress = 0x01F0; break;
    % Y0 L" y! b9 K& w* h+ y
  223.            case 1: dwBaseAddress = 0x0170; break;
    1 }# W1 l1 E5 ]
  224.            case 2: dwBaseAddress = 0x01E8; break;% Z5 a7 H/ S. ~: g+ Y& k1 a" z
  225.            case 3: dwBaseAddress = 0x0168; break;' |( }+ ^& ~( M3 }( o8 ?
  226.        }5 U7 |6 x8 l2 r; u5 T& ?

  227. 7 q# {1 T3 T8 A
  228.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);7 v! F) X2 |1 W& g$ c+ A
  229. 7 [" V9 P0 B7 A5 W. j$ M7 B
  230.        // 进入Ring02 \( O* J$ g: u
  231.        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,% s- N- D1 q4 K  P
  232.                bIsIDEExist, IsDiskExist, wOutData);3 J4 Y* X" L8 W
  233.    }  ?$ e& k5 ]/ }/ X1 ~# `% P
  234. % V' d8 U& M/ j0 J7 e$ y
  235.    // 开始读取* A& J$ W6 `4 z& |
  236.    for(int nDrive = 0; nDrive < 8; nDrive++)1 }; i5 c( O+ j& l5 O* j
  237.    {
    8 _) N" d5 E' f
  238.        WORD dwBaseAddress;" g. ^, L3 ~6 E, \1 L
  239.        BYTE btMasterSlave;         // Master Or Slave
    - `2 V' a; T3 S/ h" `
  240.        bool bIsIDEExist;
    / k5 c5 `1 i7 e% L; S" I
  241.        bool bIsDiskExist;' I1 d; N% J2 W) ?
  242.        switch(nDrive / 2)* R6 n2 M  X6 u9 Y
  243.        {2 _: h3 ~( i' i/ x) X0 N
  244.            case 0: dwBaseAddress = 0x01F0; break;% u6 i3 h8 P  K+ A6 m) d9 k  A
  245.            case 1: dwBaseAddress = 0x0170; break;
    ( k& T$ B8 q# S8 ?. @/ k: P; b
  246.            case 2: dwBaseAddress = 0x01E8; break;  }% X/ M. r' H
  247.            case 3: dwBaseAddress = 0x0168; break;: P% u3 j1 Q2 ~2 Y; ]
  248.        }( {0 ^, C+ T/ z: H* H( s

  249. * U% J% T! ~! o1 Y3 G/ u3 _: }
  250.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
    0 F4 c5 K9 E  j5 Q$ Y: L1 J: j
  251. * E/ O1 S* c- i# W, b
  252.        // 进入Ring0
    5 \& G0 }2 U% ?$ `1 ^# L
  253.        bIsIDEExist  = false;5 D- a+ t+ Z: W5 M! I# @
  254.        bIsDiskExist = false;0 @) m1 l) Y1 I8 A' ^5 T6 @+ E4 t6 q/ D" Q
  255.        ZeroMemory(wOutData, sizeof(wOutData));5 N6 f4 u0 B& F: X4 R

  256. : g2 [. \2 |& D5 a8 j3 c
  257.        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,' c. u* d0 ^( V
  258.                bIsIDEExist, bIsDiskExist, wOutData);! a/ g) X# m7 \' s: u# Y5 M
  259. ' b; `% i, _: |) e- R" @& W
  260.        if(bIsIDEExist && bIsDiskExist)
    ; S3 y1 R* K* r# `% a5 n
  261.        {
    , V3 T* r- h( b1 \7 c
  262.            DWORD dwDiskData[256];
    * R+ \( r/ ~* h9 y' _; A( Y
  263.            char  szSerialNumber[21];
    & z0 ~( ]5 c/ N% i$ y( h  S
  264.            char  szModelNumber[41];
    , R! p, o$ L- d6 I

  265. ' i3 P) U6 y9 d& D. I& p$ N& d
  266.            for(int k=0; k < 256; k++)/ v/ X6 M7 Y1 j9 w) g; S# H
  267.                dwDiskData[k] = wOutData[k];+ T1 s* L* F6 J8 U4 A7 Y

  268. & x# L8 l/ Z  u6 Z  E, E) p& A
  269.            // 取系列号8 p, L* G5 w# G$ t% u+ I
  270.            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
    2 }4 ?) a4 \% O! x" ^
  271.            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));1 A: U. Q" C3 L" b: X; N

  272. 1 s1 N. l/ g* w% F0 o2 P+ h
  273.            // 取模型号( Y& e. r" C8 s( A4 X. N
  274.            ZeroMemory(szModelNumber, sizeof(szModelNumber));
    ( D0 `4 m. w# }" D
  275.            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));7 g# v0 @9 \. @; n

  276. , I3 P$ g! K( [# W! ]( B4 w
  277.            pSerList->Add(szSerialNumber);
    # W0 D$ h* `. c2 U% _- r5 I! D
  278.            pModeList->Add(szModelNumber);
      b( v# i" b$ [0 s* i! A- `" d
  279.        }
    8 ~3 z5 z0 _( e6 t8 r
  280.    }7 H* y0 m; B. |* m. u4 Y6 M! E7 n
  281.    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
    9 k# S, T9 }; c9 u7 w/ T. r
  282. }3 g8 [+ |2 O, T9 t
  283. //---------------------------------------------------------------------------
    + d( d3 ~# v# D2 R4 {8 H
  284. // ReadPhysicalDriveOnW9X_Ring0()/ k, q; ]: O8 S. Q
  285. //5 d. m# a3 q3 A2 @2 L6 L
  286. // dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h$ U% p! x# o) g5 R6 L
  287. // btMasterSlave = Master(0xA0) Or Slave(0xB0)
    ( f9 q- c) X6 H" i0 O) j& A
  288. //---------------------------------------------------------------------------
    " u( }0 [# S- {* [' e, N- b! g2 u
  289. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
    2 i2 z2 G8 ~! Q+ a
  290.        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
    6 S0 S1 [$ G; f" \( k* s* B
  291. {0 k' r2 g- F2 I) K
  292.    BYTE  btIDTR1[6];. P4 F. N# W' z% l
  293.    DWORD dwOldExceptionHook;# l# d! d7 D! ?3 B
  294.    const int nHookExceptionNo = 5;
    % V% k8 R8 H1 R. K8 A6 |
  295. & I% E0 V8 Y) Q2 _
  296.    BYTE  btIsIDEExist = 0;
    ' {5 c1 ]6 }" [) ]; w) D- k/ O
  297.    BYTE  btIsDiskExist = 0;. t  M% W0 c; \3 _6 t# w
  298.    WORD  wOutDataBuf[256];
    & ^6 p% V  m: L8 g& I
  299. % M) {8 _) V* V. o* p
  300.    BYTE  btIsFirst = (BYTE)bIsFirst;
      P- T& c6 K. k7 y

  301. ( P$ O2 Z# O) a' L7 }2 F0 l( M
  302.    const BYTE btBit00 = 0x01;  `) }: E. O  F
  303.    // const BYTE btBit02 = 0x04;
    3 X. T( e9 q( b" V, m; `0 s0 l
  304.    const BYTE btBit06 = 0x40;* v0 p4 N  ]1 f* q
  305.    const BYTE btBit07 = 0x80;/ N$ H' r5 P9 b
  306.    // const BYTE btERR  = btBit00;
    4 G1 {: `9 e* s; T( }0 u. ?
  307.    const BYTE btBusy = btBit07;+ _2 @) t8 ^% l% F3 C
  308.    const BYTE btAtaCmd   = 0xEC;* E0 L/ x' W/ R4 _/ G
  309.    const BYTE btAtapiCmd = 0xA1;5 [" T  G$ J. g8 d( n/ G; }
  310. 1 e& {( p# Z% ?' t/ b1 y
  311.    __asm4 x8 w' Z4 L; z9 x/ _. ^- Q
  312.    {# C: S2 ~* ~$ R2 G- N
  313.        // 必须先执行这条语句
    5 S; ]1 [0 |3 m
  314.        JMP EnterRing0% R# S. C, Z, `, O/ o* P* P
  315. 2 y* t; {4 B7 y, N2 b
  316.        // 定义过程! p- N2 p& f  ~# t& ~3 N+ l; J0 I
  317.        // 等待IDE设备直到其不为忙为止
    2 ?6 ^- k3 Y. M9 Z7 t7 n( K
  318.        WaitWhileBusy proc
    / b/ _% J2 c3 s) s% l' X
  319. " ]+ _9 u/ ~( q3 O3 n$ T' V, b; V, [
  320.        MOV  EBX, 100000& ?  D# X: I2 _0 a7 }0 M4 u
  321.        MOV  DX, dwBaseAddress
    # D* T+ @) H5 ~( p( Q6 g
  322.        ADD  DX, 77 m; ]" Q4 s: a( K7 p( q

  323. . M4 e5 F& ?: z+ U6 ]7 F: v5 ~
  324.        LoopWhileBusy:
    ; S0 S& ^" D% r
  325. , t4 i, S3 \! Z8 l
  326.        DEC  EBX! F7 G4 n) v. z- ~
  327.        CMP  EBX, 0
    & m; w6 D. j2 X' S0 I1 ]& d( K
  328.        JZ   Timeout' u0 {9 g5 @1 j. ]; o& @% h0 r! w
  329.        in   AL, DX" r* G- t" M  Y5 c: x: W; a
  330.        TEST AL, btBusy  n; G. w" a6 \" q* a
  331.        JNZ  LoopWhileBusy
    % n, ]- ?2 \4 \+ a# i4 L3 L
  332.        JMP  DriveReady7 N4 b7 w  v7 P# j$ j
  333. 3 ^8 Y( G" m. L& o, t9 g- `& K
  334.        // 超时,直接退出0 h4 k1 U- K  w2 r) @
  335.        Timeout:) M1 N* X% E$ f
  336.        JMP  LeaveRing0- \1 V6 B5 [/ t0 K1 N- a1 Q
  337.        DriveReady:
    & T3 a5 @1 V$ F+ J0 N& u
  338.        RET
    2 u  ^( v+ S8 W4 G& n
  339.        ENDP   // End of WaitWhileBusy Procedure
    1 \4 @1 ?' f0 [4 r4 }0 ]6 k! `
  340. 3 t3 [* Z) ?4 k2 W
  341.        // 设置主盘和从盘标志
    0 c4 I' G5 }6 X5 F# i+ b5 a
  342.        SelectDevice proc3 N) x: M0 o' Z" d0 D

  343. ( C! _* u+ S1 g. v. [2 n  o# B9 ~
  344.        MOV  DX, dwBaseAddress( d- w2 ?9 K+ j9 A0 v5 \" s
  345.        ADD  DX, 6
    5 n3 N0 h' G' `
  346.        MOV  AL, btMasterSlave
    " B8 Y  @) G: U# i+ l. J* _" B$ f

  347. 6 T; V% {2 f; W" T3 H
  348.        out  DX, AL2 v6 I8 U: g* P: `8 l6 x
  349.        RET. [' s$ _+ d9 k/ ^4 [+ v' B8 g

  350. 5 }! ?+ w+ r# z9 I* `3 l
  351.        ENDP  // End of SelectDevice Procedure9 @. V% S# q% U; y
  352. 6 z9 g8 W1 U/ f: F; q6 r
  353.        // 向IDE设备发送存取指令
    3 V/ B8 @3 {2 X/ i% Q6 M
  354.        SendCmd proc
    " J' R$ Q+ X. @2 H3 _$ @9 [9 `% B

  355. 6 }' j9 q7 R, f6 T# ?
  356.        MOV DX, dwBaseAddress/ t5 W9 C+ r& r" Z( a: R  g
  357.        ADD DX, 70 o% J# q& K2 }% v# A
  358.        MOV AL, BL // BL是主从盘标识,在过程外设置
    ' [7 F% i( R/ @8 m/ P* m( I" h
  359.        out DX, AL+ W% W, O& T6 s+ ^5 p8 W
  360.        RET
    ( G2 S' T9 R+ t5 z1 g
  361.        ENDP  // End of SendCmd Procedure5 o* L* t3 K+ ^) R

  362. 1 v1 c; q7 t* Z: Z
  363.        // Ring0代码
    6 C, S1 e' i4 L
  364.        Ring0Proc:6 H1 H$ z* r( [: I
  365.        PUSHAD' b1 y# h6 `9 Z
  366.        // 查询IDE设备是否存在
    . y0 `. N- I: S. w5 W
  367.        MOV DX, dwBaseAddress3 G, r# Z) S% h$ }% J" L. M
  368.        ADD DX, 7* u& d  w7 F3 C
  369.        in  AL,DX
    + g8 H2 B7 L6 [: G& J% _
  370. 0 n4 f/ A- T( A$ u# X6 Z+ X2 Y/ J
  371.        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回4 J- G7 [& B! A" F, f/ e
  372.        CMP AL,0xFF: o! I4 t% L8 Y% I
  373.        JZ  LeaveRing0
    7 l& c- x3 q8 ]1 y* D+ w
  374.        CMP AL, 0x7F& x- p' y* ]* P1 l. B5 ]! M) O4 F
  375.        JZ  LeaveRing09 n0 i. B' K  S# _0 U1 o

  376. 9 L* A9 j9 c! o, h
  377.        // 设置IDE设备存在标志  f  c; [  |$ M" I3 z, O
  378.        MOV btIsIDEExist, 1. x6 x9 [' W1 t/ |
  379. * y* A* X+ u2 a* {0 U2 V
  380.        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)/ m; ~2 x* M, Z7 e$ ?& S( Y
  381.        CALL WaitWhileBusy
    ; a5 y5 i% w7 T6 W( X6 ~/ i. _5 j
  382.        CALL SelectDevice+ J8 m% @$ `; ?! X8 y
  383. 2 W% `- {/ Z! U0 W
  384.        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏- r+ i: O# K; |( W
  385.        CMP  btIsFirst, 19 m- Q0 E5 B, T4 }2 H3 s* ~
  386.        JZ   LeaveRing0# W( [% l% j2 V) V
  387. ( c8 e+ `  R, z
  388.        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
    & [- e6 b. E; D+ K! Y' L1 |/ W+ C
  389.        CALL WaitWhileBusy
    & `1 Y# C6 q% w- ~
  390. 9 a* g* B) `) b9 A( D5 U
  391.        // AL的值等于cBit06时,不存在驱动器,直接返回
      C! b4 H4 D+ m; ]* f
  392.        TEST AL, btBit06
    2 P2 e+ w' t' @! _. v9 R' N
  393.        JZ   LeaveRing0
    . \/ G2 F/ I: Z, y

  394. / q3 ~- {0 ?5 b; c2 y/ U% s
  395.        // 设置驱动器存在标志, b, {" [8 h0 O0 `8 `2 j
  396.        MOV  btIsDiskExist, 1
    0 ?6 h' p$ S- M$ T. B
  397. ) S5 Z$ J% _; U. q4 z+ [7 q2 Q5 o
  398.        // 发送存取端口命令2 F$ {7 u' ^5 m- N. j
  399.        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,3 o% y" Y! h- P& ^( s3 j
  400.        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令0 i& ?' r/ @  E- [6 V. T
  401.        CALL WaitWhileBusy
    ( f. S+ ?! K7 O" J; K
  402.        CALL SelectDevice    // 设置主从盘标识2 V  M+ v% s, p6 z- {% Q
  403.        MOV  BL, btAtaCmd      // 发送读取命令
    5 `0 A% z% z1 u2 u
  404.        CALL SendCmd0 t) i/ n+ Q. y5 n
  405.        CALL WaitWhileBusy
    4 c$ s# m$ K+ S( c# J

  406. $ L# U( m3 b! M+ G% c
  407.        // 检查是否出错' S# W7 M4 c. y* f2 t
  408.        MOV  DX, dwBaseAddress
    % {* t9 O7 ^! f* }  W. K
  409.        ADD  DX, 74 B" ]! A9 g  C

  410. 7 x. M9 [+ o/ G$ J) z& ?7 P5 G
  411.        in   AL, DX9 u0 p, I0 K" P" X" v3 R; y
  412. ) E* l; a( _% g* F
  413.        TEST AL, btBit002 e& T1 y2 g& g$ M4 D& ^& t* U
  414.        JZ   RetrieveInfo   // 没有错误时则读数据
    " I8 I* L# f2 `, q2 R; C( ~

  415.   {' o; S6 d0 N0 j) i$ M
  416.        // 如果出错,则进一步尝试使用ATAPI设备命令
    * c2 X" F: D3 j- x+ q1 V+ W
  417.        CALL WaitWhileBusy$ W* R; h) T0 p1 \2 V
  418.        CALL SelectDevice
    " O- d9 y& W5 }$ c' t) s
  419.        MOV  BL, btAtapiCmd
    ; U  D: ]+ O4 p) j8 g
  420.        CALL SendCmd
    + F- \. l6 k& t
  421.        CALL WaitWhileBusy
    : h- @4 S9 s- x: c5 x0 _# D
  422. + r) R0 u; U* Y% P
  423.        // 检查是否还出错
    $ f* C7 D9 K+ @3 ~4 j
  424.        MOV  DX, dwBaseAddress
    ' H" v$ W+ b% n# X' w: `9 j; W
  425.        ADD  DX, 7
    & U6 Q( n0 K: S# g1 p) j
  426.        in   AL, DX
    : Y$ M/ Q; f+ W3 r& B
  427.        TEST AL, btBit00
    / K8 Y/ S( m' _) W1 j
  428.        JZ   RetrieveInfo   // 没有错误时则读数据
    ) O, n; t2 j9 T' \( C7 s/ f
  429.        JMP  LeaveRing0     // 如果还是出错,直接返回4 |3 c+ ~9 C! R. `* P8 i6 @* D' T3 q
  430. 7 N8 C3 [/ b9 }( F% o
  431.        // 读取数据& T3 ^7 c: V& K- P1 E
  432.        RetrieveInfo:
    0 H; h" h; `( Y/ [
  433. 0 N% j' B- x* D+ s0 G
  434.        LEA  EDI, wOutDataBuf
    9 t3 r6 M9 {' [
  435.        MOV  ECX, 256
    $ v, S% W5 N( O" \
  436.        MOV  DX, dwBaseAddress- k/ `$ u' K. C' {
  437.        CLD
    ) q: C/ l5 y: W, b, O

  438. 7 c+ H- X! y* A0 k" w1 o* s
  439.        REP  INSW
    * s: \$ h+ {. \
  440. 3 j  ~" }  q, T& x+ `
  441.        // 退出Ring0代码6 A5 Z! t' x' n# _3 Y9 `5 r/ u
  442.        LeaveRing0:
    ) j4 M5 J* M' [, N% [5 u6 i5 e
  443. . S+ _7 T# P# v% W. S( S: F$ t
  444.        POPAD
    7 ?% E! j5 Q. I2 e6 U" [
  445.        IRETD
    2 f% e6 S& Q! S, Z# S: ^$ S

  446. 4 ]  J6 B  y- E+ P8 a- t5 R, u
  447.        // 激活Ring0代码
    - a- C4 }6 A" [" d9 N) ^
  448.        EnterRing0:
    $ B! l# d* w- v/ b1 |1 K

  449. 0 z2 P' J+ y# v: l7 L
  450.        // 修改中断门  J. E" F1 {; B. D
  451.        SIDT FWORD PTR btIDTR1
    + ?1 p1 X  F+ j( A0 I0 d0 P0 Y
  452.        MOV EAX, DWORD PTR btIDTR1 + 02h5 }3 d, F" n  t: B. B
  453.        ADD EAX, nHookExceptionNo * 08h + 04h0 F- B4 {. z) m7 @' E
  454.        CLI
    # i3 P% q# Z: S0 Z

  455. 6 n4 ]* y1 y. p0 S) r
  456.        // 保存原异常处理例程入口
    - I' X& S# G- n- T$ ?# h" z4 c
  457.        MOV ECX, DWORD PTR [EAX]
    2 b" O5 {2 p7 {% y1 g
  458.        MOV CX, WORD PTR [EAX-04h]
    . ^: b( ]5 N! v5 V3 L* P
  459.        MOV dwOldExceptionHook, ECX6 X: P; j9 J, V" y, `( H

  460. 7 P3 u0 C/ \. D0 w" [. A
  461.        // 指定新入口
    : G& N% `& `% G- g
  462.        LEA EBX, Ring0Proc
    1 n/ s5 k' L0 F  b' S
  463.        MOV WORD PTR [EAX-04h],BX
      H, I% c+ Z& A9 b. J/ U
  464.        SHR EBX, 10h
    : ?1 M- D+ k$ f% G
  465.        MOV WORD PTR[EAX+02h], BX
    1 L- b" c! W4 U) S

  466. # h' w! v" ^: M. n
  467.        // 激活Ring0代码
    ( L) `6 ~: [6 J/ v- b2 y' s
  468.        INT nHookExceptionNo
    " }. d$ m4 [+ t' {) s' t. M

  469.   D* B* O" R5 n' I, a* Y/ a. b: V/ A, K
  470.        // 复原入口% J0 G9 s' [4 B! }
  471.        MOV ECX,dwOldExceptionHook
    ) u9 B# H9 A% K
  472.        MOV WORD PTR[EAX-04h], CX5 o- K0 ~9 X/ n+ B# ^7 _; A+ x
  473.        SHR ECX,10h+ u& [; T6 B8 S9 I5 u1 r( b; f
  474.        MOV WORD PTR[EAX+02h], CX
    $ U( H7 d6 R. m) A9 h& |
  475.        STI
    " u0 L5 G9 G2 w
  476.    }9 ?/ b6 l7 w, {- T& P
  477.    if(!bIsFirst)6 P4 I. x0 A5 a1 @/ X
  478.    {' o3 [3 `% @* @8 Z1 z* s" k) ]& ~
  479.        bIsIDEExist  = (bool)btIsIDEExist;
    - W; `& u; o0 b- ?
  480.        bIsDiskExist = (bool)btIsDiskExist;
    , t5 \0 b7 u; Z- n1 ~( C
  481.        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
    ) O* c2 j+ m) P1 e/ y5 v0 H  j7 p4 G8 b
  482.    }
    5 ^( P- t# c- C6 f. W; n+ E; _! g
  483. }
    7 U1 S3 X& _1 c, |
  484. //---------------------------------------------------------------------------
    ) O7 m# F, t. {  z. r! j( f' r
  485. // 调用方法:
    % N9 \7 k: ^8 v: z& p
  486. void __fastcall TForm1::Button1Click(TObject *Sender)
      x( r" |$ S  x' u
  487. {
    # p+ H/ b- K# d+ K8 N+ E2 F; r
  488.    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
    ) c2 y) u) Y' F3 m+ R" A
  489. }
复制代码
发表于 2005-8-15 01:00:45 | 显示全部楼层
晕乎乎。。。怎么看8 洞阿
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-10-2 02:33 , Processed in 0.020145 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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