Index: dll/win32/msafd/misc/sndrcv.c =================================================================== --- dll/win32/msafd/misc/sndrcv.c (revision 72953) +++ dll/win32/msafd/misc/sndrcv.c (working copy) @@ -94,6 +94,92 @@ } +BOOL +WSPAPI +WSPGetOverlappedResult( + IN SOCKET Handle, + IN LPWSAOVERLAPPED lpOverlapped, + OUT LPDWORD lpdwBytes, + IN BOOL fWait, + OUT LPDWORD lpdwFlags, + OUT LPINT lpErrno) +{ + PIO_STATUS_BLOCK IOSB; + NTSTATUS Status; + PSOCKET_INFORMATION Socket; + + TRACE("Called (%x)\n", Handle); + + /* Get the Socket Structure associate to this Socket*/ + Socket = GetSocketStructure(Handle); + if (!Socket) + { + if(lpErrno) + *lpErrno = WSAENOTSOCK; + return SOCKET_ERROR; + } + if (!lpOverlapped || !lpdwBytes || !lpdwFlags) + { + if (lpErrno) + *lpErrno = WSAEFAULT; + return SOCKET_ERROR; + } + IOSB = (PIO_STATUS_BLOCK)lpOverlapped->Internal; + if (!IOSB) + { + if (lpErrno) + *lpErrno = WSAEFAULT; + return SOCKET_ERROR; + } + Status = IOSB->Status; + + /* Wait for completition of overlapped */ + if (Status == STATUS_PENDING) + { + /* It's up to the protocol to time out recv. We must wait + * until the protocol decides it's had enough. + */ + if (fWait) + { + WaitForSingleObject(lpOverlapped->hEvent, INFINITE); + Status = IOSB->Status; + } + } + + TRACE("Status %x Information %d\n", Status, IOSB->Information); + + if (Status != STATUS_PENDING) + { + *lpdwFlags = 0; + + *lpdwBytes = IOSB->Information; + + /* Re-enable Async Event */ + SockReenableAsyncSelectEvent(Socket, FD_OOB); + SockReenableAsyncSelectEvent(Socket, FD_WRITE); + SockReenableAsyncSelectEvent(Socket, FD_READ); + } + + return Status == STATUS_SUCCESS; +} + +VOID +NTAPI +AfdAPC(PVOID ApcContext, + PIO_STATUS_BLOCK IoStatusBlock, + ULONG Reserved) +{ + PAFDAPCCONTEXT Context = ApcContext; + + /* Re-enable Async Event */ + SockReenableAsyncSelectEvent(Context->lpSocket, FD_OOB); + SockReenableAsyncSelectEvent(Context->lpSocket, FD_READ); + SockReenableAsyncSelectEvent(Context->lpSocket, FD_WRITE); + + Context->lpCompletionRoutine(IoStatusBlock->Status, IoStatusBlock->Information, Context->lpOverlapped, 0); + HeapFree(GlobalHeap, 0, ApcContext); +} + int WSPAPI WSPRecv(SOCKET Handle, @@ -111,7 +197,7 @@ AFD_RECV_INFO RecvInfo; NTSTATUS Status; PVOID APCContext; - PVOID APCFunction; + PIO_APC_ROUTINE APCFunction; HANDLE Event = NULL; HANDLE SockEvent; PSOCKET_INFORMATION Socket; @@ -173,6 +259,12 @@ } else { + /* Overlapped request for non overlapped opened socket */ + if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0) + { + TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n"); + return MsafdReturnWithErrno(0, lpErrno, 0, lpNumberOfBytesRead); + } if (lpCompletionRoutine == NULL) { /* Using Overlapped Structure, but no Completition Routine, so no need for APC */ @@ -183,12 +275,16 @@ else { /* Using Overlapped Structure and a Completition Routine, so use an APC */ - APCFunction = NULL; // should be a private io completition function inside us - APCContext = lpCompletionRoutine; + APCFunction = &AfdAPC; // should be a private io completition function inside us + APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDAPCCONTEXT)); + ((PAFDAPCCONTEXT)APCContext)->lpCompletionRoutine = lpCompletionRoutine; + ((PAFDAPCCONTEXT)APCContext)->lpOverlapped = lpOverlapped; + ((PAFDAPCCONTEXT)APCContext)->lpSocket = Socket; RecvInfo.AfdFlags |= AFD_SKIP_FIO; } - IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal; + lpOverlapped->Internal = (ULONG_PTR)&Socket->SharedData->IOSB; + IOSB = (PIO_STATUS_BLOCK)lpOverlapped->Internal; RecvInfo.AfdFlags |= AFD_OVERLAPPED; } @@ -196,15 +292,15 @@ /* Send IOCTL */ Status = NtDeviceIoControlFile((HANDLE)Handle, - Event, - APCFunction, - APCContext, - IOSB, - IOCTL_AFD_RECV, - &RecvInfo, - sizeof(RecvInfo), - NULL, - 0); + Event, + APCFunction, + APCContext, + IOSB, + IOCTL_AFD_RECV, + &RecvInfo, + sizeof(RecvInfo), + NULL, + 0); /* Wait for completition of not overlapped */ if (Status == STATUS_PENDING && lpOverlapped == NULL) @@ -220,6 +316,12 @@ TRACE("Status %x Information %d\n", Status, IOSB->Information); + if (Status == STATUS_PENDING) + { + TRACE("Leaving (Pending)\n"); + return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesRead); + } + /* Return the Flags */ *ReceiveFlags = 0; @@ -246,6 +348,12 @@ SockReenableAsyncSelectEvent(Socket, FD_READ); } + if (Status == STATUS_SUCCESS && lpOverlapped && lpCompletionRoutine) + { + lpCompletionRoutine(Status, IOSB->Information, lpOverlapped, *ReceiveFlags); + HeapFree(GlobalHeap, 0, (PVOID)APCContext); + } + return MsafdReturnWithErrno ( Status, lpErrno, IOSB->Information, lpNumberOfBytesRead ); } @@ -355,6 +463,12 @@ } else { + /* Overlapped request for non overlapped opened socket */ + if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0) + { + TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n"); + return MsafdReturnWithErrno(0, lpErrno, 0, lpNumberOfBytesRead); + } if (lpCompletionRoutine == NULL) { /* Using Overlapped Structure, but no Completition Routine, so no need for APC */ @@ -365,12 +479,15 @@ else { /* Using Overlapped Structure and a Completition Routine, so use an APC */ - APCFunction = NULL; // should be a private io completition function inside us - APCContext = lpCompletionRoutine; + APCFunction = &AfdAPC; // should be a private io completition function inside us + APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDAPCCONTEXT)); + ((PAFDAPCCONTEXT)APCContext)->lpCompletionRoutine = lpCompletionRoutine; + ((PAFDAPCCONTEXT)APCContext)->lpOverlapped = lpOverlapped; RecvInfo.AfdFlags |= AFD_SKIP_FIO; } - IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal; + lpOverlapped->Internal = (ULONG_PTR)&Socket->SharedData->IOSB; + IOSB = (PIO_STATUS_BLOCK)lpOverlapped->Internal; RecvInfo.AfdFlags |= AFD_OVERLAPPED; } @@ -397,12 +514,19 @@ NtClose( SockEvent ); + if (Status == STATUS_PENDING) + { + TRACE("Leaving (Pending)\n"); + return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesRead); + } + /* Return the Flags */ *ReceiveFlags = 0; switch (Status) { - case STATUS_RECEIVE_EXPEDITED: *ReceiveFlags = MSG_OOB; + case STATUS_RECEIVE_EXPEDITED: + *ReceiveFlags = MSG_OOB; break; case STATUS_RECEIVE_PARTIAL_EXPEDITED: *ReceiveFlags = MSG_PARTIAL | MSG_OOB; @@ -422,6 +546,12 @@ SockReenableAsyncSelectEvent(Socket, FD_READ); } + if (Status == STATUS_SUCCESS && lpOverlapped && lpCompletionRoutine) + { + lpCompletionRoutine(Status, IOSB->Information, lpOverlapped, *ReceiveFlags); + HeapFree(GlobalHeap, 0, (PVOID)APCContext); + } + return MsafdReturnWithErrno ( Status, lpErrno, IOSB->Information, lpNumberOfBytesRead ); } @@ -494,6 +624,12 @@ } else { + /* Overlapped request for non overlapped opened socket */ + if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0) + { + TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n"); + return MsafdReturnWithErrno(0, lpErrno, 0, lpNumberOfBytesSent); + } if (lpCompletionRoutine == NULL) { /* Using Overlapped Structure, but no Completition Routine, so no need for APC */ @@ -504,12 +640,15 @@ else { /* Using Overlapped Structure and a Completition Routine, so use an APC */ - APCFunction = NULL; // should be a private io completition function inside us - APCContext = lpCompletionRoutine; + APCFunction = &AfdAPC; // should be a private io completition function inside us + APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDAPCCONTEXT)); + ((PAFDAPCCONTEXT)APCContext)->lpCompletionRoutine = lpCompletionRoutine; + ((PAFDAPCCONTEXT)APCContext)->lpOverlapped = lpOverlapped; SendInfo.AfdFlags |= AFD_SKIP_FIO; } - IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal; + lpOverlapped->Internal = (ULONG_PTR)&Socket->SharedData->IOSB; + IOSB = (PIO_STATUS_BLOCK)lpOverlapped->Internal; SendInfo.AfdFlags |= AFD_OVERLAPPED; } @@ -547,6 +686,12 @@ TRACE("Leaving (Success, %d)\n", IOSB->Information); + if (Status == STATUS_SUCCESS && lpOverlapped && lpCompletionRoutine) + { + lpCompletionRoutine(Status, IOSB->Information, lpOverlapped, 0); + HeapFree(GlobalHeap, 0, (PVOID)APCContext); + } + return MsafdReturnWithErrno( Status, lpErrno, IOSB->Information, lpNumberOfBytesSent ); } @@ -666,6 +811,12 @@ } else { + /* Overlapped request for non overlapped opened socket */ + if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0) + { + TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n"); + return MsafdReturnWithErrno(0, lpErrno, 0, lpNumberOfBytesSent); + } if (lpCompletionRoutine == NULL) { /* Using Overlapped Structure, but no Completition Routine, so no need for APC */ @@ -676,13 +827,15 @@ else { /* Using Overlapped Structure and a Completition Routine, so use an APC */ - /* Should be a private io completition function inside us */ - APCFunction = NULL; - APCContext = lpCompletionRoutine; + APCFunction = &AfdAPC; // should be a private io completition function inside us + APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDAPCCONTEXT)); + ((PAFDAPCCONTEXT)APCContext)->lpCompletionRoutine = lpCompletionRoutine; + ((PAFDAPCCONTEXT)APCContext)->lpOverlapped = lpOverlapped; SendInfo.AfdFlags |= AFD_SKIP_FIO; } - IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal; + lpOverlapped->Internal = (ULONG_PTR)&Socket->SharedData->IOSB; + IOSB = (PIO_STATUS_BLOCK)lpOverlapped->Internal; SendInfo.AfdFlags |= AFD_OVERLAPPED; } @@ -713,8 +866,20 @@ HeapFree(GlobalHeap, 0, BindAddress); } + if (Status == STATUS_PENDING) + { + TRACE("Leaving (Pending)\n"); + return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesSent); + } + SockReenableAsyncSelectEvent(Socket, FD_WRITE); + if (Status == STATUS_SUCCESS && lpOverlapped && lpCompletionRoutine) + { + lpCompletionRoutine(Status, IOSB->Information, lpOverlapped, 0); + HeapFree(GlobalHeap, 0, (PVOID)APCContext); + } + return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesSent); } Index: dll/win32/msafd/misc/stubs.c =================================================================== --- dll/win32/msafd/misc/stubs.c (revision 72953) +++ dll/win32/msafd/misc/stubs.c (working copy) @@ -26,22 +26,6 @@ BOOL WSPAPI -WSPGetOverlappedResult( - IN SOCKET s, - IN LPWSAOVERLAPPED lpOverlapped, - OUT LPDWORD lpcbTransfer, - IN BOOL fWait, - OUT LPDWORD lpdwFlags, - OUT LPINT lpErrno) -{ - UNIMPLEMENTED; - - return FALSE; -} - - -BOOL -WSPAPI WSPGetQOSByName( IN SOCKET s, IN OUT LPWSABUF lpQOSName, Index: dll/win32/msafd/msafd.h =================================================================== --- dll/win32/msafd/msafd.h (revision 72953) +++ dll/win32/msafd/msafd.h (working copy) @@ -27,6 +27,7 @@ #include #include #include +#include #include "include/helpers.h" extern HANDLE GlobalHeap; @@ -87,6 +88,7 @@ LONG AsyncDisabledEvents; SOCKADDR WSLocalAddress; SOCKADDR WSRemoteAddress; + IO_STATUS_BLOCK IOSB; } SOCK_SHARED_INFO, *PSOCK_SHARED_INFO; typedef struct _SOCKET_INFORMATION { @@ -127,6 +129,13 @@ AFD_POLL_INFO AsyncSelectInfo; } ASYNC_DATA, *PASYNC_DATA; +typedef struct _AFDAPCCONTEXT +{ + LPWSAOVERLAPPED lpOverlapped; + LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine; + PSOCKET_INFORMATION lpSocket; +} AFDAPCCONTEXT, *PAFDAPCCONTEXT; + SOCKET WSPAPI WSPAccept( @@ -493,7 +502,7 @@ if (ReturnedBytes) *ReturnedBytes = (*Errno == 0) ? Received : 0; - return (*Errno == 0) ? 0 : SOCKET_ERROR; + return (*Errno == NO_ERROR) ? 0 : SOCKET_ERROR; } else {