tcpip: fix for udp socket close.

ws2_32: unstub WSAFDIsSet, small amount of work on select
msafd: select fixes
afd: major select overhaul
- 1 exit point for poll objects from the deviceext
- make sure to cancel the timer
- UpdatePollWithFCB now runs at DISPATCH_LEVEL in every case
- Added handle locks so we can signal and check handles properly

svn path=/trunk/; revision=11684
This commit is contained in:
Art Yerkes 2004-11-17 05:17:22 +00:00
parent 4a7d199e30
commit 2c9bba03b5
11 changed files with 342 additions and 274 deletions

View file

@ -1,4 +1,4 @@
/* $Id: lock.c,v 1.6 2004/11/15 18:24:57 arty Exp $
/* $Id: lock.c,v 1.7 2004/11/17 05:17:22 arty Exp $
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/net/afd/afd/lock.c
@ -114,6 +114,40 @@ VOID UnlockBuffers( PAFD_WSABUF Buf, UINT Count, BOOL Address ) {
ExFreePool( Buf );
}
/* Produce a kernel-land handle array with handles replaced by object
* pointers. This will allow the system to do proper alerting */
PAFD_HANDLE LockHandles( PAFD_HANDLE HandleArray, UINT HandleCount ) {
UINT i;
NTSTATUS Status;
PAFD_HANDLE FileObjects = ExAllocatePool
( NonPagedPool, HandleCount * sizeof(AFD_HANDLE) );
for( i = 0; FileObjects && i < HandleCount; i++ ) {
HandleArray[i].Status = 0;
HandleArray[i].Events = HandleArray[i].Events;
Status = ObReferenceObjectByHandle
( (PVOID)HandleArray[i].Handle,
FILE_ALL_ACCESS,
NULL,
KernelMode,
(PVOID*)&FileObjects[i].Handle,
NULL );
}
return FileObjects;
}
VOID UnlockHandles( PAFD_HANDLE HandleArray, UINT HandleCount ) {
UINT i;
for( i = 0; i < HandleCount; i++ ) {
ObDereferenceObject( (PVOID)HandleArray[i].Handle );
}
ExFreePool( HandleArray );
}
/* Returns transitioned state or SOCKET_STATE_INVALID_TRANSITION */
UINT SocketAcquireStateLock( PAFD_FCB FCB ) {
NTSTATUS Status = STATUS_SUCCESS;

View file

@ -1,4 +1,4 @@
/* $Id: main.c,v 1.11 2004/11/16 18:07:57 chorns Exp $
/* $Id: main.c,v 1.12 2004/11/17 05:17:22 arty Exp $
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/net/afd/afd/main.c
@ -212,6 +212,9 @@ AfdCloseSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp,
AFD_DbgPrint(MID_TRACE,("FCB %x\n", FCB));
FileObject->FsContext = NULL;
FCB->PollState |= AFD_EVENT_CLOSE;
PollReeval( FCB->DeviceExt, FileObject );
DestroySocket( FCB );
Irp->IoStatus.Status = STATUS_SUCCESS;

View file

@ -1,4 +1,4 @@
/* $Id: read.c,v 1.10 2004/11/15 18:24:57 arty Exp $
/* $Id: read.c,v 1.11 2004/11/17 05:17:22 arty Exp $
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/net/afd/afd/read.c
@ -416,7 +416,8 @@ PacketSocketRecvComplete(
AFD_DbgPrint(MID_TRACE,("Signalling\n"));
FCB->PollState |= AFD_EVENT_RECEIVE;
PollReeval( FCB->DeviceExt, FCB->FileObject );
}
} else
FCB->PollState &= ~AFD_EVENT_RECEIVE;
if( NT_SUCCESS(Irp->IoStatus.Status) ) {
/* Now relaunch the datagram request */
@ -483,9 +484,6 @@ AfdPacketSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
return UnlockAndMaybeComplete
( FCB, Status, Irp, RecvReq->BufferArray[0].len, NULL, TRUE );
} else {
if( IsListEmpty( &FCB->DatagramList ) )
FCB->PollState &= ~AFD_EVENT_RECEIVE;
Status = SatisfyPacketRecvRequest
( FCB, Irp, DatagramRecv,
(PUINT)&Irp->IoStatus.Information );
@ -493,10 +491,12 @@ AfdPacketSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
( FCB, Status, Irp, Irp->IoStatus.Information, NULL, TRUE );
}
} else if( RecvReq->AfdFlags & AFD_IMMEDIATE ) {
FCB->PollState &= ~AFD_EVENT_RECEIVE;
AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
Status = STATUS_CANT_WAIT;
return UnlockAndMaybeComplete( FCB, Status, Irp, 0, NULL, TRUE );
} else {
FCB->PollState &= ~AFD_EVENT_RECEIVE;
return LeaveIrpUntilLater( FCB, Irp, FUNCTION_RECV );
}
}

