WSPUPCALLTABLE Upcalls;
LPWPUCOMPLETEOVERLAPPEDREQUEST lpWPUCompleteOverlappedRequest;
PSOCKET_INFORMATION SocketListHead = NULL;
+CRITICAL_SECTION SocketListLock;
LIST_ENTRY SockHelpersListHead = { NULL, NULL };
ULONG SockAsyncThreadRefCount;
HANDLE SockAsyncHelperAfdHandle;
-HANDLE SockAsyncCompletionPort;
+HANDLE SockAsyncCompletionPort = NULL;
BOOLEAN SockAsyncSelectCalled;
/* Save Group Info */
if (g != 0)
{
- GetSocketInformation(Socket, AFD_INFO_GROUP_ID_TYPE, 0, &GroupData);
+ GetSocketInformation(Socket, AFD_INFO_GROUP_ID_TYPE, NULL, NULL, &GroupData);
Socket->SharedData.GroupID = GroupData.u.LowPart;
Socket->SharedData.GroupType = GroupData.u.HighPart;
}
/* Get Window Sizes and Save them */
GetSocketInformation (Socket,
AFD_INFO_SEND_WINDOW_SIZE,
+ NULL,
&Socket->SharedData.SizeOfSendBuffer,
NULL);
GetSocketInformation (Socket,
AFD_INFO_RECEIVE_WINDOW_SIZE,
+ NULL,
&Socket->SharedData.SizeOfRecvBuffer,
NULL);
/* Save in Process Sockets List */
+ EnterCriticalSection(&SocketListLock);
Socket->NextSocket = SocketListHead;
SocketListHead = Socket;
+ LeaveCriticalSection(&SocketListLock);
/* Create the Socket Context */
CreateContext(Socket);
}
}
-DWORD MsafdReturnWithErrno(NTSTATUS Status,
- LPINT Errno,
- DWORD Received,
- LPDWORD ReturnedBytes)
-{
- *Errno = TranslateNtStatusError(Status);
-
- if (ReturnedBytes)
- {
- if (!*Errno)
- *ReturnedBytes = Received;
- else
- *ReturnedBytes = 0;
- }
-
- return *Errno ? SOCKET_ERROR : 0;
-}
-
/*
* FUNCTION: Closes an open socket
* ARGUMENTS:
HANDLE SockEvent;
AFD_DISCONNECT_INFO DisconnectInfo;
SOCKET_STATE OldState;
+ LONG LingerWait = -1;
/* Create the Wait Event */
Status = NtCreateEvent(&SockEvent,
/* FIXME: Should we do this on Datagram Sockets too? */
if ((OldState == SocketConnected) && (Socket->SharedData.LingerData.l_onoff))
{
- ULONG LingerWait;
ULONG SendsInProgress;
ULONG SleepWait;
/* Find out how many Sends are in Progress */
if (GetSocketInformation(Socket,
AFD_INFO_SENDS_IN_PROGRESS,
+ NULL,
&SendsInProgress,
NULL))
{
/* Bail out if no more sends are pending */
if (!SendsInProgress)
+ {
+ LingerWait = -1;
break;
+ }
+
/*
* We have to execute a sleep, so it's kind of like
* a block. If the socket is Nonblock, we cannot
Sleep(SleepWait);
LingerWait -= SleepWait;
}
+ }
- /*
- * We have reached the timeout or sends are over.
- * Disconnect if the timeout has been reached.
- */
+ if (OldState == SocketConnected)
+ {
if (LingerWait <= 0)
{
DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(0);
- DisconnectInfo.DisconnectType = AFD_DISCONNECT_ABORT;
-
- /* Send IOCTL */
- Status = NtDeviceIoControlFile((HANDLE)Handle,
- SockEvent,
- NULL,
- NULL,
- &IoStatusBlock,
- IOCTL_AFD_DISCONNECT,
- &DisconnectInfo,
- sizeof(DisconnectInfo),
- NULL,
- 0);
-
- /* Wait for return */
- if (Status == STATUS_PENDING)
+ DisconnectInfo.DisconnectType = LingerWait < 0 ? AFD_DISCONNECT_SEND : AFD_DISCONNECT_ABORT;
+
+ if (((DisconnectInfo.DisconnectType & AFD_DISCONNECT_SEND) && (!Socket->SharedData.SendShutdown)) ||
+ ((DisconnectInfo.DisconnectType & AFD_DISCONNECT_ABORT) && (!Socket->SharedData.ReceiveShutdown)))
{
- WaitForSingleObject(SockEvent, INFINITE);
- Status = IoStatusBlock.Status;
+ /* Send IOCTL */
+ Status = NtDeviceIoControlFile((HANDLE)Handle,
+ SockEvent,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ IOCTL_AFD_DISCONNECT,
+ &DisconnectInfo,
+ sizeof(DisconnectInfo),
+ NULL,
+ 0);
+
+ /* Wait for return */
+ if (Status == STATUS_PENDING)
+ {
+ WaitForSingleObject(SockEvent, INFINITE);
+ Status = IoStatusBlock.Status;
+ }
}
}
}
NtClose(Socket->TdiConnectionHandle);
Socket->TdiConnectionHandle = NULL;
+ EnterCriticalSection(&SocketListLock);
if (SocketListHead == Socket)
{
SocketListHead = SocketListHead->NextSocket;
CurrentSocket = CurrentSocket->NextSocket;
}
}
-
- HeapFree(GlobalHeap, 0, Socket);
+ LeaveCriticalSection(&SocketListLock);
/* Close the handle */
NtClose((HANDLE)Handle);
NtClose(SockEvent);
+ HeapFree(GlobalHeap, 0, Socket);
return MsafdReturnWithErrno(Status, lpErrno, 0, NULL);
}
IO_STATUS_BLOCK IOSB;
PAFD_POLL_INFO PollInfo;
NTSTATUS Status;
- LONG HandleCount, OutCount = 0;
+ ULONG HandleCount;
+ LONG OutCount = 0;
ULONG PollBufferSize;
PVOID PollBuffer;
ULONG i, j = 0, x;
if ( HandleCount == 0 )
{
- AFD_DbgPrint(MAX_TRACE,("HandleCount: %d. Return SOCKET_ERROR\n",
+ AFD_DbgPrint(MAX_TRACE,("HandleCount: %u. Return SOCKET_ERROR\n",
HandleCount));
if (lpErrno) *lpErrno = WSAEINVAL;
return SOCKET_ERROR;
PollBufferSize = sizeof(*PollInfo) + ((HandleCount - 1) * sizeof(AFD_HANDLE));
- AFD_DbgPrint(MID_TRACE,("HandleCount: %d BufferSize: %d\n",
+ AFD_DbgPrint(MID_TRACE,("HandleCount: %u BufferSize: %u\n",
HandleCount, PollBufferSize));
/* Convert Timeout to NT Format */
}
PollInfo->HandleCount = j;
- PollBufferSize = ((PCHAR)&PollInfo->Handles[j+1]) - ((PCHAR)PollInfo);
+ PollBufferSize = FIELD_OFFSET(AFD_POLL_INFO, Handles) + PollInfo->HandleCount * sizeof(AFD_HANDLE);
/* Send IOCTL */
Status = NtDeviceIoControlFile((HANDLE)PollInfo->Handles[0].Handle,
ULONG CallBack;
WSAPROTOCOL_INFOW ProtocolInfo;
SOCKET AcceptSocket;
+ PSOCKET_INFORMATION AcceptSocketInfo;
UCHAR ReceiveBuffer[0x1A];
HANDLE SockEvent;
MsafdReturnWithErrno( Status, lpErrno, 0, NULL );
return INVALID_SOCKET;
}
+
+ AcceptSocketInfo = GetSocketStructure(AcceptSocket);
+ if (!AcceptSocketInfo)
+ {
+ NtClose(SockEvent);
+ WSPCloseSocket( AcceptSocket, lpErrno );
+ MsafdReturnWithErrno( STATUS_INVALID_CONNECTION, lpErrno, 0, NULL );
+ return INVALID_SOCKET;
+ }
+
+ AcceptSocketInfo->SharedData.State = SocketConnected;
/* Return Address in SOCKADDR FORMAT */
if( SocketAddress )
if (Status != STATUS_SUCCESS)
goto notify;
+ Socket->SharedData.State = SocketConnected;
Socket->TdiConnectionHandle = (HANDLE)IOSB.Information;
/* Get any pending connect data */
break;
}
- DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(-1);
+ DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(-1000000);
/* Send IOCTL */
Status = NtDeviceIoControlFile((HANDLE)Handle,
return SOCKET_ERROR;
}
+ if (!Name || !NameLength)
+ {
+ NtClose(SockEvent);
+ *lpErrno = WSAEFAULT;
+ return SOCKET_ERROR;
+ }
+
/* Allocate a buffer for the address */
TdiAddressSize =
sizeof(TRANSPORT_ADDRESS) + Socket->SharedData.SizeOfLocalAddress;
if (NT_SUCCESS(Status))
{
- if (*NameLength >= SocketAddress->Address[0].AddressLength)
+ if (*NameLength >= Socket->SharedData.SizeOfLocalAddress)
{
Name->sa_family = SocketAddress->Address[0].AddressType;
RtlCopyMemory (Name->sa_data,
SocketAddress->Address[0].Address,
SocketAddress->Address[0].AddressLength);
- *NameLength = 2 + SocketAddress->Address[0].AddressLength;
+ *NameLength = Socket->SharedData.SizeOfLocalAddress;
AFD_DbgPrint (MID_TRACE, ("NameLength %d Address: %x Port %x\n",
*NameLength, ((struct sockaddr_in *)Name)->sin_addr.s_addr,
((struct sockaddr_in *)Name)->sin_port));
return SOCKET_ERROR;
}
+ if (Socket->SharedData.State != SocketConnected)
+ {
+ NtClose(SockEvent);
+ *lpErrno = WSAENOTCONN;
+ return SOCKET_ERROR;
+ }
+
+ if (!Name || !NameLength)
+ {
+ NtClose(SockEvent);
+ *lpErrno = WSAEFAULT;
+ return SOCKET_ERROR;
+ }
+
/* Allocate a buffer for the address */
- TdiAddressSize = sizeof(TRANSPORT_ADDRESS) + *NameLength;
+ TdiAddressSize = sizeof(TRANSPORT_ADDRESS) + Socket->SharedData.SizeOfRemoteAddress;
SocketAddress = HeapAlloc(GlobalHeap, 0, TdiAddressSize);
if ( SocketAddress == NULL )
if (NT_SUCCESS(Status))
{
- if (*NameLength >= SocketAddress->Address[0].AddressLength)
+ if (*NameLength >= Socket->SharedData.SizeOfRemoteAddress)
{
Name->sa_family = SocketAddress->Address[0].AddressType;
RtlCopyMemory (Name->sa_data,
SocketAddress->Address[0].Address,
SocketAddress->Address[0].AddressLength);
- *NameLength = 2 + SocketAddress->Address[0].AddressLength;
+ *NameLength = Socket->SharedData.SizeOfRemoteAddress;
AFD_DbgPrint (MID_TRACE, ("NameLength %d Address: %s Port %x\n",
*NameLength, ((struct sockaddr_in *)Name)->sin_addr.s_addr,
((struct sockaddr_in *)Name)->sin_port));
OUT LPINT lpErrno)
{
PSOCKET_INFORMATION Socket = NULL;
+ BOOLEAN NeedsCompletion;
+ BOOLEAN NonBlocking;
/* Get the Socket Structure associate to this Socket*/
Socket = GetSocketStructure(Handle);
*lpErrno = WSAENOTSOCK;
return SOCKET_ERROR;
}
+
+ *lpcbBytesReturned = 0;
switch( dwIoControlCode )
{
*lpErrno = WSAEFAULT;
return SOCKET_ERROR;
}
- Socket->SharedData.NonBlocking = *((PULONG)lpvInBuffer) ? 1 : 0;
- return SetSocketInformation(Socket, AFD_INFO_BLOCKING_MODE, (PULONG)lpvInBuffer, NULL);
+ NonBlocking = *((PULONG)lpvInBuffer) ? TRUE : FALSE;
+ Socket->SharedData.NonBlocking = NonBlocking ? 1 : 0;
+ *lpErrno = SetSocketInformation(Socket, AFD_INFO_BLOCKING_MODE, &NonBlocking, NULL, NULL);
+ if (*lpErrno != NO_ERROR)
+ return SOCKET_ERROR;
+ else
+ return NO_ERROR;
case FIONREAD:
if( cbOutBuffer < sizeof(INT) || IS_INTRESOURCE(lpvOutBuffer) )
{
*lpErrno = WSAEFAULT;
return SOCKET_ERROR;
}
- return GetSocketInformation(Socket, AFD_INFO_RECEIVE_CONTENT_SIZE, (PULONG)lpvOutBuffer, NULL);
- default:
+ *lpErrno = GetSocketInformation(Socket, AFD_INFO_RECEIVE_CONTENT_SIZE, NULL, (PULONG)lpvOutBuffer, NULL);
+ if (*lpErrno != NO_ERROR)
+ return SOCKET_ERROR;
+ else
+ {
+ *lpcbBytesReturned = sizeof(ULONG);
+ return NO_ERROR;
+ }
+ case SIO_GET_EXTENSION_FUNCTION_POINTER:
*lpErrno = WSAEINVAL;
return SOCKET_ERROR;
+ default:
+ *lpErrno = Socket->HelperData->WSHIoctl(Socket->HelperContext,
+ Handle,
+ Socket->TdiAddressHandle,
+ Socket->TdiConnectionHandle,
+ dwIoControlCode,
+ lpvInBuffer,
+ cbInBuffer,
+ lpvOutBuffer,
+ cbOutBuffer,
+ lpcbBytesReturned,
+ lpOverlapped,
+ lpCompletionRoutine,
+ (LPBOOL)&NeedsCompletion);
+
+ if (*lpErrno != NO_ERROR)
+ return SOCKET_ERROR;
+ else
+ return NO_ERROR;
}
}
}
- /* FIXME: We should handle some cases here */
+ /* FIXME: We should handle some more cases here */
+ if (level == SOL_SOCKET)
+ {
+ switch (optname)
+ {
+ case SO_BROADCAST:
+ Socket->SharedData.Broadcast = (*optval != 0) ? 1 : 0;
+ return 0;
+ }
+ }
*lpErrno = Socket->HelperData->WSHSetSocketInformation(Socket->HelperContext,
int
GetSocketInformation(PSOCKET_INFORMATION Socket,
ULONG AfdInformationClass,
+ PBOOLEAN Boolean OPTIONAL,
PULONG Ulong OPTIONAL,
PLARGE_INTEGER LargeInteger OPTIONAL)
{
{
*LargeInteger = InfoData.Information.LargeInteger;
}
+ if (Boolean != NULL)
+ {
+ *Boolean = InfoData.Information.Boolean;
+ }
NtClose( SockEvent );
int
SetSocketInformation(PSOCKET_INFORMATION Socket,
- ULONG AfdInformationClass,
+ ULONG AfdInformationClass,
+ PBOOLEAN Boolean OPTIONAL,
PULONG Ulong OPTIONAL,
PLARGE_INTEGER LargeInteger OPTIONAL)
{
{
InfoData.Information.LargeInteger = *LargeInteger;
}
+ if (Boolean != NULL)
+ {
+ InfoData.Information.Boolean = *Boolean;
+ }
AFD_DbgPrint(MID_TRACE,("XXX Info %x (Data %x)\n",
AfdInformationClass, *Ulong));
{
PSOCKET_INFORMATION CurrentSocket;
+ EnterCriticalSection(&SocketListLock);
+
CurrentSocket = SocketListHead;
while (CurrentSocket)
{
if (CurrentSocket->Handle == Handle)
+ {
+ LeaveCriticalSection(&SocketListLock);
return CurrentSocket;
+ }
CurrentSocket = CurrentSocket->NextSocket;
}
+ LeaveCriticalSection(&SocketListLock);
+
return NULL;
}
/* Check if the Thread Already Exists */
if (SockAsyncThreadRefCount)
{
+ ASSERT(SockAsyncCompletionPort);
return TRUE;
}
IO_COMPLETION_ALL_ACCESS,
NULL,
2); // Allow 2 threads only
-
+ if (!NT_SUCCESS(Status))
+ {
+ AFD_DbgPrint(MID_TRACE,("Failed to create completion port\n"));
+ return FALSE;
+ }
/* Protect Handle */
HandleFlags.ProtectFromClose = TRUE;
HandleFlags.Inherit = FALSE;
/* Heap to use when allocating */
GlobalHeap = GetProcessHeap();
+ /* Initialize the lock that protects our socket list */
+ InitializeCriticalSection(&SocketListLock);
+
AFD_DbgPrint(MAX_TRACE, ("MSAFD.DLL has been loaded\n"));
break;
break;
case DLL_PROCESS_DETACH:
+
+ /* Delete the socket list lock */
+ DeleteCriticalSection(&SocketListLock);
+
break;
}