From 961041e0ee56ee6cbcbf39739c12eb7af8b44a25 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Tue, 10 Mar 2020 17:50:43 +0100 Subject: [PATCH] winaspi: Reimplement on top of wnaspi32. Signed-off-by: Alexandre Julliard --- dlls/winaspi.dll16/Makefile.in | 2 +- dlls/winaspi.dll16/winaspi.c | 484 +++++---------------------------- 2 files changed, 71 insertions(+), 415 deletions(-) diff --git a/dlls/winaspi.dll16/Makefile.in b/dlls/winaspi.dll16/Makefile.in index 21d8ae76a36..e248c2abd7f 100644 --- a/dlls/winaspi.dll16/Makefile.in +++ b/dlls/winaspi.dll16/Makefile.in @@ -1,5 +1,5 @@ MODULE = winaspi.dll16 -IMPORTS = advapi32 +IMPORTS = wnaspi32 advapi32 EXTRADLLFLAGS = -m16 -Wb,--main-module,wnaspi32.dll C_SRCS = winaspi.c diff --git a/dlls/winaspi.dll16/winaspi.c b/dlls/winaspi.dll16/winaspi.c index 4675c1e1651..f571ff580c7 100644 --- a/dlls/winaspi.dll16/winaspi.c +++ b/dlls/winaspi.dll16/winaspi.c @@ -17,16 +17,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#include "config.h" -#include "wine/port.h" - #include #include -#include -#include -#ifdef HAVE_UNISTD_H -# include -#endif #include #include #include @@ -35,421 +27,31 @@ #include "winbase.h" #include "wine/windef16.h" #include "wine/winbase16.h" +#include "wnaspi32.h" #include "winreg.h" #include "wownt32.h" #include "aspi.h" #include "wine/winaspi.h" #include "wine/debug.h" - -/* FIXME! - * 1) Residual byte length reporting not handled - * 2) Make this code re-entrant for multithreading - * 3) Only linux supported so far - */ - -#ifdef linux - -/* Copy of info from 2.2.x kernel */ -#define SG_MAX_SENSE 16 /* too little, unlikely to change in 2.2.x */ - -struct sg_header -{ - int pack_len; /* [o] reply_len (ie useless), ignored as input */ - int reply_len; /* [i] max length of expected reply (inc. sg_header) */ - int pack_id; /* [io] id number of packet (use ints >= 0) */ - int result; /* [o] 0==ok, else (+ve) Unix errno (best ignored) */ - unsigned int twelve_byte:1; - /* [i] Force 12 byte command length for group 6 & 7 commands */ - unsigned int target_status:5; /* [o] scsi status from target */ - unsigned int host_status:8; /* [o] host status (see "DID" codes) */ - unsigned int driver_status:8; /* [o] driver status+suggestion */ - unsigned int other_flags:10; /* unused */ - unsigned char sense_buffer[SG_MAX_SENSE]; /* [o] Output in 3 cases: - when target_status is CHECK_CONDITION or - when target_status is COMMAND_TERMINATED or - when (driver_status & DRIVER_SENSE) is true. */ -}; /* This structure is 36 bytes long on i386 */ - -#define SCSI_OFF sizeof(struct sg_header) - WINE_DEFAULT_DEBUG_CHANNEL(aspi); -/* Just a container for seeing what devices are open */ -struct ASPI_DEVICE_INFO { - struct ASPI_DEVICE_INFO * next; - int fd; - int hostId; - int target; - int lun; -}; - -typedef struct ASPI_DEVICE_INFO ASPI_DEVICE_INFO; - -static ASPI_DEVICE_INFO *ASPI_open_devices = NULL; - static FARPROC16 ASPIChainFunc = NULL; -static WORD HA_Count = 1; /* host adapter count; FIXME: detect it */ +static FARPROC16 exec_postproc16; +static SEGPTR exec_cmd16; -static int -ASPI_OpenDevice16(SRB_ExecSCSICmd16 *prb) +static void SRB_PostProc( SRB_ExecSCSICmd *cmd32 ) { - HKEY hkey; - int fd; - char idstr[50]; - char device_str[50]; - ASPI_DEVICE_INFO *curr; - - /* search list of devices to see if we've opened it already. - * There is not an explicit open/close in ASPI land, so hopefully - * keeping a device open won't be a problem. - */ - - for (curr = ASPI_open_devices; curr; curr = curr->next) { - if (curr->hostId == prb->SRB_HaId && - curr->target == prb->SRB_Target && - curr->lun == prb->SRB_Lun) { - return curr->fd; - } - } - - /* device wasn't cached, go ahead and open it */ - sprintf( idstr, "Software\\Wine\\Wine\\Config\\scsi c%1dt%1dd%1d", - prb->SRB_HaId, prb->SRB_Target, prb->SRB_Lun); - - device_str[0] = 0; - if (!RegOpenKeyExA( HKEY_LOCAL_MACHINE, idstr, 0, KEY_ALL_ACCESS, &hkey )) - { - DWORD type, count = sizeof(device_str); - if (RegQueryValueExA( hkey, "Device", 0, &type, (LPBYTE)device_str, &count )) device_str[0] = 0; - RegCloseKey( hkey ); - } - - if (!device_str[0]) - { - TRACE("Trying to open unlisted scsi device %s\n", idstr); - return -1; - } - - TRACE("Opening device %s=%s\n", idstr, device_str); - - fd = open(device_str, O_RDWR); - if (fd == -1) { - int save_error = errno; - ERR("Error opening device %s, error '%s'\n", device_str, strerror(save_error)); - return -1; - } - - /* device is now open */ - curr = HeapAlloc( GetProcessHeap(), 0, sizeof(ASPI_DEVICE_INFO) ); - curr->fd = fd; - curr->hostId = prb->SRB_HaId; - curr->target = prb->SRB_Target; - curr->lun = prb->SRB_Lun; - - /* insert new record at beginning of open device list */ - curr->next = ASPI_open_devices; - ASPI_open_devices = curr; - return fd; + WOWCallback16( (DWORD)exec_postproc16, exec_cmd16 ); } -static void -ASPI_DebugPrintCmd(SRB_ExecSCSICmd16 *prb) -{ - int i; - BYTE *cdb; - BYTE *lpBuf = MapSL( prb->SRB_BufPointer ); - - switch (prb->CDBByte[0]) { - case CMD_INQUIRY: - TRACE("{\n"); - TRACE("\tEVPD: %d\n", prb->CDBByte[1] & 1); - TRACE("\tLUN: %d\n", (prb->CDBByte[1] & 0xc) >> 1); - TRACE("\tPAGE CODE: %d\n", prb->CDBByte[2]); - TRACE("\tALLOCATION LENGTH: %d\n", prb->CDBByte[4]); - TRACE("\tCONTROL: %d\n", prb->CDBByte[5]); - TRACE("}\n"); - break; - case CMD_SCAN_SCAN: - TRACE("Transfer Length: %d\n", prb->CDBByte[4]); - break; - } - - TRACE("Host Adapter: %d\n", prb->SRB_HaId); - TRACE("Flags: %d\n", prb->SRB_Flags); - if (TARGET_TO_HOST(prb)) { - TRACE("\tData transfer: Target to host. Length checked.\n"); - } - else if (HOST_TO_TARGET(prb)) { - TRACE("\tData transfer: Host to target. Length checked.\n"); - } - else if (NO_DATA_TRANSFERRED(prb)) { - TRACE("\tData transfer: none\n"); - } - else { - WARN("\tTransfer by scsi cmd. Length not checked\n"); - } - - TRACE("\tResidual byte length reporting %s\n", prb->SRB_Flags & 0x4 ? "enabled" : "disabled"); - TRACE("\tLinking %s\n", prb->SRB_Flags & 0x2 ? "enabled" : "disabled"); - TRACE("\tPosting %s\n", prb->SRB_Flags & 0x1 ? "enabled" : "disabled"); - TRACE("Target: %d\n", prb->SRB_Target); - TRACE("Lun: %d\n", prb->SRB_Lun); - TRACE("BufLen: %d\n", prb->SRB_BufLen); - TRACE("SenseLen: %d\n", prb->SRB_SenseLen); - TRACE("BufPtr: %x (%p)\n", prb->SRB_BufPointer, lpBuf); - TRACE("LinkPointer %x\n", prb->SRB_Rsvd1); - TRACE("CDB Length: %d\n", prb->SRB_CDBLen); - TRACE("POST Proc: %x\n", (DWORD) prb->SRB_PostProc); - cdb = prb->CDBByte; - if (TRACE_ON(aspi)) - { - TRACE("CDB buffer["); - for (i = 0; i < prb->SRB_CDBLen; i++) { - if (i != 0) TRACE(","); - TRACE("%02x", *cdb++); - } - TRACE("]\n"); - } -} - -static void -ASPI_PrintSenseArea16(SRB_ExecSCSICmd16 *prb) -{ - int i; - BYTE *cdb; - - if (TRACE_ON(aspi)) - { - cdb = prb->CDBByte; - TRACE("SenseArea["); - for (i = 0; i < prb->SRB_SenseLen; i++) { - if (i) TRACE(","); - TRACE("%02x", *cdb++); - } - TRACE("]\n"); - } -} - -static void -ASPI_DebugPrintResult(SRB_ExecSCSICmd16 *prb) -{ - BYTE *lpBuf = MapSL( prb->SRB_BufPointer ); - - switch (prb->CDBByte[0]) { - case CMD_INQUIRY: - TRACE("Vendor: '%s'\n", lpBuf + INQUIRY_VENDOR); - break; - case CMD_TEST_UNIT_READY: - ASPI_PrintSenseArea16(prb); - break; - } -} - -static WORD -ASPI_ExecScsiCmd(DWORD ptrPRB) -{ - SRB_ExecSCSICmd16 *lpPRB = MapSL( ptrPRB ); - struct sg_header *sg_hd, *sg_reply_hdr; - int status; - BYTE *lpBuf = 0; - int in_len, out_len; - int error_code = 0; - int fd; - - ASPI_DebugPrintCmd(lpPRB); - - fd = ASPI_OpenDevice16(lpPRB); - if (fd == -1) { - WARN("Failed: could not open device. Device permissions !?\n"); - lpPRB->SRB_Status = SS_ERR; - return SS_ERR; - } - - sg_hd = NULL; - sg_reply_hdr = NULL; - - lpPRB->SRB_Status = SS_PENDING; - lpBuf = MapSL( lpPRB->SRB_BufPointer ); - - if (!lpPRB->SRB_CDBLen) { - WARN("Failed: lpPRB->SRB_CDBLen = 0.\n"); - lpPRB->SRB_Status = SS_ERR; - return SS_ERR; - } - - /* build up sg_header + scsi cmd */ - if (HOST_TO_TARGET(lpPRB)) { - /* send header, command, and then data */ - in_len = SCSI_OFF + lpPRB->SRB_CDBLen + lpPRB->SRB_BufLen; - sg_hd = HeapAlloc(GetProcessHeap(), 0, in_len); - memset(sg_hd, 0, SCSI_OFF); - memcpy(sg_hd + 1, lpPRB->CDBByte, lpPRB->SRB_CDBLen); - if (lpPRB->SRB_BufLen) { - memcpy(((BYTE *) sg_hd) + SCSI_OFF + lpPRB->SRB_CDBLen, lpBuf, lpPRB->SRB_BufLen); - } - } - else { - /* send header and command - no data */ - in_len = SCSI_OFF + lpPRB->SRB_CDBLen; - sg_hd = HeapAlloc(GetProcessHeap(), 0, in_len); - memset(sg_hd, 0, SCSI_OFF); - memcpy(sg_hd + 1, lpPRB->CDBByte, lpPRB->SRB_CDBLen); - } - - if (TARGET_TO_HOST(lpPRB)) { - out_len = SCSI_OFF + lpPRB->SRB_BufLen; - sg_reply_hdr = HeapAlloc(GetProcessHeap(), 0, out_len); - memset(sg_reply_hdr, 0, SCSI_OFF); - sg_hd->reply_len = out_len; - } - else { - out_len = SCSI_OFF; - sg_reply_hdr = HeapAlloc(GetProcessHeap(), 0, out_len); - memset(sg_reply_hdr, 0, SCSI_OFF); - sg_hd->reply_len = out_len; - } - - status = write(fd, sg_hd, in_len); - if (status < 0 || status != in_len) { - int save_error = errno; - - WARN("Not enough bytes written to scsi device bytes=%d .. %d\n", in_len, status); - if (status < 0) { - if (save_error == ENOMEM) { - MESSAGE("ASPI: Linux generic scsi driver\n You probably need to re-compile your kernel with a larger SG_BIG_BUFF value (sg.h)\n Suggest 130560\n"); - } - WARN("error:= '%s'\n", strerror(save_error)); - } - goto error_exit; - } - - status = read(fd, sg_reply_hdr, out_len); - if (status < 0 || status != out_len) { - WARN("not enough bytes read from scsi device%d\n", status); - goto error_exit; - } - - if (sg_reply_hdr->result != 0) { - error_code = sg_reply_hdr->result; - WARN("reply header error (%d)\n", sg_reply_hdr->result); - goto error_exit; - } - - if (TARGET_TO_HOST(lpPRB) && lpPRB->SRB_BufLen) { - memcpy(lpBuf, sg_reply_hdr + 1, lpPRB->SRB_BufLen); - } - - /* copy in sense buffer to amount that is available in client */ - if (lpPRB->SRB_SenseLen) { - int sense_len = lpPRB->SRB_SenseLen; - if (lpPRB->SRB_SenseLen > 16) - sense_len = 16; - memcpy(SENSE_BUFFER(lpPRB), sg_reply_hdr->sense_buffer, sense_len); - } - - - lpPRB->SRB_Status = SS_COMP; - lpPRB->SRB_HaStat = HASTAT_OK; - lpPRB->SRB_TargStat = STATUS_GOOD; - - /* now do posting */ - - if (ASPI_POSTING(lpPRB) && lpPRB->SRB_PostProc) { - TRACE("Post Routine (%x) called\n", (DWORD) lpPRB->SRB_PostProc); - WOWCallback16((DWORD)lpPRB->SRB_PostProc, ptrPRB); - } - - HeapFree(GetProcessHeap(), 0, sg_reply_hdr); - HeapFree(GetProcessHeap(), 0, sg_hd); - ASPI_DebugPrintResult(lpPRB); - return SS_COMP; - -error_exit: - if (error_code == EBUSY) { - lpPRB->SRB_Status = SS_ASPI_IS_BUSY; - TRACE("Device busy\n"); - } - else { - WARN("Failed\n"); - lpPRB->SRB_Status = SS_ERR; - } - - /* I'm not sure exactly error codes work here - * We probably should set lpPRB->SRB_TargStat, SRB_HaStat ? - */ - WARN("error_exit\n"); - HeapFree(GetProcessHeap(), 0, sg_reply_hdr); - HeapFree(GetProcessHeap(), 0, sg_hd); - return lpPRB->SRB_Status; -} -#endif - - /*********************************************************************** * GetASPISupportInfo (WINASPI.1) */ - WORD WINAPI GetASPISupportInfo16(void) { -#ifdef linux - TRACE("GETASPISupportInfo16\n"); - /* high byte SS_COMP - low byte number of host adapters */ - return ((SS_COMP << 8) | HA_Count); -#else - return ((SS_NO_ASPI << 8) | 0); -#endif -} - - -static DWORD ASPI_SendASPICommand(DWORD ptrSRB) -{ -#ifdef linux - LPSRB16 lpSRB = MapSL( ptrSRB ); - static const char szId[] = "Wine ASPI16"; - static const char szWh[] = "Wine host"; - - if (ASPIChainFunc) - { - /* This is not the post proc, it's the chain proc this time */ - DWORD ret = WOWCallback16((DWORD)ASPIChainFunc, ptrSRB); - if (ret) - { - lpSRB->inquiry.SRB_Status = SS_INVALID_SRB; - return ret; - } - } - - switch (lpSRB->common.SRB_Cmd) { - case SC_HA_INQUIRY: - lpSRB->inquiry.SRB_Status = SS_COMP; /* completed successfully */ - if (lpSRB->inquiry.SRB_55AASignature == 0x55aa) { - TRACE("Extended request detected (Adaptec's ASPIxDOS).\nWe don't support it at the moment.\n"); - } - lpSRB->inquiry.SRB_ExtBufferSize = 0x2000; /* bogus value */ - lpSRB->inquiry.HA_Count = HA_Count; - lpSRB->inquiry.HA_SCSI_ID = 7; /* not always ID 7 */ - memcpy(lpSRB->inquiry.HA_ManagerId, szId, sizeof szId); /* max 15 chars */ - memcpy(lpSRB->inquiry.HA_Identifier, szWh, sizeof szWh); /* FIXME: return host -adapter name */ - memset(lpSRB->inquiry.HA_Unique, 0, 16); /* default HA_Unique content */ - lpSRB->inquiry.HA_Unique[6] = 0x02; /* Maximum Transfer Length (128K, Byte> 4-7) */ - FIXME("ASPI: Partially implemented SC_HA_INQUIRY for adapter %d.\n", lpSRB->inquiry.SRB_HaId); - return SS_COMP; - case SC_GET_DEV_TYPE: - FIXME("Not implemented SC_GET_DEV_TYPE\n"); - break; - case SC_EXEC_SCSI_CMD: - return ASPI_ExecScsiCmd(ptrSRB); - case SC_RESET_DEV: - FIXME("Not implemented SC_RESET_DEV\n"); - break; - default: - FIXME("Unknown command %d\n", lpSRB->common.SRB_Cmd); - } -#endif - return SS_INVALID_SRB; + return GetASPI32SupportInfo(); } @@ -458,7 +60,68 @@ adapter name */ */ WORD WINAPI SendASPICommand16(SEGPTR segptr_srb) { - return ASPI_SendASPICommand(segptr_srb); + SRB srb32; + LPSRB16 srb16 = MapSL( segptr_srb ); + DWORD ret; + + if (ASPIChainFunc) + { + /* This is not the post proc, it's the chain proc this time */ + ret = WOWCallback16((DWORD)ASPIChainFunc, segptr_srb); + if (ret) + { + srb16->inquiry.SRB_Status = SS_INVALID_SRB; + return ret; + } + } + + switch (srb16->common.SRB_Cmd) + { + case SC_HA_INQUIRY: + srb32.common.SRB_Cmd = SC_HA_INQUIRY; + ret = SendASPI32Command( &srb32 ); + memcpy( &srb16->inquiry, &srb32.inquiry, sizeof(srb16->inquiry) ); + return ret; + + case SC_GET_DEV_TYPE: + FIXME("Not implemented SC_GET_DEV_TYPE\n"); + break; + + case SC_EXEC_SCSI_CMD: + srb32.cmd.SRB_Cmd = srb16->cmd.SRB_Cmd; + srb32.cmd.SRB_Status = srb16->cmd.SRB_Status; + srb32.cmd.SRB_HaId = srb16->cmd.SRB_HaId; + srb32.cmd.SRB_Flags = srb16->cmd.SRB_Flags; + srb32.cmd.SRB_Hdr_Rsvd = srb16->cmd.SRB_Hdr_Rsvd; + srb32.cmd.SRB_Target = srb16->cmd.SRB_Target; + srb32.cmd.SRB_Lun = srb16->cmd.SRB_Lun; + srb32.cmd.SRB_BufLen = srb16->cmd.SRB_BufLen; + srb32.cmd.SRB_BufPointer = MapSL(srb16->cmd.SRB_BufPointer); + srb32.cmd.SRB_SenseLen = srb16->cmd.SRB_SenseLen; + srb32.cmd.SRB_CDBLen = srb16->cmd.SRB_CDBLen; + srb32.cmd.SRB_HaStat = srb16->cmd.SRB_HaStat; + srb32.cmd.SRB_TargStat = srb16->cmd.SRB_TargStat; + memcpy( &srb32.cmd.CDBByte, srb16->cmd.CDBByte, srb32.cmd.SRB_CDBLen ); + srb32.cmd.SRB_PostProc = SRB_PostProc; + exec_postproc16 = srb16->cmd.SRB_PostProc; + exec_cmd16 = segptr_srb; + ret = SendASPI32Command( &srb32 ); + srb16->cmd.SRB_Status = srb32.cmd.SRB_Status; + srb16->cmd.SRB_BufLen = srb32.cmd.SRB_BufLen; + srb16->cmd.SRB_HaStat = srb32.cmd.SRB_HaStat; + srb16->cmd.SRB_TargStat = srb32.cmd.SRB_TargStat; + memcpy( srb16->cmd.CDBByte + srb16->cmd.SRB_CDBLen, srb32.cmd.SenseArea, + min( 16, srb32.cmd.SRB_SenseLen ) ); + return ret; + + case SC_RESET_DEV: + FIXME("Not implemented SC_RESET_DEV\n"); + break; + + default: + FIXME("Unknown command %d\n", srb16->common.SRB_Cmd); + } + return SS_INVALID_SRB; } @@ -467,7 +130,6 @@ WORD WINAPI SendASPICommand16(SEGPTR segptr_srb) */ WORD WINAPI InsertInASPIChain16(BOOL16 remove, FARPROC16 pASPIChainFunc) { -#ifdef linux if (remove) /* Remove */ { if (ASPIChainFunc == pASPIChainFunc) @@ -484,20 +146,14 @@ WORD WINAPI InsertInASPIChain16(BOOL16 remove, FARPROC16 pASPIChainFunc) return SS_COMP; } } -#endif return SS_ERR; } /*********************************************************************** - * GETASPIDLLVERSION (WINASPI.4) + * GetASPIDLLVersion (WINASPI.4) */ - DWORD WINAPI GetASPIDLLVersion16(void) { -#ifdef linux - return 2; -#else - return 0; -#endif + return 2; }