#include #include // for offsetof #include #include typedef struct { USHORT Length; UCHAR ScsiStatus; UCHAR PathId; UCHAR TargetId; UCHAR Lun; UCHAR CdbLength; UCHAR SenseInfoLength; UCHAR DataIn; ULONG DataTransferLength; ULONG TimeOutValue; PVOID DataBuffer; ULONG SenseInfoOffset; UCHAR Cdb[16]; } SCSI_PASS_THROUGH_DIRECT, *PSCSI_PASS_THROUGH_DIRECT; typedef struct { SCSI_PASS_THROUGH_DIRECT spt; ULONG Filler; UCHAR ucSenseBuf[32]; } SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, *PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER; #define IOCTL_SCSI_BASE 0x00000004 /* * constants for DataIn member of SCSI_PASS_THROUGH* structures */ #define SCSI_IOCTL_DATA_OUT 0 #define SCSI_IOCTL_DATA_IN 1 #define SCSI_IOCTL_DATA_UNSPECIFIED 2 /* * Standard IOCTL define */ #define CTL_CODE( DevType, Function, Method, Access ) ( \ ((DevType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \ ) #define IOCTL_SCSI_PASS_THROUGH CTL_CODE( IOCTL_SCSI_BASE, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS ) #define IOCTL_SCSI_MINIPORT CTL_CODE( IOCTL_SCSI_BASE, 0x0402, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS ) #define IOCTL_SCSI_GET_INQUIRY_DATA CTL_CODE( IOCTL_SCSI_BASE, 0x0403, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_SCSI_GET_CAPABILITIES CTL_CODE( IOCTL_SCSI_BASE, 0x0404, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_SCSI_PASS_THROUGH_DIRECT CTL_CODE( IOCTL_SCSI_BASE, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS ) #define IOCTL_SCSI_GET_ADDRESS CTL_CODE( IOCTL_SCSI_BASE, 0x0406, METHOD_BUFFERED, FILE_ANY_ACCESS static bool scsi_inquiry(HANDLE deviceHandle, UCHAR page, UCHAR *inqbuf, size_t &buf_len) { char buf[2048] = {0}; BOOL status; PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER pswb; DWORD length=0, returned=0; /* * Get the drive inquiry data */ ZeroMemory( &buf, 2048 ); ZeroMemory( inqbuf, buf_len ); pswb = (PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER)buf; pswb->spt.Length = sizeof(SCSI_PASS_THROUGH_DIRECT); pswb->spt.CdbLength = 6; pswb->spt.SenseInfoLength = 32; pswb->spt.DataIn = SCSI_IOCTL_DATA_IN; pswb->spt.DataTransferLength = buf_len; pswb->spt.TimeOutValue = 2; pswb->spt.DataBuffer = inqbuf; pswb->spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER,ucSenseBuf); pswb->spt.Cdb[0] = 0x12; pswb->spt.Cdb[1] = 0x1; pswb->spt.Cdb[2] = page; pswb->spt.Cdb[4] = (UCHAR)buf_len; length = sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER); status = DeviceIoControl( deviceHandle, IOCTL_SCSI_PASS_THROUGH_DIRECT, pswb, length, pswb, length, &returned, NULL ); if (status && returned >3) { buf_len=returned; return true; } else { buf_len=0; return false; } } static bool AddPagetoXML(HANDLE dev, char *&dest, size_t &destlen, UCHAR page) { UCHAR buf[256] = {0}; size_t buflen=255; if (scsi_inquiry(dev, page, buf, buflen)) { size_t len = buf[3]; StringCchCopyNExA(dest, destlen, (char *)buf+4, len, &dest, &destlen, 0); return true; } return false; } static bool BuildXML(HANDLE dev, char *xml, size_t xmllen) { *xml=0; UCHAR pages[255] = {0}; size_t pageslen=255; if (scsi_inquiry(dev, 0xc0, pages, pageslen) && pageslen>3) { unsigned char numPages=pages[3]; if (numPages+4 <= 255) { for (int i=0;i