Index: dll/win32/msafd/misc/dllmain.c
===================================================================
--- dll/win32/msafd/misc/dllmain.c	(revision 73320)
+++ dll/win32/msafd/misc/dllmain.c	(working copy)
@@ -402,7 +402,7 @@
     return (SOCKET)Sock;
 
 error:
-    ERR("Ending %x\n", Status);
+    TRACE("Ending %x\n", Status);
 
     if( SharedData )
     {
@@ -1778,6 +1778,55 @@
     return AcceptSocket;
 }
 
+VOID
+NTAPI
+AfdConnectAPC(PVOID ApcContext,
+    PIO_STATUS_BLOCK IoStatusBlock,
+    ULONG Reserved)
+{
+    PAFDCONNECTAPCCONTEXT Context = ApcContext;
+
+    TRACE("AfdConnectAPC %p %lx %lx\n", ApcContext, IoStatusBlock->Status, IoStatusBlock->Information);
+
+    if (Context->lpConnectInfo)
+        HeapFree(GlobalHeap, 0, Context->lpConnectInfo);
+    if (!Context->lpSocket)
+    {
+        HeapFree(GlobalHeap, 0, ApcContext);
+        return;
+    }
+    if (IoStatusBlock->Status == STATUS_SUCCESS)
+    {
+        Context->lpSocket->SharedData->ConnectTime = (GetTickCount() - Context->lpSocket->SharedData->ConnectTime) / 1000;
+        Context->lpSocket->SharedData->State = SocketConnected;
+        Context->lpSocket->TdiConnectionHandle = (HANDLE)IoStatusBlock->Information;
+    }
+
+    /* Re-enable Async Event */
+    SockReenableAsyncSelectEvent(Context->lpSocket, FD_WRITE);
+
+    /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */
+    SockReenableAsyncSelectEvent(Context->lpSocket, FD_CONNECT);
+
+    if (IoStatusBlock->Status == STATUS_SUCCESS && (Context->lpSocket->HelperEvents & WSH_NOTIFY_CONNECT))
+    {
+        Context->lpSocket->HelperData->WSHNotify(Context->lpSocket->HelperContext,
+            Context->lpSocket->Handle,
+            Context->lpSocket->TdiAddressHandle,
+            Context->lpSocket->TdiConnectionHandle,
+            WSH_NOTIFY_CONNECT);
+    }
+    else if (IoStatusBlock->Status != STATUS_SUCCESS && (Context->lpSocket->HelperEvents & WSH_NOTIFY_CONNECT_ERROR))
+    {
+        Context->lpSocket->HelperData->WSHNotify(Context->lpSocket->HelperContext,
+            Context->lpSocket->Handle,
+            Context->lpSocket->TdiAddressHandle,
+            Context->lpSocket->TdiConnectionHandle,
+            WSH_NOTIFY_CONNECT_ERROR);
+    }
+    HeapFree(GlobalHeap, 0, ApcContext);
+}
+
 int
 WSPAPI
 WSPConnect(SOCKET Handle,
@@ -1789,7 +1838,8 @@
            LPQOS lpGQOS,
            LPINT lpErrno)
 {
-    IO_STATUS_BLOCK         IOSB;
+    IO_STATUS_BLOCK         DummyIOSB;
+    PIO_STATUS_BLOCK        IOSB = &DummyIOSB;
     PAFD_CONNECT_INFO       ConnectInfo = NULL;
     PSOCKET_INFORMATION     Socket;
     NTSTATUS                Status;
@@ -1800,8 +1850,10 @@
     PSOCKADDR               BindAddress;
     HANDLE                  SockEvent;
     int                     SocketDataLength;
+    PAFDCONNECTAPCCONTEXT   APCContext = NULL;
+    PIO_APC_ROUTINE         APCFunction = NULL;
 
-    TRACE("Called (%lx) %lx:%d\n", Handle, ((const struct sockaddr_in *)SocketAddress)->sin_addr, ((const struct sockaddr_in *)SocketAddress)->sin_port);
+    TRACE("WSPConnect (%lx)\n", Handle);
 
     /* Get the Socket Structure associate to this Socket*/
     Socket = GetSocketStructure(Handle);
@@ -1847,7 +1899,7 @@
                                         SockEvent,
                                         NULL,
                                         NULL,
-                                        &IOSB,
+                                        IOSB,
                                         IOCTL_AFD_SET_CONNECT_DATA,
                                         lpCallerData->buf,
                                         ConnectDataLength,
@@ -1857,7 +1909,7 @@
         if (Status == STATUS_PENDING)
         {
             WaitForSingleObject(SockEvent, INFINITE);
-            Status = IOSB.Status;
+            Status = IOSB->Status;
         }
 
         if (Status != STATUS_SUCCESS)
@@ -1868,7 +1920,7 @@
     SocketDataLength = SocketAddressLength - FIELD_OFFSET(struct sockaddr, sa_data);
 
     /* Allocate a connection info buffer with SocketDataLength bytes of payload */
-    ConnectInfo = HeapAlloc(GetProcessHeap(), 0,
+    ConnectInfo = HeapAlloc(GlobalHeap, 0,
                             FIELD_OFFSET(AFD_CONNECT_INFO,
                                          RemoteAddress.Address[0].Address[SocketDataLength]));
     if (!ConnectInfo)
@@ -1891,7 +1943,7 @@
     * at the end of this function right after the Async Thread disables it.
     * This should only happen at the *next* WSPConnect
     */
-    if (Socket->SharedData->AsyncEvents & FD_CONNECT)
+    if ((Socket->SharedData->AsyncEvents & FD_CONNECT) != 0)
     {
         Socket->SharedData->AsyncDisabledEvents |= FD_CONNECT | FD_WRITE;
     }
@@ -1904,7 +1956,7 @@
                                         SockEvent,
                                         NULL,
                                         NULL,
-                                        &IOSB,
+                                        IOSB,
                                         IOCTL_AFD_SET_CONNECT_DATA_SIZE,
                                         &InConnectDataLength,
                                         sizeof(InConnectDataLength),
@@ -1915,7 +1967,7 @@
         if (Status == STATUS_PENDING)
         {
             WaitForSingleObject(SockEvent, INFINITE);
-            Status = IOSB.Status;
+            Status = IOSB->Status;
         }
 
         if (Status != STATUS_SUCCESS)
@@ -1927,18 +1979,28 @@
     ConnectInfo->UseSAN = FALSE;
     ConnectInfo->Unknown = 0;
 
-    /* FIXME: Handle Async Connect */
     if (Socket->SharedData->NonBlocking)
     {
-        ERR("Async Connect UNIMPLEMENTED!\n");
+        APCFunction = &AfdConnectAPC; // should be a private io completition function inside us
+        APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDCONNECTAPCCONTEXT));
+        if (!APCContext)
+        {
+            ERR("Not enough memory for APC Context\n");
+            return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL);
+        }
+        APCContext->lpConnectInfo = ConnectInfo;
+        APCContext->lpSocket = Socket;
+        IOSB = &APCContext->IoStatusBlock;
     }
 
