mirror of
https://github.com/reactos/reactos.git
synced 2025-08-04 09:16:17 +00:00
[MSAFD] Implement WSPIoctl overlapped. CORE-12162 #resolve
svn path=/trunk/; revision=73030
This commit is contained in:
parent
04442ae74c
commit
ca5719a178
4 changed files with 261 additions and 122 deletions
|
@ -352,7 +352,13 @@ WSPSocket(int AddressFamily,
|
||||||
/* Save Group Info */
|
/* Save Group Info */
|
||||||
if (g != 0)
|
if (g != 0)
|
||||||
{
|
{
|
||||||
GetSocketInformation(Socket, AFD_INFO_GROUP_ID_TYPE, NULL, NULL, &GroupData);
|
GetSocketInformation(Socket,
|
||||||
|
AFD_INFO_GROUP_ID_TYPE,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
&GroupData,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
Socket->SharedData->GroupID = GroupData.u.LowPart;
|
Socket->SharedData->GroupID = GroupData.u.LowPart;
|
||||||
Socket->SharedData->GroupType = GroupData.u.HighPart;
|
Socket->SharedData->GroupType = GroupData.u.HighPart;
|
||||||
}
|
}
|
||||||
|
@ -362,12 +368,16 @@ WSPSocket(int AddressFamily,
|
||||||
AFD_INFO_SEND_WINDOW_SIZE,
|
AFD_INFO_SEND_WINDOW_SIZE,
|
||||||
NULL,
|
NULL,
|
||||||
&Socket->SharedData->SizeOfSendBuffer,
|
&Socket->SharedData->SizeOfSendBuffer,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
GetSocketInformation (Socket,
|
GetSocketInformation (Socket,
|
||||||
AFD_INFO_RECEIVE_WINDOW_SIZE,
|
AFD_INFO_RECEIVE_WINDOW_SIZE,
|
||||||
NULL,
|
NULL,
|
||||||
&Socket->SharedData->SizeOfRecvBuffer,
|
&Socket->SharedData->SizeOfRecvBuffer,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
NULL);
|
NULL);
|
||||||
ok:
|
ok:
|
||||||
|
|
||||||
|
@ -614,7 +624,7 @@ WSPCloseSocket(IN SOCKET Handle,
|
||||||
if (!Socket)
|
if (!Socket)
|
||||||
{
|
{
|
||||||
NtClose(SockEvent);
|
NtClose(SockEvent);
|
||||||
*lpErrno = WSAENOTSOCK;
|
if (lpErrno) *lpErrno = WSAENOTSOCK;
|
||||||
return SOCKET_ERROR;
|
return SOCKET_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -640,7 +650,7 @@ WSPCloseSocket(IN SOCKET Handle,
|
||||||
{
|
{
|
||||||
WARN("Socket is closing.\n");
|
WARN("Socket is closing.\n");
|
||||||
NtClose(SockEvent);
|
NtClose(SockEvent);
|
||||||
*lpErrno = WSAENOTSOCK;
|
if (lpErrno) *lpErrno = WSAENOTSOCK;
|
||||||
return SOCKET_ERROR;
|
return SOCKET_ERROR;
|
||||||
}
|
}
|
||||||
/* Set the state to close */
|
/* Set the state to close */
|
||||||
|
@ -671,6 +681,8 @@ WSPCloseSocket(IN SOCKET Handle,
|
||||||
AFD_INFO_SENDS_IN_PROGRESS,
|
AFD_INFO_SENDS_IN_PROGRESS,
|
||||||
NULL,
|
NULL,
|
||||||
&SendsInProgress,
|
&SendsInProgress,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
NULL))
|
NULL))
|
||||||
{
|
{
|
||||||
/* Bail out if anything but NO_ERROR */
|
/* Bail out if anything but NO_ERROR */
|
||||||
|
@ -696,7 +708,7 @@ WSPCloseSocket(IN SOCKET Handle,
|
||||||
WARN("Would block!\n");
|
WARN("Would block!\n");
|
||||||
NtClose(SockEvent);
|
NtClose(SockEvent);
|
||||||
Socket->SharedData->State = OldState;
|
Socket->SharedData->State = OldState;
|
||||||
*lpErrno = WSAEWOULDBLOCK;
|
if (lpErrno) *lpErrno = WSAEWOULDBLOCK;
|
||||||
return SOCKET_ERROR;
|
return SOCKET_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2182,114 +2194,116 @@ WSPIoctl(IN SOCKET Handle,
|
||||||
OUT LPINT lpErrno)
|
OUT LPINT lpErrno)
|
||||||
{
|
{
|
||||||
PSOCKET_INFORMATION Socket = NULL;
|
PSOCKET_INFORMATION Socket = NULL;
|
||||||
BOOLEAN NeedsCompletion;
|
BOOLEAN NeedsCompletion = lpOverlapped != NULL;
|
||||||
BOOLEAN NonBlocking;
|
BOOLEAN NonBlocking;
|
||||||
|
INT Errno = NO_ERROR, Ret = SOCKET_ERROR;
|
||||||
if (!lpcbBytesReturned)
|
DWORD cbRet = 0;
|
||||||
{
|
|
||||||
*lpErrno = WSAEFAULT;
|
|
||||||
return SOCKET_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get the Socket Structure associate to this Socket*/
|
/* Get the Socket Structure associate to this Socket*/
|
||||||
Socket = GetSocketStructure(Handle);
|
Socket = GetSocketStructure(Handle);
|
||||||
if (!Socket)
|
if (!Socket)
|
||||||
{
|
{
|
||||||
|
if(lpErrno)
|
||||||
*lpErrno = WSAENOTSOCK;
|
*lpErrno = WSAENOTSOCK;
|
||||||
return SOCKET_ERROR;
|
return SOCKET_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
*lpcbBytesReturned = 0;
|
if (!lpcbBytesReturned && !lpOverlapped)
|
||||||
|
{
|
||||||
|
if(lpErrno)
|
||||||
|
*lpErrno = WSAEFAULT;
|
||||||
|
return SOCKET_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
switch( dwIoControlCode )
|
switch( dwIoControlCode )
|
||||||
{
|
{
|
||||||
case FIONBIO:
|
case FIONBIO:
|
||||||
if( cbInBuffer < sizeof(INT) || IS_INTRESOURCE(lpvInBuffer) )
|
if( cbInBuffer < sizeof(INT) || IS_INTRESOURCE(lpvInBuffer) )
|
||||||
{
|
{
|
||||||
*lpErrno = WSAEFAULT;
|
Errno = WSAEFAULT;
|
||||||
return SOCKET_ERROR;
|
break;
|
||||||
}
|
}
|
||||||
NonBlocking = *((PULONG)lpvInBuffer) ? TRUE : FALSE;
|
NonBlocking = *((PULONG)lpvInBuffer) ? TRUE : FALSE;
|
||||||
Socket->SharedData->NonBlocking = NonBlocking ? 1 : 0;
|
Socket->SharedData->NonBlocking = NonBlocking ? 1 : 0;
|
||||||
*lpErrno = SetSocketInformation(Socket, AFD_INFO_BLOCKING_MODE, &NonBlocking, NULL, NULL);
|
NeedsCompletion = FALSE;
|
||||||
if (*lpErrno != NO_ERROR)
|
Errno = SetSocketInformation(Socket, AFD_INFO_BLOCKING_MODE, &NonBlocking, NULL, NULL, lpOverlapped, lpCompletionRoutine);
|
||||||
return SOCKET_ERROR;
|
if (Errno == NO_ERROR)
|
||||||
else
|
Ret = NO_ERROR;
|
||||||
return NO_ERROR;
|
break;
|
||||||
case FIONREAD:
|
case FIONREAD:
|
||||||
if (IS_INTRESOURCE(lpvOutBuffer) || cbOutBuffer == 0)
|
if (IS_INTRESOURCE(lpvOutBuffer) || cbOutBuffer == 0)
|
||||||
{
|
{
|
||||||
*lpcbBytesReturned = sizeof(ULONG);
|
cbRet = sizeof(ULONG);
|
||||||
*lpErrno = WSAEFAULT;
|
Errno = WSAEFAULT;
|
||||||
return SOCKET_ERROR;
|
break;
|
||||||
}
|
}
|
||||||
if (cbOutBuffer < sizeof(ULONG))
|
if (cbOutBuffer < sizeof(ULONG))
|
||||||
{
|
{
|
||||||
*lpErrno = WSAEINVAL;
|
Errno = WSAEINVAL;
|
||||||
return SOCKET_ERROR;
|
break;
|
||||||
}
|
}
|
||||||
*lpErrno = GetSocketInformation(Socket, AFD_INFO_RECEIVE_CONTENT_SIZE, NULL, (PULONG)lpvOutBuffer, NULL);
|
NeedsCompletion = FALSE;
|
||||||
if (*lpErrno != NO_ERROR)
|
Errno = GetSocketInformation(Socket, AFD_INFO_RECEIVE_CONTENT_SIZE, NULL, (PULONG)lpvOutBuffer, NULL, lpOverlapped, lpCompletionRoutine);
|
||||||
return SOCKET_ERROR;
|
if (Errno == NO_ERROR)
|
||||||
else
|
|
||||||
{
|
{
|
||||||
*lpcbBytesReturned = sizeof(ULONG);
|
cbRet = sizeof(ULONG);
|
||||||
return NO_ERROR;
|
Ret = NO_ERROR;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
case SIOCATMARK:
|
case SIOCATMARK:
|
||||||
if (IS_INTRESOURCE(lpvOutBuffer) || cbOutBuffer == 0)
|
if (IS_INTRESOURCE(lpvOutBuffer) || cbOutBuffer == 0)
|
||||||
{
|
{
|
||||||
*lpcbBytesReturned = sizeof(BOOL);
|
cbRet = sizeof(BOOL);
|
||||||
*lpErrno = WSAEFAULT;
|
Errno = WSAEFAULT;
|
||||||
return SOCKET_ERROR;
|
break;
|
||||||
}
|
}
|
||||||
if (cbOutBuffer < sizeof(BOOL))
|
if (cbOutBuffer < sizeof(BOOL))
|
||||||
{
|
{
|
||||||
*lpErrno = WSAEINVAL;
|
Errno = WSAEINVAL;
|
||||||
return SOCKET_ERROR;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: Return false for now */
|
/* FIXME: Return false for now */
|
||||||
*(BOOL*)lpvOutBuffer = FALSE;
|
*(BOOL*)lpvOutBuffer = FALSE;
|
||||||
|
|
||||||
*lpcbBytesReturned = sizeof(BOOL);
|
cbRet = sizeof(BOOL);
|
||||||
*lpErrno = NO_ERROR;
|
Errno = NO_ERROR;
|
||||||
return NO_ERROR;
|
Ret = NO_ERROR;
|
||||||
|
break;
|
||||||
case SIO_GET_EXTENSION_FUNCTION_POINTER:
|
case SIO_GET_EXTENSION_FUNCTION_POINTER:
|
||||||
*lpErrno = WSAEINVAL;
|
Errno = WSAEINVAL;
|
||||||
return SOCKET_ERROR;
|
break;
|
||||||
|
|
||||||
case SIO_ADDRESS_LIST_QUERY:
|
case SIO_ADDRESS_LIST_QUERY:
|
||||||
if (IS_INTRESOURCE(lpvOutBuffer) || cbOutBuffer == 0)
|
if (IS_INTRESOURCE(lpvOutBuffer) || cbOutBuffer == 0)
|
||||||
{
|
{
|
||||||
*lpcbBytesReturned = sizeof(SOCKET_ADDRESS_LIST) + sizeof(Socket->SharedData->WSLocalAddress);
|
cbRet = sizeof(SOCKET_ADDRESS_LIST) + sizeof(Socket->SharedData->WSLocalAddress);
|
||||||
*lpErrno = WSAEFAULT;
|
Errno = WSAEFAULT;
|
||||||
return SOCKET_ERROR;
|
break;
|
||||||
}
|
}
|
||||||
if (cbOutBuffer < sizeof(INT))
|
if (cbOutBuffer < sizeof(INT))
|
||||||
{
|
{
|
||||||
*lpErrno = WSAEINVAL;
|
Errno = WSAEINVAL;
|
||||||
return SOCKET_ERROR;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
*lpcbBytesReturned = sizeof(SOCKET_ADDRESS_LIST) + sizeof(Socket->SharedData->WSLocalAddress);
|
cbRet = sizeof(SOCKET_ADDRESS_LIST) + sizeof(Socket->SharedData->WSLocalAddress);
|
||||||
|
|
||||||
((SOCKET_ADDRESS_LIST*)lpvOutBuffer)->iAddressCount = 1;
|
((SOCKET_ADDRESS_LIST*)lpvOutBuffer)->iAddressCount = 1;
|
||||||
|
|
||||||
if (cbOutBuffer < (sizeof(SOCKET_ADDRESS_LIST) + sizeof(Socket->SharedData->WSLocalAddress)))
|
if (cbOutBuffer < (sizeof(SOCKET_ADDRESS_LIST) + sizeof(Socket->SharedData->WSLocalAddress)))
|
||||||
{
|
{
|
||||||
*lpErrno = WSAEFAULT;
|
Errno = WSAEFAULT;
|
||||||
return SOCKET_ERROR;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
((SOCKET_ADDRESS_LIST*)lpvOutBuffer)->Address[0].iSockaddrLength = sizeof(Socket->SharedData->WSLocalAddress);
|
((SOCKET_ADDRESS_LIST*)lpvOutBuffer)->Address[0].iSockaddrLength = sizeof(Socket->SharedData->WSLocalAddress);
|
||||||
((SOCKET_ADDRESS_LIST*)lpvOutBuffer)->Address[0].lpSockaddr = &Socket->SharedData->WSLocalAddress;
|
((SOCKET_ADDRESS_LIST*)lpvOutBuffer)->Address[0].lpSockaddr = &Socket->SharedData->WSLocalAddress;
|
||||||
|
|
||||||
*lpErrno = NO_ERROR;
|
Errno = NO_ERROR;
|
||||||
return NO_ERROR;
|
Ret = NO_ERROR;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
*lpErrno = Socket->HelperData->WSHIoctl(Socket->HelperContext,
|
Errno = Socket->HelperData->WSHIoctl(Socket->HelperContext,
|
||||||
Handle,
|
Handle,
|
||||||
Socket->TdiAddressHandle,
|
Socket->TdiAddressHandle,
|
||||||
Socket->TdiConnectionHandle,
|
Socket->TdiConnectionHandle,
|
||||||
|
@ -2298,16 +2312,36 @@ WSPIoctl(IN SOCKET Handle,
|
||||||
cbInBuffer,
|
cbInBuffer,
|
||||||
lpvOutBuffer,
|
lpvOutBuffer,
|
||||||
cbOutBuffer,
|
cbOutBuffer,
|
||||||
lpcbBytesReturned,
|
&cbRet,
|
||||||
lpOverlapped,
|
lpOverlapped,
|
||||||
lpCompletionRoutine,
|
lpCompletionRoutine,
|
||||||
(LPBOOL)&NeedsCompletion);
|
(LPBOOL)&NeedsCompletion);
|
||||||
|
|
||||||
if (*lpErrno != NO_ERROR)
|
if (Errno == NO_ERROR)
|
||||||
return SOCKET_ERROR;
|
Ret = NO_ERROR;
|
||||||
else
|
break;
|
||||||
|
}
|
||||||
|
if (lpOverlapped && NeedsCompletion)
|
||||||
|
{
|
||||||
|
lpOverlapped->Internal = Errno;
|
||||||
|
lpOverlapped->InternalHigh = cbRet;
|
||||||
|
if (lpCompletionRoutine != NULL)
|
||||||
|
{
|
||||||
|
lpCompletionRoutine(Errno, cbRet, lpOverlapped, 0);
|
||||||
|
}
|
||||||
|
if (lpOverlapped->hEvent)
|
||||||
|
SetEvent(lpOverlapped->hEvent);
|
||||||
|
if (!PostQueuedCompletionStatus((HANDLE)Handle, cbRet, 0, lpOverlapped))
|
||||||
|
{
|
||||||
|
ERR("PostQueuedCompletionStatus failed %d\n", GetLastError());
|
||||||
|
}
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
if (lpErrno)
|
||||||
|
*lpErrno = Errno;
|
||||||
|
if (lpcbBytesReturned)
|
||||||
|
*lpcbBytesReturned = cbRet;
|
||||||
|
return Ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2852,18 +2886,34 @@ WSPCleanup(OUT LPINT lpErrno)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
AfdInfoAPC(PVOID ApcContext,
|
||||||
|
PIO_STATUS_BLOCK IoStatusBlock,
|
||||||
|
ULONG Reserved)
|
||||||
|
{
|
||||||
|
PAFDAPCCONTEXT Context = ApcContext;
|
||||||
|
|
||||||
|
Context->lpCompletionRoutine(IoStatusBlock->Status, IoStatusBlock->Information, Context->lpOverlapped, 0);
|
||||||
|
HeapFree(GlobalHeap, 0, ApcContext);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
GetSocketInformation(PSOCKET_INFORMATION Socket,
|
GetSocketInformation(PSOCKET_INFORMATION Socket,
|
||||||
ULONG AfdInformationClass,
|
ULONG AfdInformationClass,
|
||||||
PBOOLEAN Boolean OPTIONAL,
|
PBOOLEAN Boolean OPTIONAL,
|
||||||
PULONG Ulong OPTIONAL,
|
PULONG Ulong OPTIONAL,
|
||||||
PLARGE_INTEGER LargeInteger OPTIONAL)
|
PLARGE_INTEGER LargeInteger OPTIONAL,
|
||||||
|
LPWSAOVERLAPPED Overlapped OPTIONAL,
|
||||||
|
LPWSAOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine OPTIONAL)
|
||||||
{
|
{
|
||||||
IO_STATUS_BLOCK IOSB;
|
PIO_STATUS_BLOCK IOSB;
|
||||||
|
IO_STATUS_BLOCK DummyIOSB;
|
||||||
AFD_INFO InfoData;
|
AFD_INFO InfoData;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
PVOID APCContext;
|
||||||
|
PIO_APC_ROUTINE APCFunction;
|
||||||
|
HANDLE Event = NULL;
|
||||||
HANDLE SockEvent;
|
HANDLE SockEvent;
|
||||||
|
|
||||||
Status = NtCreateEvent(&SockEvent,
|
Status = NtCreateEvent(&SockEvent,
|
||||||
|
@ -2878,12 +2928,56 @@ GetSocketInformation(PSOCKET_INFORMATION Socket,
|
||||||
/* Set Info Class */
|
/* Set Info Class */
|
||||||
InfoData.InformationClass = AfdInformationClass;
|
InfoData.InformationClass = AfdInformationClass;
|
||||||
|
|
||||||
|
/* Verify if we should use APC */
|
||||||
|
if (Overlapped == NULL)
|
||||||
|
{
|
||||||
|
/* Not using Overlapped structure, so use normal blocking on event */
|
||||||
|
APCContext = NULL;
|
||||||
|
APCFunction = NULL;
|
||||||
|
Event = SockEvent;
|
||||||
|
IOSB = &DummyIOSB;
|
||||||
|
}
|
||||||
|
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 0;
|
||||||
|
}
|
||||||
|
if (CompletionRoutine == NULL)
|
||||||
|
{
|
||||||
|
/* Using Overlapped Structure, but no Completition Routine, so no need for APC */
|
||||||
|
APCContext = Overlapped;
|
||||||
|
APCFunction = NULL;
|
||||||
|
Event = Overlapped->hEvent;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Using Overlapped Structure and a Completition Routine, so use an APC */
|
||||||
|
APCFunction = &AfdInfoAPC; // 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 WSAEFAULT;
|
||||||
|
}
|
||||||
|
((PAFDAPCCONTEXT)APCContext)->lpCompletionRoutine = CompletionRoutine;
|
||||||
|
((PAFDAPCCONTEXT)APCContext)->lpOverlapped = Overlapped;
|
||||||
|
((PAFDAPCCONTEXT)APCContext)->lpSocket = Socket;
|
||||||
|
}
|
||||||
|
|
||||||
|
IOSB = (PIO_STATUS_BLOCK)&Overlapped->Internal;
|
||||||
|
}
|
||||||
|
|
||||||
|
IOSB->Status = STATUS_PENDING;
|
||||||
|
|
||||||
/* Send IOCTL */
|
/* Send IOCTL */
|
||||||
Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
|
Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
|
||||||
SockEvent,
|
Event,
|
||||||
NULL,
|
APCFunction,
|
||||||
NULL,
|
APCContext,
|
||||||
&IOSB,
|
IOSB,
|
||||||
IOCTL_AFD_GET_INFO,
|
IOCTL_AFD_GET_INFO,
|
||||||
&InfoData,
|
&InfoData,
|
||||||
sizeof(InfoData),
|
sizeof(InfoData),
|
||||||
|
@ -2891,10 +2985,18 @@ GetSocketInformation(PSOCKET_INFORMATION Socket,
|
||||||
sizeof(InfoData));
|
sizeof(InfoData));
|
||||||
|
|
||||||
/* Wait for return */
|
/* Wait for return */
|
||||||
if (Status == STATUS_PENDING)
|
if (Status == STATUS_PENDING && Overlapped == NULL)
|
||||||
{
|
{
|
||||||
WaitForSingleObject(SockEvent, INFINITE);
|
WaitForSingleObject(SockEvent, INFINITE);
|
||||||
Status = IOSB.Status;
|
Status = IOSB->Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE("Status %x Information %d\n", Status, IOSB->Information);
|
||||||
|
|
||||||
|
if (Status == STATUS_PENDING)
|
||||||
|
{
|
||||||
|
TRACE("Leaving (Pending)\n");
|
||||||
|
return WSA_IO_PENDING;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Status != STATUS_SUCCESS)
|
if (Status != STATUS_SUCCESS)
|
||||||
|
@ -2926,11 +3028,17 @@ SetSocketInformation(PSOCKET_INFORMATION Socket,
|
||||||
ULONG AfdInformationClass,
|
ULONG AfdInformationClass,
|
||||||
PBOOLEAN Boolean OPTIONAL,
|
PBOOLEAN Boolean OPTIONAL,
|
||||||
PULONG Ulong OPTIONAL,
|
PULONG Ulong OPTIONAL,
|
||||||
PLARGE_INTEGER LargeInteger OPTIONAL)
|
PLARGE_INTEGER LargeInteger OPTIONAL,
|
||||||
|
LPWSAOVERLAPPED Overlapped OPTIONAL,
|
||||||
|
LPWSAOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine OPTIONAL)
|
||||||
{
|
{
|
||||||
IO_STATUS_BLOCK IOSB;
|
PIO_STATUS_BLOCK IOSB;
|
||||||
|
IO_STATUS_BLOCK DummyIOSB;
|
||||||
AFD_INFO InfoData;
|
AFD_INFO InfoData;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
PVOID APCContext;
|
||||||
|
PIO_APC_ROUTINE APCFunction;
|
||||||
|
HANDLE Event = NULL;
|
||||||
HANDLE SockEvent;
|
HANDLE SockEvent;
|
||||||
|
|
||||||
Status = NtCreateEvent(&SockEvent,
|
Status = NtCreateEvent(&SockEvent,
|
||||||
|
@ -2959,12 +3067,56 @@ SetSocketInformation(PSOCKET_INFORMATION Socket,
|
||||||
InfoData.Information.Boolean = *Boolean;
|
InfoData.Information.Boolean = *Boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Verify if we should use APC */
|
||||||
|
if (Overlapped == NULL)
|
||||||
|
{
|
||||||
|
/* Not using Overlapped structure, so use normal blocking on event */
|
||||||
|
APCContext = NULL;
|
||||||
|
APCFunction = NULL;
|
||||||
|
Event = SockEvent;
|
||||||
|
IOSB = &DummyIOSB;
|
||||||
|
}
|
||||||
|
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 0;
|
||||||
|
}
|
||||||
|
if (CompletionRoutine == NULL)
|
||||||
|
{
|
||||||
|
/* Using Overlapped Structure, but no Completition Routine, so no need for APC */
|
||||||
|
APCContext = Overlapped;
|
||||||
|
APCFunction = NULL;
|
||||||
|
Event = Overlapped->hEvent;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Using Overlapped Structure and a Completition Routine, so use an APC */
|
||||||
|
APCFunction = &AfdInfoAPC; // 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 WSAEFAULT;
|
||||||
|
}
|
||||||
|
((PAFDAPCCONTEXT)APCContext)->lpCompletionRoutine = CompletionRoutine;
|
||||||
|
((PAFDAPCCONTEXT)APCContext)->lpOverlapped = Overlapped;
|
||||||
|
((PAFDAPCCONTEXT)APCContext)->lpSocket = Socket;
|
||||||
|
}
|
||||||
|
|
||||||
|
IOSB = (PIO_STATUS_BLOCK)&Overlapped->Internal;
|
||||||
|
}
|
||||||
|
|
||||||
|
IOSB->Status = STATUS_PENDING;
|
||||||
|
|
||||||
/* Send IOCTL */
|
/* Send IOCTL */
|
||||||
Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
|
Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
|
||||||
SockEvent,
|
Event,
|
||||||
NULL,
|
APCFunction,
|
||||||
NULL,
|
APCContext,
|
||||||
&IOSB,
|
IOSB,
|
||||||
IOCTL_AFD_SET_INFO,
|
IOCTL_AFD_SET_INFO,
|
||||||
&InfoData,
|
&InfoData,
|
||||||
sizeof(InfoData),
|
sizeof(InfoData),
|
||||||
|
@ -2972,14 +3124,22 @@ SetSocketInformation(PSOCKET_INFORMATION Socket,
|
||||||
0);
|
0);
|
||||||
|
|
||||||
/* Wait for return */
|
/* Wait for return */
|
||||||
if (Status == STATUS_PENDING)
|
if (Status == STATUS_PENDING && Overlapped == NULL)
|
||||||
{
|
{
|
||||||
WaitForSingleObject(SockEvent, INFINITE);
|
WaitForSingleObject(SockEvent, INFINITE);
|
||||||
Status = IOSB.Status;
|
Status = IOSB->Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
NtClose( SockEvent );
|
NtClose( SockEvent );
|
||||||
|
|
||||||
|
TRACE("Status %x Information %d\n", Status, IOSB->Information);
|
||||||
|
|
||||||
|
if (Status == STATUS_PENDING)
|
||||||
|
{
|
||||||
|
TRACE("Leaving (Pending)\n");
|
||||||
|
return WSA_IO_PENDING;
|
||||||
|
}
|
||||||
|
|
||||||
return Status == STATUS_SUCCESS ? 0 : -1;
|
return Status == STATUS_SUCCESS ? 0 : -1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ WSPEventSelect(
|
||||||
|
|
||||||
/* Set Socket to Non-Blocking */
|
/* Set Socket to Non-Blocking */
|
||||||
BlockMode = TRUE;
|
BlockMode = TRUE;
|
||||||
SetSocketInformation(Socket, AFD_INFO_BLOCKING_MODE, &BlockMode, NULL, NULL);
|
SetSocketInformation(Socket, AFD_INFO_BLOCKING_MODE, &BlockMode, NULL, NULL, NULL, NULL);
|
||||||
Socket->SharedData->NonBlocking = TRUE;
|
Socket->SharedData->NonBlocking = TRUE;
|
||||||
|
|
||||||
/* Deactivate Async Select if there is one */
|
/* Deactivate Async Select if there is one */
|
||||||
|
|
|
@ -45,7 +45,7 @@ WSPAsyncSelect(IN SOCKET Handle,
|
||||||
|
|
||||||
/* Change the Socket to Non Blocking */
|
/* Change the Socket to Non Blocking */
|
||||||
BlockMode = TRUE;
|
BlockMode = TRUE;
|
||||||
SetSocketInformation(Socket, AFD_INFO_BLOCKING_MODE, &BlockMode, NULL, NULL);
|
SetSocketInformation(Socket, AFD_INFO_BLOCKING_MODE, &BlockMode, NULL, NULL, NULL, NULL);
|
||||||
Socket->SharedData->NonBlocking = TRUE;
|
Socket->SharedData->NonBlocking = TRUE;
|
||||||
|
|
||||||
/* Deactive WSPEventSelect */
|
/* Deactive WSPEventSelect */
|
||||||
|
@ -104,9 +104,8 @@ WSPGetOverlappedResult(
|
||||||
OUT LPDWORD lpdwFlags,
|
OUT LPDWORD lpdwFlags,
|
||||||
OUT LPINT lpErrno)
|
OUT LPINT lpErrno)
|
||||||
{
|
{
|
||||||
PIO_STATUS_BLOCK IOSB;
|
|
||||||
NTSTATUS Status;
|
|
||||||
PSOCKET_INFORMATION Socket;
|
PSOCKET_INFORMATION Socket;
|
||||||
|
BOOL Ret;
|
||||||
|
|
||||||
TRACE("Called (%x)\n", Handle);
|
TRACE("Called (%x)\n", Handle);
|
||||||
|
|
||||||
|
@ -124,43 +123,19 @@ WSPGetOverlappedResult(
|
||||||
*lpErrno = WSAEFAULT;
|
*lpErrno = WSAEFAULT;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal;
|
Ret = GetOverlappedResult((HANDLE)Handle, lpOverlapped, lpdwBytes, fWait);
|
||||||
if (!IOSB)
|
|
||||||
{
|
|
||||||
if (lpErrno)
|
|
||||||
*lpErrno = WSAEFAULT;
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
Status = IOSB->Status;
|
|
||||||
|
|
||||||
/* Wait for completition of overlapped */
|
if (Ret)
|
||||||
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;
|
*lpdwFlags = 0;
|
||||||
|
|
||||||
*lpdwBytes = IOSB->Information;
|
|
||||||
|
|
||||||
/* Re-enable Async Event */
|
/* Re-enable Async Event */
|
||||||
SockReenableAsyncSelectEvent(Socket, FD_OOB);
|
SockReenableAsyncSelectEvent(Socket, FD_OOB);
|
||||||
SockReenableAsyncSelectEvent(Socket, FD_WRITE);
|
SockReenableAsyncSelectEvent(Socket, FD_WRITE);
|
||||||
SockReenableAsyncSelectEvent(Socket, FD_READ);
|
SockReenableAsyncSelectEvent(Socket, FD_READ);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Status == STATUS_SUCCESS;
|
return Ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
|
|
@ -434,7 +434,9 @@ int GetSocketInformation(
|
||||||
ULONG AfdInformationClass,
|
ULONG AfdInformationClass,
|
||||||
PBOOLEAN Boolean OPTIONAL,
|
PBOOLEAN Boolean OPTIONAL,
|
||||||
PULONG Ulong OPTIONAL,
|
PULONG Ulong OPTIONAL,
|
||||||
PLARGE_INTEGER LargeInteger OPTIONAL
|
PLARGE_INTEGER LargeInteger OPTIONAL,
|
||||||
|
LPWSAOVERLAPPED Overlapped OPTIONAL,
|
||||||
|
LPWSAOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine OPTIONAL
|
||||||
);
|
);
|
||||||
|
|
||||||
int SetSocketInformation(
|
int SetSocketInformation(
|
||||||
|
@ -442,7 +444,9 @@ int SetSocketInformation(
|
||||||
ULONG AfdInformationClass,
|
ULONG AfdInformationClass,
|
||||||
PBOOLEAN Boolean OPTIONAL,
|
PBOOLEAN Boolean OPTIONAL,
|
||||||
PULONG Ulong OPTIONAL,
|
PULONG Ulong OPTIONAL,
|
||||||
PLARGE_INTEGER LargeInteger OPTIONAL
|
PLARGE_INTEGER LargeInteger OPTIONAL,
|
||||||
|
LPWSAOVERLAPPED Overlapped OPTIONAL,
|
||||||
|
LPWSAOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine OPTIONAL
|
||||||
);
|
);
|
||||||
|
|
||||||
int CreateContext(
|
int CreateContext(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue