From bbff093a12f92410a9726f8629365aa4bce2e913 Mon Sep 17 00:00:00 2001 From: Erich Hoover Date: Tue, 11 Oct 2011 08:19:15 -0600 Subject: ntdll: Pass ReadFile and WriteFile requests on sockets to ws2_32.dll. --- dlls/ntdll/file.c | 141 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 140 insertions(+), 1 deletions(-) diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c index 744e09f..fe5dbff 100644 --- a/dlls/ntdll/file.c +++ b/dlls/ntdll/file.c @@ -86,6 +86,9 @@ #include "winioctl.h" #include "ddk/ntddser.h" +#define USE_WS_PREFIX +#include "winsock2.h" + WINE_DEFAULT_DEBUG_CHANNEL(ntdll); WINE_DECLARE_DEBUG_CHANNEL(winediag); @@ -94,6 +97,85 @@ mode_t FILE_umask = 0; #define SECSPERDAY 86400 #define SECS_1601_TO_1970 ((369 * 365 + 89) * (ULONGLONG)SECSPERDAY) +/* NtStatusToWSAError in dlls/ws2_32/socket.c corresponds to this function */ +static inline NTSTATUS WSAErrorToNtStatus( const int status ) +{ + /* We only need to cover the status codes set by server async request handling */ + NTSTATUS nterr; + switch ( status ) + { + case 0: nterr = STATUS_SUCCESS; break; + case WSA_IO_PENDING: nterr = STATUS_PENDING; break; + case WSAENOTSOCK: nterr = STATUS_OBJECT_TYPE_MISMATCH; break; + case WSAEBADF: nterr = STATUS_INVALID_HANDLE; break; + case WSAEINVAL: nterr = STATUS_INVALID_PARAMETER; break; + case WSAESHUTDOWN: nterr = STATUS_PIPE_DISCONNECTED; break; + case WSAEALREADY: nterr = STATUS_NETWORK_BUSY; break; + case WSAENETUNREACH: nterr = STATUS_NETWORK_UNREACHABLE; break; + case WSAECONNREFUSED: nterr = STATUS_CONNECTION_REFUSED; break; + case WSAENOTCONN: nterr = STATUS_CONNECTION_DISCONNECTED; break; + case WSAECONNRESET: nterr = STATUS_CONNECTION_RESET; break; + case WSAECONNABORTED: nterr = STATUS_CONNECTION_ABORTED; break; + case WSA_OPERATION_ABORTED: nterr = STATUS_CANCELLED; break; + case WSAEADDRINUSE: nterr = STATUS_ADDRESS_ALREADY_ASSOCIATED; break; + case WSAETIMEDOUT: nterr = STATUS_IO_TIMEOUT; break; + case WSAEFAULT: nterr = STATUS_NO_MEMORY; break; + case WSAEACCES: nterr = STATUS_ACCESS_DENIED; break; + case WSAEMFILE: nterr = STATUS_TOO_MANY_OPENED_FILES; break; + case WSAEWOULDBLOCK: nterr = STATUS_CANT_WAIT; break; + case WSAEMSGSIZE: nterr = STATUS_BUFFER_OVERFLOW; break; + case WSAEOPNOTSUPP: nterr = STATUS_NOT_SUPPORTED; break; + case WSAEHOSTUNREACH: nterr = STATUS_HOST_UNREACHABLE; break; + + default: + if ( status < WSABASEERR || status > WSABASEERR+1004 ) + FIXME( "Unhandled WSAError code: %d\n", status ); + else + FIXME( "Not a WSAError code: %d\n", status); + nterr = STATUS_UNSUCCESSFUL; + } + return nterr; +} + +static int (WINAPI *pWSARecv)(SOCKET,LPWSABUF,DWORD,LPDWORD,LPDWORD,LPWSAOVERLAPPED,LPWSAOVERLAPPED_COMPLETION_ROUTINE); +static int (WINAPI *pWSASend)(SOCKET,LPWSABUF,DWORD,LPDWORD,DWORD,LPWSAOVERLAPPED,LPWSAOVERLAPPED_COMPLETION_ROUTINE); +static int (WINAPI *pWSAGetLastError)(VOID); + +/* + * Load the ws2_32 library and allocate the function pointers required + * for reading and writing to sockets + */ +static inline int LoadWSA(void) +{ + WCHAR wsalibW[] = {'w','s','2','_','3','2','.','d','l','l',0 }; + CHAR cWSAGetLastError[] = "WSAGetLastError"; + static HMODULE hModule = 0; + CHAR cWSARecv[] = "WSARecv"; + CHAR cWSASend[] = "WSASend"; + UNICODE_STRING wstr; + ANSI_STRING str; + + if (hModule) + return TRUE; + RtlInitUnicodeString( &wstr, wsalibW ); + if (LdrLoadDll( NULL, 0, &wstr, &hModule ) != STATUS_SUCCESS) + return FALSE; + RtlInitAnsiString( &str, (LPCSTR) &cWSAGetLastError ); + if (LdrGetProcedureAddress( hModule, &str, 0, (void**)&pWSAGetLastError ) != STATUS_SUCCESS) + goto failed; + RtlInitAnsiString( &str, (LPCSTR) &cWSARecv ); + if (LdrGetProcedureAddress( hModule, &str, 0, (void**)&pWSARecv ) != STATUS_SUCCESS) + goto failed; + RtlInitAnsiString( &str, (LPCSTR) &cWSASend ); + if (LdrGetProcedureAddress( hModule, &str, 0, (void**)&pWSASend ) != STATUS_SUCCESS) + goto failed; + return TRUE; + +failed: + LdrUnloadDll( hModule ); + hModule = 0; + return FALSE; +} /************************************************************************** * FILE_CreateFile (internal) @@ -621,6 +703,35 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent, status = total ? STATUS_SUCCESS : STATUS_END_OF_FILE; goto done; } + else if (type == FD_TYPE_SOCKET && LoadWSA()) + { + /* Process ReadFile requests on sockets through ws2_32.dll */ + WSAOVERLAPPED *lpOverlapped = (WSAOVERLAPPED *) io_status; + DWORD bytes_recvd = 0, flags = 0; + WSABUF wsabuf[1]; + + wsabuf[0].len = length; + wsabuf[0].buf = buffer; + if (hEvent != NULL) + { + lpOverlapped->hEvent = hEvent; + if (offset) + { + lpOverlapped->u.s.Offset = offset->u.LowPart; + lpOverlapped->u.s.OffsetHigh = offset->u.HighPart; + } + } + result = pWSARecv( (SOCKET) hFile, &wsabuf[0], 1, &bytes_recvd, &flags, + (hEvent == NULL ? NULL : lpOverlapped), NULL); + if (result == 0) + status = STATUS_SUCCESS; + else + status = WSAErrorToNtStatus(pWSAGetLastError()); + + total = bytes_recvd; + cvalue = 0; /* Completion handled by WSARecv() */ + goto done; /* Make sure NtQueueApcThread is called */ + } for (;;) { @@ -758,7 +869,6 @@ err: return status; } - /****************************************************************************** * NtReadFileScatter [NTDLL.@] * ZwReadFileScatter [NTDLL.@] @@ -970,6 +1080,35 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent, status = STATUS_SUCCESS; goto done; } + else if (type == FD_TYPE_SOCKET && LoadWSA()) + { + /* Process WriteFile requests on sockets through ws2_32.dll */ + WSAOVERLAPPED *lpOverlapped = (WSAOVERLAPPED *) io_status; + DWORD bytes_sent = 0; + WSABUF wsabuf[1]; + + wsabuf[0].len = length; + wsabuf[0].buf = (void*) buffer; + if (hEvent != NULL) + { + lpOverlapped->hEvent = hEvent; + if (offset) + { + lpOverlapped->u.s.Offset = offset->u.LowPart; + lpOverlapped->u.s.OffsetHigh = offset->u.HighPart; + } + } + result = pWSASend( (SOCKET) hFile, &wsabuf[0], 1, &bytes_sent, 0, + (hEvent == NULL ? NULL : lpOverlapped), NULL ); + if (result == 0) + status = STATUS_SUCCESS; + else + status = WSAErrorToNtStatus(pWSAGetLastError()); + + total = bytes_sent; + cvalue = 0; /* Completion handled by WSASend() */ + goto done; /* Make sure NtQueueApcThread is called */ + } for (;;) { -- 1.7.1