我的博客小站

正确获取硬盘序列号源码

参考: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;
}

 

 

 

posted on 2012-05-07 19:01  BIGSING  阅读(8954)  评论(0编辑  收藏  举报

导航

我的博客小站