+    IOSB->Status = STATUS_PENDING;
+
     /* Send IOCTL */
     Status = NtDeviceIoControlFile((HANDLE)Handle,
-                                   SockEvent,
-                                   NULL,
-                                   NULL,
-                                   &IOSB,
+                                   APCFunction != NULL ? NULL : SockEvent,
+                                   APCFunction,
+                                   APCContext,
+                                   IOSB,
                                    IOCTL_AFD_CONNECT,
                                    ConnectInfo,
                                    0x22,
@@ -1947,16 +2009,33 @@
     /* Wait for return */
     if (Status == STATUS_PENDING)
     {
-        WaitForSingleObject(SockEvent, INFINITE);
-        Status = IOSB.Status;
+        WaitForSingleObject(SockEvent, Socket->SharedData->NonBlocking ? 0 : INFINITE);
+        Status = IOSB->Status;
     }
+    if (Status == STATUS_PENDING || Status == STATUS_CANT_WAIT)
+    {
+        NtClose(SockEvent);
+        if (Socket->SharedData->NonBlocking)
+            Status = STATUS_CANT_WAIT;
+        TRACE("Leaving (Pending)\n");
+        return MsafdReturnWithErrno(Status, lpErrno, 0, NULL);
+    }
 
+    if (APCFunction)
+    {
+        APCContext->lpConnectInfo = NULL;
+        APCContext->lpSocket = NULL;
+        /* This will be freed by the APC */
+        //HeapFree(GlobalHeap, 0, APCContext);
+    }
+    if (ConnectInfo) HeapFree(GlobalHeap, 0, ConnectInfo);
+
     Socket->SharedData->SocketLastError = TranslateNtStatusError(Status);
     if (Status != STATUS_SUCCESS)
         goto notify;
 
     Socket->SharedData->State = SocketConnected;
-    Socket->TdiConnectionHandle = (HANDLE)IOSB.Information;
+    Socket->TdiConnectionHandle = (HANDLE)IOSB->Information;
     Socket->SharedData->ConnectTime = GetCurrentTimeInSeconds();
 
     /* Get any pending connect data */
@@ -1966,7 +2045,7 @@
                                        SockEvent,
                                        NULL,
                                        NULL,
-                                       &IOSB,
+                                       IOSB,
                                        IOCTL_AFD_GET_CONNECT_DATA,
                                        NULL,
                                        0,
@@ -1976,14 +2055,12 @@
         if (Status == STATUS_PENDING)
         {
             WaitForSingleObject(SockEvent, INFINITE);
-            Status = IOSB.Status;
+            Status = IOSB->Status;
         }
     }
 
-    TRACE("Ending %lx\n", IOSB.Status);
-
 notify:
-    if (ConnectInfo) HeapFree(GetProcessHeap(), 0, ConnectInfo);
+    TRACE("Ending %lx\n", IOSB->Status);
 
     /* Re-enable Async Event */
     SockReenableAsyncSelectEvent(Socket, FD_WRITE);
@@ -2923,6 +3000,9 @@
     WCHAR buffer[54]; /* 32 digits + 7':' + '[' + '%" + 5 digits + ']:' + 5 digits + '\0' */
     WCHAR *p;
 
+    /* Allow for APC to be processed */
+    SleepEx(0, TRUE);
+
     if (!lpsaAddress || !lpszAddressString || !lpdwAddressStringLength)
     {
         if (lpErrno) *lpErrno = WSAEFAULT;
@@ -3112,9 +3192,10 @@
     PIO_STATUS_BLOCK IoStatusBlock,
     ULONG Reserved)
 {
-    PAFDAPCCONTEXT Context = ApcContext;
+    PAFDINFOAPCCONTEXT Context = ApcContext;
 
-    Context->lpCompletionRoutine(IoStatusBlock->Status, IoStatusBlock->Information, Context->lpOverlapped, 0);
+    if (Context->lpCompletionRoutine)
+        Context->lpCompletionRoutine(IoStatusBlock->Status, IoStatusBlock->Information, Context->lpOverlapped, 0);
     HeapFree(GlobalHeap, 0, ApcContext);
 }
 
@@ -3131,7 +3212,7 @@
     IO_STATUS_BLOCK     DummyIOSB;
     AFD_INFO            InfoData;
     NTSTATUS            Status;
-    PAFDAPCCONTEXT      APCContext;
+    PAFDINFOAPCCONTEXT  APCContext;
     PIO_APC_ROUTINE     APCFunction;
     HANDLE              Event = NULL;
     HANDLE              SockEvent;
@@ -3163,12 +3244,12 @@
         if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0)
         {
             TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
-            return 0;
+            return MsafdReturnWithErrno(STATUS_SUCCESS, NULL, 0, NULL);
         }
         if (CompletionRoutine == NULL)
         {
             /* Using Overlapped Structure, but no Completition Routine, so no need for APC */
-            APCContext = (PAFDAPCCONTEXT)Overlapped;
+            APCContext = (PAFDINFOAPCCONTEXT)Overlapped;
             APCFunction = NULL;
             Event = Overlapped->hEvent;
         }
@@ -3176,15 +3257,14 @@
         {
             /* Using Overlapped Structure and a Completition Routine, so use an APC */
             APCFunction = &AfdInfoAPC; // should be a private io completition function inside us
-            APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDAPCCONTEXT));
+            APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDINFOAPCCONTEXT));
             if (!APCContext)
             {
                 ERR("Not enough memory for APC Context\n");
-                return WSAEFAULT;
+                return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, NULL, 0, NULL);
             }
             APCContext->lpCompletionRoutine = CompletionRoutine;
             APCContext->lpOverlapped = Overlapped;
-            APCContext->lpSocket = Socket;
         }
 
         IOSB = (PIO_STATUS_BLOCK)&Overlapped->Internal;
@@ -3205,22 +3285,24 @@
                                    sizeof(InfoData));
 
     /* Wait for return */
-    if (Status == STATUS_PENDING && Overlapped == NULL)
+    if (Status == STATUS_PENDING)
     {
-        WaitForSingleObject(SockEvent, INFINITE);
+        WaitForSingleObject(SockEvent, Overlapped != NULL ? 0 : INFINITE);
         Status = IOSB->Status;
     }
 
     TRACE("Status %x Information %d\n", Status, IOSB->Information);
 
+    NtClose( SockEvent );
+
     if (Status == STATUS_PENDING)
     {
         TRACE("Leaving (Pending)\n");
-        return WSA_IO_PENDING;
+        return MsafdReturnWithErrno(Status, NULL, IOSB->Information, NULL);
     }
 
     if (Status != STATUS_SUCCESS)
-        return SOCKET_ERROR;
+        return MsafdReturnWithErrno(Status, NULL, IOSB->Information, NULL);
 
     /* Return Information */
     if (Ulong != NULL)
@@ -3236,10 +3318,7 @@
         *Boolean = InfoData.Information.Boolean;
     }
 
-    NtClose( SockEvent );
-
-    return NO_ERROR;
-
+    return MsafdReturnWithErrno(Status, NULL, IOSB->Information, NULL);
 }
 
 
@@ -3256,7 +3335,7 @@
     IO_STATUS_BLOCK     DummyIOSB;
     AFD_INFO            InfoData;
     NTSTATUS            Status;
-    PAFDAPCCONTEXT      APCContext;
+    PAFDINFOAPCCONTEXT  APCContext;
     PIO_APC_ROUTINE     APCFunction;
     HANDLE              Event = NULL;
     HANDLE              SockEvent;
