Background
Break News
How to add local font to Tailwind Css and NextJS? - Tutorial Design Pattern? - Blockchain Technology, How to create own Bitcoin virtual currency - Zustand mordern management state - Design Pattern - Flyweight Pattern? - Docker Full training Topic

[Tips] How to "get Hard Disk serial key" using C++"

Wednesday, 30 September 2015
|
Read: Completed in minutes

[Tips] How to "get Hard Disk serial key" using C++"

You want to get serial key of Hard Disk info for check something in PC. Follow my instruction, below source code, you can easy do it

Download CHardDisk.h from here
Download CHardDisk.cpp from here


How to "get Hard Disk serial key" using C++" - Webzone Tech Tips Zidane




Create one class name CDiskInfo, post my code to your project

Source code:

CDiskInfo.h

// huuvi168@gmail.com (Zidane)
#pragma once
#include <winioctl.h>

#define DI_SET_ERROR(pError, err_code) {if (pError) *pError = err_code;}
#define COM_GETDI_SUCCESS     0
#define COM_CREATE_INSTANCE_FAILED   -1
#define COM_CONNECT_SERVER_FAILED   -2
#define COM_SET_PROXY_PLANET_FAILED   -3
#define COM_EXE_QUERY_BOOTPARTITION_FAILED  -4
#define COM_ENUMERATOR_NEXT_WIN32DP_FAILED  -5
#define COM_GET_DEVICEID_DP_FAILED   -6
#define COM_EXE_QUERY_JOIN_DP_DD_FAILED   -7
#define COM_ENUMERATOR_NEXT_WIN32DD_FAILED  -8
#define COM_GET_DEVICEID_DD_FAILED   -9

#define INVALID_INFO_PC _T("000000000000000000000000000000000000000000000000")

class DiskInfo
{
public:
 DiskInfo(void);
 ~DiskInfo(void);
 static void GetHDSerialList(CStringArray &csOutList);
 static CString ConvertToHex(CString csString);
 static int GetIndexOfOSHardDisk();
 static bool GetOSHDSerial(CString& csOsHDSerial);
 static CString GetOSHDSerialByCom(int *pErr = 0);

private:
  static char * flipAndCodeBytes (const char * str, int pos, int flip,  char * buf);
  static wchar_t *ConvertToString (DWORD diskdata [MAX_PATH], int firstIndex, 
                                            int lastIndex, wchar_t* buf);
  static int ReadPhysicalDriveInNTUsingSmart (CStringArray &csSerialList); 
  static int ReadPhysicalDriveInNTWithZeroRights (CStringArray &csSerialList);
  static int ReadIdeDriveAsScsiDriveInNT (CStringArray &csSerialList);
  static int ReadPhysicalDriveInNTWithAdminRights (CStringArray &csSerialList);
  static BOOL DoIDENTIFY( HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP, 
   PSENDCMDOUTPARAMS pSCOP, BYTE bIDCmd, BYTE bDriveNum, PDWORD lpcbBytesReturned );
  static void MergeList( CStringArray &csOutList, CStringArray const &csAddList);
};


CDiskInfo.cpp


// huuvi168@gmail.com (zidane)
#include "StdAfx.h"
#include "DiskInfo.h"
#include <windows.h>
#include <winioctl.h>
#include <cstdio>

#include <comdef.h>
#include <Wbemidl.h>


#ifdef USING_VMPROTECT
#include "VMProtectSDK.h"
#endif


#pragma comment(lib, "wbemuuid.lib")

typedef struct _MEDIA_SERAL_NUMBER_DATA {
 ULONG  SerialNumberLength; 
 ULONG  Result;
 ULONG  Reserved[2];
 UCHAR  SerialNumberData[1];
} MEDIA_SERIAL_NUMBER_DATA, *PMEDIA_SERIAL_NUMBER_DATA;

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;  

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;

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;

#define  SENDIDLENGTH  sizeof (SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE 
#define  FILE_DEVICE_SCSI              0x0000001b
#define  IOCTL_SCSI_MINIPORT_IDENTIFY  ((FILE_DEVICE_SCSI << 16) + 0x0501)
//  Valid values for the bCommandReg member of IDEREGS.  



//  Returns ID sector for ATAPI.  
#define  IDE_ATAPI_IDENTIFY        0xA1 

