[MSAFD] Implement WSPGetOverlappedResult. Reviewed by Thomas and Art. Thanks! CORE-12134 #resolve

svn path=/trunk/; revision=72966
This commit is contained in:
Peter Hater 2016-10-13 20:30:42 +00:00
parent 24100643a9
commit a82f4b1f38
3 changed files with 212 additions and 36 deletions

View file

@ -94,6 +94,92 @@ WSPAsyncSelect(IN SOCKET Handle,
} }
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 int
WSPAPI WSPAPI
WSPRecv(SOCKET Handle, WSPRecv(SOCKET Handle,
@ -111,7 +197,7 @@ WSPRecv(SOCKET Handle,
AFD_RECV_INFO RecvInfo; AFD_RECV_INFO RecvInfo;
NTSTATUS Status; NTSTATUS Status;
PVOID APCContext; PVOID APCContext;
PVOID APCFunction; PIO_APC_ROUTINE APCFunction;
HANDLE Event = NULL; HANDLE Event = NULL;
HANDLE SockEvent; HANDLE SockEvent;
PSOCKET_INFORMATION Socket; PSOCKET_INFORMATION Socket;
@ -173,6 +259,12 @@ WSPRecv(SOCKET Handle,
} }
else 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) if (lpCompletionRoutine == NULL)
{ {
/* Using Overlapped Structure, but no Completition Routine, so no need for APC */ /* Using Overlapped Structure, but no Completition Routine, so no need for APC */
@ -183,8 +275,16 @@ WSPRecv(SOCKET Handle,
else else
{ {
/* Using Overlapped Structure and a Completition Routine, so use an APC */ /* Using Overlapped Structure and a Completition Routine, so use an APC */
APCFunction = NULL; // should be a private io completition function inside us APCFunction = &AfdAPC; // should be a private io completition function inside us
APCContext = lpCompletionRoutine; 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; RecvInfo.AfdFlags |= AFD_SKIP_FIO;
} }
@ -196,15 +296,15 @@ WSPRecv(SOCKET Handle,
/* Send IOCTL */ /* Send IOCTL */
Status = NtDeviceIoControlFile((HANDLE)Handle, Status = NtDeviceIoControlFile((HANDLE)Handle,
Event, Event,
APCFunction, APCFunction,
APCContext, APCContext,
IOSB, IOSB,
IOCTL_AFD_RECV, IOCTL_AFD_RECV,
&RecvInfo, &RecvInfo,
sizeof(RecvInfo), sizeof(RecvInfo),
NULL, NULL,
0); 0);
/* Wait for completition of not overlapped */ /* Wait for completition of not overlapped */
if (Status == STATUS_PENDING && lpOverlapped == NULL) if (Status == STATUS_PENDING && lpOverlapped == NULL)
@ -220,6 +320,12 @@ WSPRecv(SOCKET Handle,
TRACE("Status %x Information %d\n", Status, IOSB->Information); 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 */ /* Return the Flags */
*ReceiveFlags = 0; *ReceiveFlags = 0;
@ -246,6 +352,12 @@ WSPRecv(SOCKET Handle,
SockReenableAsyncSelectEvent(Socket, FD_READ); 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 ); return MsafdReturnWithErrno ( Status, lpErrno, IOSB->Information, lpNumberOfBytesRead );
} }
@ -355,6 +467,12 @@ WSPRecvFrom(SOCKET Handle,
} }
else 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) if (lpCompletionRoutine == NULL)
{ {
/* Using Overlapped Structure, but no Completition Routine, so no need for APC */ /* Using Overlapped Structure, but no Completition Routine, so no need for APC */
@ -365,8 +483,16 @@ WSPRecvFrom(SOCKET Handle,
else else
{ {
/* Using Overlapped Structure and a Completition Routine, so use an APC */ /* Using Overlapped Structure and a Completition Routine, so use an APC */
APCFunction = NULL; // should be a private io completition function inside us APCFunction = &AfdAPC; // should be a private io completition function inside us
APCContext = lpCompletionRoutine; 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; RecvInfo.AfdFlags |= AFD_SKIP_FIO;
} }
@ -397,12 +523,19 @@ WSPRecvFrom(SOCKET Handle,
NtClose( SockEvent ); NtClose( SockEvent );
if (Status == STATUS_PENDING)
{
TRACE("Leaving (Pending)\n");
return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesRead);
}
/* Return the Flags */ /* Return the Flags */
*ReceiveFlags = 0; *ReceiveFlags = 0;
switch (Status) switch (Status)
{ {
case STATUS_RECEIVE_EXPEDITED: *ReceiveFlags = MSG_OOB; case STATUS_RECEIVE_EXPEDITED:
*ReceiveFlags = MSG_OOB;
break; break;
case STATUS_RECEIVE_PARTIAL_EXPEDITED: case STATUS_RECEIVE_PARTIAL_EXPEDITED:
*ReceiveFlags = MSG_PARTIAL | MSG_OOB; *ReceiveFlags = MSG_PARTIAL | MSG_OOB;
@ -422,6 +555,12 @@ WSPRecvFrom(SOCKET Handle,
SockReenableAsyncSelectEvent(Socket, FD_READ); 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 ); return MsafdReturnWithErrno ( Status, lpErrno, IOSB->Information, lpNumberOfBytesRead );
} }
@ -494,6 +633,12 @@ WSPSend(SOCKET Handle,
} }
else 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) if (lpCompletionRoutine == NULL)
{ {
/* Using Overlapped Structure, but no Completition Routine, so no need for APC */ /* Using Overlapped Structure, but no Completition Routine, so no need for APC */
@ -504,8 +649,16 @@ WSPSend(SOCKET Handle,
else else
{ {
/* Using Overlapped Structure and a Completition Routine, so use an APC */ /* Using Overlapped Structure and a Completition Routine, so use an APC */
APCFunction = NULL; // should be a private io completition function inside us APCFunction = &AfdAPC; // should be a private io completition function inside us
APCContext = lpCompletionRoutine; 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; SendInfo.AfdFlags |= AFD_SKIP_FIO;
} }
@ -547,6 +700,12 @@ WSPSend(SOCKET Handle,
TRACE("Leaving (Success, %d)\n", IOSB->Information); 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 ); return MsafdReturnWithErrno( Status, lpErrno, IOSB->Information, lpNumberOfBytesSent );
} }
@ -666,6 +825,12 @@ WSPSendTo(SOCKET Handle,
} }
else 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) if (lpCompletionRoutine == NULL)
{ {
/* Using Overlapped Structure, but no Completition Routine, so no need for APC */ /* Using Overlapped Structure, but no Completition Routine, so no need for APC */
@ -676,9 +841,16 @@ WSPSendTo(SOCKET Handle,
else else
{ {
/* Using Overlapped Structure and a Completition Routine, so use an APC */ /* Using Overlapped Structure and a Completition Routine, so use an APC */
/* Should be a private io completition function inside us */ APCFunction = &AfdAPC; // should be a private io completition function inside us
APCFunction = NULL; APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDAPCCONTEXT));
APCContext = lpCompletionRoutine; 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; SendInfo.AfdFlags |= AFD_SKIP_FIO;
} }
@ -713,8 +885,20 @@ WSPSendTo(SOCKET Handle,
HeapFree(GlobalHeap, 0, BindAddress); HeapFree(GlobalHeap, 0, BindAddress);
} }
if (Status == STATUS_PENDING)
{
TRACE("Leaving (Pending)\n");
return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesSent);
}
SockReenableAsyncSelectEvent(Socket, FD_WRITE); 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); return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesSent);
} }

View file

@ -24,22 +24,6 @@ WSPCancelBlockingCall(
} }
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 BOOL
WSPAPI WSPAPI
WSPGetQOSByName( WSPGetQOSByName(

View file

@ -27,6 +27,7 @@
#include <wsahelp.h> #include <wsahelp.h>
#include <tdi.h> #include <tdi.h>
#include <afd/shared.h> #include <afd/shared.h>
#include <mswsock.h>
#include "include/helpers.h" #include "include/helpers.h"
extern HANDLE GlobalHeap; extern HANDLE GlobalHeap;
@ -127,6 +128,13 @@ typedef struct _ASYNC_DATA {
AFD_POLL_INFO AsyncSelectInfo; AFD_POLL_INFO AsyncSelectInfo;
} ASYNC_DATA, *PASYNC_DATA; } ASYNC_DATA, *PASYNC_DATA;
typedef struct _AFDAPCCONTEXT
{
LPWSAOVERLAPPED lpOverlapped;
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine;
PSOCKET_INFORMATION lpSocket;
} AFDAPCCONTEXT, *PAFDAPCCONTEXT;
SOCKET SOCKET
WSPAPI WSPAPI
WSPAccept( WSPAccept(