@@ -3302,12 +3381,12 @@
         if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0)
         {
             TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
-            return 0;
+            return MsafdReturnWithErrno(STATUS_SUCCESS, NULL, 0, NULL);
         }
         if (CompletionRoutine == NULL)
         {
             /* Using Overlapped Structure, but no Completition Routine, so no need for APC */
-            APCContext = (PAFDAPCCONTEXT)Overlapped;
+            APCContext = (PAFDINFOAPCCONTEXT)Overlapped;
             APCFunction = NULL;
             Event = Overlapped->hEvent;
         }
@@ -3315,15 +3394,14 @@
         {
             /* Using Overlapped Structure and a Completition Routine, so use an APC */
             APCFunction = &AfdInfoAPC; // should be a private io completition function inside us
-            APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDAPCCONTEXT));
+            APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDINFOAPCCONTEXT));
             if (!APCContext)
             {
                 ERR("Not enough memory for APC Context\n");
-                return WSAEFAULT;
+                return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, NULL, 0, NULL);
             }
             APCContext->lpCompletionRoutine = CompletionRoutine;
             APCContext->lpOverlapped = Overlapped;
-            APCContext->lpSocket = Socket;
         }
 
         IOSB = (PIO_STATUS_BLOCK)&Overlapped->Internal;
@@ -3344,9 +3422,9 @@
                                    0);
 
     /* Wait for return */
-    if (Status == STATUS_PENDING && Overlapped == NULL)
+    if (Status == STATUS_PENDING)
     {
-        WaitForSingleObject(SockEvent, INFINITE);
+        WaitForSingleObject(SockEvent, Overlapped != NULL ? 0 : INFINITE);
         Status = IOSB->Status;
     }
 
@@ -3357,10 +3435,10 @@
     if (Status == STATUS_PENDING)
     {
         TRACE("Leaving (Pending)\n");
-        return WSA_IO_PENDING;
+        //return MsafdReturnWithErrno(Status, NULL, IOSB->Information, NULL);
     }
 
-    return Status == STATUS_SUCCESS ? NO_ERROR : SOCKET_ERROR;
+    return MsafdReturnWithErrno(Status, NULL, IOSB->Information, NULL);
 
 }
 
Index: dll/win32/msafd/misc/event.c
===================================================================
--- dll/win32/msafd/misc/event.c	(revision 73320)
+++ dll/win32/msafd/misc/event.c	(working copy)
@@ -192,7 +192,7 @@
 
     if (Status != STATUS_SUCCESS)
     {
-        ERR("Status 0x%08x", Status);
+        ERR("Status 0x%08x\n", Status);
         return MsafdReturnWithErrno(Status, lpErrno, 0, NULL);
     }
 
Index: dll/win32/msafd/misc/sndrcv.c
===================================================================
--- dll/win32/msafd/misc/sndrcv.c	(revision 73320)
+++ dll/win32/msafd/misc/sndrcv.c	(working copy)
@@ -140,21 +140,51 @@
 
 VOID
 NTAPI
-AfdAPC(PVOID ApcContext,
+AfdRecvAPC(PVOID ApcContext,
        PIO_STATUS_BLOCK IoStatusBlock,
        ULONG Reserved)
 {
-    PAFDAPCCONTEXT Context = ApcContext;
+    PAFDRECVAPCCONTEXT Context = ApcContext;
 
-    /* Re-enable Async Event */
-    SockReenableAsyncSelectEvent(Context->lpSocket, FD_OOB);
-    SockReenableAsyncSelectEvent(Context->lpSocket, FD_READ);
-    SockReenableAsyncSelectEvent(Context->lpSocket, FD_WRITE);
+    TRACE("AfdRecvAPC %p %lx %lx\n", ApcContext, IoStatusBlock->Status, IoStatusBlock->Information);
+    if (Context->lpSocket && Context->lpSocket->SharedData)
+    {
+        /* Re-enable Async Event */
+        SockReenableAsyncSelectEvent(Context->lpSocket, FD_OOB);
+        SockReenableAsyncSelectEvent(Context->lpSocket, FD_READ);
+    }
 
-    Context->lpCompletionRoutine(IoStatusBlock->Status, IoStatusBlock->Information, Context->lpOverlapped, 0);
+    if (Context->lpCompletionRoutine)
+        Context->lpCompletionRoutine(IoStatusBlock->Status, IoStatusBlock->Information, Context->lpOverlapped, 0);
+    if (Context->lpRecvInfo)
+        HeapFree(GlobalHeap, 0, Context->lpRecvInfo);
     HeapFree(GlobalHeap, 0, ApcContext);
 }
 
+VOID
+NTAPI
+AfdSendAPC(PVOID ApcContext,
+    PIO_STATUS_BLOCK IoStatusBlock,
+    ULONG Reserved)
+{
+    PAFDSENDAPCCONTEXT Context = ApcContext;
+
+    TRACE("AfdSendAPC %p %lx %lx\n", ApcContext, IoStatusBlock->Status, IoStatusBlock->Information);
+    if (Context->lpSocket && Context->lpSocket->SharedData)
+    {
+        /* Re-enable Async Event */
+        SockReenableAsyncSelectEvent(Context->lpSocket, FD_WRITE);
+    }
+
+    if (Context->lpCompletionRoutine)
+        Context->lpCompletionRoutine(IoStatusBlock->Status, IoStatusBlock->Information, Context->lpOverlapped, 0);
+    if (Context->lpSendInfo)
+        HeapFree(GlobalHeap, 0, Context->lpSendInfo);
+    if (Context->lpRemoteAddress)
+        HeapFree(GlobalHeap, 0, Context->lpRemoteAddress);
+    HeapFree(GlobalHeap, 0, ApcContext);
+}
+
 int
 WSPAPI
 WSPRecv(SOCKET Handle,
@@ -169,9 +199,9 @@
 {
     PIO_STATUS_BLOCK        IOSB;
     IO_STATUS_BLOCK         DummyIOSB;
-    AFD_RECV_INFO           RecvInfo;
+    PAFD_RECV_INFO          RecvInfo;
     NTSTATUS                Status;
-    PVOID                   APCContext;
+    PAFDRECVAPCCONTEXT      APCContext;
     PIO_APC_ROUTINE         APCFunction;
     HANDLE                  Event = NULL;
     HANDLE                  SockEvent;
@@ -200,38 +230,50 @@
         return SOCKET_ERROR;
     }
 
+    /* Allocate a recv info buffer */
+    RecvInfo = HeapAlloc(GlobalHeap, 0, sizeof(AFD_RECV_INFO));
+    if (!RecvInfo)
+    {
+        if (lpErrno)
+            *lpErrno = WSAENOBUFS;
+        return SOCKET_ERROR;
+    }
+
     Status = NtCreateEvent( &SockEvent, EVENT_ALL_ACCESS,
                             NULL, 1, FALSE );
 
-    if( !NT_SUCCESS(Status) )
-        return -1;
+    if (!NT_SUCCESS(Status))
+    {
+        HeapFree(GlobalHeap, 0, RecvInfo);
+        return SOCKET_ERROR;
+    }
 
     /* Set up the Receive Structure */
-    RecvInfo.BufferArray = (PAFD_WSABUF)lpBuffers;
-    RecvInfo.BufferCount = dwBufferCount;
-    RecvInfo.TdiFlags = 0;
-    RecvInfo.AfdFlags = Socket->SharedData->NonBlocking ? AFD_IMMEDIATE : 0;
+    RecvInfo->BufferArray = (PAFD_WSABUF)lpBuffers;
+    RecvInfo->BufferCount = dwBufferCount;
+    RecvInfo->TdiFlags = 0;
+    RecvInfo->AfdFlags = Socket->SharedData->NonBlocking ? AFD_IMMEDIATE : 0;
 
     /* Set the TDI Flags */
-    if (*ReceiveFlags == 0)
+    if (!ReceiveFlags || *ReceiveFlags == 0)
     {
-        RecvInfo.TdiFlags |= TDI_RECEIVE_NORMAL;
+        RecvInfo->TdiFlags |= TDI_RECEIVE_NORMAL;
     }
     else
     {
         if (*ReceiveFlags & MSG_OOB)
         {
-            RecvInfo.TdiFlags |= TDI_RECEIVE_EXPEDITED;
+            RecvInfo->TdiFlags |= TDI_RECEIVE_EXPEDITED;
         }
 
         if (*ReceiveFlags & MSG_PEEK)
         {
-            RecvInfo.TdiFlags |= TDI_RECEIVE_PEEK;
+            RecvInfo->TdiFlags |= TDI_RECEIVE_PEEK;
         }
 
         if (*ReceiveFlags & MSG_PARTIAL)
         {
-            RecvInfo.TdiFlags |= TDI_RECEIVE_PARTIAL;
+            RecvInfo->TdiFlags |= TDI_RECEIVE_PARTIAL;
         }
     }
 
@@ -251,12 +293,12 @@
         if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0)
         {
             TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
-            return MsafdReturnWithErrno(0, lpErrno, 0, lpNumberOfBytesRead);
+            return MsafdReturnWithErrno(STATUS_SUCCESS, lpErrno, 0, lpNumberOfBytesRead);
         }
         if (lpCompletionRoutine == NULL)
         {
             /* Using Overlapped Structure, but no Completion Routine, so no need for APC */
-            APCContext = lpOverlapped;
+            APCContext = (PAFDRECVAPCCONTEXT)lpOverlapped;
             APCFunction = NULL;
             Event = lpOverlapped->hEvent;
         }
@@ -263,23 +305,25 @@
         else
         {
             /* Using Overlapped Structure and a Completion Routine, so use an APC */
-            APCFunction = &AfdAPC; // should be a private io completion function inside us
-            APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDAPCCONTEXT));
+            APCFunction = &AfdRecvAPC; // should be a private io completion function inside us
+            APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDRECVAPCCONTEXT));
             if (!APCContext)
             {
                 ERR("Not enough memory for APC Context\n");
                 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, lpNumberOfBytesRead);
             }
