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

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

[复制链接]
发表于 2005-8-11 11:42:04 | 显示全部楼层 |阅读模式
  1. #include <WinIOCtl.h>
    4 D6 o; }3 D  A* a! `
  2. #include <stdio.h>
    . X% X, F# Y9 N0 C& `( ]  G

  3. - l% V& x6 W. Q& B8 G, W  x
  4. #pragma inline/ o5 g$ V$ f% c- ^
  5. //---------------------------------------------------------------------------
    9 S4 z3 Z. n  h& p: ~& u8 R
  6. // IDE NT/2000/XP专用变量' f2 O) ~2 b* I" `2 Z# E! k9 r
  7. #define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
    ) z9 D1 O  J6 G6 S  s9 o2 z% J
  8. #define DFP_GET_VERSION         SMART_GET_VERSION0 S& Y3 R2 V5 K3 m$ U; i6 s
  9. #define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
    9 N( k- u8 O7 c
  10. #define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
    % }/ Y0 j# w/ H( e$ ~
  11. 9 D+ }& _* w9 b( y& G" J
  12. const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令
    4 v2 h0 l: N% ?
  13. const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令  c4 V. k' B5 @9 h

  14. . H' \: ?/ v/ Y; S5 f6 H% M
  15. const int MAX_IDE_DRIVES = 4;" P6 X9 U" _; `( U6 c- y% p
  16. 1 h8 _; E, V4 U0 y& e
  17. // SCSI专用变量' x2 F6 p0 M+ n3 A
  18. const DWORD FILE_DEVICE_SCSI             = 0x0000001B;; A5 p9 l7 e1 H
  19. const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);6 i6 v& @  I$ p
  20. const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition: E+ U$ K5 {9 P" E" y: V8 Y
  21. const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
    2 m3 A0 ?+ _# i
  22. 4 v% y: E. O0 M2 J
  23. typedef struct _SRB_IO_CONTROL
    6 I' m; `) T% m( v) A
  24. {
    * w' ~& h/ o, [- R6 `/ i0 c
  25.    ULONG HeaderLength;
    $ E$ f1 @" ^: f. W8 ~; I: C( D
  26.    UCHAR Signature[8];. N% D' S: z- G& J/ M+ ?3 j
  27.    ULONG Timeout;
    ! {2 _, @: }" n8 ]
  28.    ULONG ControlCode;
    0 Z: i5 Y; I' C& Z) m
  29.    ULONG ReturnCode;
    + J- u2 Q6 L# L# b
  30.    ULONG Length;0 y% e6 N1 M- K9 s0 m3 A
  31. }SRB_IO_CONTROL, *PSRB_IO_CONTROL;
    1 o8 b& g/ j' Z0 d6 x: L( k
  32. . M+ \# k, |7 k# g8 `. \2 P: S
  33. // 读取的主函数( |: l3 D" X9 ~2 h8 |' |- f
  34. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);+ s( p5 V7 i" J) }0 W7 a0 E" n

  35. 8 Q+ j! b! `6 \
  36. // 辅助函数
    ! j, p# c, y! x/ U# Y0 p) V7 Z- E
  37. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);' u! c* a7 T/ f# s7 E
  38. // NT/2000/XP函数
    ( t8 u) \# \+ j, p7 l  `
  39. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);4 \: z  q; c/ E% K7 Y& F5 d* f5 I& }
  40. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP," O4 K0 m& {8 ~. x9 g; r0 v) y, M+ n8 ]
  41.        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,9 n9 {& f" W2 E7 Y( R/ X6 Z, e# ~9 p
  42.        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
    0 K9 n% R! z* G
  43. // Windows 9X函数
    6 \7 |* ~9 X% k2 B9 G, [! z5 r7 W0 f
  44. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);1 Z1 O; G0 J: F5 l5 H, K- F$ O
  45. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,2 a0 N6 k/ Z7 G  l0 n
  46.        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);" T9 `% `* Q0 D% b

  47. 1 ~2 }$ X! R1 y. B1 A$ J# L
  48. // SCSI读取函数(for NT/2000/XP)
    3 O0 N0 S) \& q
  49. String __fastcall ReadIDEDriveAsScsiDriveOnNT();
    + j# g+ [/ Z4 O
  50. //---------------------------------------------------------------------------
    $ |& Q1 D; s4 R7 T1 m8 A
  51. // ReadPhysicalDrive
    9 ^+ F/ J  n1 W8 ]( Q- T
  52. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
    * m; \% A' a! m. C/ I4 D8 U
  53. {  f2 y" m5 O! l$ g
  54.    switch(Win32Platform)
    # z5 I+ w: Y* ~' P" K
  55.    {7 J$ u" y) G  f+ F. I. z) f& R
  56.        case VER_PLATFORM_WIN32_WINDOWS:8 m) b* l; I% z) j8 ?
  57.            ReadPhysicalDriveOnW9X(pSerList, pModeList);
    " ]0 m+ c$ i( h9 m. p
  58.            break;9 C! {7 y$ v; J8 s2 `$ d2 O1 J
  59.        case VER_PLATFORM_WIN32_NT:1 \: V+ R* l9 B
  60.            ReadPhysicalDriveOnNT(pSerList, pModeList);
    3 d5 L" K  C( V' O, ^: Z! X" j
  61.            break;
    ) X/ u& S% B" w7 e6 f
  62.        default:
    ) j) p! P; I# \, }* V1 D
  63.            break;
    ! J: _0 b/ y  b+ K9 F, u7 ?; a1 p
  64.    }; G- f  W5 F( J9 P" C- F7 k
  65. }
      j5 z7 J- u, {, ~+ ]+ u
  66. //---------------------------------------------------------------------------
    2 }8 g# l% H: @$ }
  67. // ConvertToString
    3 }* J! ^( H) x# V9 @3 K
  68. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)3 ?$ E$ ?7 v& y! s6 S. s
  69. {
    1 `! L* N( t3 ?3 t
  70.    static char szResBuf[1024];5 _! D' s5 P/ Z6 t+ G. c$ Z/ h
  71.    int nIndex = 0;; r0 N3 J3 ~. L& i
  72.    int nPosition = 0;
    0 K+ N& a- b4 @4 }
  73. 3 M) G( r0 |" F4 P: O
  74.    // Each integer has two characters stored in it backwards% `; U' v0 G; v
  75.    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)" _9 t3 \+ e* U/ x  y
  76.    {, _4 Z8 L& R) b8 M* ]' E
  77.        // Get high BYTE for 1st character5 x+ p4 ?; D( s
  78.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
    + ?+ n7 ~/ x7 r
  79.        nPosition++;* r/ g/ F" j6 k6 p  J

  80. % p1 k8 u$ U+ n0 n
  81.        // Get low BYTE for 2nd character% m! l& t9 e; i2 M6 o- w. P8 t$ X
  82.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);* b6 ]8 O- r1 h( d
  83.        nPosition++;5 R9 `5 `9 O' C" z6 L' Y/ R
  84.    }
    0 n& d- G4 Q% V9 {+ U  O. w& q! D

  85. 7 g" R8 a# Z& d4 {% D: r# a
  86.    // End the string2 p' z' a$ q( G! K. K% y3 {
  87.    szResBuf[nPosition] = '\0';
    8 B: _/ f) q; C; `3 U' q

  88. ' I* Y7 }. \3 S% z3 C
  89.    // Cut off the trailing blanks' z( w! d( T$ y/ L
  90.    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)- l9 i4 i, ]. p9 v9 \$ O5 S$ z# n
  91.        szResBuf[nIndex] = '\0';- T! P* Q$ e, V; E# F8 i

  92. + A: ~& N, c  V
  93.    return szResBuf;3 q- i8 u0 ?5 B2 d* z9 b& x
  94. }6 X$ r( s$ J, K7 @( O0 u% T2 t
  95. //---------------------------------------------------------------------------
    / Z' {& W, P  O7 Y: J
  96. // Winndows NT4/2000/XP 代码
    / \5 {7 T5 x1 p' Q" w
  97. //---------------------------------------------------------------------------$ s, ]5 V& T* P* z: \0 Q3 b: Q) U: S6 s) Z
  98. // ReadPhysicalDriveOnNT( h; B: _. K4 m5 {0 C
  99. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
    6 {4 P( B/ `: [# F$ ~& @
  100. {
    " L; _' U! r& h+ i
  101.    // 输出参数. [: q+ k5 j+ ?
  102.    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];3 X9 a; p) ^" R: F- O7 z1 k
  103. 0 F/ [8 b# p( M- v$ A5 P7 ~( a
  104.    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)' k( j9 l. v8 u3 G5 ~) n$ h. I
  105.    {
    " M- {- i* X0 e8 p/ B1 p
  106.        HANDLE hPhysicalDriveIOCTL;4 D9 V  O  h/ A6 y% n& r+ f% o
  107.        char szDriveName[32];2 r$ h! A. X9 Z

  108. , z) n* W2 F) u
  109.        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
    ; C% H0 L# a4 X" i9 s0 E. {/ S/ n
  110.        hPhysicalDriveIOCTL = CreateFile(szDriveName,
      O6 [' L- S8 m" V
  111.                        GENERIC_READ | GENERIC_WRITE,% \# R5 f  `! v+ ~( @
  112.                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,* s; ^" Q4 e% i( n4 p9 \
  113.                        OPEN_EXISTING, 0, NULL);+ m' a; c* m+ g0 t  c

  114. - ]2 m* Y7 h& z' f( N! D( j, o
  115.        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)# [9 f* \) X6 O1 ]
  116.        {$ W: W' w( u/ ~2 E! O6 @7 v
  117.            DWORD dwBytesReturned = 0;. N8 S" V/ P  O) i9 M; Y% i  ~
  118.            GETVERSIONOUTPARAMS gvopVersionParams;
    " p2 p4 o! @- S2 c" B. o& x! `

  119. ! A4 s9 d* C' \6 ]' o; Y
  120.            // Get the version, etc of PhysicalDrive IOCTL$ A: \3 `7 X- r; r% v
  121.            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));
    3 ^0 g. r+ W/ Z$ `9 w1 ^; [

  122.   J6 Q% |# X1 a
  123.            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,# G% n0 B% s$ H9 K/ ~
  124.                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
    2 J& t* y# F5 K3 D% @9 m1 e* ]$ F
  125.                    &dwBytesReturned, NULL))9 x- o  `- n/ z+ k9 Q6 q% M
  126.            {$ j& V% K, [7 f, U
  127.                continue;
    ; Z+ I0 Z& Z- \; N" V) X
  128.            }
    9 c% I/ v2 l5 _4 x! m) V) S& e1 ^
  129. ! m, W7 p* ~: v" Z
  130.            if(gvopVersionParams.bIDEDeviceMap > 0)0 i7 z) b) k: J' b1 q2 [
  131.            {
    ; d* H; g/ V% s* m
  132.                // IDE or ATAPI IDENTIFY cmd
    ) \. w$ Y: z! A3 l% ^! i
  133.                BYTE btIDCmd = 0;
    $ g( \, s7 J0 `. t9 s
  134.                SENDCMDINPARAMS InParams;! j( |- \7 m# H5 z) i8 ~
  135.                // Now, get the ID sector for all IDE devices in the system.
    & H$ v% d1 o  v- h
  136.                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
    6 h+ e6 @8 Y4 V* I
  137.                // otherwise use the IDE_ATA_IDENTIFY command
    2 g# `) y+ j% J$ n0 K) [
  138.                // 具体所得结果请参考头文件中的说明. s" o: S9 W, h9 h; W
  139.                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
    1 }1 e9 B; T, s% f% }, l
  140.                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
    % H( b& z+ V8 V8 n# K
  141.                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));: O# ]& Q1 y# n( A
  142.                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));0 V9 ^3 c' ~# X" ^9 k! n- d3 i
  143. , o2 b; @5 ?  ^
  144.                if(DoIdentify(hPhysicalDriveIOCTL,
    ) f5 r9 F, {% c( A+ s" v
  145.                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
    0 b: H0 D5 N) A
  146.                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))( ?9 l% O4 q; |* ~5 t
  147.                {. n1 f$ y& _$ z  \
  148.                    DWORD dwDiskData[256];
    % _5 W& ~( z4 J" o6 e
  149.                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件2 m1 k& @: ?; ?% C
  150.                    char szSerialNumber[21];
    " @- O" ^' z1 h8 `! G
  151.                    char szModelNumber[41];
    # B6 _" R5 d" D& v
  152. " e+ K; \8 }  ?
  153.                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;2 f6 R+ v4 G) K3 `8 ~
  154.                    for(int i=0; i < 256; i++)' ], c5 l0 o! C0 y, W  t# m
  155.                        dwDiskData = pIDSector;
    & Q( ]  T: s. E& i4 |
  156.                    // 取系列号( P! R# b/ `, Y; B+ p/ F5 w
  157.                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));( S" j+ p2 c+ x3 B8 }& e; j
  158.                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
    / ]; |* G2 ^6 H3 J/ c+ _$ p

  159. 8 u. m5 B% a/ _2 R" N" z) }
  160.                    // 取模型号
    % M. g; a0 O* P
  161.                    ZeroMemory(szModelNumber, sizeof(szModelNumber));! G! Y/ k' `  I5 T* c  |2 q
  162.                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));' }' u; H: s: h  ?! F1 H

  163. $ q4 e7 i0 s' t. f3 n, W
  164.                    pSerList->Add(szSerialNumber);4 y: N+ Q2 u; |* c4 J# ^& p) k
  165.                    pModeList->Add(szModelNumber);2 N; C- u, q/ R4 Y" J
  166.                }
    - _* {% p. T% `5 L1 P+ z
  167.            }
    6 t  [) B% W' b: r, L" Y4 x
  168.            CloseHandle (hPhysicalDriveIOCTL);0 o8 v- ]% g, q/ T( T5 l5 O
  169.        }
    9 k+ y; f" ~' w. y: o
  170.    }; g1 [+ H, E- y3 @
  171. }; k- m2 J6 R  R, R3 p  L( A
  172. //---------------------------------------------------------------------------* Y2 B  K% V4 F% K$ Y& B$ w4 U) b
  173. // DoIdentify& q6 Z9 P- T$ d0 r5 F3 {4 H7 L
  174. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
    3 V2 C# K) P, Z, W/ Y# R
  175.              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,+ L3 X$ ?/ l# S3 H9 w
  176.              PDWORD pdwBytesReturned)- T. }1 d! k! Y2 U+ I' h2 e8 @
  177. {: q  \% ~  Z3 C" }9 a
  178.    // Set up data structures for IDENTIFY command.
    - O( p2 g: W  Z: I! q7 Y
  179.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
    7 j+ H0 @$ h9 w
  180.    pSCIP->irDriveRegs.bFeaturesReg = 0;
    , ], F/ P1 i5 S5 E4 [" F4 s9 T
  181.    pSCIP->irDriveRegs.bSectorCountReg  = 1;
    0 _3 G1 Y: c/ ~: H2 {" H
  182.    pSCIP->irDriveRegs.bSectorNumberReg = 1;
    ) w; q! ]0 d* m3 m8 n
  183.    pSCIP->irDriveRegs.bCylLowReg  = 0;
    # Z9 A+ N! X9 K; ?1 Y+ l9 ~4 g
  184.    pSCIP->irDriveRegs.bCylHighReg = 0;
    $ h0 c+ v/ V5 h# {1 j" q) X% X
  185. : z2 ~5 s( S( I# z2 j
  186.    // Compute the drive number.(主盘和从盘所对应的值是不一样的)/ O& T# {) y+ t! ^3 l# n
  187.    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
    % g( S+ [; u0 i7 _. z/ @& Y
  188. - F% Q6 B( Q6 Q; f% ]2 r2 o- l& E2 j
  189.    // The command can either be IDE identify or ATAPI identify.8 P- V0 I, I/ |- Y0 x
  190.    pSCIP->irDriveRegs.bCommandReg = btIDCmd;! H( D4 I, U/ i$ L$ r* l4 v( [
  191.    pSCIP->bDriveNumber = btDriveNum;; m7 r& h/ r$ d& ^
  192.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
    % A% z  \0 \0 ?/ T

  193. 7 J* T- `0 |/ ]
  194.    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,) y, C! M4 E3 H6 T3 ?/ H
  195.           (LPVOID)pSCIP,
    ; ^/ o" P# j3 V" g7 S9 e
  196.           sizeof(SENDCMDINPARAMS) - 1,
    9 p8 b  D" w$ \' ^! q4 }4 y
  197.           (LPVOID)pSCOP,% J3 u) o( M- c$ I
  198.           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
      r+ H* B7 s  u  ~. d' c
  199.           pdwBytesReturned, NULL);
    , V+ r8 z. J' I3 Y
  200. }3 y: X) s% ^1 y/ M4 _, n* _- \; G: q
  201. //---------------------------------------------------------------------------
    & I) c. B- {9 f4 w- F
  202. // Windows 95/98/ME 代码5 h$ x8 ?1 x; ?  c
  203. //---------------------------------------------------------------------------
    3 V0 f' D; z" M! O9 e4 ^
  204. // ReadPhysicalDriveOnW9X7 ?2 B# _" U, d4 ?
  205. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)
    + H, j% O0 s/ g: g5 C9 C
  206. {
    * V' g: `. u! s! @9 D9 R- O7 J
  207.    WORD wOutData[256];
    1 [/ O& }* B# n) W  M
  208.    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);  J& K1 a- J+ p1 T+ @  _8 j
  209. . ?! U6 U1 Z" m" G5 e4 ~0 M8 P7 o
  210.    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
    1 j+ ]- x+ P6 V3 w& i
  211.    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以7 x9 a' c7 f3 p, D3 J
  212.    // 避免蓝屏的出现。(期待高人能指出原因)1 Z' g) |2 w5 t& }' O5 w) [
  213.    for(int nDrive = 0; nDrive < 8; nDrive++)
    $ O' k# |( g* E- T6 r, C
  214.    {
    5 f, |/ W" M2 I- t$ b
  215.        WORD dwBaseAddress;
      a* X- V0 J# H0 A" w7 m, [
  216.        BYTE btMasterSlave;         // Master Or Slave
    2 \7 g5 C9 p% }) n, I7 B' ]
  217.        bool bIsIDEExist;7 L: C2 x" G; U. E% e9 q2 y9 T2 h
  218.        bool IsDiskExist;) P  s# v# y: }$ |( _7 P

  219. % o6 m% q- h3 E/ d# N6 L1 T( G3 }
  220.        switch(nDrive / 2)0 O& F0 s5 M  x# c
  221.        {
    + R% d6 U) ^% p! ^' i
  222.            case 0: dwBaseAddress = 0x01F0; break;* ^; k  V9 o+ T
  223.            case 1: dwBaseAddress = 0x0170; break;
    " b) N7 z2 C% W% q) m/ r
  224.            case 2: dwBaseAddress = 0x01E8; break;
    ( |- }/ r: m5 ]% z. g
  225.            case 3: dwBaseAddress = 0x0168; break;
    ( o: T. Y& A3 c, d7 f' J
  226.        }$ X" t4 E8 O( I6 C
  227. ) N4 m( U+ D4 C7 |
  228.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
    8 [/ T& ^% s9 Q6 D
  229. $ i* g" X, Q$ e8 j0 w8 J
  230.        // 进入Ring0
    4 v" d" p* z( Q; M7 y. {
  231.        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
    ; R3 C+ R8 t, a( L
  232.                bIsIDEExist, IsDiskExist, wOutData);
    4 [: \% o  l  P
  233.    }
    3 x( z/ }& y3 E1 @5 X6 `7 d
  234. + o/ U/ E1 L% @4 u  X8 ~. q
  235.    // 开始读取
    - C" u" {; A. q6 q7 p9 q; b% T
  236.    for(int nDrive = 0; nDrive < 8; nDrive++)" J! g7 m& y0 ~# s$ h% _8 x+ U6 d
  237.    {
    & `, Z0 m) f9 A, B5 u# v9 E0 P$ N
  238.        WORD dwBaseAddress;; }, E, i" Z0 j, @$ t2 B: X" G
  239.        BYTE btMasterSlave;         // Master Or Slave
    4 K7 l( b6 k! a& Z4 ^) P
  240.        bool bIsIDEExist;. U+ u5 F1 E( C) W
  241.        bool bIsDiskExist;
    & w) u& K& w1 V& S: y
  242.        switch(nDrive / 2)
    / L& I, a0 a: L% }' A0 k7 D
  243.        {
    , y5 V! [- d- m- p$ o: k: s/ M
  244.            case 0: dwBaseAddress = 0x01F0; break;
    ( C( B/ c4 S# H# z1 K6 s
  245.            case 1: dwBaseAddress = 0x0170; break;) \4 A& g8 g! n( A
  246.            case 2: dwBaseAddress = 0x01E8; break;
    ) T% _9 w. C* u2 s- }
  247.            case 3: dwBaseAddress = 0x0168; break;
    5 H3 U! z1 Q6 ]: P8 S" z  v/ D( P
  248.        }2 _* ~! A. M; I0 b6 U; U; C' d
  249. ' c7 x( H  H! k0 T2 K$ o
  250.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);+ [5 Y5 V1 |; q0 O
  251. ' c1 @. j! g1 v$ H% c3 Z- B( S# _
  252.        // 进入Ring0
    % |) T; o2 D: W& f; [
  253.        bIsIDEExist  = false;# |4 w. w% N3 ?# \
  254.        bIsDiskExist = false;$ }+ v$ N- r! \( @6 I
  255.        ZeroMemory(wOutData, sizeof(wOutData));0 p3 ~& u* q& u% t9 b1 R5 p& p

  256. & `- z% o. {0 y) ~5 a. n& U
  257.        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
    % N0 y# Z0 j* p" |# _. g! m
  258.                bIsIDEExist, bIsDiskExist, wOutData);( p2 n" _- [  M# m- B2 h

  259. 0 h/ q# N, m4 d
  260.        if(bIsIDEExist && bIsDiskExist)
    3 W! N" o* r- J( p& i
  261.        {
    ) A" Q8 t8 f1 @; p
  262.            DWORD dwDiskData[256];3 p' J& G( x: C* B! K+ w& ^1 c
  263.            char  szSerialNumber[21];
    0 h5 X+ j% P& x$ T; [
  264.            char  szModelNumber[41];
    2 Y4 ^2 w: C& p9 u, Z
  265. 1 h" z/ {+ ^% |, C- H/ q
  266.            for(int k=0; k < 256; k++)/ u. b* m" ]- \2 l3 V
  267.                dwDiskData[k] = wOutData[k];; M1 v( D) R0 ^1 v3 r  g' h7 ^

  268. 4 q5 ~2 J) N4 Y8 Z4 V9 Z
  269.            // 取系列号
    1 ?) B/ m; [+ R% Z
  270.            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
    7 m1 p2 M# `5 z' ?( Z/ z
  271.            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));$ }! a0 C& \% a: k/ _( y5 y* l

  272. + J$ ?# e! L# X# h
  273.            // 取模型号8 `) X' _  R0 C: ~- X
  274.            ZeroMemory(szModelNumber, sizeof(szModelNumber));
    1 o8 J$ x4 s8 |6 @5 |* x" q3 `
  275.            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
    ' r% |% M6 B# c  J( n! _' q9 y
  276. 1 o" `. R/ {5 e8 m' N2 T
  277.            pSerList->Add(szSerialNumber);# C# z- _( Q4 c+ }0 U8 z
  278.            pModeList->Add(szModelNumber);
    2 \5 z8 h2 r, z. h6 l) Q
  279.        }
    ) `7 f  E% w( i# F
  280.    }
    ) w* y* G* i  d
  281.    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
    2 v4 F" V& U* }2 g3 {/ A  e' i5 f7 ~
  282. }+ z+ ]* l( H7 {3 |
  283. //---------------------------------------------------------------------------! }4 L+ O& F! w" L7 e) h
  284. // ReadPhysicalDriveOnW9X_Ring0()
    0 y) J% y7 v5 a  A5 _1 l# Z/ w$ c! z
  285. //
    6 E3 R/ v, C, ~9 d0 T
  286. // dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
    # y" P! R2 s! C- \. W) s
  287. // btMasterSlave = Master(0xA0) Or Slave(0xB0)+ ?! u7 y5 G7 j2 l. G9 T
  288. //---------------------------------------------------------------------------+ V# R# k% [  J9 b$ R; u' s6 L
  289. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
    0 O, ^$ W" T4 J& ~4 r5 E
  290.        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
    , Q9 V8 f* C. k2 O2 ^5 f1 h5 }' t
  291. {7 ?5 ]2 {  {! {7 S$ t+ ~
  292.    BYTE  btIDTR1[6];2 ]3 n! j3 |' Y. s# v  f, L
  293.    DWORD dwOldExceptionHook;
    5 T) m9 g- l8 {. Y+ n% h- U: I
  294.    const int nHookExceptionNo = 5;
    & C4 {& z# Q( _$ p9 r* v
  295. 9 T% e+ Q1 g4 L8 v, [
  296.    BYTE  btIsIDEExist = 0;% x- W9 _  d; \8 Y( r
  297.    BYTE  btIsDiskExist = 0;
    0 l1 A3 _/ V& u. X' h
  298.    WORD  wOutDataBuf[256];
    0 k8 L) H/ i, ]9 o1 H, Z
  299. ; Z' q: ^" I' e% M" q( a1 ]
  300.    BYTE  btIsFirst = (BYTE)bIsFirst;7 i. P" Z- p" E7 Z
  301. ) V  @2 v1 }4 J5 ~+ U
  302.    const BYTE btBit00 = 0x01;
    1 H. e' _$ I  j) F3 b5 I
  303.    // const BYTE btBit02 = 0x04;7 P, x6 A3 G. s4 X
  304.    const BYTE btBit06 = 0x40;
    + |4 ^( @. D' }5 E+ A3 C0 \( k
  305.    const BYTE btBit07 = 0x80;, t5 \, P+ q& M; B, u+ X  q3 }! |
  306.    // const BYTE btERR  = btBit00;. u, W3 i7 H# `/ c$ O# u" m1 J
  307.    const BYTE btBusy = btBit07;9 ~/ U3 F/ E  i. U6 l
  308.    const BYTE btAtaCmd   = 0xEC;
      B. }- B) t4 q: k
  309.    const BYTE btAtapiCmd = 0xA1;
    4 E: W; q  q. i8 ^1 p, K/ O

  310. , [+ z6 ]$ n- S5 ^
  311.    __asm) O& b- C. a( i' R8 M; }3 z
  312.    {
    2 \; E. Q, {  l4 i) E
  313.        // 必须先执行这条语句" P2 u$ k" G2 f, @- {* }5 b8 Q
  314.        JMP EnterRing0
    - ~: W* ]1 v3 L
  315. 6 F/ C8 p2 \0 @0 z; i
  316.        // 定义过程" p3 |6 L! D  f2 S* t1 B2 I% d
  317.        // 等待IDE设备直到其不为忙为止
    : S/ @" G/ }( Q
  318.        WaitWhileBusy proc* L7 Q& V7 ]; [3 s$ X
  319. ' ]4 Y- J4 K/ U! F) @" B  w  G3 J7 Y
  320.        MOV  EBX, 100000; o9 d3 ]+ B6 G! a) g' `
  321.        MOV  DX, dwBaseAddress
    ! `% O# }) T9 U( C8 }
  322.        ADD  DX, 7" O5 V# b& u+ v3 y' N6 I- g" [: M" P

  323. & B/ E  g. ?; W1 P& ?" ]4 u$ g5 ~
  324.        LoopWhileBusy:
    2 S# R$ w# {* u! o2 T" ]
  325. 4 J, k2 i+ f, d: E7 f
  326.        DEC  EBX+ y2 P. X2 q5 N: o1 C2 J
  327.        CMP  EBX, 04 o. c2 i8 s; h% C6 G
  328.        JZ   Timeout
    + X( s0 u) D' B
  329.        in   AL, DX8 u4 @6 e3 b4 K
  330.        TEST AL, btBusy
    ) J& {7 {! d; C' F, S" L. j: N
  331.        JNZ  LoopWhileBusy+ M; G. W( d  p' b  {
  332.        JMP  DriveReady
    * O8 P8 i% W8 w2 c3 n

  333. ) G7 c, p' U* ~8 d5 e
  334.        // 超时,直接退出
    ! T+ G$ v( C4 t3 {
  335.        Timeout:, e9 J# A0 ^, |: R" e3 `
  336.        JMP  LeaveRing0
    # z2 {9 ?4 j  D% X2 R! G2 r
  337.        DriveReady:
    . r3 p2 u6 @6 o" R2 i& ^0 O
  338.        RET
    4 |. q6 o. z% c+ f0 u
  339.        ENDP   // End of WaitWhileBusy Procedure
    5 K/ p% _/ z  F& i+ B. Y
  340. 7 |! Q9 Q! ]. }* T1 e! r. m* K$ A; P
  341.        // 设置主盘和从盘标志) L* p! W; S) {' l8 R
  342.        SelectDevice proc& T2 G, R; P$ U1 X6 f) b

  343. 2 ]& O  I1 \7 M, Q
  344.        MOV  DX, dwBaseAddress
    9 t  o* K- g! p- z
  345.        ADD  DX, 6
    * a2 s8 T9 c4 H
  346.        MOV  AL, btMasterSlave
    1 O; X% z0 N7 a3 Y$ J3 b$ A! }

  347. , [, j8 ~1 E& d1 B/ L. j! i: M
  348.        out  DX, AL5 U* N3 P9 o8 d' j
  349.        RET+ ]1 F4 s3 @: X8 v
  350. " y/ {+ ?  z" X
  351.        ENDP  // End of SelectDevice Procedure2 {4 n1 C8 J4 \/ @( C

  352. 0 ^0 y/ c* Y7 v! w# A9 M( e
  353.        // 向IDE设备发送存取指令
    0 r, P+ f% g; ~7 k' \/ ~
  354.        SendCmd proc) P7 \0 M$ p& d5 b

  355. 9 |2 K9 l5 R( t3 |: g1 t2 D
  356.        MOV DX, dwBaseAddress# `/ V* j& h$ Z8 }* h
  357.        ADD DX, 7
    - D: }& D( Y  X8 o6 g# `
  358.        MOV AL, BL // BL是主从盘标识,在过程外设置
    9 {( A: C( O( L
  359.        out DX, AL
    ! n2 N4 w/ R2 d: j% E0 n) L
  360.        RET
    * _: t' L: o( U; b. Y
  361.        ENDP  // End of SendCmd Procedure2 b9 p9 K; p. F+ j  Y

  362. ' C& A" }2 n; Y" Q/ \" r
  363.        // Ring0代码& u' J. i7 O0 r% a7 M1 `1 c
  364.        Ring0Proc:- F/ `- O8 x* q" S( u+ _1 r
  365.        PUSHAD
    : V) W" n& ~: t  h
  366.        // 查询IDE设备是否存在
    ( J8 N9 n" e) \+ [5 \
  367.        MOV DX, dwBaseAddress6 |9 b8 P* t) f* z
  368.        ADD DX, 7
    ( o. W" G5 C9 i! e4 p
  369.        in  AL,DX
    - ~3 ~2 U; C( p! }- i( r

  370. . ^/ B9 b% w8 _
  371.        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回& H5 R2 x/ o6 L1 `% ^& D7 A
  372.        CMP AL,0xFF
    0 y: x5 H& D: v( E5 K
  373.        JZ  LeaveRing0- B' I6 _( S' m( b' Q) U
  374.        CMP AL, 0x7F6 [5 e* C7 Z! A) Y  `
  375.        JZ  LeaveRing0
    ! y( r0 b6 ]* w
  376. ' ?3 r1 M! F& y* v' K! f
  377.        // 设置IDE设备存在标志; y: Y! Z/ U3 G3 L3 e  j4 N+ E: I1 w
  378.        MOV btIsIDEExist, 1
    4 L1 d; S! _9 z! b. Y* y+ f

  379. ! z6 M) p: z: ~  M2 a
  380.        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
    ' i% d8 n- {" D! U+ F. N( f
  381.        CALL WaitWhileBusy% H  W$ T3 W3 a6 q, K' k5 z* n
  382.        CALL SelectDevice
    9 M5 {# F" C! d

  383. 5 g  m! a* U& a
  384.        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
    # T# r: ?+ v3 r. H3 M) u6 Y/ B2 j
  385.        CMP  btIsFirst, 1
    ) U" b( V$ F9 T- Q& T! F/ V; d
  386.        JZ   LeaveRing0- b) s- n* m* i% |
  387. 2 C  C9 Y2 d, H
  388.        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???& J+ H% ]* Z+ x' _! H2 @+ G- ?
  389.        CALL WaitWhileBusy
    $ p0 X, C: ]5 J5 e, M) q9 e8 x

  390. 9 r2 u! k0 g' F- R' S" u
  391.        // AL的值等于cBit06时,不存在驱动器,直接返回; h. d2 R$ J( A7 q3 `- L
  392.        TEST AL, btBit06( G$ [* R9 C. w* V
  393.        JZ   LeaveRing0
    , Y$ L5 a) @8 C2 I1 F

  394. $ u- b' ^* G+ `+ N( S5 [6 Y# A$ {
  395.        // 设置驱动器存在标志6 c, e4 Y: R& @8 \# w$ w3 a& F1 Y
  396.        MOV  btIsDiskExist, 10 a1 I) E$ F/ Y1 J
  397. ( ~; w: \8 M' w/ A9 q' c
  398.        // 发送存取端口命令
    6 w- F$ T, ^$ j0 n* ]  s
  399.        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
    # J$ [) A: p% M3 p2 B
  400.        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
    " o5 N: I# H" k; y4 `' Q
  401.        CALL WaitWhileBusy) I9 g( I1 m2 s, H* P% s8 B
  402.        CALL SelectDevice    // 设置主从盘标识, P+ c) l0 O# y: G& Y% Z
  403.        MOV  BL, btAtaCmd      // 发送读取命令
    9 \) c$ h: i0 N! I4 `
  404.        CALL SendCmd* Y. A! X) C% a; C* f0 H, a" r
  405.        CALL WaitWhileBusy
    $ h8 x( v* B: S" |2 `5 w) u
  406. ( m0 }  {2 b, j
  407.        // 检查是否出错9 _+ L6 Q, I8 S
  408.        MOV  DX, dwBaseAddress
    ' n' `; W$ F/ S9 a& F
  409.        ADD  DX, 7
    ' d+ `" Y6 Y5 f0 j) f# ~
  410. % [2 U7 i7 A% |) j
  411.        in   AL, DX; T; }" Y9 G, o( R: {  Q9 [

  412. 0 W/ P1 X+ q+ D
  413.        TEST AL, btBit00: ^: d6 K# P. z5 M# T
  414.        JZ   RetrieveInfo   // 没有错误时则读数据0 d0 T8 {( f% w  [
  415. 6 D4 z1 c! N% b. D2 Q
  416.        // 如果出错,则进一步尝试使用ATAPI设备命令5 P; e  L1 z0 f- P8 J. |# n
  417.        CALL WaitWhileBusy
    5 a# D7 Q& T* i. D+ F
  418.        CALL SelectDevice
    : {6 g) O) Y/ X
  419.        MOV  BL, btAtapiCmd
    6 ~- @+ z4 w4 Q& c
  420.        CALL SendCmd
    / F( b% g" f$ ^8 Z
  421.        CALL WaitWhileBusy
    / E" Y6 |0 }, q+ t3 v
  422.   v  J/ l) G! S# ~8 L
  423.        // 检查是否还出错
      W6 Z* T+ |( E5 O7 _
  424.        MOV  DX, dwBaseAddress" v7 w) G! t- E& S% e. x; Y4 G
  425.        ADD  DX, 7
    , u/ A2 |- ]) G: U& W( X6 @
  426.        in   AL, DX( O5 T( W4 Z! m( F
  427.        TEST AL, btBit005 U' S" [9 W& L2 L* @; a- G
  428.        JZ   RetrieveInfo   // 没有错误时则读数据
    1 h0 M$ s) X5 a! W3 L4 O
  429.        JMP  LeaveRing0     // 如果还是出错,直接返回
      U( ~1 i* l( D7 J: B! C5 U

  430. * e+ q, y( R# Y7 m2 }$ I
  431.        // 读取数据
    9 J8 c. J9 ?, E9 W3 Z5 R
  432.        RetrieveInfo:
    ' D& [# I9 E1 Z: e; x

  433. ; b) L; C$ f9 \" f9 y; X
  434.        LEA  EDI, wOutDataBuf" u* q$ }4 N( ?! X8 D
  435.        MOV  ECX, 256
    - f9 T0 N% U; P7 t- }
  436.        MOV  DX, dwBaseAddress5 I5 j. {! E# F# U6 ~# W( h
  437.        CLD
    & U4 u9 w  S7 R& w* c, f2 g$ O
  438. ( M: F9 Q3 B( W. \0 G+ S- @
  439.        REP  INSW: T! k3 z+ \$ V. P5 v( S* f7 o" y
  440. / _. b! E; J& w
  441.        // 退出Ring0代码3 {/ U5 q" U! C1 t1 ]
  442.        LeaveRing0:
    , n  n9 l+ [: S& L( G

  443. ! F8 ]  V+ V/ ^/ Y" F4 _# P. E& o
  444.        POPAD
    " T+ p( o! o, l4 }4 @& z
  445.        IRETD
    8 ?5 D# t; ?) o

  446. ( `! j3 C/ A3 u. L4 P( k
  447.        // 激活Ring0代码# f* r; l: U9 Q& J$ f2 p4 U
  448.        EnterRing0:$ N1 B6 D4 Q7 i2 N
  449. 8 `3 b- G; Z( L$ ~) ]# b( Y
  450.        // 修改中断门" M6 T! W( }: v5 N, h. d, k; j! k
  451.        SIDT FWORD PTR btIDTR1+ s8 b6 x' H. e3 R: a% a' a) j
  452.        MOV EAX, DWORD PTR btIDTR1 + 02h9 x- d: l% q+ q: W0 ?2 W* y; t( K1 q
  453.        ADD EAX, nHookExceptionNo * 08h + 04h# \6 w3 N: t+ l5 P
  454.        CLI
    0 d4 D1 Z- ^5 `5 |( u& r

  455. , h7 c8 z' h$ Y8 L! T/ _
  456.        // 保存原异常处理例程入口
    : C5 S7 t) k3 q* A4 r2 V
  457.        MOV ECX, DWORD PTR [EAX]
    ! J4 L, a4 P; j) w" q
  458.        MOV CX, WORD PTR [EAX-04h]
    7 }$ v' x& S( N/ N( ?
  459.        MOV dwOldExceptionHook, ECX
    - `$ j" v: s4 D1 U, I+ _5 L

  460. 2 M4 Z9 L2 Q: J& }( h
  461.        // 指定新入口. j) \- ^8 C$ I1 t# i) u7 l, a+ w
  462.        LEA EBX, Ring0Proc
    # l" P0 x1 q. {, T1 q" U$ m
  463.        MOV WORD PTR [EAX-04h],BX
    ) s$ d7 X. j  s  n
  464.        SHR EBX, 10h* l' b+ K- X+ D7 s8 Q
  465.        MOV WORD PTR[EAX+02h], BX
    . D" V! O7 P; C  [  z1 |6 o
  466. ) i  {) B' C9 O( f' C
  467.        // 激活Ring0代码: Q% |8 u; O/ r8 y; j3 E
  468.        INT nHookExceptionNo
    5 E# \7 f# p/ B' B# _

  469. 9 J( c* s6 ]5 r/ a0 Z
  470.        // 复原入口
    . d9 l1 b& W  }+ ~4 d
  471.        MOV ECX,dwOldExceptionHook. s4 d  e; ~8 J7 `0 `
  472.        MOV WORD PTR[EAX-04h], CX
    $ f/ _! K& Q( R4 B! ]) V' O( G
  473.        SHR ECX,10h$ h( ~; \: X- E) q1 J6 D: _
  474.        MOV WORD PTR[EAX+02h], CX: H; ], A0 r0 G6 y& Z
  475.        STI
    ( X/ }2 ^# c- u0 c/ f& B
  476.    }
    # U/ f2 q/ C0 E3 m0 F2 R- x. P
  477.    if(!bIsFirst)
    - C" g" j0 F% n* v: k  C" g6 g- G
  478.    {
    ( Y) v' f0 P, V' d/ W$ m
  479.        bIsIDEExist  = (bool)btIsIDEExist;) d& Y4 y- t+ D% J$ T
  480.        bIsDiskExist = (bool)btIsDiskExist;
    . b% _+ q2 |* Q( t# C. d1 k
  481.        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));+ Q& {6 S8 U! b) H! }$ u7 C
  482.    }
    + d# S  v2 R, [1 C; v; F! w+ E2 b2 P
  483. }4 G3 H( ^$ \+ v
  484. //---------------------------------------------------------------------------
    ; h; a- l( o' Z
  485. // 调用方法:
    1 s$ `' ?# l: K- Z3 @3 e* \/ _
  486. void __fastcall TForm1::Button1Click(TObject *Sender)' f' h# K1 v  ~
  487. {
    7 k: U# t; {% ^
  488.    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);- J+ l2 S% d6 S4 V
  489. }
复制代码
发表于 2005-8-15 01:00:45 | 显示全部楼层
晕乎乎。。。怎么看8 洞阿
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-10-2 03:04 , Processed in 0.018511 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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