[mswsock.dll] TransmitFile - some important changes [1/2]
Łukasz Chróst
lukost at gmail.com
Tue Jun 27 09:26:45 CDT 2006
Changelog (as to the previous patch):
- overlapped version releases file descriptors now
- cleared the code from useless junk (thx vitamin)
- got rid of NtXXXEvent - changed to kernel32 Set/ClearEvent (thx vitamin)
- removed C++ style comments
- created TransmitFile introduction
- changed tabs to spaces
--
Łukasz Chróst
-------------- next part --------------
Index: dlls/mswsock/Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/mswsock/Makefile.in,v
retrieving revision 1.3
diff -u -r1.3 Makefile.in
--- dlls/mswsock/Makefile.in 9 May 2005 14:42:33 -0000 1.3
+++ dlls/mswsock/Makefile.in 25 Jun 2006 22:31:28 -0000
@@ -1,16 +1,20 @@
+EXTRADEFS = -DUSE_WS_PREFIX
TOPSRCDIR = @top_srcdir@
TOPOBJDIR = ../..
SRCDIR = @srcdir@
VPATH = @srcdir@
MODULE = mswsock.dll
IMPORTLIB = libmswsock.$(IMPLIBEXT)
-IMPORTS = ws2_32 iphlpapi kernel32
+IMPORTS = ws2_32 iphlpapi kernel32 ntdll
+
C_SRCS = \
mswsock.c
RC_SRCS = version.rc
+SUBDIRS = tests
+
@MAKE_DLL_RULES@
### Dependencies:
Index: dlls/mswsock/mswsock.c
===================================================================
RCS file: /home/wine/wine/dlls/mswsock/mswsock.c,v
retrieving revision 1.4
diff -u -r1.4 mswsock.c
--- dlls/mswsock/mswsock.c 23 May 2006 12:48:20 -0000 1.4
+++ dlls/mswsock/mswsock.c 27 Jun 2006 14:09:16 -0000
@@ -17,22 +17,740 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-
+
#include "config.h"
+#include "wine/port.h"
#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#ifdef HAVE_SYS_IPC_H
+# include <sys/ipc.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif
+#ifdef HAVE_SYS_FILIO_H
+# include <sys/filio.h>
+#endif
+#ifdef HAVE_SYS_SOCKIO_H
+# include <sys/sockio.h>
+#endif
+
+#if defined(__EMX__)
+# include <sys/so_ioctl.h>
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+
+#ifdef HAVE_SYS_MSG_H
+# include <sys/msg.h>
+#endif
+#ifdef HAVE_SYS_WAIT_H
+# include <sys/wait.h>
+#endif
+#ifdef HAVE_SYS_UIO_H
+# include <sys/uio.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#ifdef HAVE_NETINET_TCP_H
+# include <netinet/tcp.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+# include <arpa/inet.h>
+#endif
+#include <ctype.h>
+#include <fcntl.h>
+#include <errno.h>
+#ifdef HAVE_SYS_ERRNO_H
+#include <sys/errno.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#include <stdlib.h>
+#ifdef HAVE_ARPA_NAMESER_H
+# include <arpa/nameser.h>
+#endif
+#ifdef HAVE_RESOLV_H
+# include <resolv.h>
+#endif
+#ifdef HAVE_NET_IF_H
+# include <net/if.h>
+#endif
+
+#ifdef HAVE_NETIPX_IPX_H
+# include <netipx/ipx.h>
+# define HAVE_IPX
+#elif defined(HAVE_LINUX_IPX_H)
+# ifdef HAVE_ASM_TYPES_H
+# include <asm/types.h>
+# endif
+# include <linux/ipx.h>
+# define HAVE_IPX
+#endif
+
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#endif
+#ifdef HAVE_SYS_POLL_H
+# include <sys/poll.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
#include "windef.h"
#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "winerror.h"
+#include "winnls.h"
#include "winsock2.h"
#include "mswsock.h"
-
+#include "ws2tcpip.h"
+#include "ws2spi.h"
+#include "wsipx.h"
+#include "winnt.h"
+#include "iphlpapi.h"
+#include "thread.h"
+#include "wine/server.h"
#include "wine/debug.h"
+#include "wine/unicode.h"
+
+#ifdef HAVE_IPX
+# include "wsnwlink.h"
+#endif
+
+
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+# define sipx_network sipx_addr.x_net
+# define sipx_node sipx_addr.x_host.c_host
+#endif /* __FreeBSD__ */
+
+#ifndef INADDR_NONE
+#define INADDR_NONE ~0UL
+#endif
+
+/* ************************************************************************************************ */
+/* Handle validation against INVALID_HANDLE_VALUE */
+#define HANDLE_VALID(x) (!(x==INVALID_HANDLE_VALUE))
+/* ************************************************************************************************ */
+
+#define FILE_DATA_BUFFER_LENGTH 1024
+
+/* HANDLE<->SOCKET conversion (SOCKET is UINT_PTR). */
+#define SOCKET2HANDLE(s) ((HANDLE)(s))
+#define HANDLE2SOCKET(h) ((SOCKET)(h))
+
+#ifdef SO_SNDTIMEO
+#define GET_SNDTIMEO(fd) get_rcvsnd_timeo( (fd), SO_SNDTIMEO)
+#else
+#define GET_SNDTIMEO(fd) (-1)
+#endif
+
+/* ************************************************************************************************ */
WINE_DEFAULT_DEBUG_CHANNEL(mswsock);
+
+/* ************************************************************************************************ */
+/* Async IO declarations */
+/* ************************************************************************************************ */
+typedef struct async_callinfo
+{
+ UCHAR bAbortIOEvent;
+ UCHAR bStartIOEvent;
+
+ HANDLE event;
+ DWORD dwCurrentId; /* id of part that should be checked at the moment */
+ DWORD dwBytesSent; /* how many bytes have been already sent */
+ DWORD dwPartsCount; /* how many parts there are */
+ DWORD dwFlags;
+ LPWSAOVERLAPPED user_overlapped;
+ HANDLE hSocket;
+ int sd; /* socket descriptor */
+ struct iovec *iov;
+} async_callinfo;
+
+typedef struct msws_async
+{
+ DWORD packetID; /* this packet id */
+ DWORD dwElFlags; /* TP_ELEMENT_FILE || TP_ELEMENT_MEMORY */
+ ULONG cLength; /* how much data to send */
+ DWORD dwJunkSize;
+ union /* simmilar to TRANSMIT_PACKETS_ELEMENT but we do not use HANDLE for file but fd */
+ {
+ struct
+ {
+ LARGE_INTEGER *lpFileOffset;
+ int fd;
+ HANDLE hFile;
+ };
+ LPVOID lpBuffer;
+ };
+ struct async_callinfo * lpCallInfo; /* common information for all APC's for the function call*/
+}msws_async;
+
+/* ************************************************************************************************ */
+/* Prepare async_callinfo structure */
+static async_callinfo * MWS2_make_callinfo(SOCKET s, int sd, LPVOID iov,
+ LPWSAOVERLAPPED lpOverlapped, DWORD dwParts, DWORD dwFlags, IO_STATUS_BLOCK **piosb)
+{
+ struct async_callinfo *ci = HeapAlloc( GetProcessHeap(), 0, sizeof( struct async_callinfo ) );
+
+ TRACE( "ci %p\n", ci );
+
+ if (!ci)
+ return NULL;
+
+ memset(ci, 0, sizeof(struct async_callinfo));
+
+ ci->bAbortIOEvent = 0;
+ ci->bStartIOEvent = 0;
+
+ ci->hSocket = (HANDLE) s;
+ ci->dwPartsCount = dwParts;
+ ci->sd = sd;
+ ci->iov = iov;
+ ci->dwFlags = dwFlags;
+ ci->user_overlapped = lpOverlapped;
+
+ if ( lpOverlapped )
+ {
+ *piosb = (IO_STATUS_BLOCK*)lpOverlapped;
+ ci->event = lpOverlapped->hEvent;
+ ResetEvent(ci->event);
+ }
+ else if (!(*piosb = HeapAlloc( GetProcessHeap(), 0, sizeof(IO_STATUS_BLOCK))))
+ goto error;
+
+ (*piosb)->Information = 0;
+ (*piosb)->u.Status = STATUS_PENDING;
+
+ return ci;
+error:
+ HeapFree( GetProcessHeap(), 0, ci );
+ return NULL;
+
+}
+
+/* ************************************************************************************************ */
+/* Prepare msws_async structure */
+static msws_async * MWS2_make_async(DWORD id, DWORD dwElFlags, ULONG length,
+ ULONG dwJunkSize, LARGE_INTEGER *lpOffset, int fd, HANDLE hFile, LPVOID pBuffer )
+{
+ struct msws_async *mswsa = HeapAlloc( GetProcessHeap(), 0,
+ sizeof( struct msws_async ) );
+
+ TRACE( "mswsa %p\n", mswsa );
+
+ if (!mswsa)
+ return NULL;
+
+ memset(mswsa, 0, sizeof(struct msws_async));
+
+ mswsa->cLength = length;
+ mswsa->dwJunkSize = dwJunkSize;
+ mswsa->packetID = id;
+ mswsa->dwElFlags = dwElFlags;
+ if(dwElFlags & TP_ELEMENT_FILE)
+ {
+ if(dwElFlags & TP_ELEMENT_MEMORY)
+ goto error;
+ mswsa->fd = fd;
+ mswsa->hFile = hFile;
+ mswsa->lpFileOffset = lpOffset;
+ }
+ else if(dwElFlags & TP_ELEMENT_MEMORY)
+ {
+ mswsa->lpBuffer = pBuffer;
+ }
+ else
+ {
+ goto error;
+ }
+
+ return mswsa;
+error:
+ HeapFree( GetProcessHeap(), 0, mswsa );
+ return NULL;
+}
+
+/* ************************************************************************************************ */
+/* register APC */
+static void WINAPI WS2_async_send_mixed(void*, IO_STATUS_BLOCK*, ULONG);
+
+static DWORD MWS2_queue_async(struct msws_async * mswsa, IO_STATUS_BLOCK* iosb)
+{
+ PIO_APC_ROUTINE apc;
+ int type;
+ NTSTATUS status;
+
+ apc = WS2_async_send_mixed; type = ASYNC_TYPE_WRITE;
+
+ SERVER_START_REQ( register_async )
+ {
+ req->handle = mswsa->lpCallInfo->hSocket;
+ req->io_apc = apc;
+ req->io_sb = iosb;
+ req->io_user = mswsa;
+ req->type = type;
+ req->count = iosb->Information;
+ status = wine_server_call( req );
+ }
+ SERVER_END_REQ;
+
+ if ( status ) iosb->u.Status = status;
+ if ( iosb->u.Status != STATUS_PENDING )
+ {
+ /* Note: we get here a non zero status when we couldn't queue the async
+ * in the server. Therefore, we simply terminate the async.
+ */
+ status = iosb->u.Status;
+ /* ws2_async_terminate(wsa, iosb);*/
+ return status;
+ }
+ NtCurrentTeb()->num_async_io++;
+ return STATUS_SUCCESS;
+}
+
+/* ************************************************************************************************ */
+inline static DWORD NtStatusToWSAError( const DWORD status )
+{
+ /* We only need to cover the status codes set by server async request handling */
+ DWORD wserr;
+ switch ( status )
+ {
+ case STATUS_SUCCESS: wserr = 0; break;
+ case STATUS_PENDING: wserr = WSA_IO_PENDING; break;
+ case STATUS_INVALID_HANDLE: wserr = WSAENOTSOCK; break; /* WSAEBADF ? */
+ case STATUS_INVALID_PARAMETER: wserr = WSAEINVAL; break;
+ case STATUS_PIPE_DISCONNECTED: wserr = WSAESHUTDOWN; break;
+ case STATUS_CANCELLED: wserr = WSA_OPERATION_ABORTED; break;
+ case STATUS_TIMEOUT: wserr = WSAETIMEDOUT; break;
+ case STATUS_NO_MEMORY: wserr = WSAEFAULT; break;
+ default:
+ if ( status >= WSABASEERR && status <= WSABASEERR+1004 )
+ /* It is not a NT status code but a winsock error */
+ wserr = status;
+ else
+ {
+ wserr = RtlNtStatusToDosError( status );
+ FIXME( "Status code %08lx converted to DOS error code %lx\n", status, wserr );
+ }
+ }
+ return wserr;
+}
+
+/* ************************************************************************************************ */
+/* forward declarations... */
+UINT wsaErrno(void);
+
+/* ************************************************************************************************ */
+/* set last error code from NT status without mapping WSA errors */
+inline static unsigned int set_error( unsigned int err )
+{
+ if (err)
+ {
+ err = NtStatusToWSAError( err );
+ SetLastError( err );
+ }
+ return err;
+}
+
+/* ************************************************************************************************ */
+/* Get fd from socket via server call */
+inline static int get_sock_fd( SOCKET s, DWORD access, int *flags )
+{
+ int fd;
+ if (set_error( wine_server_handle_to_fd( SOCKET2HANDLE(s), access, &fd, flags ) ))
+ return -1;
+ return fd;
+}
+
+/* ************************************************************************************************ */
+/* release previous */
+inline static void release_sock_fd( SOCKET s, int fd )
+{
+ wine_server_release_fd( SOCKET2HANDLE(s), fd );
+}
+
+
+/* ************************************************************************************************ */
+/* Utility: get the SO_RCVTIMEO or SO_SNDTIMEO socket option
+ * from an fd and return the value converted to milli seconds
+ * or -1 if there is an infinite time out */
+static inline int get_rcvsnd_timeo( int fd, int optname)
+{
+ struct timeval tv;
+ unsigned int len = sizeof(tv);
+ int ret = getsockopt(fd, SOL_SOCKET, optname, &tv, &len);
+ if( ret >= 0)
+ ret = tv.tv_sec * 1000 + tv.tv_usec / 1000;
+ if( ret <= 0 ) /* tv == {0,0} means infinite time out */
+ return -1;
+ return ret;
+}
+
+static inline void ws_sockaddr_free(const struct sockaddr* uaddr, const struct WS_sockaddr* wsaddr)
+{
+ if (uaddr!=(const struct sockaddr*)wsaddr)
+ HeapFree(GetProcessHeap(), 0, (void *)uaddr);
+}
+/* ************************************************************************************************ */
+/* utility: given an fd, will block until one of the events occurs */
+static inline int do_block( int fd, int events, int timeout )
+{
+ struct pollfd pfd;
+ int ret;
+
+ pfd.fd = fd;
+ pfd.events = events;
+
+ while ((ret = poll(&pfd, 1, timeout)) < 0)
+ {
+ if (errno != EINTR)
+ return -1;
+ }
+ if( ret == 0 )
+ return 0;
+ return pfd.revents;
+}
+
+/* ************************************************************************************************ */
+static void _enable_event( HANDLE s, unsigned int event,
+ unsigned int sstate, unsigned int cstate )
+{
+ SERVER_START_REQ( enable_socket_event )
+ {
+ req->handle = s;
+ req->mask = event;
+ req->sstate = sstate;
+ req->cstate = cstate;
+ wine_server_call( req );
+ }
+ SERVER_END_REQ;
+}
+
+/* ************************************************************************************************ */
+static int _is_blocking(SOCKET s)
+{
+ int ret;
+ SERVER_START_REQ( get_socket_event )
+ {
+ req->handle = SOCKET2HANDLE(s);
+ req->service = FALSE;
+ req->c_event = 0;
+ wine_server_call( req );
+ ret = (reply->state & FD_WINE_NONBLOCKING) == 0;
+ }
+ SERVER_END_REQ;
+ return ret;
+}
+
+
+/* ************************************************************************************************ *
+ * MWS2_send (INTERNAL)
+ *
+ * Workhorse for both synchronous and asynchronous send() operations.
+ */
+static int MWS2_send( int fd, struct iovec* iov, int count, DWORD dwFlags )
+{
+ struct msghdr hdr;
+ int n = -1;
+
+ TRACE("fd: %d, iovec: %p, count: %d, dwFlags: %ld\n",
+ fd, iov, count, dwFlags);
+
+ memset(&hdr, 0, sizeof (struct msghdr));
+
+ hdr.msg_iov = iov;
+ hdr.msg_iovlen = count;
+#ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
+ hdr.msg_accrights = NULL;
+ hdr.msg_accrightslen = 0;
+#else
+ hdr.msg_control = NULL;
+ hdr.msg_controllen = 0;
+ hdr.msg_flags = 0;
+#endif
+
+ ws_sockaddr_free( hdr.msg_name, (struct WS_sockaddr *)0 );
+ n = sendmsg(fd, &hdr, dwFlags);
+
+ return n;
+}
+
+/* ************************************************************************************************ *
+ * MWS2_send_mixed (INTERNAL)
+ *
+ * Workhorse for both synchronous and asynchronous send() operations.
+ */
+static int MWS2_send_mixed( struct msws_async * mswsa, DWORD dwFlags )
+{
+ DWORD dwBytesRead;
+ DWORD dwBytesSent;
+
+ struct iovec iovec;
+
+ TRACE("mswsa: %p, dwFlags: %ld\n",
+ mswsa, dwFlags);
+
+ switch(mswsa->dwElFlags)
+ {
+ case TP_ELEMENT_FILE:
+ dwBytesRead = pread(mswsa->fd,
+ mswsa->lpCallInfo->iov[1].iov_base,
+ mswsa->dwJunkSize,
+ mswsa->lpFileOffset->u.LowPart);
+
+ iovec.iov_base = mswsa->lpCallInfo->iov[1].iov_base;
+ iovec.iov_len = dwBytesRead;
+
+ if(dwBytesRead == -1)
+ goto e_exit;
+
+ dwBytesSent = MWS2_send(mswsa->lpCallInfo->sd,
+ &iovec, 1, mswsa->lpCallInfo->dwFlags );
+
+ if(dwBytesSent == -1)
+ goto e_exit;
+
+ mswsa->cLength -= dwBytesSent; /* if zeroed the call would be finished, else - reissued */
+ mswsa->lpFileOffset->u.LowPart += dwBytesSent; /* in addition to above */
+ mswsa->lpCallInfo->dwBytesSent += dwBytesSent;
+
+ return TRUE;
+
+ case TP_ELEMENT_MEMORY:
+ iovec.iov_base = mswsa->lpBuffer;
+ iovec.iov_len = mswsa->cLength;
+ TRACE("base: %p, len: %ld\n",
+ iovec.iov_base, iovec.iov_len);
+ dwBytesSent = MWS2_send( mswsa->lpCallInfo->sd, &iovec, 1,
+ mswsa->lpCallInfo->dwFlags);
+
+ if(dwBytesSent == -1)
+ goto e_exit;
+
+ mswsa->cLength -= dwBytesSent; /* if zeroed the call would be finished, else - reissued */
+ mswsa->lpBuffer += dwBytesSent; /* risky, but the data here isn't dynamically allocated*/
+ mswsa->lpCallInfo->dwBytesSent += dwBytesSent ;
+ return TRUE;
+ default:
+ FIXME("Unknown element type!\n");
+ goto e_exit;
+ }
+e_exit:
+ ERR("send error\n");
+ return FALSE;
+}
+
+/* ************************************************************************************************ */
+/* WS2_async_send_mixed (INTERNAL) */
+/* Handler for overlapped multisend operations */
+static void WINAPI WS2_async_send_mixed(void *as, IO_STATUS_BLOCK *piosb, ULONG status)
+{
+ struct msws_async *mswsa = 0;
+ DWORD dwRetVal = 0;
+ int err = 0;
+
+ mswsa = (msws_async *)as;
+ TRACE( "(%p %p %lx)\n", mswsa, piosb, status );
+
+ if(status == STATUS_ALERTED)
+ {
+ if (piosb->u.Status != STATUS_PENDING) FIXME("wrong %08lx\n", piosb->u.Status);
+
+ /* check to see if we want to process the call */
+
+ if(!mswsa->lpCallInfo->bStartIOEvent)
+ {
+ /* no we don't -> regis;ter it again.... */
+ TRACE("Not ready for operation, reissuing request: %ld\n", mswsa->packetID);
+ dwRetVal = MWS2_queue_async(mswsa, piosb);
+ if(dwRetVal != STATUS_SUCCESS)
+ {
+ piosb->u.Status = dwRetVal ;
+ goto e_exit;
+ }
+ }
+ /* check to see if we shall abort the event */
+ if(mswsa->lpCallInfo->bAbortIOEvent)
+ {
+ TRACE("Aborting IO, id: %ld, left: %ld\n", mswsa->packetID,
+ mswsa->lpCallInfo->dwPartsCount);
+ piosb->u.Status = EINTR;
+ goto e_exit; /* e_exit will do just OK */
+ }
+
+ /* check to see if we are good number */
+ if(mswsa->packetID == mswsa->lpCallInfo->dwCurrentId)
+ {
+ dwRetVal = MWS2_send_mixed( mswsa, mswsa->lpCallInfo->dwFlags );
+ if(dwRetVal) /* the operation succeded either this or hat way... */
+ {
+ /* check to see if it completed totaly or we still have some data to send.... */
+ _enable_event( mswsa->lpCallInfo->hSocket, FD_WRITE, 0, 0 );
+ if(mswsa->cLength)
+ {
+ /* reissue write to finish */
+ TRACE("Write operation reissued (uncomplete) id: %ld\n", mswsa->packetID);
+ dwRetVal = MWS2_queue_async(mswsa, piosb);
+ if(dwRetVal != STATUS_SUCCESS)
+ {
+ piosb->u.Status = dwRetVal ;
+ goto e_exit;
+ }
+ }
+ else
+ {
+ /* write finished */
+ TRACE("Write operation finished for part id: %ld\n", mswsa->packetID);
+ mswsa->lpCallInfo->dwCurrentId++;
+ mswsa->lpCallInfo->dwPartsCount--;
+
+ if((mswsa->dwElFlags & TP_ELEMENT_FILE) && mswsa->fd)
+ {
+ wine_server_release_fd( mswsa->hFile, mswsa->fd );
+ mswsa->fd = 0;
+ }
+
+ /* check to see if everything has been sent */
+ if(!mswsa->lpCallInfo->dwPartsCount)
+ {
+ TRACE("finished sending all parts.\n");
+ piosb->u.Status = STATUS_SUCCESS;
+ piosb->Information = mswsa->lpCallInfo->dwBytesSent;
+ SetEvent(mswsa->lpCallInfo->user_overlapped->hEvent);
+ /* free memory */
+ HeapFree( GetProcessHeap(), 0,
+ mswsa->lpCallInfo->iov[1].iov_base);
+ HeapFree( GetProcessHeap(), 0,
+ mswsa->lpCallInfo->iov);
+ wine_server_release_fd( mswsa->lpCallInfo->hSocket, mswsa->lpCallInfo->sd );
+
+ HeapFree( GetProcessHeap(), 0,
+ mswsa->lpCallInfo);
+ HeapFree( GetProcessHeap(), 0, piosb );
+ }
+
+ /* free the call information, leave operational information intact */
+ HeapFree( GetProcessHeap(), 0, mswsa);
+ }
+ }
+ else /* the function has returned an error */
+ {
+ err = wsaErrno();
+ if ( err == WSAEINTR )
+ {
+ piosb->u.Status = STATUS_PENDING;
+ _enable_event( mswsa->lpCallInfo->hSocket, FD_WRITE, 0, 0 );
+ TRACE( "still pending\n" );
+ dwRetVal = MWS2_queue_async(mswsa, piosb);
+ if(dwRetVal != STATUS_SUCCESS)
+ {
+ piosb->u.Status = dwRetVal ;
+ goto e_exit;
+ }
+ }
+ else
+ {
+ /* We set the status to a winsock error code and check for that
+ later in NtStatusToWSAError () */
+ piosb->u.Status = err;
+ TRACE( "Error: %x\n", err );
+ goto e_exit;
+ }
+ }
+
+ }
+ else /* wrong packet number */
+ {
+ if((mswsa->packetID) > (mswsa->lpCallInfo->dwCurrentId))
+ {
+ /* The packet came in wrong order. Requeue it...*/
+ TRACE("trying to reissue request, id: %ld, requested: %ld\n",
+ mswsa->packetID, mswsa->lpCallInfo->dwCurrentId);
+ dwRetVal = MWS2_queue_async(mswsa, piosb);
+ if(dwRetVal != STATUS_SUCCESS)
+ {
+ piosb->u.Status = dwRetVal ;
+ goto e_exit;
+ }
+ }
+ else
+ {
+ /* something really bad happened as it is totaly abnormal */
+ TRACE("packetID is to small\n");
+ piosb->u.Status = EALREADY;
+ goto e_exit;
+ }
+ }
+ }
+ else /* wrong call status */
+ {
+ FIXME( "status: %ld\n", status );
+ piosb->u.Status = status;
+ FIXME("Terminate the IO\n");
+ goto e_exit;
+ }
+ return;
+
+e_exit:
+
+ /* terminate the IO */
+ TRACE("Do 'terminate the IO' stuff here\n");
+
+ /* inform rest of requests that they shall close */
+ mswsa->lpCallInfo->bAbortIOEvent = 1;
+ mswsa->lpCallInfo->dwPartsCount --;
+
+ /* no APC's for this function call left */
+ if(!mswsa->lpCallInfo->dwPartsCount)
+ {
+ SetEvent(mswsa->lpCallInfo->user_overlapped->hEvent);
+ HeapFree( GetProcessHeap(), 0,
+ mswsa->lpCallInfo->iov[1].iov_base);
+ HeapFree( GetProcessHeap(), 0,
+ mswsa->lpCallInfo->iov);
+ wine_server_release_fd( mswsa->lpCallInfo->hSocket, mswsa->lpCallInfo->sd );
+ if((mswsa->dwElFlags & TP_ELEMENT_FILE) && mswsa->fd)
+ {
+ wine_server_release_fd( mswsa->hFile, mswsa->fd );
+ mswsa->fd = 0;
+ }
+
+ HeapFree( GetProcessHeap(), 0,
+ mswsa->lpCallInfo);
+ HeapFree( GetProcessHeap(), 0, piosb );
+ }
+ HeapFree( GetProcessHeap(), 0, mswsa);
+}
+
+
+/* ************************************************************************************************ */
+/* ************************************************************************************************ */
+
+
/***********************************************************************
- * AcceptEx (MSWSOCK.@)
+ * AcceptEx (MSWSOCK.@)
*
* This function is used to accept a new connection, get the local and remote
* address, and receive the initial block of data sent by the client.
@@ -42,22 +760,22 @@
*/
BOOL WINAPI AcceptEx(
- SOCKET sListenSocket, /* [in] Descriptor identifying a socket that
+ SOCKET sListenSocket, /* [in] Descriptor identifying a socket that
has already been called with the listen
function */
- SOCKET sAcceptSocket, /* [in] Descriptor identifying a socket on
+ SOCKET sAcceptSocket, /* [in] Descriptor identifying a socket on
which to accept an incoming connection */
- PVOID lpOutputBuffer, /* [in] Pointer to a buffer */
- DWORD dwReceiveDataLength, /* [in] Number of bytes in lpOutputBuffer
- that will be used for actual receive data
- at the beginning of the buffer */
- DWORD dwLocalAddressLength, /* [in] Number of bytes reserved for the
- local address information */
- DWORD dwRemoteAddressLength, /* [in] Number of bytes reserved for the
- remote address information */
- LPDWORD lpdwBytesReceived, /* [out] Pointer to a DWORD that receives
- the count of bytes received */
- LPOVERLAPPED lpOverlapped) /* [in] Specify in order to achieve an
+ PVOID lpOutputBuffer, /* [in] Pointer to a buffer */
+ DWORD dwReceiveDataLength, /* [in] Number of bytes in lpOutputBuffer
+ that will be used for actual receive data
+ at the beginning of the buffer */
+ DWORD dwLocalAddressLength, /* [in] Number of bytes reserved for the
+ local address information */
+ DWORD dwRemoteAddressLength, /* [in] Number of bytes reserved for the
+ remote address information */
+ LPDWORD lpdwBytesReceived, /* [out] Pointer to a DWORD that receives
+ the count of bytes received */
+ LPOVERLAPPED lpOverlapped) /* [in] Specify in order to achieve an
overlapped (asynchronous) I/O
operation */
{
@@ -67,70 +785,545 @@
}
/***********************************************************************
- * GetAcceptExSockaddrs (MSWSOCK.@)
+ * GetAcceptExSockaddrs (MSWSOCK.@)
*/
VOID WINAPI GetAcceptExSockaddrs(
- PVOID lpOutputBuffer, /* [in] Pointer to a buffer */
- DWORD dwReceiveDataLength, /* [in] Number of bytes in the buffer used
- for receiving the first data */
- DWORD dwLocalAddressLength, /* [in] Number of bytes reserved for the
- local address information */
- DWORD dwRemoteAddressLength, /* [in] Number of bytes reserved for the
- remote address information */
- struct sockaddr **LocalSockaddr, /* [out] Pointer to the sockaddr
- structure that receives the local
- address of the connection */
- LPINT LocalSockaddrLength, /* [out] Size in bytes of the local
- address */
- struct sockaddr **RemoteSockaddr, /* [out] Pointer to the sockaddr
- structure that receives the remote
- address of the connection */
- LPINT RemoteSockaddrLength) /* [out] Size in bytes of the remote address */
+ PVOID lpOutputBuffer, /* [in] Pointer to a buffer */
+ DWORD dwReceiveDataLength, /* [in] Number of bytes in the buffer used
+ for receiving the first data */
+ DWORD dwLocalAddressLength, /* [in] Number of bytes reserved for the
+ local address information */
+ DWORD dwRemoteAddressLength, /* [in] Number of bytes reserved for the
+ remote address information */
+ struct sockaddr **LocalSockaddr, /* [out] Pointer to the sockaddr
+ structure that receives the local
+ address of the connection */
+ LPINT LocalSockaddrLength, /* [out] Size in bytes of the local
+ address */
+ struct sockaddr **RemoteSockaddr, /* [out] Pointer to the sockaddr
+ structure that receives the remote
+ address of the connection */
+ LPINT RemoteSockaddrLength) /* [out] Size in bytes of the remote address */
{
FIXME("not implemented\n");
}
+
/***********************************************************************
- * TransmitFile (MSWSOCK.@)
+ * WSARecvEx (MSWSOCK.@)
+ */
+INT WINAPI WSARecvEx(
+ SOCKET s, /* [in] Descriptor identifying a connected socket */
+ char *buf, /* [out] Buffer for the incoming data */
+ INT len, /* [in] Length of buf, in bytes */
+ INT *flags) /* [in/out] Indicator specifying whether the message is
+ fully or partially received for datagram sockets */
+{
+ FIXME("not implemented\n");
+
+ return SOCKET_ERROR;
+}
+
+
+
+/* *********************************************************************************** */
+/* TransmitFileNormal - blocking*/
+static DWORD TransmitFileNormal(SOCKET s, int sd, int fd, struct iovec *iovec, DWORD dwFlags, UINT dwJunkSize, ULONG nFileLength)
+{
+ int err = WSAENOTSOCK;
+ ULONG nBytesSent = 0;
+ ULONG nBytesRead = 0;
+ ULONG nBytesToSend = 0;
+
+ TRACE("s: %d, sd: %d, fd: %d, iovec: %p, dwFlags: %ld, dwJunkSize: %u, nFileLength: %ld\n",
+ s, sd, fd, iovec, dwFlags, dwJunkSize, nFileLength);
+
+
+ if(iovec[0].iov_len)
+ {
+ nBytesToSend = iovec[0].iov_len;
+ while(nBytesToSend)
+ {
+ nBytesSent = send( s, &((char*)(iovec[0].iov_base))[nBytesSent], nBytesToSend, dwFlags );
+ if(nBytesSent == -1)
+ goto error;
+ nBytesToSend -= nBytesSent;
+ }
+ }
+
+ iovec[1].iov_base = HeapAlloc(GetProcessHeap(), 0, dwJunkSize+1);
+
+ nBytesSent = 0;
+ while(nFileLength)
+ {
+ int n;
+
+ nBytesRead = pread(fd, iovec[1].iov_base,
+ (dwJunkSize < nFileLength) ? dwJunkSize: nFileLength,
+ nBytesSent);
+ iovec[1].iov_len = nBytesRead;
+
+ n = MWS2_send( sd, &iovec[1], 1, dwFlags );
+
+ /* n = send( s, iovec[1].iov_base, iovec[1].iov_len, dwFlags ); */
+
+ if ( n == -1 )
+ {
+ err = wsaErrno();
+ if ( err == WSAEWOULDBLOCK )
+ {
+ _enable_event(SOCKET2HANDLE(s), FD_WRITE, 0, 0);
+ continue; /* We do not mind blocking, in fact they were expected to occur */
+ }
+ goto error;
+ }
+ nFileLength -= n;
+ nBytesSent+=n;
+ }
+
+ nBytesSent = 0;
+ if(iovec[2].iov_len)
+ {
+ nBytesToSend = iovec[2].iov_len;
+ while(nBytesToSend)
+ {
+ nBytesSent = send( s, &((char *)iovec[2].iov_base)[nBytesSent], nBytesToSend, dwFlags );
+ if(nBytesSent == -1)
+ goto error;
+ nBytesToSend -= nBytesSent;
+ }
+ }
+
+ return TRUE;
+
+ error:
+ WSASetLastError( err); /*FIXME*/
+ return FALSE;
+}
+
+/* *********************************************************************************** */
+/* TransmitFileOverlapped */
+static DWORD TransmitFileOverlapped(SOCKET s, int sd, HANDLE hFile, int fd, struct iovec *iovec,
+ DWORD dwFlags, UINT dwJunkSize, DWORD dwFileLength,
+ LPWSAOVERLAPPED lpOverlapped)
+{
+ IO_STATUS_BLOCK *iosb = 0;
+ struct async_callinfo * ci = 0;
+ struct msws_async * mswsa = 0;
+ DWORD nParts = 0;
+ DWORD len = 0;
+ int err = WSAENOTSOCK;
+ ULONG nBytesSent = 0;
+ ULONG nBytesToSend = 0;
+ ULONG nBytesLeft = 0;
+ DWORD dwRetVal = 0;
+ LARGE_INTEGER * pLI = 0;
+
+ len = dwFileLength + iovec[0].iov_len + iovec[2].iov_len;
+
+ if(!len)
+ {
+ TRACE("Exiting with true while no data to send...\n");
+ WSASetLastError(0);
+ return TRUE;
+ }
+
+ ci = MWS2_make_callinfo(s, sd, iovec, lpOverlapped, 0, dwFlags, &iosb);
+
+ if ( !ci )
+ {
+ ERR("Can't create ci!\n");
+ err = WSAEFAULT;
+ goto e_exit;
+ }
+
+ nBytesSent = 0;
+ nBytesToSend = iovec[0].iov_len;
+ nBytesLeft = nBytesToSend;
+
+ while(nBytesLeft)
+ {
+ nBytesToSend = (nBytesLeft < dwJunkSize) ? nBytesLeft : dwJunkSize;
+
+ mswsa = MWS2_make_async(nParts, TP_ELEMENT_MEMORY, nBytesToSend,
+ dwJunkSize, 0, 0, 0, &((char*)iovec[0].iov_base)[nBytesSent]);
+
+ if(!mswsa)
+ goto e_exit;
+
+ mswsa->lpCallInfo = ci;
+ dwRetVal = MWS2_queue_async(mswsa, iosb);
+ if(dwRetVal != STATUS_SUCCESS)
+ goto e_exit;
+
+ nBytesSent += nBytesToSend;
+ nBytesLeft -= nBytesToSend;
+
+ nParts ++;
+ }
+
+ iovec[1].iov_base = HeapAlloc(GetProcessHeap(), 0, dwJunkSize+1);
+
+ nBytesSent = 0;
+ nBytesLeft = dwFileLength;
+ while(nBytesLeft)
+ {
+ pLI = HeapAlloc(GetProcessHeap(), 0, sizeof(LARGE_INTEGER));
+ pLI->u.LowPart = lpOverlapped->u.s.Offset + nBytesSent;
+ pLI->u.HighPart = lpOverlapped->u.s.OffsetHigh;
+
+ nBytesToSend = nBytesLeft;
+ mswsa = MWS2_make_async(nParts, TP_ELEMENT_FILE, nBytesToSend,
+ dwJunkSize, pLI, fd, hFile,0);
+
+ if(!mswsa)
+ goto e_exit;
+
+ mswsa->lpCallInfo = ci;
+ dwRetVal = MWS2_queue_async(mswsa, iosb);
+ if(dwRetVal != STATUS_SUCCESS)
+ goto e_exit;
+
+ nBytesSent += nBytesToSend;
+ nBytesLeft -= nBytesToSend;
+
+ nParts ++;
+ }
+
+ nBytesSent = 0;
+ nBytesToSend = iovec[2].iov_len;
+ nBytesLeft = nBytesToSend;
+
+ while(nBytesLeft)
+ {
+ nBytesToSend = (nBytesLeft < dwJunkSize) ? nBytesLeft : dwJunkSize;
+ mswsa = MWS2_make_async(nParts, TP_ELEMENT_MEMORY, nBytesToSend, dwJunkSize,
+ 0, 0, 0, &((char*)iovec[2].iov_base)[nBytesSent]);
+ if(!mswsa)
+ goto e_exit;
+
+ mswsa->lpCallInfo = ci;
+ dwRetVal = MWS2_queue_async(mswsa, iosb);
+ if(dwRetVal != STATUS_SUCCESS)
+ goto e_exit;
+
+ nBytesSent += nBytesToSend;
+ nBytesLeft -= nBytesToSend;
+
+ nParts ++;
+ }
+
+ if(ci)
+ {
+ ci->dwPartsCount = nParts;
+ ci->bStartIOEvent = 1;
+ }
+
+ FIXME("no immediate completion test here\n");
+ WSASetLastError( WSA_IO_PENDING );
+ return FALSE;
+
+ e_exit:
+ /* cancel IO!!! */
+ if(ci)
+ {
+ ci->bAbortIOEvent = 1;
+ ci->bStartIOEvent = 1;
+ }
+
+ WSASetLastError( err); /*FIXME*/
+ return SOCKET_ERROR;
+}
+
+
+
+/***********************************************************************
+ * WSAAddressToStringW (MSWSOCK.@)
*
- * This function is used to transmit a file over socket.
+ * Transmit file via socket. Header / Footer data is also supported.
*
- * TODO
- * This function is currently implemented as a stub.
+ * PARAMS
+ * hSocket [I] Socket for sending the data. Not handle.
+ * hFile [I] file to transmit.
+ * nNumberOfBytesToWrite [I] How much data to write. Optional
+ * nNumberOfBytesPerSend [I] Maximum length of single packet (usefull for communication protocols)
+ * lpOverlapped [I/O] used for overlapped operations
+ * lpTransmitBuffers [I] data to send as header/tail usefull for communication protocols)
+ * dwFlags [I] communication flags.
+ *
+ * RETURNS
+ * Success: non-overlapped: TRUE, overlapped: TRUE/FALSE (check real result with WSAGetOverlappedResult)
+ * Failure: FALSE
+ *
+ * NOTES
+ * Use lpOverlapped->Offset for file offset
+ *
+ * BUGS
+ * lpOverlapped->OffsetHigh is not supported.
+ * limited to ULONG long files size (see above)
+ * doesn't support TF_REUSE_SOCKET and TF_REUSE_SOCKET
*/
BOOL WINAPI TransmitFile(
SOCKET hSocket, /* [in] Handle to a connected socket */
- HANDLE hFile, /* [in] Handle to the open file that should be
+ HANDLE hFile, /* [in] Handle to the open file that should be
transmited */
- DWORD nNumberOfBytesToWrite, /* [in] Number of file bytes to
- transmit */
- DWORD nNumberOfBytesPerSend, /* [in] Size in bytes of each block of
+ DWORD nNumberOfBytesToWrite, /* [in] Number of file bytes to
+ transmit - starting offset can be set through OVERLAPPED
+ Offset and OffsetHigh fields */
+ DWORD nNumberOfBytesPerSend, /* [in] Size in bytes of each block of
data sent in each send operation */
- LPOVERLAPPED lpOverlapped, /* [in] Specify in order to achieve an
+ LPOVERLAPPED lpOverlapped, /* [in] Specify in order to achieve an
overlapped (asynchronous) I/O
operation */
- LPTRANSMIT_FILE_BUFFERS lpTransmitBuffers,
- /* [in] Contains pointers to data to send before and after
+ LPTRANSMIT_FILE_BUFFERS lpTransmitBuffers,
+ /* [in] Contains pointers to data to send before and after
the file data is sent */
- DWORD dwFlags) /* [in] Flags */
+ DWORD dwFlags) /* [in] Flags */
{
- FIXME("not implemented\n");
+ unsigned int i = 0;
+ long filelen = 0;
+ DWORD filepos = 0;
+ unsigned int nVectors = 0;
+ unsigned int nFileJunks = 0;
+
+ int sd, fd , ret = 0;
+ struct iovec* iovec;
+
+ int FD_flags;
+ int SD_flags;
+ long flen;
+
+ iovec = 0;
+
+
+ TRACE("hSocket %04x, hFile %p, nbytes %ld, npsize %ld, ovl %p, tfbuf %p, flags %ld\n",
+ hSocket, hFile, nNumberOfBytesToWrite, nNumberOfBytesPerSend,
+ lpOverlapped, lpTransmitBuffers, dwFlags);
+
+ if(nNumberOfBytesPerSend > FILE_DATA_BUFFER_LENGTH)
+ nNumberOfBytesPerSend = FILE_DATA_BUFFER_LENGTH; /*we are using local var anyway ;-) */
+ if(!nNumberOfBytesPerSend)
+ nNumberOfBytesPerSend = FILE_DATA_BUFFER_LENGTH; /* we are using local var anyway ;-) */
+
+ /* check if the socket is usable */
+ sd = get_sock_fd(hSocket, FILE_WRITE_DATA, &SD_flags);
+ TRACE( "sd=%d, flags=%x\n", sd, SD_flags);
+
+ if ( sd == -1 )
+ {
+ TRACE("Can't get sd!\n");
+ WSASetLastError(WSAEFAULT);
+ return SOCKET_ERROR;
+ }
+
+ if(dwFlags & TF_REUSE_SOCKET)
+ {
+ FIXME("TF_REUSE_SOCKET not yet implemented\n");
+ WSASetLastError(WSAEINVAL);
+ return FALSE;
+ }
+
+ if(dwFlags & TF_DISCONNECT)
+ {
+ FIXME("TF_DISCONNECT not yet implemented\n");
+ WSASetLastError(WSAEINVAL);
+ return FALSE;
+ }
+
+ if(lpOverlapped)
+ {
+ if(lpOverlapped->u.s.OffsetHigh)
+ {
+ FIXME("High order offset not currently supported\n");
+ WSASetLastError(WSAEINVAL);
+ return FALSE;
+ }
+ }
+
+ /* process file length */
+ if(hFile)
+ {
+ TRACE("Processing file...\n");
+
+ if(wine_server_handle_to_fd( hFile, FILE_READ_DATA, &fd, &FD_flags ))
+ {
+ TRACE("Get fd: ERROR!\n");
+ WSASetLastError(WSA_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ if(lpOverlapped)
+ filepos = lpOverlapped->u.s.Offset;
+ else
+ filepos = 0;
+
+ lseek(fd, filepos, SEEK_SET); /* back to offset */
+ flen=lseek(fd, 0,SEEK_END); /*get file length */
+ lseek(fd, filepos, SEEK_SET); /* back to offset */
+
+
+ filelen = (flen < 0) ? 0 : flen;
+
+ if(nNumberOfBytesToWrite)
+ filelen = (filelen < nNumberOfBytesToWrite) ? filelen : nNumberOfBytesToWrite;
+
+ nFileJunks = filelen / nNumberOfBytesPerSend;
+
+ if(filelen % nNumberOfBytesPerSend)
+ nFileJunks++;
+ }
+
+
+ iovec = HeapAlloc(GetProcessHeap(), 0, 3 * sizeof(struct iovec));
+ memset(iovec, 0, 3 * sizeof(struct iovec));
+ nVectors = 3;
+
+
+ if(lpTransmitBuffers)
+ {
+ if(lpTransmitBuffers->Head && lpTransmitBuffers->HeadLength)
+ {
+ iovec[0].iov_base = lpTransmitBuffers->Head;
+ iovec[0].iov_len = lpTransmitBuffers->HeadLength;
+ }
+ if(lpTransmitBuffers->Tail && lpTransmitBuffers->TailLength)
+ {
+ iovec[nVectors-1].iov_base = lpTransmitBuffers->Tail;
+ iovec[nVectors-1].iov_len = lpTransmitBuffers->TailLength;
+ }
+ }
+
+ if ( lpOverlapped && SD_flags & FD_FLAG_OVERLAPPED )
+ {
+ if(TransmitFileOverlapped(hSocket, sd,hFile, fd, iovec, dwFlags, nNumberOfBytesPerSend,
+ filelen, lpOverlapped))
+ {
+ ret = TRUE;
+ goto ok_exit;
+ }
+ else
+ return FALSE;
+ }
+
+ ret = TransmitFileNormal(hSocket,sd,fd, iovec, dwFlags, nNumberOfBytesPerSend, filelen);
+
+ok_exit:
+ release_sock_fd( hSocket, sd );
+ if(iovec)
+ {
+ if(iovec[1].iov_base)
+ HeapFree(GetProcessHeap(), 0 , iovec[i].iov_base);
+ HeapFree( GetProcessHeap(), 0, iovec );
+ }
+
+ return ret;
+
+e_exit:
+
+ release_sock_fd( hSocket, sd );
+ if(iovec)
+ {
+ if(iovec[1].iov_base)
+ HeapFree(GetProcessHeap(), 0 , iovec[i].iov_base);
+ HeapFree( GetProcessHeap(), 0, iovec );
+ }
return FALSE;
}
-/***********************************************************************
- * WSARecvEx (MSWSOCK.@)
- */
-INT WINAPI WSARecvEx(
- SOCKET s, /* [in] Descriptor identifying a connected socket */
- char *buf, /* [out] Buffer for the incoming data */
- INT len, /* [in] Length of buf, in bytes */
- INT *flags) /* [in/out] Indicator specifying whether the message is
- fully or partially received for datagram sockets */
+
+
+/* *********************************************************************************** */
+/* ----------------------------------- error handling */
+
+UINT wsaErrno(void)
{
- FIXME("not implemented\n");
-
- return SOCKET_ERROR;
+ int loc_errno = errno;
+ WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
+
+ switch(loc_errno)
+ {
+ case EINTR: return WSAEINTR;
+ case EBADF: return WSAEBADF;
+ case EPERM:
+ case EACCES: return WSAEACCES;
+ case EFAULT: return WSAEFAULT;
+ case EINVAL: return WSAEINVAL;
+ case EMFILE: return WSAEMFILE;
+ case EWOULDBLOCK: return WSAEWOULDBLOCK;
+ case EINPROGRESS: return WSAEINPROGRESS;
+ case EALREADY: return WSAEALREADY;
+ case ENOTSOCK: return WSAENOTSOCK;
+ case EDESTADDRREQ: return WSAEDESTADDRREQ;
+ case EMSGSIZE: return WSAEMSGSIZE;
+ case EPROTOTYPE: return WSAEPROTOTYPE;
+ case ENOPROTOOPT: return WSAENOPROTOOPT;
+ case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
+ case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
+ case EOPNOTSUPP: return WSAEOPNOTSUPP;
+ case EPFNOSUPPORT: return WSAEPFNOSUPPORT;
+ case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
+ case EADDRINUSE: return WSAEADDRINUSE;
+ case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
+ case ENETDOWN: return WSAENETDOWN;
+ case ENETUNREACH: return WSAENETUNREACH;
+ case ENETRESET: return WSAENETRESET;
+ case ECONNABORTED: return WSAECONNABORTED;
+ case EPIPE:
+ case ECONNRESET: return WSAECONNRESET;
+ case ENOBUFS: return WSAENOBUFS;
+ case EISCONN: return WSAEISCONN;
+ case ENOTCONN: return WSAENOTCONN;
+ case ESHUTDOWN: return WSAESHUTDOWN;
+ case ETOOMANYREFS: return WSAETOOMANYREFS;
+ case ETIMEDOUT: return WSAETIMEDOUT;
+ case ECONNREFUSED: return WSAECONNREFUSED;
+ case ELOOP: return WSAELOOP;
+ case ENAMETOOLONG: return WSAENAMETOOLONG;
+ case EHOSTDOWN: return WSAEHOSTDOWN;
+ case EHOSTUNREACH: return WSAEHOSTUNREACH;
+ case ENOTEMPTY: return WSAENOTEMPTY;
+#ifdef EPROCLIM
+ case EPROCLIM: return WSAEPROCLIM;
+#endif
+#ifdef EUSERS
+ case EUSERS: return WSAEUSERS;
+#endif
+#ifdef EDQUOT
+ case EDQUOT: return WSAEDQUOT;
+#endif
+#ifdef ESTALE
+ case ESTALE: return WSAESTALE;
+#endif
+#ifdef EREMOTE
+ case EREMOTE: return WSAEREMOTE;
+#endif
+
+ /* just in case we ever get here and there are no problems */
+ case 0: return 0;
+ default:
+ WARN("Unknown errno %d!\n", loc_errno);
+ return WSAEOPNOTSUPP;
+ }
+}
+
+UINT wsaHerrno(int loc_errno)
+{
+
+ WARN("h_errno %d.\n", loc_errno);
+
+ switch(loc_errno)
+ {
+ case HOST_NOT_FOUND: return WSAHOST_NOT_FOUND;
+ case TRY_AGAIN: return WSATRY_AGAIN;
+ case NO_RECOVERY: return WSANO_RECOVERY;
+ case NO_DATA: return WSANO_DATA;
+ case ENOBUFS: return WSAENOBUFS;
+
+ case 0: return 0;
+ default:
+ WARN("Unknown h_errno %d!\n", loc_errno);
+ return WSAEOPNOTSUPP;
+ }
}
Index: dlls/mswsock/mswsock.spec
===================================================================
RCS file: /home/wine/wine/dlls/mswsock/mswsock.spec,v
retrieving revision 1.4
diff -u -r1.4 mswsock.spec
--- dlls/mswsock/mswsock.spec 21 Nov 2005 11:58:49 -0000 1.4
+++ dlls/mswsock/mswsock.spec 25 Jun 2006 22:56:26 -0000
@@ -19,7 +19,8 @@
@ stub StartWsdpService
@ stub StopWsdpService
@ stub SvchostPushServiceGlobals
-@ stdcall TransmitFile(long long long long ptr ptr long)
+@ stdcall TransmitFile(long long long long ptr ptr long) TransmitFile
+@ stub TransmitPackets
@ stub WSARecvEx
@ stub WSPStartup
@ stub dn_expand
More information about the wine-patches
mailing list