-            ((PAFDAPCCONTEXT)APCContext)->lpCompletionRoutine = lpCompletionRoutine;
-            ((PAFDAPCCONTEXT)APCContext)->lpOverlapped = lpOverlapped;
-            ((PAFDAPCCONTEXT)APCContext)->lpSocket = Socket;
-            RecvInfo.AfdFlags |= AFD_SKIP_FIO;
+            APCContext->lpCompletionRoutine = lpCompletionRoutine;
+            APCContext->lpOverlapped = lpOverlapped;
+            APCContext->lpSocket = Socket;
+            APCContext->lpRecvInfo = RecvInfo;
+            RecvInfo->AfdFlags |= AFD_SKIP_FIO;
         }
 
         IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal;
-        RecvInfo.AfdFlags |= AFD_OVERLAPPED;
+        RecvInfo->AfdFlags |= AFD_OVERLAPPED;
     }
 
+    IOSB->Information = 0;
     IOSB->Status = STATUS_PENDING;
 
     /* Send IOCTL */
@@ -289,25 +333,23 @@
                                    APCContext,
                                    IOSB,
                                    IOCTL_AFD_RECV,
-                                   &RecvInfo,
-                                   sizeof(RecvInfo),
+                                   RecvInfo,
+                                   sizeof(AFD_RECV_INFO),
                                    NULL,
                                    0);
 
     /* Wait for completion of not overlapped */
-    if (Status == STATUS_PENDING && lpOverlapped == NULL)
+    if (Status == STATUS_PENDING)
     {
         /* It's up to the protocol to time out recv.  We must wait
          * until the protocol decides it's had enough.
          */
-        WaitForSingleObject(SockEvent, INFINITE);
+        WaitForSingleObject(SockEvent, (lpOverlapped || Socket->SharedData->NonBlocking) ? 0 : INFINITE);
         Status = IOSB->Status;
     }
 
     NtClose( SockEvent );
 
-    TRACE("Status %x Information %d\n", Status, IOSB->Information);
-
     if (Status == STATUS_PENDING)
     {
         TRACE("Leaving (Pending)\n");
@@ -314,11 +356,23 @@
         return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesRead);
     }
 
+    if (APCFunction)
+    {
+        APCContext->lpRecvInfo = NULL;
+        APCContext->lpCompletionRoutine = NULL;
+        APCContext->lpSocket = NULL;
+        /* This will be freed by the APC */
+        //HeapFree(GlobalHeap, 0, APCContext);
+    }
+    HeapFree(GlobalHeap, 0, RecvInfo);
+
     /* Return the Flags */