//  Returns ID sector for ATA.
#define  IDE_ATA_IDENTIFY        0xEC

//  see NTDDSCSI.H for definition    
#define  IOCTL_SCSI_MINIPORT  0x0004D008  
#define  MAX_IDE_DRIVES           16
#define  DFP_GET_VERSION  0x00074080
#define  DFP_RECEIVE_DRIVE_DATA  0x0007c088

DiskInfo::DiskInfo(void)
{

}

DiskInfo::~DiskInfo(void)
{

}

int DiskInfo::ReadPhysicalDriveInNTWithZeroRights( CStringArray &csSerialList )
{
#ifdef USING_VMPROTECT 
// VMProtectBegin("ProtectRPDInNTZR");
#endif
 int done = 0;
 csSerialList.RemoveAll();
 char buffer [10000];
 wchar_t driveName [256] = {0};  

 for (int 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.  
  
  swprintf (driveName, _T("\\\\.\\PhysicalDrive%d"), drive);  
  
  // swprintf ( driveName, 100, _T("\\\\.\\PhysicalDrive%d"), 
                                                                16, 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)
    continue;
    
  STORAGE_PROPERTY_QUERY query;  
  DWORD cbBytesReturned = 0;  
 

  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;  
   CString csSerialNumber; 
           char szSerialNumber [512] = {0};
   wchar_t wcSerialNumber [512] = {0};
   
  flipAndCodeBytes (buffer, descrip -> SerialNumberOffset, 
                                                           1, szSerialNumber ); 
  mbstowcs_s(NULL, wcSerialNumber, sizeof(wcSerialNumber) / 
                               sizeof(wcSerialNumber[0]), szSerialNumber, 
                                                   strlen(szSerialNumber));
  csSerialNumber = wcSerialNumber;
  csSerialNumber.Trim();
   done = true;

   if (!csSerialNumber.IsEmpty() && 
                                 csSerialNumber.CompareNoCase(INVALID_INFO_PC))
   {
    // Get the disk drive geometry.  
    memset (buffer, 0, sizeof(buffer));  
    if ( DeviceIoControl (hPhysicalDriveIOCTL,  
     IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,  
     NULL,  
     0,  
     &buffer,  
     sizeof(buffer),  
     &cbBytesReturned,  
     NULL))  
    {           
   DISK_GEOMETRY_EX* geom = (DISK_GEOMETRY_EX*) &buffer;  
   if (geom->Geometry.MediaType == FixedMedia)
     {
      csSerialList.Add(csSerialNumber);
     }
    }  
   }
  }  
  CloseHandle (hPhysicalDriveIOCTL);  
 }  
 return done;
#ifdef USING_VMPROTECT 
// VMProtectEnd();
#endif
}


int DiskInfo::ReadPhysicalDriveInNTUsingSmart( CStringArray &csSerialList )
{
#ifdef USING_VMPROTECT 
// VMProtectBegin("ProtectRPDInNTUS");
#endif
 csSerialList.RemoveAll();

 int done = FALSE;  
 int drive = 0;  
 
 wchar_t driveName [256];
 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.  
  wsprintf (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)  
  {  
   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) )  
   {           

    // Print the SMART version  
    // PrintVersion (& GetVersionParams);  
    // Allocate the command buffer  
 ULONG CommandSize = sizeof(SENDCMDINPARAMS) + IDENTIFY_BUFFER_SIZE;  
 PSENDCMDINPARAMS Command = (PSENDCMDINPARAMS) malloc (CommandSize);  
    // Retrieve the IDENTIFY data  
    // Prepare the command  
  Command -> irDriveRegs.bCommandReg = IDE_ATA_IDENTIFY;  
    DWORD BytesReturned = 0;  
  if ( DeviceIoControl (hPhysicalDriveIOCTL,   
   SMART_RCV_DRIVE_DATA, Command, sizeof(SENDCMDINPARAMS),  
     Command, CommandSize,  
     &BytesReturned, NULL) )  
    {  
       // 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];  

          if (diskdata [0] & 0x0040)
          {
      wchar_t szTemp[256] = {0};
      CString csTemp;
     ConvertToString(diskdata, 10, 19, szTemp);
      csTemp = szTemp;
      csTemp.Trim();

      if (!csTemp.IsEmpty() && csTemp.CompareNoCase(INVALID_INFO_PC) != 0)
     {
         csSerialList.Add(csTemp);
         done = TRUE;
     }
         }
    }  
    // Done  
    CloseHandle (hPhysicalDriveIOCTL);  
    free (Command);  
   }
  }
 }
 return done;
