Concise, neat and centralized code which showing in the forum is very important for me, especially for those who are eager to find an off-the-shelf solution (like me).
Here is the fixed version:
...
#include <ntddstor.h>
#define DEVICE_DESCRIPTOR 'CDVD'
#define SERIAL_NUMBER 'BNRS'
...
NTSTATUS GetHardDiskDriveSerialNumber(_Out_ PCHAR *pSerialNumber, _Out_ SIZE_T *pLength) {
NTSTATUS status = STATUS_SUCCESS;
STORAGE_PROPERTY_QUERY storagePropertyQuery = { StorageDeviceProperty, PropertyStandardQuery, 0 };
STORAGE_DESCRIPTOR_HEADER storageDescriptorHeader = { 0 };
PSTORAGE_DEVICE_DESCRIPTOR pDeviceDescriptor = nullptr;
UNICODE_STRING fileName;
RtlInitUnicodeString(&fileName, L"\\DosDevices\\PhysicalDrive0");
OBJECT_ATTRIBUTES attributes;
InitializeObjectAttributes(&attributes, &fileName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, nullptr, nullptr);
HANDLE fileHandle = nullptr;
IO_STATUS_BLOCK ioStatus;
// open PhysicalDrive0
status = ZwCreateFile(
&fileHandle,
GENERIC_READ,
&attributes,
&ioStatus,
nullptr,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_OPEN,
FILE_NON_DIRECTORY_FILE,
nullptr,
0);
if (!NT_SUCCESS(status) || !NT_SUCCESS(ioStatus.Status)) {
KdPrint(("Open PhysicalDrive0 failed, status: %!STATUS!, ioStatus: %!STATUS!, information: %llu.\n",
status, ioStatus.Status, ioStatus.Information));
if (!NT_SUCCESS(ioStatus.Status))
status = ioStatus.Status;
goto END;
}
KdPrint(("Open PhysicalDrive0 success: %p.\n", fileHandle));
// first call for getting size
status = ZwDeviceIoControlFile(
fileHandle,
nullptr,
nullptr,
nullptr,
&ioStatus,
IOCTL_STORAGE_QUERY_PROPERTY,
&storagePropertyQuery,
sizeof(STORAGE_PROPERTY_QUERY),
&storageDescriptorHeader,
sizeof(STORAGE_DESCRIPTOR_HEADER));
if (!NT_SUCCESS(status) || !NT_SUCCESS(ioStatus.Status)) {
KdPrint(("ZwDeviceIoControlFile first call failed, status: %!STATUS!, ioStatus: %!STATUS!, information: %llu.\n",
status, ioStatus.Status, ioStatus.Information));
if (!NT_SUCCESS(ioStatus.Status))
status = ioStatus.Status;
goto END;
}
// alloc for descriptor
pDeviceDescriptor = (PSTORAGE_DEVICE_DESCRIPTOR)ExAllocatePoolWithTag(NonPagedPoolNx, storageDescriptorHeader.Size, DEVICE_DESCRIPTOR);
if (!pDeviceDescriptor) {
status = STATUS_INSUFFICIENT_RESOURCES;
goto END;
}
RtlZeroMemory(pDeviceDescriptor, storageDescriptorHeader.Size);
// second call for getting serial number
status = ZwDeviceIoControlFile(
fileHandle,
nullptr,
nullptr,
nullptr,
&ioStatus,
IOCTL_STORAGE_QUERY_PROPERTY,
&storagePropertyQuery,
sizeof(STORAGE_PROPERTY_QUERY),
pDeviceDescriptor,
storageDescriptorHeader.Size);
if (!NT_SUCCESS(status) || !NT_SUCCESS(ioStatus.Status)) {
KdPrint(("ZwDeviceIoControlFile second call failed, status: %!STATUS!, ioStatus: %!STATUS!, information: %llu.\n",
status, ioStatus.Status, ioStatus.Information));
if (!NT_SUCCESS(ioStatus.Status))
status = ioStatus.Status;
goto END;
}
if (pDeviceDescriptor->SerialNumberOffset > 0) {
PCHAR originSerialNumber = WDF_PTR_ADD_OFFSET_TYPE(pDeviceDescriptor, pDeviceDescriptor->SerialNumberOffset, PCHAR);
KdPrint(("SerialNumber: %s.\n", originSerialNumber));
status = RtlStringCbLengthA(originSerialNumber, 128, pLength);
if (!NT_SUCCESS(status)) {
KdPrint(("RtlStringCbLengthA failed, string: %s.\n", originSerialNumber));
goto END;
}
SIZE_T bufferSize = (*pLength) + 1; // include terminating null character
PCHAR serialNumber = (PCHAR)ExAllocatePoolWithTag(NonPagedPoolNx, bufferSize, SERIAL_NUMBER);
if (!serialNumber) {
status = STATUS_INSUFFICIENT_RESOURCES;
goto END;
}
RtlZeroMemory(serialNumber, bufferSize);
status = RtlStringCbCopyA(serialNumber, bufferSize, originSerialNumber);
if (!NT_SUCCESS(status)) {
KdPrint(("RtlStringCbCopyA failed, status: %!STATUS!, string: %s.\n", status, originSerialNumber));
if (serialNumber)
ExFreePoolWithTag(serialNumber, SERIAL_NUMBER);
goto END;
}
*pSerialNumber = serialNumber;
} else {
KdPrint(("SerialNumberOffset: %u.\n", pDeviceDescriptor->SerialNumberOffset));
status = STATUS_QUERY_STORAGE_ERROR;
*pSerialNumber = nullptr;
*pLength = 0;
}
END:
if (fileHandle)
ZwClose(fileHandle);
if (pDeviceDescriptor)
ExFreePoolWithTag(pDeviceDescriptor, DEVICE_DESCRIPTOR);
return status;
}
VOID FreeHardDiskDriveSerialNumber(_In_ PCHAR serialNumber) {
ExFreePoolWithTag(serialNumber, SERIAL_NUMBER);
}