X-Git-Url: https://git.reactos.org/?p=reactos.git;a=blobdiff_plain;f=reactos%2Fdll%2Fwin32%2Fmsafd%2Fmisc%2Fdllmain.c;h=9142a39958d101d099c76f08589cfccc257ca84a;hp=fd204fdcdbd527987c20b0d6f0a4155681cdc1fb;hb=e0549f61008d95ecde6879b7ad7d3517b9303a76;hpb=94b78efb6a494fb79a6a53021384e28d83375d88 diff --git a/reactos/dll/win32/msafd/misc/dllmain.c b/reactos/dll/win32/msafd/misc/dllmain.c index fd204fdcdbd..9142a39958d 100644 --- a/reactos/dll/win32/msafd/misc/dllmain.c +++ b/reactos/dll/win32/msafd/misc/dllmain.c @@ -23,7 +23,7 @@ HANDLE GlobalHeap; WSPUPCALLTABLE Upcalls; LPWPUCOMPLETEOVERLAPPEDREQUEST lpWPUCompleteOverlappedRequest; ULONG SocketCount = 0; -PSOCKET_INFORMATION *Sockets = NULL; +PSOCKET_INFORMATION SocketListHead = NULL; LIST_ENTRY SockHelpersListHead = { NULL, NULL }; ULONG SockAsyncThreadRefCount; HANDLE SockAsyncHelperAfdHandle; @@ -292,8 +292,8 @@ WSPSocket(int AddressFamily, NULL); /* Save in Process Sockets List */ - Sockets[SocketCount] = Socket; - SocketCount ++; + Socket->NextSocket = SocketListHead; + SocketListHead = Socket; /* Create the Socket Context */ CreateContext(Socket); @@ -318,79 +318,95 @@ error: return INVALID_SOCKET; } +INT +TranslateNtStatusError(NTSTATUS Status) +{ + switch (Status) + { + case STATUS_CANT_WAIT: + return WSAEWOULDBLOCK; + + case STATUS_TIMEOUT: + return WSAETIMEDOUT; + + case STATUS_SUCCESS: + return NO_ERROR; + + case STATUS_FILE_CLOSED: + case STATUS_END_OF_FILE: + return WSAESHUTDOWN; + + case STATUS_PENDING: + return WSA_IO_PENDING; + + case STATUS_BUFFER_TOO_SMALL: + case STATUS_BUFFER_OVERFLOW: + DbgPrint("MSAFD: STATUS_BUFFER_TOO_SMALL/STATUS_BUFFER_OVERFLOW\n"); + return WSAEMSGSIZE; + + case STATUS_NO_MEMORY: + case STATUS_INSUFFICIENT_RESOURCES: + DbgPrint("MSAFD: STATUS_NO_MEMORY/STATUS_INSUFFICIENT_RESOURCES\n"); + return WSAENOBUFS; + + case STATUS_INVALID_CONNECTION: + DbgPrint("MSAFD: STATUS_INVALID_CONNECTION\n"); + return WSAEAFNOSUPPORT; + + case STATUS_INVALID_ADDRESS: + DbgPrint("MSAFD: STATUS_INVALID_ADDRESS\n"); + return WSAEADDRNOTAVAIL; + + case STATUS_REMOTE_NOT_LISTENING: + DbgPrint("MSAFD: STATUS_REMOTE_NOT_LISTENING\n"); + return WSAECONNREFUSED; + + case STATUS_NETWORK_UNREACHABLE: + DbgPrint("MSAFD: STATUS_NETWORK_UNREACHABLE\n"); + return WSAENETUNREACH; + + case STATUS_INVALID_PARAMETER: + DbgPrint("MSAFD: STATUS_INVALID_PARAMETER\n"); + return WSAEINVAL; + + case STATUS_CANCELLED: + DbgPrint("MSAFD: STATUS_CANCELLED\n"); + return WSA_OPERATION_ABORTED; + + case STATUS_ADDRESS_ALREADY_EXISTS: + DbgPrint("MSAFD: STATUS_ADDRESS_ALREADY_EXISTS\n"); + return WSAEADDRINUSE; + + case STATUS_LOCAL_DISCONNECT: + DbgPrint("MSAFD: STATUS_LOCAL_DISCONNECT\n"); + return WSAECONNABORTED; + + case STATUS_REMOTE_DISCONNECT: + DbgPrint("MSAFD: STATUS_REMOTE_DISCONNECT\n"); + return WSAECONNRESET; + + default: + DbgPrint("MSAFD: Unhandled NTSTATUS value: 0x%x\n", Status); + return WSAENETDOWN; + } +} DWORD MsafdReturnWithErrno(NTSTATUS Status, LPINT Errno, DWORD Received, LPDWORD ReturnedBytes) { - if( ReturnedBytes ) - *ReturnedBytes = 0; - if( Errno ) + *Errno = TranslateNtStatusError(Status); + + if (ReturnedBytes) { - switch (Status) - { - case STATUS_CANT_WAIT: - *Errno = WSAEWOULDBLOCK; - break; - case STATUS_TIMEOUT: - *Errno = WSAETIMEDOUT; - break; - case STATUS_SUCCESS: - /* Return Number of bytes Read */ - if( ReturnedBytes ) - *ReturnedBytes = Received; - break; - case STATUS_FILE_CLOSED: - case STATUS_END_OF_FILE: - *Errno = WSAESHUTDOWN; - break; - case STATUS_PENDING: - *Errno = WSA_IO_PENDING; - break; - case STATUS_BUFFER_TOO_SMALL: - case STATUS_BUFFER_OVERFLOW: - DbgPrint("MSAFD: STATUS_BUFFER_TOO_SMALL/STATUS_BUFFER_OVERFLOW\n"); - *Errno = WSAEMSGSIZE; - break; - case STATUS_NO_MEMORY: /* Fall through to STATUS_INSUFFICIENT_RESOURCES */ - case STATUS_INSUFFICIENT_RESOURCES: - DbgPrint("MSAFD: STATUS_NO_MEMORY/STATUS_INSUFFICIENT_RESOURCES\n"); - *Errno = WSAENOBUFS; - break; - case STATUS_INVALID_CONNECTION: - DbgPrint("MSAFD: STATUS_INVALID_CONNECTION\n"); - *Errno = WSAEAFNOSUPPORT; - break; - case STATUS_INVALID_ADDRESS: - DbgPrint("MSAFD: STATUS_INVALID_ADDRESS\n"); - *Errno = WSAEADDRNOTAVAIL; - break; - case STATUS_REMOTE_NOT_LISTENING: - DbgPrint("MSAFD: STATUS_REMOTE_NOT_LISTENING\n"); - *Errno = WSAECONNREFUSED; - break; - case STATUS_NETWORK_UNREACHABLE: - DbgPrint("MSAFD: STATUS_NETWORK_UNREACHABLE\n"); - *Errno = WSAENETUNREACH; - break; - case STATUS_INVALID_PARAMETER: - DbgPrint("MSAFD: STATUS_INVALID_PARAMETER\n"); - *Errno = WSAEINVAL; - break; - case STATUS_CANCELLED: - DbgPrint("MSAFD: STATUS_CANCELLED\n"); - *Errno = WSA_OPERATION_ABORTED; - break; - default: - DbgPrint("MSAFD: Error %x is unknown\n", Status); - *Errno = WSAEINVAL; - break; - } + if (!*Errno) + *ReturnedBytes = Received; + else + *ReturnedBytes = 0; } - /* Success */ - return Status == STATUS_SUCCESS ? 0 : SOCKET_ERROR; + return *Errno ? SOCKET_ERROR : 0; } /* @@ -407,7 +423,7 @@ WSPCloseSocket(IN SOCKET Handle, OUT LPINT lpErrno) { IO_STATUS_BLOCK IoStatusBlock; - PSOCKET_INFORMATION Socket = NULL; + PSOCKET_INFORMATION Socket = NULL, CurrentSocket; NTSTATUS Status; HANDLE SockEvent; AFD_DISCONNECT_INFO DisconnectInfo; @@ -426,6 +442,22 @@ WSPCloseSocket(IN SOCKET Handle, /* Get the Socket Structure associate to this Socket*/ Socket = GetSocketStructure(Handle); + if (Socket->HelperEvents & WSH_NOTIFY_CLOSE) + { + Status = Socket->HelperData->WSHNotify(Socket->HelperContext, + Socket->Handle, + Socket->TdiAddressHandle, + Socket->TdiConnectionHandle, + WSH_NOTIFY_CLOSE); + + if (Status) + { + if (lpErrno) *lpErrno = Status; + NtClose(SockEvent); + return SOCKET_ERROR; + } + } + /* If a Close is already in Process, give up */ if (Socket->SharedData.State == SocketClosed) { @@ -517,12 +549,11 @@ WSPCloseSocket(IN SOCKET Handle, if (Status == STATUS_PENDING) { WaitForSingleObject(SockEvent, INFINITE); + Status = IoStatusBlock.Status; } } } - /* FIXME: We should notify the Helper DLL of WSH_NOTIFY_CLOSE */ - /* Cleanup Time! */ Socket->HelperContext = NULL; Socket->SharedData.AsyncDisabledEvents = -1; @@ -531,11 +562,32 @@ WSPCloseSocket(IN SOCKET Handle, NtClose(Socket->TdiConnectionHandle); Socket->TdiConnectionHandle = NULL; + if (SocketListHead == Socket) + { + SocketListHead = SocketListHead->NextSocket; + } + else + { + CurrentSocket = SocketListHead; + while (CurrentSocket->NextSocket) + { + if (CurrentSocket->NextSocket == Socket) + { + CurrentSocket->NextSocket = CurrentSocket->NextSocket->NextSocket; + break; + } + + CurrentSocket = CurrentSocket->NextSocket; + } + } + + HeapFree(GlobalHeap, 0, Socket); + /* Close the handle */ NtClose((HANDLE)Handle); NtClose(SockEvent); - return NO_ERROR; + return MsafdReturnWithErrno(Status, lpErrno, 0, NULL); } @@ -560,25 +612,31 @@ WSPBind(SOCKET Handle, PAFD_BIND_DATA BindData; PSOCKET_INFORMATION Socket = NULL; NTSTATUS Status; - UCHAR BindBuffer[0x1A]; SOCKADDR_INFO SocketInfo; HANDLE SockEvent; + /* See below */ + BindData = HeapAlloc(GlobalHeap, 0, 0xA + SocketAddressLength); + if (!BindData) + { + return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL); + } + Status = NtCreateEvent(&SockEvent, GENERIC_READ | GENERIC_WRITE, NULL, 1, FALSE); - if( !NT_SUCCESS(Status) ) - return -1; + if (!NT_SUCCESS(Status)) + { + HeapFree(GlobalHeap, 0, BindData); + return SOCKET_ERROR; + } /* Get the Socket Structure associate to this Socket*/ Socket = GetSocketStructure(Handle); - /* Dynamic Structure...ugh */ - BindData = (PAFD_BIND_DATA)BindBuffer; - /* Set up Address in TDI Format */ BindData->Address.TAAddressCount = 1; BindData->Address.Address[0].AddressLength = SocketAddressLength - sizeof(SocketAddress->sa_family); @@ -629,11 +687,30 @@ WSPBind(SOCKET Handle, Status = IOSB.Status; } + NtClose( SockEvent ); + HeapFree(GlobalHeap, 0, BindData); + + if (Status != STATUS_SUCCESS) + return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL ); + /* Set up Socket Data */ Socket->SharedData.State = SocketBound; Socket->TdiAddressHandle = (HANDLE)IOSB.Information; - NtClose( SockEvent ); + if (Socket->HelperEvents & WSH_NOTIFY_BIND) + { + Status = Socket->HelperData->WSHNotify(Socket->HelperContext, + Socket->Handle, + Socket->TdiAddressHandle, + Socket->TdiConnectionHandle, + WSH_NOTIFY_BIND); + + if (Status) + { + if (lpErrno) *lpErrno = Status; + return SOCKET_ERROR; + } + } return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL ); } @@ -687,12 +764,30 @@ WSPListen(SOCKET Handle, { WaitForSingleObject(SockEvent, INFINITE); Status = IOSB.Status; - } + } + + NtClose( SockEvent ); + + if (Status != STATUS_SUCCESS) + return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL ); /* Set to Listening */ Socket->SharedData.Listening = TRUE; - NtClose( SockEvent ); + if (Socket->HelperEvents & WSH_NOTIFY_LISTEN) + { + Status = Socket->HelperData->WSHNotify(Socket->HelperContext, + Socket->Handle, + Socket->TdiAddressHandle, + Socket->TdiConnectionHandle, + WSH_NOTIFY_LISTEN); + + if (Status) + { + if (lpErrno) *lpErrno = Status; + return SOCKET_ERROR; + } + } return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL ); } @@ -840,6 +935,7 @@ WSPSelect(int nfds, if (Status == STATUS_PENDING) { WaitForSingleObject(SockEvent, INFINITE); + Status = IOSB.Status; } /* Clear the Structures */ @@ -1230,7 +1326,7 @@ WSPAccept(SOCKET Handle, NULL); /* Set up the Accept Structure */ - AcceptData.ListenHandle = AcceptSocket; + AcceptData.ListenHandle = (HANDLE)AcceptSocket; AcceptData.SequenceNumber = ListenReceiveData->SequenceNumber; /* Send IOCTL to Accept */ @@ -1277,6 +1373,21 @@ WSPAccept(SOCKET Handle, AFD_DbgPrint(MID_TRACE,("Socket %x\n", AcceptSocket)); + if (Status == STATUS_SUCCESS && (Socket->HelperEvents & WSH_NOTIFY_ACCEPT)) + { + Status = Socket->HelperData->WSHNotify(Socket->HelperContext, + Socket->Handle, + Socket->TdiAddressHandle, + Socket->TdiConnectionHandle, + WSH_NOTIFY_ACCEPT); + + if (Status) + { + if (lpErrno) *lpErrno = Status; + return INVALID_SOCKET; + } + } + *lpErrno = 0; /* Return Socket */ @@ -1334,7 +1445,8 @@ WSPConnect(SOCKET Handle, BindAddress, &BindAddressLength); /* Bind it */ - WSPBind(Handle, BindAddress, BindAddressLength, NULL); + if (WSPBind(Handle, BindAddress, BindAddressLength, lpErrno) == SOCKET_ERROR) + return INVALID_SOCKET; } /* Set the Connect Data */ @@ -1357,6 +1469,9 @@ WSPConnect(SOCKET Handle, WaitForSingleObject(SockEvent, INFINITE); Status = IOSB.Status; } + + if (Status != STATUS_SUCCESS) + goto notify; } /* Dynamic Structure...ugh */ @@ -1402,6 +1517,9 @@ WSPConnect(SOCKET Handle, WaitForSingleObject(SockEvent, INFINITE); Status = IOSB.Status; } + + if (Status != STATUS_SUCCESS) + goto notify; } /* AFD doesn't seem to care if these are invalid, but let's 0 them anyways */ @@ -1433,6 +1551,11 @@ WSPConnect(SOCKET Handle, Status = IOSB.Status; } + if (Status != STATUS_SUCCESS) + goto notify; + + Socket->TdiConnectionHandle = (HANDLE)IOSB.Information; + /* Get any pending connect data */ if (lpCalleeData != NULL) { @@ -1454,16 +1577,46 @@ WSPConnect(SOCKET Handle, } } + AFD_DbgPrint(MID_TRACE,("Ending\n")); + +notify: /* Re-enable Async Event */ SockReenableAsyncSelectEvent(Socket, FD_WRITE); /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */ SockReenableAsyncSelectEvent(Socket, FD_CONNECT); - AFD_DbgPrint(MID_TRACE,("Ending\n")); - NtClose( SockEvent ); + if (Status == STATUS_SUCCESS && (Socket->HelperEvents & WSH_NOTIFY_CONNECT)) + { + Status = Socket->HelperData->WSHNotify(Socket->HelperContext, + Socket->Handle, + Socket->TdiAddressHandle, + Socket->TdiConnectionHandle, + WSH_NOTIFY_CONNECT); + + if (Status) + { + if (lpErrno) *lpErrno = Status; + return SOCKET_ERROR; + } + } + else if (Status != STATUS_SUCCESS && (Socket->HelperEvents & WSH_NOTIFY_CONNECT_ERROR)) + { + Status = Socket->HelperData->WSHNotify(Socket->HelperContext, + Socket->Handle, + Socket->TdiAddressHandle, + Socket->TdiConnectionHandle, + WSH_NOTIFY_CONNECT_ERROR); + + if (Status) + { + if (lpErrno) *lpErrno = Status; + return SOCKET_ERROR; + } + } + return MsafdReturnWithErrno( Status, lpErrno, 0, NULL ); } int @@ -1740,6 +1893,7 @@ WSPIoctl(IN SOCKET Handle, *lpErrno = WSAEFAULT; return SOCKET_ERROR; } + Socket->SharedData.NonBlocking = *((PULONG)lpvInBuffer) ? 1 : 0; return SetSocketInformation(Socket, AFD_INFO_BLOCKING_MODE, (PULONG)lpvInBuffer, NULL); case FIONREAD: if( cbOutBuffer < sizeof(INT) || IS_INTRESOURCE(lpvOutBuffer) ) @@ -1849,11 +2003,52 @@ WSPGetSockOpt(IN SOCKET Handle, case IPPROTO_TCP: /* FIXME */ default: - *lpErrno = WSAEINVAL; - return SOCKET_ERROR; + *lpErrno = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, + Handle, + Socket->TdiAddressHandle, + Socket->TdiConnectionHandle, + Level, + OptionName, + OptionValue, + (LPINT)OptionLength); + return (*lpErrno == 0) ? 0 : SOCKET_ERROR; } } +INT +WSPAPI +WSPSetSockOpt( + IN SOCKET s, + IN INT level, + IN INT optname, + IN CONST CHAR FAR* optval, + IN INT optlen, + OUT LPINT lpErrno) +{ + PSOCKET_INFORMATION Socket; + + /* Get the Socket Structure associate to this Socket*/ + Socket = GetSocketStructure(s); + if (Socket == NULL) + { + *lpErrno = WSAENOTSOCK; + return SOCKET_ERROR; + } + + + /* FIXME: We should handle some cases here */ + + + *lpErrno = Socket->HelperData->WSHSetSocketInformation(Socket->HelperContext, + s, + Socket->TdiAddressHandle, + Socket->TdiConnectionHandle, + level, + optname, + (PCHAR)optval, + optlen); + return (*lpErrno == 0) ? 0 : SOCKET_ERROR; +} /* * FUNCTION: Initialize service provider for a client @@ -1983,8 +2178,12 @@ GetSocketInformation(PSOCKET_INFORMATION Socket, if (Status == STATUS_PENDING) { WaitForSingleObject(SockEvent, INFINITE); + Status = IOSB.Status; } + if (Status != STATUS_SUCCESS) + return -1; + /* Return Information */ if (Ulong != NULL) { @@ -2054,27 +2253,34 @@ SetSocketInformation(PSOCKET_INFORMATION Socket, if (Status == STATUS_PENDING) { WaitForSingleObject(SockEvent, INFINITE); + Status = IOSB.Status; } NtClose( SockEvent ); - return 0; + return Status == STATUS_SUCCESS ? 0 : -1; } PSOCKET_INFORMATION GetSocketStructure(SOCKET Handle) { - ULONG i; + PSOCKET_INFORMATION CurrentSocket; + + /* This is a special case */ + if (SocketListHead->Handle == Handle) + return SocketListHead; - for (i=0; iNextSocket) { - if (Sockets[i]->Handle == Handle) - { - return Sockets[i]; - } + if (CurrentSocket->Handle == Handle) + return CurrentSocket; + + CurrentSocket = CurrentSocket->NextSocket; } - return 0; + + return NULL; } int CreateContext(PSOCKET_INFORMATION Socket) @@ -2119,11 +2325,12 @@ int CreateContext(PSOCKET_INFORMATION Socket) if (Status == STATUS_PENDING) { WaitForSingleObject(SockEvent, INFINITE); + Status = IOSB.Status; } NtClose( SockEvent ); - return 0; + return Status == STATUS_SUCCESS ? 0 : -1; } BOOLEAN SockCreateOrReferenceAsyncThread(VOID) @@ -2591,10 +2798,6 @@ DllMain(HANDLE hInstDll, /* Heap to use when allocating */ GlobalHeap = GetProcessHeap(); - /* Allocate Heap for 1024 Sockets, can be expanded later */ - Sockets = HeapAlloc(GetProcessHeap(), 0, sizeof(PSOCKET_INFORMATION) * 1024); - if (!Sockets) return FALSE; - AFD_DbgPrint(MAX_TRACE, ("MSAFD.DLL has been loaded\n")); break;