From 2c9bba03b50c1fa804d5f313f7fae15d67362cb6 Mon Sep 17 00:00:00 2001 From: Art Yerkes Date: Wed, 17 Nov 2004 05:17:22 +0000 Subject: [PATCH] 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 --- reactos/drivers/net/afd/afd/lock.c | 36 ++- reactos/drivers/net/afd/afd/main.c | 5 +- reactos/drivers/net/afd/afd/read.c | 10 +- reactos/drivers/net/afd/afd/select.c | 259 ++++++++++----------- reactos/drivers/net/afd/include/afd.h | 4 +- reactos/drivers/net/tcpip/tcpip/fileobjs.c | 1 - reactos/drivers/net/tcpip/tcpip/main.c | 2 +- reactos/lib/msafd/misc/dllmain.c | 227 ++++++++++-------- reactos/lib/ws2_32/makefile | 3 +- reactos/lib/ws2_32/misc/dllmain.c | 52 ++++- reactos/lib/ws2_32/misc/stubs.c | 17 -- 11 files changed, 342 insertions(+), 274 deletions(-) diff --git a/reactos/drivers/net/afd/afd/lock.c b/reactos/drivers/net/afd/afd/lock.c index 6f65fd898f7..64256488367 100644 --- a/reactos/drivers/net/afd/afd/lock.c +++ b/reactos/drivers/net/afd/afd/lock.c @@ -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; diff --git a/reactos/drivers/net/afd/afd/main.c b/reactos/drivers/net/afd/afd/main.c index f35d1286828..a8fa98f6d58 100644 --- a/reactos/drivers/net/afd/afd/main.c +++ b/reactos/drivers/net/afd/afd/main.c @@ -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; diff --git a/reactos/drivers/net/afd/afd/read.c b/reactos/drivers/net/afd/afd/read.c index 04cd52d7204..d2e19df75b1 100644 --- a/reactos/drivers/net/afd/afd/read.c +++ b/reactos/drivers/net/afd/afd/read.c @@ -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 ); } } diff --git a/reactos/drivers/net/afd/afd/select.c b/reactos/drivers/net/afd/afd/select.c index b714c3597b2..9258643b1d3 100644 --- a/reactos/drivers/net/afd/afd/select.c +++ b/reactos/drivers/net/afd/afd/select.c @@ -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; } diff --git a/reactos/drivers/net/afd/include/afd.h b/reactos/drivers/net/afd/include/afd.h index 4c1dc463c5c..73fbb191628 100644 --- a/reactos/drivers/net/afd/include/afd.h +++ b/reactos/drivers/net/afd/include/afd.h @@ -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 ); diff --git a/reactos/drivers/net/tcpip/tcpip/fileobjs.c b/reactos/drivers/net/tcpip/tcpip/fileobjs.c index 65ca49b3bc2..142bf3f8e07 100644 --- a/reactos/drivers/net/tcpip/tcpip/fileobjs.c +++ b/reactos/drivers/net/tcpip/tcpip/fileobjs.c @@ -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; } diff --git a/reactos/drivers/net/tcpip/tcpip/main.c b/reactos/drivers/net/tcpip/tcpip/main.c index 230e0ef00c4..6267659e050 100644 --- a/reactos/drivers/net/tcpip/tcpip/main.c +++ b/reactos/drivers/net/tcpip/tcpip/main.c @@ -9,7 +9,7 @@ */ #include "precomp.h" -//#define NDEBUG +#define NDEBUG #ifndef NDEBUG DWORD DebugTraceLevel = 0x7fffffff; diff --git a/reactos/lib/msafd/misc/dllmain.c b/reactos/lib/msafd/misc/dllmain.c index 71fa58ce901..0f571883bd2 100644 --- a/reactos/lib/msafd/misc/dllmain.c +++ b/reactos/lib/msafd/misc/dllmain.c @@ -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 diff --git a/reactos/lib/ws2_32/makefile b/reactos/lib/ws2_32/makefile index 6f8e66405f2..e9a10e0297b 100644 --- a/reactos/lib/ws2_32/makefile +++ b/reactos/lib/ws2_32/makefile @@ -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 diff --git a/reactos/lib/ws2_32/misc/dllmain.c b/reactos/lib/ws2_32/misc/dllmain.c index 96edc3a7fa4..1d513394462 100644 --- a/reactos/lib/ws2_32/misc/dllmain.c +++ b/reactos/lib/ws2_32/misc/dllmain.c @@ -7,6 +7,7 @@ * REVISIONS: * CSH 01/09-2000 Created */ +#include #include #include #include @@ -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 diff --git a/reactos/lib/ws2_32/misc/stubs.c b/reactos/lib/ws2_32/misc/stubs.c index 332ef500b8e..5e836544ca8 100644 --- a/reactos/lib/ws2_32/misc/stubs.c +++ b/reactos/lib/ws2_32/misc/stubs.c @@ -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 */ /*