#ifdef USING_VMPROTECT 
// VMProtectEnd();
#endif
}








int DiskInfo::ReadIdeDriveAsScsiDriveInNT( CStringArray &csSerialList )
{
#ifdef USING_VMPROTECT 
// VMProtectBegin("ProtectRIDASCSIDInNT");
#endif

 csSerialList.RemoveAll();

 int done = FALSE;
 wchar_t driveName [256] = {0};  
 HANDLE hScsiDriveIOCTL = 0;
 for (int controller = 0; controller < 16; controller++)  
 {  
  //  Try to get a handle to PhysicalDrive IOCTL, report failure  
  //  and exit if can't.  
  wsprintf (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)
   continue;
  
  for (int 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 ((char *) p -> Signature, "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);
      if (diskdata [0] & 0x0040)
     {
        wchar_t szTemp[256] = {0};
        CString csTemp;
       ConvertToString(diskdata, 10, 19, szTemp);
        csTemp = szTemp;
        csTemp.Trim();
      
   if (!csTemp.IsEmpty() && csTemp.CompareNoCase(INVALID_INFO_PC) != 0)
        {
      csSerialList.Add(csTemp);
      done = TRUE;
        }
     }
    }  
   }  
  }  
  CloseHandle (hScsiDriveIOCTL);  
 }
 return done;
#ifdef USING_VMPROTECT 
// VMProtectEnd();
#endif
}

int DiskInfo::ReadPhysicalDriveInNTWithAdminRights( CStringArray &csSerialList )
{
#ifdef USING_VMPROTECT 
// VMProtectBegin("ProtectRPDInNTWAR");
#endif

 csSerialList.RemoveAll();
 
 wchar_t driveName [256] = {0};
 GETVERSIONOUTPARAMS VersionParams;
 int done = FALSE;
 BYTE IdOutCmd [sizeof (SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
 
 for (int 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.  
  wsprintf (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)  
   continue;

  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))
  {
  
   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] = {0};  
     int ijk = 0;  
     USHORT *pIdSector = (USHORT *)  
     ((PSENDCMDOUTPARAMS) IdOutCmd) -> bBuffer;  

     for (ijk = 0; ijk < 256; ijk++)  
      diskdata [ijk] = pIdSector [ijk];  

     if (diskdata [0] & 0x0040)
     {
      wchar_t szTemp[256] = {0};
      CString csTemp;
     ConvertToString(diskdata, 10, 19, szTemp);
      csTemp = szTemp;
      csTemp.Trim();
    
 if (!csTemp.IsEmpty() && csTemp.CompareNoCase(INVALID_INFO_PC) != 0)
      {
       csSerialList.Add(csTemp);
       done = TRUE;
      }
     } 
    }  
   }
  }
  CloseHandle (hPhysicalDriveIOCTL); 
 }
 return done; 
#ifdef USING_VMPROTECT 
// VMProtectEnd();
#endif
}

BOOL DiskInfo::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) ); 
}

int DiskInfo::GetIndexOfOSHardDisk()
{
 int nDiskOS = 0;

 HANDLE m_hOSPartition = 0;
 wchar_t szSysDir[MAX_PATH] = {0};
 GetSystemDirectory(szSysDir, MAX_PATH);
 
 CString csPartitionOS;
 csPartitionOS.Format(_T("\\\\.\\%s"), CString(szSysDir).Left(2));
 
 m_hOSPartition = CreateFile (csPartitionOS, 0,  
  FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,  
  OPEN_EXISTING, 0, NULL);  

 if (m_hOSPartition != INVALID_HANDLE_VALUE)   
 {
  //char buffer [10000];
  VOLUME_DISK_EXTENTS buffer;
  DWORD cbBytesReturned = 0;
if ( DeviceIoControl (m_hOSPartition, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,  
   NULL,  
   0,  
   &buffer,  
   sizeof (buffer),  
   & cbBytesReturned, NULL) )  
  {
   nDiskOS = buffer.Extents->DiskNumber;
  }
 }
 CloseHandle(m_hOSPartition);
 return nDiskOS;
}