-    *ReceiveFlags = 0;
+    if (ReceiveFlags)
+    {
+        *ReceiveFlags = 0;
 
-    switch (Status)
-    {
+        switch (Status)
+        {
         case STATUS_RECEIVE_EXPEDITED:
             *ReceiveFlags = MSG_OOB;
             break;
@@ -328,22 +382,27 @@
         case STATUS_RECEIVE_PARTIAL:
             *ReceiveFlags = MSG_PARTIAL;
             break;
+        }
     }
 
-    /* Re-enable Async Event */
-    if (*ReceiveFlags & MSG_OOB)
+    if (Status == STATUS_SUCCESS)
     {
-        SockReenableAsyncSelectEvent(Socket, FD_OOB);
+        /* Re-enable Async Event */
+        if (ReceiveFlags && *ReceiveFlags & MSG_OOB)
+        {
+            SockReenableAsyncSelectEvent(Socket, FD_OOB);
+        }
+        else
+        {
+            SockReenableAsyncSelectEvent(Socket, FD_READ);
+        }
     }
-    else
-    {
-        SockReenableAsyncSelectEvent(Socket, FD_READ);
-    }
 
+    TRACE("Leaving (Success, %ld %ld)\n", Status, IOSB->Information);
+
     if (Status == STATUS_SUCCESS && lpOverlapped && lpCompletionRoutine)
     {
-        lpCompletionRoutine(Status, IOSB->Information, lpOverlapped, *ReceiveFlags);
-        HeapFree(GlobalHeap, 0, (PVOID)APCContext);
+        lpCompletionRoutine(Status, IOSB->Information, lpOverlapped, ReceiveFlags != NULL ? *ReceiveFlags : 0);
     }
 
     return MsafdReturnWithErrno ( Status, lpErrno, IOSB->Information, lpNumberOfBytesRead );
@@ -365,14 +424,16 @@
 {
     PIO_STATUS_BLOCK            IOSB;
     IO_STATUS_BLOCK             DummyIOSB;
-    AFD_RECV_INFO_UDP           RecvInfo;
+    PAFD_RECV_INFO_UDP          RecvInfo;
     NTSTATUS                    Status;
-    PVOID                       APCContext;
-    PVOID                       APCFunction;
+    PAFDRECVAPCCONTEXT          APCContext;
+    PIO_APC_ROUTINE             APCFunction;
     HANDLE                      Event = NULL;
     HANDLE                      SockEvent;
     PSOCKET_INFORMATION         Socket;
 
+    TRACE("WSPRecvFrom Called (%x)\n", Handle);
+
     /* Get the Socket Structure associate to this Socket*/
     Socket = GetSocketStructure(Handle);
     if (!Socket)
@@ -419,40 +480,52 @@
             return SOCKET_ERROR;
     }
 
+    /* Allocate a recv info buffer */
+    RecvInfo = HeapAlloc(GlobalHeap, 0, sizeof(AFD_RECV_INFO_UDP));
+    if (!RecvInfo)
+    {
+        if (lpErrno)
+            *lpErrno = WSAENOBUFS;
+        return SOCKET_ERROR;
+    }
+
     Status = NtCreateEvent( &SockEvent, EVENT_ALL_ACCESS,
                             NULL, 1, FALSE );
 
     if( !NT_SUCCESS(Status) )
-        return -1;
+    {
+        HeapFree(GlobalHeap, 0, RecvInfo);
+        return SOCKET_ERROR;
+    }
 
     /* Set up the Receive Structure */
-    RecvInfo.BufferArray = (PAFD_WSABUF)lpBuffers;
-    RecvInfo.BufferCount = dwBufferCount;
-    RecvInfo.TdiFlags = 0;
-    RecvInfo.AfdFlags = Socket->SharedData->NonBlocking ? AFD_IMMEDIATE : 0;
-    RecvInfo.AddressLength = SocketAddressLength;
-    RecvInfo.Address = SocketAddress;
+    RecvInfo->BufferArray = (PAFD_WSABUF)lpBuffers;
+    RecvInfo->BufferCount = dwBufferCount;
+    RecvInfo->TdiFlags = 0;
+    RecvInfo->AfdFlags = Socket->SharedData->NonBlocking ? AFD_IMMEDIATE : 0;
+    RecvInfo->AddressLength = SocketAddressLength;
+    RecvInfo->Address = SocketAddress;
 
     /* Set the TDI Flags */
-    if (*ReceiveFlags == 0)
+    if (!ReceiveFlags || *ReceiveFlags == 0)
     {
-        RecvInfo.TdiFlags |= TDI_RECEIVE_NORMAL;
+        RecvInfo->TdiFlags |= TDI_RECEIVE_NORMAL;
     }
     else
     {
         if (*ReceiveFlags & MSG_OOB)
         {
-            RecvInfo.TdiFlags |= TDI_RECEIVE_EXPEDITED;
+            RecvInfo->TdiFlags |= TDI_RECEIVE_EXPEDITED;
         }
 
         if (*ReceiveFlags & MSG_PEEK)
         {
-            RecvInfo.TdiFlags |= TDI_RECEIVE_PEEK;
+            RecvInfo->TdiFlags |= TDI_RECEIVE_PEEK;
         }
 
         if (*ReceiveFlags & MSG_PARTIAL)
         {
-            RecvInfo.TdiFlags |= TDI_RECEIVE_PARTIAL;
+            RecvInfo->TdiFlags |= TDI_RECEIVE_PARTIAL;
         }
     }
 
@@ -472,12 +545,12 @@
         if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0)
         {
             TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
-            return MsafdReturnWithErrno(0, lpErrno, 0, lpNumberOfBytesRead);
+            return MsafdReturnWithErrno(STATUS_SUCCESS, lpErrno, 0, lpNumberOfBytesRead);
         }
         if (lpCompletionRoutine == NULL)
         {
             /* Using Overlapped Structure, but no Completion Routine, so no need for APC */
-            APCContext = lpOverlapped;
+            APCContext = (PAFDRECVAPCCONTEXT)lpOverlapped;
             APCFunction = NULL;
             Event = lpOverlapped->hEvent;
         }
@@ -484,23 +557,25 @@
         else
         {
             /* Using Overlapped Structure and a Completion Routine, so use an APC */
-            APCFunction = &AfdAPC; // should be a private io completion function inside us
-            APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDAPCCONTEXT));
+            APCFunction = &AfdRecvAPC; // should be a private io completion function inside us
+            APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDRECVAPCCONTEXT));
             if (!APCContext)
             {
                 ERR("Not enough memory for APC Context\n");
                 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, lpNumberOfBytesRead);
             }
-            ((PAFDAPCCONTEXT)APCContext)->lpCompletionRoutine = lpCompletionRoutine;
-            ((PAFDAPCCONTEXT)APCContext)->lpOverlapped = lpOverlapped;
-            ((PAFDAPCCONTEXT)APCContext)->lpSocket = Socket;
-            RecvInfo.AfdFlags |= AFD_SKIP_FIO;
+            APCContext->lpCompletionRoutine = lpCompletionRoutine;
+            APCContext->lpOverlapped = lpOverlapped;
+            APCContext->lpSocket = Socket;
+            APCContext->lpRecvInfo = RecvInfo;
+            RecvInfo->AfdFlags |= AFD_SKIP_FIO;
         }
 
         IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal;
-        RecvInfo.AfdFlags |= AFD_OVERLAPPED;
+        RecvInfo->AfdFlags |= AFD_OVERLAPPED;
     }
 
+    IOSB->Information = 0;
     IOSB->Status = STATUS_PENDING;
 
     /* Send IOCTL */
@@ -510,15 +585,15 @@
                                     APCContext,
                                     IOSB,
                                     IOCTL_AFD_RECV_DATAGRAM,
-                                    &RecvInfo,
-                                    sizeof(RecvInfo),
+                                    RecvInfo,
+                                    sizeof(AFD_RECV_INFO_UDP),
                                     NULL,
                                     0);
 
     /* Wait for completion of not overlapped */
-    if (Status == STATUS_PENDING && lpOverlapped == NULL)
+    if (Status == STATUS_PENDING)
     {
-        WaitForSingleObject(SockEvent, INFINITE); // BUGBUG, shouldn wait infinitely for receive...
+        WaitForSingleObject(SockEvent, (lpOverlapped || Socket->SharedData->NonBlocking) ? 0 : INFINITE); // BUGBUG, shouldn wait infintely for receive...
         Status = IOSB->Status;
     }
 
@@ -530,11 +605,23 @@
         return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesRead);
     }
 
-    /* Return the Flags */
-    *ReceiveFlags = 0;
+    if (APCFunction)
+    {
+        APCContext->lpRecvInfo = NULL;
+        APCContext->lpCompletionRoutine = NULL;
+        APCContext->lpSocket = NULL;
+        /* This will be freed by the APC */
+        //HeapFree(GlobalHeap, 0, APCContext);
+    }
+    HeapFree(GlobalHeap, 0, RecvInfo);
 
-    switch (Status)
+    if (ReceiveFlags)
     {
+        /* Return the Flags */
+        *ReceiveFlags = 0;
+
+        switch (Status)
+        {
         case STATUS_RECEIVE_EXPEDITED:
             *ReceiveFlags = MSG_OOB;
             break;
@@ -544,22 +631,27 @@
         case STATUS_RECEIVE_PARTIAL:
             *ReceiveFlags = MSG_PARTIAL;
             break;
+        }
     }
 
-    /* Re-enable Async Event */
-    if (*ReceiveFlags & MSG_OOB)
+    if (Status == STATUS_SUCCESS)
     {
-        SockReenableAsyncSelectEvent(Socket, FD_OOB);
+        /* Re-enable Async Event */
+        if (ReceiveFlags && *ReceiveFlags & MSG_OOB)
+        {
+            SockReenableAsyncSelectEvent(Socket, FD_OOB);
+        }
+        else
+        {
+            SockReenableAsyncSelectEvent(Socket, FD_READ);
+        }
     }
