[MSAFD] Implement async connect
[reactos.git] / reactos / dll / win32 / msafd / misc / dllmain.c
index b156980..dda602f 100644 (file)
@@ -1719,6 +1719,46 @@ WSPAccept(SOCKET Handle,
     return AcceptSocket;
 }
 
+VOID
+NTAPI
+AfdConnectAPC(PVOID ApcContext,
+              PIO_STATUS_BLOCK IoStatusBlock,
+              ULONG Reserved)
+{
+    PAFDCONNECTAPCCONTEXT Context = ApcContext;
+
+    if (IoStatusBlock->Status == STATUS_SUCCESS)
+    {
+        Context->lpSocket->SharedData->State = SocketConnected;
+        Context->lpSocket->TdiConnectionHandle = (HANDLE)IoStatusBlock->Information;
+    }
+
+    if (Context->lpConnectInfo) HeapFree(GetProcessHeap(), 0, Context->lpConnectInfo);
+
+    /* 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,
@@ -1741,15 +1781,8 @@ WSPConnect(SOCKET Handle,
     PSOCKADDR               BindAddress;
     HANDLE                  SockEvent;
     int                     SocketDataLength;
-
-    Status = NtCreateEvent(&SockEvent,
-                           EVENT_ALL_ACCESS,
-                           NULL,
-                           1,
-                           FALSE);
-
-    if (!NT_SUCCESS(Status))
-        return MsafdReturnWithErrno(Status, lpErrno, 0, NULL);
+    PVOID                   APCContext = NULL;
+    PVOID                   APCFunction = NULL;
 
     TRACE("Called\n");
 
@@ -1757,11 +1790,19 @@ WSPConnect(SOCKET Handle,
     Socket = GetSocketStructure(Handle);
     if (!Socket)
     {
-        NtClose(SockEvent);
         if (lpErrno) *lpErrno = WSAENOTSOCK;
         return SOCKET_ERROR;
     }
 
+    Status = NtCreateEvent(&SockEvent,
+                           EVENT_ALL_ACCESS,
+                           NULL,
+                           1,
+                           FALSE);
+
+    if (!NT_SUCCESS(Status))
+        return MsafdReturnWithErrno(Status, lpErrno, 0, NULL);
+
     /* Bind us First */
     if (Socket->SharedData->State == SocketOpen)
     {
@@ -1872,14 +1913,22 @@ WSPConnect(SOCKET Handle,
     /* 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);
+        }
+        ((PAFDCONNECTAPCCONTEXT)APCContext)->lpConnectInfo = ConnectInfo;
+        ((PAFDCONNECTAPCCONTEXT)APCContext)->lpSocket = Socket;
     }
 
     /* Send IOCTL */
     Status = NtDeviceIoControlFile((HANDLE)Handle,
                                    SockEvent,
-                                   NULL,
-                                   NULL,
+                                   APCFunction,
+                                   APCContext,
                                    &IOSB,
                                    IOCTL_AFD_CONNECT,
                                    ConnectInfo,
@@ -1887,12 +1936,20 @@ WSPConnect(SOCKET Handle,
                                    NULL,
                                    0);
     /* Wait for return */
-    if (Status == STATUS_PENDING)
+    if (Status == STATUS_PENDING && !Socket->SharedData->NonBlocking)
     {
         WaitForSingleObject(SockEvent, INFINITE);
         Status = IOSB.Status;
     }
 
+    if (Status == STATUS_PENDING)
+    {
+        TRACE("Leaving (Pending)\n");
+        return MsafdReturnWithErrno(STATUS_CANT_WAIT, lpErrno, 0, NULL);
+    }
+
+    if (APCContext) HeapFree(GetProcessHeap(), 0, APCContext);
+
     if (Status != STATUS_SUCCESS)
         goto notify;