bool DiskInfo::GetOSHDSerial(CString& csOsHDSerial)
{
#ifdef USING_VMPROTECT 
// VMProtectBegin("GetOSHDSerial");
#endif

 int err = 0;
 //Get HD Serial by Com
 csOsHDSerial = GetOSHDSerialByCom(&err);
 if (!csOsHDSerial.IsEmpty())
  return true;

 wchar_t szErr[256] = {0};
 wsprintf(szErr, L"Get MCByCom failed %d", err);
 //CHelper::WriteLog(szErr);

 CStringArray csSerialList;
 GetHDSerialList(csSerialList);
 if (csSerialList.GetCount() <= 0)
  return false;

 int nOsDiskIndex = GetIndexOfOSHardDisk();
 if (nOsDiskIndex < 0 || nOsDiskIndex >= csSerialList.GetCount())
  return false;

 csOsHDSerial = csSerialList.GetAt(nOsDiskIndex);
 csSerialList.RemoveAll();
 return true;
#ifdef USING_VMPROTECT 
// VMProtectEnd();
#endif
}

wchar_t *DiskInfo::ConvertToString( DWORD diskdata [MAX_PATH], 
                                int firstIndex, int lastIndex, wchar_t* buf )
{
 int index = 0;  
 int position = 0;  

 //  each integer has two characters stored in it backwards  
 for (index = firstIndex; index <= lastIndex; index++)  
 {  
  //  get high byte for 1st character  
  buf [position++] = (wchar_t) (diskdata [index] / 256);  

  //  get low byte for 2nd character  
  buf [position++] = (wchar_t) (diskdata [index] % 256);  
 }  

 //  end the string   
 buf[position] = '\0';  

 //  cut off the trailing blanks  
 for (index = position - 1; index > 0 && isspace(buf [index]); index--)  
  buf [index] = '\0';  

 return buf;
}

char* DiskInfo::flipAndCodeBytes (const char * str, int pos, int flip, char * buf)  
{  
 int i;  
 int j = 0;  
 int k = 0;  

 buf [0] = '\0';  
 if (pos <= 0)  
  return buf;  

 if ( ! j)  
 {  
  char p = 0;  

  // First try to gather all characters representing hex digits only.  
  j = 1;  
  k = 0;  
  buf[k] = 0;  
  for (i = pos; j && str[i] != '\0'; ++i)  
  {  
   char c = tolower(str[i]);  

   if (isspace(c))  
    c = '0';  

   ++p;  
   buf[k] <<= 4;  

   if (c >= '0' && c <= '9')  
    buf[k] |= (unsigned char) (c - '0');  
   else if (c >= 'a' && c <= 'f')  
    buf[k] |= (unsigned char) (c - 'a' + 10);  
   else  
   {  
    j = 0;  
    break;  
   }  

   if (p == 2)  
   {  
         if (buf[k] != '\0' && ! isprint(buf[k]))  
    {  
     j = 0;  
     break;  
    }  
    ++k;  
    p = 0;  
    buf[k] = 0;  
   }  

  }  
 }  

 if ( ! j)  
 {  
  // There are non-digit characters, gather them as is.  
  j = 1;  
  k = 0;  
  for (i = pos; j && str[i] != '\0'; ++i)  
  {  
   char c = str[i];  

   if ( ! isprint(c))  
   {  
    j = 0;  
    break;  
   }  

   buf[k++] = c;  
  }  
 }  

 if ( ! j)  
 {  
  // The characters are not there or are not printable.  
  k = 0;  
 }  

 buf[k] = '\0';  

 if (flip)  
  // Flip adjacent characters  
  for (j = 0; j < k; j += 2)  
  {  
   char t = buf[j];  
   buf[j] = buf[j + 1];  
   buf[j + 1] = t;  
  }  

  // Trim any beginning and end space  
  i = j = -1;  
  for (k = 0; buf[k] != '\0'; ++k)  
  {  
   if (! isspace(buf[k]))  
   {  
    if (i < 0)  
     i = k;  
    j = k;  
   }  
  }  

  if ((i >= 0) && (j >= 0))  
  {  
   for (k = i; (k <= j) && (buf[k] != '\0'); ++k)  
    buf[k - i] = buf[k];  
   buf[k - i] = '\0';  
  }  

  return buf;  
}  

