GetHardDriveID.cpp
上传用户:yffx2008
上传日期:2014-10-12
资源大小:12414k
文件大小:20k
源码类别:

交通/航空行业

开发平台:

Visual C++

  1. // GetScsiHardDriveID.cpp: implementation of the CGetScsiHardDriveID class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "GetHardDriveID.h"
  6. #ifdef _DEBUG
  7. #undef THIS_FILE
  8. static char THIS_FILE[]=__FILE__;
  9. #define new DEBUG_NEW
  10. #endif
  11. //////////////////////////////////////////////////////////////////////
  12. // Construction/Destruction
  13. //////////////////////////////////////////////////////////////////////
  14. CGetScsiHardDriveID::CGetScsiHardDriveID()
  15. {
  16. }
  17. CGetScsiHardDriveID::~CGetScsiHardDriveID()
  18. {
  19. }
  20. ////////////////////////////////////////////////////////////////////////////////
  21. //
  22. //                        自加的
  23. //
  24. ////////////////////////////////////////////////////////////////////////////////
  25. // HWID.cpp: implementation of the HWID class.
  26. //
  27. //////////////////////////////////////////////////////////////////////
  28. #include "stdafx.h"
  29. //#include "PCInfo.h"
  30. #include "GetHardDriveID.h"
  31. #include <winioctl.h>
  32. #include <stdio.h>
  33. //////////////////////////////////////////////////////////////////////
  34. // Construction/Destruction
  35. //////////////////////////////////////////////////////////////////////
  36.    // Define global buffers.
  37. BYTE IdOutCmd [sizeof (SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
  38. BOOL  IsWinNT()//判断是否NT
  39. {
  40.   OSVERSIONINFO OSVersionInfo;
  41.   OSVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  42.   GetVersionEx(&OSVersionInfo);
  43.   return OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT;
  44. }
  45. BOOL IsNT = IsWinNT();
  46. void TrimRight(char * psString)
  47. {
  48. int len = strlen(psString);
  49. for (int i = len - 1; i >= 0; --i)
  50. {
  51. if (psString[i] != ' ')
  52. break;
  53. // continue;
  54. psString[i] = '';
  55. }
  56. }
  57. char _szInfo[1024];
  58. BOOL GetHardDiskID(char szBuff[128])
  59. {
  60. DRIVER_INFO_OK io = {0};
  61. if (IsNT)
  62. strcat(_szInfo, "NT[yes]rn");
  63. else
  64. strcat(_szInfo, "NT[no]rn");
  65. if (IsNT)
  66. ReadPhysicalDriveInNT(0, &io);
  67. else
  68. ReadDrivePortsInWin9X(0, &io);
  69. TrimRight(io.ModalNumber);
  70. TrimRight(io.SerialNumber);
  71. TrimRight(io.ControlNum);
  72. if (   (!io.ModalNumber[0]) 
  73. && (!io.SerialNumber[0]) 
  74. && (!io.ControlNum[0]))
  75. {
  76. if (IsNT)
  77. {
  78. ReadIdeDriveAsScsiDriveInNT(0, &io);//拿SCSI硬盘ID
  79. strcat(_szInfo, "[ReadIdeDriveAsScsiDriveInNT]rn");
  80. TrimRight(io.ModalNumber);
  81. TrimRight(io.SerialNumber);
  82. TrimRight(io.ControlNum);
  83. if (   (!io.ModalNumber[0]) 
  84. && (!io.SerialNumber[0]) 
  85. && (!io.ControlNum[0]))
  86. return FALSE;
  87. }
  88. }
  89. sprintf(szBuff, "%s", io.SerialNumber); //,io.ControlNum );
  90. // strcat(_szInfo, "HDSN[");
  91. // strcat(_szInfo, szBuff);
  92. // strcat(_szInfo, "]rn");
  93. return TRUE;
  94. }
  95. #include "nb30.h"
  96. // Define the various device type values.  Note that values used by Microsoft
  97. // Corporation are in the range 0-32767, and 32768-65535 are reserved for use
  98. // by customers.
  99. #define FILE_DEVICE_WINIO 0x00008010
  100. // Macro definition for defining IOCTL and FSCTL function control codes.
  101. // Note that function codes 0-2047 are reserved for Microsoft Corporation,
  102. // and 2048-4095 are reserved for customers.
  103. #define WINIO_IOCTL_INDEX 0x810
  104. // Define our own private IOCTL
  105. #define IOCTL_WINIO_WRITEPORT     CTL_CODE(FILE_DEVICE_WINIO,  
  106.                                   WINIO_IOCTL_INDEX + 2,   
  107.                                   METHOD_BUFFERED,         
  108.                                   FILE_ANY_ACCESS)
  109. #define IOCTL_WINIO_READPORT      CTL_CODE(FILE_DEVICE_WINIO,  
  110.                                   WINIO_IOCTL_INDEX + 3,   
  111.                                   METHOD_BUFFERED,         
  112.                                   FILE_ANY_ACCESS)
  113. struct tagPort32Struct
  114. {
  115.   USHORT wPortAddr;
  116.   ULONG dwPortVal;
  117.   UCHAR bSize;
  118. };
  119. struct tagPort32Struct Port32Struct;
  120.    // DoIDENTIFY
  121.    // FUNCTION: Send an IDENTIFY command to the drive
  122.    // bDriveNum = 0-3
  123.    // bIDCmd = IDE_ATA_IDENTIFY or IDE_ATAPI_IDENTIFY
  124. BOOL DoIDENTIFY (HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
  125.                  PSENDCMDOUTPARAMS pSCOP, BYTE bIDCmd, BYTE bDriveNum,
  126.                  PDWORD lpcbBytesReturned)
  127. {
  128.       // Set up data structures for IDENTIFY command.
  129.    pSCIP -> cBufferSize = IDENTIFY_BUFFER_SIZE;
  130.    pSCIP -> irDriveRegs.bFeaturesReg = 0;
  131.    pSCIP -> irDriveRegs.bSectorCountReg = 1;
  132.    pSCIP -> irDriveRegs.bSectorNumberReg = 1;
  133.    pSCIP -> irDriveRegs.bCylLowReg = 0;
  134.    pSCIP -> irDriveRegs.bCylHighReg = 0;
  135.       // Compute the drive number.
  136.    pSCIP -> irDriveRegs.bDriveHeadReg = 0xA0 | ((bDriveNum & 1) << 4);
  137.       // The command can either be IDE identify or ATAPI identify.
  138.    pSCIP -> irDriveRegs.bCommandReg = bIDCmd;
  139.    pSCIP -> bDriveNumber = bDriveNum;
  140.    pSCIP -> cBufferSize = IDENTIFY_BUFFER_SIZE;
  141.    return ( DeviceIoControl (hPhysicalDriveIOCTL, DFP_RECEIVE_DRIVE_DATA,
  142.                (LPVOID) pSCIP,
  143.                sizeof(SENDCMDINPARAMS) - 1,
  144.                (LPVOID) pSCOP,
  145.                sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
  146.                lpcbBytesReturned, NULL) );
  147. }
  148. char * ConvertToString (DWORD diskdata [256], int firstIndex, int lastIndex)
  149. {
  150.    static char string [1024];
  151.    int index = 0;
  152.    int position = 0;
  153.       //  each integer has two characters stored in it backwards
  154.    for (index = firstIndex; index <= lastIndex; index++)
  155.    {
  156.          //  get high byte for 1st character
  157.       string [position] = (char) (diskdata [index] / 256);
  158.       position++;
  159.          //  get low byte for 2nd character
  160.       string [position] = (char) (diskdata [index] % 256);
  161.       position++;
  162.    }
  163.       //  end the string 
  164.    string [position] = '';
  165.       //  cut off the trailing blanks
  166.    for (index = position - 1; index > 0 && ' ' == string [index]; index--)
  167.       string [index] = '';
  168.    return string;
  169. }
  170. BOOL  ReadPhysicalDriveInNT(const int idrive,PDRIVE_INFO_OK buf)
  171. {
  172. BOOL done = 0;
  173. int drive = 0;
  174. drive = idrive;
  175. HANDLE hPhysicalDriveIOCTL = 0;
  176.     //  Try to get a handle to PhysicalDrive IOCTL, report failure
  177.     //  and exit if can't.
  178.     char driveName [256];
  179.     sprintf (driveName, "\\.\PhysicalDrive%d", drive);
  180. //  Windows NT, Windows 2000, must have admin rights
  181.     hPhysicalDriveIOCTL = CreateFile (driveName,
  182.                                GENERIC_READ | GENERIC_WRITE, 
  183.                                FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
  184.                                OPEN_EXISTING, 0, NULL);
  185.     if (hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
  186.     {
  187. //MessageBox(0,"OK","OK",MB_YESNOCANCEL);
  188. GETVERSIONOUTPARAMS VersionParams;
  189.         DWORD               cbBytesReturned = 0;
  190.         // Get the version, etc of PhysicalDrive IOCTL
  191.         memset ((void*) &VersionParams, 0, sizeof(VersionParams));
  192. if ( ! DeviceIoControl (hPhysicalDriveIOCTL, DFP_GET_VERSION,
  193.                    NULL, 
  194.                    0,
  195.                    &VersionParams,
  196.                    sizeof(VersionParams),
  197.                    &cbBytesReturned, NULL) )
  198.         {         
  199. done = FALSE; //设备打开错误
  200.         }
  201.         // If there is a IDE device at number "i" issue commands
  202.         // to the device
  203.         if (VersionParams.bIDEDeviceMap > 0)
  204.         {
  205. BYTE             bIDCmd = 0;   // IDE or ATAPI IDENTIFY cmd
  206.             SENDCMDINPARAMS  scip;
  207.             //SENDCMDOUTPARAMS OutCmd;
  208. // Now, get the ID sector for all IDE devices in the system.
  209.             // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
  210.             // otherwise use the IDE_ATA_IDENTIFY command
  211.             bIDCmd = (VersionParams.bIDEDeviceMap >> drive & 0x10) ? 
  212.                       IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
  213.             memset (&scip, 0, sizeof(scip));
  214.             memset (IdOutCmd, 0, sizeof(IdOutCmd));
  215.             if ( DoIDENTIFY (hPhysicalDriveIOCTL, 
  216.                        &scip, 
  217.                        (PSENDCMDOUTPARAMS)&IdOutCmd, 
  218.                        (BYTE) bIDCmd,
  219.                        (BYTE) drive,
  220.                        &cbBytesReturned))
  221.             {
  222. DWORD diskdata [256];
  223. int ijk = 0;
  224. USHORT *pIdSector = (USHORT *)
  225.                              ((PSENDCMDOUTPARAMS) IdOutCmd) -> bBuffer;
  226. for (ijk = 0; ijk < 256; ijk++)
  227. diskdata [ijk] = pIdSector [ijk];
  228.     //将diskdata中的硬盘信息保存到buf中
  229. buf->Heads = diskdata[3];
  230. buf->Cylinders = diskdata[1];
  231. buf->Sectors = diskdata[6];
  232. strcpy(buf->ControlNum , ConvertToString(diskdata,23,26));
  233. strcpy(buf->SerialNumber , ConvertToString(diskdata,10,19));
  234. strcpy(buf->ModalNumber , ConvertToString(diskdata,27,46));
  235. if (diskdata [0] & 0x0080)
  236. buf->DriveType = 0; //可移动驱动器
  237. else if (diskdata [0] & 0x0040)
  238. buf->DriveType = 0; //固定驱动器
  239.                done = TRUE;
  240.             }
  241.     }
  242.         CloseHandle (hPhysicalDriveIOCTL);
  243. }
  244. return done;
  245. }
  246. #define  SENDIDLENGTH  sizeof (SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE
  247. BOOL  ReadIdeDriveAsScsiDriveInNT(const int idrive,PDRIVE_INFO_OK buf)
  248. {
  249. // AfxMessageBox("ReadIdeDriveAsScsiDriveInNT");
  250.    BOOL done = FALSE;
  251.    int controller = 0;
  252.    for (controller = 0; controller < 4; controller++)
  253.    {
  254.       HANDLE hScsiDriveIOCTL = 0;
  255.       char   driveName [256];
  256.          //  Try to get a handle to PhysicalDrive IOCTL, report failure
  257.          //  and exit if can't.
  258.       //sprintf (driveName, "\\.\Scsi%d:", controller);
  259.          //  Windows NT, Windows 2000, any rights should do
  260.       hScsiDriveIOCTL = CreateFile (driveName,
  261.                                GENERIC_READ | GENERIC_WRITE, 
  262.                                FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
  263.                                OPEN_EXISTING, 0, NULL);
  264.        if (hScsiDriveIOCTL == INVALID_HANDLE_VALUE)
  265.           printf ("Unable to open SCSI controller %d, error code: 0x%lXn",
  266.                   controller, GetLastError ());
  267.       if (hScsiDriveIOCTL != INVALID_HANDLE_VALUE)
  268.       {
  269.          int drive = 0;
  270.          for (drive = 0; drive < 2; drive++)
  271.          {
  272.             char buffer [sizeof (SRB_IO_CONTROL) + SENDIDLENGTH];
  273.             SRB_IO_CONTROL *p = (SRB_IO_CONTROL *) buffer;
  274.             SENDCMDINPARAMS *pin =
  275.                    (SENDCMDINPARAMS *) (buffer + sizeof (SRB_IO_CONTROL));
  276.             DWORD dummy;
  277.    
  278.             memset (buffer, 0, sizeof (buffer));
  279.             p -> HeaderLength = sizeof (SRB_IO_CONTROL);
  280.             p -> Timeout = 10000;
  281.             p -> Length = SENDIDLENGTH;
  282.             p -> ControlCode = IOCTL_SCSI_MINIPORT_IDENTIFY;
  283.             strncpy ((char *) p -> Signature, "SCSIDISK", 8);
  284.   
  285.             pin -> irDriveRegs.bCommandReg = IDE_ATA_IDENTIFY;
  286.             pin -> bDriveNumber = drive;
  287.             if (DeviceIoControl (hScsiDriveIOCTL, IOCTL_SCSI_MINIPORT, 
  288.                                  buffer,
  289.                                  sizeof (SRB_IO_CONTROL) +
  290.                                          sizeof (SENDCMDINPARAMS) - 1,
  291.                                  buffer,
  292.                                  sizeof (SRB_IO_CONTROL) + SENDIDLENGTH,
  293.                                  &dummy, NULL))
  294.             {
  295.                SENDCMDOUTPARAMS *pOut =
  296.                     (SENDCMDOUTPARAMS *) (buffer + sizeof (SRB_IO_CONTROL));
  297.                IDSECTOR *pId = (IDSECTOR *) (pOut -> bBuffer);
  298.                if (pId -> sModelNumber [0])
  299.                {
  300.                   DWORD diskdata [256];
  301.                   int ijk = 0;
  302.                   USHORT *pIdSector = (USHORT *) pId;
  303.           
  304.                   for (ijk = 0; ijk < 256; ijk++)
  305.                      diskdata [ijk] = pIdSector [ijk];
  306. buf->Heads = diskdata[3];
  307. buf->Cylinders = diskdata[1];
  308. buf->Sectors = diskdata[6];
  309. strcpy(buf->ControlNum , ConvertToString(diskdata,23,26));
  310. strcpy(buf->SerialNumber , ConvertToString(diskdata,10,19));
  311. strcpy(buf->ModalNumber , ConvertToString(diskdata,27,46));
  312. if (diskdata [0] & 0x0080)
  313. buf->DriveType = 0; //可移动驱动器
  314. else if (diskdata [0] & 0x0040)
  315. buf->DriveType = 0; //固定驱动器
  316.                   done = TRUE;
  317.                }
  318.             }
  319.          }
  320.          CloseHandle (hScsiDriveIOCTL);
  321.       }
  322.    }
  323.    return done;
  324. }
  325. HANDLE hDriver;
  326. BOOL IsWinIoInitialized = FALSE;
  327. bool InitializeWinIo()
  328. {
  329.   char szExePath[MAX_PATH];
  330.   PSTR pszSlash;
  331.   if (IsNT)
  332.   {
  333.     if (!GetModuleFileName(GetModuleHandle(NULL), szExePath, sizeof(szExePath)))
  334.       return false;
  335.     pszSlash = strrchr(szExePath, '\');
  336.     if (pszSlash)
  337.       pszSlash[1] = 0;
  338.     else
  339.       return false;
  340.     strcat(szExePath, "winio.sys");
  341. //    UnloadDeviceDriver("WINIO");
  342. //    if (!LoadDeviceDriver("WINIO", szExePath, &hDriver))
  343. //      return false;
  344.   }
  345.   
  346.   IsWinIoInitialized = true;
  347.   return true;
  348. }
  349. #ifdef WINIO_DLL
  350. #define PORT32API _declspec(dllexport)
  351. #else
  352. #define PORT32API _declspec(dllimport)
  353. #endif
  354. #pragma pack(1)
  355. struct GDT_DESCRIPTOR
  356. {
  357.   WORD Limit_0_15;
  358.   WORD Base_0_15;
  359.   BYTE Base_16_23;
  360.   BYTE Type         : 4;
  361.   BYTE System       : 1;
  362.   BYTE DPL          : 2;
  363.   BYTE Present      : 1;
  364.   BYTE Limit_16_19  : 4;
  365.   BYTE Available    : 1;
  366.   BYTE Reserved     : 1;
  367.   BYTE D_B          : 1;
  368.   BYTE Granularity  : 1;
  369.   BYTE Base_24_31;
  370. };
  371. struct CALLGATE_DESCRIPTOR
  372. {
  373.   WORD Offset_0_15;
  374.   WORD Selector;
  375.   WORD ParamCount   : 5;
  376.   WORD Unused       : 3;
  377.   WORD Type         : 4;
  378.   WORD System       : 1;
  379.   WORD DPL          : 2;
  380.   WORD Present      : 1;
  381.   WORD Offset_16_31;
  382. };
  383. struct GDTR
  384. {
  385.   WORD wGDTLimit;
  386.   DWORD dwGDTBase;
  387. };
  388. #pragma pack()
  389. // This function makes it possible to call ring 0 code from a ring 3
  390. // application.
  391. bool CallRing0(PVOID pvRing0FuncAddr, WORD wPortAddr, PDWORD pdwPortVal, BYTE bSize)
  392. {
  393.   struct GDT_DESCRIPTOR *pGDTDescriptor;
  394.   struct GDTR gdtr;
  395.   WORD CallgateAddr[3];
  396.   WORD wGDTIndex = 1;
  397.   _asm Sgdt [gdtr]
  398.   // Skip the null descriptor
  399.   pGDTDescriptor = (struct GDT_DESCRIPTOR *)(gdtr.dwGDTBase + 8);
  400.   // Search for a free GDT descriptor
  401.   for (wGDTIndex = 1; wGDTIndex < (gdtr.wGDTLimit / 8); wGDTIndex++)
  402.   {
  403.     if (pGDTDescriptor->Type == 0     &&
  404.         pGDTDescriptor->System == 0   &&
  405.         pGDTDescriptor->DPL == 0      &&
  406.         pGDTDescriptor->Present == 0)
  407.     {
  408.       // Found one !
  409.       // Now we need to transform this descriptor into a callgate.
  410.       // Note that we're using selector 0x28 since it corresponds
  411.       // to a ring 0 segment which spans the entire linear address
  412.       // space of the processor (0-4GB).
  413.       struct CALLGATE_DESCRIPTOR *pCallgate;
  414.       pCallgate = (struct CALLGATE_DESCRIPTOR *) pGDTDescriptor;
  415.       pCallgate->Offset_0_15 = LOWORD(pvRing0FuncAddr);
  416.       pCallgate->Selector = 0x28;
  417.       pCallgate->ParamCount = 0;
  418.       pCallgate->Unused = 0;
  419.       pCallgate->Type = 0xc;
  420.       pCallgate->System = 0;
  421.       pCallgate->DPL = 3;
  422.       pCallgate->Present = 1;
  423.       pCallgate->Offset_16_31 = HIWORD(pvRing0FuncAddr);
  424.       // Prepare the far call parameters
  425.       CallgateAddr[0] = 0x0;
  426.       CallgateAddr[1] = 0x0;
  427.       CallgateAddr[2] = (wGDTIndex << 3) | 3;
  428.       // Please fasten your seat belts!
  429.       // We're about to make a hyperspace jump into RING 0.
  430.       _asm Mov DX, [wPortAddr]
  431.       _asm Mov EBX, [pdwPortVal]
  432.       _asm Mov CL, [bSize]
  433.       _asm Call FWORD PTR [CallgateAddr]
  434.       // We have made it !
  435.       // Now free the GDT descriptor
  436.       memset(pGDTDescriptor, 0, 8);
  437.       // Our journey was successful. Seeya.
  438.       return true;
  439.     }
  440.     // Advance to the next GDT descriptor
  441.     pGDTDescriptor++; 
  442.   }
  443.   // Whoops, the GDT is full
  444.   return false;
  445. }
  446. __declspec(naked) void Ring0GetPortVal()
  447. {
  448.   _asm
  449.   {
  450.     Cmp CL, 1
  451.     Je ByteVal
  452.     Cmp CL, 2
  453.     Je WordVal
  454.     Cmp CL, 4
  455.     Je DWordVal
  456. ByteVal:
  457.     In AL, DX
  458.     Mov [EBX], AL
  459.     Retf
  460. WordVal:
  461.     In AX, DX
  462.     Mov [EBX], AX
  463.     Retf
  464. DWordVal:
  465.     In EAX, DX
  466.     Mov [EBX], EAX
  467.     Retf
  468.   }
  469. }
  470. bool GetPortVal(WORD wPortAddr, PDWORD pdwPortVal, BYTE bSize)
  471. {
  472.   bool Result;
  473.   DWORD dwBytesReturned;
  474.   struct tagPort32Struct Port32Struct;
  475.   if (IsNT)
  476.   {
  477.     if (!IsWinIoInitialized)
  478.       return false;
  479.     Port32Struct.wPortAddr = wPortAddr;
  480.     Port32Struct.bSize = bSize;
  481.     if (!DeviceIoControl(hDriver, IOCTL_WINIO_READPORT, &Port32Struct,
  482.                          sizeof(struct tagPort32Struct), &Port32Struct, 
  483.  sizeof(struct tagPort32Struct),
  484.                          &dwBytesReturned, NULL))
  485.       return false;
  486.     else
  487.       *pdwPortVal = Port32Struct.dwPortVal;
  488.   }
  489.   else
  490.   {
  491.     Result = CallRing0((PVOID)Ring0GetPortVal, wPortAddr, pdwPortVal, bSize);
  492.     if (Result == false)
  493.       return false;
  494.   }
  495.   return true;
  496. }
  497. __declspec(naked) void Ring0SetPortVal()
  498. {
  499.   _asm
  500.   {
  501.     Cmp CL, 1
  502.     Je ByteVal
  503.     Cmp CL, 2
  504.     Je WordVal
  505.     Cmp CL, 4
  506.     Je DWordVal
  507. ByteVal:
  508.     Mov AL, [EBX]
  509.     Out DX, AL
  510.     Retf
  511. WordVal:
  512.     Mov AX, [EBX]
  513.     Out DX, AX
  514.     Retf
  515. DWordVal:
  516.     Mov EAX, [EBX]
  517.     Out DX, EAX
  518.     Retf
  519.   }
  520. }
  521. bool SetPortVal(WORD wPortAddr, DWORD dwPortVal, BYTE bSize)
  522. {
  523.   DWORD dwBytesReturned;
  524.   struct tagPort32Struct Port32Struct;
  525.   if (IsNT)
  526.   {
  527.     if (!IsWinIoInitialized)
  528.       return false;
  529.     Port32Struct.wPortAddr = wPortAddr;
  530.     Port32Struct.dwPortVal = dwPortVal;
  531.     Port32Struct.bSize = bSize;
  532.     if (!DeviceIoControl(hDriver, IOCTL_WINIO_WRITEPORT, &Port32Struct,
  533.                          sizeof(struct tagPort32Struct), NULL, 0, &dwBytesReturned, NULL))
  534.       return false;
  535.   }
  536.   else
  537.     return CallRing0((PVOID)Ring0SetPortVal, wPortAddr, &dwPortVal, bSize);
  538.   
  539.   return true;
  540. }
  541. BOOL ReadDrivePortsInWin9X (int idrive, PDRIVE_INFO_OK buf)
  542. {
  543. int done = FALSE;
  544. int drive = 0;
  545. InitializeWinIo ();   
  546.       //  Get IDE Drive info from the hardware ports
  547.       //  loop thru all possible drives
  548.    //for (drive = 0; drive < 8; drive++)
  549. drive = idrive;
  550.    
  551. DWORD diskdata [256];
  552.     WORD  baseAddress = 0;   //  Base address of drive controller 
  553.     DWORD portValue = 0;
  554.     int waitLoop = 0;
  555.     int index = 0;
  556.  
  557.     switch (drive / 2)
  558.     {
  559. case 0: baseAddress = 0x1f0; break;
  560.         case 1: baseAddress = 0x170; break;
  561.         case 2: baseAddress = 0x1e8; break;
  562.         case 3: baseAddress = 0x168; break;
  563.     }
  564.     //  Wait for controller not busy 
  565.     waitLoop = 10000;
  566.     while (--waitLoop > 0)
  567.     {
  568. GetPortVal ((WORD) (baseAddress + 7), &portValue, (BYTE) 1);
  569.         //  drive is ready
  570.         if ((portValue & 0x40) == 0x40) break;
  571.         //  previous drive command ended in error
  572.         if ((portValue & 0x01) == 0x01) break;
  573.     }
  574.     //if (waitLoop < 1) continue;
  575.     //  Set Master or Slave drive
  576.     if ((drive % 2) == 0)
  577. SetPortVal ((WORD) (baseAddress + 6), 0xA0, 1);
  578.     else
  579.         SetPortVal ((WORD) (baseAddress + 6), 0xB0, 1);
  580.     //  Get drive info data
  581.     SetPortVal ((WORD) (baseAddress + 7), 0xEC, 1);
  582.     // Wait for data ready 
  583.     waitLoop = 10000;
  584.     while (--waitLoop > 0)
  585.     {
  586. GetPortVal ((WORD) (baseAddress + 7), &portValue, 1);
  587.         //  see if the drive is ready and has it's info ready for us
  588.         if ((portValue & 0x48) == 0x48) break;
  589.             //  see if there is a drive error
  590.         if ((portValue & 0x01) == 0x01) break;
  591.     }
  592.          //  check for time out or other error                                                    
  593.       //if (waitLoop < 1 || portValue & 0x01) continue;
  594.          //  read drive id information
  595.     for (index = 0; index < 256; index++)
  596.     {
  597. diskdata [index] = 0;   //  init the space
  598.         GetPortVal (baseAddress, &(diskdata [index]), 2);
  599.     }
  600. //将diskdata中的硬盘信息保存到buf中
  601. buf->Heads = diskdata[3];
  602. buf->Cylinders = diskdata[1];
  603. buf->Sectors = diskdata[6];
  604. strcpy(buf->ControlNum , ConvertToString(diskdata,23,26));
  605. strcpy(buf->SerialNumber , ConvertToString(diskdata,10,19));
  606. strcpy(buf->ModalNumber , ConvertToString(diskdata,27,46));
  607. if (diskdata [0] & 0x0080)
  608. buf->DriveType = 0; //可移动驱动器
  609. else if (diskdata [0] & 0x0040)
  610. buf->DriveType = 0; //固定驱动器
  611. /*if (datalen < 256)
  612. {
  613. memcpy(drivedata,diskdata,datalen);
  614. }
  615. else
  616. memcpy(drivedata,diskdata,256);*/
  617.     done = TRUE;
  618.    
  619. // ShutdownWinIo ();
  620. return done;
  621. }