• 正确获取硬盘序列号源码


    参考:http://www.winsim.com/diskid32/diskid32.cpp

    //  diskid32.cpp 
    //  for displaying the details of hard drives in a command window 
    //  06/11/00  Lynn McGuire  written with many contributions from others, 
    //                            IDE drives only under Windows NT/2K and 9X, 
    //                            maybe SCSI drives later 
    //  11/20/03  Lynn McGuire  added ReadPhysicalDriveInNTWithZeroRights 
    //  10/26/05  Lynn McGuire  fix the flipAndCodeBytes function 
    //  12/8/06   Chunlin Deng  update the string function to security version. 
    //  Testing Passed with Visul Studio 2005. 
    
    #include "stdafx.h"
    #include <stdlib.h> 
    #include <stdio.h> 
    #include <stddef.h> 
    #include <string.h> 
    #include "diskid.h"
    #include <WinIoCtl.h>
    
    
    //  Required to ensure correct PhysicalDrive IOCTL structure setup 
    #pragma pack(1) 
    
    #define  IDENTIFY_BUFFER_SIZE  512 
    
    //  IOCTL commands 
    #define  DFP_GET_VERSION                0x00074080 
    #define  DFP_SEND_DRIVE_COMMAND            0x0007c084 
    #define  DFP_RECEIVE_DRIVE_DATA            0x0007c088 
    #define  FILE_DEVICE_SCSI                0x0000001b 
    #define  IOCTL_SCSI_MINIPORT_IDENTIFY    ((FILE_DEVICE_SCSI << 16) + 0x0501) 
    #define  IOCTL_SCSI_MINIPORT            0x0004D008        //see NTDDSCSI.H for definition 
    
       //  GETVERSIONOUTPARAMS contains the data returned from the  
       //  Get Driver Version function. 
    typedef struct _GETVERSIONOUTPARAMS 
    { 
       BYTE bVersion;      // Binary driver version. 
       BYTE bRevision;     // Binary driver revision. 
       BYTE bReserved;     // Not used. 
       BYTE bIDEDeviceMap; // Bit map of IDE devices. 
       DWORD fCapabilities; // Bit mask of driver capabilities. 
       DWORD dwReserved[4]; // For future use. 
    } GETVERSIONOUTPARAMS, *PGETVERSIONOUTPARAMS, *LPGETVERSIONOUTPARAMS; 
    
       //  Bits returned in the fCapabilities member of GETVERSIONOUTPARAMS  
    #define  CAP_IDE_ID_FUNCTION             1  // ATA ID command supported 
    #define  CAP_IDE_ATAPI_ID                2  // ATAPI ID command supported 
    #define  CAP_IDE_EXECUTE_SMART_FUNCTION  4  // SMART commannds supported 
    
       //  Valid values for the bCommandReg member of IDEREGS. 
    #define  IDE_ATAPI_IDENTIFY  0xA1  //  Returns ID sector for ATAPI. 
    #define  IDE_ATA_IDENTIFY    0xEC  //  Returns ID sector for ATA. 
    
       
       // The following struct defines the interesting part of the IDENTIFY 
       // buffer: 
    typedef struct _IDSECTOR 
    { 
       USHORT  wGenConfig; 
       USHORT  wNumCyls; 
       USHORT  wReserved; 
       USHORT  wNumHeads; 
       USHORT  wBytesPerTrack; 
       USHORT  wBytesPerSector; 
       USHORT  wSectorsPerTrack; 
       USHORT  wVendorUnique[3]; 
       CHAR    sSerialNumber[20]; 
       USHORT  wBufferType; 
       USHORT  wBufferSize; 
       USHORT  wECCSize; 
       CHAR    sFirmwareRev[8]; 
       CHAR    sModelNumber[40]; 
       USHORT  wMoreVendorUnique; 
       USHORT  wDoubleWordIO; 
       USHORT  wCapabilities; 
       USHORT  wReserved1; 
       USHORT  wPIOTiming; 
       USHORT  wDMATiming; 
       USHORT  wBS; 
       USHORT  wNumCurrentCyls; 
       USHORT  wNumCurrentHeads; 
       USHORT  wNumCurrentSectorsPerTrack; 
       ULONG   ulCurrentSectorCapacity; 
       USHORT  wMultSectorStuff; 
       ULONG   ulTotalAddressableSectors; 
       USHORT  wSingleWordDMA; 
       USHORT  wMultiWordDMA; 
       BYTE    bReserved[128]; 
    } IDSECTOR, *PIDSECTOR; 
    
    typedef struct _SRB_IO_CONTROL 
    { 
       ULONG HeaderLength; 
       UCHAR Signature[8]; 
       ULONG Timeout; 
       ULONG ControlCode; 
       ULONG ReturnCode; 
       ULONG Length; 
    } SRB_IO_CONTROL, *PSRB_IO_CONTROL; 
    
       // Define global buffers. 
    BYTE IdOutCmd [sizeof (SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1]; 
    
    char *ConvertToString (DWORD diskdata [256], int firstIndex, int lastIndex); 
    void PrintIdeInfo(int drive, DWORD diskdata [256],char *sDest,int nLen); 
    BOOL DoIDENTIFY (HANDLE, PSENDCMDINPARAMS, PSENDCMDOUTPARAMS, BYTE, BYTE, PDWORD); 
    
    //  Max number of drives assuming primary/secondary, master/slave topology 
    #define  MAX_IDE_DRIVES  16 
    
    int ReadPhysicalDriveInNTWithAdminRights(char *sBuff,int nLen)
    { 
        int done = FALSE; 
        HANDLE hPhysicalDriveIOCTL = 0; 
        TCHAR driveName[MAX_PATH]; 
    
        for ( int drive = 0; drive < MAX_IDE_DRIVES; drive++ ){ 
            //  Try to get a handle to PhysicalDrive IOCTL, report failure 
            //  and exit if can''t. 
            _stprintf_s (driveName, _T("\\\\.\\PhysicalDrive%d"), drive); 
            //  Windows NT, Windows 2000, must have admin rights 
            hPhysicalDriveIOCTL = CreateFile (driveName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE , NULL, OPEN_EXISTING, 0, NULL); 
            
            // if (hPhysicalDriveIOCTL == INVALID_HANDLE_VALUE) 
            //    printf ("Unable to open physical drive %d, error code: 0x%lX\n", 
            //            drive, GetLastError ()); 
            
            if ( hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE ){ 
                GETVERSIONOUTPARAMS VersionParams; 
                DWORD               cbBytesReturned = 0; 
                
                // Get the version, etc of PhysicalDrive IOCTL 
                memset ((void*) &VersionParams, 0, sizeof(VersionParams)); 
                if ( !DeviceIoControl (hPhysicalDriveIOCTL, DFP_GET_VERSION, NULL, 0, &VersionParams, sizeof(VersionParams), &cbBytesReturned, NULL) ){          
                    // printf ("DFP_GET_VERSION failed for drive %d\n", i); 
                    // continue; 
                } 
                
                // If there is a IDE device at number "i" issue commands 
                // to the device 
                if ( VersionParams.bIDEDeviceMap > 0 ){ 
                    BYTE             bIDCmd = 0;   // IDE or ATAPI IDENTIFY cmd 
                    SENDCMDINPARAMS  scip; 
                    //SENDCMDOUTPARAMS OutCmd; 
                    // Now, get the ID sector for all IDE devices in the system. 
                    // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command, 
                    // otherwise use the IDE_ATA_IDENTIFY command 
                    bIDCmd = (VersionParams.bIDEDeviceMap >> drive & 0x10) ? IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY; 
                    memset (&scip, 0, sizeof(scip)); 
                    memset (IdOutCmd, 0, sizeof(IdOutCmd)); 
                    if ( DoIDENTIFY(hPhysicalDriveIOCTL,&scip,(PSENDCMDOUTPARAMS)&IdOutCmd, (BYTE)bIDCmd, (BYTE)drive, &cbBytesReturned) ){ 
                        DWORD diskdata [256]; 
                        int ijk = 0; 
                        USHORT *pIdSector = (USHORT *)((PSENDCMDOUTPARAMS) IdOutCmd) -> bBuffer; 
                        for (ijk = 0; ijk < 256; ijk++) {
                            diskdata [ijk] = pIdSector [ijk]; 
                        }
                        PrintIdeInfo (drive, diskdata,sBuff,nLen); 
                        done = TRUE; 
                    } 
                } 
    
                CloseHandle(hPhysicalDriveIOCTL); 
            } 
        }//end for
        return done; 
    } 
    
    //  Required to ensure correct PhysicalDrive IOCTL structure setup 
    #pragma pack(4) 
    
    // 
    // IOCTL_STORAGE_QUERY_PROPERTY 
    // 
    // Input Buffer: 
    //      a STORAGE_PROPERTY_QUERY structure which describes what type of query 
    //      is being done, what property is being queried for, and any additional 
    //      parameters which a particular property query requires. 
    // 
    //  Output Buffer: 
    //      Contains a buffer to place the results of the query into.  Since all 
    //      property descriptors can be cast into a STORAGE_DESCRIPTOR_HEADER, 
    //      the IOCTL can be called once with a small buffer then again using 
    //      a buffer as large as the header reports is necessary. 
    // 
    
    #define IOCTL_STORAGE_QUERY_PROPERTY   CTL_CODE(IOCTL_STORAGE_BASE, 0x0500, METHOD_BUFFERED, FILE_ANY_ACCESS) 
    
    // 
    // Device property descriptor - this is really just a rehash of the inquiry 
    // data retrieved from a scsi device 
    // 
    // This may only be retrieved from a target device.  Sending this to the bus 
    // will result in an error 
    // 
    #pragma pack(4) 
    
     //  function to decode the serial numbers of IDE hard drives 
     //  using the IOCTL_STORAGE_QUERY_PROPERTY command  
    char * flipAndCodeBytes (char * str) 
    { 
        static char flipped [1000]; 
        int i = 0; 
        int j = 0; 
        int k = 0; 
        int num = strlen (str); 
        strcpy_s (flipped,""); 
        for (i = 0; i < num; i += 4) 
        { 
            for (j = 1; j >= 0; j--) 
            { 
                int sum = 0; 
                for (k = 0; k < 2; k++) 
                { 
                    sum *= 16; 
                    switch (str [i + j * 2 + k]) 
                    { 
                    case '0':  sum += 0; break; 
                    case '1':  sum += 1; break; 
                    case '2':  sum += 2; break; 
                    case '3':  sum += 3; break; 
                    case '4':  sum += 4; break; 
                    case '5':  sum += 5; break; 
                    case '6':  sum += 6; break; 
                    case '7':  sum += 7; break; 
                    case '8':  sum += 8; break; 
                    case '9':  sum += 9; break; 
                    case 'a':  sum += 10; break; 
                    case 'b':  sum += 11; break; 
                    case 'c':  sum += 12; break; 
                    case 'd':  sum += 13; break; 
                    case 'e':  sum += 14; break; 
                    case 'f':  sum += 15; break; 
                    case 'A':  sum += 10; break; 
                    case 'B':  sum += 11; break; 
                    case 'C':  sum += 12; break; 
                    case 'D':  sum += 13; break; 
                    case 'E':  sum += 14; break; 
                    case 'F':  sum += 15; break; 
                    } 
                } 
                if (sum > 0)  
                { 
                    char sub [2]; 
                    sub [0] = (char) sum; 
                    sub [1] = 0; 
                    strcat_s (flipped, sub); 
                } 
            } 
        } 
        return flipped; 
    } 
    
    typedef struct _MEDIA_SERAL_NUMBER_DATA { 
      ULONG  SerialNumberLength;  
      ULONG  Result; 
      ULONG  Reserved[2]; 
      UCHAR  SerialNumberData[1]; 
    } MEDIA_SERIAL_NUMBER_DATA, *PMEDIA_SERIAL_NUMBER_DATA; 
    
    int ReadPhysicalDriveInNTWithZeroRights(char *sBuff,int nLen)
    { 
        int done = FALSE; 
        HANDLE hPhysicalDriveIOCTL = 0; 
        TCHAR driveName [MAX_PATH]; 
    
        for (int drive = 0; drive < MAX_IDE_DRIVES; drive++){ 
            //  Try to get a handle to PhysicalDrive IOCTL, report failure 
            //  and exit if can''t. 
            _stprintf_s (driveName, _T("\\\\.\\PhysicalDrive%d"), drive); 
            //  Windows NT, Windows 2000, Windows XP - admin rights not required 
            hPhysicalDriveIOCTL = CreateFile (driveName, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); 
            // if (hPhysicalDriveIOCTL == INVALID_HANDLE_VALUE) 
            //    printf ("Unable to open physical drive %d, error code: 0x%lX\n", 
            //            drive, GetLastError ()); 
            
            if ( hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE ) { 
                STORAGE_PROPERTY_QUERY query; 
                DWORD cbBytesReturned = 0; 
                char buffer [10000]; 
    
                memset ((void *) & query, 0, sizeof (query)); 
                query.PropertyId = StorageDeviceProperty; 
                query.QueryType = PropertyStandardQuery; 
                memset (buffer, 0, sizeof (buffer)); 
                if ( DeviceIoControl (hPhysicalDriveIOCTL, IOCTL_STORAGE_QUERY_PROPERTY, & query, sizeof(query), &buffer, sizeof(buffer), &cbBytesReturned, NULL) ){          
                    STORAGE_DEVICE_DESCRIPTOR * descrip = (STORAGE_DEVICE_DESCRIPTOR *) & buffer; 
                    char serialNumber [1000]; 
                    char modelNumber [1000]; 
    
                    strcpy_s (serialNumber,  
                    flipAndCodeBytes ( & buffer [descrip -> SerialNumberOffset])); 
                    strcpy_s (modelNumber, & buffer [descrip -> ProductIdOffset]); 
                    if ( 0 == sBuff [0] && 
                        //  serial number must be alphanumeric 
                                //  (but there can be leading spaces on IBM drives) 
                        (isalnum (serialNumber [0]) || isalnum (serialNumber [19])) ) { 
                        strcpy_s (sBuff, nLen, serialNumber); 
                        //strcpy_s (HardDriveModelNumber, modelNumber); 
                        done = TRUE; 
                    }  
                }else{ 
                    DWORD err = GetLastError(); 
                    //printf ("\nDeviceIOControl IOCTL_STORAGE_QUERY_PROPERTY error = %d\n", err); 
                } 
                memset (buffer, 0, sizeof (buffer)); 
                if ( DeviceIoControl (hPhysicalDriveIOCTL, IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER, NULL, 0, &buffer, sizeof(buffer), &cbBytesReturned, NULL) ) {          
                    MEDIA_SERIAL_NUMBER_DATA * mediaSerialNumber = (MEDIA_SERIAL_NUMBER_DATA *) & buffer; 
                    char serialNumber [1000]; 
                    // char modelNumber [1000]; 
                    strcpy_s (serialNumber, (char *) mediaSerialNumber -> SerialNumberData); 
                    // strcpy_s (modelNumber, & buffer [descrip -> ProductIdOffset]); 
                    if ( 0 == sBuff[0] && 
                        //  serial number must be alphanumeric 
                                //  (but there can be leading spaces on IBM drives) 
                        (isalnum (serialNumber [0]) || isalnum (serialNumber [19])) ) { 
                        strcpy_s (sBuff, nLen, serialNumber); 
                        // strcpy_s (HardDriveModelNumber, modelNumber); 
                        done = TRUE; 
                    } 
                    //printf ("\n**** MEDIA_SERIAL_NUMBER_DATA for drive %d ****\nSerial Number = %s\n", drive, serialNumber); 
                }else{ 
                    //DWORD err = GetLastError (); 
                    //switch (err) 
                    //{ 
                    //case 1:  
                    //    printf ("\nDeviceIOControl IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER error = \n" 
                    //        "              The request is not valid for this device.\n\n"); 
                    //    break; 
                    //case 50: 
                    //    printf ("\nDeviceIOControl IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER error = \n" 
                    //        "              The request is not supported for this device.\n\n"); 
                    //    break; 
                    //default: 
                    //    printf ("\nDeviceIOControl IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER error = %d\n\n", err); 
                    //} 
                } 
    
                CloseHandle (hPhysicalDriveIOCTL); 
            } 
        }//end for
        return done; 
    } 
    
    // DoIDENTIFY 
    // FUNCTION: Send an IDENTIFY command to the drive 
    // bDriveNum = 0-3 
    // bIDCmd = IDE_ATA_IDENTIFY or IDE_ATAPI_IDENTIFY 
    BOOL DoIDENTIFY (HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP, PSENDCMDOUTPARAMS pSCOP, BYTE bIDCmd, BYTE bDriveNum, PDWORD lpcbBytesReturned) 
    { 
       // Set up data structures for IDENTIFY command. 
       pSCIP -> cBufferSize = IDENTIFY_BUFFER_SIZE; 
       pSCIP -> irDriveRegs.bFeaturesReg = 0; 
       pSCIP -> irDriveRegs.bSectorCountReg = 1; 
       //pSCIP -> irDriveRegs.bSectorNumberReg = 1; 
       pSCIP -> irDriveRegs.bCylLowReg = 0; 
       pSCIP -> irDriveRegs.bCylHighReg = 0; 
       // Compute the drive number. 
       pSCIP -> irDriveRegs.bDriveHeadReg = 0xA0 | ((bDriveNum & 1) << 4); 
       // The command can either be IDE identify or ATAPI identify. 
       pSCIP -> irDriveRegs.bCommandReg = bIDCmd; 
       pSCIP -> bDriveNumber = bDriveNum; 
       pSCIP -> cBufferSize = IDENTIFY_BUFFER_SIZE; 
       return ( DeviceIoControl (hPhysicalDriveIOCTL, DFP_RECEIVE_DRIVE_DATA, (LPVOID) pSCIP, sizeof(SENDCMDINPARAMS) - 1, (LPVOID) pSCOP, sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1, lpcbBytesReturned, NULL) ); 
    } 
    
    //  --------------------------------------------------- 
       // (* Output Bbuffer for the VxD (rt_IdeDinfo record) *) 
    typedef struct _rt_IdeDInfo_ 
    { 
        BYTE IDEExists[4]; 
        BYTE DiskExists[8]; 
        WORD DisksRawInfo[8*256]; 
    } rt_IdeDInfo, *pt_IdeDInfo; 
    
       // (* IdeDinfo "data fields" *) 
    typedef struct _rt_DiskInfo_ 
    { 
       BOOL DiskExists; 
       BOOL ATAdevice; 
       BOOL RemovableDevice; 
       WORD TotLogCyl; 
       WORD TotLogHeads; 
       WORD TotLogSPT; 
       char SerialNumber[20]; 
       char FirmwareRevision[8]; 
       char ModelNumber[40]; 
       WORD CurLogCyl; 
       WORD CurLogHeads; 
       WORD CurLogSPT; 
    } rt_DiskInfo; 
    
    #define  m_cVxDFunctionIdesDInfo  1 
    
    //////////////////////////////////////////////////////////////////////////
    
    int ReadDrivePortsInWin9X(char *sBuff,int nLen)
    { 
        int done = FALSE; 
        HANDLE VxDHandle = 0; 
        pt_IdeDInfo pOutBufVxD = 0; 
        DWORD lpBytesReturned = 0; 
        //  set the thread priority high so that we get exclusive access to the disk 
        BOOL status = SetPriorityClass (GetCurrentProcess (), REALTIME_PRIORITY_CLASS); 
        if (0 == status){
            //printf ("\nERROR: Could not SetPriorityClass, LastError: %d\n", GetLastError ()); 
        }  
        // 1. Make an output buffer for the VxD 
        rt_IdeDInfo info; 
        pOutBufVxD = &info; 
        // ***************** 
        // KLUDGE WARNING!!! 
        // HAVE to zero out the buffer space for the IDE information! 
        // If this is NOT done then garbage could be in the memory 
        // locations indicating if a disk exists or not. 
        ZeroMemory (&info, sizeof(info)); 
        // 1. Try to load the VxD 
        //  must use the short file name path to open a VXD file 
        //char StartupDirectory [2048]; 
        //char shortFileNamePath [2048]; 
        //char *p = NULL; 
        //char vxd [2048]; 
        //  get the directory that the exe was started from 
        //GetModuleFileName (hInst, (LPSTR) StartupDirectory, sizeof (StartupDirectory)); 
        //  cut the exe name from string 
        //p = &(StartupDirectory [strlen (StartupDirectory) - 1]); 
        //while (p >= StartupDirectory && *p && ''\\'' != *p) p--; 
        //*p = ''\0'';    
        //GetShortPathName (StartupDirectory, shortFileNamePath, 2048); 
        //sprintf_s (vxd, "\\\\.\\%s\\IDE21201.VXD", shortFileNamePath); 
        //VxDHandle = CreateFile (vxd, 0, 0, 0, 
        //               0, FILE_FLAG_DELETE_ON_CLOSE, 0);    
        VxDHandle = CreateFile (_T("\\\\.\\IDE21201.VXD"), 0, 0, 0, 0, FILE_FLAG_DELETE_ON_CLOSE, 0); 
        if (VxDHandle != INVALID_HANDLE_VALUE) { 
            // 2. Run VxD function 
            DeviceIoControl (VxDHandle, m_cVxDFunctionIdesDInfo, 0, 0, pOutBufVxD, sizeof(pt_IdeDInfo), &lpBytesReturned, 0); 
            // 3. Unload VxD 
            CloseHandle (VxDHandle); 
        }else{
            //MessageBox (NULL, "ERROR: Could not open IDE21201.VXD file",TITLE, MB_ICONSTOP); 
        }
     
            // 4. Translate and store data 
        for (int i=0; i<8; i++) { 
            if((pOutBufVxD->DiskExists[i]) && (pOutBufVxD->IDEExists[i/2])) { 
                DWORD diskinfo [256]; 
                for (int j = 0; j < 256; j++)  
                diskinfo [j] = pOutBufVxD -> DisksRawInfo [i * 256 + j]; 
                        // process the information for this buffer 
                PrintIdeInfo (i, diskinfo,sBuff,nLen); 
                done = TRUE; 
            } 
        } 
        //  reset the thread priority back to normal 
        // SetThreadPriority (GetCurrentThread(), THREAD_PRIORITY_NORMAL); 
        SetPriorityClass (GetCurrentProcess (), NORMAL_PRIORITY_CLASS); 
        return done; 
    } 
    
    #define  SENDIDLENGTH  sizeof (SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE 
    
    int ReadIdeDriveAsScsiDriveInNT(char *sBuff,int nLen)
    { 
       int done = FALSE; 
       int controller = 0; 
       for (controller = 0; controller < 16; controller++) 
       { 
          HANDLE hScsiDriveIOCTL = 0; 
          TCHAR  driveName [MAX_PATH]; 
             //  Try to get a handle to PhysicalDrive IOCTL, report failure 
             //  and exit if can''t. 
          _stprintf_s (driveName, _T("\\\\.\\Scsi%d:"), controller); 
             //  Windows NT, Windows 2000, any rights should do 
          hScsiDriveIOCTL = CreateFile (driveName, 
                                   GENERIC_READ | GENERIC_WRITE,  
                                   FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, 
                                   OPEN_EXISTING, 0, NULL); 
          // if (hScsiDriveIOCTL == INVALID_HANDLE_VALUE) 
          //    printf ("Unable to open SCSI controller %d, error code: 0x%lX\n", 
          //            controller, GetLastError ()); 
          if (hScsiDriveIOCTL != INVALID_HANDLE_VALUE) 
          { 
             int drive = 0; 
             for (drive = 0; drive < 2; drive++) 
             { 
                char buffer [sizeof (SRB_IO_CONTROL) + SENDIDLENGTH]; 
                SRB_IO_CONTROL *p = (SRB_IO_CONTROL *) buffer; 
                SENDCMDINPARAMS *pin = 
                       (SENDCMDINPARAMS *) (buffer + sizeof (SRB_IO_CONTROL)); 
                DWORD dummy; 
        
                memset (buffer, 0, sizeof (buffer)); 
                p -> HeaderLength = sizeof (SRB_IO_CONTROL); 
                p -> Timeout = 10000; 
                p -> Length = SENDIDLENGTH; 
                p -> ControlCode = IOCTL_SCSI_MINIPORT_IDENTIFY; 
                strncpy_s ((char *) p -> Signature,9,"SCSIDISK", 8); 
                  
                pin -> irDriveRegs.bCommandReg = IDE_ATA_IDENTIFY; 
                pin -> bDriveNumber = drive; 
                if (DeviceIoControl (hScsiDriveIOCTL, IOCTL_SCSI_MINIPORT,  
                                     buffer, 
                                     sizeof (SRB_IO_CONTROL) + 
                                             sizeof (SENDCMDINPARAMS) - 1, 
                                     buffer, 
                                     sizeof (SRB_IO_CONTROL) + SENDIDLENGTH, 
                                     &dummy, NULL)) 
                { 
                   SENDCMDOUTPARAMS *pOut = 
                        (SENDCMDOUTPARAMS *) (buffer + sizeof (SRB_IO_CONTROL)); 
                   IDSECTOR *pId = (IDSECTOR *) (pOut -> bBuffer); 
                   if (pId -> sModelNumber [0]) 
                   { 
                      DWORD diskdata [256]; 
                      int ijk = 0; 
                      USHORT *pIdSector = (USHORT *) pId; 
               
                      for (ijk = 0; ijk < 256; ijk++) 
                         diskdata [ijk] = pIdSector [ijk]; 
                      PrintIdeInfo (controller * 2 + drive, diskdata,sBuff,nLen); 
                      done = TRUE; 
                   } 
                } 
             } 
             CloseHandle (hScsiDriveIOCTL); 
          } 
       } 
       return done; 
    } 
    
    
    //////////////////////////////////////////////////////////////////////////
    
    
    //
    // IDENTIFY data (from ATAPI driver source)
    //
    
    #pragma pack(1)
    
    typedef struct _IDENTIFY_DATA {
        USHORT GeneralConfiguration;            // 00 00
        USHORT NumberOfCylinders;               // 02  1
        USHORT Reserved1;                       // 04  2
        USHORT NumberOfHeads;                   // 06  3
        USHORT UnformattedBytesPerTrack;        // 08  4
        USHORT UnformattedBytesPerSector;       // 0A  5
        USHORT SectorsPerTrack;                 // 0C  6
        USHORT VendorUnique1[3];                // 0E  7-9
        USHORT SerialNumber[10];                // 14  10-19
        USHORT BufferType;                      // 28  20
        USHORT BufferSectorSize;                // 2A  21
        USHORT NumberOfEccBytes;                // 2C  22
        USHORT FirmwareRevision[4];             // 2E  23-26
        USHORT ModelNumber[20];                 // 36  27-46
        UCHAR  MaximumBlockTransfer;            // 5E  47
        UCHAR  VendorUnique2;                   // 5F
        USHORT DoubleWordIo;                    // 60  48
        USHORT Capabilities;                    // 62  49
        USHORT Reserved2;                       // 64  50
        UCHAR  VendorUnique3;                   // 66  51
        UCHAR  PioCycleTimingMode;              // 67
        UCHAR  VendorUnique4;                   // 68  52
        UCHAR  DmaCycleTimingMode;              // 69
        USHORT TranslationFieldsValid:1;        // 6A  53
        USHORT Reserved3:15;
        USHORT NumberOfCurrentCylinders;        // 6C  54
        USHORT NumberOfCurrentHeads;            // 6E  55
        USHORT CurrentSectorsPerTrack;          // 70  56
        ULONG  CurrentSectorCapacity;           // 72  57-58
        USHORT CurrentMultiSectorSetting;       //     59
        ULONG  UserAddressableSectors;          //     60-61
        USHORT SingleWordDMASupport : 8;        //     62
        USHORT SingleWordDMAActive : 8;
        USHORT MultiWordDMASupport : 8;         //     63
        USHORT MultiWordDMAActive : 8;
        USHORT AdvancedPIOModes : 8;            //     64
        USHORT Reserved4 : 8;
        USHORT MinimumMWXferCycleTime;          //     65
        USHORT RecommendedMWXferCycleTime;      //     66
        USHORT MinimumPIOCycleTime;             //     67
        USHORT MinimumPIOCycleTimeIORDY;        //     68
        USHORT Reserved5[2];                    //     69-70
        USHORT ReleaseTimeOverlapped;           //     71
        USHORT ReleaseTimeServiceCommand;       //     72
        USHORT MajorRevision;                   //     73
        USHORT MinorRevision;                   //     74
        USHORT Reserved6[50];                   //     75-126
        USHORT SpecialFunctionsEnabled;         //     127
        USHORT Reserved7[128];                  //     128-255
    } IDENTIFY_DATA, *PIDENTIFY_DATA;
    
    #pragma pack()
    
    
    int ReadPhysicalDriveInNTUsingSmart(char *sBuff,int nLen)
    {
        int done = FALSE;
        int drive = 0;
    
        for (drive = 0; drive < MAX_IDE_DRIVES; drive++)
        {
            HANDLE hPhysicalDriveIOCTL = 0;
    
            //  Try to get a handle to PhysicalDrive IOCTL, report failure
            //  and exit if can't.
            TCHAR driveName [MAX_PATH];
    
            _stprintf (driveName, _T("\\\\.\\PhysicalDrive%d"), drive);
    
            //  Windows NT, Windows 2000, Windows Server 2003, Vista
            hPhysicalDriveIOCTL = CreateFile (driveName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
            // if (hPhysicalDriveIOCTL == INVALID_HANDLE_VALUE)
            //    printf ("Unable to open physical drive %d, error code: 0x%lX\n",
            //            drive, GetLastError ());
    
            if (hPhysicalDriveIOCTL == INVALID_HANDLE_VALUE){
                //if (PRINT_DEBUG) 
                //    printf ("\n%d ReadPhysicalDriveInNTUsingSmart ERROR"
                //    "\nCreateFile(%s) returned INVALID_HANDLE_VALUE\n"
                //    "Error Code %d\n",
                //    __LINE__, driveName, GetLastError ());
            }else{
                GETVERSIONINPARAMS GetVersionParams;
                DWORD cbBytesReturned = 0;
    
                // Get the version, etc of PhysicalDrive IOCTL
                memset ((void*) & GetVersionParams, 0, sizeof(GetVersionParams));
    
                if ( ! DeviceIoControl (hPhysicalDriveIOCTL, SMART_GET_VERSION, NULL, 0, &GetVersionParams, sizeof (GETVERSIONINPARAMS), &cbBytesReturned, NULL) ){         
                    //if (PRINT_DEBUG)
                    //{
                    //    DWORD err = GetLastError ();
                    //    printf ("\n%d ReadPhysicalDriveInNTUsingSmart ERROR"
                    //        "\nDeviceIoControl(%d, SMART_GET_VERSION) returned 0, error is %d\n",
                    //        __LINE__, (int) hPhysicalDriveIOCTL, (int) err);
                    //}
                }else{
                    // Print the SMART version
                    // PrintVersion (& GetVersionParams);
                    // Allocate the command buffer
                    ULONG CommandSize = sizeof(SENDCMDINPARAMS) + IDENTIFY_BUFFER_SIZE;
                    PSENDCMDINPARAMS Command = (PSENDCMDINPARAMS)new BYTE[CommandSize];
                    // Retrieve the IDENTIFY data
                    // Prepare the command
                    #define ID_CMD          0xEC            // Returns ID sector for ATA
                    Command -> irDriveRegs.bCommandReg = ID_CMD;
                    DWORD BytesReturned = 0;
                    if ( ! DeviceIoControl (hPhysicalDriveIOCTL,SMART_RCV_DRIVE_DATA, Command, sizeof(SENDCMDINPARAMS), Command, CommandSize, &BytesReturned, NULL) ){
                        // Print the error
                        //PrintError ("SMART_RCV_DRIVE_DATA IOCTL", GetLastError());
                    }else{
                        // Print the IDENTIFY data
                        DWORD diskdata [256];
                        USHORT *pIdSector = (USHORT *)(PIDENTIFY_DATA) ((PSENDCMDOUTPARAMS) Command) -> bBuffer;
    
                        for (int ijk = 0; ijk < 256; ijk++){
                            diskdata [ijk] = pIdSector [ijk];
                        }
    
                        PrintIdeInfo (drive, diskdata,sBuff,nLen); 
                        done = TRUE;
                    }
                    // Done
                    CloseHandle (hPhysicalDriveIOCTL);
                    delete []Command;
                }
            }
        }
    
        return done;
    }
    
    void PrintIdeInfo(int drive, DWORD diskdata [256],char *sDest,int nLen) 
    { 
       char string1 [1024]; 
       __int64 sectors = 0; 
       __int64 bytes = 0; 
          //  copy the hard drive serial number to the buffer 
       strcpy_s (string1, ConvertToString (diskdata, 10, 19)); 
       if (0 == sDest[0] && 
                //  serial number must be alphanumeric 
                //  (but there can be leading spaces on IBM drives) 
           (isalnum (string1 [0]) || isalnum (string1 [19]))) 
       { 
          strcpy_s (sDest, nLen, string1); 
          //strcpy_s (HardDriveModelNumber, ConvertToString (diskdata, 27, 46)); 
       } 
    } 
    
    char *ConvertToString (DWORD diskdata [256], int firstIndex, int lastIndex) 
    { 
       static char string [1024]; 
       int position = 0; 
          //  each integer has two characters stored in it backwards 
       for (int index = firstIndex; index <= lastIndex; index++) 
       { 
             //  get high byte for 1st character 
          string [position] = (char) (diskdata [index] / 256); 
          position++; 
             //  get low byte for 2nd character 
          string [position] = (char) (diskdata [index] % 256); 
          position++; 
       } 
          //  end the string  
       string [position] = '\0'; 
          //  cut off the trailing blanks 
       for (int index = position - 1; index > 0 && ' ' == string [index]; index--) 
          string [index] = '\0'; 
       return string; 
    } 
    
    int GetHardDriveSerialNumber(char *sBuff,int nLen)
    {
        int done = FALSE;
        // char string [1024];
        __int64 id = 0;
        OSVERSIONINFO version = {0};
        version.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
        GetVersionEx (&version);
    
        memset(sBuff,0,nLen);
    
        if (version.dwPlatformId == VER_PLATFORM_WIN32_NT) {
            //  this works under WinNT4 or Win2K if you have admin rights
            //printf ("\nTrying to read the drive IDs using physical access with admin rights\n");
            done = ReadPhysicalDriveInNTWithAdminRights(sBuff,nLen);
    
            //  this should work in WinNT or Win2K if previous did not work
            //  this is kind of a backdoor via the SCSI mini port driver into
            //     the IDE drives
            //printf ("\nTrying to read the drive IDs using the SCSI back door\n");
            if ( ! done){ 
                done = ReadIdeDriveAsScsiDriveInNT(sBuff,nLen);
            }
    
            //  this works under WinNT4 or Win2K or WinXP if you have any rights
            //printf ("\nTrying to read the drive IDs using physical access with zero rights\n");
            if ( ! done){
                done = ReadPhysicalDriveInNTWithZeroRights(sBuff,nLen);
            }
    
            //  this works under WinNT4 or Win2K or WinXP or Windows Server 2003 or Vista if you have any rights
            //printf ("\nTrying to read the drive IDs using Smart\n");
            if ( ! done){
                done = ReadPhysicalDriveInNTUsingSmart(sBuff,nLen);
            }
        }else{
            //  this works under Win9X and calls a VXD
            //  try this up to 10 times to get a hard drive serial number
            for (int attempt = 0; attempt < 10 && ! done && 0 == sBuff[0]; attempt++) {
                done = ReadDrivePortsInWin9X(sBuff,nLen);
            }
        }
    
        return done;
    }
  • 相关阅读:
    c# 日期函数DateTime.ToString()日期的各种格式 (本人亲测)
    C# Excel导入、导出【源码下载】
    微信支付服务器CA证书更换服务器安装der证书的方法 DigiCert的根证书
    重置winsock目录解决不能上网的问题
    模型验证组件 FluentValidation
    对于“Newtonsoft.Json”已拥有为“NETStander.Library”定义的依赖项,解决办法
    .NET平台开源项目速览(6)FluentValidation验证组件介绍与入门(一)
    C# 中参数验证方式的演变
    一步一步ITextSharp 低级操作函数使用
    Winform 打印PDF顺序混乱,获取打印队列
  • 原文地址:https://www.cnblogs.com/daxingxing/p/2488185.html
Copyright © 2020-2023  润新知