Commit in reactos/lib/msafd on MAIN
include/msafd.h+1-11.11 -> 1.12
misc/dllmain.c+121-31.26 -> 1.27
+122-4
2 modified files
Implemented WSPCloseSocket.

reactos/lib/msafd/include
msafd.h 1.11 -> 1.12
diff -u -r1.11 -r1.12
--- msafd.h	4 Dec 2004 23:29:55 -0000	1.11
+++ msafd.h	19 Dec 2004 20:13:28 -0000	1.12
@@ -49,7 +49,7 @@
     INT							Protocol;
     INT							SizeOfLocalAddress;
     INT							SizeOfRemoteAddress;
-    ULONG						LingerData;
+    struct linger				LingerData;
     ULONG						SendTimeout;
     ULONG						RecvTimeout;
     ULONG						SizeOfRecvBuffer;

reactos/lib/msafd/misc
dllmain.c 1.26 -> 1.27
diff -u -r1.26 -r1.27
--- dllmain.c	19 Dec 2004 17:28:07 -0000	1.26
+++ dllmain.c	19 Dec 2004 20:13:28 -0000	1.27
@@ -284,7 +284,7 @@
 INT
 WSPAPI
 WSPCloseSocket(
-  IN  SOCKET s,
+  IN  SOCKET Handle,
   OUT	LPINT lpErrno)
 /*
  * FUNCTION: Closes an open socket
@@ -295,9 +295,127 @@
  *     NO_ERROR, or SOCKET_ERROR if the socket could not be closed
  */
 {
-	return 0;
-}
+    IO_STATUS_BLOCK IoStatusBlock;
+    PSOCKET_INFORMATION Socket = NULL;
+    NTSTATUS Status;
+    HANDLE SockEvent;
+    AFD_DISCONNECT_INFO DisconnectInfo;
+    SOCKET_STATE OldState;
+
+    /* Create the Wait Event */
+    Status = NtCreateEvent(&SockEvent,
+                           GENERIC_READ | GENERIC_WRITE,
+                           NULL,
+                           1,
+                           FALSE);    
 
+    if(!NT_SUCCESS(Status)) return SOCKET_ERROR;
+
+    /* Get the Socket Structure associate to this Socket*/
+    Socket = GetSocketStructure(Handle);
+
+    /* If a Close is already in Process, give up */
+    if (Socket->SharedData.State == SocketClosed) {
+        *lpErrno = WSAENOTSOCK;
+        return SOCKET_ERROR;
+    }
+
+    /* Set the state to close */
+    OldState = Socket->SharedData.State;
+    Socket->SharedData.State = SocketClosed;
+    
+    /* If SO_LINGER is ON and the Socket is connected, we need to disconnect */
+    /* FIXME: Should we do this on Datagram Sockets too? */
+    if ((OldState == SocketConnected) && (Socket->SharedData.LingerData.l_onoff)) {
+        ULONG LingerWait;
+        ULONG SendsInProgress;
+        ULONG SleepWait;
+        
+        /* We need to respect the timeout */
+        SleepWait = 100;
+        LingerWait = Socket->SharedData.LingerData.l_linger * 1000;
+        
+        /* Loop until no more sends are pending, within the timeout */
+        while (LingerWait) {
+            
+            /* Find out how many Sends are in Progress */
+            if (GetSocketInformation(Socket, 
+                                     AFD_INFO_SENDS_IN_PROGRESS,
+                                     &SendsInProgress,
+                                     NULL)) {
+                /* Bail out if anything but NO_ERROR */
+                LingerWait = 0;
+                break;
+            }
+
+            /* Bail out if no more sends are pending */
+            if (!SendsInProgress) break;
+            
+            /* 
+             * We have to execute a sleep, so it's kind of like
+             * a block. If the socket is Nonblock, we cannot
+             * go on since asyncronous operation is expected
+             * and we cannot offer it
+             */
+            if (Socket->SharedData.NonBlocking) {
+                Socket->SharedData.State = OldState;
+                *lpErrno = WSAEWOULDBLOCK;
+                return SOCKET_ERROR;
+            }
+            
+            /* Now we can sleep, and decrement the linger wait */
+            /* 
+             * FIXME: It seems Windows does some funky acceleration
+             * since the waiting seems to be longer and longer. I
+             * don't think this improves performance so much, so we
+             * wait a fixed time instead.
+             */
+            Sleep(SleepWait);
+            LingerWait -= SleepWait;
+        }
+        
+        /*
+         * We have reached the timeout or sends are over.
+         * Disconnect if the timeout has been reached. 
+         */
+        if (LingerWait <= 0) {
+        
+            DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(0);
+            DisconnectInfo.DisconnectType = AFD_DISCONNECT_ABORT;
+            
+            /* Send IOCTL */
+            Status = NtDeviceIoControlFile((HANDLE)Handle,
+                                           SockEvent,
+                                           NULL,
+                                           NULL,
+                                           &IoStatusBlock,
+                                           IOCTL_AFD_DISCONNECT,
+                                           &DisconnectInfo,
+                                           sizeof(DisconnectInfo),
+                                           NULL,
+                                           0);
+        
+            /* Wait for return */
+            if (Status == STATUS_PENDING) {
+                WaitForSingleObject(SockEvent, INFINITE);
+            }         
+        }
+    }
+    
+    /* FIXME: We should notify the Helper DLL of WSH_NOTIFY_CLOSE */
+    
+    /* Cleanup Time! */
+    Socket->HelperContext = NULL;
+    Socket->SharedData.AsyncDisabledEvents = -1;
+    NtClose(Socket->TdiAddressHandle);
+    Socket->TdiAddressHandle = NULL;
+    NtClose(Socket->TdiConnectionHandle);
+    Socket->TdiConnectionHandle = NULL;
+
+    /* Close the handle */
+    NtClose((HANDLE)Handle);
+    return NO_ERROR;
+}
 
 INT
 WSPAPI
CVSspam 0.2.8