-    else
-    {
-        SockReenableAsyncSelectEvent(Socket, FD_READ);
-    }
 
+    TRACE("Leaving (Success, %ld %ld)\n", Status, IOSB->Information);
+
     if (Status == STATUS_SUCCESS && lpOverlapped && lpCompletionRoutine)
     {
-        lpCompletionRoutine(Status, IOSB->Information, lpOverlapped, *ReceiveFlags);
-        HeapFree(GlobalHeap, 0, (PVOID)APCContext);
+        lpCompletionRoutine(Status, IOSB->Information, lpOverlapped, ReceiveFlags != NULL ? *ReceiveFlags : 0);
     }
 
     return MsafdReturnWithErrno ( Status, lpErrno, IOSB->Information, lpNumberOfBytesRead );
@@ -580,14 +672,16 @@
 {
     PIO_STATUS_BLOCK        IOSB;
     IO_STATUS_BLOCK         DummyIOSB;
-    AFD_SEND_INFO           SendInfo;
+    PAFD_SEND_INFO          SendInfo;
     NTSTATUS                Status;
-    PVOID                   APCContext;
-    PVOID                   APCFunction;
+    PAFDSENDAPCCONTEXT      APCContext;
+    PIO_APC_ROUTINE         APCFunction;
     HANDLE                  Event = NULL;
     HANDLE                  SockEvent;
     PSOCKET_INFORMATION     Socket;
 
+    TRACE("WSPSend Called (%x)\n", Handle);
+
     /* Get the Socket Structure associate to this Socket*/
     Socket = GetSocketStructure(Handle);
     if (!Socket)
@@ -603,19 +697,29 @@
         return SOCKET_ERROR;
     }
 
+    /* Allocate a send info buffer */
+    SendInfo = HeapAlloc(GlobalHeap, 0, sizeof(AFD_SEND_INFO));
+    if (!SendInfo)
+    {
+        if (lpErrno)
+            *lpErrno = WSAENOBUFS;
+        return SOCKET_ERROR;
+    }
+
     Status = NtCreateEvent( &SockEvent, EVENT_ALL_ACCESS,
                             NULL, 1, FALSE );
 
     if( !NT_SUCCESS(Status) )
-        return -1;
+    {
+        HeapFree(GlobalHeap, 0, SendInfo);
+        return SOCKET_ERROR;
+    }
 
-    TRACE("Called\n");
-
     /* Set up the Send Structure */
-    SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers;
-    SendInfo.BufferCount = dwBufferCount;
-    SendInfo.TdiFlags = 0;
-    SendInfo.AfdFlags = Socket->SharedData->NonBlocking ? AFD_IMMEDIATE : 0;
+    SendInfo->BufferArray = (PAFD_WSABUF)lpBuffers;
+    SendInfo->BufferCount = dwBufferCount;
+    SendInfo->TdiFlags = 0;
+    SendInfo->AfdFlags = Socket->SharedData->NonBlocking ? AFD_IMMEDIATE : 0;
 
     /* Set the TDI Flags */
     if (iFlags)
@@ -622,11 +726,11 @@
     {
         if (iFlags & MSG_OOB)
         {
-            SendInfo.TdiFlags |= TDI_SEND_EXPEDITED;
+            SendInfo->TdiFlags |= TDI_SEND_EXPEDITED;
         }
         if (iFlags & MSG_PARTIAL)
         {
-            SendInfo.TdiFlags |= TDI_SEND_PARTIAL;
+            SendInfo->TdiFlags |= TDI_SEND_PARTIAL;
         }
     }
 
@@ -645,12 +749,12 @@
         if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0)
         {
             TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
-            return MsafdReturnWithErrno(0, lpErrno, 0, lpNumberOfBytesSent);
+            return MsafdReturnWithErrno(STATUS_SUCCESS, lpErrno, 0, lpNumberOfBytesSent);
         }
         if (lpCompletionRoutine == NULL)
         {
             /* Using Overlapped Structure, but no Completion Routine, so no need for APC */
-            APCContext = lpOverlapped;
+            APCContext = (PAFDSENDAPCCONTEXT)lpOverlapped;
             APCFunction = NULL;
             Event = lpOverlapped->hEvent;
         }
@@ -657,23 +761,26 @@
         else
         {
             /* Using Overlapped Structure and a Completion Routine, so use an APC */
-            APCFunction = &AfdAPC; // should be a private io completion function inside us
-            APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDAPCCONTEXT));
+            APCFunction = &AfdSendAPC; // should be a private io completion function inside us
+            APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDSENDAPCCONTEXT));
             if (!APCContext)
             {
                 ERR("Not enough memory for APC Context\n");
                 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, lpNumberOfBytesSent);
             }
-            ((PAFDAPCCONTEXT)APCContext)->lpCompletionRoutine = lpCompletionRoutine;
-            ((PAFDAPCCONTEXT)APCContext)->lpOverlapped = lpOverlapped;
-            ((PAFDAPCCONTEXT)APCContext)->lpSocket = Socket;
-            SendInfo.AfdFlags |= AFD_SKIP_FIO;
+            APCContext->lpCompletionRoutine = lpCompletionRoutine;
+            APCContext->lpOverlapped = lpOverlapped;
+            APCContext->lpSocket = Socket;
+            APCContext->lpSendInfo = SendInfo;
+            APCContext->lpRemoteAddress = NULL;
+            SendInfo->AfdFlags |= AFD_SKIP_FIO;
         }
 
         IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal;
-        SendInfo.AfdFlags |= AFD_OVERLAPPED;
+        SendInfo->AfdFlags |= AFD_OVERLAPPED;
     }
 
+    IOSB->Information = 0;
     IOSB->Status = STATUS_PENDING;
 
     /* Send IOCTL */
@@ -683,15 +790,15 @@
                                     APCContext,
                                     IOSB,
                                     IOCTL_AFD_SEND,
-                                    &SendInfo,
-                                    sizeof(SendInfo),
+                                    SendInfo,
+                                    sizeof(AFD_SEND_INFO),
                                     NULL,
                                     0);
 
     /* Wait for completion of not overlapped */
-    if (Status == STATUS_PENDING && lpOverlapped == NULL)
+    if (Status == STATUS_PENDING)
     {
-        WaitForSingleObject(SockEvent, INFINITE); // BUGBUG, shouldn wait infinitely for send...
+        WaitForSingleObject(SockEvent, (lpOverlapped || Socket->SharedData->NonBlocking) ? 0 : INFINITE); // BUGBUG, shouldn wait infintely for send...
         Status = IOSB->Status;
     }
 
@@ -703,15 +810,24 @@
         return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesSent);
     }
 
+    if (APCFunction)
+    {
+        APCContext->lpSendInfo = NULL;
+        APCContext->lpCompletionRoutine = NULL;
+        APCContext->lpSocket = NULL;
+        /* This will be freed by the APC */
+        //HeapFree(GlobalHeap, 0, APCContext);
+    }
+    HeapFree(GlobalHeap, 0, SendInfo);
+
     /* Re-enable Async Event */
     SockReenableAsyncSelectEvent(Socket, FD_WRITE);
 