void DiskInfo::MergeList( CStringArray &csOutList, 
                                       CStringArray const &csAddList)
{
 CString csTmp;
 bool bExist;

 for (int i = 0; i < csAddList.GetCount(); i++)
 {
  csTmp = csAddList.GetAt(i);
  bExist = false;
  for (int j = 0; j < csOutList.GetCount(); j++)
  {
   if (csOutList.GetAt(j).CompareNoCase(csTmp) == 0)
   {
    bExist = true;
    break;
   }
  }
  if (!bExist)
   csOutList.Add(csTmp);
 }
}

void DiskInfo::GetHDSerialList(CStringArray &csHDSerialList)
{
 CStringArray csTmpList;

 csHDSerialList.RemoveAll();
 
 ReadPhysicalDriveInNTWithAdminRights(csTmpList);
 MergeList(csHDSerialList, csTmpList);
 ReadPhysicalDriveInNTUsingSmart(csTmpList);
 MergeList(csHDSerialList, csTmpList);
 ReadPhysicalDriveInNTWithZeroRights(csTmpList);
 MergeList(csHDSerialList, csTmpList);
 ReadIdeDriveAsScsiDriveInNT(csTmpList);
 MergeList(csHDSerialList, csTmpList);
}

CString DiskInfo::ConvertToHex(CString csString)
{
 CString csOutHex;
 for(register int i = 0; i < csString.GetLength(); i++)
 {
  csOutHex.AppendFormat(_T("%02x"), csString[i]);
 }
 return csOutHex;
}

