Sending a specific SCSI command to a SCSI device in Windows

Ganesh picture Ganesh · Jul 23, 2010 · Viewed 9.4k times · Source

Does windows have specific interface by which I can send a specific scsi command such Inquiry to scsi device ? I searched the net, found passing reference to SCSI Pass Through interface. But Its very Vague.

Is there any documentation for that API on how to use it??

Answer

Hardy Feng picture Hardy Feng · Feb 8, 2013
#include <iostream>
#include <windows.h>
#include <winioctl.h>
#define ULONG_PTR ULONG
#include <ntddscsi.h> //from SDK
#include <spti.h>      //from DDK 
using namespace std;

int demo()
{
    HANDLE hDisk;
    SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER sptdwb; 
    ULONG length = 0;
    DWORD bytesReturn;
    BYTE bufDataRead[64*1024+10];
    int iRet;        

    hDisk = CreateFile(path,GENERIC_READ | GENERIC_WRITE,     
            FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,OPEN_EXISTING,0,NULL                                 
            );
    if (hDisk ==INVALID_HANDLE_VALUE)  {              
          return 0;
    }
    ZeroMemory(&sptdwb, sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER));
    sptdwb.sptd.Length = sizeof(SCSI_PASS_THROUGH_DIRECT);
    sptdwb.sptd.PathId = 0;
    sptdwb.sptd.TargetId = 1;
    sptdwb.sptd.Lun = 0;
    sptdwb.sptd.CdbLength = 6;
    sptdwb.sptd.DataIn = SCSI_IOCTL_DATA_IN;
    sptdwb.sptd.SenseInfoLength = 24;
    sptdwb.sptd.DataTransferLength = 8; 
    sptdwb.sptd.TimeOutValue = 2;
    sptdwb.sptd.DataBuffer = bufDataRead; 
    sptdwb.sptd.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER,ucSenseBuf);       
    sptdwb.sptd.Cdb[0] = 0x12;
    sptdwb.sptd.Cdb[1] = 0x00;
    sptdwb.sptd.Cdb[2] = 0x00;
    sptdwb.sptd.Cdb[3] = 0x00;
    sptdwb.sptd.Cdb[4] = 0xFF;
    sptdwb.sptd.Cdb[5] = 0x00;

    length = sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER);
    iRet = DeviceIoControl(hDisk,
            IOCTL_SCSI_PASS_THROUGH_DIRECT,
            &sptdwb,
            length,
            &sptdwb,
            length,
            &bytesReturn,
            NULL);
    if (0 == iRet)  {
        printf("inquiry fail");
        return 0;
    } else {
    //Check returned data in sptdwb.sptd.DataBuffer.
    }       
    return 0;

}