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

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

[复制链接]
发表于 2005-8-11 11:42:04 | 显示全部楼层 |阅读模式
  1. #include <WinIOCtl.h>
    3 W' o! I& ~; n0 e8 l
  2. #include <stdio.h>
    2 _0 M3 Z3 n5 H' n. t+ r

  3. % q/ P5 `; \+ S0 u/ B
  4. #pragma inline
    , @9 F7 O0 k8 y7 I; _
  5. //---------------------------------------------------------------------------
    8 q% a3 D8 M, ]8 z) e+ y
  6. // IDE NT/2000/XP专用变量
    0 q. z' Y6 F" ?
  7. #define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
    5 _0 G8 ?: X/ b* p8 b9 e4 T& h
  8. #define DFP_GET_VERSION         SMART_GET_VERSION6 Q: S" R4 h# t* @. u4 B& y7 `" X
  9. #define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
    5 j2 S( S+ t8 o% a( f7 U) z
  10. #define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA5 w& e( C* q  s0 U) N

  11. # D% X7 C' y( l0 U; P
  12. const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令! r# l; c* D2 b& [' h. X9 u( h
  13. const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令( Q' G! @' \6 T8 Y7 J- U/ G
  14. & j8 B" K# l- ?1 [- @' r! W5 x
  15. const int MAX_IDE_DRIVES = 4;9 I+ O/ ^5 ]: B/ J0 g( X) E  M

  16. ( \( o& c8 F: H8 [7 y$ L  k
  17. // SCSI专用变量
    # R8 P" R0 |$ J8 u2 C( c7 ]
  18. const DWORD FILE_DEVICE_SCSI             = 0x0000001B;
    6 a" J5 M/ k* h. a! c4 C& K
  19. const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);0 y1 M0 [) z4 H( z: F& f7 V2 @
  20. const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
    ) ~4 f- x4 k! G7 _9 d2 ]- {) Q0 l
  21. const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
    8 {. i5 P; c' q! U1 h

  22. ' S# w' V. k1 y2 \/ m
  23. typedef struct _SRB_IO_CONTROL  l, H( R" t' z5 {
  24. {  t, Z% t  ?( r' I. Q# d  ^% ^3 H
  25.    ULONG HeaderLength;2 N5 m' N! g; @9 Z2 D3 ?
  26.    UCHAR Signature[8];: f4 k4 o0 i1 J* d
  27.    ULONG Timeout;" e0 D+ S' w. c. C
  28.    ULONG ControlCode;) R  _+ n; r. R6 I) z0 W5 F
  29.    ULONG ReturnCode;* g1 `9 u4 P4 ^5 c& ^4 F
  30.    ULONG Length;4 K3 E. U& F( U/ }2 l2 I& t( h
  31. }SRB_IO_CONTROL, *PSRB_IO_CONTROL;7 T6 U; s5 [# Q6 G2 Z" T

  32.   n! [* D# @) U0 K8 @+ {
  33. // 读取的主函数
    ' T/ q" e, ^, j1 a0 {8 A
  34. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);
    " k( t. r4 I/ ^: f! A
  35. , N/ r: A* R1 V! G
  36. // 辅助函数$ E- T4 p5 E) H6 D( w3 `
  37. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
    ; {$ i2 ^3 ^- S5 z5 ]7 H! A
  38. // NT/2000/XP函数- {+ m: z( _) {$ s6 W/ h: T' d8 S
  39. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
    * z) T" a! ~3 v1 B: u1 D
  40. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,  W& W! W$ w$ W3 U3 X! P
  41.        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,( z+ W  K8 W: G. W' y+ D* j% h
  42.        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);% d$ S6 ^3 B" h# w
  43. // Windows 9X函数# Z) E0 {8 d6 m* J
  44. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);, R9 L2 e( u; A7 _1 b: J* ^9 |
  45. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,( k; u- }1 R, B; g2 o: h/ t
  46.        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
    $ X4 X" ]. a9 u/ I4 x! E

  47. . M' n6 U2 N. o0 ^0 }
  48. // SCSI读取函数(for NT/2000/XP)
    2 T1 D, {7 M- Q. E
  49. String __fastcall ReadIDEDriveAsScsiDriveOnNT();
    ) }& V9 w$ X) k2 L" V
  50. //---------------------------------------------------------------------------' T# }9 x/ o0 K- x6 R
  51. // ReadPhysicalDrive
    & Q4 j& K$ n/ C$ i) ~
  52. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)+ c2 j% P# D7 M
  53. {
    - m  D( I6 e: }  q( ]. h
  54.    switch(Win32Platform)
    2 L5 p" X2 U2 b
  55.    {
    ' L. P1 }% G" ?6 ^0 b+ b) Z
  56.        case VER_PLATFORM_WIN32_WINDOWS:
    8 E, w! s- ^: Z+ E
  57.            ReadPhysicalDriveOnW9X(pSerList, pModeList);
    0 r+ E3 B! e! C
  58.            break;
    5 e' q* v) L& s9 |
  59.        case VER_PLATFORM_WIN32_NT:
    ; j* g: M$ c& K' B# u1 M, _
  60.            ReadPhysicalDriveOnNT(pSerList, pModeList);
    " d% h  ?9 ~$ E+ R8 A, q
  61.            break;
    * ]' k7 s4 G4 r- H. {4 N1 L5 |
  62.        default:
    2 G: m' S5 i. g$ d' ?; U
  63.            break;
    . S7 Z: o% L1 Q* w
  64.    }( M; X5 @1 `1 h+ I4 W
  65. }4 e: Q7 C% q+ u% K9 t  s
  66. //---------------------------------------------------------------------------0 Z. D4 F4 c" L$ E" z
  67. // ConvertToString
    - h  r; l  {0 b. _0 ^9 \7 ^
  68. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)8 U' _- Q+ ]( {5 k3 n4 ]
  69. {' g2 Q7 V+ D% f1 r, X) o/ h- {# w5 T
  70.    static char szResBuf[1024];
    ' ]( [2 B3 |. n1 y' b* c
  71.    int nIndex = 0;
    ( z  T+ S# E' ^  K
  72.    int nPosition = 0;) K( c0 v" j7 x6 \* ]- r, ?

  73. " D. Y  z5 L7 D: D6 t" L7 u
  74.    // Each integer has two characters stored in it backwards4 m1 j( h! k5 ]( y3 d( z1 q
  75.    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)3 t  f; g: `$ x7 B9 k) Q
  76.    {9 X0 w1 D1 b1 L6 z- O1 X# y
  77.        // Get high BYTE for 1st character+ a8 K5 a1 p* d2 K3 g
  78.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
    9 j' B7 u$ o# G
  79.        nPosition++;" M( r  F4 [# g! `! M; v! o

  80. , W, v6 R  ^0 C1 P- M, r
  81.        // Get low BYTE for 2nd character2 C2 [- q7 \* h1 h6 Q% R& I3 Y
  82.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);0 ~7 U& s5 o) K. x# {* c( ?
  83.        nPosition++;0 M1 z& E( i8 x. k
  84.    }
    $ x* R, [+ ?' p  X$ k
  85. % Y& e$ G9 c0 _4 h) G/ m
  86.    // End the string; y: H0 I( I; l; B& E7 Q% ?
  87.    szResBuf[nPosition] = '\0';7 U- W% Z0 }- Y& |1 U( ~) l7 q
  88. , x2 E: y7 ?# Z& S1 ]2 _
  89.    // Cut off the trailing blanks( B8 l5 O1 \( k& l8 R7 h3 f
  90.    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--); y- J1 t" R8 D+ l" X: T( o( E
  91.        szResBuf[nIndex] = '\0';
    ) k' n1 p. P- I* K1 |+ \, i3 j

  92. & h2 g+ K- H/ H  \$ s
  93.    return szResBuf;/ ~' X/ E6 t" C+ A$ A1 p/ k
  94. }
    # i, U! ^2 Z4 E: M/ b
  95. //---------------------------------------------------------------------------
    % n; D2 k, ]1 `6 s  K+ G
  96. // Winndows NT4/2000/XP 代码
      C$ S! t" Z( u8 H# K3 N; ^% e
  97. //---------------------------------------------------------------------------: F4 l9 M! A8 d& q
  98. // ReadPhysicalDriveOnNT
      l- X5 z! _$ T' G
  99. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)0 F/ h3 X( h+ R( U
  100. {, e( h$ E/ V  |# h
  101.    // 输出参数
    ) r4 g/ J! K1 u& b  K
  102.    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
    8 B8 f) y$ _# S& o1 f
  103. 1 \1 L8 \- z( G  m% @' J9 H
  104.    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
    & l3 G; `* _$ `% u# k4 g' n( W
  105.    {% x& J' J. P% \6 t& w
  106.        HANDLE hPhysicalDriveIOCTL;
    3 w7 [) a5 `* c/ Q: ]8 M6 D
  107.        char szDriveName[32];6 l5 L. {$ e. y! b7 E
  108. % e, D# v0 b0 i3 y
  109.        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);# v8 k1 u" t: B& k. F
  110.        hPhysicalDriveIOCTL = CreateFile(szDriveName,1 y/ |5 Q) j4 ?. a
  111.                        GENERIC_READ | GENERIC_WRITE,* \# w5 [$ W& f' d
  112.                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,, {1 k8 z- I. w. _& s0 I
  113.                        OPEN_EXISTING, 0, NULL);- g# e3 x, i, i# t  m7 K/ D
  114. ! i& P+ {, X+ c& t
  115.        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
    / m: Z: g3 W* u
  116.        {& @* M* ?7 H  f; v
  117.            DWORD dwBytesReturned = 0;, u# J& m/ j  G
  118.            GETVERSIONOUTPARAMS gvopVersionParams;
    % a& X  w1 n# P" M  `
  119. + X" m; ]9 m; J- w9 ?/ W, G
  120.            // Get the version, etc of PhysicalDrive IOCTL3 l% {0 {' x% E. s
  121.            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));: N4 u) ^* p4 K2 D
  122. 7 W, u/ X" Q1 c3 |, V/ A1 D2 w
  123.            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,( m2 ]& a3 ^, o. m* b' \9 P$ ~
  124.                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
    2 M: M! m. |& L( ?
  125.                    &dwBytesReturned, NULL))
    * g+ y8 d/ U% ]  ~! d
  126.            {) o! Z" D/ k5 O
  127.                continue;
    - E; Q) X# ~' l
  128.            }  A# T% H, g1 g+ F2 X) `9 q

  129. 7 a3 E, L! @/ w) H3 [8 R9 R* o
  130.            if(gvopVersionParams.bIDEDeviceMap > 0)) a' M# N% y1 s5 B
  131.            {( m) x" y) v( @) w
  132.                // IDE or ATAPI IDENTIFY cmd
    ; o( n8 g. x( w- t2 j0 w$ t
  133.                BYTE btIDCmd = 0;
    5 Y9 s4 Y4 g$ c8 S% c
  134.                SENDCMDINPARAMS InParams;
    . |! s' Y1 F0 L; Y' |: ]
  135.                // Now, get the ID sector for all IDE devices in the system.
    $ N4 u- Z* i" Q) S7 J7 ^6 L
  136.                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,2 V/ b+ ]) I& W; d0 o8 O9 c
  137.                // otherwise use the IDE_ATA_IDENTIFY command" @! ~; F, N5 q" |! e( V
  138.                // 具体所得结果请参考头文件中的说明
    ! h1 I/ ~- t$ R& M$ s
  139.                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
    1 c4 \: e8 Q8 N  ~" ]
  140.                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
    ( W. y& r: {6 B
  141.                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
    3 a+ K* ]0 Q5 G; w- @6 q- `; [! d& Z
  142.                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
    2 E4 q4 y0 c) `( m9 w; `' T

  143. , M: w& Y8 H: |7 e- y
  144.                if(DoIdentify(hPhysicalDriveIOCTL,
    2 }. s4 _% H- R, ?) x' h/ `
  145.                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,; W* @8 g7 W: [$ A7 k
  146.                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
    $ i( v4 f* C0 W, }: y9 k
  147.                {  o5 S- [" {! k; A3 R
  148.                    DWORD dwDiskData[256];1 L) i- g* E' w1 S! Q; q  f0 J
  149.                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件3 U+ M6 M( d0 W/ X" V$ k* z
  150.                    char szSerialNumber[21];
    8 V5 |$ t2 s& M( S- R, ~
  151.                    char szModelNumber[41];
    * Y; d0 v7 I) R0 F" m$ _
  152. ; h& d8 v2 v3 P# a- ^- u
  153.                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
    5 `, `& |5 V6 c) E  B7 }
  154.                    for(int i=0; i < 256; i++)) r$ ?  ~2 b$ X' P
  155.                        dwDiskData = pIDSector;# C% }2 R# s' I& q& b
  156.                    // 取系列号% E. I5 |: f. W0 M' w9 s+ O% T
  157.                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));( B2 S  A+ w# @! b3 d
  158.                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));+ Y) z9 U2 @/ b7 V1 d* A5 n

  159. 9 [. j0 W. A  D, @9 w! _/ d2 c' W
  160.                    // 取模型号
    & w" R( m/ V; z7 U/ J* R
  161.                    ZeroMemory(szModelNumber, sizeof(szModelNumber));! L8 \8 }! [! K
  162.                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));/ n- l( u6 H4 j+ t3 K

  163. 0 E" @. k. s. o. j  R+ q
  164.                    pSerList->Add(szSerialNumber);. S- p6 h3 q0 F
  165.                    pModeList->Add(szModelNumber);* \! H' I2 t$ W
  166.                }# E0 F* S' w, [5 [+ j6 ~/ n$ {" _
  167.            }( n$ \0 s2 ]0 ^# ~- }- R8 g  r, k
  168.            CloseHandle (hPhysicalDriveIOCTL);) @7 R3 q6 x0 f9 d" L$ c
  169.        }
    $ j4 {/ _* L+ E/ m
  170.    }2 g1 V% G: p5 f& r$ k# M, Z
  171. }
    % p% ?' a1 `, v, z8 `& `1 C* [" W
  172. //---------------------------------------------------------------------------
    + t: d5 D4 h) ]
  173. // DoIdentify
    0 \) k8 d1 {# L, |# B+ q0 q+ N% l( I
  174. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,4 S& E' A8 i5 ~, r
  175.              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,8 I2 O8 m( }3 T: D" B( L2 E
  176.              PDWORD pdwBytesReturned)5 ~0 Z8 F6 Z" y3 C" ?
  177. {
    . S0 q& D3 o/ v
  178.    // Set up data structures for IDENTIFY command.
    ( F& `) T3 v1 s5 X- e
  179.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
    ; C! H. B% [+ B8 i- |
  180.    pSCIP->irDriveRegs.bFeaturesReg = 0;" p6 Q, r4 b- {: o  `# Y$ V
  181.    pSCIP->irDriveRegs.bSectorCountReg  = 1;
    8 T2 ?* c0 o* G% w3 _
  182.    pSCIP->irDriveRegs.bSectorNumberReg = 1;
    2 Q/ ~* g+ J' V  {) s  s) j
  183.    pSCIP->irDriveRegs.bCylLowReg  = 0;
    4 B$ k1 L; D; Z- E8 Z8 K$ o7 a
  184.    pSCIP->irDriveRegs.bCylHighReg = 0;2 P. i& f, A5 k( Y4 Z

  185. 8 [$ i, y" h. Z, i
  186.    // Compute the drive number.(主盘和从盘所对应的值是不一样的)! B: k" `2 ^+ Z2 q
  187.    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
    , i7 E1 X6 F: f( p3 D9 M
  188. 6 N' T, ~- q/ y. ^5 Z
  189.    // The command can either be IDE identify or ATAPI identify.8 C! B- ]' M/ \4 h+ _& h7 I5 j
  190.    pSCIP->irDriveRegs.bCommandReg = btIDCmd;1 o3 U" ^' s' F& n7 }; [  G3 j5 i
  191.    pSCIP->bDriveNumber = btDriveNum;( i' Z7 }6 y4 C2 ~# F$ r
  192.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;  F% B; l1 D" i5 e

  193. ( E4 T! `( M: f: l; }" V
  194.    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,! n* i: R3 c8 I9 Y3 Q: S
  195.           (LPVOID)pSCIP,
    " O$ w9 O! H( R- d& G
  196.           sizeof(SENDCMDINPARAMS) - 1,
    : o: _3 i4 B) J; X
  197.           (LPVOID)pSCOP,6 H1 F/ P0 I! _9 s/ u2 \/ s8 I
  198.           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
    9 v- ~; V4 ^2 w8 q( V
  199.           pdwBytesReturned, NULL);* p3 W! u* R" K' y# P) v7 D
  200. }8 {4 U0 F% b& \( x0 a$ m
  201. //---------------------------------------------------------------------------) {3 r  k+ L" {8 f) |5 z$ U; ]' V
  202. // Windows 95/98/ME 代码6 E6 K8 t: a# y, A
  203. //---------------------------------------------------------------------------
    " f2 J0 `% U7 T( g# n
  204. // ReadPhysicalDriveOnW9X
    # ]! I( i- H8 J! w1 O; q
  205. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)9 m% ?) K* v7 |# i0 _
  206. {
    4 l) j  O3 E8 Q# M
  207.    WORD wOutData[256];5 `& j* G' Q/ m3 w" `/ z0 V
  208.    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);. |: O* Y* f$ k' e* @: f9 q( T+ R
  209. * n7 z2 z! L! l# U2 z
  210.    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。1 Q" B$ V( T0 }
  211.    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
    - p+ p: c7 j+ \: B- t: `
  212.    // 避免蓝屏的出现。(期待高人能指出原因)8 Q5 A  |+ o* c+ q, @" W0 \9 a
  213.    for(int nDrive = 0; nDrive < 8; nDrive++)
    ; y* s9 j" v3 q: P
  214.    {) i, u) L+ _2 f6 K& x( z& q
  215.        WORD dwBaseAddress;
    " L6 N" I9 S$ x) F, C6 J( v
  216.        BYTE btMasterSlave;         // Master Or Slave, ]+ D* w; i5 G+ k0 J
  217.        bool bIsIDEExist;. L9 Y  k7 O: E3 ?
  218.        bool IsDiskExist;
    4 Z4 N% k7 F' M# b! ^

  219. 7 L& ]% ~/ |+ {0 Y; u! q5 m
  220.        switch(nDrive / 2)
    ; a, w+ u8 i6 A" B
  221.        {9 u: o# a" K: \, {2 }) W: M& G& |
  222.            case 0: dwBaseAddress = 0x01F0; break;
      d" d  Y2 h1 @  f" x
  223.            case 1: dwBaseAddress = 0x0170; break;
    0 ~* o2 ]: `  n6 z9 e
  224.            case 2: dwBaseAddress = 0x01E8; break;% Z2 `6 [3 d1 i" E# }# r# l1 x0 W
  225.            case 3: dwBaseAddress = 0x0168; break;( _8 L" l* l# c- ^6 y6 H! [+ S
  226.        }# n2 @; B: ?; D& g* L2 d3 D# v
  227. " u& a& }9 f, Z
  228.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);% J/ v" H- ?5 g5 {0 \8 A; F. x
  229. 3 W% V! Y3 D$ n1 w& S6 k2 n5 V
  230.        // 进入Ring0
    , c. x1 I7 W5 m, g
  231.        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,3 _9 T: K* r( i
  232.                bIsIDEExist, IsDiskExist, wOutData);  e- U7 \: K9 o1 I2 X
  233.    }
    $ q. A. o- R3 D5 X3 O& i

  234. 1 [' U0 }, o9 C0 A1 Q* u' Q$ J
  235.    // 开始读取
    * g" i2 l' M2 S. c
  236.    for(int nDrive = 0; nDrive < 8; nDrive++)- H2 z/ _* `  y$ u
  237.    {" X, I, L% U) J9 x  {0 L5 m
  238.        WORD dwBaseAddress;" m9 V! i- g. s8 Y: d( _
  239.        BYTE btMasterSlave;         // Master Or Slave
    ' j3 a* n9 \) L
  240.        bool bIsIDEExist;& N  U. t- u6 d) E( ~. c
  241.        bool bIsDiskExist;
    8 V, v- c3 K* J" n3 ?0 P+ w) M
  242.        switch(nDrive / 2)+ ]6 k# E3 f7 _7 C) U- b
  243.        {0 p* j4 W/ ?) M4 a+ o6 d* X
  244.            case 0: dwBaseAddress = 0x01F0; break;0 L/ w( T( B# l0 R: Y5 w) ~/ u* `
  245.            case 1: dwBaseAddress = 0x0170; break;8 X$ n) ]6 M( a( ?( Z
  246.            case 2: dwBaseAddress = 0x01E8; break;
    # V# \; P) t# E
  247.            case 3: dwBaseAddress = 0x0168; break;
    , G3 @+ T5 h* w. B5 l
  248.        }
    9 v& }6 r  _2 v7 |

  249. . a) r$ [+ e. x% y% q4 q
  250.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
    7 B& h/ T# Y. w2 Z5 [7 B. n

  251. " q5 c8 R- I9 n0 I6 q3 A5 I: Y2 D
  252.        // 进入Ring04 [9 o5 i$ a/ h% i* i
  253.        bIsIDEExist  = false;- {( q4 h. n7 s3 J( [) v6 A
  254.        bIsDiskExist = false;% f4 T: y5 P0 m) [8 d
  255.        ZeroMemory(wOutData, sizeof(wOutData));6 e! i6 {1 m0 S2 M
  256. 4 S  a2 E/ ^1 b; `5 a
  257.        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,, t5 n5 `% _: A2 [
  258.                bIsIDEExist, bIsDiskExist, wOutData);
    4 d# [( e8 S4 u# {
  259. $ @' S, J& a! f1 Q. ^; C- S
  260.        if(bIsIDEExist && bIsDiskExist)7 D. k+ h8 b) e) W- d
  261.        {% R. P$ v0 n4 ~
  262.            DWORD dwDiskData[256];9 v" O5 O; z6 U' R( R+ ~
  263.            char  szSerialNumber[21];" E- i5 L' h: e; N0 Y" x
  264.            char  szModelNumber[41];2 J! {2 A3 ]8 ~) s
  265. 8 H6 G& `2 o! ]2 N$ d7 t/ b& q
  266.            for(int k=0; k < 256; k++)! g) B/ r! J, W& b. S" z8 w3 U
  267.                dwDiskData[k] = wOutData[k];  I1 d; W3 ^) V
  268. 6 _2 Y8 G) ]0 A
  269.            // 取系列号( g/ {' E! H5 R9 v: f
  270.            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));2 [  i  z, C+ ~0 A" S4 ?* v) a  @9 z7 R
  271.            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
    + K: a# l% y. u4 x( V

  272. 6 @! T# ?& Q/ ?# z- Z& v6 y
  273.            // 取模型号
    1 y' }' r# U# H  J  ]  U
  274.            ZeroMemory(szModelNumber, sizeof(szModelNumber));
    & a) q! F  D- Q; j$ u7 ~. R
  275.            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));& d% f2 A) [, d4 E  Z6 o

  276.   [  r" J# W0 V% \5 X: N" H7 |
  277.            pSerList->Add(szSerialNumber);
    ! R# [' z/ R4 S- K4 J
  278.            pModeList->Add(szModelNumber);. O3 x% S, Y  r) o7 w' u4 D
  279.        }
    # V, N6 r1 m* x
  280.    }0 ]9 d! s8 I1 ?0 k
  281.    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
    4 H  `* t0 D3 c# W; `0 J" I
  282. }
      C+ q; {; m+ S- e" g
  283. //---------------------------------------------------------------------------
    1 w7 A  ]& {, J. `
  284. // ReadPhysicalDriveOnW9X_Ring0()1 S" c, `. L! d0 v
  285. //
    5 ]1 Q0 V5 i7 f3 P/ q+ ]
  286. // dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
    . J4 w. V) j6 j3 H$ x1 q; E
  287. // btMasterSlave = Master(0xA0) Or Slave(0xB0)2 H0 [1 ~: h6 R( B4 j4 j5 e' s2 c
  288. //---------------------------------------------------------------------------
    2 S& n, E. a  ~& b2 W- v. F8 H
  289. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
    ' a8 T: ^, T/ L) y4 f
  290.        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData); L3 l+ L' }! {+ D: Y4 ~
  291. {
    $ ~# m  t" j8 H% x! ^7 ^1 w
  292.    BYTE  btIDTR1[6];
    ! Z9 [% e' e% ?) B4 k
  293.    DWORD dwOldExceptionHook;
    1 l1 Z  A" P9 M8 J
  294.    const int nHookExceptionNo = 5;, ]! k) b5 K3 H  [
  295. 2 B3 |4 o4 ]$ ?
  296.    BYTE  btIsIDEExist = 0;  R4 _' z/ J' r/ V! S  h1 E
  297.    BYTE  btIsDiskExist = 0;
    1 u; |6 v& D/ a' s$ o
  298.    WORD  wOutDataBuf[256];
    5 {: F* R9 }% v* t
  299. : a- O$ Q. m! X2 n! h, e+ M9 C9 N
  300.    BYTE  btIsFirst = (BYTE)bIsFirst;6 e3 U9 e& w& |  h9 t: p
  301. , P& c. C' ~7 m9 Y) S+ _3 J6 H$ P
  302.    const BYTE btBit00 = 0x01;
    $ z; Z4 K) \4 b' O. R9 W
  303.    // const BYTE btBit02 = 0x04;; L# Z- ^7 X" I. Q7 i
  304.    const BYTE btBit06 = 0x40;
    2 J: m4 Z  B$ L6 \0 z
  305.    const BYTE btBit07 = 0x80;% A. p4 Z2 `, ]1 }) u' U9 N  T) c5 a
  306.    // const BYTE btERR  = btBit00;
    # Y6 A) {8 l: Q; G  h
  307.    const BYTE btBusy = btBit07;3 R& w* }! r0 w! X. K! K$ E
  308.    const BYTE btAtaCmd   = 0xEC;9 g9 h1 b4 }  C* A0 ^
  309.    const BYTE btAtapiCmd = 0xA1;. f+ p% i' W$ n+ M& R

  310. ) D- R# y/ h* r; \" M3 h
  311.    __asm
    ( p  S% T  A3 S( I8 o4 S
  312.    {
    ; |1 e, D! Q3 k" D- t: _  N
  313.        // 必须先执行这条语句
    + \, C9 |8 Y! o1 r
  314.        JMP EnterRing0
    + P) H9 f8 H: X7 ?7 m/ P! l
  315. 7 m  `- Z9 m" ~, v& o- |  }
  316.        // 定义过程
    9 E) M4 i+ O4 `
  317.        // 等待IDE设备直到其不为忙为止# a+ ~4 l9 D) Z, z9 u' z  y7 E" N
  318.        WaitWhileBusy proc
    . Q, K% h" `; {) Z6 E* k- W; u

  319. ; z- I) z  D9 r/ d0 w8 j) m+ P+ R
  320.        MOV  EBX, 100000
    ; u& O$ {& I8 K3 x. K5 k' a
  321.        MOV  DX, dwBaseAddress
    # \) _, v  H3 U; y& q& z# }
  322.        ADD  DX, 7. g# Q& m3 Z+ O7 D% f. n" j
  323. 1 @2 v; \# ^. o; D# z
  324.        LoopWhileBusy:
    7 F1 v% a# E: o! d8 v; S" v# G7 X
  325. 8 F" H/ g, r; v5 s: j- F
  326.        DEC  EBX
    - O4 d4 n9 I9 {: l1 R- j
  327.        CMP  EBX, 0
    6 \; f1 ], \2 [
  328.        JZ   Timeout4 t: z( Y; r& B3 s. F: i
  329.        in   AL, DX
    ( z$ z- r. p% _$ C7 x
  330.        TEST AL, btBusy
    3 n' w1 }; n6 c8 I4 c* I4 i1 {5 y
  331.        JNZ  LoopWhileBusy
    ' E+ I3 b' H$ Q2 L# ~! l8 ?9 L* J
  332.        JMP  DriveReady6 Y$ f& G. J8 _0 A: w/ |2 @3 u
  333. ! _' J% [6 L  b9 ^6 s$ `! @
  334.        // 超时,直接退出
      l5 f1 K, |( O8 z- P  O
  335.        Timeout:) N1 m  c, a( z9 s- x6 u6 b+ F  Q
  336.        JMP  LeaveRing0
    4 y$ W( g0 y$ g) n4 K/ q
  337.        DriveReady:
    9 e. @  C2 z9 h" `
  338.        RET2 \6 |2 J" D0 R$ U- w
  339.        ENDP   // End of WaitWhileBusy Procedure1 B% C) I/ A& e. `9 H; f
  340. 7 _8 ?% o& _- ?: }. [( ^" I" ], R2 `
  341.        // 设置主盘和从盘标志
    7 O7 d" G6 E! s9 u, S/ m! F
  342.        SelectDevice proc% A8 n: F* X$ [/ o8 \0 M

  343. 8 g! R2 X' [* s; K1 q% ?
  344.        MOV  DX, dwBaseAddress4 Z! w. x; {; v0 k/ V) v' \, K$ `0 A
  345.        ADD  DX, 6
    " b4 h2 C, w  b* a
  346.        MOV  AL, btMasterSlave0 v+ R8 R7 _  U  t: R

  347. ( X5 g+ E, c* ]3 n9 L% E
  348.        out  DX, AL) x8 D* ^" }) L0 h: d" A. p  q
  349.        RET# y' w2 J, s) q9 ]
  350. - s% a# U) x9 V/ S
  351.        ENDP  // End of SelectDevice Procedure, V4 X1 \8 b5 n, }5 r
  352. 2 q1 |& J) Q5 d: _0 y
  353.        // 向IDE设备发送存取指令5 ~1 [+ d% A  g% g, j' {4 P
  354.        SendCmd proc8 Y0 Z( X% @3 L! J5 X  r, R! t; Z

  355. 4 Z( a0 n/ l# C
  356.        MOV DX, dwBaseAddress
    + _9 N! E8 `. y/ w, W$ g
  357.        ADD DX, 7/ q3 G2 V7 p5 [! M
  358.        MOV AL, BL // BL是主从盘标识,在过程外设置5 q0 t% F0 c  f- G
  359.        out DX, AL
    5 n% R# ], |# ^& n% w9 k
  360.        RET
    " F5 o1 t3 F% `1 Y% B6 r
  361.        ENDP  // End of SendCmd Procedure: S+ K% x; {1 a5 ~0 ~% S
  362. $ L4 o" z' C% {: v3 I5 C
  363.        // Ring0代码
    # v$ r1 U& r+ B" J7 R
  364.        Ring0Proc:
    8 P/ L( F* `% A: V# f. }& K* ?; K
  365.        PUSHAD/ l3 g* \9 ?/ }  T
  366.        // 查询IDE设备是否存在) ~& W: C9 Q2 d7 |
  367.        MOV DX, dwBaseAddress
    ' L/ t8 \5 t, a) d, E
  368.        ADD DX, 7
    ; s9 U$ }- y5 W! z5 {. \" i' t) V( y) _
  369.        in  AL,DX
    2 H; P$ p! @8 `8 D; P/ x
  370. " @! s( n* [3 @6 J2 o$ p5 A
  371.        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
    ! [' f+ f; M& X& ^5 o1 y, e
  372.        CMP AL,0xFF
    , b/ `% Y9 i- ~1 u8 O+ R
  373.        JZ  LeaveRing0& O* D/ r  p  Y' A9 n( N) u
  374.        CMP AL, 0x7F1 @# k1 o; e$ e. N8 C. H
  375.        JZ  LeaveRing0
    9 w! m$ s6 S6 N) d. i; S4 v/ ~

  376. + z' s0 _* C6 E$ M# u5 A
  377.        // 设置IDE设备存在标志
    1 F; i1 V; C6 k9 D# B
  378.        MOV btIsIDEExist, 1& T7 X: @- {+ p( Q7 d" Q1 `9 E
  379.   I) O. O& `) D$ Q* o* A
  380.        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)" E: p1 `& W( z
  381.        CALL WaitWhileBusy, j6 E' l3 h8 T, q7 ]% W6 g6 o9 N5 H
  382.        CALL SelectDevice
    / h6 {* o5 Z5 I8 x" B, N8 O
  383. * _+ z" t5 P4 y# c8 ]1 t2 r
  384.        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏6 I9 [- X- K8 d( R
  385.        CMP  btIsFirst, 17 s, h8 z3 t0 d% Z0 x" `
  386.        JZ   LeaveRing0& ?$ c" z& W; {! a( X  B/ X1 [5 s
  387. % r9 V$ v" X3 v
  388.        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???$ j" V5 g# l8 {
  389.        CALL WaitWhileBusy
    ' X( o9 v7 h7 X2 a
  390. # D* P- @2 u- s. ?# M1 y
  391.        // AL的值等于cBit06时,不存在驱动器,直接返回- M: l" ~: L0 l2 w
  392.        TEST AL, btBit069 Z6 W" V- k# |& Y7 \$ h' U
  393.        JZ   LeaveRing0
    0 Q8 z8 r8 X9 ^# y1 b1 A
  394. 9 S! }; C: U3 C
  395.        // 设置驱动器存在标志. U' t# r& k' _2 f; q6 v) u) U9 M
  396.        MOV  btIsDiskExist, 1. U* U& Y5 l; L3 U9 y
  397. $ ^+ D, B/ Z+ G, }4 l3 i5 l
  398.        // 发送存取端口命令
    ! C' D/ g0 }+ a' D8 F
  399.        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
    2 H5 _( r8 C8 N: v% @3 V8 Q" S  C
  400.        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令# a' f& s0 ?  R8 I, p
  401.        CALL WaitWhileBusy
    : R7 l3 O- ]) h: J& ]; d! d+ U
  402.        CALL SelectDevice    // 设置主从盘标识
    % V: M. s* U+ U* O& F
  403.        MOV  BL, btAtaCmd      // 发送读取命令. d( P* d& w5 ]7 d5 g
  404.        CALL SendCmd/ i- {. {! K+ ~# z
  405.        CALL WaitWhileBusy- G- `5 b0 N9 Y- f  D
  406. 4 i# z3 \: V5 D
  407.        // 检查是否出错! G% z# _- x2 V, P
  408.        MOV  DX, dwBaseAddress
    * u4 ]4 O' E  e; B
  409.        ADD  DX, 7
    " l6 w( Z0 L" N

  410. & Y3 t# q0 [9 Q. @- a. i
  411.        in   AL, DX6 t# S+ d4 ]) j3 X

  412. 9 ~5 F+ i& r5 C7 g7 z  ?7 W. U# Z. Y% k
  413.        TEST AL, btBit00
    ; \; ~$ P9 e" _) F( j
  414.        JZ   RetrieveInfo   // 没有错误时则读数据7 b: o9 j) `, I+ @
  415. 5 A' s0 m  \5 A! y; H# b: M
  416.        // 如果出错,则进一步尝试使用ATAPI设备命令; v6 d1 F+ X+ T8 V) }5 k$ T1 t
  417.        CALL WaitWhileBusy
    1 o! M- h! m/ y9 ~, U. d
  418.        CALL SelectDevice
    / |9 s! ?7 y$ C7 Y+ E! f- t  Z% E
  419.        MOV  BL, btAtapiCmd7 t# F. k2 T7 w# |4 X0 [4 N
  420.        CALL SendCmd* U% `- h, Z6 b2 ]( h7 k+ t
  421.        CALL WaitWhileBusy
    2 o. f( L! f* i8 a  Q+ h# T
  422. 8 B( _9 G9 _0 N) d  i# t
  423.        // 检查是否还出错& i0 C0 ]3 e( I( y
  424.        MOV  DX, dwBaseAddress0 G4 t3 U4 h; Q$ _2 a  M
  425.        ADD  DX, 7
    + `6 K. {: B9 I$ J  O" B$ v
  426.        in   AL, DX
    2 m  h" i5 g+ I) ]' \, @
  427.        TEST AL, btBit008 U/ u; g8 S4 j4 H
  428.        JZ   RetrieveInfo   // 没有错误时则读数据
    / ?$ L8 J$ M& ~+ T5 s5 y
  429.        JMP  LeaveRing0     // 如果还是出错,直接返回
    2 I6 G/ u5 t/ W. G% Q8 `+ V; E
  430. . z* ^/ T" ~( j2 ?
  431.        // 读取数据
    . w- t. a. M0 P: [  L2 I6 y( k
  432.        RetrieveInfo:
    4 n. o; P( t0 r2 W7 J) x

  433. ! s* S& O5 G7 C& i1 ~8 M
  434.        LEA  EDI, wOutDataBuf
    ' n9 J5 t* ^; R5 @- k9 H( J5 V" t
  435.        MOV  ECX, 2562 q* V2 K) [) H% z
  436.        MOV  DX, dwBaseAddress
    8 s4 k- o; \) m
  437.        CLD& a+ D, M2 M  U( J+ s* G
  438. 5 ^6 M! Z" ~1 X- G- u9 y1 a) m
  439.        REP  INSW
    ! T: A! \! j4 Y& S" [2 X+ ?
  440. $ D2 [, r: p& \' B
  441.        // 退出Ring0代码
    6 _8 M, V2 S$ g* B% B. N; ^
  442.        LeaveRing0:
    4 f; P3 V* B" ^. x- u# j* X
  443. 8 |4 G+ G- i% p2 G8 ?
  444.        POPAD  p& T4 |4 o; a2 F* U/ ^
  445.        IRETD/ A5 b- z3 L+ `) B
  446. ) \, A9 b. W9 ~5 P+ n
  447.        // 激活Ring0代码
    : h  V! O" n% I
  448.        EnterRing0:
    ! e9 r. [  g: P: r
  449. ; U2 G4 ]4 s4 @% Y! T2 c0 j
  450.        // 修改中断门' w* z* W2 u* M) t/ m& K/ r" n
  451.        SIDT FWORD PTR btIDTR1) X5 {6 K2 x) D% y: }: J$ [
  452.        MOV EAX, DWORD PTR btIDTR1 + 02h
    8 [7 @0 j' V6 n
  453.        ADD EAX, nHookExceptionNo * 08h + 04h
    % u; \) A7 W8 R* w) X
  454.        CLI
    2 l6 r2 X4 F; [1 J+ b1 P8 F
  455. 9 Z; ]8 p3 s; q6 C( Y  \3 C' w
  456.        // 保存原异常处理例程入口
    2 ]% [5 S  o  Y4 E- Z
  457.        MOV ECX, DWORD PTR [EAX]3 P9 E$ r' R$ C, A
  458.        MOV CX, WORD PTR [EAX-04h]
    2 }7 q  I$ ?! X' n2 N( Z7 v
  459.        MOV dwOldExceptionHook, ECX
    0 e% L) `' B8 z7 d  B
  460. 9 \/ C7 X% O2 {: h3 `
  461.        // 指定新入口6 ]( j3 D- B& r
  462.        LEA EBX, Ring0Proc: m; ?+ }4 Q; b: A; ?) P
  463.        MOV WORD PTR [EAX-04h],BX1 i' a# D3 E3 S1 c6 R6 v" x1 O# v2 E
  464.        SHR EBX, 10h
    9 \1 H& B- [8 v* O& _+ a1 D
  465.        MOV WORD PTR[EAX+02h], BX. {/ _* M, _6 O5 ?& m2 g

  466. , V* m2 A# F; e/ e% E- _6 }# c
  467.        // 激活Ring0代码
    % j* r$ N4 n0 M, d7 K* j9 m0 K% {
  468.        INT nHookExceptionNo. y! K, H) ~0 k5 B, [9 R4 k

  469. " E9 @  R$ \' E5 @+ I/ {" B
  470.        // 复原入口" l6 O6 L1 D& b9 J. \+ B( L
  471.        MOV ECX,dwOldExceptionHook4 ]. V7 ^" O6 S" S
  472.        MOV WORD PTR[EAX-04h], CX
    1 w9 {9 G( M! f5 ~( G
  473.        SHR ECX,10h
    & P5 S2 c7 K& W0 a8 f+ g
  474.        MOV WORD PTR[EAX+02h], CX
    1 [+ v; o) T2 [8 c# S5 P
  475.        STI6 @! W- y1 l3 ~+ y! j1 i* b
  476.    }& |1 C6 m3 ]5 d0 z; J4 Q
  477.    if(!bIsFirst)
    * @# U7 y( J- ^1 J' R$ B) _" s
  478.    {$ |. ^" b* C' V
  479.        bIsIDEExist  = (bool)btIsIDEExist;
    , U# A8 w6 y% x* N4 C
  480.        bIsDiskExist = (bool)btIsDiskExist;) F' \* d& P$ w" j9 n& O/ L
  481.        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));! a) ^* z- t+ Q1 o5 e, }, L
  482.    }
    ( {: g, R/ P( r( _; g& H  s
  483. }
    9 r6 T( h9 u/ x0 ~0 t" ^
  484. //---------------------------------------------------------------------------
    ; F& P3 n" n% C/ d5 b( k
  485. // 调用方法:
    - `5 e" j. C6 X8 q- `- r8 V' D
  486. void __fastcall TForm1::Button1Click(TObject *Sender)+ ^# M( L4 M5 Q0 i5 u3 N. G
  487. {
      E6 e2 K$ H; l# I* l& v
  488.    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
    / m% r9 @: j/ s5 \6 q
  489. }
复制代码
发表于 2005-8-15 01:00:45 | 显示全部楼层
晕乎乎。。。怎么看8 洞阿
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-5-4 16:53 , Processed in 0.024519 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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