CString DiskInfo::GetOSHDSerialByCom(int *pError)
{
#ifdef USING_VMPROTECT 
// VMProtectBegin("GetOSHDSerialByCom");
#endif

 HRESULT hr = CoInitialize(NULL);
    HRESULT hres;
    CString strRetId = _T("");
       
 DI_SET_ERROR(pError, COM_GETDI_SUCCESS);
 IWbemLocator *pLoc = NULL;
    hres = CoCreateInstance(
        CLSID_WbemLocator,             
        0, 
        CLSCTX_INPROC_SERVER, 
        IID_IWbemLocator, (LPVOID *) &pLoc);

    if (FAILED(hres))
    {
        DI_SET_ERROR(pError, COM_CREATE_INSTANCE_FAILED);
  CoUninitialize(); 
        return strRetId;                   // Program has failed.
    }
    // Step 4: -----------------------------------------------------
    // Connect to WMI through the IWbemLocator::ConnectServer method
    IWbemServices *pSvc = NULL;
    // Connect to the root\cimv2 namespace with
    // the current user and obtain pointer pSvc
    // to make IWbemServices calls.
    hres = pLoc->ConnectServer(
         _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace
         NULL,                    // User name. NULL = current user
         NULL,                    // User password. NULL = current
         0,                       // Locale. NULL indicates current
         NULL,                    // Security flags.
         0,                       // Authority (e.g. Kerberos)
         0,                       // Context object 
         &pSvc                    // pointer to IWbemServices proxy
         );
    
    if (FAILED(hres))
    {
        DI_SET_ERROR(pError, COM_CONNECT_SERVER_FAILED);
  pLoc->Release();   
        CoUninitialize(); 
        return strRetId;
        // Program has failed.
    }


    // Step 5: --------------------------------------------------
    // Set security levels on the proxy -------------------------

    hres = CoSetProxyBlanket(
       pSvc,                        // Indicates the proxy to set
       RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx
       RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx
       NULL,                        // Server principal name 
       RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx 
       RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
       NULL,                        // client identity
       EOAC_NONE                    // proxy capabilities 
    );

    if (FAILED(hres))
    {
        DI_SET_ERROR(pError, COM_SET_PROXY_PLANET_FAILED);
  pSvc->Release();
        pLoc->Release();    
        CoUninitialize(); 
        return strRetId;
        // Program has failed.
    }

 IEnumWbemClassObject* pEnumerator = NULL;
 IEnumWbemClassObject* pEnumerator1 = NULL;
 IEnumWbemClassObject* pEnumerator2 = NULL;
 IWbemClassObject *pclsObj = NULL;
 IWbemClassObject *pclsObj1 = NULL;
 IWbemClassObject *pclsObj2 = NULL;
 ULONG uReturn = 0;
 wchar_t wmihddsn[256] = {0};


 hres = pSvc->ExecQuery(
   bstr_t(_T("WQL")),
   bstr_t(_T("SELECT * FROM Win32_DiskPartition WHERE BootPartition=True")),
   WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 
   NULL,
   &pEnumerator);

    if (!SUCCEEDED(hres) || !pEnumerator)
 {
  DI_SET_ERROR(pError, COM_EXE_QUERY_BOOTPARTITION_FAILED);
  if (pEnumerator)
   pEnumerator->Release();
  pSvc->Release();
        pLoc->Release();    
        CoUninitialize(); 
  return strRetId;
 }

 // get the first Win32_DiskPartition
 hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
 if (!SUCCEEDED(hr) || 0 == uReturn)
 {
  DI_SET_ERROR(pError, COM_ENUMERATOR_NEXT_WIN32DP_FAILED);
  if (pclsObj)
   pclsObj->Release();
  pEnumerator->Release();
  pSvc->Release();
        pLoc->Release();    
        CoUninitialize(); 
  return strRetId;
 }

 VARIANT vtProp;
 wchar_t tmp[1024];
 wchar_t query[1024];
 
 tmp[0]  = '\0';
 query[0] = '\0';

 // Get the value of the partition's DeviceID property
 hr = pclsObj->Get(_T("DeviceID"), 0, &vtProp, 0, 0);
 if (!SUCCEEDED(hr))
 {
  DI_SET_ERROR(pError, COM_GET_DEVICEID_DP_FAILED);
  pclsObj->Release();
  pEnumerator->Release();
  pSvc->Release();
        pLoc->Release();    
        CoUninitialize(); 
  return strRetId;
 }

 if(vtProp.vt == VT_BSTR) 
 {
  wcscpy(tmp, vtProp.bstrVal);
 }
 VariantClear(&vtProp);
 // "join" Win32_DiskPartition to Win32_DiskDrive
 wsprintf(query, _T("ASSOCIATORS OF {Win32_DiskPartition.DeviceID='%s'} 
                                        WHERE ResultClass=Win32_DiskDrive"), tmp);

 hres = pSvc->ExecQuery(
    bstr_t(_T("WQL")),
    bstr_t(query),
    WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 
    NULL,
    &pEnumerator1);
 if(!SUCCEEDED(hres) || !pEnumerator1)
 {
  DI_SET_ERROR(pError, COM_EXE_QUERY_JOIN_DP_DD_FAILED);
  if (pEnumerator1)
   pEnumerator1->Release();
  pclsObj->Release();
  pEnumerator->Release();
  pSvc->Release();
        pLoc->Release();    
        CoUninitialize(); 
  return strRetId;
 }
    
 // get the first Win32_DiskDrive
 hr = pEnumerator1->Next(WBEM_INFINITE, 1, &pclsObj1, &uReturn);
 if(!SUCCEEDED(hr) || 0 == uReturn)
 {
  DI_SET_ERROR(pError, COM_ENUMERATOR_NEXT_WIN32DD_FAILED);
  if (pclsObj1)
   pclsObj1->Release();
  pEnumerator1->Release();
  pclsObj->Release();
  pEnumerator->Release();
  pSvc->Release();
        pLoc->Release();    
        CoUninitialize(); 
  return strRetId;
 }

 // Get the value of the disk-drive's DeviceID
 hr = pclsObj1->Get(_T("DeviceID"), 0, &vtProp, 0, 0);
 if(!SUCCEEDED(hr))
 {
  DI_SET_ERROR(pError, COM_GET_DEVICEID_DD_FAILED);
  pclsObj1->Release();
  pEnumerator1->Release();
  pclsObj->Release();
  pEnumerator->Release();
  pSvc->Release();
        pLoc->Release();    
        CoUninitialize(); 
  return strRetId;
 }

 if(vtProp.vt == VT_BSTR)
 {
  wcscpy(tmp, vtProp.bstrVal);
 }
 VariantClear(&vtProp);

 // "join" Win32_DiskDrive to Win32_PhysicalMedia
 wsprintf(query, _T("ASSOCIATORS OF {Win32_DiskDrive.DeviceID='%s'} 
                             WHERE ResultClass=Win32_PhysicalMedia"), tmp);
 hres = pSvc->ExecQuery(
     bstr_t(_T("WQL")),
     bstr_t(query),
     WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 
     NULL,
     &pEnumerator2);

 hr = WBEM_S_NO_ERROR; 
 while (hr == WBEM_S_NO_ERROR && pEnumerator2)
 {
  // get the first Win32_PhysicalMedia
  pclsObj2 = NULL;
  hr = pEnumerator2->Next(WBEM_INFINITE, 1, &pclsObj2, &uReturn);
  if(!SUCCEEDED(hr) || 0 == uReturn || !pclsObj2)
  {
   if(pclsObj2) 
     pclsObj2->Release();
   continue;
  }

  // get the PhysicalMedia's SerialNumber
  hr = pclsObj2->Get(_T("SerialNumber"), 0, &vtProp, 0, 0);
  if(!SUCCEEDED(hr))
  {
   pclsObj2->Release();
   continue;
  }

  if(vtProp.vt == VT_BSTR && vtProp.bstrVal) 
  {
     wcscpy(wmihddsn, vtProp.bstrVal);
     strRetId = wmihddsn;
  }
  VariantClear(&vtProp);
  pclsObj2->Release();
  if (strRetId.GetLength() > 0)
  {
   strRetId.Trim();
   if (!strRetId.IsEmpty() && strRetId.CompareNoCase(INVALID_INFO_PC) != 0)
    break;
   else
    strRetId.Empty();
  }
 }
 
 if(pEnumerator2) 
  pEnumerator2->Release();

 pclsObj1->Release();
 pEnumerator1->Release();
 pclsObj->Release();
 pEnumerator->Release();
 pSvc->Release();
 pLoc->Release();    
 CoUninitialize();
 
 return strRetId;   // Program successfully completed.
#ifdef USING_VMPROTECT 
// VMProtectEnd();
#endif
}


How to use


CString csOSHDSerial;
DiskInfo::GetOSHDSerial(csOSHDSerial);
AfxMessageBox(csOSHDSerial);



How to "get Hard Disk serial key" using C++" - Webzone Tech Tips Zidane
Download CHardDisk.h from here
Download CHardDisk.cpp from here


If you have any feedback on How to get Hard Disk serial key using C++. please leave your comment, we can discuss about it

Thank you for reading this post. I hope you found it helpful and easy to follow. If you have any feedback or questions about How to "get Hard Disk serial key using C++" , please share them in the comments below. I would love to hear from you and discuss this topic further
✋✋✋✋  Webzone Tech Tips  - I am Zidane, See you next time soon ✋✋✋✋

🙇🏼🙇🏼 We Appreciate Your Comments and Suggestions - Webzone, all things Tech Tips web development
Popular Webzone Tech Tips topic maybe you will be like it - by Webzone Tech Tips - Zidane
As a student, I found Blogspot very useful when I joined in 2014. I have been a developer for years . To give back and share what I learned, I started Webzone, a blog with tech tips. You can also search for tech tips zidane on Google and find my helpful posts. Love you all,

I am glad you visited my blog. I hope you find it useful for learning tech tips and webzone tricks. If you have any technical issues, feel free to browse my posts and see if they can help you solve them. You can also leave a comment or contact me if you need more assistance. Here is my blog address: https://learn-tech-tips.blogspot.com.

My blog where I share my passion for web development, webzone design, and tech tips. You will find tutorials on how to build websites from scratch, using hot trends frameworks like nestjs, nextjs, cakephp, devops, docker, and more. You will also learn how to fix common bugs on development, like a mini stackoverflow. Plus, you will discover how to easily learn programming languages such as PHP (CAKEPHP, LARAVEL), C#, C++, Web(HTML, CSS, javascript), and other useful things like Office (Excel, Photoshop). I hope you enjoy my blog and find it helpful for your projects. :)

Thanks and Best Regards!
Follow me on Tiktok @learntechtips and send me a direct message. I will be happy to chat with you.
Webzone - Zidane (huuvi168@gmail.com)
I'm developer, I like code, I like to learn new technology and want to be friend with people for learn each other
I'm a developer who loves coding, learning new technologies, and making friends with people who share the same passion. I have been a full stack developer since 2015, with more than years of experience in web development.
Copyright @2022(November) Version 1.0.0 - By Webzone, all things Tech Tips for Web Development Zidane
https://learn-tech-tips.blogspot.com