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

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

[复制链接]
发表于 2005-8-11 11:42:04 | 显示全部楼层 |阅读模式
  1. #include <WinIOCtl.h>
    3 w' B# Z' ~. v4 t8 U
  2. #include <stdio.h>9 {8 W4 m7 J! E* |, s8 l

  3. / h) X3 t- e  W) F
  4. #pragma inline
    7 g. y5 B6 T1 k- E% ]& J  ^/ m/ c/ E
  5. //---------------------------------------------------------------------------7 r$ t' Y+ V0 ?$ ^  i
  6. // IDE NT/2000/XP专用变量) H( Y$ u2 @" W  u# I# o
  7. #define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS, g) t# ?# ^+ p; {6 J% r( m; r
  8. #define DFP_GET_VERSION         SMART_GET_VERSION
    - u7 p8 \1 X: Z2 `8 i3 o. S" [! j
  9. #define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
    " u0 x1 ?+ U1 I0 ]% W$ K) u& m" q
  10. #define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA
    + g: F  h9 U  Y. f( O; }

  11. 6 i$ o- Z& {+ ~
  12. const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令
    / P) \. P# k0 V2 w. O
  13. const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令3 Y' o1 _5 T9 {
  14. ( @1 B- ^% D# t( {- F5 ?
  15. const int MAX_IDE_DRIVES = 4;8 Z! H0 i* E) \1 m  [* K( _
  16. % c& O- B3 `$ ?5 u; G: M
  17. // SCSI专用变量" p, j  {" M1 J7 ?' ?4 E
  18. const DWORD FILE_DEVICE_SCSI             = 0x0000001B;1 W2 @) |# e  k7 `
  19. const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);/ x" i; W# n" m! C
  20. const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition; w. k9 j4 M. y4 ^' Z7 Z% Q* Z
  21. const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;# H! _0 ]' o8 g( ^1 w: ?4 f2 I
  22. % h" Q; T) S; M
  23. typedef struct _SRB_IO_CONTROL! n5 @1 w. ], @$ ^
  24. {% A) p' R- Y' q
  25.    ULONG HeaderLength;8 m# X  {$ W* t6 A0 H8 B
  26.    UCHAR Signature[8];
    + D- Z, W) C. u5 n1 V/ l: n
  27.    ULONG Timeout;
    7 y" x& Q# r4 S' {  G% G0 g- ]8 J
  28.    ULONG ControlCode;. l1 m( L3 w7 X4 W( s2 F( d
  29.    ULONG ReturnCode;
      w% {% s+ T5 ^  ]# C$ V) V) _
  30.    ULONG Length;( u( `, h( f$ V. a7 _
  31. }SRB_IO_CONTROL, *PSRB_IO_CONTROL;! o' l6 x0 }, Z. |9 m% s
  32. : l* i6 z4 s0 \5 e) _
  33. // 读取的主函数
    8 Q1 o& B. V7 A
  34. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);9 ]. n) u! t; [6 j3 n' l
  35. 8 ^; c, _& }) K/ \* Y
  36. // 辅助函数' i; h' w$ d- o) n
  37. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
    - j, W' _$ k' R( |& O
  38. // NT/2000/XP函数. j' m1 A. W& N0 P  ~' }4 [& C
  39. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
    6 B- Y* G7 f% E9 n# o' q
  40. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
    1 @0 ~0 C$ O# g$ F# w* K/ i% ^
  41.        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
      f( K3 ?0 u2 y/ [6 J- T' u4 v
  42.        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);. G2 @- c$ [$ {7 i* A
  43. // Windows 9X函数
    5 ~& _6 d7 u6 H# g$ y- f3 `
  44. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);
    1 w' N9 b; P+ W4 h9 ]1 E- F7 ~, ]
  45. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
    " r, k( N% f/ C' k
  46.        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);' }% J" n5 _2 z1 t( w1 J

  47. ! s! K  k. N- F: K- g  u- r. u6 e
  48. // SCSI读取函数(for NT/2000/XP)
    ! n: ~  h* T- m/ C
  49. String __fastcall ReadIDEDriveAsScsiDriveOnNT();
    % Z0 B* ~: D% Z. X' n* f, m
  50. //---------------------------------------------------------------------------# [2 v7 z2 |! D
  51. // ReadPhysicalDrive
    ; z* g: w' J/ |  t/ L" m; A/ r" Z
  52. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
    , T& w: F+ @+ o, Q5 P, B/ U
  53. {+ r! `5 S% }9 `1 _6 O* @
  54.    switch(Win32Platform)
    6 S' M8 m8 j: R* F
  55.    {& u5 T  y! N0 @$ o+ M
  56.        case VER_PLATFORM_WIN32_WINDOWS:0 i: o" R3 E. |8 O! H
  57.            ReadPhysicalDriveOnW9X(pSerList, pModeList);' f# k2 W3 }; w+ t! |; f& q$ G
  58.            break;  ~! k4 d, X! D) n
  59.        case VER_PLATFORM_WIN32_NT:4 _! z/ }. X8 R' A% O( ^7 o- n2 K
  60.            ReadPhysicalDriveOnNT(pSerList, pModeList);
    6 X" R: S# D( I# r: z5 |
  61.            break;
    5 G  u; k+ [8 @: i* L1 B8 E9 W
  62.        default:
    1 c, ?. }. @# E! N7 S7 ?
  63.            break;$ v" F5 S) O# ]# K; V
  64.    }
    ' g& c' \3 `2 x! X2 j' K9 J5 y  i4 e
  65. }! i; j+ j' s' r; x
  66. //---------------------------------------------------------------------------0 d/ q' \0 {. ]
  67. // ConvertToString7 q% v# `1 l# g
  68. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
    / U3 T4 V% v# E
  69. {; f& H( t) P0 B- I3 P1 G$ N; B
  70.    static char szResBuf[1024];: o$ N9 ^( ^3 R" w4 S
  71.    int nIndex = 0;& ]9 F" ]* w+ b$ g
  72.    int nPosition = 0;9 O1 W/ I3 d! D6 f/ ?2 P

  73. 0 v. u* a0 O/ O" X
  74.    // Each integer has two characters stored in it backwards
    ) V; `  H3 U' B+ C2 l
  75.    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
    ! k% P# O5 }+ i7 E: K% r, m4 c
  76.    {! L! R4 c9 U$ L$ t9 C# _
  77.        // Get high BYTE for 1st character
    8 q& p( e/ [# }( H1 b
  78.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
    $ O" \; n% s9 D
  79.        nPosition++;
    ' K7 f7 x6 Q  o* J  Q/ H$ i
  80. * _" |5 b- Y5 b% [' b
  81.        // Get low BYTE for 2nd character
    # ^$ e2 J/ A" b* }$ p. T
  82.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);9 X. c  z' e- O
  83.        nPosition++;% U4 ^% v6 U* l' M) ~  J7 V
  84.    }
    7 t6 O7 c8 o3 U
  85. , G0 `% {$ o9 J" P7 v
  86.    // End the string2 @0 J' e7 V% r8 R: D6 }
  87.    szResBuf[nPosition] = '\0';# o" ^6 p% b5 V9 z" J$ V
  88.   y# B: n! I9 t2 g& x
  89.    // Cut off the trailing blanks
    2 h/ l, ^  n- G+ O
  90.    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)* v( {; {, M2 A+ n
  91.        szResBuf[nIndex] = '\0';
    % {! {' d# V. m( L" w2 l1 S
  92. / v# P& D! j5 J1 z: W
  93.    return szResBuf;& Q; i: m2 ]; R$ b. s
  94. }
    9 o2 [  j! |# j6 K0 G3 k2 x
  95. //---------------------------------------------------------------------------
    : T$ A! O% q$ k2 k! r
  96. // Winndows NT4/2000/XP 代码
    ; u- M& Z6 ^# t* c/ `
  97. //---------------------------------------------------------------------------
    5 S" q0 P  m  N' x! @7 x
  98. // ReadPhysicalDriveOnNT
    & a4 E( P, s- l0 F8 G
  99. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList): Q+ N* g0 e( @! Z2 M% y3 T& N
  100. {7 I- q- G! u* l1 h9 m+ [$ t
  101.    // 输出参数6 b4 f) o' U1 }6 y. G2 G3 q& ~- Q
  102.    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
    / d2 [+ u9 g, U

  103. . A* X' {3 o  C: o; A, b& e& U
  104.    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
    , H+ {+ x: V% V* p3 v% J
  105.    {: U) B7 f* D7 G8 x) v, M* H
  106.        HANDLE hPhysicalDriveIOCTL;9 _( Z1 ~; C* C( T+ k, |
  107.        char szDriveName[32];
    8 I) F% r+ v& U" m3 [( }5 g

  108. 1 l9 h. I* `/ z- B, c
  109.        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);
    . O, j( P6 e# k* j7 H
  110.        hPhysicalDriveIOCTL = CreateFile(szDriveName,# {( w9 h7 @. d7 c# _
  111.                        GENERIC_READ | GENERIC_WRITE,- i( {, x" z  J
  112.                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,* T% }9 J% q7 X: |
  113.                        OPEN_EXISTING, 0, NULL);5 I- `. e* Z# X- O
  114. . O$ t- q# {' w: n! T  H
  115.        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)& ~  J- R& I6 E
  116.        {
    - \8 }( E6 o& O; N  `9 g
  117.            DWORD dwBytesReturned = 0;% k8 O! Q# L$ _
  118.            GETVERSIONOUTPARAMS gvopVersionParams;, @: U7 h5 p" P

  119. 7 r8 a; I9 x; }- _; k
  120.            // Get the version, etc of PhysicalDrive IOCTL
      w; @# r, l# P8 n/ I) k
  121.            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));! L: \6 ~, H" L
  122. 7 x4 Y% l/ C1 \2 {" j; `& g# P. H
  123.            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,2 t& H9 G% n) h; p
  124.                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
    6 b& O8 _3 S) ^8 q; G4 S
  125.                    &dwBytesReturned, NULL))4 R! E# q: q+ W. X  Y. J2 S
  126.            {; c  c* n$ c, e: w) ~
  127.                continue;
    ' _9 s  Q. R  r0 @% l. G: e
  128.            }
    , |' B$ J# j! T

  129. 4 Q  C& b, P+ P1 I, {
  130.            if(gvopVersionParams.bIDEDeviceMap > 0)
    9 }, P+ R; c/ {, m  v" ^
  131.            {
    3 N$ m5 ^3 e( q5 W. k2 G6 G
  132.                // IDE or ATAPI IDENTIFY cmd% H1 ~6 ~3 \6 h7 @( W2 d
  133.                BYTE btIDCmd = 0;
    + w' e6 I8 G0 e/ u$ g) J, L
  134.                SENDCMDINPARAMS InParams;
    2 t* t9 q5 G* B" `, U$ s
  135.                // Now, get the ID sector for all IDE devices in the system.
    / y  G: _' q) w# i; N% p' M
  136.                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
    ) @, G+ Y6 I/ b3 h% {
  137.                // otherwise use the IDE_ATA_IDENTIFY command7 B& G& x% W& e4 x7 y/ T% Z
  138.                // 具体所得结果请参考头文件中的说明  p1 d6 r/ x; q) Z) x
  139.                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?) v" `5 ~1 i* x) i1 f
  140.                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
    & c) @# L7 \4 n
  141.                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));$ {. F# c" i9 s" Y- m- A" A
  142.                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
    ; e! R- ?4 K  j9 f6 }4 ?7 `" d7 u3 q4 o
  143. + ]* o; S2 ^/ ^7 r4 L1 u& z
  144.                if(DoIdentify(hPhysicalDriveIOCTL,
    4 Y  o  Y9 x9 E
  145.                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
    4 z- ~) s2 W' |9 J
  146.                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned)). r7 a6 }; M# |
  147.                {
    7 J: P7 i) `8 k: ~
  148.                    DWORD dwDiskData[256];
    ( q' H6 g0 c2 ?0 `7 e5 B! U- E
  149.                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件6 U5 d2 G- O# {8 W% Q$ [- W# o
  150.                    char szSerialNumber[21];
    6 }. G' D$ ], Y8 R7 U0 O1 c5 h
  151.                    char szModelNumber[41];2 T! E/ w7 C# ]+ V4 s
  152. 4 w" G# E6 |, k- `
  153.                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
      C9 e+ D' X& ]
  154.                    for(int i=0; i < 256; i++), h, V+ Z1 G) j$ ]  c6 f$ J6 ?
  155.                        dwDiskData = pIDSector;
    ! I* f: d, x4 Q0 A9 P
  156.                    // 取系列号! J" M: o# ^8 f! z+ X3 p; D7 @6 |& H/ d
  157.                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));; k( C% _1 J& H5 L/ Z0 ^
  158.                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));9 T9 A# j( l7 e( s2 a

  159. 1 _$ x# P) k: M' R) e
  160.                    // 取模型号& t0 [! n( m. I$ M- }
  161.                    ZeroMemory(szModelNumber, sizeof(szModelNumber));
    . y* B) a2 o  E. F, B/ a
  162.                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));7 `% x! f- S& |" C9 U# {( s
  163. ( `$ O4 H. J0 N. n
  164.                    pSerList->Add(szSerialNumber);- w6 m1 g* l# R# L6 S1 A5 h
  165.                    pModeList->Add(szModelNumber);
    , P' d1 @; U; `$ G* {$ u/ f
  166.                }% @  J# X4 y% c4 i/ K
  167.            }* f0 R/ c, Q# y2 H
  168.            CloseHandle (hPhysicalDriveIOCTL);% Z: B1 ]; \; Z4 S2 I) ^3 t
  169.        }& _- r+ O5 g( ~; u
  170.    }& S7 K# S4 e, u# z2 H
  171. }% I% i# e4 s! s
  172. //---------------------------------------------------------------------------6 G5 m( X+ v( `, \6 E( c% J
  173. // DoIdentify5 }9 j4 i4 u# R- o- E
  174. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,4 Z, `& D' G) _- P- w8 ?
  175.              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
    : s6 t! }/ R! t' n( E4 G' v4 d5 B
  176.              PDWORD pdwBytesReturned)
    $ E9 \5 J$ o& X, d
  177. {) _3 v0 J4 K, D1 P; l4 \
  178.    // Set up data structures for IDENTIFY command.
    - q" ?; U) b* a* |0 W" F
  179.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
    7 q) v8 G$ [" E% M5 ?9 J! `
  180.    pSCIP->irDriveRegs.bFeaturesReg = 0;
    0 M3 T1 |% j7 _/ M2 K; H) K
  181.    pSCIP->irDriveRegs.bSectorCountReg  = 1;' g2 [3 f: w2 U# Y; _
  182.    pSCIP->irDriveRegs.bSectorNumberReg = 1;, @/ Y+ i" o! e4 X7 j2 `
  183.    pSCIP->irDriveRegs.bCylLowReg  = 0;4 h; r) D4 s( g/ E
  184.    pSCIP->irDriveRegs.bCylHighReg = 0;0 @6 k# G6 h4 `& _7 s) g
  185. 1 {( O+ v3 e) `3 X
  186.    // Compute the drive number.(主盘和从盘所对应的值是不一样的)
    ) e# H. E8 O. G7 s$ h% J
  187.    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;9 Q3 c2 y  O2 B) N( k- A/ c" _

  188. ) X' {) s3 e! k; t, @/ S
  189.    // The command can either be IDE identify or ATAPI identify.0 Z0 q5 S5 X) `( ^6 C$ ~
  190.    pSCIP->irDriveRegs.bCommandReg = btIDCmd;$ c7 u3 w4 G* E9 ]3 x* M
  191.    pSCIP->bDriveNumber = btDriveNum;
    / z; u& p5 L! y  o) I) m; n
  192.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;: m- W5 D4 D4 h4 M; B  o# Z
  193. ; j% |$ b8 T' i) @$ y
  194.    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,  {- X% j' G. K) _
  195.           (LPVOID)pSCIP,
    1 s4 C& [8 F( f2 Q; Q
  196.           sizeof(SENDCMDINPARAMS) - 1,9 W. n! j# U2 V
  197.           (LPVOID)pSCOP,: `- u3 ?2 x- B# j5 P+ l
  198.           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
    1 R! m' s* G3 p1 ~
  199.           pdwBytesReturned, NULL);
    & ]9 {/ C; c4 q2 |& x
  200. }: n. O  e( }) ~# C* @, d
  201. //---------------------------------------------------------------------------' ~- p6 F. y7 X, @' a
  202. // Windows 95/98/ME 代码  q0 k+ L: K( A/ }4 Z- Z
  203. //---------------------------------------------------------------------------
    ! |4 R) H# z1 w+ v, q0 f  H5 ^& s6 F
  204. // ReadPhysicalDriveOnW9X9 |5 B/ M# N7 |+ U# t/ z! k6 f
  205. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)/ q, @  z8 |" J  p4 u$ v
  206. {
    ( r& ?% q# _' w  ]% T
  207.    WORD wOutData[256];
    ' D4 h1 P5 P7 B
  208.    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
    7 S, d. Q* B; U' L0 ?5 p1 R
  209. 8 ~* c: o/ F" N' X* ?9 n4 H
  210.    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
    " L2 t. J; F: R0 K  G; P0 u( T
  211.    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以" c5 y2 k" Z$ k) J
  212.    // 避免蓝屏的出现。(期待高人能指出原因)2 D4 L( f9 \- Y" ]6 U
  213.    for(int nDrive = 0; nDrive < 8; nDrive++)
    1 H+ A+ {9 P; q# F* y. q
  214.    {9 F; I+ S. ?( W5 @5 N
  215.        WORD dwBaseAddress;
    1 r" l$ E; w5 F2 M9 z8 b1 {/ c
  216.        BYTE btMasterSlave;         // Master Or Slave5 L: V, p% i# ^+ U; W
  217.        bool bIsIDEExist;1 z  ^8 t+ e; P' b$ k8 ?) C" T- K+ B1 U
  218.        bool IsDiskExist;/ D  Z! j5 \$ ?( \6 {
  219. 7 c" I) d# P& f! z; p6 b# F
  220.        switch(nDrive / 2)
    5 x. s2 F/ [  L1 \& G; ~  @
  221.        {
    0 K/ F9 t$ L- h
  222.            case 0: dwBaseAddress = 0x01F0; break;
    $ j* L2 m. H  C& m& y1 e2 W
  223.            case 1: dwBaseAddress = 0x0170; break;
    ) s+ X# U# U1 T2 b# S  q
  224.            case 2: dwBaseAddress = 0x01E8; break;; u9 g" `& f- O8 L, i7 S
  225.            case 3: dwBaseAddress = 0x0168; break;: k* v/ T4 p3 h
  226.        }5 K- w) o( M, H/ ~8 C9 V

  227. ( d" }5 N( s5 @6 a1 J! w
  228.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);) L* m+ T  o# d8 l+ i& \
  229. " O: F4 y$ N5 l5 r  y
  230.        // 进入Ring0
    4 W' m5 d& V, C  j1 w
  231.        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
    4 x3 g# e7 @/ O
  232.                bIsIDEExist, IsDiskExist, wOutData);
    ( l' g7 E, u4 K. l
  233.    }6 T! s' h; o. |& r. Q# ?: Q" D' z

  234.   Q3 c3 E- P) g
  235.    // 开始读取' j  R9 }' q) K( ^6 p
  236.    for(int nDrive = 0; nDrive < 8; nDrive++)- q0 t# i" ?/ J5 g0 p$ _
  237.    {
    3 s) t8 y) O! l. J0 c
  238.        WORD dwBaseAddress;8 r1 |2 V% O3 \0 ~( z$ w
  239.        BYTE btMasterSlave;         // Master Or Slave
    7 S0 j' U9 @& }1 I
  240.        bool bIsIDEExist;
    # Y7 S7 |; k: X$ F5 |* C
  241.        bool bIsDiskExist;
    4 S: L1 Y. d; ~: b  I9 z
  242.        switch(nDrive / 2)
    . \* l% D1 |5 G5 m# _- e
  243.        {4 Z. P3 z$ L! u7 @+ e
  244.            case 0: dwBaseAddress = 0x01F0; break;
    ( C' O3 d8 H2 S$ g, E7 X
  245.            case 1: dwBaseAddress = 0x0170; break;
    $ B, d, `- g4 Q, W
  246.            case 2: dwBaseAddress = 0x01E8; break;
    / j! }6 V! c  }  Q4 s2 T7 k
  247.            case 3: dwBaseAddress = 0x0168; break;
    - Y. d, `  L: i
  248.        }
    & ?9 @6 s; X- M6 y# ~, u9 f# |

  249. $ W5 T+ P1 {* Q
  250.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);7 N' \: ^6 I3 X1 v. g! ~4 ?  }
  251. * a  [1 n" ~/ w  g, A# ]- ?
  252.        // 进入Ring0
    ; I' D! Z: }4 v
  253.        bIsIDEExist  = false;
    - q: f% c: A8 T# i. @4 x
  254.        bIsDiskExist = false;. |4 U, J2 ]# r/ j5 d2 A8 F
  255.        ZeroMemory(wOutData, sizeof(wOutData));$ `2 |& E; t: _1 s* P% R( H

  256. ) O3 ]' x- O- ?0 ]' F# u4 R
  257.        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
    " {, K4 z6 N  b/ ]* P* Z6 n) r* d8 ~
  258.                bIsIDEExist, bIsDiskExist, wOutData);) r5 U  j0 V* a2 X- A- F

  259. : z3 V& H& D7 Y4 K  e  A
  260.        if(bIsIDEExist && bIsDiskExist)
    * Y2 h/ D5 ~6 g% t' M  `! ?& Z
  261.        {
    2 _$ w2 J4 B6 Q4 ~/ f6 u8 t7 W7 u
  262.            DWORD dwDiskData[256];9 `8 e9 J1 k/ ^: ?
  263.            char  szSerialNumber[21];
    ) Y& o. r! B7 _$ c0 F9 a
  264.            char  szModelNumber[41];+ Y3 \5 G% c! R; c& F% s! h) @

  265. " ]8 E+ t" Q0 A: I* s( ]- U; E
  266.            for(int k=0; k < 256; k++)
    " `  q/ K6 }, N! ]* N1 ]! `
  267.                dwDiskData[k] = wOutData[k];; T5 G8 ^( h5 w8 B- D# n
  268. 9 C0 H( c) h. r$ T* U9 r
  269.            // 取系列号
    + q+ `" s  D3 f5 Z2 t6 M
  270.            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));4 M+ J. ]6 D7 i9 C( d
  271.            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
    $ T5 o- F) j. o$ K* Q6 k6 x
  272. ) }0 K' }8 \' l3 E
  273.            // 取模型号; D- k9 {* v- N
  274.            ZeroMemory(szModelNumber, sizeof(szModelNumber));
    , J, `( _: L0 O+ |4 j0 a9 x3 f8 o
  275.            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
    5 x( w3 B6 {6 w4 \; h) \

  276. $ G7 A. {2 N6 [; p6 v( u
  277.            pSerList->Add(szSerialNumber);- a# E1 c5 n8 N$ ^1 T0 N
  278.            pModeList->Add(szModelNumber);4 M* K- c3 h+ k& g
  279.        }1 d5 w5 l, v/ z1 \; A5 Y
  280.    }) E6 F* H' w7 v" G+ d
  281.    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);* q/ L7 o- I$ a% J$ X
  282. }
    ( j* _. T- p" J5 @
  283. //---------------------------------------------------------------------------1 s6 p6 p& C" Q& C* C! Z2 j' ^
  284. // ReadPhysicalDriveOnW9X_Ring0()' r+ L* O: Y5 M
  285. //9 a0 u4 {; i6 j0 _; s" L! j$ Q
  286. // dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h/ F5 a3 D2 |+ E' A0 X/ O- h/ k1 [
  287. // btMasterSlave = Master(0xA0) Or Slave(0xB0)
    & z0 L% J/ A# J2 }9 x; U
  288. //---------------------------------------------------------------------------. \! r; f. t5 z/ O9 }+ `
  289. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
    - F4 H# U5 A5 O/ h3 F) [3 ]5 c
  290.        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
    ) X  [% w4 Q+ {8 C) H' ~! i5 ^( a) a
  291. {: L: b, D* Z: j9 O
  292.    BYTE  btIDTR1[6];! S7 z* k: c% b5 V7 @- h! K* Z, r2 W
  293.    DWORD dwOldExceptionHook;% E# N1 e# v6 q& N; y$ e+ h
  294.    const int nHookExceptionNo = 5;
    3 L) J3 S7 O/ }1 W9 m

  295. / n% f7 K& r6 j* r
  296.    BYTE  btIsIDEExist = 0;8 }+ y4 S& F+ {+ {; @  s
  297.    BYTE  btIsDiskExist = 0;9 S8 B! }# |4 b2 S
  298.    WORD  wOutDataBuf[256];0 S# a! w9 J" T( O& q5 [" w% g% @
  299. $ P1 e6 n) S2 S! c8 v
  300.    BYTE  btIsFirst = (BYTE)bIsFirst;
    , o# M# m, o7 e1 s: N7 W4 \$ z; @7 x

  301. % k' ~! e6 x% E) }- R' R& G
  302.    const BYTE btBit00 = 0x01;
    3 F* u. E: ^, W
  303.    // const BYTE btBit02 = 0x04;5 h% I- E" I1 Z4 R; k
  304.    const BYTE btBit06 = 0x40;8 g; a7 v" h8 b( f. L! B
  305.    const BYTE btBit07 = 0x80;
    0 B2 s4 m# e" O3 ]& Z- ^, \2 L
  306.    // const BYTE btERR  = btBit00;) e/ s2 V8 e: G% Z. V
  307.    const BYTE btBusy = btBit07;
    ( z+ l" P# l# h2 h
  308.    const BYTE btAtaCmd   = 0xEC;- p. z* e" O6 W1 p
  309.    const BYTE btAtapiCmd = 0xA1;( Q, W: i; l  g

  310. 7 g! V* C5 D& L( s8 E
  311.    __asm6 P' \7 z: W, U0 x, l
  312.    {; ~# J8 C+ ?1 S; c
  313.        // 必须先执行这条语句
    2 C9 T( ~% X# l+ o. S: n
  314.        JMP EnterRing0
    : ~# b8 {8 z8 I* m0 l) n

  315.   M# f3 D1 ~* l* J4 {6 l
  316.        // 定义过程! W5 g8 [' ]1 M5 n* y
  317.        // 等待IDE设备直到其不为忙为止$ v4 ~' `. M( ?% Z
  318.        WaitWhileBusy proc% a; P! v, z5 c6 Q

  319. , I2 D/ P% \% u4 b3 c! Z- S1 g
  320.        MOV  EBX, 100000
    / z+ B% {; u; Q+ C# J" d6 X
  321.        MOV  DX, dwBaseAddress
    - O9 g' u4 X* @8 n8 v" q0 _
  322.        ADD  DX, 7& s1 t% [3 U: ?6 I
  323.   X4 f; P! n. P, A% o9 ~9 g2 |  X
  324.        LoopWhileBusy:+ R9 R4 E: x# ^
  325. 3 b! k  r. ]" X: t: ]: W
  326.        DEC  EBX8 m3 ^9 X6 \1 c. y3 p  Y& o
  327.        CMP  EBX, 0
    8 p% @1 k! S8 N$ E/ `) q# u  }
  328.        JZ   Timeout) m; T9 |2 }  F, I6 q0 G
  329.        in   AL, DX
    " Y; R, i# o- [; ]* m+ }( F
  330.        TEST AL, btBusy5 E2 f: O0 D& w, ]5 {5 E7 N
  331.        JNZ  LoopWhileBusy9 Z8 m6 _( A2 H$ V3 e
  332.        JMP  DriveReady
    / H$ k, f6 d) V! t  b

  333. # R3 m+ L* w1 `8 s! W- D* [
  334.        // 超时,直接退出
    ) i# ]+ U' u9 E; T3 @
  335.        Timeout:
    3 Q6 F0 w: X1 H
  336.        JMP  LeaveRing0
    9 P9 W9 Y) ~. r$ p3 u; x& @
  337.        DriveReady:
    2 o, ?# v& D  ^5 ?- J  n
  338.        RET! e3 O+ G) E  M( S- Z( `
  339.        ENDP   // End of WaitWhileBusy Procedure+ {5 D& f0 C/ X# {" z+ [- ?

  340.   X! {) ~7 w: J4 ]
  341.        // 设置主盘和从盘标志$ [% V) i' y4 J; ^  V/ ]: v
  342.        SelectDevice proc% A1 E% X& c- R" I5 U" k" a+ Z" I
  343. # r0 \* L; F2 n( E9 _- r
  344.        MOV  DX, dwBaseAddress
    ( }( c, K# R. S+ \0 }
  345.        ADD  DX, 6
    0 f! f$ N) L' W0 F% v
  346.        MOV  AL, btMasterSlave0 {& X" G3 c9 r3 [

  347. # T" m6 g* e7 J
  348.        out  DX, AL: }" z& X. V6 {3 [6 _( W
  349.        RET% V# j5 H) c5 r) b3 F& |1 \# q3 b

  350. % k& L6 b2 Q! \, K, C" ?: {  y
  351.        ENDP  // End of SelectDevice Procedure. G6 T% |9 b* A+ p
  352. 6 p  n/ P, s6 S* z% ]( ^! [
  353.        // 向IDE设备发送存取指令5 w- S; Z6 L) a6 P8 Y- y7 Z4 w
  354.        SendCmd proc
    # @/ |8 H! I6 ^. `0 `  B# g( R4 X

  355. ' a: C2 q% x' Q: r7 V
  356.        MOV DX, dwBaseAddress) V  }# P6 B+ G/ @9 l4 S* A$ S
  357.        ADD DX, 7
    ' s. i. d+ a, n  Z3 D% \' x
  358.        MOV AL, BL // BL是主从盘标识,在过程外设置
    + z; i, n/ B7 ]5 a0 s3 N
  359.        out DX, AL4 q( X) B, \- D/ z  ~
  360.        RET9 k( l8 i0 `- p( c& S+ w1 j5 d, W
  361.        ENDP  // End of SendCmd Procedure9 Y0 ^/ x* ]9 N" a' D( d

  362. 7 I3 g. M3 |; x
  363.        // Ring0代码3 m7 D8 f2 A2 L0 F& X- H0 c6 _& i
  364.        Ring0Proc:
    / u9 J& ~% j3 t* H" Q) L6 m6 }8 ?# Z
  365.        PUSHAD8 o) p! g& i, F: e& R* t& d7 g
  366.        // 查询IDE设备是否存在
    ! @, \' _) z, ?! H
  367.        MOV DX, dwBaseAddress4 u& K+ `5 x8 r+ `! {  z5 O
  368.        ADD DX, 7' y3 O7 W4 E' L" G4 E( i
  369.        in  AL,DX& m. n8 c9 Y/ i- Y& z8 h6 a8 ?; G

  370.   L$ u) q- r7 r! T0 B" c4 f  s
  371.        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
    9 i- g3 x$ m2 J; w% y& c
  372.        CMP AL,0xFF
    7 Q* C7 q0 ^! O
  373.        JZ  LeaveRing03 s+ }' g2 o# i! L% K( F4 [
  374.        CMP AL, 0x7F
    ) ?2 g$ z$ x: s7 j) o( X6 _4 A% X
  375.        JZ  LeaveRing0
    : h; |; `7 n: t9 j7 `$ D
  376. % K; K! c9 ?: S% b4 ?7 _% T
  377.        // 设置IDE设备存在标志; f( w/ i$ T4 K8 w0 o# i' [
  378.        MOV btIsIDEExist, 1
    , ^6 Y) p5 }! I! ^; e& U2 {

  379. ( K3 a9 h5 w* B4 A" E  n
  380.        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)3 ]" G7 G4 I4 F8 L% u+ g
  381.        CALL WaitWhileBusy( {* J5 j/ g* ?  r$ b# }
  382.        CALL SelectDevice+ {+ d# z9 X( r4 g8 A

  383. , k' U1 T2 w1 [$ c0 y/ t& D
  384.        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
    ' Y- t) I' z, f, q" ?( r  g' i
  385.        CMP  btIsFirst, 1
    ; `) O" V" t# b* J1 {1 L
  386.        JZ   LeaveRing0
    ( D1 H; V8 R1 @& k
  387. / G! _3 N% Y" [8 J& D3 c
  388.        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???0 u6 |- l, b! Y
  389.        CALL WaitWhileBusy" p. U- E' f9 J" s" R! r

  390. " t8 }2 W/ N7 p
  391.        // AL的值等于cBit06时,不存在驱动器,直接返回
    + x+ w$ h; e! l! i8 `
  392.        TEST AL, btBit06, ?( d* c& g7 t6 N( |
  393.        JZ   LeaveRing0
    % n" U6 K, r& p6 O6 U
  394. 6 M& w5 d  R; E9 e
  395.        // 设置驱动器存在标志8 T. `6 ^8 C- i0 P2 m$ V& K
  396.        MOV  btIsDiskExist, 1
    2 b; p. l: y+ J( k
  397. : s: Z% U# g- o  M
  398.        // 发送存取端口命令$ n6 s  A! q) t; Z* s) a* x
  399.        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,  V, \, [. g% Z% m+ G+ n
  400.        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
    2 T3 Z" T9 e, c. M4 v
  401.        CALL WaitWhileBusy- t& F3 `9 ]6 l# x
  402.        CALL SelectDevice    // 设置主从盘标识
    6 O9 @* n5 A7 _# }. V" d
  403.        MOV  BL, btAtaCmd      // 发送读取命令6 l, H' F1 L2 b9 L& o# f
  404.        CALL SendCmd5 ?; f+ O/ H" l7 ]
  405.        CALL WaitWhileBusy
    4 {* d: M" z1 i- n. b6 u4 X
  406. 8 S( ?+ M& r6 t2 s& s, |
  407.        // 检查是否出错
    0 M6 ^7 H& p6 G* U  U0 Z9 B( o+ G! f
  408.        MOV  DX, dwBaseAddress
    2 }/ j4 U' {) ]  n1 t9 E
  409.        ADD  DX, 7  j1 `! n8 u* G+ i1 F2 B9 H

  410.   }) G, R( u/ {/ }. G
  411.        in   AL, DX( Z7 a8 L# E; A1 ?2 {
  412. # e2 g3 c' R. N; J
  413.        TEST AL, btBit00. G9 }6 i, z# F3 p
  414.        JZ   RetrieveInfo   // 没有错误时则读数据
    # S, `: t0 b) h' m2 A
  415. ' ~9 R1 d& A5 e: u$ D# I
  416.        // 如果出错,则进一步尝试使用ATAPI设备命令+ C; ~2 y4 f* z- u0 }
  417.        CALL WaitWhileBusy$ Z! Z! J7 p% {, y
  418.        CALL SelectDevice% k9 n1 w3 i, M
  419.        MOV  BL, btAtapiCmd' ~7 K) w, o( q- x
  420.        CALL SendCmd$ g# C4 G- W4 m/ \  i! x
  421.        CALL WaitWhileBusy
    ' L' S3 e: d7 L& B- o

  422. # ^/ j5 D- J5 Y8 I
  423.        // 检查是否还出错
      ?  I# R) k' {  a
  424.        MOV  DX, dwBaseAddress9 P) V. [$ N1 Z. R- h' m* F' W
  425.        ADD  DX, 7
    4 S% o7 \$ _$ [8 M
  426.        in   AL, DX
    - q- O* B6 K# i7 e' M( N
  427.        TEST AL, btBit00
    ( \/ l- V- L" n! W1 Y) u! p* M
  428.        JZ   RetrieveInfo   // 没有错误时则读数据
    5 j4 R& N& f! Z+ n" D1 r5 |- V
  429.        JMP  LeaveRing0     // 如果还是出错,直接返回
    # V- R( A0 }, Y0 j
  430. 6 Q, Z  b  M+ _; e" E( N0 \
  431.        // 读取数据
    6 G8 N/ x- n+ J5 e, M6 X
  432.        RetrieveInfo:4 q/ w  H4 u3 N4 w

  433. 8 @. e8 u: i1 T. `& z) o
  434.        LEA  EDI, wOutDataBuf
    % _- J# ?( r0 C0 _4 E$ r$ C8 `, s
  435.        MOV  ECX, 256
    ) [, [* l# ?' L7 T/ I' n' f
  436.        MOV  DX, dwBaseAddress
    ( e& }; o. t  L, f( d
  437.        CLD
    & Y. v. `: ^- h/ s) f3 d( D9 Y2 D- s

  438. 5 \' I( |. ~9 j; T1 O$ s6 G0 `, l
  439.        REP  INSW8 }: c- D7 C- c* K) k; W& Y% v. N9 g

  440. ) W! G& H# T3 }# u6 t0 X4 J
  441.        // 退出Ring0代码; |3 b, p; v; v2 [
  442.        LeaveRing0:
    % B; p# e5 E! W
  443. 3 |% o1 V; R' \& a0 q0 O
  444.        POPAD
    : f: k- X4 Z+ j
  445.        IRETD
    " A' \% y$ {$ h8 t* y! P6 A& W" j/ F

  446. / B% ~+ b5 A& q* _
  447.        // 激活Ring0代码
    ' U' U- c# @$ @1 `6 I2 j
  448.        EnterRing0:6 u) h6 F7 l$ G  U5 M

  449. 9 o$ Z' }" L8 _1 w4 S* A% K
  450.        // 修改中断门" z; e0 N8 `8 J+ X
  451.        SIDT FWORD PTR btIDTR1) w5 [/ [1 W% E/ h& A7 i  k
  452.        MOV EAX, DWORD PTR btIDTR1 + 02h; O% x4 A5 C7 P3 z% `3 H
  453.        ADD EAX, nHookExceptionNo * 08h + 04h
    ( l; W1 ?  L# o+ k& e4 \
  454.        CLI
    8 R+ Q" ]; D: F9 Z
  455. / W! M3 J$ _4 Q& U: i0 ?
  456.        // 保存原异常处理例程入口
    4 o2 y  c# [3 J8 b1 v
  457.        MOV ECX, DWORD PTR [EAX]9 u* W! F3 l7 U/ R, K. k" W
  458.        MOV CX, WORD PTR [EAX-04h]# p! |3 j$ |3 A3 r( y9 x
  459.        MOV dwOldExceptionHook, ECX
    9 d1 M0 n! M$ H% [6 N
  460. 8 \& L( R, q7 ?# @
  461.        // 指定新入口5 i# p  D" Q" r, m# N6 x. D
  462.        LEA EBX, Ring0Proc
    - i* q" e* K  k
  463.        MOV WORD PTR [EAX-04h],BX
    . u0 U& [( n: Q4 P* G0 o
  464.        SHR EBX, 10h1 _; N6 P0 p( F* y  J
  465.        MOV WORD PTR[EAX+02h], BX
    * }4 N" b) b5 H' m: e* M. g3 ]

  466. ! w( N0 D. B5 j: N9 W
  467.        // 激活Ring0代码* F: e5 }; W, K& v; i$ L  \" D
  468.        INT nHookExceptionNo
    9 s' U( u5 c$ h5 E( y- j

  469. 5 r9 |- P9 Y. t5 ~6 Q
  470.        // 复原入口
    + [& t' U' K* P  S4 w1 ^
  471.        MOV ECX,dwOldExceptionHook
    . N& y0 d$ t+ y+ g, E* ?
  472.        MOV WORD PTR[EAX-04h], CX0 i: G2 `3 J) s) u5 T' N
  473.        SHR ECX,10h
    1 ?/ w" X6 w7 D, w7 M/ Y
  474.        MOV WORD PTR[EAX+02h], CX
    , b0 p% {2 S: E# l
  475.        STI8 F, u* Z6 P4 M2 W6 W& K
  476.    }# b" o! Z/ ^5 C4 V
  477.    if(!bIsFirst)3 O2 d$ W  k# I5 P9 }! R
  478.    {, O6 h2 Y: c# R8 p: C! k
  479.        bIsIDEExist  = (bool)btIsIDEExist;/ K9 S) g4 G+ j
  480.        bIsDiskExist = (bool)btIsDiskExist;& G( x5 n! n" H2 w; g/ v
  481.        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));' m$ d* o/ c. N/ ^  \/ b
  482.    }2 {- L) B4 }' |8 B$ y- U& R( D% u
  483. }7 ?5 a; m0 Y% Y' b, C
  484. //---------------------------------------------------------------------------6 m6 d& O! z  N! {
  485. // 调用方法:6 B) J, S4 W9 \" U- V0 q
  486. void __fastcall TForm1::Button1Click(TObject *Sender)
    % D" O$ ^2 j" `% W/ N/ ^- O3 t
  487. {
    2 Q0 \* R: W, C0 H+ u- X
  488.    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);/ s) T# \( ^& u9 ?
  489. }
复制代码
发表于 2005-8-15 01:00:45 | 显示全部楼层
晕乎乎。。。怎么看8 洞阿
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-8-9 01:38 , Processed in 0.035151 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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