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

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

[复制链接]
发表于 2005-8-11 11:42:04 | 显示全部楼层 |阅读模式
  1. #include <WinIOCtl.h>) B3 k2 k1 g# K) k' |4 i" B. G: j
  2. #include <stdio.h>/ t1 {- i' m( q5 X3 m5 J( t% q% }
  3. + g' q1 P  N; g4 P# w/ K
  4. #pragma inline
    # L+ M' Q) F$ }& `( T
  5. //---------------------------------------------------------------------------1 F3 b: |+ V/ w5 n7 g" h
  6. // IDE NT/2000/XP专用变量
    : \" d% B- i6 k
  7. #define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS2 I/ I! A: M/ R% @, M  m
  8. #define DFP_GET_VERSION         SMART_GET_VERSION
    / H4 P. k  s' e  r  J  L  C2 r
  9. #define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND7 ~; v8 M1 p. f4 x" W, q; x' @+ E
  10. #define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA; [% p! V2 e& F" E/ }* G4 Y4 r

  11. 3 h; K  t) Q+ E, F2 I+ `
  12. const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令8 `3 [# [- k0 Q: Q. T
  13. const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令% m9 F" Y5 Q5 M" Q* T
  14.   v! Z: E' b* t2 O+ U1 w
  15. const int MAX_IDE_DRIVES = 4;
      W% F2 H8 E+ h  ]# J1 N
  16. & A6 h0 H0 o$ k
  17. // SCSI专用变量
    ) }0 A( r" o& H; T$ e2 g8 ^- i
  18. const DWORD FILE_DEVICE_SCSI             = 0x0000001B;9 G+ ^6 K# g& _% B# R) J: g4 O' K( S
  19. const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);8 r; i/ u9 C& i# y8 O" l
  20. const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition! d. P0 z; H5 b7 @; K8 {/ m
  21. const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
    ! x1 l* |' o1 F+ T. Q9 z
  22. 1 w; e7 |& T: ^) W: i
  23. typedef struct _SRB_IO_CONTROL
    ' L: M, J9 }/ E( s
  24. {! f6 t6 i& o  s/ q  L% U
  25.    ULONG HeaderLength;1 o; Y' U, I( {% y# W$ [: K4 j
  26.    UCHAR Signature[8];. z. S& z% b8 v% j1 L
  27.    ULONG Timeout;
    0 m& f6 T) u) O& e/ B9 o
  28.    ULONG ControlCode;/ |6 A4 S! W, {, H& B2 v
  29.    ULONG ReturnCode;  [9 P5 X; j7 ?* T7 N
  30.    ULONG Length;  W! f+ h" k4 ]3 {/ b/ J
  31. }SRB_IO_CONTROL, *PSRB_IO_CONTROL;
    & w2 h5 S4 M! I+ [. R* [; Z
  32. 0 U( E& ]0 N8 u/ y! P# e
  33. // 读取的主函数
    0 C! r" U! E2 k2 H9 C) A8 Y" u
  34. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
    2 \3 T1 U1 o/ U8 W3 P5 [
  35. 4 G7 }( F- E4 l5 |
  36. // 辅助函数/ A: M: S4 D4 t( W( c% y" D2 w9 ~
  37. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
    ; J" U" y+ ^( D2 x
  38. // NT/2000/XP函数" D) m1 _) n, Q" U+ e* F
  39. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);7 X5 M0 {; t1 g! }
  40. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
    * u( b( \# M* g, k1 S
  41.        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
    3 \: T3 A+ {+ S( M
  42.        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);& r3 \3 _* r+ [
  43. // Windows 9X函数
    3 _# r4 @- B# f, D9 U
  44. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);' w5 Y5 D) u  L6 N! j1 ~+ i( P
  45. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
      m) U) q7 N2 ^* _" ~
  46.        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
    + M4 t# Z: c" H5 B1 [% m. _, ~

  47. & z4 s3 ]% c+ m- z2 ]+ H. [
  48. // SCSI读取函数(for NT/2000/XP)
      Q8 e) K+ ?9 T. e; A0 O3 w) g
  49. String __fastcall ReadIDEDriveAsScsiDriveOnNT();1 W% w; J( e' p% C: N
  50. //---------------------------------------------------------------------------
    $ Z/ E) f5 @' r8 _) R
  51. // ReadPhysicalDrive: i( E6 }" s9 r/ C6 {# ]
  52. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
    ; C; Q5 g/ a- [5 n1 v
  53. {: x8 {) q. p: y# p
  54.    switch(Win32Platform)6 b+ z. ?) @$ b- v, y. m0 a# U
  55.    {
    # W# J" z8 R# k0 v
  56.        case VER_PLATFORM_WIN32_WINDOWS:* V# s4 Z8 [  C9 o" m3 W1 j
  57.            ReadPhysicalDriveOnW9X(pSerList, pModeList);
    " b- q; A8 K' i+ l% B) z
  58.            break;5 T" r+ w6 n" w- g% A9 X
  59.        case VER_PLATFORM_WIN32_NT:; X6 y* C) C# k! g+ \* \5 ?
  60.            ReadPhysicalDriveOnNT(pSerList, pModeList);$ q6 K' g9 ^' ?* i/ v8 b# O2 }# y
  61.            break;
    " `  W) q6 y0 z5 U: c
  62.        default:
    9 F9 M) q3 K/ r! Q1 k% @
  63.            break;
    2 B: Z5 a% P6 s
  64.    }6 h: |& f* u; d9 M0 d
  65. }! ^! \2 f. L6 y) C* Y- n
  66. //---------------------------------------------------------------------------/ N& w2 ?7 |9 L" b
  67. // ConvertToString
    4 b/ I" N* |% v7 B; e) z
  68. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)8 q  W' D! e3 M2 L) }
  69. {. t2 L! u1 A' n
  70.    static char szResBuf[1024];7 k# D) M4 f2 a8 [' _& ^- Z
  71.    int nIndex = 0;* G5 B9 t7 U+ Y0 w( F9 f0 K  M6 q
  72.    int nPosition = 0;  ^/ _3 |, R- E( a, i" p7 B
  73.   L7 X. y+ x7 ^
  74.    // Each integer has two characters stored in it backwards
    7 y( v# v' r0 X) n) L1 r$ W+ v
  75.    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
    8 Q' A5 l+ a8 c
  76.    {
    9 j# Z% k( \6 u- i: x7 D
  77.        // Get high BYTE for 1st character
    , s. w$ E8 [+ r1 L4 C
  78.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);  Q- u0 r. ^$ b# q7 H% N
  79.        nPosition++;* P; j4 Y  ]5 O( c$ J4 m7 w
  80. : w  e0 v- P, ~% @- u0 W
  81.        // Get low BYTE for 2nd character
    3 I+ a2 n4 h& k, V/ d
  82.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);% K) U# r! D" V  V" D
  83.        nPosition++;
      ]6 z6 K4 P: S) x! g+ l7 e, ^
  84.    }0 Q- ^- w3 J/ q& S: E
  85. , P; v4 R& M6 O# e# X0 ~0 w' r9 V& U
  86.    // End the string& i, A" B+ Z' {4 A& `0 @% z
  87.    szResBuf[nPosition] = '\0';% K. t% l2 B$ K
  88. 7 T) A8 V) m$ d) _# ?
  89.    // Cut off the trailing blanks7 P6 k- H* _! r& k6 G
  90.    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)( U- r: d& B" k; L+ g( a
  91.        szResBuf[nIndex] = '\0';: W/ T- y. V- j. Y! q% m
  92. 4 T2 _1 p; q$ I6 k% K2 z5 g& y  ?
  93.    return szResBuf;
    " N  V- U- c: G# t8 k) L/ J
  94. }# Z5 `; F3 Z- h: O6 A
  95. //---------------------------------------------------------------------------2 V4 G) }/ |  P$ a4 h$ [# Y' x: Z
  96. // Winndows NT4/2000/XP 代码
    7 O/ Q1 S3 F# ?
  97. //---------------------------------------------------------------------------
    : I: R% z7 {, z" b$ m2 h2 Y9 y
  98. // ReadPhysicalDriveOnNT
    4 j" Y) A6 ~9 I- R$ G6 c  H
  99. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
    0 Y5 q% h! w" g: F% n' v8 s
  100. {, `( j! i4 G8 Q9 V1 p) ]
  101.    // 输出参数
    & V) q. f5 a' L7 x
  102.    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
    % Y( E+ U6 B  I! P9 {, W) ~* D  j" h

  103. " [4 @& [9 ~! j/ |3 [5 @" T
  104.    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++): i$ y7 b! t" d* _. y
  105.    {+ D8 \( i% I8 q) I' l$ i6 T
  106.        HANDLE hPhysicalDriveIOCTL;
    3 Q- N" |; `: |2 `2 x' u7 c
  107.        char szDriveName[32];
    4 K3 ?( ]; R" N" x5 f  g

  108. 9 C4 K8 S* _/ S+ {8 T$ {
  109.        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
    0 F+ Q) b$ U& }/ o& s
  110.        hPhysicalDriveIOCTL = CreateFile(szDriveName,5 M& ^0 e" B/ [9 S% M0 ?" C
  111.                        GENERIC_READ | GENERIC_WRITE,( @; V4 c/ e1 J
  112.                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
    & y. b8 G: A4 I5 w) Z/ c& C
  113.                        OPEN_EXISTING, 0, NULL);3 l, {8 s2 N4 ~. \

  114. 7 T$ h/ F3 O3 i' r; y2 v
  115.        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE), {2 E+ H$ r& [' n
  116.        {& ?; e% c3 c& d# `" z3 \" {
  117.            DWORD dwBytesReturned = 0;
    7 O' O. x! v9 F' r
  118.            GETVERSIONOUTPARAMS gvopVersionParams;
    5 ~0 {, }0 s+ h% J  U1 Q) k

  119. % e" ^, z9 g/ p' K: ?
  120.            // Get the version, etc of PhysicalDrive IOCTL
    7 e1 N; ^7 m/ f& B. {* y
  121.            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));& T' ~0 `, x: V7 P
  122. ) t+ v, G, Y  \9 C# L  [. \' U
  123.            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
      w" z$ L2 K7 J
  124.                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),9 x7 |7 |) M' |5 S' l9 X
  125.                    &dwBytesReturned, NULL))
    4 g4 |9 W& M) y# O2 D* X
  126.            {. K- u. ]' F- D9 u0 m7 }* h2 S
  127.                continue;
    ) |' E7 H6 p$ Q8 T
  128.            }+ `8 l2 n. Y% ~: B0 W( d% e
  129. * ?  G3 P# U9 t+ c2 G) `1 V6 Y
  130.            if(gvopVersionParams.bIDEDeviceMap > 0)& K6 V8 `& z& u! p. |
  131.            {9 _/ D" K( F( y, x; c* W
  132.                // IDE or ATAPI IDENTIFY cmd
    5 y3 Y/ S$ h3 N; O, a9 x2 t! v
  133.                BYTE btIDCmd = 0;
    / J, U) n7 z8 \# E8 @, ~
  134.                SENDCMDINPARAMS InParams;3 i' P5 n: v* C( I- ]
  135.                // Now, get the ID sector for all IDE devices in the system.
    - D7 g4 C6 H0 h2 h
  136.                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,- R( p2 G9 j  I! {) U
  137.                // otherwise use the IDE_ATA_IDENTIFY command
    . O+ V; ]+ r; ^  j
  138.                // 具体所得结果请参考头文件中的说明* ]7 s; L/ \; U- y
  139.                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
    ( ^5 t$ b8 c* T1 s  x% ^0 ]
  140.                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;- n8 G) w8 @" U
  141.                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
      n: H: m7 J" c1 a
  142.                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));- }! P& [# X5 j

  143.   ^: {) A) V4 G, e5 l9 y- B
  144.                if(DoIdentify(hPhysicalDriveIOCTL,# Z3 U+ l& A% t/ P' C
  145.                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
    8 P$ r2 X. m+ @, r; v* o- h) j
  146.                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
    9 y7 w2 M% K3 U3 h( Q/ d
  147.                {( f9 C/ p$ P& Q0 ?0 g% C  j( ]0 b
  148.                    DWORD dwDiskData[256];7 g7 |1 G  {2 q  K7 @* s
  149.                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件5 C0 M" B9 h$ C1 i5 n$ o8 @  H
  150.                    char szSerialNumber[21];- K% x0 S1 W7 M4 h
  151.                    char szModelNumber[41];
    0 ?" U9 p$ Y* Z% [/ I
  152. 9 C9 Z5 |2 S! t" x
  153.                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
    ( W' c. F6 s7 V, p3 d
  154.                    for(int i=0; i < 256; i++)
    ! d* _' \# Q6 W; W
  155.                        dwDiskData = pIDSector;% L- `1 F: G+ T, V1 p
  156.                    // 取系列号
    ! A) J9 X8 U- ]. f
  157.                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));" N1 c) s/ k. h  T; U  Q1 U
  158.                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
    4 L& P6 J* J$ b2 S0 t

  159. * v: ~# D7 j6 y1 R
  160.                    // 取模型号
    2 r# o0 u8 d* H* h! o8 a
  161.                    ZeroMemory(szModelNumber, sizeof(szModelNumber));
    0 j/ p/ ?! V# ~- R) v2 k; {
  162.                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));+ t9 i9 x6 a- U" J! [3 r
  163. 7 p/ s2 o3 {7 O
  164.                    pSerList->Add(szSerialNumber);+ B2 l# A' q9 B
  165.                    pModeList->Add(szModelNumber);
    ) E* g! S$ G0 {( _2 H+ P
  166.                }
    1 A' ]/ H& H4 w% a
  167.            }
      E' B0 w) B8 ]$ k& c8 z# @
  168.            CloseHandle (hPhysicalDriveIOCTL);
    # D- l% r( t( Y4 F) p8 D% E
  169.        }3 j6 _! R$ G" ^, q" C9 |- g( O
  170.    }% L% {! J3 [1 Z7 ~) @
  171. }
    * R. P; l# o5 r9 d) `! f3 Q! s
  172. //---------------------------------------------------------------------------1 G6 B1 A$ I: c+ _4 Q! d9 y
  173. // DoIdentify
    , q7 i' J' g/ q: V  A% a' @- p
  174. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,' D, k- e+ n" b: z& W5 a( x
  175.              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,) A7 a( y: p1 Y6 G7 R4 H* D0 `
  176.              PDWORD pdwBytesReturned)/ }% `% T1 o5 w
  177. {2 y6 L( f+ }* s0 i+ t
  178.    // Set up data structures for IDENTIFY command.7 z( v+ J! `1 {& w% A# q; W% V
  179.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
    ; T8 ?; l( ~1 K) }% o1 h; _1 K/ f
  180.    pSCIP->irDriveRegs.bFeaturesReg = 0;
    # H' T! C4 L+ \( M; n
  181.    pSCIP->irDriveRegs.bSectorCountReg  = 1;! L* M9 ?& T+ X- T
  182.    pSCIP->irDriveRegs.bSectorNumberReg = 1;
    5 Z& n. ?% ?: `' }. s
  183.    pSCIP->irDriveRegs.bCylLowReg  = 0;+ W( m8 R6 E+ g, W: P5 W  W# z
  184.    pSCIP->irDriveRegs.bCylHighReg = 0;
    * ]1 }% R) L. _

  185. ! ]0 k  y' p2 T* Y1 p$ d% z; p% U
  186.    // Compute the drive number.(主盘和从盘所对应的值是不一样的)
    ! Y- @2 Y" M# {7 f
  187.    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
    1 s: N* |3 C' o; v* L' z5 p
  188. / w" ]$ A7 t) r' {5 P5 @: L
  189.    // The command can either be IDE identify or ATAPI identify.
    4 Y7 e3 P: d7 W0 i! `
  190.    pSCIP->irDriveRegs.bCommandReg = btIDCmd;
    6 A& d% _( o: Z: O  M1 |
  191.    pSCIP->bDriveNumber = btDriveNum;
    ; O3 G! w: s3 G7 t$ I/ F+ \
  192.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;0 ]$ b. C6 T/ [/ r" ~. p+ @& E

  193. * h" W$ E! ^; ~2 O
  194.    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
    2 I! W, g# u( K  D6 c
  195.           (LPVOID)pSCIP,) g2 ^% a$ `$ A7 `; v8 {8 W8 I
  196.           sizeof(SENDCMDINPARAMS) - 1,
      ?; O$ I# V7 \& F3 e- `
  197.           (LPVOID)pSCOP,
    / f- k2 L: C8 C8 a$ V- G' w7 u
  198.           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
    + p* A* \8 F% y! s5 r
  199.           pdwBytesReturned, NULL);
    & F7 ^$ p3 B+ c' J6 ]8 B
  200. }
    6 [- {& A% @7 K/ A' n, E% p1 I
  201. //---------------------------------------------------------------------------* G" X. E) v6 F0 b! V9 h
  202. // Windows 95/98/ME 代码7 u6 w! @0 h( n9 E# n5 `
  203. //---------------------------------------------------------------------------
      A! U( q& t! s
  204. // ReadPhysicalDriveOnW9X8 B3 k+ I% s, @' P! G# V  Y0 p
  205. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)$ m& x$ i' h0 a2 m: U( q& @) E
  206. {6 A. W! N0 W- c* w7 C4 `8 s% w
  207.    WORD wOutData[256];7 [, [( O; F! o3 W
  208.    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
    $ B% M8 h$ ]1 a+ g$ |8 U' U. F

  209. ; X. p' A$ L4 z1 O
  210.    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
    ; V% L1 l4 S5 D8 l" y; S
  211.    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以" ?6 L( y$ ?6 t$ l2 y
  212.    // 避免蓝屏的出现。(期待高人能指出原因)
    7 X6 }/ m/ n6 F  V
  213.    for(int nDrive = 0; nDrive < 8; nDrive++)4 m; I- P: N6 l! X; C7 M, V
  214.    {
    + x' V0 g/ O8 {) `) C4 c4 ~$ k* k
  215.        WORD dwBaseAddress;1 O6 K# h# x7 w9 E
  216.        BYTE btMasterSlave;         // Master Or Slave, e0 A; M* s1 l1 c8 `0 Z+ B
  217.        bool bIsIDEExist;
    8 ^# B% [+ }; z4 L4 Z% D4 @- u. I7 a
  218.        bool IsDiskExist;
    $ O  P( a& J3 N1 L
  219. % @8 r1 H& j# ^
  220.        switch(nDrive / 2)( h, L+ [, Z9 a9 \/ d. l% j& g( ?
  221.        {' \! @3 Z* y0 N  D6 u6 {( }
  222.            case 0: dwBaseAddress = 0x01F0; break;) r9 I' m7 _) ?7 @8 i# }0 J0 T
  223.            case 1: dwBaseAddress = 0x0170; break;
    9 n: b0 ^; x6 _% i, l' A
  224.            case 2: dwBaseAddress = 0x01E8; break;/ L" C7 Z8 a! X1 B* z7 P" u
  225.            case 3: dwBaseAddress = 0x0168; break;0 F  g+ v6 ], n' X( Y
  226.        }
    * M8 C  k! d' G' P4 I  ?
  227. . Y0 D$ \( u% \! y) u& p$ k6 @$ p
  228.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);' e, {' U3 Q; J" v7 I
  229. 3 n3 \% R/ F$ y/ {- Z* v& E4 ]+ R
  230.        // 进入Ring0# J* Q$ b. C( d* ]
  231.        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
    5 X0 L4 U  @+ |6 K' _9 e) l
  232.                bIsIDEExist, IsDiskExist, wOutData);$ t6 x! A: J' |+ r  O
  233.    }
    ; Q4 }$ d4 W; D5 V
  234. 6 |- k$ `; P0 h; ]* P7 y1 q
  235.    // 开始读取, M1 T4 ^+ M' q/ D1 n  e* ]
  236.    for(int nDrive = 0; nDrive < 8; nDrive++)
    % x; y1 X$ E- ]* P+ \- L4 U
  237.    {" h% a- m% }# o
  238.        WORD dwBaseAddress;
    * o% s: _0 j# j+ S5 y
  239.        BYTE btMasterSlave;         // Master Or Slave; Y+ n+ {! D- x8 R+ o6 f! c2 C
  240.        bool bIsIDEExist;; O' Y. E& ?' z0 [# U
  241.        bool bIsDiskExist;' e7 p/ O0 z/ ^0 ?
  242.        switch(nDrive / 2)0 u7 D/ l8 j  t% a% E
  243.        {) ^+ z3 Z5 L( e! t. X4 |9 ~
  244.            case 0: dwBaseAddress = 0x01F0; break;
    3 y* U3 I$ c* w5 N" I% q, @
  245.            case 1: dwBaseAddress = 0x0170; break;
    " D" x8 D6 }, h' u
  246.            case 2: dwBaseAddress = 0x01E8; break;
    4 q/ b5 t' s7 `3 a
  247.            case 3: dwBaseAddress = 0x0168; break;
    $ N; X8 c$ s. L8 ]" r
  248.        }8 J' S' ?6 B; B1 S- @# p$ a( ~
  249. ; l# C% v- F5 R( L
  250.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);5 R; M" |* i# M3 J3 I5 F1 x  {

  251. # m% u$ z8 @! \; x7 p' e! u
  252.        // 进入Ring0; [1 t2 g; }* q$ N
  253.        bIsIDEExist  = false;- ^0 j5 q3 P2 s3 v/ B' h
  254.        bIsDiskExist = false;
    * B/ Q* S5 F5 {, _  k
  255.        ZeroMemory(wOutData, sizeof(wOutData));
    : x6 I% F# M7 x) D0 l& q
  256. . u) s& M* b/ `( q! k8 F: L' v
  257.        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
    3 i' X7 Z- d1 d8 s" R$ ^0 K
  258.                bIsIDEExist, bIsDiskExist, wOutData);$ e% {7 O9 m" K+ P; S; A! n
  259. 6 x3 n+ O+ A6 q3 v* M$ e
  260.        if(bIsIDEExist && bIsDiskExist)
    " S5 H0 G/ K, P3 e, d( v
  261.        {
    2 N- O! p1 Y7 v& _1 d% N! j- y
  262.            DWORD dwDiskData[256];
    . X( Z0 k" B' s4 m
  263.            char  szSerialNumber[21];1 R3 e% I  \( W
  264.            char  szModelNumber[41];
    7 \. W  t! l# S2 K2 H
  265.   {% M& A% o* I; E& b7 @# r
  266.            for(int k=0; k < 256; k++)3 U; T  b/ F0 F, t* K& [, C1 V, s; D
  267.                dwDiskData[k] = wOutData[k];
    ; U( H* B. U/ O6 Z. `" {) {- o" |7 s
  268. 8 U7 U" K8 ]* Q/ t. G! Y
  269.            // 取系列号
    + B& I2 i# R* I+ E8 J6 O
  270.            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
    1 l1 f0 u2 r$ ]4 L
  271.            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));/ P* o0 l5 z/ k9 k) }- Y
  272. 6 z4 ^9 a9 A: c* m  ^
  273.            // 取模型号
    , n1 M8 G0 X6 M
  274.            ZeroMemory(szModelNumber, sizeof(szModelNumber));8 U& E9 i! n( L; |* N
  275.            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));: p6 l% I# D, a$ k
  276. / R" t& [3 |" h. F. p+ U' L" s" x
  277.            pSerList->Add(szSerialNumber);
    # z, q8 I4 O, |/ h/ h
  278.            pModeList->Add(szModelNumber);9 V5 A( y- L0 }
  279.        }7 E6 [* y5 j: V0 \6 u9 i
  280.    }
    ( n6 P! y* _" I2 R
  281.    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
    / _2 z! y2 B: k+ W. z, o
  282. }
    . ^0 ~3 v  x2 j8 q; ]6 H" z
  283. //---------------------------------------------------------------------------
    ; W6 K/ }- w2 w' S  F
  284. // ReadPhysicalDriveOnW9X_Ring0()- G3 D: }( _. r0 v+ Q" a/ M9 X/ Y
  285. //
    7 S) W9 t0 w4 J& T- C
  286. // dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
    - U- o0 V. ?3 n0 F" z
  287. // btMasterSlave = Master(0xA0) Or Slave(0xB0)
    ) K1 w# O0 i* j. L3 e
  288. //---------------------------------------------------------------------------- r5 T' H: T/ b% Z) z
  289. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,5 ]6 b0 B! U0 I6 j+ d2 T
  290.        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)8 O; i) o! ^9 G& d+ n
  291. {
    7 d3 K6 ?# o, w) G9 k! r
  292.    BYTE  btIDTR1[6];
    7 x% U$ ~# X& Q% p& o- ]
  293.    DWORD dwOldExceptionHook;
    $ V( s$ s0 O) v+ ^. s
  294.    const int nHookExceptionNo = 5;
    . X7 N  Y$ V- b8 E! c
  295. - J- p# [1 D( l$ X0 d6 \
  296.    BYTE  btIsIDEExist = 0;6 S' x) _0 E9 L  l; x, T2 x( O. |0 z
  297.    BYTE  btIsDiskExist = 0;
    + k5 A, S& A( Z  a- r
  298.    WORD  wOutDataBuf[256];  o. x  _% G1 Y; q

  299. 4 s# I+ n% i. I2 J, k1 ~$ k
  300.    BYTE  btIsFirst = (BYTE)bIsFirst;1 y9 G, T2 p+ r8 `

  301. 7 C0 p& d# K+ ^$ `2 i$ E& A
  302.    const BYTE btBit00 = 0x01;( M0 |1 p% {8 H/ J4 a6 i
  303.    // const BYTE btBit02 = 0x04;7 ?3 V/ f/ E# }* o* `2 \: R% C
  304.    const BYTE btBit06 = 0x40;
    5 M% C6 B6 P0 B0 U# M
  305.    const BYTE btBit07 = 0x80;
    , n/ k6 W. W8 n
  306.    // const BYTE btERR  = btBit00;
    4 I8 F/ `9 e! B9 C: H- z- F
  307.    const BYTE btBusy = btBit07;9 k2 [/ V$ @- G: y
  308.    const BYTE btAtaCmd   = 0xEC;4 N% S1 h7 n4 B  Z4 D. n9 a# N- d, H* y8 m
  309.    const BYTE btAtapiCmd = 0xA1;
    9 K3 W8 D( z2 S' n
  310. 7 y7 {: E# H3 G% s: {- h
  311.    __asm& t1 H& J" d; y8 j& F5 i5 q1 i) V; Q
  312.    {; ~, Q$ M8 g# D7 m
  313.        // 必须先执行这条语句
    % B$ x+ h$ y9 d1 X. @# V
  314.        JMP EnterRing0
    ; X) p. O$ p* ^# T" S& ~# Q& z
  315. / M! J3 l; Z6 x! k* `; ^. k2 R( v
  316.        // 定义过程
    . x" q* L' P7 v
  317.        // 等待IDE设备直到其不为忙为止
    3 U# R+ r( H% M+ p
  318.        WaitWhileBusy proc: S- ]4 \7 u9 F4 R* Q% X, h$ j/ X" J
  319. / b* S5 T0 K+ c
  320.        MOV  EBX, 100000
    ( o- a% b9 }, i# b* }6 I
  321.        MOV  DX, dwBaseAddress
    3 v1 X5 F  `$ U# t
  322.        ADD  DX, 7
    * i* q- X1 v& g7 ^
  323. 8 K4 M5 p8 f. r3 S3 B
  324.        LoopWhileBusy:% b# {* A4 K3 e4 \& e3 k+ n
  325. 1 t1 w  h% V& Q: d4 i
  326.        DEC  EBX
    3 s# B4 {% ]' Z7 e
  327.        CMP  EBX, 0
    * o" u' \" H& t1 C
  328.        JZ   Timeout4 x; \* F8 A$ w4 x  R: b5 O) N2 q0 W
  329.        in   AL, DX% B7 _/ z9 W# l! {
  330.        TEST AL, btBusy# C  e6 |- L; j3 E- t3 A
  331.        JNZ  LoopWhileBusy' I" Q8 }) y' N3 u* H
  332.        JMP  DriveReady2 e2 i8 @  _- K: Q
  333. . V! b% y9 `* n+ C
  334.        // 超时,直接退出
    # I2 W! Q' R6 L, I& [
  335.        Timeout:
    6 G; ], G2 @- f( m$ X; ~% T; M# x6 R
  336.        JMP  LeaveRing0
    ) c9 z6 }* x, V1 u$ @
  337.        DriveReady:
    / V* G0 G! B7 O! \, a9 l" x
  338.        RET% ]! G+ ~" P, c0 Z- |- n% |- f
  339.        ENDP   // End of WaitWhileBusy Procedure
    . R8 k) [6 W2 }0 N

  340. * M' x- N  t% E9 T' o& A
  341.        // 设置主盘和从盘标志" k7 \/ N) {  J: D" ~( e
  342.        SelectDevice proc& F: L1 g: u: |6 A% y* g3 G

  343. 8 b4 f( ~6 k) t5 \- K" }. K! u
  344.        MOV  DX, dwBaseAddress4 A8 [, I- Z( o7 P  C0 j  o2 v6 B% E
  345.        ADD  DX, 69 q% r& f9 u7 B' u5 `* L
  346.        MOV  AL, btMasterSlave# `, ~+ R' J0 T

  347.   Y0 ^9 E+ e+ |; t. z! I3 w
  348.        out  DX, AL
    ; |: \0 D, ~) u/ Q; k. R& j$ V1 ~
  349.        RET
    / |* `: J) _& F0 J

  350. ( k8 F' a6 {& h2 {  _' M7 q
  351.        ENDP  // End of SelectDevice Procedure7 h9 T* A1 b  p7 m
  352. ; }3 v, j* [* r1 \! e" Y+ _
  353.        // 向IDE设备发送存取指令
      |: O$ C, g$ @' h% q
  354.        SendCmd proc
    / r& v3 H7 k4 S0 c3 {

  355. ) U+ i) }& @9 D% f. I2 T
  356.        MOV DX, dwBaseAddress
      A3 S6 j5 E3 L0 M, f4 U
  357.        ADD DX, 7
    / E- i* S! c+ Y+ O' f& L. ?- m: [7 a
  358.        MOV AL, BL // BL是主从盘标识,在过程外设置
    & N$ H" h% W) N' r0 \
  359.        out DX, AL& W5 A7 N# W; G6 J' Z0 e, f
  360.        RET" ^4 `- K5 t! ^  @
  361.        ENDP  // End of SendCmd Procedure5 R8 E# Y( d5 U9 K. N
  362. ) a/ Z9 E9 J8 h8 l
  363.        // Ring0代码) r* `; v& {# U
  364.        Ring0Proc:% W! _2 v  A7 s& p0 _, k
  365.        PUSHAD
    7 i& X7 v' A. P/ Z
  366.        // 查询IDE设备是否存在% J# |2 s  v! w8 w" L# q; z; w
  367.        MOV DX, dwBaseAddress
    5 Q1 n9 s) [% v# F5 a8 L$ {3 q
  368.        ADD DX, 7
    4 w) P4 }9 I3 r" m0 d
  369.        in  AL,DX
    5 R' r% r" B4 U- e7 \, J" {* k
  370. $ ~/ [, ]0 s$ t
  371.        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
    6 N7 U2 `, ]; d# ?2 }+ s
  372.        CMP AL,0xFF
    1 b+ D8 `3 N. L( G; H. W3 s
  373.        JZ  LeaveRing0
    0 V7 V2 c) b/ P( G; z2 f
  374.        CMP AL, 0x7F
    ; d- B4 F& L: a) [/ w, j
  375.        JZ  LeaveRing0
    + D" x+ c9 H$ o8 G. w0 h6 f$ v4 K
  376. 1 Q9 H. x& e1 r
  377.        // 设置IDE设备存在标志
    4 R5 ]. C' H( ], n, r
  378.        MOV btIsIDEExist, 1
    ! v( W: Q7 b- q/ B' X& D
  379. 7 M! _$ ]! H6 d( F4 x
  380.        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)& F2 C) f. |9 p7 p* ]  `
  381.        CALL WaitWhileBusy
    - \7 `; V9 w3 J
  382.        CALL SelectDevice
    9 R7 z3 t- `. d. R! v: Z
  383. ) j+ u5 O% A7 N
  384.        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
    2 n$ Y3 @* T% P. t
  385.        CMP  btIsFirst, 1+ j3 u9 U6 [# U' N' W+ Y
  386.        JZ   LeaveRing0  V2 o# H& r. z

  387. * ~  E, O, W; ?" `5 A  Q, P# ~
  388.        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
    6 x+ \5 q% m1 D9 O& `
  389.        CALL WaitWhileBusy
    2 `" V1 a* V9 G% W) b( @
  390. 2 U5 L! f) ~' A  |0 n3 D
  391.        // AL的值等于cBit06时,不存在驱动器,直接返回
    $ I& b: f8 e; ?% ~$ S$ @9 ]& q
  392.        TEST AL, btBit06
    7 t8 b  O5 M2 D0 O
  393.        JZ   LeaveRing0# W) g8 p. [* U/ i7 ~$ @
  394. : w: D9 H0 C3 \$ ~6 O/ G4 d
  395.        // 设置驱动器存在标志
    8 J7 b; L7 D8 a* q% z+ b
  396.        MOV  btIsDiskExist, 1! d4 L8 ?* _# z1 B

  397.   }- K; y/ r, L+ q1 ]+ l
  398.        // 发送存取端口命令
    , C1 X" f. Z3 W+ `  S4 Z! F
  399.        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,2 d8 h+ i, M0 Z3 j) o
  400.        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令3 h; V& J7 m& J9 W! S0 H% y0 X
  401.        CALL WaitWhileBusy
    5 g2 r/ g) J" |8 ^2 g
  402.        CALL SelectDevice    // 设置主从盘标识
    * ^/ H1 O+ w+ q0 u" d( G8 f# h  C, B
  403.        MOV  BL, btAtaCmd      // 发送读取命令, T- @& a: R8 ^. h6 S4 D4 v
  404.        CALL SendCmd; w& {/ |' W- V' E/ F
  405.        CALL WaitWhileBusy
    % o6 J) R% Z* I, u# n7 O
  406. , @9 F3 `4 R0 v/ u# _9 W
  407.        // 检查是否出错
    + B& H; ~4 i  h: g( M
  408.        MOV  DX, dwBaseAddress; _" A. u  e0 S1 I# w
  409.        ADD  DX, 7
    ) B3 j: x7 U; ]7 L# |

  410. + I1 o4 V! t9 d% R
  411.        in   AL, DX! E' d$ K/ A4 e- d% f8 c+ f4 U" M

  412. 8 U+ @% d$ z. Q3 z, C
  413.        TEST AL, btBit00$ b) \! n& V, n
  414.        JZ   RetrieveInfo   // 没有错误时则读数据
    ) _2 j: S) S$ L. g# ~* @
  415. 2 E7 i; i5 p5 d6 U
  416.        // 如果出错,则进一步尝试使用ATAPI设备命令
    ' u5 [/ A* N3 n) ]8 ~1 }) O/ r
  417.        CALL WaitWhileBusy6 y) }3 S) e) @
  418.        CALL SelectDevice
    . Y6 f6 _! O" Y8 E8 ]
  419.        MOV  BL, btAtapiCmd" M0 f6 b) [+ L7 P: D  i; j
  420.        CALL SendCmd* M2 b; p& q6 k2 A1 k6 g
  421.        CALL WaitWhileBusy+ U) s+ d: U; x' O

  422. # W) Z5 L5 r! h, b/ J$ K7 J1 I
  423.        // 检查是否还出错
    & P. d$ [# ~& @, m" X3 _; x
  424.        MOV  DX, dwBaseAddress' \% i1 f# ~8 Q% |% [0 G2 s" I
  425.        ADD  DX, 79 [" a% y% E7 m( J! h2 \
  426.        in   AL, DX1 s7 g% l* k2 L1 d- J
  427.        TEST AL, btBit00
    ( K( R# o- |) B5 A: J+ B
  428.        JZ   RetrieveInfo   // 没有错误时则读数据+ Y1 y% O) j: A4 x
  429.        JMP  LeaveRing0     // 如果还是出错,直接返回
    - H( p. E. D8 ^9 [3 z' m

  430. 5 B1 i1 j8 B) C6 t2 K. j3 c! H
  431.        // 读取数据
    2 i0 b# i3 l1 d& y
  432.        RetrieveInfo:
    ; J7 n3 c9 D) v

  433. 9 w5 l: U/ H- ]
  434.        LEA  EDI, wOutDataBuf+ Z+ V. U) j+ {. Z
  435.        MOV  ECX, 256
    & {) H: n/ y2 p2 F5 N8 V+ r! }7 p
  436.        MOV  DX, dwBaseAddress
    ' m9 Y; I4 D' @5 J7 m
  437.        CLD
    1 _: e! B" z5 V, B) j" H9 `& s# m

  438. ! _% W* [' s4 |) z2 e% @
  439.        REP  INSW
    , O! ]* n% a$ e" {# Q

  440. # m4 ~6 _0 U0 t7 B; O
  441.        // 退出Ring0代码. c0 C; D1 q( }5 Q% a( i
  442.        LeaveRing0:
    : d- B$ i, A* I7 }
  443. ' X( z( s4 v) \* @/ W$ ~! Q" I
  444.        POPAD; n: P& K- F% m( ?9 F9 ~
  445.        IRETD
    ( D! H! E$ U8 X6 ^

  446. 1 z- I# S& u: G/ g( p+ E: \$ h: v
  447.        // 激活Ring0代码3 O# A( |& H: M) o4 J% @4 Z5 L
  448.        EnterRing0:
      G7 e* P# Z& t

  449. ) z0 r- z' l) T: x
  450.        // 修改中断门
    . a: u4 l: `5 _( `( j  t
  451.        SIDT FWORD PTR btIDTR15 l% h1 }6 K( S, e, n; i6 K
  452.        MOV EAX, DWORD PTR btIDTR1 + 02h& z: a. }4 `$ v" }
  453.        ADD EAX, nHookExceptionNo * 08h + 04h& K% m  X" i. r2 L6 Z: |1 {
  454.        CLI. S' F* S, T. I  }1 ~0 @4 M3 i
  455. $ j7 ?8 i3 P# J( ?' h( {
  456.        // 保存原异常处理例程入口
    , H7 N( v! F7 l/ k. U8 K
  457.        MOV ECX, DWORD PTR [EAX]
    6 h, W" v7 }- o6 k% _2 `6 @/ g
  458.        MOV CX, WORD PTR [EAX-04h]
    6 `. L4 {8 I6 @" b  X- V9 R9 w
  459.        MOV dwOldExceptionHook, ECX" W0 I7 J+ b( F6 V, f, b

  460. - N  L4 X2 x. H: K6 j
  461.        // 指定新入口+ ?7 p& C  Q* W" u! ~6 j1 G: s* a
  462.        LEA EBX, Ring0Proc
    / x# o* ^+ y; A" l
  463.        MOV WORD PTR [EAX-04h],BX
    ! }' C; k7 L1 U
  464.        SHR EBX, 10h
    2 E: V5 w4 s0 y5 Q
  465.        MOV WORD PTR[EAX+02h], BX
    $ O* c  O& a2 f- V- i

  466. % \8 i3 k1 c; b8 H
  467.        // 激活Ring0代码
    $ ~+ S9 X/ i  _' l$ u4 c
  468.        INT nHookExceptionNo
    * v  }% }( F! }" _1 D: ^

  469. ) \# q4 c9 M9 A  C. h# T# O
  470.        // 复原入口6 ~2 g3 Q( w0 g
  471.        MOV ECX,dwOldExceptionHook# z- O9 z9 a( G9 h" W$ z
  472.        MOV WORD PTR[EAX-04h], CX1 r, I; c9 Q+ [3 z/ _
  473.        SHR ECX,10h1 w5 A. n$ Y" B8 a/ E
  474.        MOV WORD PTR[EAX+02h], CX
    4 R- X8 D0 ?2 ]# t: S
  475.        STI/ I+ {" X5 Z. n, A
  476.    }5 D  a5 r) V( p) K
  477.    if(!bIsFirst): }8 W  [+ G, L" Q1 f" n" h
  478.    {0 R1 U, h0 t4 v4 E. J
  479.        bIsIDEExist  = (bool)btIsIDEExist;
      Z5 U5 R1 E( o
  480.        bIsDiskExist = (bool)btIsDiskExist;
    1 m  `; O+ ]7 q: T. l, s# J+ d
  481.        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));3 T$ l% X. c2 L9 `
  482.    }1 S3 }: p/ v6 O8 G
  483. }& `1 W+ f9 t) ?  l
  484. //---------------------------------------------------------------------------
      ]! t4 ]3 S9 H' T  Z* G
  485. // 调用方法:2 V" P: B' m' ?/ p' u4 `# E5 X5 L8 }
  486. void __fastcall TForm1::Button1Click(TObject *Sender)$ j+ M2 I3 C& L7 B" K5 a, p
  487. {3 b9 z7 e) s  g7 C/ F" a
  488.    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);% K! q9 `" i! I& q
  489. }
复制代码
发表于 2005-8-15 01:00:45 | 显示全部楼层
晕乎乎。。。怎么看8 洞阿
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-12-13 11:53 , Processed in 0.018826 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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