Hi guys,
i need to retrieve unique information from an HD (i.e. serial number or
sort of). I’ve read on the list that the IOCTL to be used is
SMART_RCV_DATA, which should work even with non-SMART capable drives. So
i’ve put together this quick test code, but the IoCallDriver returns
STATUS_IO_DEVICE_ERROR (tested only on VMWare, but i doubt its a VMWare
fault). Have i missed something ?
NTSTATUS UtilGetHdInfo ()
{
NTSTATUS Status = STATUS_UNSUCCESSFUL;
UNICODE_STRING ucName;
char* pBuffer = NULL;
PIRP Irp = NULL;
SENDCMDINPARAMS SendParams;
PFILE_OBJECT FileObject = NULL;
PDEVICE_OBJECT DeviceObject = NULL;
KEVENT Event;
IO_STATUS_BLOCK Iosb;
pBuffer = ExAllocatePool(PagedPool,sizeof (SENDCMDOUTPARAMS) + 512
- 1);
if (!pBuffer)
goto __exit;
// open physical disk 0 device
KdBreakPoint();
RtlInitUnicodeString(&ucName,L"\Device\Harddisk0\DR0");
Status = IoGetDeviceObjectPointer(&ucName,FILE_READ_ATTRIBUTES,
&FileObject,&DeviceObject);
if (!NT_SUCCESS (Status))
goto __exit;
ObDereferenceObject(FileObject);
// build and send irp to hd device
memset(&SendParams,0,sizeof (SENDCMDINPARAMS));
memset(pBuffer,0,sizeof (SENDCMDOUTPARAMS) + 512);
SendParams.cBufferSize = IDENTIFY_BUFFER_SIZE;
SendParams.bDriveNumber = 0;
SendParams.irDriveRegs.bFeaturesReg = 0;
SendParams.irDriveRegs.bCommandReg = ID_CMD;
SendParams.irDriveRegs.bSectorCountReg = 1;
SendParams.irDriveRegs.bSectorNumberReg = 0;
SendParams.irDriveRegs.bCylLowReg = SMART_CYL_LOW;
SendParams.irDriveRegs.bCylHighReg = SMART_CYL_HI;
SendParams.irDriveRegs.bDriveHeadReg = 0;
KeInitializeEvent(&Event,NotificationEvent,FALSE);
Irp = IoBuildDeviceIoControlRequest(SMART_RCV_DRIVE_DATA,
DeviceObject, &SendParams, sizeof(SENDCMDINPARAMS), pBuffer, sizeof
(SENDCMDOUTPARAMS) + 512,
FALSE, &Event, &Iosb);
// send command
Status = IoCallDriver(DeviceObject, Irp);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
Status = Iosb.Status;
}
__exit:
if (pBuffer)
ExFreePool (pBuffer);
return Status;
}
Regards,
Valerio