#include #include #include //returns the serial number of the first physical drive in a std::string or an empty std::string in case of failure //based on http://codexpert.ro/blog/2013/10/26/get-physical-drive-serial-number-part-1/ std::string getFirstHddSerialNumber() { //get a handle to the first physical drive HANDLE h = CreateFileW(L"\\\\.\\PhysicalDrive0", 0, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if(h == INVALID_HANDLE_VALUE) return {}; //an std::unique_ptr is used to perform cleanup automatically when returning (i.e. to avoid code duplication) std::unique_ptr::type, void(*)(HANDLE)> hDevice{h, [](HANDLE handle){CloseHandle(handle);}}; //initialize a STORAGE_PROPERTY_QUERY data structure (to be used as input to DeviceIoControl) STORAGE_PROPERTY_QUERY storagePropertyQuery{}; storagePropertyQuery.PropertyId= StorageDeviceProperty; storagePropertyQuery.QueryType= PropertyStandardQuery; //initialize a STORAGE_DESCRIPTOR_HEADER data structure (to be used as output from DeviceIoControl) STORAGE_DESCRIPTOR_HEADER storageDescriptorHeader{}; //the next call to DeviceIoControl retrieves necessary size (in order to allocate a suitable buffer) //call DeviceIoControl and return an empty std::string on failure DWORD dwBytesReturned= 0; if(!DeviceIoControl(hDevice.get(), IOCTL_STORAGE_QUERY_PROPERTY, &storagePropertyQuery, sizeof(STORAGE_PROPERTY_QUERY), &storageDescriptorHeader, sizeof(STORAGE_DESCRIPTOR_HEADER), &dwBytesReturned, NULL)) return {}; //allocate a suitable buffer const DWORD dwOutBufferSize= storageDescriptorHeader.Size; std::unique_ptr pOutBuffer{new BYTE[dwOutBufferSize]{}}; //call DeviceIoControl with the allocated buffer if(!DeviceIoControl(hDevice.get(), IOCTL_STORAGE_QUERY_PROPERTY, &storagePropertyQuery, sizeof(STORAGE_PROPERTY_QUERY), pOutBuffer.get(), dwOutBufferSize, &dwBytesReturned, NULL)) return {}; //read and return the serial number out of the output buffer STORAGE_DEVICE_DESCRIPTOR* pDeviceDescriptor= reinterpret_cast(pOutBuffer.get()); const DWORD dwSerialNumberOffset= pDeviceDescriptor->SerialNumberOffset; if(dwSerialNumberOffset==0) return {}; const char* serialNumber= reinterpret_cast(pOutBuffer.get() + dwSerialNumberOffset); return serialNumber; } #include int main() { std::string serialNumber = getFirstHddSerialNumber(); if(serialNumber.empty()) std::cout << "failed to retrieve serial number\n"; else std::cout << "serial number: " << serialNumber << "\n"; return 0; }