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

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

[复制链接]
发表于 2005-8-11 11:42:04 | 显示全部楼层 |阅读模式
  1. #include <WinIOCtl.h>5 |6 H: N" P" I- |- v* X
  2. #include <stdio.h>" Q- L- w2 k$ P( F! f

  3. ( h+ A& f; M8 s' i# w& l0 I" J5 L
  4. #pragma inline) `, g8 z0 J# M9 V
  5. //---------------------------------------------------------------------------! x" m- J5 {* b0 f$ w
  6. // IDE NT/2000/XP专用变量
    % h7 r" W6 u7 b4 X
  7. #define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS! d& ~" @* @0 U! h5 {1 s
  8. #define DFP_GET_VERSION         SMART_GET_VERSION; J' q% e4 F4 f; @% N) A9 X
  9. #define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
      g9 v/ e  B& ]
  10. #define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA( j* j6 \4 j, c# U4 ~
  11. # u& @: A5 o9 C$ o9 B% h
  12. const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令+ v" g  O+ C  U8 W' v* ]
  13. const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令
    5 ?; P9 f8 p8 C
  14. 5 V* V+ ^$ Z& }
  15. const int MAX_IDE_DRIVES = 4;
    # u* N- h5 t) |& j4 A
  16. 3 Z- ]5 E- i$ s" R* c7 F/ z
  17. // SCSI专用变量- D* M' P& e) Z/ Q
  18. const DWORD FILE_DEVICE_SCSI             = 0x0000001B;: p8 `; u  O1 J8 Q! I
  19. const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
    ) \2 r: }4 A7 G$ }" O9 h( C
  20. const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
    ; w6 E! q/ b6 _9 d, {
  21. const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;
    , h! X& `, [% b$ A( F5 Q

  22. , ^; ]; c$ V9 A. z  V
  23. typedef struct _SRB_IO_CONTROL
    . f. T1 `4 ~* G3 x* ~. j) ?/ e
  24. {
    ' C; \2 C- g/ }
  25.    ULONG HeaderLength;  U1 R3 S! f- @6 m9 T/ k
  26.    UCHAR Signature[8];$ b* R/ j1 {3 }% n
  27.    ULONG Timeout;
    8 y8 F! M$ p, N( [0 Z
  28.    ULONG ControlCode;6 ~5 d7 @) G3 J4 o
  29.    ULONG ReturnCode;# ]0 q1 X4 \# H6 Q7 D
  30.    ULONG Length;' e" S9 F' {. t, l0 o
  31. }SRB_IO_CONTROL, *PSRB_IO_CONTROL;
    $ P1 g. b. n4 A. Q: j7 U& h2 ~
  32. $ x# v. w1 ^* C0 A- a* M  V1 l
  33. // 读取的主函数1 D! Z; s3 Z+ M  f7 W
  34. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);3 g9 a" h; [& C

  35. + @9 `$ I  |, \( a% m! [! R* M
  36. // 辅助函数" F* b% @6 f4 N4 {5 U# R0 K
  37. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);  K' S8 O7 p8 r6 ?, l1 [9 |
  38. // NT/2000/XP函数
    7 {, S* R4 B4 W9 o5 z% Z0 D
  39. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
    ) ]. @. N- }2 @1 d
  40. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
    / z" Q1 H: S- i; w
  41.        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,& N0 q& O4 E. B! I
  42.        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
    ' j4 ^3 n% k- ?7 j  ^2 G) u0 i
  43. // Windows 9X函数; g4 U$ n5 ?4 E$ k' ^
  44. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);7 }7 v7 n$ F: Y9 `# Q
  45. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
    ! u- n0 z& j/ f/ {7 S
  46.        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);* b* I$ U! [; L
  47.   a1 g2 O) O  p0 A% e" n  x
  48. // SCSI读取函数(for NT/2000/XP)$ m! b. l* W  c& i
  49. String __fastcall ReadIDEDriveAsScsiDriveOnNT();
    6 o' k( h2 u2 |4 h& N6 s# ]3 p  p
  50. //---------------------------------------------------------------------------
    ! L* K6 \1 u4 l; h( a# D" x7 ]+ H
  51. // ReadPhysicalDrive1 ^* A* _4 l6 U0 G3 {
  52. void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
    6 D# o: K- I3 v8 X  y" L
  53. {; n+ K/ I  K+ r- W9 D; j8 a
  54.    switch(Win32Platform)
    ( L  C* }3 ?- @) s+ G, D+ d! Z
  55.    {& {) d3 @8 ~( }* X7 W' ^: V
  56.        case VER_PLATFORM_WIN32_WINDOWS:0 d8 v. V+ Q0 }5 C5 d$ a% O! C
  57.            ReadPhysicalDriveOnW9X(pSerList, pModeList);0 X6 q( Q5 O/ s) d0 I
  58.            break;
    ! Q' z3 Q6 {& c( `
  59.        case VER_PLATFORM_WIN32_NT:+ S6 d% X! J0 s2 \' J
  60.            ReadPhysicalDriveOnNT(pSerList, pModeList);
    * q! E$ L& B" r  l) G/ E
  61.            break;- G9 }2 z1 N' T$ K/ b7 K
  62.        default:
    * G9 D6 ?! j. V3 m
  63.            break;% C( `" v: G% J) C& Q
  64.    }
    % ~; u3 J% ?8 A5 k! n9 r; N
  65. }* e$ {  N0 I% I/ n& ^
  66. //---------------------------------------------------------------------------# N$ S) I& r" H1 x
  67. // ConvertToString
    . j& T+ e, n) @% b# r
  68. char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)9 @; {. j! o9 |9 k4 }
  69. {
    : V7 z  J* e1 }  V; p( W+ O- T5 s4 [
  70.    static char szResBuf[1024];9 x! Z9 m: y+ ~; ?# g
  71.    int nIndex = 0;
    7 j1 q# g$ ~5 c. ^1 \" z
  72.    int nPosition = 0;5 {% y; Q8 B- R+ g" M* g) m& z

  73. 9 m' A3 M. E$ q
  74.    // Each integer has two characters stored in it backwards
    1 C+ D7 n7 c: r- I# }4 l
  75.    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
    5 b1 o/ b0 j5 W4 Q
  76.    {: j2 |# x0 S; i5 k1 P0 _+ X
  77.        // Get high BYTE for 1st character) G' P: k: ?8 ^; Y. V$ a9 L# [
  78.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
    5 {. d' L, O, B$ g$ v
  79.        nPosition++;
    5 U$ W' T9 M4 U2 H6 J9 ~7 T' J
  80. 0 U- `+ x. d4 l6 b3 z# x4 {
  81.        // Get low BYTE for 2nd character
    & j) p- _9 D+ H( z/ R1 E
  82.        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);# R4 K/ R( ?0 j, Y7 o
  83.        nPosition++;
    6 b' Q* A. e0 b4 l* T1 K
  84.    }1 q3 r7 X' H2 P7 G$ a( c' k
  85. ! R& t* C9 d' H' w2 p& s, d7 u; |
  86.    // End the string
    8 x9 V$ r6 j2 j# F  `. p& D
  87.    szResBuf[nPosition] = '\0';
    9 [* R/ t" E% E) F8 C* V
  88. # |. k/ g# b) q: S# }2 d
  89.    // Cut off the trailing blanks
    9 I# U" ]; n: {' G8 a# m
  90.    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
    9 e/ K. X% H1 w
  91.        szResBuf[nIndex] = '\0';7 ~/ p7 I- r! W

  92. / R1 H0 W1 V. y7 J7 j) g
  93.    return szResBuf;
    7 l- Y4 M9 k3 o* k) V) f
  94. }
    ( f: e/ n( `& k( T  f
  95. //---------------------------------------------------------------------------0 V3 s( k% a+ q9 G. Y
  96. // Winndows NT4/2000/XP 代码. e/ `, v- o0 W7 X% _( s% ~0 L
  97. //---------------------------------------------------------------------------" |$ Q- T7 r  W4 V' q
  98. // ReadPhysicalDriveOnNT
    ( k9 G* K3 x* a- W% d
  99. void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
    ; l# H* {) U/ y& |; a. O
  100. {  R( W+ K% v- p
  101.    // 输出参数
    : b3 W1 M; F& V3 y. @) I6 }/ Z
  102.    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
    . j# |' F5 ~$ S/ r: t1 M9 W  B

  103. 2 L# a9 A$ G7 m1 K, C0 {
  104.    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)% S" A7 Y: M( A" ~+ r7 W
  105.    {7 @+ u/ S# m: E* z. d
  106.        HANDLE hPhysicalDriveIOCTL;* W# z; Y, W6 o$ @
  107.        char szDriveName[32];' ]3 @' e# F7 ?9 t3 p, q, H

  108. # W, I2 F$ ]- A5 k5 ^
  109.        sprintf(szDriveName, "\\\\.\\PhysicalDrive%d", nDrive);" |# r! Q, g" s/ ?6 T
  110.        hPhysicalDriveIOCTL = CreateFile(szDriveName,& ~3 j, K& v( U+ W4 p
  111.                        GENERIC_READ | GENERIC_WRITE,
    / e/ m& k0 b8 q: O2 a" c  X
  112.                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,* \: W! }4 s8 D2 d: b  |; c; G
  113.                        OPEN_EXISTING, 0, NULL);6 R, p, c7 ]7 ^) {* q

  114.   y  s1 F2 d1 K
  115.        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
    # B8 @, l* J  I, B8 \; B
  116.        {
    6 S/ x  \& b$ E/ r( ~
  117.            DWORD dwBytesReturned = 0;/ f1 R. s& X9 N' q
  118.            GETVERSIONOUTPARAMS gvopVersionParams;4 E- I1 J$ k- q

  119. 1 a1 M% Z& L2 E- r# V! `
  120.            // Get the version, etc of PhysicalDrive IOCTL# y* ?+ M$ K# a, e( w1 q
  121.            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));5 h4 A; `3 T. z' C7 h9 Q9 G
  122. 4 v% [* B8 F" z; _0 I- k; r
  123.            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
    & D4 C% c6 ~; P0 j! [* }3 O' u$ T
  124.                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
      I# D, m$ v5 w2 B
  125.                    &dwBytesReturned, NULL)): \! M* {; ?0 g) s) |% Z
  126.            {, N7 ]) O2 {% x3 L8 R6 W* z+ e: W
  127.                continue;6 X1 x- J# c9 f% z; V
  128.            }
    8 ^/ l. A! \: ^0 b$ i7 b/ @! n

  129. % U, f4 D: V" N" N  R: r9 D
  130.            if(gvopVersionParams.bIDEDeviceMap > 0)' I/ |% _8 Z; E, [; U  V3 l2 l0 ?
  131.            {
    $ H1 y5 b! |6 A% \- a0 R
  132.                // IDE or ATAPI IDENTIFY cmd
    ( |4 Y. `2 g6 e* r, D/ k8 M, Z7 f
  133.                BYTE btIDCmd = 0;
    4 p4 p* ?' w( g1 G- h1 v  b# |' j
  134.                SENDCMDINPARAMS InParams;
    $ o! \( B$ r* P" _1 K7 j% S
  135.                // Now, get the ID sector for all IDE devices in the system.
    . W2 g% H. p- v2 Z) Y) @) ?
  136.                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,4 y4 \1 U* y5 ~
  137.                // otherwise use the IDE_ATA_IDENTIFY command
    2 n  F( @2 m4 o5 k; x/ U
  138.                // 具体所得结果请参考头文件中的说明
    : Q' c. T+ ]+ F6 Q8 |& ]  \* ~
  139.                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?+ v5 n0 g1 w7 E; I! `6 d2 n) H
  140.                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
      U9 o3 B+ i; o9 x
  141.                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
    ; z" g0 L' C& {* I1 S/ \
  142.                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));
    + l& i' o. P8 I: e6 A

  143. ' @# S/ M6 t( P! h( k7 `
  144.                if(DoIdentify(hPhysicalDriveIOCTL,# g0 b) r7 T" b& H) w( s
  145.                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,6 i, x1 Z% |2 \
  146.                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
    * \6 J* f& B& q7 U" h1 V
  147.                {
    2 |5 P+ W' v: @% G- V8 H
  148.                    DWORD dwDiskData[256];- v4 s* I8 r$ H- r, O9 q
  149.                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
    3 x: N8 W# o8 R6 M. U
  150.                    char szSerialNumber[21];8 w9 _; ]& q! S. ~
  151.                    char szModelNumber[41];5 ]1 l  o  A3 b2 m7 f3 N1 p5 `

  152. ( B/ [2 m1 f8 n* E% |
  153.                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;$ |0 [2 C2 l, O4 y/ b7 P' l' M
  154.                    for(int i=0; i < 256; i++)/ \/ |" x4 T8 I+ ?5 w
  155.                        dwDiskData = pIDSector;  v5 k- t* @& L4 p* K/ @. H
  156.                    // 取系列号
    $ U4 F' x  _8 o1 I0 T# ~  V  B
  157.                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));4 }& O' Q. a6 z2 F. \7 K8 C
  158.                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));' u- B7 Y0 ]- Q* U4 Z% ^2 X/ R+ u

  159. 4 R- n1 z/ t$ U
  160.                    // 取模型号/ t3 H3 N5 }9 }, b
  161.                    ZeroMemory(szModelNumber, sizeof(szModelNumber));
    7 i7 l7 W" p$ w! X3 E; k* h
  162.                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
    ! `. x  N. I6 C- @; _
  163. 2 o! D* z- r' l1 g& w/ x
  164.                    pSerList->Add(szSerialNumber);" h; I( R' I: [
  165.                    pModeList->Add(szModelNumber);' }( m7 d9 F- s4 L3 Q: u, D
  166.                }
    0 f6 H# G  J/ W6 i6 _8 b# m! y1 `
  167.            }' R, k, a* e# b
  168.            CloseHandle (hPhysicalDriveIOCTL);4 a4 n& I9 u' a# v2 s
  169.        }
    % U5 T6 @. N% x' M5 \$ ^
  170.    }8 v4 E- I" Y+ G, }
  171. }2 v7 L. m: l6 k6 T+ W: z5 L; X  m$ b
  172. //---------------------------------------------------------------------------6 r- ?9 E) Q$ J+ s: J( q
  173. // DoIdentify6 u( k) b. ^+ c1 d9 s' F
  174. bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,3 O& ^) L1 c& W8 l1 }( K
  175.              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
    % K+ S3 y4 s/ L4 u) }
  176.              PDWORD pdwBytesReturned)
      Q8 f" \: U5 J- x1 `" `- P
  177. {$ e6 h; I6 H4 g0 p; Z1 h( v
  178.    // Set up data structures for IDENTIFY command.! m  w" X: e. T8 z3 f" c/ Y
  179.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;6 O+ \8 u, [3 s+ ~- _4 F4 C8 f/ L
  180.    pSCIP->irDriveRegs.bFeaturesReg = 0;
    0 U  B7 f7 _% ]6 c8 \
  181.    pSCIP->irDriveRegs.bSectorCountReg  = 1;' l, A* J% V, d" R. A
  182.    pSCIP->irDriveRegs.bSectorNumberReg = 1;
    ( l; Q. |5 @: U5 W& o
  183.    pSCIP->irDriveRegs.bCylLowReg  = 0;3 q$ @# e; k7 D7 N; f2 p8 [9 T
  184.    pSCIP->irDriveRegs.bCylHighReg = 0;
    3 B9 ^6 \2 Q9 m7 d" F

  185. 8 q9 B3 n, E% R" K/ H, `
  186.    // Compute the drive number.(主盘和从盘所对应的值是不一样的)# \$ |% a* O6 r; ]0 f
  187.    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
    9 @4 k# G& s' \+ r7 n/ S

  188. 5 h# v: O+ {6 ~6 A
  189.    // The command can either be IDE identify or ATAPI identify.8 R3 k9 e9 I. X
  190.    pSCIP->irDriveRegs.bCommandReg = btIDCmd;
    & @' i8 C0 K  g: v( s" c  F8 I! r
  191.    pSCIP->bDriveNumber = btDriveNum;
    . d5 _8 }* t! F
  192.    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;% j3 P1 Y# K- m* [! x5 b. u" @
  193. 0 g! x& L. y/ w& S3 u
  194.    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,1 e6 X8 {& p5 Y; @1 R; Z) I9 ~4 T
  195.           (LPVOID)pSCIP,
    + [" ~9 {2 A3 C1 k( y
  196.           sizeof(SENDCMDINPARAMS) - 1,% S6 @$ g% S; L' a  @9 j
  197.           (LPVOID)pSCOP,7 f( B7 V. q8 K4 i7 O& K: v1 R$ n
  198.           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,9 j/ y, R. }4 Q7 [
  199.           pdwBytesReturned, NULL);0 b6 E6 C, ~9 d. m7 a% l
  200. }0 P# y8 s, y( y8 B
  201. //---------------------------------------------------------------------------: W8 @8 h6 M! f) V( O
  202. // Windows 95/98/ME 代码' o, d! L5 v9 m. T& {1 {: J
  203. //---------------------------------------------------------------------------
    ! ?- m* B' v" |: d3 E
  204. // ReadPhysicalDriveOnW9X6 Y8 q6 k) a, R& Z
  205. void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)
    - @# P' f: \( F: A) u
  206. {: Z2 `/ I  s3 Q4 R4 f1 H
  207.    WORD wOutData[256];7 j) M; }7 D9 ~7 f
  208.    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);4 W( a  ?: Z  n
  209. 1 j) N& \& K1 Z) }8 p- n3 Y. w" `
  210.    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。3 J; D: G- i2 w
  211.    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
    4 ?0 N2 K# ~! n" l. R; S
  212.    // 避免蓝屏的出现。(期待高人能指出原因)6 Y5 B  X3 N& ]6 v' O  Y) T, @
  213.    for(int nDrive = 0; nDrive < 8; nDrive++)* Z' Z% c, l3 P9 @# E* v4 p: y
  214.    {
    6 g0 K$ c$ a9 f1 E1 V: ?! }4 M: ~, c5 b4 E
  215.        WORD dwBaseAddress;/ p: v, j0 ]0 ?) _+ p  f
  216.        BYTE btMasterSlave;         // Master Or Slave
    , d# P$ o* v2 D3 Q8 g. `
  217.        bool bIsIDEExist;! \( P$ L, P  o2 K" {
  218.        bool IsDiskExist;$ Z. g& o! B& F# |% X
  219. / t* a4 ]+ `8 d8 Z8 N! N, Y
  220.        switch(nDrive / 2), P: h& S' q6 y4 q- z
  221.        {2 J( j; W+ I' Z/ C: h3 z5 Z, e( f
  222.            case 0: dwBaseAddress = 0x01F0; break;
    - u6 j6 L/ j( W- Q: d$ B4 q
  223.            case 1: dwBaseAddress = 0x0170; break;9 y! \6 i; g3 E/ r+ V
  224.            case 2: dwBaseAddress = 0x01E8; break;
    / s3 k+ A  }3 V7 s; L
  225.            case 3: dwBaseAddress = 0x0168; break;
    . g0 A# u0 W8 Q/ E: l2 [" L
  226.        }
    ' p" \/ L2 H% `. e
  227. 4 E; _$ W% z# F! \# s# u) ^+ f- v; l$ o
  228.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);
    : Z5 z1 f  l( T# m3 b8 P; c. @

  229. 1 _* Q$ C) t4 P/ p
  230.        // 进入Ring0$ L+ I" [9 o! t& H
  231.        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
    0 H; \8 i. ?% q" `. l0 T2 |1 q# {
  232.                bIsIDEExist, IsDiskExist, wOutData);4 t! ~; j8 P9 [, t3 r7 e9 q; }. I! u
  233.    }! d! p& v1 \5 J; W' n9 o" Y
  234. ! d8 H; l# {: ?( w2 {
  235.    // 开始读取
    / g5 K" @- `2 _+ r7 [
  236.    for(int nDrive = 0; nDrive < 8; nDrive++)
    , q) H+ d  b/ K$ Z1 N2 I
  237.    {1 A, |7 j+ o: M  A# S+ E9 j  [
  238.        WORD dwBaseAddress;, Z' M3 `( H- w
  239.        BYTE btMasterSlave;         // Master Or Slave; ?; ~; i+ X2 h# j  L/ O( g6 e
  240.        bool bIsIDEExist;
    8 k2 q( m0 r" R9 u) o; u
  241.        bool bIsDiskExist;
    # }6 r: Y# l2 |5 r
  242.        switch(nDrive / 2)4 ~  s4 Y  k/ o0 D; f$ }' P
  243.        {
    # i2 N- T+ w! W7 K# L; w) X2 c2 W
  244.            case 0: dwBaseAddress = 0x01F0; break;, Q# g9 U# B7 S
  245.            case 1: dwBaseAddress = 0x0170; break;! L/ O0 a9 \. a6 c) c
  246.            case 2: dwBaseAddress = 0x01E8; break;9 u$ |$ d8 }0 t
  247.            case 3: dwBaseAddress = 0x0168; break;/ E/ d$ r  ^& ?& H1 s( ^- W
  248.        }
    ' [) K1 `7 D; z2 n+ p; ~

  249. 5 K& I) j' k) W& C+ r2 ]8 B
  250.        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);2 d1 G+ u) r' D2 I' s" W
  251. / a! S" [) o# u/ \. \. w3 n* d3 ^
  252.        // 进入Ring0
    6 B% g# T+ K9 Z* {/ }/ r; m; z( F
  253.        bIsIDEExist  = false;' p! J  S- v) n" \  _* e9 d! o6 T/ F! U
  254.        bIsDiskExist = false;
    / Y5 u, H& E' S7 Q2 q
  255.        ZeroMemory(wOutData, sizeof(wOutData));
      T6 s7 F) b' C9 }
  256. , q& D, i; B- A/ c8 r$ g" u$ ~
  257.        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,& w/ u1 X; v. u1 X2 d
  258.                bIsIDEExist, bIsDiskExist, wOutData);
    & o- M$ T- v$ x) q/ [: O" t/ v

  259. 8 V0 D0 k4 ^/ Q
  260.        if(bIsIDEExist && bIsDiskExist)/ ?. c' o+ O5 @
  261.        {: J3 Q( |2 c3 W4 a$ w1 I7 d
  262.            DWORD dwDiskData[256];+ _$ C* R5 @6 V% D
  263.            char  szSerialNumber[21];8 j8 _" C6 v+ \
  264.            char  szModelNumber[41];
    6 J1 f' ~0 N/ [2 U( \* c
  265. % r5 ?8 Y/ \( K8 _% n" H! l
  266.            for(int k=0; k < 256; k++)
    3 w* L; ^9 h* Z
  267.                dwDiskData[k] = wOutData[k];
    : O% {$ {! E) A' ?" k
  268. ; u; u" V# p" ~, \
  269.            // 取系列号
    + p% t$ ~8 T4 }5 w/ y/ d
  270.            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));7 W( g" p; i+ @% ~' ]
  271.            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
    " U6 b( t' H( \' W3 a& m

  272. ( ?4 |( r/ t; B6 N
  273.            // 取模型号2 U1 g7 s  K; q' i
  274.            ZeroMemory(szModelNumber, sizeof(szModelNumber));) J$ `4 E  G/ @- Y$ w! {
  275.            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
    & K' `- _8 ^5 h8 D  P  Q0 G) L

  276. 0 m* b& U  x. y- j, N" B* m
  277.            pSerList->Add(szSerialNumber);. o" P0 k0 `. S# L' h% @
  278.            pModeList->Add(szModelNumber);6 ]- l- ?* U' S+ r% ~3 ^
  279.        }2 A) V6 j5 S! {7 i& n  w
  280.    }
    " M& H# E2 X" @9 ^' n& L; S  ^
  281.    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);. A( d' B" d; \* y" B: t
  282. }7 }! N: `7 J" ]: m: V
  283. //---------------------------------------------------------------------------
    3 x' @* x$ e# q  @
  284. // ReadPhysicalDriveOnW9X_Ring0(); R4 o+ ?: E1 O* n
  285. //7 e. X* ]% Y9 P5 g/ D1 _, W
  286. // dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h7 |; `. I% r1 `9 }4 t6 {+ @, Q( \
  287. // btMasterSlave = Master(0xA0) Or Slave(0xB0)* |0 {1 c' L4 U3 G7 `
  288. //---------------------------------------------------------------------------* g! s  E5 Q( p1 o4 [- Z" Y
  289. void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,% w  f; {5 r! M& w/ r- q$ A& k
  290.        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
    : g1 k0 n  h  A/ [
  291. {9 |2 g4 k$ P5 e$ m( J+ ?3 Q
  292.    BYTE  btIDTR1[6];; P4 M7 N7 v  ~* v1 j' [% s- q
  293.    DWORD dwOldExceptionHook;) w2 ]: ^& g$ i* z3 D6 T
  294.    const int nHookExceptionNo = 5;, N; c, [6 u7 K- q7 |! Y
  295. & C0 C) V, ?7 c" Z  ^* |2 g7 l
  296.    BYTE  btIsIDEExist = 0;# E" L! f9 J2 ^- C/ d
  297.    BYTE  btIsDiskExist = 0;
    ( B4 X9 ~: r% r6 b4 m- U
  298.    WORD  wOutDataBuf[256];5 O% j$ j+ \+ |/ f7 a/ y6 e

  299. 5 Q, _4 l7 t8 L( q
  300.    BYTE  btIsFirst = (BYTE)bIsFirst;
      S- _( ]+ [* O6 R

  301. 0 j9 }% ~; ^' @8 F3 `0 s* \% M1 N
  302.    const BYTE btBit00 = 0x01;/ w  g: {2 h( V% R$ F
  303.    // const BYTE btBit02 = 0x04;
    9 ^1 t6 V& }1 i; J1 m4 j: j
  304.    const BYTE btBit06 = 0x40;
    : T4 J9 F# x! S  E& N3 d9 h
  305.    const BYTE btBit07 = 0x80;7 H2 B) X5 c! W$ }7 z* h% k- ]1 i
  306.    // const BYTE btERR  = btBit00;2 `" E' i+ ?: }# z  u
  307.    const BYTE btBusy = btBit07;. M4 l2 k( x* l# ]* V
  308.    const BYTE btAtaCmd   = 0xEC;
    " K; b4 v. o# @* `
  309.    const BYTE btAtapiCmd = 0xA1;1 X  d5 h' v/ T- C

  310. + p0 z, u6 |4 {( t3 C
  311.    __asm
    6 L- O) j' Q: g' k* ]& F
  312.    {8 {+ q0 ]  e8 ^9 W' G& R7 N$ o- r& t
  313.        // 必须先执行这条语句6 }" v4 T. y7 J. L7 A) X2 t
  314.        JMP EnterRing0
      ~5 D4 [- n2 i
  315. , ?9 r: k5 Y1 S2 w0 F) r
  316.        // 定义过程
    1 o- R$ m1 f5 j2 v+ b* \' J$ W
  317.        // 等待IDE设备直到其不为忙为止
    : e# o& e( k- V6 o6 m5 i+ N4 t6 u
  318.        WaitWhileBusy proc2 |) E. w/ h' z5 _

  319. 2 Z: r4 q1 {, c9 [
  320.        MOV  EBX, 100000
    8 t! t1 [& w' X% c2 W  \
  321.        MOV  DX, dwBaseAddress
    0 ]5 M1 e; b' T1 s
  322.        ADD  DX, 7- u! B* C% l0 ]1 T3 D+ }8 L6 J

  323.   }+ s  \1 W# n. ]
  324.        LoopWhileBusy:, Z% I( y3 G% R. S7 q- U, [" X1 ?* ?3 S

  325. ' i7 M9 S! F9 i* Y6 m1 U
  326.        DEC  EBX
    & v& @  h: j6 M9 m1 z( P
  327.        CMP  EBX, 0
    4 y0 e$ _* M! [
  328.        JZ   Timeout
    ( [" G( R) g1 f- @7 R
  329.        in   AL, DX- c" V  b! M! _$ T9 I
  330.        TEST AL, btBusy3 h& H, ]3 C& p* t: B
  331.        JNZ  LoopWhileBusy
    6 y: }" V( g8 A1 ]4 \, m
  332.        JMP  DriveReady& W0 y2 j3 K' P* ^/ i5 P

  333. ! Q4 Y# p' W6 `* s! B' z0 d8 P2 l
  334.        // 超时,直接退出8 W; P, }# M. S0 j" m
  335.        Timeout:1 T2 \! \. W: J) o. k& i# U! P7 x
  336.        JMP  LeaveRing0
    $ O9 k+ G& l* t8 D3 t* N/ V. G! L
  337.        DriveReady:* U0 q/ q2 W1 v5 _/ Q( C0 w) |4 ?8 ^
  338.        RET. D9 D! u, X7 m' m" ^2 A
  339.        ENDP   // End of WaitWhileBusy Procedure
    ! @# C; m, z. g& i1 `* j( n

  340. 1 E' b# }$ T4 {) K
  341.        // 设置主盘和从盘标志
    # b1 q8 C, c; L- b; u
  342.        SelectDevice proc+ H1 T; B2 }, F9 N9 V. Y

  343. . k- S, d# W6 Y+ C
  344.        MOV  DX, dwBaseAddress2 u2 J7 s0 M2 T2 N
  345.        ADD  DX, 6
    : B5 u; V* C) k  _1 r0 |0 F
  346.        MOV  AL, btMasterSlave9 h# C6 O1 ~$ {

  347. - V5 V6 f  ~2 v2 R$ R8 v
  348.        out  DX, AL
    : I6 e! U4 M1 U; S. B" b
  349.        RET
    / D  h' G; f) M  |

  350. $ h: m9 @: |3 q1 }0 H
  351.        ENDP  // End of SelectDevice Procedure
    - q/ s7 J# k+ N+ T" Y; r% h

  352. 5 r5 _5 D  h& v! F
  353.        // 向IDE设备发送存取指令
    " l$ ?/ R: `+ z3 S* Q' F/ [, F
  354.        SendCmd proc3 o' z+ v/ u) Q+ A' g
  355. % P2 e# C2 Y% _/ g
  356.        MOV DX, dwBaseAddress
    9 Y1 D: D! V3 ?& L  C7 B
  357.        ADD DX, 7
    . A! q- d" b$ ^1 R$ a3 ?/ s
  358.        MOV AL, BL // BL是主从盘标识,在过程外设置- Q8 x2 ~: _$ P9 d
  359.        out DX, AL+ q0 {; T1 J* [( L+ `  B$ F
  360.        RET( G# l0 V4 `* d7 k$ N
  361.        ENDP  // End of SendCmd Procedure
    ' F4 d; t! C$ F" N8 ]& \# n/ C

  362. ) T- m0 S7 E9 h' a9 J5 M- L" ~
  363.        // Ring0代码
    - Q+ R$ y# A; f, k; k+ W& z: J7 o
  364.        Ring0Proc:$ d' W- C2 w( r2 n8 i' g" m; T
  365.        PUSHAD) r! W/ Q5 B" B& _
  366.        // 查询IDE设备是否存在
    6 b( s, \0 R8 B6 K9 m  ~; f3 o
  367.        MOV DX, dwBaseAddress7 `8 D! u' v8 L) r/ k9 Y) x
  368.        ADD DX, 7
    8 X9 c$ M4 B" u5 P" _
  369.        in  AL,DX  i2 W; Y* P( \, A

  370. 2 m" y; L6 i0 C4 D  o
  371.        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
    7 q& s  G& S2 M7 N+ _0 J% w) J7 E
  372.        CMP AL,0xFF
    . |" Y, U# f6 [7 z
  373.        JZ  LeaveRing0+ `  b7 M) I. h2 P  `
  374.        CMP AL, 0x7F
    - E6 u( T, S: F& h) k; C" q# j; X
  375.        JZ  LeaveRing0
    , u- ~% [7 }+ f" F; T8 g
  376. 6 d9 {3 D5 M7 C
  377.        // 设置IDE设备存在标志
      t1 o7 p# D% K9 \4 A/ r
  378.        MOV btIsIDEExist, 1: f( y9 P5 j2 ?/ D% P3 x1 \1 ?
  379. 7 c$ i3 R/ M1 [0 d# m) @$ L" e
  380.        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面): f* ^7 D" X# {) t* M4 ~* l& W- \
  381.        CALL WaitWhileBusy
    # X3 @" }$ \- B8 z! n4 z) H2 m+ g5 |
  382.        CALL SelectDevice3 Y* P" G' w2 D1 V5 P+ ]- e- j
  383. 9 J0 |2 R0 r5 Y+ _4 m( T
  384.        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏: r9 j$ E: ]0 n! H7 H3 G
  385.        CMP  btIsFirst, 1; U  U% w& }( T1 R
  386.        JZ   LeaveRing0& b: a* h7 N/ y0 D, T4 K& `

  387. ( R* q# {# O$ s
  388.        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???9 l1 a' b1 e8 K& ~4 B! l
  389.        CALL WaitWhileBusy! v: I1 K$ B% y

  390. # s) Q  F1 c! P5 k, \" t
  391.        // AL的值等于cBit06时,不存在驱动器,直接返回
    9 Q/ O5 |/ m$ r: n4 @+ l
  392.        TEST AL, btBit062 F2 B3 O9 E2 ~1 ?1 _
  393.        JZ   LeaveRing0
    5 ^/ t8 I" q! u) m! {% o* h/ O

  394. 9 s+ O4 `/ V" s, g% G0 l, S
  395.        // 设置驱动器存在标志
    ' C5 _1 o& }+ N6 W( Y
  396.        MOV  btIsDiskExist, 1* P; v* R0 k8 M6 X# g9 G. H0 l, ?
  397. / b. X9 `& X" l0 q, ^' Q2 r
  398.        // 发送存取端口命令) j- z$ n* Y' Z, \1 v
  399.        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
    4 a3 H  n0 |4 ^; T* H
  400.        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
    & c2 d7 e- ]8 g$ k& D
  401.        CALL WaitWhileBusy0 `0 T: k" }. Z: w
  402.        CALL SelectDevice    // 设置主从盘标识
    8 T; |, p$ d$ x6 w& V
  403.        MOV  BL, btAtaCmd      // 发送读取命令3 e: ]2 c. P5 n) S. b# ?
  404.        CALL SendCmd
    # V9 n' x/ _" m
  405.        CALL WaitWhileBusy
    : q6 R" h( l3 u& C
  406. $ ~( D/ A" S  @3 B" N% K
  407.        // 检查是否出错
    3 I0 `5 B' n# y& G
  408.        MOV  DX, dwBaseAddress8 m% z' B& }6 y- k8 ~
  409.        ADD  DX, 7
    3 U/ S# V% {, w/ B

  410. + @' c0 W& J9 g- E- h; I% i
  411.        in   AL, DX( A- M) e+ U/ ~7 i$ [) h

  412. $ g0 S' c; X; J
  413.        TEST AL, btBit00
    ' Q: [4 L/ n9 k/ R" [; w: w
  414.        JZ   RetrieveInfo   // 没有错误时则读数据: @' l$ H$ F: Y8 f; g2 a2 f
  415. & _. ^! h& P7 V: P* o) r& A! ^8 a7 v
  416.        // 如果出错,则进一步尝试使用ATAPI设备命令
    * o- y6 z6 }$ I/ g, B
  417.        CALL WaitWhileBusy* w# m+ a! k+ U
  418.        CALL SelectDevice
    - x  O) J6 y9 S  H# U5 j5 g% m; ~
  419.        MOV  BL, btAtapiCmd
    8 a' l0 [' w( H; l( z
  420.        CALL SendCmd: N, U. U7 x* o+ V2 P' e
  421.        CALL WaitWhileBusy
    . A3 u9 B7 d0 C* \

  422. 4 l- S8 p7 \* O7 {
  423.        // 检查是否还出错% J2 Y3 ^- [2 r+ W  L
  424.        MOV  DX, dwBaseAddress
    6 ?# Y) I. c5 d9 N$ m+ Q  `
  425.        ADD  DX, 7
    ' y& q4 o  ?! a6 F: G7 d( U
  426.        in   AL, DX# u2 d  W* N3 f7 m
  427.        TEST AL, btBit00$ V3 @1 Z% |4 T7 I% K
  428.        JZ   RetrieveInfo   // 没有错误时则读数据
    / O6 U) K" r+ K- p! `" \! h: A
  429.        JMP  LeaveRing0     // 如果还是出错,直接返回0 N4 Q6 h/ j9 q2 \( T: v

  430. 4 ^' l. M8 \- b0 K( m
  431.        // 读取数据/ m# s, Y1 z. T  u5 @5 s
  432.        RetrieveInfo:
      N/ ~8 k3 q* g1 z9 x: u8 `" G
  433. ' l  [0 L, J2 H7 \* x
  434.        LEA  EDI, wOutDataBuf
    0 W, X7 Y1 @% p* _3 Z
  435.        MOV  ECX, 256* R/ C# H- p' D) l
  436.        MOV  DX, dwBaseAddress* w8 y% X3 I' i# R3 l5 }8 b: u2 K, E* ^
  437.        CLD
    ( q7 @! ]# b! ?) B" M7 o
  438. 8 X, r* L, `# _; X+ q7 h& V* _
  439.        REP  INSW
    ( F$ c, a1 h, J' W; c
  440. 0 j' Z* Z6 T: i" V) z
  441.        // 退出Ring0代码
    9 R$ a( T! p+ M$ R* B
  442.        LeaveRing0:
    ' w3 o$ D& M4 H, v; l" J

  443. 6 `& w7 b4 U# K$ b, d5 a) o' N
  444.        POPAD
    * b) @- S9 X# g/ j# f6 J& i
  445.        IRETD
    + f( T; _! }. ?! g5 p* c* N4 `
  446. " B: X/ m" N: @3 f
  447.        // 激活Ring0代码
    1 Q+ W/ k% r5 f
  448.        EnterRing0:9 N" D+ L2 L2 |

  449. 2 ]" p+ c9 z: _6 p% c2 V
  450.        // 修改中断门
    1 C( \+ k& P7 J" i2 [
  451.        SIDT FWORD PTR btIDTR13 {; ^( o1 M' ~) Q8 v. H  u
  452.        MOV EAX, DWORD PTR btIDTR1 + 02h
    2 e; R: K5 L' H, d. s4 @9 r
  453.        ADD EAX, nHookExceptionNo * 08h + 04h
    " L/ |/ P7 Z" B' ?+ q
  454.        CLI) t" y1 Y- Q' V5 ^! ~6 B+ O

  455. / T! A" i1 L. V- j9 g' U
  456.        // 保存原异常处理例程入口
    # H4 C) i! S6 d, {
  457.        MOV ECX, DWORD PTR [EAX]
    $ b4 ?; E* i, l9 @4 o. G
  458.        MOV CX, WORD PTR [EAX-04h]
    4 t$ G: ^- u3 d2 N' P
  459.        MOV dwOldExceptionHook, ECX
    : O( L# H; x2 v. Y0 B7 O
  460. , p- R4 T2 N  r  z3 a4 u9 m
  461.        // 指定新入口
    ; x6 D9 t5 e3 M: K( p! n9 _- b
  462.        LEA EBX, Ring0Proc' d; D7 K, y- z1 S3 K
  463.        MOV WORD PTR [EAX-04h],BX
    4 w; [% }) _8 |8 x
  464.        SHR EBX, 10h
    2 I3 w+ v: {2 i& t# b
  465.        MOV WORD PTR[EAX+02h], BX
    * q4 c4 n2 V& @+ a
  466. 3 ^  l. K7 I' C
  467.        // 激活Ring0代码
    7 ]" Y; \5 _" R1 }
  468.        INT nHookExceptionNo
    ; F, @* s, w8 u3 |, a- @
  469. * N- s8 f3 e) O* Z" F  ?
  470.        // 复原入口
    2 ]+ }: D) v! k, \0 ]
  471.        MOV ECX,dwOldExceptionHook3 F$ H; E. D/ ^
  472.        MOV WORD PTR[EAX-04h], CX6 O% r, r. U0 F( _# C& h' I/ s" @
  473.        SHR ECX,10h
    1 S8 o, g' I0 I+ Q- e5 n
  474.        MOV WORD PTR[EAX+02h], CX- a4 U6 x8 l; _$ {0 A, M1 K' @
  475.        STI
    7 @9 |' ~8 z4 S7 o( z
  476.    }
    & R' _+ b, ~, v( Z5 E( p
  477.    if(!bIsFirst)
    7 \3 ?1 E8 R2 I0 T4 L
  478.    {* q1 {3 w: z: n, U/ [; h5 J
  479.        bIsIDEExist  = (bool)btIsIDEExist;
    & Z* [. P/ J9 s7 w8 N- A
  480.        bIsDiskExist = (bool)btIsDiskExist;
    * }: c, T" P% H
  481.        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));; Z" A7 E3 v/ U6 J. m
  482.    }6 G* z+ C3 ]$ ?0 f
  483. }
    ( N' o: K* P; Y; |
  484. //---------------------------------------------------------------------------
    0 s7 x  o- w* \" U7 A$ r* x* L3 S
  485. // 调用方法:5 z3 T; H) D/ e, h6 h5 l
  486. void __fastcall TForm1::Button1Click(TObject *Sender): j. u* Q( K: e: S. g
  487. {$ [* _+ D* U$ W3 Q2 N  G0 E
  488.    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
    3 S7 n7 A/ ]# W, S3 e0 ^& C
  489. }
复制代码
发表于 2005-8-15 01:00:45 | 显示全部楼层
晕乎乎。。。怎么看8 洞阿
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-5-2 10:36 , Processed in 0.020649 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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