On Windows XP the SMART_GET_VERSION code for PhysicalDrive0 (a SATA drive)
works. On Windows 2003 Server SP1, the same code fails with
ERROR_INVALID_FUNCTION.
I've searched the DDK and knowledgebase without any luck of finding the
necessary information.
Why does the code fail?
I've found a workaround using SCSI_MINIPORT and \\.\scsi0 device name.
Please see below.
sprintf(devcName, "\\\\.\\PhysicalDrive%u", deviceId);
devcHndl = CreateFile (devcName,
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);
if (devcHndl == INVALID_HANDLE_VALUE)
{
printf("cannot open device %s error %d\n", devcName, GetLastError());
}
retVal = DeviceIoControl(devcHndl,
SMART_GET_VERSION,
NULL, 0,
&versionInfo, sizeof(GETVERSIONINPARAMS),
&retSize,
0);
if (retVal)
printf ( "Device........... %s\n"
"Driver version... %1d\n"
"Revision......... %1d\n"
"Device map....... 0x%02x\n"
"Capabilities......0x%02x\n",
devcName,
versionInfo.bVersion,
versionInfo.bRevision,
versionInfo.bIDEDeviceMap,
versionInfo.fCapabilities);
else
printf("DeviceIoControl (SMART_GET_VERSION) for %s error %d\n",
devcName, GetLastError ());
CloseHandle(devcHndl);
Workaround:
sprintf(devcName, "\\\\.\\scsi%u:", controllerId);
devcHndl = CreateFileA (devcName,
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL
);
if (devcHndl == INVALID_HANDLE_VALUE)
{
printf("cannot open device %s error %d\n", devcName, GetLastError());
}
PSENDCMDINPARAMS cmdIn = (PSENDCMDINPARAMS )&iobuff.cmdBuff;
memset(&iobuff, 0, sizeof(iobuff));
cmdIn->cBufferSize = 0;
cmdIn->bBuffer[0] = 0;
cmdIn->bDriveNumber = (BYTE) deviceId; //For IDE: 0=master;
1=slave; actual ID for SCSI
iobuff.srbCtrl.ControlCode = IOCTL_SCSI_MINIPORT_SMART_VERSION;
iobuff.srbCtrl.Length = sizeof(iobuff.cmdBuff);
iobuff.srbCtrl.HeaderLength = sizeof(SRB_IO_CONTROL);
iobuff.srbCtrl.Timeout = 1000;
memcpy(iobuff.srbCtrl.Signature, "SCSIDISK",
sizeof(iobuff.srbCtrl.Signature));
retVal = DeviceIoControl(devcHndl,
IOCTL_SCSI_MINIPORT,
&iobuff, sizeof(iobuff),
&iobuff, sizeof(iobuff),
&retSize,
0);
if (retVal)
{
versionInfo = (GETVERSIONINPARAMS *) iobuff.cmdBuff;
printf ( "Controller........... %s\n"
"Device........... %1d\n"
"Driver version... %1d\n"
"Revision......... %1d\n"
"Device map....... 0x%02x\n"
"Capabilities......0x%02x\n",
devcName,
deviceId,
versionInfo->bVersion,
versionInfo->bRevision,
versionInfo->bIDEDeviceMap,
versionInfo->fCapabilities);
}
else
printf("DeviceIoControl (IOCTL_SCSI_MINIPORT) for %d error %d\n",
controllerId, GetLastError ());
Thank you in advance.
Regards,
Mik