Skip to content

Instantly share code, notes, and snippets.

@LambdaSix
Created April 27, 2016 12:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save LambdaSix/d0ff2d33f547398e9bebcac545215662 to your computer and use it in GitHub Desktop.
Save LambdaSix/d0ff2d33f547398e9bebcac545215662 to your computer and use it in GitHub Desktop.
Getting a harddrives serial number.
#include <Windows.h>
#include <atlstr.h>
DWORD GetPhysicalDriveSerialNumber(UINT nDriveNumber, CString& strSerialNumber)
{
DWORD dwResult = NO_ERROR;
strSerialNumber.Empty();
// Format physical drive path (may be '\\.\PhysicalDrive0', '\\.\PhysicalDrive1' and so on).
CString strDrivePath;
strDrivePath.Format(_T("\\\\.\\PhysicalDrive%u"), nDriveNumber);
// call CreateFile to get a handle to physical drive
HANDLE hDevice = ::CreateFile(strDrivePath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL);
if(INVALID_HANDLE_VALUE == hDevice)
return ::GetLastError();
// set the input STORAGE_PROPERTY_QUERY data structure
STORAGE_PROPERTY_QUERY storagePropertyQuery;
ZeroMemory(&storagePropertyQuery, sizeof(STORAGE_PROPERTY_QUERY));
storagePropertyQuery.PropertyId = StorageDeviceProperty;
storagePropertyQuery.QueryType = PropertyStandardQuery;
// get the necessary output buffer size
STORAGE_DESCRIPTOR_HEADER storageDescriptorHeader = { 0 };
DWORD dwBytesReturned = 0;
if(!::DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY,
&storagePropertyQuery, sizeof(STORAGE_PROPERTY_QUERY),
&storageDescriptorHeader, sizeof(STORAGE_DESCRIPTOR_HEADER),
&dwBytesReturned, NULL))
{
dwResult = ::GetLastError();
::CloseHandle(hDevice);
return dwResult;
}
// allocate the necessary memory for the output buffer
const DWORD dwOutBufferSize = storageDescriptorHeader.Size;
BYTE* pOutBuffer = new BYTE[dwOutBufferSize];
ZeroMemory(pOutBuffer, dwOutBufferSize);
// get the storage device descriptor
if (!::DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY,
&storagePropertyQuery, sizeof(STORAGE_PROPERTY_QUERY),
pOutBuffer, dwOutBufferSize,
&dwBytesReturned, NULL))
{
dwResult = ::GetLastError();
delete[]pOutBuffer;
::CloseHandle(hDevice);
return dwResult;
}
// Now, the output buffer points to a STORAGE_DEVICE_DESCRIPTOR structure
// followed by additional info like vendor ID, product ID, serial number, and so on.
STORAGE_DEVICE_DESCRIPTOR* pDeviceDescriptor = (STORAGE_DEVICE_DESCRIPTOR*)pOutBuffer;
const DWORD dwSerialNumberOffset = pDeviceDescriptor->SerialNumberOffset;
if (dwSerialNumberOffset != 0)
{
// finally, get the serial number
strSerialNumber = CString(pOutBuffer + dwSerialNumberOffset);
}
// perform cleanup and return
delete[]pOutBuffer;
::CloseHandle(hDevice);
return dwResult;
}
// ...
UINT nDriveNumber = 0;
CString strSerialNumber;
DWORD dwResult = GetPhysicalDriveSerialNumber(nDriveNumber, strSerialNumber);
CString strReport;
if (NO_ERROR == dwResult)
{
strReport.Format(_T("Drive #%u serial number: '%s'"), nDriveNumber, strSerialNumber);
}
else
{
strReport.Format(_T("GetPhysicalDriveSerialNumber failed. Error: %u"), dwResult);
}
::MessageBox(NULL, strReport, _T("Test"), MB_OK);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment