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

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

[复制链接]
发表于 2005-8-11 11:42:04 | 显示全部楼层 |阅读模式
  1. #include <WinIOCtl.h>
    , ?! A2 u3 e9 h
  2. #include <stdio.h>
    7 e; `& B. w3 N& x9 J3 I

  3. 4 ^! N' S, A' @; f7 V& W& s& |7 l
  4. #pragma inline' ~- w7 i5 a- J) e1 L
  5. //---------------------------------------------------------------------------9 {1 ]! d/ u, W6 f& G
  6. // IDE NT/2000/XP专用变量
    0 W/ i- M2 ^$ b( F0 R; t
  7. #define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS3 s! \% W! g" v5 q' i5 R  Q9 B$ Y
  8. #define DFP_GET_VERSION         SMART_GET_VERSION
      l; U# s6 A% J6 M7 c* D% P) i1 f
  9. #define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
    4 q- P! B9 g% n
  10. #define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
    6 Y( J3 v# U7 _

  11. 7 x4 L5 v, z% Q
  12. const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令6 H) _" y9 Z; U
  13. const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令+ r* t' q( ^" O9 \

  14. . o6 c% e$ w7 o/ N  p- z
  15. const int MAX_IDE_DRIVES = 4;9 n4 ^3 I1 F/ O4 \: |

  16. ) M- A' j) ?0 l0 h, z' ]5 n0 D
  17. // SCSI专用变量  B% z( o+ v9 H. U! [+ m7 h' v
  18. const DWORD FILE_DEVICE_SCSI             = 0x0000001B;' D  G& @  m- I# N6 O6 c
  19. const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);1 g# \% N. g; N
  20. const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
    " ?3 t1 Y8 C: H( D
  21. const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;+ T5 e& g  U: Q9 e, K1 c; z+ A
  22. $ V: a+ j# F# m5 ~& Q: W
  23. typedef struct _SRB_IO_CONTROL) }) S4 m9 r4 e& a! E0 F: m% N
  24. {
    / @3 D+ J6 _  w
  25.    ULONG HeaderLength;& `, A1 S' j* D! ]
  26.    UCHAR Signature[8];
    . B# x8 Y) G+ ^
  27.    ULONG Timeout;
    8 X0 p( {  g1 S# l* j, y
  28.    ULONG ControlCode;7 U# s' g9 A  |  j' Y" ?" k) o
  29.    ULONG ReturnCode;0 E6 m* f6 Q7 H
  30.    ULONG Length;# p0 n9 M0 v2 e% P' q( O' E
  31. }SRB_IO_CONTROL, *PSRB_IO_CONTROL;
    - k2 c" x5 P0 y3 R, F1 l

  32.   F; {5 @+ E& b" h1 d, q% ^
  33. // 读取的主函数
    , V' e& s  c; N
  34. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
    - r) x; N5 l5 t( R
  35. " m. T# b& O9 U7 ^" r1 E2 d# ?
  36. // 辅助函数
    $ U* v& ?9 Q; {* |* e: A
  37. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
    # i! R1 n7 D' J
  38. // NT/2000/XP函数- w; R1 S8 p2 Y& p) b
  39. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);% l6 M" N: b0 s: R% Y
  40. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,) m" ]  `" ]1 k5 W' s9 e6 j6 ?
  41.        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
    4 |0 d  o- f1 ?* \
  42.        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
    9 S; {# T4 y& k+ i3 N# w+ B; t
  43. // Windows 9X函数
    ) A" o( m0 k8 }2 G
  44. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);& |- ^6 k' q- \$ t
  45. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
    8 C- ~9 t" J9 x% q3 k
  46.        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);& R! ]% i1 h" A" I, f% A4 b& @2 p
  47. 2 |8 L% p! |" N
  48. // SCSI读取函数(for NT/2000/XP)
    " t1 w2 H- [" T5 n! X$ o
  49. String __fastcall ReadIDEDriveAsScsiDriveOnNT();
    5 o9 }9 E+ x, w0 r( _9 w6 B! n
  50. //---------------------------------------------------------------------------- E- N2 w  M" j: I, P; e
  51. // ReadPhysicalDrive1 y2 w/ c, V# B5 w
  52. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)0 q# Y* J( h6 V" H
  53. {
    ) `0 ]2 J; G# C, \+ _; f5 v
  54.    switch(Win32Platform)& N. Y! i4 E. M1 Q
  55.    {
    ( {; {6 g5 {+ t% r9 i) K+ f
  56.        case VER_PLATFORM_WIN32_WINDOWS:
    6 ?. ?# b5 z& {9 A
  57.            ReadPhysicalDriveOnW9X(pSerList, pModeList);8 R: ]: X* G. Q0 A3 G  H" y$ s
  58.            break;
    9 y2 a+ s6 l. o7 B( [
  59.        case VER_PLATFORM_WIN32_NT:6 y, S: g" ~6 d# m
  60.            ReadPhysicalDriveOnNT(pSerList, pModeList);3 o; q) q! e, t7 A' L. s; `6 C
  61.            break;, u: e7 z9 \. ]: n  Z9 y4 H
  62.        default:
    * T8 l8 b0 A$ d- f
  63.            break;8 k9 r# _2 C' R: ?! S  k2 E
  64.    }- G; D! s. D9 Q+ ~
  65. }5 D' y* `- F  ]: e/ b8 O5 }
  66. //---------------------------------------------------------------------------- _- h  R2 @4 i" I$ z$ p9 k
  67. // ConvertToString
    ! A. C8 ]4 l% V- K+ @9 G
  68. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
    ) c) k9 u& z* m. ~* K* J
  69. {+ E2 W; G+ v9 V5 s5 M& P( l
  70.    static char szResBuf[1024];
    # E5 w( p9 K; u; k# B+ j- }5 T
  71.    int nIndex = 0;
    % x) [7 `2 C  y2 t
  72.    int nPosition = 0;
    ' X2 B5 }  R; c2 h( g' N
  73. 0 ^7 _" L, I/ N0 e
  74.    // Each integer has two characters stored in it backwards
    * L3 x3 L! i2 e7 X# C
  75.    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
    ' v$ M8 q) z9 U! B
  76.    {- z) u7 O$ K) V+ h" H9 e' z
  77.        // Get high BYTE for 1st character
    2 N, x9 j2 J7 d* D; i/ G3 Y3 f
  78.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
    5 A$ {; I/ ]3 ?& g
  79.        nPosition++;( O. K3 P1 Z8 \/ V

  80. ' k; W8 i+ v/ D8 [
  81.        // Get low BYTE for 2nd character3 p7 v" v8 p' A5 t
  82.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);2 W% d( B: M5 g
  83.        nPosition++;4 u" I" Z0 H9 p, s8 g- @& c! M
  84.    }/ X9 u) p* Q, Y
  85. % p* \4 B, Y7 n) I$ n% i
  86.    // End the string
    * i! o( _8 o! Q1 i8 c' ?
  87.    szResBuf[nPosition] = '\0';
    1 E; X8 }& E& J1 f7 D& `+ W
  88. 3 L$ z2 e& K* \* z; G! T2 {: T
  89.    // Cut off the trailing blanks3 b- O) b4 \! T! }
  90.    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
    . ^% W8 ^6 D: N; I4 y
  91.        szResBuf[nIndex] = '\0';
    + {: g! v$ w2 M+ P
  92. $ c" A3 T  ?! X$ s3 y$ x7 P
  93.    return szResBuf;
    . D1 I' G1 y9 @/ \  \$ c4 X
  94. }; P  O8 ?  G/ o% }9 {9 t
  95. //---------------------------------------------------------------------------
    % y* [9 m7 X. ~# l" z
  96. // Winndows NT4/2000/XP 代码
    ! d, ~9 k& X4 N* s2 V/ ]& R
  97. //---------------------------------------------------------------------------
    + {. H( \+ d& T( u* G  A  ]" x7 C
  98. // ReadPhysicalDriveOnNT" n& O, L0 n8 S5 b
  99. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)5 i" a5 _) K2 R; J/ c, M( d
  100. {
    7 K; d0 u7 `8 J4 W+ V
  101.    // 输出参数' E& Z, m2 O5 r2 H2 w2 w
  102.    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
    . L# d# A# g( J3 D/ g0 [

  103.   M" _/ y: x: w7 w5 P! `
  104.    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)6 d9 t7 s! W( F3 O* \
  105.    {
    ) y! g' j/ G+ d$ q' n! e
  106.        HANDLE hPhysicalDriveIOCTL;4 b4 J, s0 j* Y$ b
  107.        char szDriveName[32];) h/ C7 k1 P) }9 j- [) T( g
  108. ; H- G3 Q# w$ I5 M4 ^
  109.        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
    $ s7 O) I5 h4 I
  110.        hPhysicalDriveIOCTL = CreateFile(szDriveName,% P$ u6 A7 n6 p5 u1 O
  111.                        GENERIC_READ | GENERIC_WRITE,
    1 T6 ?$ N7 Q+ c: z2 n- {' Q3 u6 \& U% @
  112.                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,: N# Z! ^1 D* a3 V* r" a- f% w
  113.                        OPEN_EXISTING, 0, NULL);% V, A# N; c9 ^5 n

  114. % o0 I) F; j8 o0 M& m
  115.        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)4 N, ^/ c9 g" n4 ]2 I
  116.        {4 S$ `! a6 `; [+ N/ _
  117.            DWORD dwBytesReturned = 0;- X4 ]: `5 P0 N7 q
  118.            GETVERSIONOUTPARAMS gvopVersionParams;9 v1 E1 \. b% i  C5 G# H$ F* ^
  119. , ]$ s# z: i# R( M& \
  120.            // Get the version, etc of PhysicalDrive IOCTL
    ! [5 x( R) F- P
  121.            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));! E6 T8 p- `. a' r$ Q

  122. ) N8 b) B+ F: ?" U
  123.            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
    3 v5 o3 T+ X: Z
  124.                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
    ' M$ A- [6 ~# w! v: {& }7 [
  125.                    &dwBytesReturned, NULL))+ R" {; [# c/ q
  126.            {, A6 h/ n' o4 E$ l# ~( F" m
  127.                continue;
    1 M+ X5 g' J- x) g
  128.            }5 y! x* Y* i/ e
  129. " y& P+ r* T7 u; `" w8 ~! k
  130.            if(gvopVersionParams.bIDEDeviceMap > 0)
    3 y/ g! z( K  {! _' a1 s, P6 G' c
  131.            {
    2 ?6 M* x  \: V4 X% P7 D6 A; u
  132.                // IDE or ATAPI IDENTIFY cmd
    - J5 x7 M& {" ~; c' g1 E" y
  133.                BYTE btIDCmd = 0;
    4 W  q1 A% o- e% m$ m! w
  134.                SENDCMDINPARAMS InParams;' p& K9 W6 I, P8 [2 D5 X# d$ @1 J
  135.                // Now, get the ID sector for all IDE devices in the system.
    ' n: k: o, b; q' U, @% R; i' c- E
  136.                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
    9 y, _4 u+ L; V, p
  137.                // otherwise use the IDE_ATA_IDENTIFY command  ?4 }. I. Z" R5 s) m. v6 _9 I
  138.                // 具体所得结果请参考头文件中的说明
    7 C# G2 x7 V; @
  139.                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?& L" V! w7 C: A
  140.                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;" J7 y% U; M7 L; v, v
  141.                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
    % p1 {6 ?  j6 p! H3 b! Z
  142.                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));, O2 s* M: U3 a1 O

  143. ( |* j, N, R1 S
  144.                if(DoIdentify(hPhysicalDriveIOCTL,( C2 q1 e5 G6 J) k! ~
  145.                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
    6 [/ s% `" f8 x8 i
  146.                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
    . r4 g7 d! u9 Q/ |; ?
  147.                {
    * H2 F( }2 E( w
  148.                    DWORD dwDiskData[256];4 P+ f* o6 e% K' W" A7 W6 g
  149.                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件# l# B  A. t2 ~- A
  150.                    char szSerialNumber[21];  E8 P/ W- _6 S9 a& g
  151.                    char szModelNumber[41];
    - l' H! I' d$ n' Y8 z8 H2 L+ t; ~
  152. 9 c4 R' _1 d  Y1 m
  153.                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;5 r. Z  H. T# J& P  d1 P
  154.                    for(int i=0; i < 256; i++)& @2 S( g& p1 y$ @8 T2 O0 P
  155.                        dwDiskData = pIDSector;
    * e+ r- K5 P! q6 g0 t+ X
  156.                    // 取系列号
    : Z' I& o  P) J2 T
  157.                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
    7 t: J8 v$ j9 n$ h& G* h
  158.                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
    7 [; f+ @; H1 W& N0 r! @" w7 b

  159. + `; p- N5 H* N" ~5 J* h' [, Z
  160.                    // 取模型号
    # s( h& H, i8 q" m. Y  B2 F7 Q- B
  161.                    ZeroMemory(szModelNumber, sizeof(szModelNumber));
    , ^9 w: U7 r! F, D+ N- t8 |
  162.                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
    & i, d4 V/ D: l) E5 Q6 |# d

  163. + B; B: p. L$ Q  A% n
  164.                    pSerList->Add(szSerialNumber);/ h5 }( Z5 s. M
  165.                    pModeList->Add(szModelNumber);
    0 j1 U5 n  I& ^* ^. u+ ?
  166.                }
    : `1 N1 e& J: V: P* Z% k; z; q( M
  167.            }* {8 z) e3 S$ d* k- c
  168.            CloseHandle (hPhysicalDriveIOCTL);
    6 i/ M2 ~8 ^9 V2 t$ {0 @
  169.        }  a; R4 q( Q; V/ M$ T( z3 x0 @; |0 p
  170.    }
    4 x  v1 K! D  b8 `
  171. }5 Q( o! C9 ^9 ?- S$ b/ H3 O/ m
  172. //---------------------------------------------------------------------------! \' _4 b8 D! X+ E, U5 r1 @/ ^  [
  173. // DoIdentify2 B  V6 N! z1 K3 U7 y. ?. z
  174. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,, i  Q' w9 C1 a! V+ [2 m
  175.              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,+ u9 ~2 ]: C/ T
  176.              PDWORD pdwBytesReturned)  x* v* _% I& h2 _( d' L1 C+ E6 ]# _
  177. {
    , K: ~- y# h1 n7 O0 b* ?9 @
  178.    // Set up data structures for IDENTIFY command.6 r3 v7 \! ^% ]4 n
  179.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
    8 q  \- E( i% \0 d$ Z% T  p$ v; J
  180.    pSCIP->irDriveRegs.bFeaturesReg = 0;/ ~% f, v0 L8 l: R" F
  181.    pSCIP->irDriveRegs.bSectorCountReg  = 1;
    7 E3 _# h# ^& x
  182.    pSCIP->irDriveRegs.bSectorNumberReg = 1;5 Z% Q( m- F; n2 B5 n6 C
  183.    pSCIP->irDriveRegs.bCylLowReg  = 0;
    & S' _/ L# W" ~
  184.    pSCIP->irDriveRegs.bCylHighReg = 0;; F/ C$ N; r# u! ?0 D( u

  185.   R# r& r6 A3 A' B
  186.    // Compute the drive number.(主盘和从盘所对应的值是不一样的)
    " x7 Z% Q2 o, r7 x
  187.    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;+ l) |+ X  {4 b* e9 \2 W) p, z
  188. ! p, ]' Y6 B2 Z
  189.    // The command can either be IDE identify or ATAPI identify.
    - n+ _2 |# B5 ^
  190.    pSCIP->irDriveRegs.bCommandReg = btIDCmd;+ A7 e  b6 {% e* e. Z2 M
  191.    pSCIP->bDriveNumber = btDriveNum;8 D# r, c1 Z% C4 R
  192.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
    + b3 e! M& o7 Z' D: e" h9 T* s

  193. & p: z# g) E. P' |3 a4 o$ L4 M- R; m5 ]
  194.    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
    ! |' n5 Q) s! A0 x; i" \
  195.           (LPVOID)pSCIP," _- O5 ~. g) {, W
  196.           sizeof(SENDCMDINPARAMS) - 1,# a7 I3 W- D/ @
  197.           (LPVOID)pSCOP,8 g. C9 {' M, ?, S3 `
  198.           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
    6 _7 a7 Z3 y5 G9 O" k
  199.           pdwBytesReturned, NULL);
    ) K* B/ U) C+ d( N
  200. }1 c6 T7 R! W# X- m2 f. j
  201. //---------------------------------------------------------------------------8 ?: N" Y! a0 u% R9 \
  202. // Windows 95/98/ME 代码
    - b7 {, k# m* u+ j7 _  a
  203. //---------------------------------------------------------------------------
    % }+ `/ M5 o' b; t( _; d0 x5 z
  204. // ReadPhysicalDriveOnW9X% o, E" P5 g+ }
  205. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)* U( R1 L) M! M" H; w. @  P
  206. {8 G4 H& t& R6 c) [* C
  207.    WORD wOutData[256];( d7 z8 v# y# s/ O8 f
  208.    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);9 O) |: V+ H: ]& t8 n' n
  209. + u" R% f3 N5 v: ^, b* a
  210.    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。$ _  h: ?) }+ N8 P+ C
  211.    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以2 G; g, l: B0 W+ j# @
  212.    // 避免蓝屏的出现。(期待高人能指出原因)' ^# \6 h8 |8 ?- b
  213.    for(int nDrive = 0; nDrive < 8; nDrive++)$ y9 `3 x5 T- B& p" U4 q
  214.    {
      y0 J6 Z; N6 ]. _+ }' k+ \, X. {
  215.        WORD dwBaseAddress;
    ; D  s, ~4 C5 o; r/ O7 `1 M' Q
  216.        BYTE btMasterSlave;         // Master Or Slave
    ) g( v' O  e) q. \3 ?9 G- w
  217.        bool bIsIDEExist;
    . U1 @: K$ e0 N
  218.        bool IsDiskExist;7 J/ Z. b$ R+ x* J
  219. 9 Z& V8 n( p3 o* ~4 o
  220.        switch(nDrive / 2)- z4 P' N0 t, i3 F
  221.        {
    $ K- C- Q% J! E+ y$ h- _
  222.            case 0: dwBaseAddress = 0x01F0; break;' E% j1 ?( H) Y$ y
  223.            case 1: dwBaseAddress = 0x0170; break;; _" R9 I% ?6 F+ i+ S- K
  224.            case 2: dwBaseAddress = 0x01E8; break;
    ; _. @, U$ F) q- S) h- s" D& E
  225.            case 3: dwBaseAddress = 0x0168; break;# U, W7 }2 O/ w! T
  226.        }
    : Q" E  T6 D% v  A2 v4 C5 C* [
  227. - p6 y2 Z+ J4 ]- h
  228.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
    ( l: m6 |' `- s8 G3 o
  229. 2 `3 h& v' a" J" ~" r/ |# k
  230.        // 进入Ring0
    3 S2 t: F2 a  F! r
  231.        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
    , z1 [4 c+ }. s2 n: J! R% B
  232.                bIsIDEExist, IsDiskExist, wOutData);
    " D+ S/ ~. W% ?
  233.    }
    7 W; S. E3 E$ K4 S; q$ S3 V

  234. / S& u  W- e+ `
  235.    // 开始读取6 l9 U, q9 g1 a6 R$ x  w
  236.    for(int nDrive = 0; nDrive < 8; nDrive++)
    ) A" X  J( t6 |
  237.    {
    7 d. n, [' w9 x
  238.        WORD dwBaseAddress;
    & o% E3 {* M  k3 y  W3 O' d/ j
  239.        BYTE btMasterSlave;         // Master Or Slave5 z: m; G6 L! w2 A) l$ G6 T
  240.        bool bIsIDEExist;# S1 W* b: R. ?0 i
  241.        bool bIsDiskExist;
    3 c' P/ \* A6 ~! o( r6 {4 ^
  242.        switch(nDrive / 2)
    1 f0 K* \6 m# J5 |& ?0 }
  243.        {1 m; {* Y7 ~6 o8 r3 X2 x9 s
  244.            case 0: dwBaseAddress = 0x01F0; break;
    7 P, D0 I: b( U) B; ?
  245.            case 1: dwBaseAddress = 0x0170; break;
    % V4 r! L- @' S/ a  C
  246.            case 2: dwBaseAddress = 0x01E8; break;" M. b( r0 n- @: t: ?3 B
  247.            case 3: dwBaseAddress = 0x0168; break;. b1 H) ]" ?# V% n' l
  248.        }
    3 }9 o+ l; S* a/ T$ F/ Q+ Q

  249. 5 ~" Y9 |: Q$ K
  250.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);5 e& o0 m* o4 m- N8 I* }
  251. ! M) E7 P* D$ J+ e
  252.        // 进入Ring0
    4 P9 W+ i5 U5 @0 H% |7 @
  253.        bIsIDEExist  = false;
    , ~  L, Y4 N' E1 e5 t
  254.        bIsDiskExist = false;" k1 x& B, M" I0 t& m! v3 C7 l0 `
  255.        ZeroMemory(wOutData, sizeof(wOutData));! B& Y+ b5 C8 v4 r
  256. ( u/ T0 b0 Z/ U! s% n. I1 A
  257.        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
    2 P* v& @! @& ]' u
  258.                bIsIDEExist, bIsDiskExist, wOutData);
    6 P1 O* f& P- k7 E  H
  259. 2 u2 U0 D/ O* O+ `
  260.        if(bIsIDEExist && bIsDiskExist)  I3 `0 F. Z& _$ i5 q
  261.        {. W% J! b. @! H4 j1 c. E
  262.            DWORD dwDiskData[256];
    " M2 _  U5 V+ m
  263.            char  szSerialNumber[21];
    4 I% w6 O$ ~. ~
  264.            char  szModelNumber[41];1 ]: \4 W" R5 `7 w4 r
  265. 1 G$ b: _) M3 Q4 c% E' N9 n
  266.            for(int k=0; k < 256; k++), `# k* @& Z4 [# ?
  267.                dwDiskData[k] = wOutData[k];
    ( Y& ]" v1 s( N
  268. 9 B4 q* f- V4 O
  269.            // 取系列号: {1 L9 @0 @! Z( w
  270.            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));7 a/ Q- q8 H" O$ [7 }+ [5 _: T
  271.            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));# l: S9 j8 ?& ]; r) O$ u" l. r6 Y1 r

  272. : _; J. b% S0 t& ^. O
  273.            // 取模型号
    , H) q% S2 c/ \! N: O6 y4 U
  274.            ZeroMemory(szModelNumber, sizeof(szModelNumber));
    " G2 h$ W% ~1 G- O
  275.            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
    ) ?+ L1 h) @3 P: ]. Z

  276. ' V. @, y2 Y; }5 c9 D4 Z6 G1 s
  277.            pSerList->Add(szSerialNumber);$ d. }# |+ [: U4 {; A! o: [+ u
  278.            pModeList->Add(szModelNumber);
    3 F& |6 w$ B; |# Y' t4 l
  279.        }3 _/ ?' q; F3 u' r) }
  280.    }
    ! F* ]/ V) Y0 d  Y/ h2 ?
  281.    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
    " A4 V. l$ g+ T4 T
  282. }3 k9 f: B6 L: L. V2 r+ ^: s
  283. //---------------------------------------------------------------------------# i2 p9 g: V) S3 o
  284. // ReadPhysicalDriveOnW9X_Ring0()
    9 U2 w8 Q( u3 R
  285. //7 K: K, m7 @+ k. q
  286. // dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h: e) o8 d) o; \& ]" D. K
  287. // btMasterSlave = Master(0xA0) Or Slave(0xB0)  m& T9 v( [( ~/ q2 E
  288. //---------------------------------------------------------------------------; U; ~/ X! ]! m! [# f# K1 k0 C( p
  289. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,( k* V" D9 ^+ K  \( u
  290.        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
    / }# j$ D% ]9 K  r9 g- Z8 q
  291. {% o1 o. a, [7 ~- D+ l/ g$ f( k
  292.    BYTE  btIDTR1[6];9 A# _- s# q" _7 D+ d8 @# @
  293.    DWORD dwOldExceptionHook;' S, \' {9 z' a: [# a
  294.    const int nHookExceptionNo = 5;( j2 ]- f# z8 A/ o$ }2 ^

  295. ! r! A8 ?* t" T) w7 ~& v, z
  296.    BYTE  btIsIDEExist = 0;
    1 p. S+ h& ~. G/ X) S8 S, l% M
  297.    BYTE  btIsDiskExist = 0;
    + c9 c6 h8 k, y! j/ M# [
  298.    WORD  wOutDataBuf[256];
    % d. X: j: ^' a* @& f1 Z5 Q
  299. ! y' a2 M/ W8 y' L. n" f8 R8 @: p
  300.    BYTE  btIsFirst = (BYTE)bIsFirst;
    / y" ~; D+ Z: R2 `* e$ Y+ `

  301. " o5 C. v  G9 ^. Q% F2 k* Y, K
  302.    const BYTE btBit00 = 0x01;
    $ M+ X; `( w& r4 s0 f1 I# N% C0 Q- o
  303.    // const BYTE btBit02 = 0x04;. q9 P7 }$ D2 z# H/ r0 G- p& L
  304.    const BYTE btBit06 = 0x40;
    + O  h' P) x7 T8 g2 w6 M
  305.    const BYTE btBit07 = 0x80;
    ; w- {3 s* [' L' c* j* e
  306.    // const BYTE btERR  = btBit00;% u3 k0 c% \2 V+ v
  307.    const BYTE btBusy = btBit07;' b) [+ ?. `! @# f
  308.    const BYTE btAtaCmd   = 0xEC;1 E. z/ n. Z1 H: K- f2 {
  309.    const BYTE btAtapiCmd = 0xA1;
    8 w* w" [9 X* z/ b: g- m% n

  310. # h1 q; h/ V  C  ]/ }& k- Q" c8 W
  311.    __asm
    0 I* h. J' J1 l/ p9 o
  312.    {1 V2 T8 s9 q! X3 h& {
  313.        // 必须先执行这条语句
    9 D" g9 Q/ z: j5 @& s; S; q8 m
  314.        JMP EnterRing0( f% e% J9 s* a9 O1 K: ~: f

  315. 3 R* a& K+ }9 H: V
  316.        // 定义过程  Z5 B2 q  n" K3 [3 D1 _
  317.        // 等待IDE设备直到其不为忙为止
    3 F" Q3 [  H7 z4 u1 r
  318.        WaitWhileBusy proc
    # {  }5 W& E. q5 g/ @

  319. & p4 \; Z& H4 W) J
  320.        MOV  EBX, 100000
    + r1 ]% r4 n" ]2 N3 x
  321.        MOV  DX, dwBaseAddress+ q' A% R6 s/ t  M" ^5 o. e9 h" @
  322.        ADD  DX, 7
    " k, L: b3 m$ c0 R( p7 t

  323. 0 P, X, n  S) H6 z0 x- m- Z
  324.        LoopWhileBusy:
    3 d+ @9 [- W% n( ~
  325. ! u6 ^3 A& O, N+ F, n  ^7 G
  326.        DEC  EBX
    4 Y3 |0 I1 Q8 \) `
  327.        CMP  EBX, 01 c! a7 E) M$ y' }2 Z3 C1 _
  328.        JZ   Timeout* A! Q' [+ h$ @0 [. N7 m
  329.        in   AL, DX+ A: {. g- g4 r7 e. r/ l, ?. J
  330.        TEST AL, btBusy. J3 F, X: B- b* ]" ^0 e0 p
  331.        JNZ  LoopWhileBusy5 z/ d4 E( S# W. u* _# j- E& n
  332.        JMP  DriveReady
    . W  Z2 @2 O9 K* D0 C5 m( @4 D

  333.   Y- y' P! |# _9 c6 h
  334.        // 超时,直接退出
    $ J$ E& Y* ]# M$ |, _) X5 ^  i
  335.        Timeout:" _# s$ U, k5 n& S* f
  336.        JMP  LeaveRing0
    0 U/ X! Y) t6 q1 b# A. }
  337.        DriveReady:. O: Y5 M+ z$ }% V7 u4 ?
  338.        RET
    : {# U  L0 A" l  _7 ?, h* f5 b
  339.        ENDP   // End of WaitWhileBusy Procedure9 L' D, D& s/ a3 R

  340.   T/ L/ c  |' |
  341.        // 设置主盘和从盘标志
    2 `! Z( B0 [% i) Y; Q
  342.        SelectDevice proc
    $ x2 G% n; d# q5 v9 N7 a; g

  343. # h/ u1 S7 ^( O2 F  X& |
  344.        MOV  DX, dwBaseAddress7 a$ E% S8 E. f8 c6 i& ^$ L6 J" T
  345.        ADD  DX, 6
    + Y# u& @1 k2 ^) o
  346.        MOV  AL, btMasterSlave( x4 W  p5 ?$ q7 S
  347. $ H* L" k/ g7 p
  348.        out  DX, AL
    2 }* i& ^/ A% C# d8 g2 k
  349.        RET
    ' l3 X8 i* z6 w# h
  350. / A5 j! Y" j5 a% n7 v, J0 x
  351.        ENDP  // End of SelectDevice Procedure0 ^6 i/ ?& ^8 [- r3 e; k, m

  352. 1 o! }: O, J( v
  353.        // 向IDE设备发送存取指令9 N) p" d, N1 q! h+ f1 x4 ~- \
  354.        SendCmd proc9 [2 e5 ~- \. X, ]  k4 @% \* H+ v- K
  355. . ~& K3 q# |  G
  356.        MOV DX, dwBaseAddress
    . C2 c/ S6 p1 f+ t' [7 m
  357.        ADD DX, 7
    4 ~3 }/ X: f  b5 R8 b8 m
  358.        MOV AL, BL // BL是主从盘标识,在过程外设置
    + [' `; D' v* |# O
  359.        out DX, AL
    5 Z) h, v5 [  m+ o& a
  360.        RET; y" j7 d9 f: e5 B. [
  361.        ENDP  // End of SendCmd Procedure
    " k" ?; u6 O: y. `5 M! P

  362. & s" l0 R2 y- r& }9 t
  363.        // Ring0代码
    1 t9 n  u' b) |3 T+ X
  364.        Ring0Proc:6 f3 ]! }0 i/ _4 l5 q7 u9 M" s
  365.        PUSHAD
    $ F% _) B: U3 D. O
  366.        // 查询IDE设备是否存在9 t) a: j, w$ v* s( q: W8 v. p
  367.        MOV DX, dwBaseAddress
    # s% O  w0 P5 P* o6 ~+ v5 h
  368.        ADD DX, 78 B7 t) C1 k% E$ S
  369.        in  AL,DX8 |% x) n$ Q0 k. m& j/ }2 v" t

  370. . e# J) ]& d5 P
  371.        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
    . w: m( x) O9 n2 I$ P2 S+ w
  372.        CMP AL,0xFF
    % I0 |) r3 I8 ?3 @* n$ D5 z: p
  373.        JZ  LeaveRing0
    - |* b0 p; b3 M; R0 p1 k
  374.        CMP AL, 0x7F/ H! W/ c7 H1 Z% R0 h6 V
  375.        JZ  LeaveRing0+ u' W/ `: L* y; @* ]8 y2 s

  376. " j+ ]/ ?" K! x
  377.        // 设置IDE设备存在标志
    ) |: J" }4 b4 K+ d$ b/ K& q
  378.        MOV btIsIDEExist, 1
    5 u; c# B3 ^0 \- A
  379. 1 j( E) _) p; f
  380.        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)( e, n! K; I$ T) ?/ }' J
  381.        CALL WaitWhileBusy* r8 d- m( f3 @  S- X2 ~
  382.        CALL SelectDevice7 |0 |7 c9 g& i4 X' L! S
  383. 9 F- o& E0 M$ k1 P. q$ `* n+ V* M% t: ?
  384.        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏) _5 {4 x9 w% T) ?! g5 n  Z
  385.        CMP  btIsFirst, 1
    ; X' P1 e( A) {
  386.        JZ   LeaveRing0
    ' u5 z; Z1 U! k( P& c7 n2 I& x

  387. . z1 ~3 c% H  z
  388.        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???5 y4 e  S8 \# R5 Y( g' X5 ?  z
  389.        CALL WaitWhileBusy$ R. w$ O5 \, e3 m5 d8 ^

  390. & ~) p) B4 a5 w) X/ n# N1 k
  391.        // AL的值等于cBit06时,不存在驱动器,直接返回% y* S6 ~8 O; X5 p+ Y2 N( U
  392.        TEST AL, btBit06
      s' s5 I5 _! x7 W/ r6 q
  393.        JZ   LeaveRing0
    , f% y" J4 k4 [/ w' a! u

  394. 4 I% K/ e3 x: M& i$ m8 s
  395.        // 设置驱动器存在标志' B' b8 N7 S  U: b5 Y; K. ^
  396.        MOV  btIsDiskExist, 1, L/ R/ C& ]% n0 N+ W2 ~* ~8 h

  397. $ e  S1 W* E; T; A
  398.        // 发送存取端口命令
    % M: \+ n. c  J# c( S
  399.        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
    ; Z8 I6 z; U4 D0 W8 @
  400.        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
    ( o: t0 n- s; {( i9 j: a9 f
  401.        CALL WaitWhileBusy
    / Z+ r% r6 u: c- S
  402.        CALL SelectDevice    // 设置主从盘标识
    4 B& s4 _& l- s! Z6 s  r
  403.        MOV  BL, btAtaCmd      // 发送读取命令
    $ s+ x& d2 S: o
  404.        CALL SendCmd. q3 \' U5 @8 k$ l- F1 ^1 N$ n
  405.        CALL WaitWhileBusy% C2 ~; F1 q4 Y
  406.   r% P  k& j$ j) r0 W5 s( x
  407.        // 检查是否出错5 k2 z  o* g: q! H% e7 I
  408.        MOV  DX, dwBaseAddress
    & N$ a7 m3 L7 m" U$ c
  409.        ADD  DX, 7
    ) E% _- d! d# Z; r4 L6 k6 M

  410. 0 F2 N9 W' B7 w
  411.        in   AL, DX
    5 {' c# @7 U$ k
  412. # [" I; F8 Z1 |, g( }
  413.        TEST AL, btBit00( h) O2 ~% a3 B9 i  C
  414.        JZ   RetrieveInfo   // 没有错误时则读数据
    8 n- O* x, `% s( r4 U

  415. 7 j9 F$ R% n. j  z' l$ k: o. T
  416.        // 如果出错,则进一步尝试使用ATAPI设备命令. f" ^+ c* {7 u+ p; l( t
  417.        CALL WaitWhileBusy5 X4 Z' r# [: z2 g2 N: u
  418.        CALL SelectDevice# o- |$ S# h- \. `
  419.        MOV  BL, btAtapiCmd
    : ~9 f3 R; r9 o6 H8 F
  420.        CALL SendCmd, F# L! s5 q# n5 w8 u4 r; K
  421.        CALL WaitWhileBusy% Y0 T! {$ w; }* O9 e! Z
  422. ! p2 c# D# ~. T, m/ E
  423.        // 检查是否还出错3 O8 P) \; M" }2 @0 u( @2 v3 d
  424.        MOV  DX, dwBaseAddress
    ) \2 n$ d/ y4 j, `5 V
  425.        ADD  DX, 7
    * S+ K' V! t# Z3 i1 |/ x% G1 c2 l
  426.        in   AL, DX
    2 d3 e/ u3 W8 `7 B. ]
  427.        TEST AL, btBit007 @. H) j* L9 l6 ^3 ^4 @
  428.        JZ   RetrieveInfo   // 没有错误时则读数据
    4 m% K6 p4 g$ U
  429.        JMP  LeaveRing0     // 如果还是出错,直接返回/ b9 Y; Q. u+ \1 L

  430. * ~$ L+ P/ C! P# c5 L$ e
  431.        // 读取数据
    + I1 ^% F! {: D9 y' T/ T
  432.        RetrieveInfo:
    8 r8 T" }, f) E, G- N& s, ]

  433. # ?$ p6 p6 V4 L) W6 v
  434.        LEA  EDI, wOutDataBuf9 c' n4 l3 t- a
  435.        MOV  ECX, 256# h' j2 o' E: K$ ?; |; l* ?: R: r
  436.        MOV  DX, dwBaseAddress! R. h4 ^8 c  E& Y
  437.        CLD7 H7 ]; L( a# y
  438. ' ?9 T; h" `( X. Z: y' q
  439.        REP  INSW# f5 t4 [! ?6 Y% W% A- B
  440. $ a9 M& g+ k( h$ q# C) f( N$ j! J
  441.        // 退出Ring0代码) X  @3 p- U! X
  442.        LeaveRing0:
    ! P1 `' ]- H: R

  443. ! z( y- y0 X+ E; a  B) R& s
  444.        POPAD2 U8 b: h$ z( O" p( S: z$ s
  445.        IRETD
    & X8 [! y- S4 D1 g

  446. ; `3 A% B# m- e( }/ ?; q
  447.        // 激活Ring0代码( {; r/ c6 l8 M5 m* Q) E
  448.        EnterRing0:2 S( t( ?. O; Z/ L0 D, R" c
  449. ) [. D; Y& j$ M" }: t+ \5 z
  450.        // 修改中断门  J7 z' X+ X% B9 f
  451.        SIDT FWORD PTR btIDTR1" o9 S& X( i; w& Q  |- [  Q
  452.        MOV EAX, DWORD PTR btIDTR1 + 02h; s, z2 {. R0 b# G
  453.        ADD EAX, nHookExceptionNo * 08h + 04h
    1 a/ T0 h3 i- g: ?( I
  454.        CLI* h3 ~9 A/ @" u
  455.   [  y0 G- p$ C( j+ v. w# L
  456.        // 保存原异常处理例程入口% q3 \* H5 s  W3 h" h
  457.        MOV ECX, DWORD PTR [EAX]
    7 v8 I: O  f, f! n' x& a7 T
  458.        MOV CX, WORD PTR [EAX-04h]5 `+ L/ c# p2 m: u8 i% v' I
  459.        MOV dwOldExceptionHook, ECX$ G. U  x/ E3 b" h* r8 c

  460. : v2 o: E8 [$ t) g( d% l$ L
  461.        // 指定新入口% |2 G1 M) T* |& D4 X: [# b8 d# P* K6 R8 B
  462.        LEA EBX, Ring0Proc' W2 j& D7 m8 T5 q3 N
  463.        MOV WORD PTR [EAX-04h],BX# ]5 m6 z" J' {. {, x" q
  464.        SHR EBX, 10h5 O0 o+ G( a4 O4 M# y
  465.        MOV WORD PTR[EAX+02h], BX8 o0 B: d6 l0 ~9 j- W5 L/ s, b
  466. 5 c# K" U( Q: T0 o& [
  467.        // 激活Ring0代码
    ! e' i4 f6 L2 b# n  y5 U5 m
  468.        INT nHookExceptionNo
    0 B, m5 {2 l9 u% H
  469. ( C" B$ o4 C* ]3 ]9 c
  470.        // 复原入口4 y( |- V" T' }, k  Z. m
  471.        MOV ECX,dwOldExceptionHook, i; W+ g& o& I9 c, r
  472.        MOV WORD PTR[EAX-04h], CX
    / p- f$ m6 w1 Y
  473.        SHR ECX,10h
    * N4 C+ F* V. \: t3 @: |( j
  474.        MOV WORD PTR[EAX+02h], CX  N( u* |: O, ]! ?! g
  475.        STI
      n# l$ I0 E- g
  476.    }
    5 R& n# z& b' J4 |
  477.    if(!bIsFirst)9 i6 s4 y" j- c# {3 A6 `5 _
  478.    {
      T5 C! b) q8 i! f
  479.        bIsIDEExist  = (bool)btIsIDEExist;
    + k, s' w2 a" U/ [4 W
  480.        bIsDiskExist = (bool)btIsDiskExist;. U1 K' g$ H7 K9 S2 k2 v  T
  481.        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));$ }  s: G/ P5 i* ?* n! r
  482.    }
    8 a5 z( e6 {! z- N# H+ X7 {
  483. }
    , a' A9 m9 w* ?7 }% T% ~
  484. //---------------------------------------------------------------------------  \5 I; Q" a4 R( s
  485. // 调用方法:
    ! z: v+ j: d/ U6 R1 F6 u  ~
  486. void __fastcall TForm1::Button1Click(TObject *Sender)
    , b1 A$ s) X3 p+ v
  487. {
    % U8 l) u( Q3 b
  488.    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
    : c/ F' s: L; k1 K5 \
  489. }
复制代码
发表于 2005-8-15 01:00:45 | 显示全部楼层
晕乎乎。。。怎么看8 洞阿
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-5-2 12:14 , Processed in 0.019504 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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