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