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

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

[复制链接]
发表于 2005-8-11 11:42:04 | 显示全部楼层 |阅读模式
  1. #include <WinIOCtl.h>
    2 J% F: y$ s$ E& r# Y) B4 S7 `+ t
  2. #include <stdio.h>
    . [( o: P0 V* I: n

  3. # [, C+ m: ]8 c
  4. #pragma inline' r( E3 }+ v& ?; T6 ~
  5. //---------------------------------------------------------------------------
    , i! W2 {7 L6 t( e: G
  6. // IDE NT/2000/XP专用变量
    3 K: ~1 P2 K. @5 d* n
  7. #define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
    ( _5 C: R, Y4 G  v  D5 A
  8. #define DFP_GET_VERSION         SMART_GET_VERSION. Y! o9 E; Z2 E, E" j5 D
  9. #define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
    7 L* M) P: X/ J. r" B
  10. #define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA/ K: s; p' |# c' _

  11. , l, p  W' x; t& Y
  12. const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令
      e8 P9 {* A% A- ?! y& N
  13. const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令( d5 v, _  z6 ]

  14. $ ~" L2 k4 l' t' v" i7 u
  15. const int MAX_IDE_DRIVES = 4;* H7 P- e5 L; l. w# T7 _/ t4 A
  16. ; {' J/ Z1 d# @9 P# s
  17. // SCSI专用变量
    ! [2 ]- [4 W  Z# |
  18. const DWORD FILE_DEVICE_SCSI             = 0x0000001B;
    2 B6 Z3 N/ J+ F& j4 C) z* P
  19. const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
    5 A# h9 h+ m. l. z$ R
  20. const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition+ o4 s9 J6 B3 f0 a* _3 ~
  21. const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
    * X+ v8 G3 `1 k
  22. 3 \1 c7 ?# Y- q' x1 m' K0 ^
  23. typedef struct _SRB_IO_CONTROL
    # Q2 O4 M) b* {9 E9 @1 h& B1 G
  24. {
    1 |2 }3 M: w* {; `
  25.    ULONG HeaderLength;
    ; W: n1 I0 X  p3 s, v
  26.    UCHAR Signature[8];
    9 y" @+ T7 w2 U) y& I3 B3 a
  27.    ULONG Timeout;
    8 x7 i7 v& K: W$ J1 ]- V6 B+ ^
  28.    ULONG ControlCode;
    - ^1 `5 D. l$ U! l
  29.    ULONG ReturnCode;  M* N0 i# u* k2 n; ~7 h% ?
  30.    ULONG Length;
    ) P: c6 [1 M* l
  31. }SRB_IO_CONTROL, *PSRB_IO_CONTROL;
    . d' c7 j9 n+ E# g4 C

  32. ; s* o& [1 [! q- ^6 ], h
  33. // 读取的主函数, m3 g! Z4 a6 W% ?. z( X3 m* z& T  P- g
  34. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);# X7 `3 l7 c: N1 t2 p" S' I

  35. " Y+ z# {( s- B1 ^& s& K* l
  36. // 辅助函数" l( W6 [5 k! u. h/ t& d3 d
  37. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
    . {( t% @" A1 i+ `  {
  38. // NT/2000/XP函数6 P2 e  ~5 `5 K( n; o
  39. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
    4 Z0 d* O/ J  v8 F* F! K
  40. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
    , o- w2 X5 W$ `/ Y
  41.        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,3 D9 T6 u, h1 P  N! n+ s
  42.        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
    ; M9 S/ i, j9 }4 D" b3 c
  43. // Windows 9X函数
    " t7 g/ |1 r% h, d1 a2 `2 `
  44. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);. ?. x) Y$ D* y: A: s$ m
  45. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
    ; C9 X( ?" h" T
  46.        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);8 T5 G$ x; G8 E3 X7 ~1 I

  47. 6 [( }( f- C, y9 e; c
  48. // SCSI读取函数(for NT/2000/XP)
    2 ]% z  j; ~( r7 U
  49. String __fastcall ReadIDEDriveAsScsiDriveOnNT();# _9 F+ B. D; d  l* |" r0 K# y
  50. //---------------------------------------------------------------------------! B) |) _: \3 y+ ~
  51. // ReadPhysicalDrive
    2 o: x; P/ \' G: b- f
  52. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)8 L, R8 s# [* k2 A4 e: S
  53. {$ \1 x% }8 P9 B/ _0 {
  54.    switch(Win32Platform)2 g2 |$ o+ ~* F8 i5 m
  55.    {
    9 g" \, h9 |5 L, q9 q4 C
  56.        case VER_PLATFORM_WIN32_WINDOWS:
    , G) s0 }  d: M% i; C
  57.            ReadPhysicalDriveOnW9X(pSerList, pModeList);
    6 X& s3 W7 K0 Q  u" I5 }/ L
  58.            break;+ N; Z6 p- @* Q3 p& h- t/ N
  59.        case VER_PLATFORM_WIN32_NT:
    / \1 U/ ?: V7 }- F$ K
  60.            ReadPhysicalDriveOnNT(pSerList, pModeList);  |* ~( s: I4 v% I6 D) ]
  61.            break;% V4 z% B; v* B2 `
  62.        default:, b8 x1 |; q! }: ]6 I1 T
  63.            break;
    + m% l0 \: }3 v: {
  64.    }% L* S* g$ W% S8 Z5 Q
  65. }) V5 D4 @  \! }: q+ N! H9 e
  66. //---------------------------------------------------------------------------6 e, O6 K, T5 F; L9 _* u0 F+ _
  67. // ConvertToString0 O' W$ V, S' `/ B7 G
  68. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
    6 B" F1 H& S" C0 S
  69. {, ]+ A8 N' z/ S1 u( ]6 r3 d/ q& t
  70.    static char szResBuf[1024];2 r. Z- ~4 H3 P" H/ w# w
  71.    int nIndex = 0;
    # n2 N: z0 K" C1 M$ l2 M- x
  72.    int nPosition = 0;
    ! T$ @; Y& @2 D9 g2 E

  73. 8 y! b# \+ x& i
  74.    // Each integer has two characters stored in it backwards
    9 h7 L, ~  o6 T5 u$ p+ c
  75.    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)2 `" Y6 P7 B4 w3 M  t. l
  76.    {
    9 @, e6 M. j/ a  j2 Q; L  e( @+ @
  77.        // Get high BYTE for 1st character8 N+ P9 J+ Q- N
  78.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
      j: D# S6 }8 v0 _( s! z3 I2 \
  79.        nPosition++;
    ' P2 M7 `! R% V5 W0 G* Y( k" A4 k
  80. 1 y  D6 F9 z9 w. _1 u1 z- Y
  81.        // Get low BYTE for 2nd character
    9 E7 x' E* u' q) C) i9 T
  82.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);) s& I% p% z1 C3 q. G: x) B% m
  83.        nPosition++;
    - x, F+ _$ L& W) ?! f0 d+ L
  84.    }
      ?5 L8 }7 a& k; ~; w) C  p
  85. 1 C. z* h$ H* z' N$ D
  86.    // End the string) `- o, m8 D! x# ]0 j3 a4 M( K' p
  87.    szResBuf[nPosition] = '\0';
    : P9 ~6 m& H% Y4 |/ x5 b
  88. ( G' r7 l3 l' f: [; e3 L
  89.    // Cut off the trailing blanks
    2 Z" s" j  {( d9 w9 W1 Z
  90.    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)- R1 n& |4 A: ?  W$ _  B
  91.        szResBuf[nIndex] = '\0';+ G" B8 X& L- P5 d" I1 L
  92. 1 R$ _- T3 \+ m: e% t
  93.    return szResBuf;' ^1 z4 ~, y: `  O# j8 r5 I" B5 M
  94. }
    4 n, C7 {  Q8 S" e; c& m; h
  95. //---------------------------------------------------------------------------
    - V! W, m; X  \
  96. // Winndows NT4/2000/XP 代码* l2 V% ]1 q( |; w
  97. //---------------------------------------------------------------------------6 n5 a1 A( Y  M# ~: ~
  98. // ReadPhysicalDriveOnNT8 P) J8 T' ]; k5 C2 K4 n
  99. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
    , Z3 ?8 ~% u* T* T7 T* `
  100. {
    . M8 N" _! x  I# X* e% [
  101.    // 输出参数" [1 d* W* {" r
  102.    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];+ Y6 T: R) ]; Z2 }7 l* E

  103. 2 K, e( ?  H! G6 w5 N( H
  104.    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
    ) y0 T) |0 Q; W5 p/ `: h5 G8 b# h
  105.    {0 ]- p5 y8 G4 i- i% N5 ?2 N9 E
  106.        HANDLE hPhysicalDriveIOCTL;$ t  i2 v4 |. G4 v) T: ?) W
  107.        char szDriveName[32];+ q0 R0 a7 ?8 X) S
  108. ( C( \3 `3 t( l1 ]5 n
  109.        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
    1 k0 b! m- Z/ f& f# F! B9 w% X
  110.        hPhysicalDriveIOCTL = CreateFile(szDriveName,
    " X* V0 Q. P) Q1 C) U5 M' J- D& Q
  111.                        GENERIC_READ | GENERIC_WRITE,
    * h: j9 a- ~! _+ i6 O& J8 j/ Y
  112.                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,% ^8 ~. m5 s) S* w6 M; k. O) I  U2 D& X
  113.                        OPEN_EXISTING, 0, NULL);
    7 u% X/ ?3 x6 A* `, g

  114. 3 ~: ?6 X9 u% J. U5 G2 W
  115.        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)" I' l' {; E3 r" Q) g
  116.        {
    % w& w" d5 x) K, X2 v0 G! q
  117.            DWORD dwBytesReturned = 0;$ W! ?8 z7 Y  P1 y3 F0 t
  118.            GETVERSIONOUTPARAMS gvopVersionParams;
    $ L3 Z1 V: L4 U7 N. X. `. Q

  119. 3 z' K! @* r# H; n
  120.            // Get the version, etc of PhysicalDrive IOCTL
    9 o5 o9 s8 W! `- r5 o3 {
  121.            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));% f/ R- V& j' L, b7 }1 o  S
  122. 5 x" g2 W: G* q' u
  123.            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
    + Y/ a+ \  q2 }7 @! k# K# a8 A
  124.                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
    ; U% R1 M( b$ s
  125.                    &dwBytesReturned, NULL)): p% x0 C% g9 K! a1 m! {0 j6 K
  126.            {
    , J. X" q1 x+ p  u
  127.                continue;9 [/ c9 N: Z# P2 L
  128.            }
    1 z9 ^* n5 w: J, J2 c) ^: {

  129. 9 Y3 ~0 D9 i& T5 u# H
  130.            if(gvopVersionParams.bIDEDeviceMap > 0)  H5 |( Q+ k! x) l$ B9 {$ Z' g
  131.            {# h; m, z7 ]' u7 o1 i$ H
  132.                // IDE or ATAPI IDENTIFY cmd
    & x7 k+ _  O/ ?/ P
  133.                BYTE btIDCmd = 0;
    2 B/ j/ F5 q, y, V
  134.                SENDCMDINPARAMS InParams;2 @3 m1 T# P' p8 P/ x
  135.                // Now, get the ID sector for all IDE devices in the system.
    : m  h5 f, K5 G- n3 T$ h
  136.                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
    ( p& K+ c6 x7 Z% j# j
  137.                // otherwise use the IDE_ATA_IDENTIFY command
    # Q. ^2 a0 i" F) C' j: P. K
  138.                // 具体所得结果请参考头文件中的说明
    ( `; g4 D; V1 Z5 ?
  139.                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
    1 P# p1 [2 Z9 I( i
  140.                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;( I) k, j" e; p* {4 s& a5 h6 v
  141.                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));$ |; T. k9 ?2 R
  142.                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));3 ?4 v; X& C/ O$ {  t$ U5 N1 u1 Y
  143. + L, k- B$ w/ t0 y% O! l6 ~
  144.                if(DoIdentify(hPhysicalDriveIOCTL,( M5 k% a* Z' y% ]3 R% d! J
  145.                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
    . I. b0 a9 T! ]- H$ s9 N
  146.                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
    9 ^! S" ~4 Y; P' ]* A% o1 ^" |
  147.                {
    + u4 _5 K& }1 }7 [0 J; ?
  148.                    DWORD dwDiskData[256];: ]* g& U$ ?; e& c4 e
  149.                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
    - r* U4 C! T. u( X+ _
  150.                    char szSerialNumber[21];$ |( e4 D8 x( @) ]6 U+ r
  151.                    char szModelNumber[41];! h" M" k+ X' O6 K  n

  152. 2 P+ V* ^1 h( K7 P% C8 E
  153.                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;7 W; \' ~4 y+ Q# [" Q
  154.                    for(int i=0; i < 256; i++)
    & p: o" J- o6 e6 X
  155.                        dwDiskData = pIDSector;
    + v2 E7 ?( {$ @
  156.                    // 取系列号
    , h$ e% Z2 e1 Z
  157.                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
    ; I* ~  |6 c6 F7 Y
  158.                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));; v% Q; o) K3 {: L5 l) h

  159. " f0 b0 ^- t7 J0 H& Y) @: M# W: Q
  160.                    // 取模型号# B( u# k( z# e' p4 W
  161.                    ZeroMemory(szModelNumber, sizeof(szModelNumber));
    * I% F5 k8 _  _, p# S
  162.                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
    " s8 ]: Q0 Y4 ^& x4 q6 ^* k

  163. , v* v8 o5 d9 P7 k1 {4 u
  164.                    pSerList->Add(szSerialNumber);
    0 D- r2 D. K9 B
  165.                    pModeList->Add(szModelNumber);
    & d+ s9 ]) a/ {% A2 @
  166.                }
    + ]$ ?! |3 F; `/ H
  167.            }
    & i$ Z- h+ S! v2 S. H" l  T! h
  168.            CloseHandle (hPhysicalDriveIOCTL);
    3 x! J9 R1 u+ u. D8 Z6 E! g3 |
  169.        }
      ^8 Z5 m5 |, d/ x  b
  170.    }
    ; X; m9 z% x8 ]) d, N
  171. }1 l. u! T0 z3 M* ^; B- v
  172. //---------------------------------------------------------------------------
    4 u& T7 Q. e* ^  B! Y$ {
  173. // DoIdentify
    & E3 C2 ]5 a% z' V
  174. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,) t6 P" C, \, y, V! V7 T0 d
  175.              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,% `# {3 H' _* q8 \2 {) ^
  176.              PDWORD pdwBytesReturned)
    4 Y" h5 O6 ]4 V, x- D
  177. {$ K6 `- `0 B+ ]7 t7 y
  178.    // Set up data structures for IDENTIFY command.1 y. j0 |7 I2 @+ ~$ U
  179.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
    ; H2 N5 z6 |, |3 o" c. P+ G7 ?
  180.    pSCIP->irDriveRegs.bFeaturesReg = 0;! {9 ]" y* j5 g2 V
  181.    pSCIP->irDriveRegs.bSectorCountReg  = 1;
    ; c, I! c9 G0 ]0 V" O1 @4 o* C
  182.    pSCIP->irDriveRegs.bSectorNumberReg = 1;
    5 M! u; }, h! }) B$ ]
  183.    pSCIP->irDriveRegs.bCylLowReg  = 0;% M* y3 r/ d! L9 P* G
  184.    pSCIP->irDriveRegs.bCylHighReg = 0;, R4 `$ K& `% _6 J) ], |; b: y
  185. & h- r( q5 `" @/ s$ y
  186.    // Compute the drive number.(主盘和从盘所对应的值是不一样的)
    ! |  p! Y3 {- ?0 P/ d1 V
  187.    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
    ( c- A* N# e7 o6 t
  188. ! z/ ]& F4 t! m: H3 z9 H0 O
  189.    // The command can either be IDE identify or ATAPI identify.
    . s% \4 ]8 ?' X8 Q8 a. S3 u2 Q
  190.    pSCIP->irDriveRegs.bCommandReg = btIDCmd;
    7 D. ^) Y" _5 g1 S  b) m$ D7 c
  191.    pSCIP->bDriveNumber = btDriveNum;" |  ~9 ]  F/ L* d2 V5 i
  192.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;  G. V' m6 u2 }: d/ ?

  193. # \+ q" |+ \1 q  Z
  194.    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,8 J' G6 `- X, T' j
  195.           (LPVOID)pSCIP,1 O. q  u8 r4 q4 S, K+ N
  196.           sizeof(SENDCMDINPARAMS) - 1,$ b5 ], D% o' v0 I; i2 q
  197.           (LPVOID)pSCOP,( e, L: `! N# P
  198.           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,/ t+ g; ^" y" n* {
  199.           pdwBytesReturned, NULL);
    / A& S- m" ?# j
  200. }5 u% Q5 k& a" s9 A& E. R0 u6 E/ V9 @
  201. //---------------------------------------------------------------------------
    ( R* N: y) D5 n. Y; U* G
  202. // Windows 95/98/ME 代码
    % B! L* w3 M* S
  203. //---------------------------------------------------------------------------
    - [( Q) X. B% q& [
  204. // ReadPhysicalDriveOnW9X$ p: G2 O" Z$ T1 z0 y( [
  205. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)$ K1 T5 \/ a7 P+ C8 |# I! k
  206. {
    2 b4 B1 ~0 {. F# q; P5 N
  207.    WORD wOutData[256];
    6 S+ q! R) J2 g* `7 _+ ^" b7 D+ x
  208.    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
    1 y% N' i$ w) y& T6 N# q

  209. . G% W8 s1 D1 [5 S: o3 E
  210.    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
    9 R/ H1 o9 s3 g/ \" V( O
  211.    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
    ) B( F% p9 J/ }
  212.    // 避免蓝屏的出现。(期待高人能指出原因)
    * S# [* \3 M2 a9 F$ a
  213.    for(int nDrive = 0; nDrive < 8; nDrive++), s: o0 @2 y8 F& E3 J3 U
  214.    {
    6 h1 V$ Y: e6 l6 t+ A% j) a. |
  215.        WORD dwBaseAddress;2 w- Z3 K" F) R; e) n4 F
  216.        BYTE btMasterSlave;         // Master Or Slave, k* Z! a4 w6 f1 B: I8 i
  217.        bool bIsIDEExist;! I) c7 g5 b+ J, R# x$ Q6 ~8 U/ a
  218.        bool IsDiskExist;$ [3 g& t- L1 ~6 |# K! E% |  ?
  219. ; c% G0 J1 J$ n( h* N6 I" D
  220.        switch(nDrive / 2)
      B- Q. t0 b+ @/ u" z
  221.        {
    4 N9 i/ t% t% t, o, J% @3 u
  222.            case 0: dwBaseAddress = 0x01F0; break;
    % g5 Z& f  y& q3 q$ p5 d' h: C
  223.            case 1: dwBaseAddress = 0x0170; break;. i' v3 X/ @/ f% X$ f& g
  224.            case 2: dwBaseAddress = 0x01E8; break;% i7 a  ]; E! E# r7 Q
  225.            case 3: dwBaseAddress = 0x0168; break;' ?7 y3 V- a- ~" l* s7 }5 @
  226.        }
    3 a, v) g5 s; |" s' I; g% j

  227. + ~5 |6 m1 z7 O* c; D
  228.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);0 N9 j) r  Q9 _: k* Y% {# h& [

  229. 3 P: }+ D0 c0 S+ G
  230.        // 进入Ring0
    # c, E3 P7 ?# r# l* ~; c5 b
  231.        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
    9 ~( Y& V' p( b4 N
  232.                bIsIDEExist, IsDiskExist, wOutData);  ]9 G* v! e8 \) i$ H! {8 W
  233.    }/ G1 R  @' s5 _/ y& h$ c

  234. 1 n# k$ D+ o8 A
  235.    // 开始读取7 B' I. z, F9 V) ?
  236.    for(int nDrive = 0; nDrive < 8; nDrive++)) Y, C& e# D3 e
  237.    {
    9 Y( v, {( o; p
  238.        WORD dwBaseAddress;& T" m' S6 h& P
  239.        BYTE btMasterSlave;         // Master Or Slave: m8 k& ^' q" C/ }7 f/ W8 z; _' p
  240.        bool bIsIDEExist;+ ~3 ~# r9 A; `5 K: }  |
  241.        bool bIsDiskExist;+ R# R7 }' \0 m& {
  242.        switch(nDrive / 2)
    " }$ [0 l. G4 O" X
  243.        {
    * h1 J2 b! o' D" g
  244.            case 0: dwBaseAddress = 0x01F0; break;
    3 s% S# Y6 V" V  I2 V9 O1 d
  245.            case 1: dwBaseAddress = 0x0170; break;
    4 W4 W% w% A; Z7 s$ r
  246.            case 2: dwBaseAddress = 0x01E8; break;
    7 _. v+ y: G0 [7 _
  247.            case 3: dwBaseAddress = 0x0168; break;" g5 {* s/ R5 O9 {
  248.        }
    & U. V. g' J5 U; q
  249. * z) T' K+ ~5 S7 G7 E
  250.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
    9 [% G, W4 O* W2 _% X3 S$ y  _

  251. ; i  T1 }+ h+ r# o5 t! \' x
  252.        // 进入Ring0
    ' I. h9 f9 ~, ~$ |) c
  253.        bIsIDEExist  = false;& H; @( E3 {# P0 C& C7 Z7 ^
  254.        bIsDiskExist = false;
    5 C8 D  d( T# l
  255.        ZeroMemory(wOutData, sizeof(wOutData));
    / z6 d4 O& m5 V- Q1 N; m7 \
  256. # \8 ?! Z( A3 \) S; E
  257.        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,' |( B# {/ t3 [0 U  T% Q7 ^
  258.                bIsIDEExist, bIsDiskExist, wOutData);# D4 z4 j1 m. o4 y4 ?! x4 _
  259. ' C# h+ `- x+ c# N) o
  260.        if(bIsIDEExist && bIsDiskExist)
    5 u4 B" l6 _( i( f
  261.        {
    $ @3 V3 C- r" i, N+ p
  262.            DWORD dwDiskData[256];
    8 @" K& ?" E; c
  263.            char  szSerialNumber[21];8 A+ j% e# I- \2 D# N* d# O
  264.            char  szModelNumber[41];8 E# t4 d' b5 _+ D* F5 m
  265. . R, A% k/ \& L: n8 h: K2 w
  266.            for(int k=0; k < 256; k++)" C6 c: b1 Q9 n
  267.                dwDiskData[k] = wOutData[k];/ o& ~6 m& Y  I

  268. $ g  e; ?" y+ L( @! X  _9 N3 H
  269.            // 取系列号
    " U! n2 o0 O) B( I2 I, {
  270.            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
    ) i1 h# d: o* S4 H% }; V( l! t. ]
  271.            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));' m( J9 D3 Q/ O/ b$ A

  272. 8 a! @3 s- m! X
  273.            // 取模型号
    ! i' p2 M: [' F% R/ u
  274.            ZeroMemory(szModelNumber, sizeof(szModelNumber));
    & c& G7 f$ U) |& C2 v
  275.            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));* }2 R# G+ t. Z8 e# D1 T

  276.   F$ p7 I0 q4 k' F% v* y( @2 `4 ?
  277.            pSerList->Add(szSerialNumber);
    ( \. `" Q* W# r, u8 |3 H- w
  278.            pModeList->Add(szModelNumber);) @5 j1 Y8 r' |3 i* B3 A
  279.        }5 U4 O9 G1 ?* |. z* p5 Z1 p( B4 r
  280.    }) V6 d0 z: h6 h, G; u
  281.    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
    , a2 b, ^0 W( w3 k( o6 x. c
  282. }% }1 A3 x5 A) O4 N2 ?( m% h) U8 H
  283. //---------------------------------------------------------------------------
    ( e' i1 X: V: J6 q
  284. // ReadPhysicalDriveOnW9X_Ring0()
    4 v( z/ `; B! N) w0 A
  285. //
    $ h* d$ u2 `  f, k! ~# W
  286. // dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h' b, `8 K1 R* A
  287. // btMasterSlave = Master(0xA0) Or Slave(0xB0)
    - R' V  F3 {5 c8 M" w- O
  288. //---------------------------------------------------------------------------
    " _) R# d$ o/ v0 F" y3 A* e  ^
  289. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,, l# D& B; y; B3 ^7 r3 e
  290.        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)  \" ]8 ^$ ~8 F5 f# S% X( R. t
  291. {0 q7 s7 {+ R$ h0 D' c1 t. c  j9 l
  292.    BYTE  btIDTR1[6];. E% q8 X! Q7 z- Y% W9 ~
  293.    DWORD dwOldExceptionHook;
    ! f6 g( a) m  g1 ]  }7 V! V
  294.    const int nHookExceptionNo = 5;+ Q' L' T" ^, ^  ?0 b0 J' [, m

  295. $ E3 B* x* P9 Q1 B
  296.    BYTE  btIsIDEExist = 0;
    ! }" L2 n: u* C, z0 p9 c" d  [, J
  297.    BYTE  btIsDiskExist = 0;) l7 z$ h( _) V8 P! q( a, p7 G! A- M0 d
  298.    WORD  wOutDataBuf[256];
    3 B7 Z' B' L) W

  299. ( N. ^8 h$ V# Q+ i. S8 O
  300.    BYTE  btIsFirst = (BYTE)bIsFirst;
    / k* o& i, X" ^! Q: U6 Y8 O: J0 {

  301. 2 ], F  c9 {: U" F3 H: A
  302.    const BYTE btBit00 = 0x01;" s+ x7 F5 [0 K! c
  303.    // const BYTE btBit02 = 0x04;
    , g" r" k' B  ^
  304.    const BYTE btBit06 = 0x40;
    + i$ x2 W! `# d. ]) |  d0 [$ z
  305.    const BYTE btBit07 = 0x80;2 p8 M4 W! G. Q' P* d
  306.    // const BYTE btERR  = btBit00;  A) }. K) R4 V
  307.    const BYTE btBusy = btBit07;) ~9 ]. c% ~. Y' a8 [( \7 I
  308.    const BYTE btAtaCmd   = 0xEC;/ B: `/ q3 ^1 s6 c, R, ?0 D: x. q
  309.    const BYTE btAtapiCmd = 0xA1;
    , ~: R7 H( q/ @$ r  b9 U

  310. & t! ]4 C6 p' z2 `! q9 d
  311.    __asm
    3 @/ s9 R: a+ c: A- D5 J# h
  312.    {
    9 ^) g$ Q) [& k8 e# c' p1 w% `* m
  313.        // 必须先执行这条语句8 L$ ?$ J% x9 ]6 z1 N& Z# f. E. s- q
  314.        JMP EnterRing0
    7 W- M, K9 B7 d4 H- T# m* l
  315. " G8 d5 g  T$ u8 U
  316.        // 定义过程  V* f2 Q1 K# _$ b# @. ?5 M
  317.        // 等待IDE设备直到其不为忙为止: c# s. X& @$ {5 f
  318.        WaitWhileBusy proc
    0 F* @0 e/ Q* s; F/ {7 P
  319. ! n" p" j7 d/ t- V& O
  320.        MOV  EBX, 100000- F' |, ~) z* \- V
  321.        MOV  DX, dwBaseAddress
    # L9 `# a) W! {8 U0 w" X& @+ g7 p
  322.        ADD  DX, 7
    " \* D% k$ J& R/ O
  323. 5 o' K6 g0 {; c' t3 y
  324.        LoopWhileBusy:
    ( [4 @+ Q- ^- w1 J) e/ g% D& A

  325. $ t: Z7 y' m# k
  326.        DEC  EBX
    + I) ], `) M; V5 f3 J
  327.        CMP  EBX, 0
    * C/ t+ w' ^. H8 b0 \* y& m# `# _1 g
  328.        JZ   Timeout
    + N$ Y3 ?. c) s- w& u0 v
  329.        in   AL, DX
    3 z- A8 P* X/ \) X
  330.        TEST AL, btBusy
    4 l% }# i8 ]6 [1 _
  331.        JNZ  LoopWhileBusy
    & C! d  ~1 U9 x4 ~9 Q; I
  332.        JMP  DriveReady/ d! j2 s2 c/ ^2 N( k

  333. " B3 X, C3 @. l: K3 _- z& l6 l
  334.        // 超时,直接退出  @: h$ _" R- R' N4 z
  335.        Timeout:' j+ n4 G) x0 V3 a: A' n+ J
  336.        JMP  LeaveRing0
    5 o; S: z  t3 S& p# C5 u
  337.        DriveReady:
    8 j$ G( C7 h! O$ a
  338.        RET7 Y5 b/ M; n4 z: m# b- y) K
  339.        ENDP   // End of WaitWhileBusy Procedure
    / Z6 ~9 }* {, Z# J
  340. ; j  q* V  Q  p
  341.        // 设置主盘和从盘标志
    ; o2 c0 I! ~' u5 r3 f% P1 ]
  342.        SelectDevice proc& t2 W- X/ U2 o8 L# D9 H
  343. " X; m. [, M6 j: k5 Z
  344.        MOV  DX, dwBaseAddress; n4 g( ~. p7 l* m, R4 c& k
  345.        ADD  DX, 6
    * P+ `1 K& G. W9 t8 m$ ^' [
  346.        MOV  AL, btMasterSlave
    - `  `9 |  d0 T. n1 t: b* U
  347. 1 x6 G3 C) b* D* t2 T: `( J
  348.        out  DX, AL# }5 b  y: p% u; D0 U
  349.        RET
    ; j# e$ B% v- J) V$ Y) ~' f
  350. : Z  N7 |$ ~6 T- e6 w
  351.        ENDP  // End of SelectDevice Procedure/ u% T$ e1 _7 D) F5 N& v/ G

  352. + I3 h- z6 _- k. }3 x
  353.        // 向IDE设备发送存取指令" j3 k; _( [4 A! w2 g) f5 W
  354.        SendCmd proc
    / H4 F( N1 |" c; g. y" _
  355. ( n. W* z2 ]$ f! P
  356.        MOV DX, dwBaseAddress0 v0 _- }. Q% ~  i6 W; y1 P
  357.        ADD DX, 7
    5 S) Z- ]2 e+ C$ M5 @+ a
  358.        MOV AL, BL // BL是主从盘标识,在过程外设置! e. e6 Q& r  _$ s! K1 Z
  359.        out DX, AL0 ?$ L1 W. ^9 S9 ~( \/ r1 L
  360.        RET
    $ S2 ?2 y# e2 s0 Z4 V* v& ~8 ~" \
  361.        ENDP  // End of SendCmd Procedure
    6 V5 k7 c$ Y3 {1 Y4 ^; q4 x% M

  362. , A9 c" q1 P' }- Z  \3 g! ]' w
  363.        // Ring0代码( p- C) L+ \6 w% {) T9 v1 t: l
  364.        Ring0Proc:0 M' h" ^1 l3 C: C+ E
  365.        PUSHAD! R) I3 j! k7 c; q( `- T4 }$ r
  366.        // 查询IDE设备是否存在
    1 f1 K# @. t" a9 K. j% S1 S6 v
  367.        MOV DX, dwBaseAddress0 }! I6 N4 P8 R4 d5 [
  368.        ADD DX, 71 c: r( V" @" x) _( \/ W
  369.        in  AL,DX1 Y! @6 L: ]( G) N

  370. ) w8 N3 F: R- ~/ b! f# V& U* X
  371.        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
    4 ~; J/ [6 U3 v7 I: [( p9 M& H3 L* N
  372.        CMP AL,0xFF) l0 ]( s: |3 D: N4 ~* y" ^# B/ P
  373.        JZ  LeaveRing0
    ( |9 G$ L* A1 ?% o
  374.        CMP AL, 0x7F4 l  f% i$ W* y4 z, L) V
  375.        JZ  LeaveRing0* ?/ U0 R- N5 A

  376. $ q* n6 d2 |$ d
  377.        // 设置IDE设备存在标志! U# |3 l* J4 Y3 V
  378.        MOV btIsIDEExist, 1
    - Q' Q9 M0 g/ Z6 V1 K
  379. ! t/ C6 b$ I; M. L# D
  380.        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)* Y0 i( h, w* O1 j" V
  381.        CALL WaitWhileBusy
    , D; V! T0 G& H, @# Y
  382.        CALL SelectDevice
    & d% r& d9 i  i( }* {% y8 U- K

  383. $ u2 O9 ]$ Q+ |2 d- \' ]& v
  384.        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏" w( ?& N/ n- W2 _, A9 N
  385.        CMP  btIsFirst, 1
    # l7 c7 I( q$ B& x3 x
  386.        JZ   LeaveRing0
    : Z& P* r) d8 ]
  387. * w6 o; I$ d# j3 P5 W
  388.        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???* o9 L  Y+ T2 C4 B9 y+ m
  389.        CALL WaitWhileBusy
    9 ~* F7 Z/ p) d7 ?8 X+ j
  390. 8 E% C$ k5 J# Y1 P+ }/ P
  391.        // AL的值等于cBit06时,不存在驱动器,直接返回8 r# c" ^7 l/ y9 X8 ?
  392.        TEST AL, btBit06
    - N( E! Q+ q* T9 h9 J
  393.        JZ   LeaveRing0
    9 T" @7 b$ q# l' P7 l
  394. 3 Q5 C* S# ~% U" d! K- G
  395.        // 设置驱动器存在标志  V) g% h9 [, g" F/ R$ k$ s
  396.        MOV  btIsDiskExist, 16 @! e/ `+ v$ V' S' z2 z) m

  397. , V/ C" S  r' O5 o
  398.        // 发送存取端口命令) \7 m$ p$ ^% Z* A& C
  399.        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
    * t0 a9 R5 @! s7 S: e! Y
  400.        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
    ; J& Q5 |5 a( B! h$ |3 K
  401.        CALL WaitWhileBusy
    7 Q5 n! [+ _# F! C
  402.        CALL SelectDevice    // 设置主从盘标识
    5 E! h. Z- t  I' H" j. d! @  i6 D
  403.        MOV  BL, btAtaCmd      // 发送读取命令
    % B: z1 s4 w3 K: _1 \/ A
  404.        CALL SendCmd$ Q% E0 I# k  q( H: t. a* m# {
  405.        CALL WaitWhileBusy
    $ x9 I/ q; M3 a" j- s

  406. / P# O* h# [" @
  407.        // 检查是否出错* `/ p/ h7 A% t
  408.        MOV  DX, dwBaseAddress6 R/ `+ {( `5 l$ A, q* ?" @: _
  409.        ADD  DX, 7+ n+ \! Q/ L4 s; X+ C' v

  410. + z5 s8 w( `$ \, m+ P
  411.        in   AL, DX& U! P6 v) O% X2 q9 P
  412. & k* L- Q0 S/ y+ x8 g/ f: h9 P% \
  413.        TEST AL, btBit00
      i6 x6 o/ C2 }, {; `8 q/ r( ]
  414.        JZ   RetrieveInfo   // 没有错误时则读数据
    & }7 @  K5 N4 k! v. Y) T3 \
  415. - I+ S( @# j! w  d. `- K
  416.        // 如果出错,则进一步尝试使用ATAPI设备命令
    - K6 \2 t6 o: ^" l, o# `
  417.        CALL WaitWhileBusy
    8 h+ w/ H- W: }  x; z
  418.        CALL SelectDevice& _' `+ a% t* J
  419.        MOV  BL, btAtapiCmd
    # Y% _0 V$ r2 v& p
  420.        CALL SendCmd
    " h6 Y' y9 E% z8 ?& l
  421.        CALL WaitWhileBusy5 J% N* K! M7 y
  422. " J$ }* K& W9 M8 X; R8 u# b
  423.        // 检查是否还出错; F, O) _# H; ]% C0 p: B1 }
  424.        MOV  DX, dwBaseAddress
    ) f5 m( _4 x9 _8 ]
  425.        ADD  DX, 7" V3 E+ T3 L' }& G+ a5 [' A$ G
  426.        in   AL, DX
    3 T- k1 i; V1 S! _$ p$ J' |
  427.        TEST AL, btBit00" Z! Y) |* n1 j& [( I
  428.        JZ   RetrieveInfo   // 没有错误时则读数据
    % r3 ^8 Q7 [* U7 P
  429.        JMP  LeaveRing0     // 如果还是出错,直接返回
    2 U5 c% i1 e, j2 z4 b. ~/ `: l
  430. ( i( \8 D% a! [/ b5 I
  431.        // 读取数据
    ( F- q! r  y4 m
  432.        RetrieveInfo:" _" y/ h+ R# }. N% ~
  433. 5 M+ z- }% y1 n+ s, A  m$ D, n
  434.        LEA  EDI, wOutDataBuf# z, j$ V/ @$ E8 e! B: v
  435.        MOV  ECX, 256' h: [1 q; h; e; i$ T
  436.        MOV  DX, dwBaseAddress
    6 ~$ r( @  X2 P* Z. G# ?2 H
  437.        CLD
    8 h" V8 U  n( H' s3 g
  438. " V( Y* t; d+ U
  439.        REP  INSW. P' U9 `7 t, o" B

  440. ; l9 {3 _6 d4 q- @, D  {" ]) l
  441.        // 退出Ring0代码
    : L- f! V- S& _3 v# \
  442.        LeaveRing0:' `6 N  N5 t4 g# H
  443. / R$ g" S8 s) T+ o
  444.        POPAD' S' j/ K- i4 L, K7 |
  445.        IRETD* _1 M5 Y+ J& U# O& Q( R+ r

  446. % V4 Y- E$ x, r, y8 p# d/ t" v# t
  447.        // 激活Ring0代码
    " W7 Q7 I" H: f1 {1 F% |
  448.        EnterRing0:4 p: f7 n" [4 Y
  449. % F: D$ G$ |  j: R
  450.        // 修改中断门
    " s1 z7 ^9 t3 v- m0 T
  451.        SIDT FWORD PTR btIDTR10 @! r& p* a: c- [9 j1 t3 {6 q! t7 s
  452.        MOV EAX, DWORD PTR btIDTR1 + 02h$ M% j, [5 |- s( d0 j/ b* o% H
  453.        ADD EAX, nHookExceptionNo * 08h + 04h
    2 y2 U9 G7 C* |- J( L
  454.        CLI
    / B. t- q% m- E9 ]1 \( B4 [7 A

  455. 0 G0 r1 Z5 X. R# l1 }( e' [
  456.        // 保存原异常处理例程入口
    - e. e% o- k; f$ B- k
  457.        MOV ECX, DWORD PTR [EAX]) F2 H, Z! E" Z+ `. w
  458.        MOV CX, WORD PTR [EAX-04h]
    9 h6 Q, U3 j0 e! L
  459.        MOV dwOldExceptionHook, ECX
      V1 A5 e7 p4 K! M" G$ h  s
  460. ! I) w0 w5 m# \; F+ z. P. c  r
  461.        // 指定新入口9 D$ M+ K5 G5 X% ^
  462.        LEA EBX, Ring0Proc
    4 k- K+ |8 {2 \! t0 p6 Q; ^
  463.        MOV WORD PTR [EAX-04h],BX
    ! ?+ R8 H2 Q3 F+ E
  464.        SHR EBX, 10h& ]. D. D  D& [: I
  465.        MOV WORD PTR[EAX+02h], BX
    $ L  r; V9 t' `( R" i4 l. }% }# T( F

  466. , ~( D+ G! ~3 \: g4 V/ a) q
  467.        // 激活Ring0代码) }9 \7 ?" [# Z1 P
  468.        INT nHookExceptionNo! R5 g/ a" _3 U

  469. - n# k& `8 U  b6 a# `+ |8 e
  470.        // 复原入口
    5 k' C. l  [: i" l+ ]7 S
  471.        MOV ECX,dwOldExceptionHook! l9 K# l% U! l6 |& G8 d
  472.        MOV WORD PTR[EAX-04h], CX
    1 G" l2 y5 o3 X' v
  473.        SHR ECX,10h
    3 B; D4 `# n# i
  474.        MOV WORD PTR[EAX+02h], CX
    7 n: C+ v9 O8 l, S% B7 }
  475.        STI2 }5 k2 x  ?3 B8 J" X% g  a! I
  476.    }; }+ [& u. Y% {9 w  f
  477.    if(!bIsFirst)
    " q# \6 u5 z7 G1 x3 m% s( V( M
  478.    {
    " E- d' L+ z0 }) F4 q  w1 d
  479.        bIsIDEExist  = (bool)btIsIDEExist;+ ~! ]# g0 H3 B; t
  480.        bIsDiskExist = (bool)btIsDiskExist;  U3 ?3 D' `7 C* c  U6 z
  481.        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
      \% z7 D3 C& e3 q$ q
  482.    }- [! C) a; J" [; j( e0 B2 \9 M9 Q
  483. }4 u& H8 j( _( e. C# Q
  484. //---------------------------------------------------------------------------
    8 _  d( E& _; c  o* H: y
  485. // 调用方法:
    # q4 k% n* d6 `( ^. ~$ I
  486. void __fastcall TForm1::Button1Click(TObject *Sender)
    , D) ?1 P) l* \1 b4 A+ ]0 H3 P* g, a6 f
  487. {) O4 @- K; n3 G0 |6 Q3 Q
  488.    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);% a7 `6 k' B+ A% a% d
  489. }
复制代码
发表于 2005-8-15 01:00:45 | 显示全部楼层
晕乎乎。。。怎么看8 洞阿
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-10-1 22:01 , Processed in 0.019204 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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