-    TRACE("Leaving (Success, %d)\n", IOSB->Information);
+    TRACE("Leaving (%ld %ld)\n", Status, IOSB->Information);
 
     if (Status == STATUS_SUCCESS && lpOverlapped && lpCompletionRoutine)
     {
         lpCompletionRoutine(Status, IOSB->Information, lpOverlapped, 0);
-        HeapFree(GlobalHeap, 0, (PVOID)APCContext);
     }
 
     return MsafdReturnWithErrno( Status, lpErrno, IOSB->Information, lpNumberOfBytesSent );
@@ -733,10 +849,10 @@
 {
     PIO_STATUS_BLOCK        IOSB;
     IO_STATUS_BLOCK         DummyIOSB;
-    AFD_SEND_INFO_UDP       SendInfo;
+    PAFD_SEND_INFO_UDP      SendInfo;
     NTSTATUS                Status;
-    PVOID                   APCContext;
-    PVOID                   APCFunction;
+    PAFDSENDAPCCONTEXT      APCContext;
+    PIO_APC_ROUTINE         APCFunction;
     HANDLE                  Event = NULL;
     PTRANSPORT_ADDRESS      RemoteAddress;
     PSOCKADDR               BindAddress = NULL;
@@ -744,6 +860,8 @@
     HANDLE                  SockEvent;
     PSOCKET_INFORMATION     Socket;
 
+    TRACE("WSPSendTo Called (%x)\n", Handle);
+
     /* Get the Socket Structure associate to this Socket */
     Socket = GetSocketStructure(Handle);
     if (!Socket)
@@ -803,6 +921,17 @@
         return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL);
     }
 
+    SendInfo = HeapAlloc(GlobalHeap, 0, sizeof(AFD_SEND_INFO_UDP));
+    if (!SendInfo)
+    {
+        HeapFree(GlobalHeap, 0, RemoteAddress);
+        if (BindAddress != NULL)
+        {
+            HeapFree(GlobalHeap, 0, BindAddress);
+        }
+        return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL);
+    }
+
     Status = NtCreateEvent(&SockEvent,
                            EVENT_ALL_ACCESS,
                            NULL, 1, FALSE);
@@ -809,6 +938,7 @@
 
     if (!NT_SUCCESS(Status))
     {
+        HeapFree(GlobalHeap, 0, SendInfo);
         HeapFree(GlobalHeap, 0, RemoteAddress);
         if (BindAddress != NULL)
         {
@@ -823,11 +953,11 @@
     RtlCopyMemory(&RemoteAddress->Address[0].AddressType, SocketAddress, SocketAddressLength);
 
     /* Set up Structure */
-    SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers;
-    SendInfo.AfdFlags = Socket->SharedData->NonBlocking ? AFD_IMMEDIATE : 0;
-    SendInfo.BufferCount = dwBufferCount;
-    SendInfo.TdiConnection.RemoteAddress = RemoteAddress;
-    SendInfo.TdiConnection.RemoteAddressLength = Socket->HelperData->MaxTDIAddressLength;
+    SendInfo->BufferArray = (PAFD_WSABUF)lpBuffers;
+    SendInfo->AfdFlags = Socket->SharedData->NonBlocking ? AFD_IMMEDIATE : 0;
+    SendInfo->BufferCount = dwBufferCount;
+    SendInfo->TdiConnection.RemoteAddress = RemoteAddress;
+    SendInfo->TdiConnection.RemoteAddressLength = Socket->HelperData->MaxTDIAddressLength;
 
     /* Verify if we should use APC */
     if (lpOverlapped == NULL)
@@ -844,12 +974,12 @@
         if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0)
         {
             TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
-            return MsafdReturnWithErrno(0, lpErrno, 0, lpNumberOfBytesSent);
+            return MsafdReturnWithErrno(STATUS_SUCCESS, lpErrno, 0, lpNumberOfBytesSent);
         }
         if (lpCompletionRoutine == NULL)
         {
             /* Using Overlapped Structure, but no Completion Routine, so no need for APC */
-            APCContext = lpOverlapped;
+            APCContext = (PAFDSENDAPCCONTEXT)lpOverlapped;
             APCFunction = NULL;
             Event = lpOverlapped->hEvent;
         }
@@ -856,23 +986,28 @@
         else
         {
             /* Using Overlapped Structure and a Completion Routine, so use an APC */
-            APCFunction = &AfdAPC; // should be a private io completion function inside us
-            APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDAPCCONTEXT));
+            APCFunction = &AfdSendAPC; // should be a private io completion function inside us
+            APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDSENDAPCCONTEXT));
             if (!APCContext)
             {
                 ERR("Not enough memory for APC Context\n");
                 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, lpNumberOfBytesSent);
             }
-            ((PAFDAPCCONTEXT)APCContext)->lpCompletionRoutine = lpCompletionRoutine;
-            ((PAFDAPCCONTEXT)APCContext)->lpOverlapped = lpOverlapped;
-            ((PAFDAPCCONTEXT)APCContext)->lpSocket = Socket;
-            SendInfo.AfdFlags |= AFD_SKIP_FIO;
+            APCContext->lpCompletionRoutine = lpCompletionRoutine;
+            APCContext->lpOverlapped = lpOverlapped;
+            APCContext->lpSocket = Socket;
+            APCContext->lpSendInfo = SendInfo;
+            APCContext->lpRemoteAddress = RemoteAddress;
+            SendInfo->AfdFlags |= AFD_SKIP_FIO;
         }
 
         IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal;
-        SendInfo.AfdFlags |= AFD_OVERLAPPED;
+        SendInfo->AfdFlags |= AFD_OVERLAPPED;
     }
 
+    IOSB->Information = 0;
+    IOSB->Status = STATUS_PENDING;
+
     /* Send IOCTL */
     Status = NtDeviceIoControlFile((HANDLE)Handle,
                                    Event,
@@ -880,21 +1015,21 @@
                                    APCContext,
                                    IOSB,
                                    IOCTL_AFD_SEND_DATAGRAM,
-                                   &SendInfo,
-                                   sizeof(SendInfo),
+                                   SendInfo,
+                                   sizeof(AFD_SEND_INFO_UDP),
                                    NULL,
                                    0);
 
     /* Wait for completion of not overlapped */
-    if (Status == STATUS_PENDING && lpOverlapped == NULL)
+    if (Status == STATUS_PENDING)
     {
         /* BUGBUG, shouldn't wait infinitely for send... */
-        WaitForSingleObject(SockEvent, INFINITE);
+        WaitForSingleObject(SockEvent, (lpOverlapped || Socket->SharedData->NonBlocking) ? 0 : INFINITE);
         Status = IOSB->Status;
     }
 
     NtClose(SockEvent);
-    HeapFree(GlobalHeap, 0, RemoteAddress);
+
     if (BindAddress != NULL)
     {
         HeapFree(GlobalHeap, 0, BindAddress);
@@ -905,13 +1040,25 @@
         TRACE("Leaving (Pending)\n");
         return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesSent);
     }
+    if (APCFunction)
+    {
+        APCContext->lpSendInfo = NULL;
+        APCContext->lpRemoteAddress = NULL;
+        APCContext->lpCompletionRoutine = NULL;
+        APCContext->lpSocket = NULL;
+        /* This will be freed by the APC */
+        //HeapFree(GlobalHeap, 0, APCContext);
+    }
+    HeapFree(GlobalHeap, 0, SendInfo);
+    HeapFree(GlobalHeap, 0, RemoteAddress);
 
     SockReenableAsyncSelectEvent(Socket, FD_WRITE);
 
