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

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

[复制链接]
发表于 2005-8-11 11:42:04 | 显示全部楼层 |阅读模式
  1. #include <WinIOCtl.h>
    - G. Y: T5 Q& t6 T# a) U. t
  2. #include <stdio.h>
    5 r3 s& ~" t, E' T% U" a5 H5 O
  3. ) \6 C2 [/ n+ }( h8 s$ |
  4. #pragma inline3 A0 c% ?: i* I8 o$ _" b: z
  5. //---------------------------------------------------------------------------
    $ R2 }; z7 ?' J! {5 M: _' U5 o
  6. // IDE NT/2000/XP专用变量
    8 Y7 S; m3 P5 p; B
  7. #define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS$ p8 o; c# Q5 c2 I
  8. #define DFP_GET_VERSION         SMART_GET_VERSION# C, L% z/ L% U/ T$ u) |6 B
  9. #define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND) l- V; W$ P" s% E- F8 u
  10. #define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
    ! y8 E- @+ G% \8 q# \- W' \

  11. 2 U0 x; S6 M- ]: c0 z1 M5 z- }
  12. const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令
    ; K$ y, w5 F7 Z7 t( }
  13. const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
    2 d# i1 s; c5 j
  14. 9 j% l6 Z! @+ \) Y
  15. const int MAX_IDE_DRIVES = 4;
    # @( H( {( t: R' k  \7 x: }; d
  16. ! y! \6 g4 `: g7 E. L) {% ]
  17. // SCSI专用变量1 X- J5 A: w, N! a; ?3 u! N/ S
  18. const DWORD FILE_DEVICE_SCSI             = 0x0000001B;
    / V- Z3 B: B- E7 {1 a8 h( {
  19. const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
    1 \- E) \$ W. u: L
  20. const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
    ; u! I2 w3 f2 ~, P% U
  21. const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
    ' P8 D5 r. o2 W- Y

  22. 0 Z8 K! \8 Y- s
  23. typedef struct _SRB_IO_CONTROL
    1 g& G, E+ E# }7 H% Y3 {- g# ^" P
  24. {5 o5 C* j& w2 ~" L& E
  25.    ULONG HeaderLength;, k/ t8 K. p1 t( R6 h- x) h1 X
  26.    UCHAR Signature[8];
    0 _/ m& k4 E; b6 C3 u4 }
  27.    ULONG Timeout;
    % B. U% W% z+ i  n6 z  k
  28.    ULONG ControlCode;4 Y' k# T; C* R; D4 W
  29.    ULONG ReturnCode;, Y* q+ Z! p3 c, I
  30.    ULONG Length;8 p8 v+ G: s( F! D
  31. }SRB_IO_CONTROL, *PSRB_IO_CONTROL;4 P2 V# C  y2 x+ f

  32. & }) H' {8 I0 ^! _1 q/ L
  33. // 读取的主函数- E6 c& [* I) P- U
  34. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);+ e, `/ p, r: M6 e) M$ Q

  35.   M5 i/ F1 d4 P
  36. // 辅助函数& c! d6 ?" j" M/ }1 E
  37. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
    , }9 r0 O% g2 L1 F0 Y4 \( K
  38. // NT/2000/XP函数+ V9 Q1 D  H  t5 O. _& f. f: ]. x
  39. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);: }1 Z7 {" u" X( B+ k, B+ p" g
  40. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,4 q2 m& k7 i9 q: S
  41.        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,4 h7 O2 d! ?( E7 H+ Q0 U0 G9 j
  42.        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
    4 i5 O8 o  l3 h% z" `& t
  43. // Windows 9X函数
    ; @- y/ v( ]5 W" O  F9 g+ }  G
  44. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);- d4 Q) N% j+ t2 a* y
  45. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
    6 n" \4 S- j9 B3 ^' ?9 ~+ J4 I
  46.        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
    9 x  z* w2 w5 _& x
  47. 9 ]4 q+ B* z: P" d- o
  48. // SCSI读取函数(for NT/2000/XP)
    ) S, |4 [+ l' b2 U; p; Y) l  ?
  49. String __fastcall ReadIDEDriveAsScsiDriveOnNT();
    . Q) {" x" T$ R
  50. //---------------------------------------------------------------------------+ w5 M: t% Y% n! x3 G
  51. // ReadPhysicalDrive" V8 l4 L4 w1 f
  52. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
    " Z5 X; ~* ]" z9 I" e
  53. {
    ! ^  E0 `, C& A( o( N
  54.    switch(Win32Platform)
      b* U; _" ^# o. |  \
  55.    {) K+ a3 e& \7 n, j; d
  56.        case VER_PLATFORM_WIN32_WINDOWS:
    " B( ]0 W9 x' w# M1 q$ [6 e* j
  57.            ReadPhysicalDriveOnW9X(pSerList, pModeList);
    6 S7 x/ A# a, j. Y- _% [- f, B
  58.            break;6 O, z7 W' f# g2 Y4 D
  59.        case VER_PLATFORM_WIN32_NT:
    * l$ B7 T2 h) v! [8 V6 {8 z
  60.            ReadPhysicalDriveOnNT(pSerList, pModeList);) C. m. o: N. U1 A  t. x6 v
  61.            break;  y* t( Q  t" l1 D* k1 ^
  62.        default:
    2 H; U# `9 S4 p5 [, v3 s
  63.            break;2 ^2 j+ _  y- j2 Y& H
  64.    }; n. _/ K$ ~4 Y5 q) ~  i) v/ \% I+ M
  65. }( P0 O9 D& X4 [2 K: ?! S, @
  66. //---------------------------------------------------------------------------5 ~! ?+ }% y0 p8 U8 H2 u- Q
  67. // ConvertToString
    ) b$ R3 e. c2 E- K) v
  68. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex). w1 |7 J+ f& x  {
  69. {: s! d8 _8 x- @: a4 a6 f
  70.    static char szResBuf[1024];
    1 I$ r7 o! d. ]) C5 a! |. @, d( L
  71.    int nIndex = 0;
    6 {0 h: e- p9 e& @$ V) z; Z6 h+ k. ]
  72.    int nPosition = 0;/ Q9 E3 h8 [1 o/ ?8 K
  73. . H( q$ ?; f( |! S3 ~0 @; L, p7 I! K
  74.    // Each integer has two characters stored in it backwards
    3 R/ R4 {( _2 O3 Y. `& s" p
  75.    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
    % w; h) W; Y+ L& K3 D% y3 W& e
  76.    {
    , S) P0 Z' }' |
  77.        // Get high BYTE for 1st character+ T% c' v( z$ X0 W  v
  78.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
    ' t4 z2 k  {; t
  79.        nPosition++;
    , s( Y. k0 e/ g3 |

  80. # q. [6 [' u9 D* K0 |  G
  81.        // Get low BYTE for 2nd character* ?6 t* O- s+ r% O2 x, m
  82.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);$ h. h# V6 W2 r* G$ S) K6 w3 E9 D$ m
  83.        nPosition++;" }. }& T( ~4 d7 E2 ~
  84.    }- U9 j8 j% }* Q% S: m+ e
  85. * m; w& [. f1 h! W5 ?: ^
  86.    // End the string
    3 G" O8 M- U* t8 W7 {
  87.    szResBuf[nPosition] = '\0';7 B2 G; L* R) f1 z; Q1 C& T: p% O

  88. 0 F- X/ u& ?6 c$ A* w# w
  89.    // Cut off the trailing blanks
    ' |; M) m& B8 r: w
  90.    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
    1 s* I! W& U4 G- o! ^
  91.        szResBuf[nIndex] = '\0';
    ; l/ R5 c( m; [! J( Q

  92. 7 {: G7 g9 K' {1 R' v" l# p
  93.    return szResBuf;4 A3 f" {: v' K; [7 o# Y3 E! @( \
  94. }* S1 i! J* }) Z# J2 ]/ t; ?4 D
  95. //---------------------------------------------------------------------------
    ( S, U- B% c* m
  96. // Winndows NT4/2000/XP 代码, S! ~( k! m' a# |% g
  97. //---------------------------------------------------------------------------
    " Q  n4 G$ o# C& j6 _4 C
  98. // ReadPhysicalDriveOnNT
    3 L: u% X- {6 R$ ~" Q: {  q
  99. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
    $ z+ b3 w; F' `. q# K$ [
  100. {
    - y0 e# L4 f% W  Z4 V6 j& I
  101.    // 输出参数
    # T0 ]4 L' H% s, I( [
  102.    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
    : }0 w& b2 i7 o0 ^6 E. |
  103. # Q' ?0 j% h) K' ~* d
  104.    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
    4 A2 i: v; @0 l) b
  105.    {; t$ n( {+ V9 ?+ c1 A4 `: Q6 V
  106.        HANDLE hPhysicalDriveIOCTL;: U6 G3 x: }1 k- K3 \2 b
  107.        char szDriveName[32];+ p+ z- R) ?7 o: l' Y+ g! v# x3 |

  108. " f% J- C& d) y! _& Z; B& }
  109.        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
    9 o  F+ ~/ O, `! Q% ]
  110.        hPhysicalDriveIOCTL = CreateFile(szDriveName,+ i& b2 w+ g5 o; b3 P) N# p6 K
  111.                        GENERIC_READ | GENERIC_WRITE,, t3 {4 p3 I! g& G" k
  112.                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,3 o* ~. C$ {8 V: G1 m, R: d- E) w8 B
  113.                        OPEN_EXISTING, 0, NULL);
    3 u! e0 a3 v  z5 S
  114. 0 C6 I" ]# j7 T, y0 P
  115.        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)/ a6 ~% |0 F  Y2 K
  116.        {- Q+ F2 Y3 x4 q! B& b4 W! O  C. d
  117.            DWORD dwBytesReturned = 0;
    ' r+ k9 s0 X/ Z/ V3 E0 G& J
  118.            GETVERSIONOUTPARAMS gvopVersionParams;
    " J0 U1 i" P; D. p

  119. : y* b; p% h6 E( V# G
  120.            // Get the version, etc of PhysicalDrive IOCTL. K+ P- w! u$ L" a
  121.            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));, I" L* f. {  }  f+ }# J
  122.   Z; F5 ?! P) B  L. R
  123.            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,9 }( |4 @1 o% s: e
  124.                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),. o) F% T2 z) h4 u" `
  125.                    &dwBytesReturned, NULL))) N6 D: X- y2 |9 m& L' D: m
  126.            {1 e& K" Y  x. b4 L  I( @
  127.                continue;
    - E2 S! T; h$ N+ ~# e( |1 m
  128.            }
    ; C4 k1 w" m$ h. P8 }- e2 v2 P+ G; D
  129. 3 ]) K6 x, S' m3 Y  e
  130.            if(gvopVersionParams.bIDEDeviceMap > 0)8 @/ |3 f% L. @9 K1 C. D
  131.            {" G- U5 `/ }) t5 p* R! w
  132.                // IDE or ATAPI IDENTIFY cmd$ [" ]8 h0 b* P1 f5 J+ h) g
  133.                BYTE btIDCmd = 0;/ q7 ?6 \2 S) J4 f
  134.                SENDCMDINPARAMS InParams;
    " |8 o, Q7 k, ~
  135.                // Now, get the ID sector for all IDE devices in the system.' l/ F2 Q8 L) g% h8 n- ]" n. Y
  136.                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command," i+ ~6 e8 d! v5 k2 j" l
  137.                // otherwise use the IDE_ATA_IDENTIFY command
    4 p; b2 a' b: h1 t1 N2 v
  138.                // 具体所得结果请参考头文件中的说明$ [1 D6 g, m6 c4 B4 ~# f- Z5 t
  139.                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?: {$ t6 {) ]2 R0 R/ b, T& w  P
  140.                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;& E; T1 M- q4 V1 b
  141.                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));3 S5 P  \) J, k8 y. X: l+ i) U
  142.                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));# s9 z. C/ M% b6 q$ f# u% A
  143. . N6 X$ V0 ?% X) S% w( n4 Q
  144.                if(DoIdentify(hPhysicalDriveIOCTL,+ p, b3 j3 B& J1 M
  145.                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,* l# Y! I& Z7 V4 A
  146.                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
    # j/ k! @+ g1 |
  147.                {" d6 [, P# b5 e# W0 e: s6 X
  148.                    DWORD dwDiskData[256];
    5 z0 X7 N# Q( U; l; [
  149.                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件* [: {# H- y, T8 U4 t- |
  150.                    char szSerialNumber[21];1 U" [: ~: z3 X, w- L1 k# ^4 g
  151.                    char szModelNumber[41];
    5 q0 v3 J) F. k! j! n; i9 O. O
  152. % ~2 d- s& t( h. b
  153.                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;# B; k& ?" X  s; o/ C  X- c& k
  154.                    for(int i=0; i < 256; i++)
    - }8 e. @) ]2 _, Z
  155.                        dwDiskData = pIDSector;
    8 m; |' P# w# [- n) m4 `
  156.                    // 取系列号
    , o: b/ w& w. J
  157.                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
    3 |# z$ N: [4 {, K2 w' z( b) @
  158.                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
    4 ~" a- K  p) w3 v1 h; E

  159. . [) [; Z5 o& h9 o. {+ u
  160.                    // 取模型号
    1 N; W6 P" Q4 n  F# j" R' X
  161.                    ZeroMemory(szModelNumber, sizeof(szModelNumber));# J, T  i1 l& K
  162.                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));. R. M: f' O& U, `

  163. * v& G$ C# N$ T
  164.                    pSerList->Add(szSerialNumber);9 ]  A7 [$ u9 K+ o6 {. ]
  165.                    pModeList->Add(szModelNumber);
    ' n+ d; `" ^$ v8 z
  166.                }
    6 g* C- b7 W1 m2 {9 Y% ^
  167.            }
    6 U1 L* f3 c6 d7 Y% D# h% ?
  168.            CloseHandle (hPhysicalDriveIOCTL);& A* C9 N$ b" O' F0 h  e
  169.        }" Z) Z$ f- y/ U8 K/ u& N7 [+ b
  170.    }
    9 g5 X) J( t6 X8 a$ q
  171. }: S8 T- X: T$ F! Z
  172. //---------------------------------------------------------------------------" s, d! A% l3 h, l  k  @6 M
  173. // DoIdentify/ ]' D. S# ]0 ~1 B( k( V3 j  @
  174. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,' h, ~+ }& m1 ?' U( u# x& O5 q$ A
  175.              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,) ^; z) A+ x9 O4 E) G/ _9 w
  176.              PDWORD pdwBytesReturned)
    & g: R& D$ C( w6 w' D7 Q) {1 u0 t
  177. {! s+ A$ ^' s0 G
  178.    // Set up data structures for IDENTIFY command.
    2 w" \. `0 N) h1 h/ R
  179.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
    $ y2 c' v+ Z) x* n
  180.    pSCIP->irDriveRegs.bFeaturesReg = 0;
    6 [5 c8 h  D$ l" S9 {& X5 D
  181.    pSCIP->irDriveRegs.bSectorCountReg  = 1;
    ( `9 {' C; X, d- m1 R# W0 W
  182.    pSCIP->irDriveRegs.bSectorNumberReg = 1;
    ! {+ i" ^+ t  f& O7 P0 }
  183.    pSCIP->irDriveRegs.bCylLowReg  = 0;+ U/ I0 \+ |& P% c- d$ |$ b
  184.    pSCIP->irDriveRegs.bCylHighReg = 0;
    & l; k9 Z9 C( ]& m/ {$ \# l
  185. , w1 h9 ]- j0 s  o
  186.    // Compute the drive number.(主盘和从盘所对应的值是不一样的)4 y6 k" V+ w# c7 ]
  187.    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
    . x$ F. f6 u, _/ S1 d
  188. # ^( N3 Y  s1 L: o. y! }' V- i
  189.    // The command can either be IDE identify or ATAPI identify.. \, v3 l% }& B9 h, [' Y
  190.    pSCIP->irDriveRegs.bCommandReg = btIDCmd;
      x3 o) v6 E& d+ h6 j$ E0 p+ Q/ t
  191.    pSCIP->bDriveNumber = btDriveNum;
    % G' S3 w+ P3 J6 \9 y, Q- U
  192.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;% V6 c" \1 A' U: g$ k

  193. 5 V- f+ `& c% V6 J4 b9 }
  194.    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,  K! t0 V( M3 X  L
  195.           (LPVOID)pSCIP,
    3 p: R# H+ i( P2 T5 I8 B$ Y
  196.           sizeof(SENDCMDINPARAMS) - 1,
    1 N8 [+ y7 }; G! ^; r1 o) O6 E
  197.           (LPVOID)pSCOP,
    % |0 T8 y9 |1 L' Z# h% C( J
  198.           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,/ C$ ?0 l& m  F0 u" \
  199.           pdwBytesReturned, NULL);# Z) d  ^# G& ]/ o: v
  200. }
    ! y0 F# @' ^9 s7 U! K- L3 W; W9 B
  201. //---------------------------------------------------------------------------
    5 a$ \  [; R# I5 B
  202. // Windows 95/98/ME 代码4 ]+ v4 q) ~3 _3 b
  203. //---------------------------------------------------------------------------
    8 G! }5 A# s2 I5 k$ ?) @# U+ G
  204. // ReadPhysicalDriveOnW9X
    # o0 Y: z9 @" w* C0 q# a
  205. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)
    : v1 U  f" s$ Q. d& m: K' ^% f
  206. {3 {- n! G! P! D' _8 B0 ]+ G
  207.    WORD wOutData[256];
    ) V% S0 F' D6 y) f9 h. a
  208.    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
    8 P, ~5 ~* q$ h$ s3 y

  209. . S2 Z4 N3 r$ E9 n  w* f9 I
  210.    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。; [& A* J5 z! W( h, p8 y
  211.    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以6 x+ z1 T) Q# n
  212.    // 避免蓝屏的出现。(期待高人能指出原因). o: X& n9 j9 g+ B
  213.    for(int nDrive = 0; nDrive < 8; nDrive++)2 p' r* l* C2 F4 C
  214.    {
    + z& k) Q. ?  P0 O" F. _
  215.        WORD dwBaseAddress;! M1 `% v) J# Y$ m
  216.        BYTE btMasterSlave;         // Master Or Slave  b; {- y( c' t8 D9 M
  217.        bool bIsIDEExist;: c* R8 h5 _* B8 H0 x
  218.        bool IsDiskExist;
    9 e" x/ p- j3 ?
  219. 1 ]! S) i( w  c7 ]3 F" l% m4 U* _
  220.        switch(nDrive / 2)1 ?8 S% Y4 T9 a( u* A% K# v4 Q3 O
  221.        {
    ( d+ j: ?% n; c: E3 x2 l9 I
  222.            case 0: dwBaseAddress = 0x01F0; break;
    ! b- m6 E7 |$ T% ~: i
  223.            case 1: dwBaseAddress = 0x0170; break;. d2 F& w& Q; h, m" e
  224.            case 2: dwBaseAddress = 0x01E8; break;) c1 V5 H9 J$ l, ?# O
  225.            case 3: dwBaseAddress = 0x0168; break;! m$ S! x4 Q, {. j
  226.        }# \+ ^0 u0 n9 a2 h$ ~6 r
  227. " @1 I* v: B* J: S4 {2 w, z
  228.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);0 D7 K  r5 @/ `8 R

  229. 5 }8 T- I2 a3 G7 G6 M
  230.        // 进入Ring0$ J) P) a' v& A1 H  R0 G
  231.        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,' U! N$ G0 x- N* u+ t) y. b, C
  232.                bIsIDEExist, IsDiskExist, wOutData);
    : [- [1 w0 i6 Q* k, a
  233.    }+ r2 H/ _4 V0 U+ p1 I/ |
  234. 9 b. {$ D) {& w6 o% D
  235.    // 开始读取  p( f' R' y+ e) {* y3 s& \& X
  236.    for(int nDrive = 0; nDrive < 8; nDrive++)6 z, B8 u$ C; U! `) a) H6 j
  237.    {
    / f5 S! |) W9 u3 n4 h% ^) R
  238.        WORD dwBaseAddress;- z& K6 B2 t4 c( F3 p5 Y$ O/ t1 q
  239.        BYTE btMasterSlave;         // Master Or Slave
    ' m6 E* R9 _3 F/ l' `- A/ t6 ]
  240.        bool bIsIDEExist;6 m& e  n9 M3 ^0 J' D
  241.        bool bIsDiskExist;
    . a+ ]) a+ B/ z
  242.        switch(nDrive / 2). ~& G0 Z  K4 V' N4 @
  243.        {! p. i5 a  \2 F) `* a" H6 n3 U
  244.            case 0: dwBaseAddress = 0x01F0; break;
    3 m5 S( S6 p' l$ W9 T, \$ H
  245.            case 1: dwBaseAddress = 0x0170; break;
    9 V1 G, }* e& s6 T+ b- A) x, |& P
  246.            case 2: dwBaseAddress = 0x01E8; break;1 g2 Y! M. _+ i# \5 W5 t1 u
  247.            case 3: dwBaseAddress = 0x0168; break;1 V% S+ `. m) e; f. f1 ^
  248.        }
    : p& o/ }- u/ h' D

  249. / A0 ~7 Z8 ]0 |/ ?1 ?4 _) B
  250.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);. N9 u8 T; w5 {" K; a
  251. ) A; j' s/ t& i* M
  252.        // 进入Ring0
    ) ]4 {, l1 S$ S! H5 K
  253.        bIsIDEExist  = false;8 p. A  Z0 t- a. m! R
  254.        bIsDiskExist = false;' v7 U' l) _( |& E7 R, a
  255.        ZeroMemory(wOutData, sizeof(wOutData));
    ; D" D8 _/ }6 ]" u. J1 K
  256. 6 t# E/ g+ {2 p$ G
  257.        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,7 A, Q- i  m1 m
  258.                bIsIDEExist, bIsDiskExist, wOutData);
    ' d) U4 M: u. ~- v: p
  259. . N7 \+ T: |, l$ z" h5 w
  260.        if(bIsIDEExist && bIsDiskExist)- ^- w, r$ H& P7 F2 k2 r; p& q
  261.        {& Z, ]4 Q7 ~1 D/ m8 M
  262.            DWORD dwDiskData[256];
    ) s, Y8 L0 H5 g& @
  263.            char  szSerialNumber[21];
    1 p! D. {7 g9 j) v+ O
  264.            char  szModelNumber[41];* d, U. w2 ~) b6 |, T' Z. q

  265. + o2 n" `( X6 z6 t
  266.            for(int k=0; k < 256; k++)
    2 G9 x- u( J* d5 h. \
  267.                dwDiskData[k] = wOutData[k];
    : ]/ d: V3 w, F% }

  268. $ l) M* k! Z# b% y/ E0 q; W
  269.            // 取系列号% a2 F# s# R1 j% k) t# N7 f, C: N7 F
  270.            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));; M6 W# c! Y' Z9 E
  271.            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));, i: [2 p/ k& k8 W, H

  272. 8 q8 W( M2 A- L6 f% Q
  273.            // 取模型号5 ]/ G' q0 g. C( ^  `3 Y
  274.            ZeroMemory(szModelNumber, sizeof(szModelNumber));8 A0 L4 v  U. x2 L. l+ C2 I5 L/ H
  275.            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
    ) f" H! j2 b3 R" E) f! z9 Y
  276. % X* p5 i  d: v' a. L8 F' k
  277.            pSerList->Add(szSerialNumber);" Y# d( \- v6 ~4 ?/ S
  278.            pModeList->Add(szModelNumber);
    - n: X0 I, j, F
  279.        }
    ! g7 l7 I* R6 P4 |/ q. N: h
  280.    }
    2 o" `" Q2 ^" q2 x& I# l' h
  281.    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
    6 E/ |' m$ U! y$ `/ S' _
  282. }
    % k( u. j5 ?) \7 a. [7 |, F$ m7 x
  283. //---------------------------------------------------------------------------
    ) g9 h4 N" m3 }5 S; ?8 ^/ q
  284. // ReadPhysicalDriveOnW9X_Ring0()- B( \; b: t+ z9 k; L, ]
  285. //4 c( `' ^# E4 U9 @' t7 F, M; ?: W
  286. // dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h2 \  n& ^! G# Z8 [8 d
  287. // btMasterSlave = Master(0xA0) Or Slave(0xB0)+ c( u: v  V6 v/ n4 v) s
  288. //---------------------------------------------------------------------------
    - K9 w6 {. y" l% p: p: y* t
  289. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,+ z' Z1 d9 b+ N* g9 y6 h+ u9 ^- @
  290.        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)$ Y0 U) R& N. r8 h- y
  291. {. A3 g  v8 N( z9 U
  292.    BYTE  btIDTR1[6];
    6 B% z+ T1 r+ `% V! n# C9 c; M( P& i
  293.    DWORD dwOldExceptionHook;
    : G4 F$ c% ~! _2 R8 G8 j
  294.    const int nHookExceptionNo = 5;8 i' U8 T2 c: L# w

  295. 3 R& \. x' t% @6 u! _1 n- p
  296.    BYTE  btIsIDEExist = 0;
      d- M3 I  A, v) ~6 |3 T# h  p
  297.    BYTE  btIsDiskExist = 0;
    & Y  C1 c% L# ]8 N1 |
  298.    WORD  wOutDataBuf[256];
    7 g( I; b. d! _9 J1 \2 Q5 f

  299. 0 O. b/ z9 Z  m9 x* _: A
  300.    BYTE  btIsFirst = (BYTE)bIsFirst;
    ; F) X0 g2 V) _3 n3 L# V+ A- I
  301. ! K: z# _6 E6 N# @
  302.    const BYTE btBit00 = 0x01;
    9 w% C4 w/ U0 G) G  k5 u
  303.    // const BYTE btBit02 = 0x04;
    ( X5 E4 {. @, e& c5 k3 ^
  304.    const BYTE btBit06 = 0x40;/ A5 u. n9 F. O4 v6 }8 _
  305.    const BYTE btBit07 = 0x80;2 o+ J' ~  E& S: w) H1 P! L
  306.    // const BYTE btERR  = btBit00;! w- l$ g. ~( h4 |! }, `) L
  307.    const BYTE btBusy = btBit07;) h9 Q* Q2 u% {2 Y/ @4 E$ d0 K  L
  308.    const BYTE btAtaCmd   = 0xEC;
    , l9 {& _* a9 b' S9 l& L
  309.    const BYTE btAtapiCmd = 0xA1;% j- }4 Q7 ?- w' r; F% k

  310. 8 V; ^8 G% h1 a* ]- k
  311.    __asm1 l3 F" {1 Y5 }* w
  312.    {
    % ^/ n0 P+ B) `& q0 ?" Q& R
  313.        // 必须先执行这条语句
    - y: D$ [1 R0 L
  314.        JMP EnterRing0+ W' p4 B4 ?* |& y, O8 G

  315. ( [7 G, J- Y( g# b, F
  316.        // 定义过程
    , c& e* W' p- V6 b. j& H% \
  317.        // 等待IDE设备直到其不为忙为止, k. x) K" y6 G7 J
  318.        WaitWhileBusy proc
      U6 A$ P/ A" Q5 b
  319. : j7 C+ ~- c7 h, j; v
  320.        MOV  EBX, 100000' c7 L; F6 I8 [4 D- {2 E
  321.        MOV  DX, dwBaseAddress
    ' X  M5 ?- W* q4 b' O5 F; h1 X
  322.        ADD  DX, 72 {5 O/ l* r$ p* l/ B
  323. * `! t6 [5 ~; @! s3 s
  324.        LoopWhileBusy:
    - c% Z' v8 a. V$ c2 b' t$ h! }

  325. 5 T5 n' w2 j8 t. \, {
  326.        DEC  EBX
    1 ?! D" t( j& [
  327.        CMP  EBX, 06 Y* B- u1 y& A% J+ ]  H% m7 J( P# y
  328.        JZ   Timeout- n) \0 h8 P& J1 M) O( S1 P' p
  329.        in   AL, DX
    , M& {+ n5 ^# c+ ~# N/ ^/ r
  330.        TEST AL, btBusy
    6 P9 }  m- R+ p. H
  331.        JNZ  LoopWhileBusy
    2 }- f& n$ r: M4 v) g+ n1 g: H
  332.        JMP  DriveReady' Z4 _- \( c" q2 a
  333. 2 X( |: z# i" b; q6 v
  334.        // 超时,直接退出% l( B/ J# T: l
  335.        Timeout:" i  l* P8 u. O( M
  336.        JMP  LeaveRing0' o3 i  }# N' e* k  x
  337.        DriveReady:
    , q+ y( T# i. K; g- B, H- \
  338.        RET
    , Y  O+ n+ U/ Z7 l4 m
  339.        ENDP   // End of WaitWhileBusy Procedure) f8 Y4 I- r4 Y1 }
  340. % ]% Z( m5 ~0 J" a1 I' `. W& p
  341.        // 设置主盘和从盘标志/ ~5 K  X4 f/ @/ n5 I, h" L
  342.        SelectDevice proc! V$ K7 F8 d+ D+ z6 [1 l

  343. ) K  M3 N* d. ?7 N  f+ \/ D7 r
  344.        MOV  DX, dwBaseAddress* A1 Y% r& ^1 p8 t$ y0 j) |8 J! n
  345.        ADD  DX, 6
    " x1 I3 B9 [) b2 M# H4 W
  346.        MOV  AL, btMasterSlave
    , x" i$ x5 V9 m' o. ]! g& ]) T6 j
  347. / p; s$ u- Q8 J8 {! j
  348.        out  DX, AL* f1 S3 Y& I8 S* n, V/ c/ f
  349.        RET
    0 L" r" Y5 }* A

  350. * g8 `  k* b6 I. C% I
  351.        ENDP  // End of SelectDevice Procedure
    3 t, Q9 V  s8 f5 Q2 P2 w1 U

  352. ! g4 h* n# ^# Q$ h# z
  353.        // 向IDE设备发送存取指令
    * y' J( m+ q$ m% X
  354.        SendCmd proc
    % u: r8 i% K  F" ~4 Y5 v8 [) W
  355.   l1 m  F6 V/ C5 H0 K- N, ~% E
  356.        MOV DX, dwBaseAddress9 R# c" X8 L7 w; ~
  357.        ADD DX, 7; I4 v/ d$ z8 ]5 w; u( x
  358.        MOV AL, BL // BL是主从盘标识,在过程外设置
    ; x9 p1 y# x+ Z& U( ^: j8 k+ M$ B9 z
  359.        out DX, AL0 E) j- d" p9 h) o3 |' U
  360.        RET4 t: z: i9 f+ |/ @5 [9 l  V
  361.        ENDP  // End of SendCmd Procedure
    : e5 A+ P+ R2 W+ Z0 v: ?+ B3 Q

  362.   H& v. @0 i# d
  363.        // Ring0代码( }, b0 V3 c2 X( i. c3 m* ?. C7 V
  364.        Ring0Proc:- @3 c0 Q" Q2 C" A
  365.        PUSHAD8 g  m0 s; @3 K! z
  366.        // 查询IDE设备是否存在
    / f3 s/ l: s. E
  367.        MOV DX, dwBaseAddress
    1 u! b/ L4 V' j# T( B9 Y+ ~# q* N
  368.        ADD DX, 7
    5 P* `' E% q- K3 W, c* Y
  369.        in  AL,DX
    6 |8 Z) |( X* f% \- h& E" K

  370. % k/ n0 {4 ?, [$ w& f# M- W7 K
  371.        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回* ?* L8 b) ~* n/ }
  372.        CMP AL,0xFF
    " K, W# e% s- Q! t! m
  373.        JZ  LeaveRing0
    ) o# F0 T  \4 |1 C9 R
  374.        CMP AL, 0x7F9 U' k; h! U  f2 R, m: I( q
  375.        JZ  LeaveRing0$ m, W: M3 z2 O3 I

  376. 1 M0 J5 X& Q: t4 p$ t/ F5 a' l
  377.        // 设置IDE设备存在标志
    & [9 J3 \* t8 ?
  378.        MOV btIsIDEExist, 1
    / g) Q1 K1 i' y% B; a  o9 w
  379. 7 f6 l2 S9 F- {) s' l
  380.        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)$ A' |( T5 p2 ]7 |& x
  381.        CALL WaitWhileBusy7 l1 P1 X( W  @) Y
  382.        CALL SelectDevice7 h0 J# h8 c* U: v! l2 w* [

  383. " [% G* Q- M# V3 a  f
  384.        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏# k; @9 v6 k+ J$ v3 F: l) i0 }
  385.        CMP  btIsFirst, 1
    + |& W5 `/ Z" O7 v  `, r+ E& O$ h
  386.        JZ   LeaveRing0
    9 v$ ]+ |# k4 h7 `" V: m

  387. : \* L% f8 u* F3 M0 `
  388.        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???8 Y! w: |( j4 L. H7 d* M3 ]
  389.        CALL WaitWhileBusy- ?9 n. `1 E; ?" y+ q2 E7 M
  390. ! J! r# o) c, ^
  391.        // AL的值等于cBit06时,不存在驱动器,直接返回! }- N# K) m  K) L
  392.        TEST AL, btBit06# j- H0 O. E7 ~3 T$ j( y
  393.        JZ   LeaveRing0
    7 L* i) T7 a$ A3 Q2 \9 g' N+ H) H

  394. # v6 {$ [/ M. [5 w
  395.        // 设置驱动器存在标志
    0 }' s" _( `! O4 J# ?- i
  396.        MOV  btIsDiskExist, 1
    " E* w- q% n* e

  397. # L" h$ l; i# w: E+ b- N
  398.        // 发送存取端口命令
      b8 |7 Z0 z. j
  399.        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,8 T4 E4 S! G# \/ B, z  r: V
  400.        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
    8 [7 D* j9 O! x8 W" _
  401.        CALL WaitWhileBusy
    ) p  N/ Y5 }$ ?  S/ q2 R3 S: W$ }
  402.        CALL SelectDevice    // 设置主从盘标识( k) X/ U2 O$ b6 X+ U5 {) f1 z
  403.        MOV  BL, btAtaCmd      // 发送读取命令
    + H# J8 e9 _/ A; P9 e; r
  404.        CALL SendCmd9 Z6 O3 E0 S) U4 ~% j1 ?
  405.        CALL WaitWhileBusy
    + C! }2 r5 L( P
  406. 6 U4 {, D, |0 b
  407.        // 检查是否出错
    0 N5 f# M( C4 `9 |+ V' z# |8 w; J
  408.        MOV  DX, dwBaseAddress; p( {  X( h8 C2 i3 z  B
  409.        ADD  DX, 7" A3 u( z* v6 ~

  410. " \6 ~, [: l8 V  Z+ d. [
  411.        in   AL, DX
    4 e# X+ G4 |  i

  412. % i  ^$ {; V  ~/ |/ T, j5 U
  413.        TEST AL, btBit00% s2 n) a" y2 W! o* W7 q6 r7 K
  414.        JZ   RetrieveInfo   // 没有错误时则读数据
    ( @; q# C1 _  Q

  415. 3 B$ I3 U  W5 `, X: }
  416.        // 如果出错,则进一步尝试使用ATAPI设备命令* y+ k7 l' M9 K% L5 K
  417.        CALL WaitWhileBusy* R$ V0 X0 @# k, V- ~6 h
  418.        CALL SelectDevice/ e! ^3 o& {% u- a! @4 Q3 Q! ~
  419.        MOV  BL, btAtapiCmd; s  f8 s" {$ u( C
  420.        CALL SendCmd& p1 Y4 e9 e9 Y: K
  421.        CALL WaitWhileBusy5 B/ E' ^% @8 J

  422. " u% e  j) K' k/ N- T2 A
  423.        // 检查是否还出错
    - o- W2 k6 ?& k) x% c
  424.        MOV  DX, dwBaseAddress6 @: x  T3 I: z5 T
  425.        ADD  DX, 7, k0 x) R; K& R( s" e5 H
  426.        in   AL, DX1 ~) M! A- \" f, D. A0 s2 r  J# k3 P: D
  427.        TEST AL, btBit00
    , c  J9 E5 l3 F5 ~0 H, G
  428.        JZ   RetrieveInfo   // 没有错误时则读数据
    ' b* k9 y5 I% h! X8 X5 b4 M& {
  429.        JMP  LeaveRing0     // 如果还是出错,直接返回
    0 I! @, m; x8 v4 \, R" |

  430.   p* I* a+ O( Z- t* x
  431.        // 读取数据
    " s0 m1 w# p" q9 {, m" o) Z( f& u
  432.        RetrieveInfo:2 X* }8 I% f. o# ]. K! {/ o; f

  433.   b: @$ x4 e. _* I0 F) D
  434.        LEA  EDI, wOutDataBuf3 h7 l3 z4 v, ^
  435.        MOV  ECX, 2560 h+ P. E; Y% M+ Y! e$ l
  436.        MOV  DX, dwBaseAddress1 n/ X2 J1 z* Q" T% o
  437.        CLD( `3 g6 h( E( U! I$ b5 s
  438. 1 {% f) T% T0 B( w6 I
  439.        REP  INSW
    & y! T0 Y- Z# o6 X2 C, ?, ]0 X

  440. 5 S' ^- `9 ]  x$ U7 {( U: W! {0 _
  441.        // 退出Ring0代码
    - H1 E" z5 M& k% p9 ^* K' i1 S
  442.        LeaveRing0:
    1 {2 m, h) {, P. X9 W! ~' U1 E

  443. + X" d: B: l/ E+ j+ A6 }1 Z6 x
  444.        POPAD2 s1 L' T; K0 c1 _
  445.        IRETD
    & U' O2 b7 O) P- t2 _! I% s
  446.   H0 R6 O( ?; }$ l9 y
  447.        // 激活Ring0代码
    : f5 g; |5 @; r) \
  448.        EnterRing0:
    . I: Z) h( M2 d+ H/ S4 t

  449. ' [5 _6 p: b8 F, c; g4 Y1 y9 {
  450.        // 修改中断门, _% g! \1 x' U) T5 {! I
  451.        SIDT FWORD PTR btIDTR17 S' {% ]3 x% H/ n/ B" }  P! }. w- _1 d
  452.        MOV EAX, DWORD PTR btIDTR1 + 02h
    ) s$ G$ T* G8 ]/ I8 G
  453.        ADD EAX, nHookExceptionNo * 08h + 04h3 ^+ C; O: o' E9 ?' V4 k4 D
  454.        CLI& t3 x: h! |. v  a
  455. # x8 ]. B7 {# v9 E5 P& }
  456.        // 保存原异常处理例程入口) s3 E& q6 U$ ~6 q) b  f/ \
  457.        MOV ECX, DWORD PTR [EAX]: O! p. p1 {2 f) N$ v( S
  458.        MOV CX, WORD PTR [EAX-04h]
    ! J* p1 s: H. g$ E5 u2 X: U9 A4 L
  459.        MOV dwOldExceptionHook, ECX- [, G; z0 o" g2 z$ W. V& x3 r4 y2 z
  460. & W2 X, }* X& Q  ]
  461.        // 指定新入口' i0 s, }. u8 p+ r. J7 U: B3 ~! F
  462.        LEA EBX, Ring0Proc
    ' S! a) L7 k- @& @* G
  463.        MOV WORD PTR [EAX-04h],BX0 z* {9 \: G3 @3 ]2 Z4 ]
  464.        SHR EBX, 10h
    1 R* w) T4 v4 _& r* `4 R
  465.        MOV WORD PTR[EAX+02h], BX# Y- ?9 E; R, n# p, _, J1 ?
  466. 1 @: n5 a, z; }3 e" z
  467.        // 激活Ring0代码' I. U2 C* P' l4 Y! _; z
  468.        INT nHookExceptionNo; F1 m) S0 D; B: v3 M) m9 d
  469. ; g% l% P& r+ a0 b0 p- L& G! [8 s
  470.        // 复原入口# r. Q& l, W0 E+ e7 E1 [0 l7 y
  471.        MOV ECX,dwOldExceptionHook
    0 ^- {8 G+ y$ \' `: V0 m. K3 K7 M  [
  472.        MOV WORD PTR[EAX-04h], CX4 \# m, b0 \  @% X6 I, {
  473.        SHR ECX,10h) B' S5 n  d+ W' u1 Z* U4 ]; X
  474.        MOV WORD PTR[EAX+02h], CX
    : |# `5 F/ b( j. u3 W7 O
  475.        STI
    + H$ ~' f! f1 Q# t% U5 C# w
  476.    }0 C  F) U4 W% |0 H* D* u. q
  477.    if(!bIsFirst)
    " G: i. `* n' Y
  478.    {( o3 X- s, E9 c8 E
  479.        bIsIDEExist  = (bool)btIsIDEExist;- O' j/ O$ o* y* l. T% O% l
  480.        bIsDiskExist = (bool)btIsDiskExist;3 z9 [# J6 a  r" `. e( a
  481.        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));3 R% k) h! w% _& z( b3 K2 Q
  482.    }; V! Y+ K! k/ h& C
  483. }
    ! [% u+ `; O% b; K0 M, D
  484. //---------------------------------------------------------------------------
    8 _# S6 ^- H! R5 O$ d: R; [
  485. // 调用方法:- E- J+ q+ I: |* d1 G
  486. void __fastcall TForm1::Button1Click(TObject *Sender)
    ! _2 J: i4 O1 g- H- F
  487. {$ ~0 x& w; R# k) d" p$ c
  488.    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
    ' G' B) h% M8 e( o* T: R3 z
  489. }
复制代码
发表于 2005-8-15 01:00:45 | 显示全部楼层
晕乎乎。。。怎么看8 洞阿
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-6-18 08:11 , Processed in 0.019763 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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