Author: phater
Date: Thu Oct 13 20:30:42 2016
New Revision: 72966
URL:
http://svn.reactos.org/svn/reactos?rev=72966&view=rev
Log:
[MSAFD] Implement WSPGetOverlappedResult. Reviewed by Thomas and Art. Thanks! CORE-12134
#resolve
Modified:
trunk/reactos/dll/win32/msafd/misc/sndrcv.c
trunk/reactos/dll/win32/msafd/misc/stubs.c
trunk/reactos/dll/win32/msafd/msafd.h
Modified: trunk/reactos/dll/win32/msafd/misc/sndrcv.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msafd/misc/sndrc…
==============================================================================
--- trunk/reactos/dll/win32/msafd/misc/sndrcv.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msafd/misc/sndrcv.c [iso-8859-1] Thu Oct 13 20:30:42 2016
@@ -93,6 +93,92 @@
return ERROR_SUCCESS;
}
+
+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 FALSE;
+ }
+ if (!lpOverlapped || !lpdwBytes || !lpdwFlags)
+ {
+ if (lpErrno)
+ *lpErrno = WSAEFAULT;
+ return FALSE;
+ }
+ IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal;
+ if (!IOSB)
+ {
+ if (lpErrno)
+ *lpErrno = WSAEFAULT;
+ return FALSE;
+ }
+ 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
@@ -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,8 +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));
+ if (!APCContext)
+ {
+ ERR("Not enough memory for APC Context\n");
+ return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0,
lpNumberOfBytesRead);
+ }
+ ((PAFDAPCCONTEXT)APCContext)->lpCompletionRoutine = lpCompletionRoutine;
+ ((PAFDAPCCONTEXT)APCContext)->lpOverlapped = lpOverlapped;
+ ((PAFDAPCCONTEXT)APCContext)->lpSocket = Socket;
RecvInfo.AfdFlags |= AFD_SKIP_FIO;
}
@@ -196,15 +296,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)
@@ -219,6 +319,12 @@
NtClose( SockEvent );
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;
@@ -244,6 +350,12 @@
else
{
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 +467,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,8 +483,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));
+ if (!APCContext)
+ {
+ ERR("Not enough memory for APC Context\n");
+ return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0,
lpNumberOfBytesRead);
+ }
+ ((PAFDAPCCONTEXT)APCContext)->lpCompletionRoutine = lpCompletionRoutine;
+ ((PAFDAPCCONTEXT)APCContext)->lpOverlapped = lpOverlapped;
+ ((PAFDAPCCONTEXT)APCContext)->lpSocket = Socket;
RecvInfo.AfdFlags |= AFD_SKIP_FIO;
}
@@ -397,12 +523,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;
@@ -420,6 +553,12 @@
else
{
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 +633,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,8 +649,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));
+ if (!APCContext)
+ {
+ ERR("Not enough memory for APC Context\n");
+ return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0,
lpNumberOfBytesSent);
+ }
+ ((PAFDAPCCONTEXT)APCContext)->lpCompletionRoutine = lpCompletionRoutine;
+ ((PAFDAPCCONTEXT)APCContext)->lpOverlapped = lpOverlapped;
+ ((PAFDAPCCONTEXT)APCContext)->lpSocket = Socket;
SendInfo.AfdFlags |= AFD_SKIP_FIO;
}
@@ -546,6 +699,12 @@
SockReenableAsyncSelectEvent(Socket, FD_WRITE);
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 +825,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,9 +841,16 @@
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));
+ if (!APCContext)
+ {
+ ERR("Not enough memory for APC Context\n");
+ return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0,
lpNumberOfBytesSent);
+ }
+ ((PAFDAPCCONTEXT)APCContext)->lpCompletionRoutine = lpCompletionRoutine;
+ ((PAFDAPCCONTEXT)APCContext)->lpOverlapped = lpOverlapped;
+ ((PAFDAPCCONTEXT)APCContext)->lpSocket = Socket;
SendInfo.AfdFlags |= AFD_SKIP_FIO;
}
@@ -713,7 +885,19 @@
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);
}
Modified: trunk/reactos/dll/win32/msafd/misc/stubs.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msafd/misc/stubs…
==============================================================================
--- trunk/reactos/dll/win32/msafd/misc/stubs.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msafd/misc/stubs.c [iso-8859-1] Thu Oct 13 20:30:42 2016
@@ -21,22 +21,6 @@
UNIMPLEMENTED;
return 0;
-}
-
-
-BOOL
-WSPAPI
-WSPGetOverlappedResult(
- IN SOCKET s,
- IN LPWSAOVERLAPPED lpOverlapped,
- OUT LPDWORD lpcbTransfer,
- IN BOOL fWait,
- OUT LPDWORD lpdwFlags,
- OUT LPINT lpErrno)
-{
- UNIMPLEMENTED;
-
- return FALSE;
}
Modified: trunk/reactos/dll/win32/msafd/msafd.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msafd/msafd.h?re…
==============================================================================
--- trunk/reactos/dll/win32/msafd/msafd.h [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msafd/msafd.h [iso-8859-1] Thu Oct 13 20:30:42 2016
@@ -27,6 +27,7 @@
#include <wsahelp.h>
#include <tdi.h>
#include <afd/shared.h>
+#include <mswsock.h>
#include "include/helpers.h"
extern HANDLE GlobalHeap;
@@ -127,6 +128,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(