CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums
Results 1 to 1 of 1
  1. #1
    Join Date
    Feb 2003
    Iasi - Romania

    WinAPI: How to Get Hard Disk Serial Number?

    Q: How to programmatically get the serial number assigned to a hard disk (or another type of physical drive) by the manufacturer?

    A: One solution is to call DeviceIoControl function with IOCTL_STORAGE_QUERY_PROPERTY control code.

    #include <Windows.h>
    #include <atlstr.h>
    DWORD GetPhysicalDriveSerialNumber(UINT nDriveNumber, CString& strSerialNumber)
        DWORD dwResult = NO_ERROR;
        // 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();
            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();
            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.
        const DWORD dwSerialNumberOffset = pDeviceDescriptor->SerialNumberOffset;
        if (dwSerialNumberOffset != 0)
            // finally, get the serial number
            strSerialNumber = CString(pOutBuffer + dwSerialNumberOffset);
        // perform cleanup and return
        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);
            strReport.Format(_T("GetPhysicalDriveSerialNumber failed. Error: %u"), dwResult);
        ::MessageBox(NULL, strReport, _T("Test"), MB_OK);
    Resources and related articles
    Last edited by ovidiucucu; February 6th, 2024 at 09:18 AM. Reason: fix broken link
    "When in Rome, do as Romans do."
    My latest articles:

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts

Click Here to Expand Forum to Full Width