#include <debug.h>
-#ifdef DBG
+#if DBG
//DWORD DebugTraceLevel = DEBUG_ULTRA;
DWORD DebugTraceLevel = 0;
#endif /* DBG */
HANDLE GlobalHeap;
WSPUPCALLTABLE Upcalls;
LPWPUCOMPLETEOVERLAPPEDREQUEST lpWPUCompleteOverlappedRequest;
-ULONG SocketCount = 0;
-PSOCKET_INFORMATION *Sockets = NULL;
+PSOCKET_INFORMATION SocketListHead = NULL;
+CRITICAL_SECTION SocketListLock;
LIST_ENTRY SockHelpersListHead = { NULL, NULL };
ULONG SockAsyncThreadRefCount;
HANDLE SockAsyncHelperAfdHandle;
ULONG SizeOfEA;
PAFD_CREATE_PACKET AfdPacket;
HANDLE Sock;
- PSOCKET_INFORMATION Socket = NULL, PrevSocket = NULL;
+ PSOCKET_INFORMATION Socket = NULL;
PFILE_FULL_EA_INFORMATION EABuffer = NULL;
PHELPER_DATA HelperData;
PVOID HelperDLLContext;
/* Set Socket Data */
Socket = HeapAlloc(GlobalHeap, 0, sizeof(*Socket));
+ if (!Socket)
+ return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL);
+
RtlZeroMemory(Socket, sizeof(*Socket));
Socket->RefCount = 2;
Socket->Handle = -1;
/* Set up EA Buffer */
EABuffer = HeapAlloc(GlobalHeap, 0, SizeOfEA);
+ if (!EABuffer)
+ return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL);
+
RtlZeroMemory(EABuffer, SizeOfEA);
EABuffer->NextEntryOffset = 0;
EABuffer->Flags = 0;
ourselves after every call to NtDeviceIoControlFile. This is
because the kernel doesn't support overlapping synchronous I/O
requests (made from multiple threads) at this time (Sep 2005) */
- ZwCreateFile(&Sock,
- GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
- &Object,
- &IOSB,
- NULL,
- 0,
- FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN_IF,
- 0,
- EABuffer,
- SizeOfEA);
-
- /* Save Handle */
- Socket->Handle = (SOCKET)Sock;
+ Status = NtCreateFile(&Sock,
+ GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
+ &Object,
+ &IOSB,
+ NULL,
+ 0,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_OPEN_IF,
+ 0,
+ EABuffer,
+ SizeOfEA);
- /* XXX See if there's a structure we can reuse -- We need to do this
- * more properly. */
- PrevSocket = GetSocketStructure( (SOCKET)Sock );
+ HeapFree(GlobalHeap, 0, EABuffer);
- if( PrevSocket )
+ if (Status != STATUS_SUCCESS)
{
- RtlCopyMemory( PrevSocket, Socket, sizeof(*Socket) );
- RtlFreeHeap( GlobalHeap, 0, Socket );
- Socket = PrevSocket;
+ AFD_DbgPrint(MIN_TRACE, ("Failed to open socket\n"));
+
+ HeapFree(GlobalHeap, 0, Socket);
+
+ return MsafdReturnWithErrno(Status, lpErrno, 0, NULL);
}
+ /* Save Handle */
+ Socket->Handle = (SOCKET)Sock;
+
/* Save Group Info */
if (g != 0)
{
NULL);
/* Save in Process Sockets List */
- Sockets[SocketCount] = Socket;
- SocketCount ++;
+ EnterCriticalSection(&SocketListLock);
+ Socket->NextSocket = SocketListHead;
+ SocketListHead = Socket;
+ LeaveCriticalSection(&SocketListLock);
/* Create the Socket Context */
CreateContext(Socket);
error:
AFD_DbgPrint(MID_TRACE,("Ending %x\n", Status));
+ if( Socket )
+ HeapFree(GlobalHeap, 0, Socket);
+
if( lpErrno )
*lpErrno = Status;
return INVALID_SOCKET;
}
-
-DWORD MsafdReturnWithErrno(NTSTATUS Status,
- LPINT Errno,
- DWORD Received,
- LPDWORD ReturnedBytes)
+INT
+TranslateNtStatusError(NTSTATUS Status)
{
- if( ReturnedBytes )
- *ReturnedBytes = 0;
- if( Errno )
+ switch (Status)
{
- switch (Status)
- {
- case STATUS_CANT_WAIT:
- *Errno = WSAEWOULDBLOCK;
- break;
- case STATUS_TIMEOUT:
- *Errno = WSAETIMEDOUT;
- break;
- case STATUS_SUCCESS:
- /* Return Number of bytes Read */
- if( ReturnedBytes )
- *ReturnedBytes = Received;
- break;
- case STATUS_FILE_CLOSED:
- case STATUS_END_OF_FILE:
- *Errno = WSAESHUTDOWN;
- break;
- case STATUS_PENDING:
- *Errno = WSA_IO_PENDING;
- break;
- case STATUS_BUFFER_TOO_SMALL:
- case STATUS_BUFFER_OVERFLOW:
- DbgPrint("MSAFD: STATUS_BUFFER_TOO_SMALL/STATUS_BUFFER_OVERFLOW\n");
- *Errno = WSAEMSGSIZE;
- break;
- case STATUS_NO_MEMORY: /* Fall through to STATUS_INSUFFICIENT_RESOURCES */
- case STATUS_INSUFFICIENT_RESOURCES:
- DbgPrint("MSAFD: STATUS_NO_MEMORY/STATUS_INSUFFICIENT_RESOURCES\n");
- *Errno = WSA_NOT_ENOUGH_MEMORY;
- break;
- case STATUS_INVALID_CONNECTION:
- DbgPrint("MSAFD: STATUS_INVALID_CONNECTION\n");
- *Errno = WSAEAFNOSUPPORT;
- break;
- case STATUS_REMOTE_NOT_LISTENING:
- DbgPrint("MSAFD: STATUS_REMOTE_NOT_LISTENING\n");
- *Errno = WSAECONNREFUSED;
- break;
- case STATUS_NETWORK_UNREACHABLE:
- DbgPrint("MSAFD: STATUS_NETWORK_UNREACHABLE\n");
- *Errno = WSAENETUNREACH;
- break;
- case STATUS_INVALID_PARAMETER:
- DbgPrint("MSAFD: STATUS_INVALID_PARAMETER\n");
- *Errno = WSAEINVAL;
- break;
- case STATUS_CANCELLED:
- DbgPrint("MSAFD: STATUS_CANCELLED\n");
- *Errno = WSA_OPERATION_ABORTED;
- break;
- default:
- DbgPrint("MSAFD: Error %x is unknown\n", Status);
- *Errno = WSAEINVAL;
- break;
- }
- }
+ case STATUS_CANT_WAIT:
+ return WSAEWOULDBLOCK;
+
+ case STATUS_TIMEOUT:
+ return WSAETIMEDOUT;
+
+ case STATUS_SUCCESS:
+ return NO_ERROR;
+
+ case STATUS_FILE_CLOSED:
+ case STATUS_END_OF_FILE:
+ return WSAESHUTDOWN;
+
+ case STATUS_PENDING:
+ return WSA_IO_PENDING;
+
+ case STATUS_BUFFER_TOO_SMALL:
+ case STATUS_BUFFER_OVERFLOW:
+ DbgPrint("MSAFD: STATUS_BUFFER_TOO_SMALL/STATUS_BUFFER_OVERFLOW\n");
+ return WSAEMSGSIZE;
+
+ case STATUS_NO_MEMORY:
+ case STATUS_INSUFFICIENT_RESOURCES:
+ DbgPrint("MSAFD: STATUS_NO_MEMORY/STATUS_INSUFFICIENT_RESOURCES\n");
+ return WSAENOBUFS;
- /* Success */
- return Status == STATUS_SUCCESS ? 0 : SOCKET_ERROR;
+ case STATUS_INVALID_CONNECTION:
+ DbgPrint("MSAFD: STATUS_INVALID_CONNECTION\n");
+ return WSAEAFNOSUPPORT;
+
+ case STATUS_INVALID_ADDRESS:
+ DbgPrint("MSAFD: STATUS_INVALID_ADDRESS\n");
+ return WSAEADDRNOTAVAIL;
+
+ case STATUS_REMOTE_NOT_LISTENING:
+ DbgPrint("MSAFD: STATUS_REMOTE_NOT_LISTENING\n");
+ return WSAECONNREFUSED;
+
+ case STATUS_NETWORK_UNREACHABLE:
+ DbgPrint("MSAFD: STATUS_NETWORK_UNREACHABLE\n");
+ return WSAENETUNREACH;
+
+ case STATUS_INVALID_PARAMETER:
+ DbgPrint("MSAFD: STATUS_INVALID_PARAMETER\n");
+ return WSAEINVAL;
+
+ case STATUS_CANCELLED:
+ DbgPrint("MSAFD: STATUS_CANCELLED\n");
+ return WSA_OPERATION_ABORTED;
+
+ case STATUS_ADDRESS_ALREADY_EXISTS:
+ DbgPrint("MSAFD: STATUS_ADDRESS_ALREADY_EXISTS\n");
+ return WSAEADDRINUSE;
+
+ case STATUS_LOCAL_DISCONNECT:
+ DbgPrint("MSAFD: STATUS_LOCAL_DISCONNECT\n");
+ return WSAECONNABORTED;
+
+ case STATUS_REMOTE_DISCONNECT:
+ DbgPrint("MSAFD: STATUS_REMOTE_DISCONNECT\n");
+ return WSAECONNRESET;
+
+ default:
+ DbgPrint("MSAFD: Unhandled NTSTATUS value: 0x%x\n", Status);
+ return WSAENETDOWN;
+ }
}
/*
OUT LPINT lpErrno)
{
IO_STATUS_BLOCK IoStatusBlock;
- PSOCKET_INFORMATION Socket = NULL;
+ PSOCKET_INFORMATION Socket = NULL, CurrentSocket;
NTSTATUS Status;
HANDLE SockEvent;
AFD_DISCONNECT_INFO DisconnectInfo;
/* Get the Socket Structure associate to this Socket*/
Socket = GetSocketStructure(Handle);
+ if (!Socket)
+ {
+ NtClose(SockEvent);
+ *lpErrno = WSAENOTSOCK;
+ return SOCKET_ERROR;
+ }
+
+ if (Socket->HelperEvents & WSH_NOTIFY_CLOSE)
+ {
+ Status = Socket->HelperData->WSHNotify(Socket->HelperContext,
+ Socket->Handle,
+ Socket->TdiAddressHandle,
+ Socket->TdiConnectionHandle,
+ WSH_NOTIFY_CLOSE);
+
+ if (Status)
+ {
+ if (lpErrno) *lpErrno = Status;
+ NtClose(SockEvent);
+ return SOCKET_ERROR;
+ }
+ }
/* If a Close is already in Process, give up */
if (Socket->SharedData.State == SocketClosed)
if (Status == STATUS_PENDING)
{
WaitForSingleObject(SockEvent, INFINITE);
+ Status = IoStatusBlock.Status;
}
}
}
- /* FIXME: We should notify the Helper DLL of WSH_NOTIFY_CLOSE */
-
/* Cleanup Time! */
Socket->HelperContext = NULL;
Socket->SharedData.AsyncDisabledEvents = -1;
NtClose(Socket->TdiConnectionHandle);
Socket->TdiConnectionHandle = NULL;
+ EnterCriticalSection(&SocketListLock);
+ if (SocketListHead == Socket)
+ {
+ SocketListHead = SocketListHead->NextSocket;
+ }
+ else
+ {
+ CurrentSocket = SocketListHead;
+ while (CurrentSocket->NextSocket)
+ {
+ if (CurrentSocket->NextSocket == Socket)
+ {
+ CurrentSocket->NextSocket = CurrentSocket->NextSocket->NextSocket;
+ break;
+ }
+
+ CurrentSocket = CurrentSocket->NextSocket;
+ }
+ }
+ LeaveCriticalSection(&SocketListLock);
+
+ HeapFree(GlobalHeap, 0, Socket);
+
/* Close the handle */
NtClose((HANDLE)Handle);
NtClose(SockEvent);
- return NO_ERROR;
+ return MsafdReturnWithErrno(Status, lpErrno, 0, NULL);
}
PAFD_BIND_DATA BindData;
PSOCKET_INFORMATION Socket = NULL;
NTSTATUS Status;
- UCHAR BindBuffer[0x1A];
SOCKADDR_INFO SocketInfo;
HANDLE SockEvent;
+ /* See below */
+ BindData = HeapAlloc(GlobalHeap, 0, 0xA + SocketAddressLength);
+ if (!BindData)
+ {
+ return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL);
+ }
+
Status = NtCreateEvent(&SockEvent,
GENERIC_READ | GENERIC_WRITE,
NULL,
1,
FALSE);
- if( !NT_SUCCESS(Status) )
- return -1;
+ if (!NT_SUCCESS(Status))
+ {
+ HeapFree(GlobalHeap, 0, BindData);
+ return SOCKET_ERROR;
+ }
/* Get the Socket Structure associate to this Socket*/
Socket = GetSocketStructure(Handle);
-
- /* Dynamic Structure...ugh */
- BindData = (PAFD_BIND_DATA)BindBuffer;
+ if (!Socket)
+ {
+ HeapFree(GlobalHeap, 0, BindData);
+ *lpErrno = WSAENOTSOCK;
+ return SOCKET_ERROR;
+ }
/* Set up Address in TDI Format */
BindData->Address.TAAddressCount = 1;
Status = IOSB.Status;
}
+ NtClose( SockEvent );
+ HeapFree(GlobalHeap, 0, BindData);
+
+ if (Status != STATUS_SUCCESS)
+ return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL );
+
/* Set up Socket Data */
Socket->SharedData.State = SocketBound;
Socket->TdiAddressHandle = (HANDLE)IOSB.Information;
- NtClose( SockEvent );
+ if (Socket->HelperEvents & WSH_NOTIFY_BIND)
+ {
+ Status = Socket->HelperData->WSHNotify(Socket->HelperContext,
+ Socket->Handle,
+ Socket->TdiAddressHandle,
+ Socket->TdiConnectionHandle,
+ WSH_NOTIFY_BIND);
+
+ if (Status)
+ {
+ if (lpErrno) *lpErrno = Status;
+ return SOCKET_ERROR;
+ }
+ }
return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL );
}
/* Get the Socket Structure associate to this Socket*/
Socket = GetSocketStructure(Handle);
+ if (!Socket)
+ {
+ *lpErrno = WSAENOTSOCK;
+ return SOCKET_ERROR;
+ }
if (Socket->SharedData.Listening)
return 0;
{
WaitForSingleObject(SockEvent, INFINITE);
Status = IOSB.Status;
- }
+ }
+
+ NtClose( SockEvent );
+
+ if (Status != STATUS_SUCCESS)
+ return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL );
/* Set to Listening */
Socket->SharedData.Listening = TRUE;
- NtClose( SockEvent );
+ if (Socket->HelperEvents & WSH_NOTIFY_LISTEN)
+ {
+ Status = Socket->HelperData->WSHNotify(Socket->HelperContext,
+ Socket->Handle,
+ Socket->TdiAddressHandle,
+ Socket->TdiConnectionHandle,
+ WSH_NOTIFY_LISTEN);
+
+ if (Status)
+ {
+ if (lpErrno) *lpErrno = Status;
+ return SOCKET_ERROR;
+ }
+ }
return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL );
}
int
WSPAPI
-WSPSelect(int nfds,
- fd_set *readfds,
- fd_set *writefds,
- fd_set *exceptfds,
- struct timeval *timeout,
- LPINT lpErrno)
+WSPSelect(IN int nfds,
+ IN OUT fd_set *readfds OPTIONAL,
+ IN OUT fd_set *writefds OPTIONAL,
+ IN OUT fd_set *exceptfds OPTIONAL,
+ IN const struct timeval *timeout OPTIONAL,
+ OUT LPINT lpErrno)
{
IO_STATUS_BLOCK IOSB;
PAFD_POLL_INFO PollInfo;
PollInfo->Handles[j].Events = AFD_EVENT_RECEIVE |
AFD_EVENT_DISCONNECT |
AFD_EVENT_ABORT |
+ AFD_EVENT_CLOSE |
AFD_EVENT_ACCEPT;
}
}
if (Status == STATUS_PENDING)
{
WaitForSingleObject(SockEvent, INFINITE);
+ Status = IOSB.Status;
}
/* Clear the Structures */
struct sockaddr *SocketAddress,
int *SocketAddressLength,
LPCONDITIONPROC lpfnCondition,
- DWORD_PTR dwCallbackData,
+ DWORD dwCallbackData,
LPINT lpErrno)
{
IO_STATUS_BLOCK IOSB;
/* Get the Socket Structure associate to this Socket*/
Socket = GetSocketStructure(Handle);
+ if (!Socket)
+ {
+ NtClose(SockEvent);
+ *lpErrno = WSAENOTSOCK;
+ return INVALID_SOCKET;
+ }
/* If this is non-blocking, make sure there's something for us to accept */
FD_ZERO(&ReadSet);
Timeout.tv_sec=0;
Timeout.tv_usec=0;
- WSPSelect(0, &ReadSet, NULL, NULL, &Timeout, NULL);
+ if (WSPSelect(0, &ReadSet, NULL, NULL, &Timeout, lpErrno) == SOCKET_ERROR)
+ {
+ NtClose(SockEvent);
+ return INVALID_SOCKET;
+ }
if (ReadSet.fd_array[0] != Socket->Handle)
{
NtClose(SockEvent);
- return 0;
+ *lpErrno = WSAEWOULDBLOCK;
+ return INVALID_SOCKET;
}
/* Send IOCTL */
{
/* Allocate needed space */
PendingData = HeapAlloc(GlobalHeap, 0, PendingDataLength);
+ if (!PendingData)
+ {
+ MsafdReturnWithErrno( STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL );
+ return INVALID_SOCKET;
+ }
/* We want the data now */
PendingAcceptData.ReturnSize = FALSE;
CalleeID.buf = (PVOID)Socket->LocalAddress;
CalleeID.len = Socket->SharedData.SizeOfLocalAddress;
+ RemoteAddress = HeapAlloc(GlobalHeap, 0, sizeof(*RemoteAddress));
+ if (!RemoteAddress)
+ {
+ MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL);
+ return INVALID_SOCKET;
+ }
+
/* Set up Address in SOCKADDR Format */
RtlCopyMemory (RemoteAddress,
&ListenReceiveData->Address.Address[0].AddressType,
{
/* Allocate Buffer for Callee Data */
CalleeDataBuffer = HeapAlloc(GlobalHeap, 0, 4096);
+ if (!CalleeDataBuffer) {
+ MsafdReturnWithErrno( STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL );
+ return INVALID_SOCKET;
+ }
CalleeData.buf = CalleeDataBuffer;
CalleeData.len = 4096;
}
&ProtocolInfo,
GroupID,
Socket->SharedData.CreateFlags,
- NULL);
+ lpErrno);
+ if (AcceptSocket == INVALID_SOCKET)
+ return INVALID_SOCKET;
/* Set up the Accept Structure */
- AcceptData.ListenHandle = AcceptSocket;
+ AcceptData.ListenHandle = (HANDLE)AcceptSocket;
AcceptData.SequenceNumber = ListenReceiveData->SequenceNumber;
/* Send IOCTL to Accept */
AFD_DbgPrint(MID_TRACE,("Socket %x\n", AcceptSocket));
+ if (Status == STATUS_SUCCESS && (Socket->HelperEvents & WSH_NOTIFY_ACCEPT))
+ {
+ Status = Socket->HelperData->WSHNotify(Socket->HelperContext,
+ Socket->Handle,
+ Socket->TdiAddressHandle,
+ Socket->TdiConnectionHandle,
+ WSH_NOTIFY_ACCEPT);
+
+ if (Status)
+ {
+ if (lpErrno) *lpErrno = Status;
+ return INVALID_SOCKET;
+ }
+ }
+
*lpErrno = 0;
/* Return Socket */
/* Get the Socket Structure associate to this Socket*/
Socket = GetSocketStructure(Handle);
+ if (!Socket)
+ {
+ NtClose(SockEvent);
+ *lpErrno = WSAENOTSOCK;
+ return SOCKET_ERROR;
+ }
/* Bind us First */
if (Socket->SharedData.State == SocketOpen)
/* Get the Wildcard Address */
BindAddressLength = Socket->HelperData->MaxWSAddressLength;
BindAddress = HeapAlloc(GetProcessHeap(), 0, BindAddressLength);
+ if (!BindAddress)
+ {
+ MsafdReturnWithErrno( STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL );
+ return INVALID_SOCKET;
+ }
Socket->HelperData->WSHGetWildcardSockaddr (Socket->HelperContext,
BindAddress,
&BindAddressLength);
/* Bind it */
- WSPBind(Handle, BindAddress, BindAddressLength, NULL);
+ if (WSPBind(Handle, BindAddress, BindAddressLength, lpErrno) == SOCKET_ERROR)
+ return INVALID_SOCKET;
}
/* Set the Connect Data */
WaitForSingleObject(SockEvent, INFINITE);
Status = IOSB.Status;
}
+
+ if (Status != STATUS_SUCCESS)
+ goto notify;
}
/* Dynamic Structure...ugh */
WaitForSingleObject(SockEvent, INFINITE);
Status = IOSB.Status;
}
+
+ if (Status != STATUS_SUCCESS)
+ goto notify;
}
/* AFD doesn't seem to care if these are invalid, but let's 0 them anyways */
Status = IOSB.Status;
}
+ if (Status != STATUS_SUCCESS)
+ goto notify;
+
+ Socket->TdiConnectionHandle = (HANDLE)IOSB.Information;
+
/* Get any pending connect data */
if (lpCalleeData != NULL)
{
}
}
+ AFD_DbgPrint(MID_TRACE,("Ending\n"));
+
+notify:
/* Re-enable Async Event */
SockReenableAsyncSelectEvent(Socket, FD_WRITE);
/* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */
SockReenableAsyncSelectEvent(Socket, FD_CONNECT);
- AFD_DbgPrint(MID_TRACE,("Ending\n"));
-
NtClose( SockEvent );
+ if (Status == STATUS_SUCCESS && (Socket->HelperEvents & WSH_NOTIFY_CONNECT))
+ {
+ Status = Socket->HelperData->WSHNotify(Socket->HelperContext,
+ Socket->Handle,
+ Socket->TdiAddressHandle,
+ Socket->TdiConnectionHandle,
+ WSH_NOTIFY_CONNECT);
+
+ if (Status)
+ {
+ if (lpErrno) *lpErrno = Status;
+ return SOCKET_ERROR;
+ }
+ }
+ else if (Status != STATUS_SUCCESS && (Socket->HelperEvents & WSH_NOTIFY_CONNECT_ERROR))
+ {
+ Status = Socket->HelperData->WSHNotify(Socket->HelperContext,
+ Socket->Handle,
+ Socket->TdiAddressHandle,
+ Socket->TdiConnectionHandle,
+ WSH_NOTIFY_CONNECT_ERROR);
+
+ if (Status)
+ {
+ if (lpErrno) *lpErrno = Status;
+ return SOCKET_ERROR;
+ }
+ }
+
return MsafdReturnWithErrno( Status, lpErrno, 0, NULL );
}
int
/* Get the Socket Structure associate to this Socket*/
Socket = GetSocketStructure(Handle);
+ if (!Socket)
+ {
+ NtClose(SockEvent);
+ *lpErrno = WSAENOTSOCK;
+ return SOCKET_ERROR;
+ }
/* Set AFD Disconnect Type */
switch (HowTo)
/* Get the Socket Structure associate to this Socket*/
Socket = GetSocketStructure(Handle);
+ if (!Socket)
+ {
+ NtClose(SockEvent);
+ *lpErrno = WSAENOTSOCK;
+ return SOCKET_ERROR;
+ }
/* Allocate a buffer for the address */
TdiAddressSize =
/* Get the Socket Structure associate to this Socket*/
Socket = GetSocketStructure(s);
+ if (!Socket)
+ {
+ NtClose(SockEvent);
+ *lpErrno = WSAENOTSOCK;
+ return SOCKET_ERROR;
+ }
/* Allocate a buffer for the address */
TdiAddressSize = sizeof(TRANSPORT_ADDRESS) + *NameLength;
OUT LPINT lpErrno)
{
PSOCKET_INFORMATION Socket = NULL;
+ BOOLEAN NeedsCompletion;
/* Get the Socket Structure associate to this Socket*/
Socket = GetSocketStructure(Handle);
+ if (!Socket)
+ {
+ *lpErrno = WSAENOTSOCK;
+ return SOCKET_ERROR;
+ }
+
+ *lpcbBytesReturned = 0;
switch( dwIoControlCode )
{
case FIONBIO:
- if( cbInBuffer < sizeof(INT) )
+ if( cbInBuffer < sizeof(INT) || IS_INTRESOURCE(lpvInBuffer) )
+ {
+ *lpErrno = WSAEFAULT;
return SOCKET_ERROR;
- Socket->SharedData.NonBlocking = *((PINT)lpvInBuffer) ? 1 : 0;
- AFD_DbgPrint(MID_TRACE,("[%x] Set nonblocking %d\n", Handle, Socket->SharedData.NonBlocking));
- return 0;
+ }
+ Socket->SharedData.NonBlocking = *((PULONG)lpvInBuffer) ? 1 : 0;
+ *lpErrno = SetSocketInformation(Socket, AFD_INFO_BLOCKING_MODE, (PULONG)lpvInBuffer, NULL);
+ if (*lpErrno != NO_ERROR)
+ return SOCKET_ERROR;
+ else
+ return NO_ERROR;
case FIONREAD:
- return GetSocketInformation(Socket, AFD_INFO_RECEIVE_CONTENT_SIZE, (PULONG)lpvOutBuffer, NULL);
+ if( cbOutBuffer < sizeof(INT) || IS_INTRESOURCE(lpvOutBuffer) )
+ {
+ *lpErrno = WSAEFAULT;
+ return SOCKET_ERROR;
+ }
+ *lpErrno = GetSocketInformation(Socket, AFD_INFO_RECEIVE_CONTENT_SIZE, (PULONG)lpvOutBuffer, NULL);
+ if (*lpErrno != NO_ERROR)
+ {
+ *lpcbBytesReturned = sizeof(ULONG);
+ return SOCKET_ERROR;
+ }
+ else
+ return NO_ERROR;
default:
- *lpErrno = WSAEINVAL;
- return SOCKET_ERROR;
+ *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;
}
}
case IPPROTO_TCP: /* FIXME */
default:
- *lpErrno = WSAEINVAL;
- return SOCKET_ERROR;
+ *lpErrno = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext,
+ Handle,
+ Socket->TdiAddressHandle,
+ Socket->TdiConnectionHandle,
+ Level,
+ OptionName,
+ OptionValue,
+ (LPINT)OptionLength);
+ return (*lpErrno == 0) ? 0 : SOCKET_ERROR;
}
}
+INT
+WSPAPI
+WSPSetSockOpt(
+ IN SOCKET s,
+ IN INT level,
+ IN INT optname,
+ IN CONST CHAR FAR* optval,
+ IN INT optlen,
+ OUT LPINT lpErrno)
+{
+ PSOCKET_INFORMATION Socket;
+
+ /* Get the Socket Structure associate to this Socket*/
+ Socket = GetSocketStructure(s);
+ if (Socket == NULL)
+ {
+ *lpErrno = WSAENOTSOCK;
+ return SOCKET_ERROR;
+ }
+
+
+ /* 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,
+ s,
+ Socket->TdiAddressHandle,
+ Socket->TdiConnectionHandle,
+ level,
+ optname,
+ (PCHAR)optval,
+ optlen);
+ return (*lpErrno == 0) ? 0 : SOCKET_ERROR;
+}
/*
* FUNCTION: Initialize service provider for a client
if (Status == STATUS_PENDING)
{
WaitForSingleObject(SockEvent, INFINITE);
+ Status = IOSB.Status;
}
+ if (Status != STATUS_SUCCESS)
+ return -1;
+
/* Return Information */
- *Ulong = InfoData.Information.Ulong;
+ if (Ulong != NULL)
+ {
+ *Ulong = InfoData.Information.Ulong;
+ }
if (LargeInteger != NULL)
{
*LargeInteger = InfoData.Information.LargeInteger;
InfoData.InformationClass = AfdInformationClass;
/* Set Information */
- InfoData.Information.Ulong = *Ulong;
+ if (Ulong != NULL)
+ {
+ InfoData.Information.Ulong = *Ulong;
+ }
if (LargeInteger != NULL)
{
InfoData.Information.LargeInteger = *LargeInteger;
if (Status == STATUS_PENDING)
{
WaitForSingleObject(SockEvent, INFINITE);
+ Status = IOSB.Status;
}
NtClose( SockEvent );
- return 0;
+ return Status == STATUS_SUCCESS ? 0 : -1;
}
PSOCKET_INFORMATION
GetSocketStructure(SOCKET Handle)
{
- ULONG i;
+ PSOCKET_INFORMATION CurrentSocket;
+
+ EnterCriticalSection(&SocketListLock);
- for (i=0; i<SocketCount; i++)
+ CurrentSocket = SocketListHead;
+ while (CurrentSocket)
{
- if (Sockets[i]->Handle == Handle)
+ if (CurrentSocket->Handle == Handle)
{
- return Sockets[i];
+ LeaveCriticalSection(&SocketListLock);
+ return CurrentSocket;
}
+
+ CurrentSocket = CurrentSocket->NextSocket;
}
- return 0;
+
+ LeaveCriticalSection(&SocketListLock);
+
+ return NULL;
}
int CreateContext(PSOCKET_INFORMATION Socket)
if (Status == STATUS_PENDING)
{
WaitForSingleObject(SockEvent, INFINITE);
+ Status = IOSB.Status;
}
NtClose( SockEvent );
- return 0;
+ return Status == STATUS_SUCCESS ? 0 : -1;
}
BOOLEAN SockCreateOrReferenceAsyncThread(VOID)
/* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */
case AFD_EVENT_CONNECT:
+ case AFD_EVENT_CONNECT_FAIL:
if (0 != (Socket->SharedData.AsyncEvents & FD_CONNECT) &&
0 == (Socket->SharedData.AsyncDisabledEvents & FD_CONNECT))
{
if (lNetworkEvents & FD_CLOSE)
{
- AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_DISCONNECT | AFD_EVENT_ABORT;
+ AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_DISCONNECT | AFD_EVENT_ABORT | AFD_EVENT_CLOSE;
}
if (lNetworkEvents & FD_QOS)
/* Wait on new events */
AsyncData = HeapAlloc(GetProcessHeap(), 0, sizeof(ASYNC_DATA));
+ if (!AsyncData) return;
/* Create the Asynch Thread if Needed */
SockCreateOrReferenceAsyncThread();
/* Heap to use when allocating */
GlobalHeap = GetProcessHeap();
- /* Allocate Heap for 1024 Sockets, can be expanded later */
- Sockets = HeapAlloc(GetProcessHeap(), 0, sizeof(PSOCKET_INFORMATION) * 1024);
+ /* Initialize the lock that protects our socket list */
+ InitializeCriticalSection(&SocketListLock);
AFD_DbgPrint(MAX_TRACE, ("MSAFD.DLL has been loaded\n"));
break;
case DLL_PROCESS_DETACH:
+
+ /* Delete the socket list lock */
+ DeleteCriticalSection(&SocketListLock);
+
break;
}