Writing Portable Win32 SCSI Applications
by Thomas Tewell

Listing One
if(GetVersion() < 0x8000000)
{
    Windows NT
}
else
{
    Windows 95
}

Listing Two
//-------------------------------------------------------------------
// Open SCSI Port Driver
//-------------------------------------------------------------------
wsprintf(adapter_name,"\\\\.\\SCSI%d:",AdapterCount);
fileHandle = CreateFile(adapter_name, GENERIC_WRITE | GENERIC_READ,
          FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);

Listing Three
status = DeviceIoControl(fileHandle, IOCTL_SCSI_GET_INQUIRY_DATA, NULL, 0,
                                    InquiryBuffer, 2048, &returned, FALSE);

Listing Four
UCHAR NumberOfBuses;

// Each structure allocated contiguously for each bus 
// indicated in NumberOfBuses
SCSI_BUS_DATA BusData[x]; 

// Each structure allocated contiguously for each bus indicated in
// BusData[x].NumberOfLogicalUnits
SCSI_INQUIRY_DATA DeviceData[x];  // one structure for each device indicated 
                                  // in SCSI_BUS_DATA

Listing Five
typedef struct _ASPI_ENTRY {
    SCSI_PASS_THROUGH_DIRECT Srb;    
    ULONG Filler;
    BYTE ucSenseBuf[32];
    HANDLE hFileHandle;
    BYTE byDeviceType;
    BYTE byPath;
    BYTE byTarget;
    BYTE byLun;
    BOOL fDeviceClaimed;
    struct _ASPI_ENTRY *AEForwardPtr;
    struct _ASPI_ENTRY *AEBackwardPtr;
} ASPI_ENTRY, *PASPI_ENTRY;

Listing Six
strcpy(devname,"\\\\.\\");
strcat(devname,bufptr);
bufptr += strlen(bufptr);
++bufptr;

fileHandle = CreateFile(devname, GENERIC_WRITE | GENERIC_READ,
           FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
//---------------------------------------
// if device won't open, try read only...
//---------------------------------------
if(fileHandle == INVALID_HANDLE_VALUE)
{
    fileHandle = CreateFile(devname, GENERIC_READ, FILE_SHARE_READ, NULL,
                                                     OPEN_EXISTING, 0, NULL);
}

Listing Seven
status = DeviceIoControl(fileHandle, IOCTL_SCSI_GET_ADDRESS, NULL, 0, &sa,
                                 sizeof(SCSI_ADDRESS), &returned, FALSE);


Listing Eight
typedef struct _SCSI_PASS_THROUGH_DIRECT {
    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;

Listing Nine
return(DeviceIoControl(pae->hFileHandle, IOCTL_SCSI_PASS_THROUGH_DIRECT,
                &pae->Srb, sizeof(ASPI_ENTRY), &pae->Srb,
                sizeof(ASPI_ENTRY), &returned, FALSE) ? 0 : GetLastError());

Listing Ten
if((ASPICompletionEvent = CreateEvent(NULL,FALSE,FALSE,NULL)) == NULL)
{
    return(ERROR_RESOURCE_FAILURE);
}
de->AspiSrb.SRB_Flags      = SRB_DIR_IN;
de->AspiSrb.SRB_BufLen     = INQUIRY_DATA_SIZE;
de->AspiSrb.SRB_BufPointer = (BYTE *)&de->InquiryData;
de->AspiSrb.SRB_CDBLen     = 6;
de->AspiSrb.CDBByte[0]     = 0x12;
de->AspiSrb.CDBByte[1]     = (de->AspiSrb.SRB_Lun << 5);
de->AspiSrb.CDBByte[2]     = 0;
de->AspiSrb.CDBByte[3]     = 0;
de->AspiSrb.CDBByte[4]     = INQUIRY_DATA_SIZE;
de->AspiSrb.CDBByte[5]     = 0;
de->AspiSrb.SRB_Status     = SS_PENDING;
de->AspiSrb.SRB_Flags     |= SRB_EVENT_NOTIFY;
de->AspiSrb.SRB_PostProc   = ASPICompletionEvent;
de->AspiSrb.SRB_Time_Out   = de->TimeOut;

SendASPI32Command(&de->AspiSrb);

if(de->AspiSrb.SRB_Status == SS_PENDING)
{
    WaitForSingleObject(ASPICompletionEvent, INFINITE);
}
    CloseHandle(ASPICompletionEvent);

3


