[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