View file

@ -1,4 +1,4 @@
/* $Id: select.c,v 1.5 2004/11/15 18:24:57 arty Exp $
/* $Id: select.c,v 1.6 2004/11/17 05:17:22 arty Exp $
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/net/afd/afd/select.c
@ -26,58 +26,36 @@ VOID ZeroEvents( PAFD_HANDLE HandleArray,
UINT HandleCount ) {
UINT i;
for( i = 0; i < HandleCount; i++ ) {
HandleArray[i].Events = 0;
for( i = 0; i < HandleCount; i++ )
HandleArray[i].Status = 0;
}
}
NTSTATUS STDCALL
ScanForImmediateTrigger( PAFD_HANDLE HandleArray,
UINT HandleCount,
PUINT HandlesSet ) {
NTSTATUS Status = STATUS_SUCCESS;
PFILE_OBJECT FileObject;
PAFD_FCB FCB;
UINT i;
BOOLEAN ShouldReturnNow = FALSE;
VOID RemoveSelect( PAFD_ACTIVE_POLL Poll ) {
AFD_DbgPrint(MID_TRACE,("Called\n"));
for( i = 0; i < HandleCount && NT_SUCCESS(Status); i++ ) {
HandleArray[i].Status = 0;
Status =
ObReferenceObjectByHandle
( (PVOID)HandleArray[i].Handle,
FILE_ALL_ACCESS,
NULL,
KernelMode,
(PVOID*)&FileObject,
NULL );
RemoveEntryList( &Poll->ListEntry );
KeCancelTimer( &Poll->Timer );
if( NT_SUCCESS(Status) ) {
FCB = FileObject->FsContext;
/* Check select bits */
AFD_DbgPrint(MID_TRACE,("Locking socket state\n"));
ExFreePool( Poll );
if( !SocketAcquireStateLock( FCB ) ) {
AFD_DbgPrint(MID_TRACE,("Failed to get a socket state\n"));
Status = STATUS_UNSUCCESSFUL;
} else {
AFD_DbgPrint(MID_TRACE,("Got a socket state\n"));
Status = STATUS_SUCCESS;
HandleArray[i].Status =
FCB->PollState & HandleArray[i].Events;
if( HandleArray[i].Status ) ShouldReturnNow = TRUE;
ObDereferenceObject( (PVOID)HandleArray[i].Handle );
AFD_DbgPrint(MID_TRACE,("Unlocking\n"));
SocketStateUnlock( FCB );
AFD_DbgPrint(MID_TRACE,("Unlocked\n"));
}
}
}
AFD_DbgPrint(MID_TRACE,("Done\n"));
}
if( !NT_SUCCESS(Status) || ShouldReturnNow ) return Status;
else return STATUS_PENDING;
VOID SignalSocket( PAFD_ACTIVE_POLL Poll, PAFD_POLL_INFO PollReq,
NTSTATUS Status, UINT Collected ) {
PIRP Irp = Poll->Irp;
AFD_DbgPrint(MID_TRACE,("Called (Status %x Events %d)\n",
Status, Collected));
Poll->Irp->IoStatus.Status = Status;
Poll->Irp->IoStatus.Information = Collected;
CopyBackStatus( PollReq->Handles,
PollReq->HandleCount );
UnlockHandles( PollReq->InternalUse, PollReq->HandleCount );
AFD_DbgPrint(MID_TRACE,("Completing\n"));
IoCompleteRequest( Irp, IO_NETWORK_INCREMENT );
RemoveEntryList( &Poll->ListEntry );
RemoveSelect( Poll );
AFD_DbgPrint(MID_TRACE,("Done\n"));
}
VOID SelectTimeout( PKDPC Dpc,
@ -86,33 +64,31 @@ VOID SelectTimeout( PKDPC Dpc,
PVOID SystemArgument2 ) {
PAFD_ACTIVE_POLL Poll = DeferredContext;
PAFD_POLL_INFO PollReq;
PAFD_DEVICE_EXTENSION DeviceExt;
PIRP Irp;
KIRQL OldIrql;
PAFD_DEVICE_EXTENSION DeviceExt;
AFD_DbgPrint(MID_TRACE,("Called\n"));
Irp = Poll->Irp;
DeviceExt = Poll->DeviceExt;
PollReq = Irp->AssociatedIrp.SystemBuffer;
KeAcquireSpinLock( &DeviceExt->Lock, &OldIrql );
RemoveEntryList( &Poll->ListEntry );
KeReleaseSpinLock( &DeviceExt->Lock, OldIrql );
ExFreePool( Poll );
ZeroEvents( PollReq->Handles, PollReq->HandleCount );
Irp->IoStatus.Status = STATUS_TIMEOUT;
Irp->IoStatus.Information = -1;
KeAcquireSpinLock( &DeviceExt->Lock, &OldIrql );
SignalSocket( Poll, PollReq, STATUS_TIMEOUT, 0 );
KeReleaseSpinLock( &DeviceExt->Lock, OldIrql );
IoCompleteRequest( Irp, IO_NO_INCREMENT );
AFD_DbgPrint(MID_TRACE,("Timeout\n"));
}
NTSTATUS STDCALL
AfdSelect( PDEVICE_OBJECT DeviceObject, PIRP Irp,
PIO_STACK_LOCATION IrpSp ) {
NTSTATUS Status = STATUS_NO_MEMORY;
PAFD_FCB FCB;
PFILE_OBJECT FileObject;
PAFD_POLL_INFO PollReq = Irp->AssociatedIrp.SystemBuffer;
PAFD_DEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension;
PAFD_ACTIVE_POLL Poll = NULL;
@ -120,115 +96,122 @@ AfdSelect( PDEVICE_OBJECT DeviceObject, PIRP Irp,
UINT AllocSize =
CopySize + sizeof(AFD_ACTIVE_POLL) - sizeof(AFD_POLL_INFO);
KIRQL OldIrql;
UINT HandlesSignalled;
UINT i, Signalled = 0;
AFD_DbgPrint(MID_TRACE,("Called (HandleCount %d Timeout %d)\n",
PollReq->HandleCount,
(INT)(PollReq->Timeout.QuadPart * -1)));
(INT)(PollReq->Timeout.QuadPart)));
Status = ScanForImmediateTrigger( PollReq->Handles,
PollReq->HandleCount,
&HandlesSignalled );
if( Status == STATUS_PENDING ) {
Poll = ExAllocatePool( NonPagedPool, AllocSize );
if( Poll ) {
KeAcquireSpinLock( &DeviceExt->Lock, &OldIrql );
KeInitializeDpc( (PRKDPC)&Poll->TimeoutDpc,
(PKDEFERRED_ROUTINE)SelectTimeout,
Poll );
PollReq->Timeout.QuadPart *= -1;
/* Negative values are relative */
KeInitializeTimerEx( &Poll->Timer, NotificationTimer );
KeSetTimer( &Poll->Timer, PollReq->Timeout, &Poll->TimeoutDpc );
Poll->Irp = Irp;
Poll->DeviceExt = DeviceExt;
PollReq->InternalUse =
LockHandles( PollReq->Handles, PollReq->HandleCount );
InsertTailList( &DeviceExt->Polls, &Poll->ListEntry );
Status = STATUS_PENDING;
KeReleaseSpinLock( &DeviceExt->Lock, OldIrql );
} else Status = STATUS_NO_MEMORY;
} else if( Status == STATUS_SUCCESS ) {
CopyBackStatus( PollReq->Handles,
PollReq->HandleCount );
} else {
ZeroEvents( PollReq->Handles,
PollReq->HandleCount );
if( !PollReq->InternalUse ) {
Irp->IoStatus.Status = STATUS_NO_MEMORY;
Irp->IoStatus.Information = -1;
IoCompleteRequest( Irp, IO_NETWORK_INCREMENT );
return Irp->IoStatus.Status;
}
ZeroEvents( PollReq->Handles,
PollReq->HandleCount );
Poll = ExAllocatePool( NonPagedPool, AllocSize );
if( Poll ) {
Poll->Irp = Irp;
Poll->DeviceExt = DeviceExt;
KeInitializeTimerEx( &Poll->Timer, NotificationTimer );
KeSetTimer( &Poll->Timer, PollReq->Timeout, &Poll->TimeoutDpc );
KeInitializeDpc( (PRKDPC)&Poll->TimeoutDpc,
(PKDEFERRED_ROUTINE)SelectTimeout,
Poll );
KeAcquireSpinLock( &DeviceExt->Lock, &OldIrql );
InsertTailList( &DeviceExt->Polls, &Poll->ListEntry );
for( i = 0; i < PollReq->HandleCount; i++ ) {
if( !PollReq->InternalUse[i].Handle ) continue;
FileObject = (PFILE_OBJECT)PollReq->InternalUse[i].Handle;
FCB = FileObject->FsContext;
if( (FCB->PollState & AFD_EVENT_CLOSE) ||
(PollReq->Handles[i].Status & AFD_EVENT_CLOSE) ) {
PollReq->InternalUse[i].Handle = 0;
PollReq->Handles[i].Events = 0;
PollReq->Handles[i].Status = AFD_EVENT_CLOSE;
Signalled++;
} else {
PollReq->Handles[i].Status =
PollReq->Handles[i].Events & FCB->PollState;
if( PollReq->Handles[i].Status ) {
AFD_DbgPrint(MID_TRACE,("Signalling %x with %x\n",
FCB, FCB->PollState));
Signalled++;
}
}
}
if( Signalled ) {
Status = STATUS_SUCCESS;
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = Signalled;
SignalSocket( Poll, PollReq, Status, Signalled );
} else {
Status = STATUS_PENDING;
IoMarkIrpPending( Irp );
}
KeReleaseSpinLock( &DeviceExt->Lock, OldIrql );
} else Status = STATUS_NO_MEMORY;
AFD_DbgPrint(MID_TRACE,("Returning %x\n", Status));
if( Status == STATUS_PENDING )
IoMarkIrpPending( Irp );
else {
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = HandlesSignalled;
IoCompleteRequest( Irp, IO_NETWORK_INCREMENT );
}
return Status;
}
VOID SignalSocket( PAFD_ACTIVE_POLL Poll, PAFD_POLL_INFO PollReq, UINT i ) {
/* One of the files was destroyed. We return now with error. */
Poll->Irp->IoStatus.Status = STATUS_SUCCESS; /* XXX REVISIT */
Poll->Irp->IoStatus.Information = 1;
CopyBackStatus( PollReq->Handles,
PollReq->HandleCount );
IoCompleteRequest( Poll->Irp, IO_NETWORK_INCREMENT );
}
/* * * NOTE ALWAYS CALLED AT DISPATCH_LEVEL * * */
BOOLEAN UpdatePollWithFCB( PAFD_ACTIVE_POLL Poll, PFILE_OBJECT FileObject ) {
UINT i;
NTSTATUS Status;
PFILE_OBJECT TargetFile;
PAFD_FCB FCB;
UINT Signalled = 0;
PAFD_POLL_INFO PollReq = Poll->Irp->AssociatedIrp.SystemBuffer;
ASSERT( KeGetCurrentIrql() == DISPATCH_LEVEL );
for( i = 0; i < PollReq->HandleCount; i++ ) {
Status =
ObReferenceObjectByHandle
( (PVOID)PollReq->Handles[i].Handle,
FILE_ALL_ACCESS,
NULL,
KernelMode,
(PVOID*)&TargetFile,
NULL );
if( !PollReq->InternalUse[i].Handle ) continue;
FileObject = (PFILE_OBJECT)PollReq->InternalUse[i].Handle;
FCB = FileObject->FsContext;
if( !NT_SUCCESS(Status) ) {
if( (FCB->PollState & AFD_EVENT_CLOSE) ||
(PollReq->Handles[i].Status & AFD_EVENT_CLOSE) ) {
PollReq->InternalUse[i].Handle = 0;
PollReq->Handles[i].Events = 0;
PollReq->Handles[i].Status = AFD_EVENT_CLOSE;
SignalSocket( Poll, PollReq, i );
return TRUE;
Signalled++;
} else {
FCB = FileObject->FsContext;
AFD_DbgPrint(MID_TRACE,("Locking socket state\n"));
if( !SocketAcquireStateLock( FCB ) ) {
PollReq->Handles[i].Status = AFD_EVENT_CLOSE;
SignalSocket( Poll, PollReq, i );
} else {
PollReq->Handles[i].Status =
PollReq->Handles[i].Events & FCB->PollState;
if( PollReq->Handles[i].Status )
SignalSocket( Poll, PollReq, i );
SocketStateUnlock( FCB );
PollReq->Handles[i].Status =
PollReq->Handles[i].Events & FCB->PollState;
if( PollReq->Handles[i].Status ) {
AFD_DbgPrint(MID_TRACE,("Signalling %x with %x\n",
FCB, FCB->PollState));
Signalled++;
}
return TRUE;
}
}
return FALSE;
return Signalled ? 1 : 0;
}
VOID PollReeval( PAFD_DEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject ) {
PAFD_ACTIVE_POLL Poll = NULL;
PLIST_ENTRY ThePollEnt = NULL;
KIRQL OldIrql;
PAFD_POLL_INFO PollReq;
AFD_DbgPrint(MID_TRACE,("Called: DeviceExt %x FileObject %x\n",
DeviceExt, FileObject));
@ -239,9 +222,13 @@ VOID PollReeval( PAFD_DEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject ) {
while( ThePollEnt != &DeviceExt->Polls ) {
Poll = CONTAINING_RECORD( ThePollEnt, AFD_ACTIVE_POLL, ListEntry );
PollReq = Poll->Irp->AssociatedIrp.SystemBuffer;
AFD_DbgPrint(MID_TRACE,("Checking poll %x\n", Poll));
if( UpdatePollWithFCB( Poll, FileObject ) ) {
ThePollEnt = ThePollEnt->Flink;
RemoveEntryList( &Poll->ListEntry );
AFD_DbgPrint(MID_TRACE,("Signalling socket\n"));
SignalSocket( Poll, PollReq, STATUS_SUCCESS, 1 );
} else
ThePollEnt = ThePollEnt->Flink;
}

View file

@ -1,4 +1,4 @@
/* $Id: afd.h,v 1.23 2004/11/15 18:24:57 arty Exp $
/* $Id: afd.h,v 1.24 2004/11/17 05:17:22 arty Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -186,6 +186,8 @@ NTSTATUS DDKAPI UnlockAndMaybeComplete
BOOL ShouldUnlockIrp );
VOID SocketStateUnlock( PAFD_FCB FCB );
NTSTATUS LostSocket( PIRP Irp, BOOL ShouldUnlockIrp );
PAFD_HANDLE LockHandles( PAFD_HANDLE HandleArray, UINT HandleCount );
VOID UnlockHandles( PAFD_HANDLE HandleArray, UINT HandleCount );
PVOID LockRequest( PIRP Irp, PIO_STACK_LOCATION IrpSp );
VOID UnlockRequest( PIRP Irp, PIO_STACK_LOCATION IrpSp );
VOID SocketCalloutEnter( PAFD_FCB FCB );

View file

@ -160,7 +160,6 @@ VOID DeleteAddress(PADDRESS_FILE AddrFile)
/* Abort the request and free its resources */
TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql);
(*ReceiveRequest->Complete)(ReceiveRequest->Context, STATUS_ADDRESS_CLOSED, 0);
ExFreePool(ReceiveRequest);
TcpipAcquireSpinLock(&AddrFile->Lock, &OldIrql);
CurrentEntry = NextEntry;
}

View file

@ -9,7 +9,7 @@
*/
#include "precomp.h"
//#define NDEBUG
#define NDEBUG
#ifndef NDEBUG
DWORD DebugTraceLevel = 0x7fffffff;

View file

@ -413,113 +413,142 @@ WSPSelect(
struct timeval *timeout,
LPINT lpErrno)
{
IO_STATUS_BLOCK IOSB;
PAFD_POLL_INFO PollInfo;
NTSTATUS Status;
ULONG HandleCount;
ULONG PollBufferSize;
LARGE_INTEGER uSec;
PVOID PollBuffer;
ULONG i, j = 0;
HANDLE SockEvent;
IO_STATUS_BLOCK IOSB;
PAFD_POLL_INFO PollInfo;
NTSTATUS Status;
ULONG HandleCount, OutCount = 0;
ULONG PollBufferSize;
LARGE_INTEGER uSec;
PVOID PollBuffer;
ULONG i, j = 0, x;
HANDLE SockEvent;
Status = NtCreateEvent( &SockEvent, GENERIC_READ | GENERIC_WRITE,
NULL, 1, FALSE );
if( !NT_SUCCESS(Status) ) return -1;
/* Find out how many sockets we have, and how large the buffer needs
* to be */
HandleCount =
( readfds ? readfds->fd_count : 0 ) +
( writefds ? writefds->fd_count : 0 ) +
( exceptfds ? exceptfds->fd_count : 0 );
PollBufferSize = sizeof(*PollInfo) +
(HandleCount * sizeof(AFD_HANDLE));
/* Allocate */
PollBuffer = HeapAlloc(GlobalHeap, 0, PollBufferSize);
PollInfo = (PAFD_POLL_INFO)PollBuffer;
RtlZeroMemory( PollInfo, PollBufferSize );
Status = NtCreateEvent( &SockEvent, GENERIC_READ | GENERIC_WRITE,
NULL, 1, FALSE );
if( !NT_SUCCESS(Status) ) return -1;
/* Find out how many sockets we have, and how large the buffer needs to be */
HandleCount = ( readfds ? readfds->fd_count : 0 ) +
( writefds ? writefds->fd_count : 0 ) +
( exceptfds ? exceptfds->fd_count : 0 );
PollBufferSize = sizeof(*PollInfo) + (HandleCount * sizeof(AFD_HANDLE));
/* Allocate */
PollBuffer = HeapAlloc(GlobalHeap, 0, PollBufferSize);
PollInfo = (PAFD_POLL_INFO)PollBuffer;
/* Convert Timeout to NT Format */
if (timeout == NULL) {
PollInfo->Timeout.u.LowPart = -1;
PollInfo->Timeout.u.HighPart = 0x7FFFFFFF;
} else {
PollInfo->Timeout = RtlEnlargedIntegerMultiply(timeout->tv_sec, -10000000);
uSec = RtlEnlargedIntegerMultiply(timeout->tv_usec, -10);
PollInfo->Timeout.QuadPart += uSec.QuadPart;
/* Convert Timeout to NT Format */
if (timeout == NULL) {
PollInfo->Timeout.u.LowPart = -1;
PollInfo->Timeout.u.HighPart = 0x7FFFFFFF;
} else {
PollInfo->Timeout = RtlEnlargedIntegerMultiply
((timeout->tv_sec * 1000) + timeout->tv_usec, -10000);
PollInfo->Timeout.QuadPart += uSec.QuadPart;
}
/* Number of handles for AFD to Check */
PollInfo->HandleCount = HandleCount;
PollInfo->InternalUse = 0;
if (readfds != NULL) {
for (i = 0; i < readfds->fd_count; i++, j++) {
PollInfo->Handles[j].Handle = readfds->fd_array[i];
PollInfo->Handles[j].Events = AFD_EVENT_RECEIVE | AFD_EVENT_DISCONNECT | AFD_EVENT_ABORT;
}
}
if (writefds != NULL) {
for (i = 0; i < writefds->fd_count; i++, j++) {
PollInfo->Handles[j].Handle = writefds->fd_array[i];
PollInfo->Handles[j].Events |= AFD_EVENT_SEND;
}
/* Number of handles for AFD to Check */
PollInfo->HandleCount = HandleCount;
PollInfo->Unknown = 0;
if (readfds != NULL) {
for (i = 0; i < readfds->fd_count; i++, j++) {
PollInfo->Handles[j].Handle = readfds->fd_array[i];
PollInfo->Handles[j].Events = AFD_EVENT_RECEIVE | AFD_EVENT_DISCONNECT | AFD_EVENT_ABORT;
}
} else if (writefds != NULL) {
for (i = 0; i < writefds->fd_count; i++, j++) {
PollInfo->Handles[j].Handle = writefds->fd_array[i];
PollInfo->Handles[j].Events = AFD_EVENT_SEND;
}
} else if (exceptfds != NULL) {
for (i = 0; i < exceptfds->fd_count; i++, j++) {
PollInfo->Handles[j].Handle = exceptfds->fd_array[i];
PollInfo->Handles[j].Events = AFD_EVENT_OOB_RECEIVE | AFD_EVENT_CONNECT_FAIL;
}
}
if (exceptfds != NULL) {
for (i = 0; i < exceptfds->fd_count; i++, j++) {
PollInfo->Handles[j].Handle = exceptfds->fd_array[i];
PollInfo->Handles[j].Events |=
AFD_EVENT_OOB_RECEIVE | AFD_EVENT_CONNECT_FAIL;
}
}
/* Send IOCTL */
Status = NtDeviceIoControlFile( (HANDLE)Sockets[0]->Handle,
SockEvent,
NULL,
NULL,
&IOSB,
IOCTL_AFD_SELECT,
PollInfo,
PollBufferSize,
PollInfo,
PollBufferSize);
/* Send IOCTL */
Status = NtDeviceIoControlFile( (HANDLE)Sockets[0]->Handle,
SockEvent,
NULL,
NULL,
&IOSB,
IOCTL_AFD_SELECT,
PollInfo,
PollBufferSize,
PollInfo,
PollBufferSize);
/* Wait for Completition */
if (Status == STATUS_PENDING) {
WaitForSingleObject(SockEvent, 0);
AFD_DbgPrint(MID_TRACE,("DeviceIoControlFile => %x\n", Status));
/* Wait for Completition */
if (Status == STATUS_PENDING) {
WaitForSingleObject(SockEvent, 0);
}
/* Clear the Structures */
if( readfds ) FD_ZERO(readfds);
if( writefds ) FD_ZERO(writefds);
if( exceptfds ) FD_ZERO(exceptfds);
/* Loop through return structure */
HandleCount = PollInfo->HandleCount;
/* Return in FDSET Format */
for (i = 0; i < HandleCount; i++) {
for(x = 1; x; x<<=1) {
switch (PollInfo->Handles[i].Events & x) {
case AFD_EVENT_RECEIVE:
case AFD_EVENT_DISCONNECT:
case AFD_EVENT_ABORT:
case AFD_EVENT_ACCEPT:
case AFD_EVENT_CLOSE:
AFD_DbgPrint(MID_TRACE,("Event %x on handle %x\n",
PollInfo->Handles[i].Events,
PollInfo->Handles[i].Handle));
OutCount++;
if( readfds ) FD_SET(PollInfo->Handles[i].Handle, readfds);
case AFD_EVENT_SEND: case AFD_EVENT_CONNECT:
AFD_DbgPrint(MID_TRACE,("Event %x on handle %x\n",
PollInfo->Handles[i].Events,
PollInfo->Handles[i].Handle));
OutCount++;
if( writefds ) FD_SET(PollInfo->Handles[i].Handle, writefds);
break;
case AFD_EVENT_OOB_RECEIVE: case AFD_EVENT_CONNECT_FAIL:
AFD_DbgPrint(MID_TRACE,("Event %x on handle %x\n",
PollInfo->Handles[i].Events,
PollInfo->Handles[i].Handle));
OutCount++;
if( exceptfds ) FD_SET(PollInfo->Handles[i].Handle, exceptfds);
break;
}
}
}
/* Clear the Structures */
readfds ? FD_ZERO(readfds) : 0;
writefds ? FD_ZERO(writefds) : 0;
exceptfds ? FD_ZERO(exceptfds) : 0;
NtClose( SockEvent );
switch( IOSB.Status ) {
case STATUS_SUCCESS:
case STATUS_TIMEOUT: *lpErrno = 0; break;
default: *lpErrno = WSAEINVAL;
}
/* Loop through return structure */
HandleCount = PollInfo->HandleCount;
/* Return in FDSET Format */
for (i = 0; i < HandleCount; i++) {
switch (PollInfo->Handles[i].Events) {
case AFD_EVENT_RECEIVE:
case AFD_EVENT_DISCONNECT:
case AFD_EVENT_ABORT:
case AFD_EVENT_ACCEPT:
case AFD_EVENT_CLOSE:
FD_SET(PollInfo->Handles[i].Handle, readfds);
break;
case AFD_EVENT_SEND: case AFD_EVENT_CONNECT:
FD_SET(PollInfo->Handles[i].Handle, writefds);
break;
case AFD_EVENT_OOB_RECEIVE: case AFD_EVENT_CONNECT_FAIL:
FD_SET(PollInfo->Handles[i].Handle, exceptfds);
break;
}
}
NtClose( SockEvent );
return 0;
AFD_DbgPrint(MID_TRACE,("%d events\n", OutCount));
return OutCount;
}
SOCKET

View file

@ -1,4 +1,4 @@
# $Id: makefile,v 1.17 2004/10/23 21:05:11 chorns Exp $
# $Id: makefile,v 1.18 2004/11/17 05:17:21 arty Exp $
PATH_TO_TOP = ../..
@ -19,7 +19,6 @@ TARGET_CFLAGS = \
-fno-builtin \
-DUNICODE \
-DLE \
-DDBG \
-D__USE_W32API
# require os code to explicitly request A/W version of structs/functions

View file

@ -7,6 +7,7 @@
* REVISIONS:
* CSH 01/09-2000 Created
*/
#include <roscfg.h>
#include <w32api.h>
#include <ws2_32.h>
#include <catalog.h>
@ -18,6 +19,7 @@
/* See debug.h for debug/trace constants */
DWORD DebugTraceLevel = MIN_TRACE;
//DWORD DebugTraceLevel = MAX_TRACE;
//DWORD DebugTraceLevel = DEBUG_ULTRA;
#endif /* DBG */
@ -339,6 +341,7 @@ select(
if (!WSAINITIALIZED) {
WSASetLastError(WSANOTINITIALISED);
WS_DbgPrint(MID_TRACE,("Not initialized\n"));
return SOCKET_ERROR;
}
@ -348,33 +351,48 @@ select(
if ((readfds != NULL) && (readfds->fd_count > 0)) {
if (!ReferenceProviderByHandle((HANDLE)readfds->fd_array[0], &Provider)) {
WSASetLastError(WSAENOTSOCK);
WS_DbgPrint(MID_TRACE,("No provider (read)\n"));
return SOCKET_ERROR;
}
} else if ((writefds != NULL) && (writefds->fd_count > 0)) {
if (!ReferenceProviderByHandle((HANDLE)writefds->fd_array[0], &Provider)) {
WSASetLastError(WSAENOTSOCK);
WS_DbgPrint(MID_TRACE,("No provider (write)\n"));
return SOCKET_ERROR;
}
} else if ((exceptfds != NULL) && (exceptfds->fd_count > 0)) {
if (!ReferenceProviderByHandle((HANDLE)exceptfds->fd_array[0], &Provider)) {
WSASetLastError(WSAENOTSOCK);
WS_DbgPrint(MID_TRACE,("No provider (err)\n"));
return SOCKET_ERROR;
}
#if 0 /* XXX empty select is not an error */
} else {
WSASetLastError(WSAEINVAL);
return SOCKET_ERROR;
#endif
}
Count = Provider->ProcTable.lpWSPSelect(
nfds, readfds, writefds, exceptfds, (LPTIMEVAL)timeout, &Errno);
WS_DbgPrint(MAX_TRACE, ("Provider (0x%X).\n", Provider));
DereferenceProviderByPointer(Provider);
if (Errno != NO_ERROR) {
WSASetLastError(Errno);
return SOCKET_ERROR;
if( !Provider ) {
if( timeout ) {
WS_DbgPrint(MID_TRACE,("Select: used as timer\n"));
Sleep( timeout->tv_sec * 1000 + (timeout->tv_usec / 1000) );
}
return 0;
} else {
WS_DbgPrint(MID_TRACE,("Calling WSPSelect\n"));
Count = Provider->ProcTable.lpWSPSelect(
nfds, readfds, writefds, exceptfds, (LPTIMEVAL)timeout, &Errno);
WS_DbgPrint(MAX_TRACE, ("[%x] Select: Count %d Errno %x\n",
Provider, Count, Errno));
DereferenceProviderByPointer(Provider);
if (Errno != NO_ERROR) {
WSASetLastError(Errno);
return SOCKET_ERROR;
}
}
return Count;
@ -630,6 +648,20 @@ WSAIoctl(
return Status;
}
/*
* @implemented
*/
INT
EXPORT
__WSAFDIsSet(SOCKET s, LPFD_SET set)
{
int i;
for( i = 0; i < set->fd_count; i++ )
if( set->fd_array[i] == s ) return TRUE;
return FALSE;
}
BOOL
STDCALL

View file

@ -636,23 +636,6 @@ WSACancelAsyncRequest(
return 0;
}
/*
* @unimplemented
*/
INT
#if 0
PASCAL FAR
#else
EXPORT
#endif
__WSAFDIsSet(SOCKET s, LPFD_SET set)
{
UNIMPLEMENTED
return 0;
}
/* WinSock Service Provider support functions */
/*