[MSAFD]
[reactos.git] / reactos / dll / win32 / msafd / misc / dllmain.c
index 9b459b7..3fb76c8 100644 (file)
@@ -23,6 +23,7 @@ HANDLE GlobalHeap;
 WSPUPCALLTABLE Upcalls;
 LPWPUCOMPLETEOVERLAPPEDREQUEST lpWPUCompleteOverlappedRequest;
 PSOCKET_INFORMATION SocketListHead = NULL;
+CRITICAL_SECTION SocketListLock;
 LIST_ENTRY SockHelpersListHead = { NULL, NULL };
 ULONG SockAsyncThreadRefCount;
 HANDLE SockAsyncHelperAfdHandle;
@@ -280,8 +281,10 @@ WSPSocket(int AddressFamily,
                           NULL);
 
     /* Save in Process Sockets List */
+    EnterCriticalSection(&SocketListLock);
     Socket->NextSocket = SocketListHead;
     SocketListHead = Socket;
+    LeaveCriticalSection(&SocketListLock);
 
     /* Create the Socket Context */
     CreateContext(Socket);
@@ -379,24 +382,6 @@ TranslateNtStatusError(NTSTATUS Status)
     }
 }
 
-DWORD MsafdReturnWithErrno(NTSTATUS Status,
-                           LPINT Errno,
-                           DWORD Received,
-                           LPDWORD ReturnedBytes)
-{
-    *Errno = TranslateNtStatusError(Status);
-
-    if (ReturnedBytes)
-    {
-        if (!*Errno)
-            *ReturnedBytes = Received;
-        else
-            *ReturnedBytes = 0;
-    }
-
-    return *Errno ? SOCKET_ERROR : 0;
-}
-
 /*
  * FUNCTION: Closes an open socket
  * ARGUMENTS:
@@ -556,6 +541,7 @@ WSPCloseSocket(IN SOCKET Handle,
     NtClose(Socket->TdiConnectionHandle);
     Socket->TdiConnectionHandle = NULL;
 
+    EnterCriticalSection(&SocketListLock);
     if (SocketListHead == Socket)
     {
         SocketListHead = SocketListHead->NextSocket;
@@ -574,6 +560,7 @@ WSPCloseSocket(IN SOCKET Handle,
             CurrentSocket = CurrentSocket->NextSocket;
         }
     }
+    LeaveCriticalSection(&SocketListLock);
 
     HeapFree(GlobalHeap, 0, Socket);
 
@@ -800,12 +787,12 @@ WSPListen(SOCKET Handle,
 
 int
 WSPAPI
-WSPSelect(int nfds,
-          fd_set *readfds,
-          fd_set *writefds,
-          fd_set *exceptfds,
-          const LPTIMEVAL timeout,
-          LPINT lpErrno)
+WSPSelect(IN int nfds,
+          IN OUT fd_set *readfds OPTIONAL,
+          IN OUT fd_set *writefds OPTIONAL,
+          IN OUT fd_set *exceptfds OPTIONAL,
+          IN const struct timeval *timeout OPTIONAL,
+          OUT LPINT lpErrno)
 {
     IO_STATUS_BLOCK     IOSB;
     PAFD_POLL_INFO      PollInfo;
@@ -920,7 +907,7 @@ WSPSelect(int nfds,
     }
 
     PollInfo->HandleCount = j;
-    PollBufferSize = ((PCHAR)&PollInfo->Handles[j+1]) - ((PCHAR)PollInfo);
+    PollBufferSize = FIELD_OFFSET(AFD_POLL_INFO, Handles) + PollInfo->HandleCount * sizeof(AFD_HANDLE);
 
     /* Send IOCTL */
     Status = NtDeviceIoControlFile((HANDLE)PollInfo->Handles[0].Handle,
@@ -1923,6 +1910,7 @@ WSPIoctl(IN  SOCKET Handle,
          OUT LPINT lpErrno)
 {
     PSOCKET_INFORMATION Socket = NULL;
+       BOOLEAN NeedsCompletion;
 
     /* Get the Socket Structure associate to this Socket*/
     Socket = GetSocketStructure(Handle);
@@ -1931,6 +1919,8 @@ WSPIoctl(IN  SOCKET Handle,
        *lpErrno = WSAENOTSOCK;
        return SOCKET_ERROR;
     }
+       
+       *lpcbBytesReturned = 0;
 
     switch( dwIoControlCode )
     {
@@ -1941,17 +1931,44 @@ WSPIoctl(IN  SOCKET Handle,
                 return SOCKET_ERROR;
             }
             Socket->SharedData.NonBlocking = *((PULONG)lpvInBuffer) ? 1 : 0;
-            return SetSocketInformation(Socket, AFD_INFO_BLOCKING_MODE, (PULONG)lpvInBuffer, NULL);
+            *lpErrno = SetSocketInformation(Socket, AFD_INFO_BLOCKING_MODE, (PULONG)lpvInBuffer, NULL);
+                       if (*lpErrno != NO_ERROR)
+                               return SOCKET_ERROR;
+                       else
+                               return NO_ERROR;
         case FIONREAD:
             if( cbOutBuffer < sizeof(INT) || IS_INTRESOURCE(lpvOutBuffer) )
             {
                 *lpErrno = WSAEFAULT;
                 return SOCKET_ERROR;
             }
-            return GetSocketInformation(Socket, AFD_INFO_RECEIVE_CONTENT_SIZE, (PULONG)lpvOutBuffer, NULL);
+            *lpErrno = GetSocketInformation(Socket, AFD_INFO_RECEIVE_CONTENT_SIZE, (PULONG)lpvOutBuffer, NULL);
+                       if (*lpErrno != NO_ERROR)
+                               return SOCKET_ERROR;
+                       else
+                       {
+                               *lpcbBytesReturned = sizeof(ULONG);
+                               return NO_ERROR;
+                       }
         default:
-            *lpErrno = WSAEINVAL;
-            return SOCKET_ERROR;
+                       *lpErrno = Socket->HelperData->WSHIoctl(Socket->HelperContext,
+                                                                                                       Handle,
+                                                                                                       Socket->TdiAddressHandle,
+                                                                                                       Socket->TdiConnectionHandle,
+                                                                                                       dwIoControlCode,
+                                                                                                       lpvInBuffer,
+                                                                                                       cbInBuffer,
+                                                                                                       lpvOutBuffer,
+                                                                                                       cbOutBuffer,
+                                                                                                       lpcbBytesReturned,
+                                                                                                       lpOverlapped,
+                                                                                                       lpCompletionRoutine,
+                                                                                                       (LPBOOL)&NeedsCompletion);
+                       
+                       if (*lpErrno != NO_ERROR)
+                               return SOCKET_ERROR;
+                       else
+                               return NO_ERROR;
     }
 }
 
@@ -2083,7 +2100,16 @@ WSPSetSockOpt(
     }
 
 
-    /* FIXME: We should handle some cases here */
+    /* FIXME: We should handle some more cases here */
+    if (level == SOL_SOCKET)
+    {
+        switch (optname)
+        {
+           case SO_BROADCAST:
+              Socket->SharedData.Broadcast = (*optval != 0) ? 1 : 0;
+              return 0;
+        }
+    }
 
 
     *lpErrno = Socket->HelperData->WSHSetSocketInformation(Socket->HelperContext,
@@ -2314,15 +2340,22 @@ GetSocketStructure(SOCKET Handle)
 {
     PSOCKET_INFORMATION CurrentSocket;
 
+    EnterCriticalSection(&SocketListLock);
+
     CurrentSocket = SocketListHead;
     while (CurrentSocket)
     {
         if (CurrentSocket->Handle == Handle)
+        {
+            LeaveCriticalSection(&SocketListLock);
             return CurrentSocket;
+        }
 
         CurrentSocket = CurrentSocket->NextSocket;
     }
 
+    LeaveCriticalSection(&SocketListLock);
+
     return NULL;
 }
 
@@ -2841,6 +2874,9 @@ DllMain(HANDLE hInstDll,
         /* Heap to use when allocating */
         GlobalHeap = GetProcessHeap();
 
+        /* Initialize the lock that protects our socket list */
+        InitializeCriticalSection(&SocketListLock);
+
         AFD_DbgPrint(MAX_TRACE, ("MSAFD.DLL has been loaded\n"));
 
         break;
@@ -2852,6 +2888,10 @@ DllMain(HANDLE hInstDll,
         break;
 
     case DLL_PROCESS_DETACH:
+
+        /* Delete the socket list lock */
+        DeleteCriticalSection(&SocketListLock);
+
         break;
     }