/* * wnaspi32.cpp * * This source file for Win 2K/XP exists to make: * * LoadLibrary("wnaspi32.dll"); * * work enough like it did in Win 9X/ME to allow * trivial apps to function. * * Our "wnaspi32.h" appears unattributed, unlicensed, * and without copyright, precisely as it reached us * via Google. * * msdn.microsoft.com probably documents what our * history of pain has taught us of this interface. * * Bugs include: * * Misbehaviour above 2 GiB per CDB. * * Drive letter = ('C' + SRB_Target). * No CloseHandle. * CreateFile called til success, for each cdb sent to a drive letter. * * Auto sense data echod out stderr, never passed back. * No check for unused for the fields not copied, e.g. SRB_SenseLen. * * x00 SC_HA_INQUIRY never becomes IOCTL_SCSI_GET_CAPABILITIES * x02 SC_EXEC_SCSI_CMD never becomes IOCTL_SCSI_PASS_THROUGH_DIRECT * * x80 SS_INVALID_CMD includes x08 SC_GETSET_TIMEOUTS * x80 SS_INVALID_CMD includes x07 SC_RESCAN_SCSI_BUS * x80 SS_INVALID_CMD includes x06 SC_GET_DISK_INFO * x80 SS_INVALID_CMD includes x05 SC_SET_HA_PARMS * x80 SS_INVALID_CMD includes x04 SC_RESET_DEV * x80 SS_INVALID_CMD includes x03 SC_ABORT_SRB * x80 SS_INVALID_CMD includes x01 SC_GET_DEV_TYPE */ #include "windows.h" #include "ntddscsi.hpp" #include #include #include "gccscsi.h" #include "wnaspi32.hpp" #define TARGET_COUNT (1 << 5) /* enough for 'C' .. 'Z' and one host */ int devs[TARGET_COUNT]; extern "C" { extern DWORD GetASPI32SupportInfo(void); extern DWORD SendASPI32Command(LPSRB v); } __declspec(dllexport) extern DWORD GetASPI32SupportInfo(void) { BYTE srbStatus = SS_NO_ADAPTERS; /* xE8 */ BYTE haCount = ('Z' - 'A' + 1); srbStatus = SS_COMP; /* x01 */ return ((srbStatus << 8) | haCount); } static BYTE ha_inquiry(SRB_HAInquiry * shai) { WORD alignment_mask = (4 * Ki); BYTE may_count_data = 0x01; DWORD max_length = (64 * Ki); shai->HA_Count = 1; shai->HA_SCSI_ID = (TARGET_COUNT - 1); memset(&shai->HA_ManagerId[0], '\0', sizeof shai->HA_ManagerId); memset(&shai->HA_Identifier[0], '\0', sizeof shai->HA_Identifier); memset(&shai->HA_Unique[0], '\0', sizeof shai->HA_Unique); strncpy((char *) &shai->HA_ManagerId[0], "Wnaspi32.dll", sizeof shai->HA_ManagerId); strncpy((char *) &shai->HA_Identifier[0], "Slow SPT (not SPTD)", sizeof shai->HA_Identifier); * (WORD *) &shai->HA_Unique[0x00] = alignment_mask; * (BYTE *) &shai->HA_Unique[0x02] = may_count_data; * (BYTE *) &shai->HA_Unique[0x03] = TARGET_COUNT; * (DWORD *) &shai->HA_Unique[0x04] = max_length; return SS_COMP; /* x01 */ } static BYTE exec_scsi_cmd(SRB_ExecSCSICmd * sesc) { BYTE SRB_Target = sesc->SRB_Target; BYTE SRB_Lun = sesc->SRB_Lun; int letter = ('C' + SRB_Target); if (!(('A' <= letter) & (letter <= 'Z'))) return SS_NO_DEVICE; /* x82 */ if (SRB_Lun != 0x00) return SS_NO_DEVICE; /* x82 */ int dev = devs[SRB_Target]; if (dev == 0) { char name[123] = "//./A:"; sprintf(&name[0], "\\\\.\\%c:", letter); dev = sp_open(&name[0]); } if (dev == 0) return SS_NO_DEVICE; /* x82 */ char * cdbChars = (char *) &sesc->CDBByte[0]; int cdbLength = sesc->SRB_CDBLen; char * inChars = (char *) sesc->SRB_BufPointer; char * outChars = inChars; int maxLength = (int) sesc->SRB_BufLen; BYTE SRB_Flags = sesc->SRB_Flags; BYTE SRB_Flags_In_Out = (SRB_Flags & (SRB_DIR_OUT|SRB_DIR_IN)); /* x18 */ if (maxLength == 0) { outChars = inChars = NULL; } else if (SRB_Flags_In_Out == SRB_DIR_IN) { /* x08 */ outChars = NULL; } else if (SRB_Flags_In_Out == SRB_DIR_OUT) { /* x10 */ inChars = NULL; } else { return SS_INVALID_SRB; /* xE0 */ } int rc = sp_say(dev, cdbChars, cdbLength, outChars, inChars, maxLength); if (rc == 0) { sesc->SRB_HaStat = HASTAT_OK; /* x00 */ sesc->SRB_TargStat = 0x00; /* good */ return SS_COMP; /* x01 */ } if (0 < rc) { sesc->SRB_HaStat = HASTAT_DO_DU; /* x12 */ sesc->SRB_TargStat = 0x00; /* good */ return SS_ERR; /* x04 */ } sesc->SRB_HaStat = HASTAT_BUS_FREE; /* x13 */ sesc->SRB_TargStat = 0x00; /* good */ return SS_ERR; /* x04 */ } __declspec(dllexport) extern DWORD SendASPI32Command(LPSRB v) { BYTE srbStatus = SS_INVALID_CMD; /* x80 */ SRB_Abort * sa = (SRB_Abort *) v; if (sa->SRB_HaId != 0) { return SS_INVALID_HA; } switch (sa->SRB_Cmd) { case SC_HA_INQUIRY: /* x00 */ srbStatus = ha_inquiry((SRB_HAInquiry *) v); break; case SC_EXEC_SCSI_CMD: /* x02 */ srbStatus = exec_scsi_cmd((SRB_ExecSCSICmd *) v); break; default: break; } sa->SRB_Status = srbStatus; return srbStatus; } /* end of file */