+    TRACE("Leaving (%ld %ld)\n", Status, IOSB->Information);
+
     if (Status == STATUS_SUCCESS && lpOverlapped && lpCompletionRoutine)
     {
         lpCompletionRoutine(Status, IOSB->Information, lpOverlapped, 0);
-        HeapFree(GlobalHeap, 0, (PVOID)APCContext);
     }
 
     return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesSent);
Index: dll/win32/msafd/msafd.h
===================================================================
--- dll/win32/msafd/msafd.h	(revision 73320)
+++ dll/win32/msafd/msafd.h	(working copy)
@@ -129,13 +129,38 @@
 	AFD_POLL_INFO AsyncSelectInfo;
 } ASYNC_DATA, *PASYNC_DATA;
 
-typedef struct _AFDAPCCONTEXT
+typedef struct _AFDINFOAPCCONTEXT
 {
     LPWSAOVERLAPPED lpOverlapped;
     LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine;
+} AFDINFOAPCCONTEXT, *PAFDINFOAPCCONTEXT;
+
+typedef struct _AFDSENDAPCCONTEXT
+{
+    LPWSAOVERLAPPED lpOverlapped;
+    LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine;
     PSOCKET_INFORMATION lpSocket;
-} AFDAPCCONTEXT, *PAFDAPCCONTEXT;
+    IO_STATUS_BLOCK IoStatusBlock;
+    LPVOID lpSendInfo;
+    PTRANSPORT_ADDRESS lpRemoteAddress;
+} AFDSENDAPCCONTEXT, *PAFDSENDAPCCONTEXT;
 
+typedef struct _AFDRECVAPCCONTEXT
+{
+    LPWSAOVERLAPPED lpOverlapped;
+    LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine;
+    PSOCKET_INFORMATION lpSocket;
+    IO_STATUS_BLOCK IoStatusBlock;
+    LPVOID lpRecvInfo;
+} AFDRECVAPCCONTEXT, *PAFDRECVAPCCONTEXT;
+
+typedef struct _AFDCONNECTAPCCONTEXT
+{
+    PAFD_CONNECT_INFO lpConnectInfo;
+    PSOCKET_INFORMATION lpSocket;
+    IO_STATUS_BLOCK IoStatusBlock;
+} AFDCONNECTAPCCONTEXT, *PAFDCONNECTAPCCONTEXT;
+
 SOCKET
 WSPAPI
 WSPAccept(
@@ -499,6 +524,9 @@
                      DWORD Received,
                      LPDWORD ReturnedBytes)
 {
+    /* Allow for APC to be processed */
+    SleepEx(0, TRUE);
+
     if (Errno)
     {
         *Errno = TranslateNtStatusError(Status);
@@ -510,7 +538,7 @@
     }
     else
     {
-        DbgPrint("%s: Received invalid lpErrno pointer!\n", __FUNCTION__);
+        //DbgPrint("%s: Received invalid lpErrno pointer!\n", __FUNCTION__);
 
         if (ReturnedBytes)
             *ReturnedBytes = (Status == STATUS_SUCCESS) ? Received : 0;
Index: drivers/network/afd/afd/tdi.c
===================================================================
--- drivers/network/afd/afd/tdi.c	(revision 73320)
+++ drivers/network/afd/afd/tdi.c	(working copy)
@@ -955,11 +955,9 @@
                  Flags,                  /* Flags */
                  BufferLength);          /* Length of data */
 
-    TdiCall(*Irp, DeviceObject, NULL, NULL);
     /* Does not block...  The MDL is deleted in the receive completion
        routine. */
-
-    return STATUS_PENDING;
+    return TdiCall(*Irp, DeviceObject, NULL, NULL);
 }
 
 NTSTATUS TdiReceive(
@@ -1228,11 +1226,9 @@
                          BufferLength,           /* Bytes to send */
                          Addr);                  /* Address */
 
-    TdiCall(*Irp, DeviceObject, NULL, NULL);
     /* Does not block...  The MDL is deleted in the send completion
        routine. */
-
-    return STATUS_PENDING;
+    return TdiCall(*Irp, DeviceObject, NULL, NULL);
 }
 
 NTSTATUS TdiDisconnect(
Index: drivers/network/afd/afd/write.c
===================================================================
--- drivers/network/afd/afd/write.c	(revision 73320)
+++ drivers/network/afd/afd/write.c	(working copy)
@@ -379,6 +379,10 @@
             Status = QueueUserModeIrp(FCB, Irp, FUNCTION_SEND);
             if (Status == STATUS_PENDING)
             {
+                if (SendReq->BufferCount > 1)
+                {
+                    AFD_DbgPrint(MIN_TRACE,("WARN: More than one buffer %ld!\n", SendReq->BufferCount));
+                }
                 Status = TdiSendDatagram(&FCB->SendIrp.InFlightRequest,
                                          FCB->AddressFile.Object,
                                          SendReq->BufferArray[0].buf,
@@ -390,7 +394,7 @@
                 {
                     NT_VERIFY(RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]) == &Irp->Tail.Overlay.ListEntry);
                     Irp->IoStatus.Status = Status;
-                    Irp->IoStatus.Information = 0;
+                    Irp->IoStatus.Information = Status == STATUS_SUCCESS ? SendReq->BufferArray[0].len : 0;
                     (void)IoSetCancelRoutine(Irp, NULL);
                     UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE);
                     UnlockRequest(Irp, IoGetCurrentIrpStackLocation(Irp));
@@ -641,6 +645,10 @@
         Status = QueueUserModeIrp(FCB, Irp, FUNCTION_SEND);
         if (Status == STATUS_PENDING)
         {
+            if (SendReq->BufferCount > 1)
+            {
+                AFD_DbgPrint(MIN_TRACE,("WARN: More than one buffer %ld!\n", SendReq->BufferCount));
+            }
             Status = TdiSendDatagram(&FCB->SendIrp.InFlightRequest,
                                      FCB->AddressFile.Object,
                                      SendReq->BufferArray[0].buf,
@@ -652,7 +660,7 @@
             {
                 NT_VERIFY(RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]) == &Irp->Tail.Overlay.ListEntry);
                 Irp->IoStatus.Status = Status;
-                Irp->IoStatus.Information = 0;
+                Irp->IoStatus.Information = Status == STATUS_SUCCESS ? SendReq->BufferArray[0].len : 0;
                 (void)IoSetCancelRoutine(Irp, NULL);
                 UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE);
                 UnlockRequest(Irp, IoGetCurrentIrpStackLocation(Irp));
Index: sdk/lib/drivers/ip/transport/tcp/tcp.c
===================================================================
--- sdk/lib/drivers/ip/transport/tcp/tcp.c	(revision 73089)
+++ sdk/lib/drivers/ip/transport/tcp/tcp.c	(working copy)
@@ -337,6 +337,12 @@
     
     if (NT_SUCCESS(Status))
     {
+        /* Check if we had an unspecified address */
+        if (Connection->AddressFile->Address.Address.IPv4Address != bindaddr.addr)
+        {
+            /* We did, so we need to copy back the address */
+            Connection->AddressFile->Address.Address.IPv4Address = bindaddr.addr;
+        }
         /* Check if we had an unspecified port */
         if (!Connection->AddressFile->Port)
         {
