WSPUPCALLTABLE Upcalls;
LPWPUCOMPLETEOVERLAPPEDREQUEST lpWPUCompleteOverlappedRequest;
ULONG SocketCount = 0;
-PSOCKET_INFORMATION *Sockets = NULL;
+PSOCKET_INFORMATION SocketListHead = NULL;
LIST_ENTRY SockHelpersListHead = { NULL, NULL };
ULONG SockAsyncThreadRefCount;
HANDLE SockAsyncHelperAfdHandle;
NULL);
/* Save in Process Sockets List */
- Sockets[SocketCount] = Socket;
- SocketCount ++;
+ Socket->NextSocket = SocketListHead;
+ SocketListHead = Socket;
/* Create the Socket Context */
CreateContext(Socket);
return INVALID_SOCKET;
}
+INT
+TranslateNtStatusError(NTSTATUS Status)
+{
+ switch (Status)
+ {
+ 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;
+
+ 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;
+ }
+}
DWORD MsafdReturnWithErrno(NTSTATUS Status,
LPINT Errno,
DWORD Received,
LPDWORD ReturnedBytes)
{
- if( ReturnedBytes )
- *ReturnedBytes = 0;
- if( Errno )
+ *Errno = TranslateNtStatusError(Status);
+
+ if (ReturnedBytes)
{
- 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 = WSAENOBUFS;
- break;
- case STATUS_INVALID_CONNECTION:
- DbgPrint("MSAFD: STATUS_INVALID_CONNECTION\n");
- *Errno = WSAEAFNOSUPPORT;
- break;
- case STATUS_INVALID_ADDRESS:
- DbgPrint("MSAFD: STATUS_INVALID_ADDRESS\n");
- *Errno = WSAEADDRNOTAVAIL;
- 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;
- }
+ if (!*Errno)
+ *ReturnedBytes = Received;
+ else
+ *ReturnedBytes = 0;
}
- /* Success */
- return Status == STATUS_SUCCESS ? 0 : SOCKET_ERROR;
+ return *Errno ? SOCKET_ERROR : 0;
}
/*
OUT LPINT lpErrno)
{
IO_STATUS_BLOCK IoStatusBlock;
- PSOCKET_INFORMATION Socket = NULL;
+ PSOCKET_INFORMATION Socket = NULL, CurrentSocket;
NTSTATUS Status;
HANDLE SockEvent;
AFD_DISCONNECT_INFO DisconnectInfo;
NtClose(Socket->TdiConnectionHandle);
Socket->TdiConnectionHandle = NULL;
+ 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;
+ }
+ }
+
+ HeapFree(GlobalHeap, 0, Socket);
+
/* Close the handle */
NtClose((HANDLE)Handle);
NtClose(SockEvent);
- return NO_ERROR;
+ return MsafdReturnWithErrno(Status, lpErrno, 0, NULL);
}
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 );
- HeapFree(GlobalHeap, 0, BindData);
- if (Status == STATUS_SUCCESS && (Socket->HelperEvents & WSH_NOTIFY_BIND))
+ if (Socket->HelperEvents & WSH_NOTIFY_BIND)
{
Status = Socket->HelperData->WSHNotify(Socket->HelperContext,
Socket->Handle,
{
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 (Status == STATUS_SUCCESS && (Socket->HelperEvents & WSH_NOTIFY_LISTEN))
+ if (Socket->HelperEvents & WSH_NOTIFY_LISTEN)
{
Status = Socket->HelperData->WSHNotify(Socket->HelperContext,
Socket->Handle,
if (Status == STATUS_PENDING)
{
WaitForSingleObject(SockEvent, INFINITE);
+ Status = IOSB.Status;
}
/* Clear the Structures */
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 */
}
}
+ 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))
if (Status == STATUS_PENDING)
{
WaitForSingleObject(SockEvent, INFINITE);
+ Status = IOSB.Status;
}
+ if (Status != STATUS_SUCCESS)
+ return -1;
+
/* Return Information */
if (Ulong != NULL)
{
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;
+
+ /* This is a special case */
+ if (SocketListHead->Handle == Handle)
+ return SocketListHead;
- for (i=0; i<SocketCount; i++)
+ CurrentSocket = SocketListHead;
+ while (CurrentSocket->NextSocket)
{
- if (Sockets[i]->Handle == Handle)
- {
- return Sockets[i];
- }
+ if (CurrentSocket->Handle == Handle)
+ return CurrentSocket;
+
+ CurrentSocket = CurrentSocket->NextSocket;
}
- return 0;
+
+ 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)
/* Heap to use when allocating */
GlobalHeap = GetProcessHeap();
- /* Allocate Heap for 1024 Sockets, can be expanded later */
- Sockets = HeapAlloc(GetProcessHeap(), 0, sizeof(PSOCKET_INFORMATION) * 1024);
- if (!Sockets) return FALSE;
-
AFD_DbgPrint(MAX_TRACE, ("MSAFD.DLL has been loaded\n"));
break;