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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
* FILE: drivers/net/afd/afd/lock.c * FILE: drivers/net/afd/afd/lock.c
@ -114,6 +114,40 @@ VOID UnlockBuffers( PAFD_WSABUF Buf, UINT Count, BOOL Address ) {
ExFreePool( Buf ); 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 */ /* Returns transitioned state or SOCKET_STATE_INVALID_TRANSITION */
UINT SocketAcquireStateLock( PAFD_FCB FCB ) { UINT SocketAcquireStateLock( PAFD_FCB FCB ) {
NTSTATUS Status = STATUS_SUCCESS; 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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
* FILE: drivers/net/afd/afd/main.c * 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)); AFD_DbgPrint(MID_TRACE,("FCB %x\n", FCB));
FileObject->FsContext = NULL; FileObject->FsContext = NULL;
FCB->PollState |= AFD_EVENT_CLOSE;
PollReeval( FCB->DeviceExt, FileObject );
DestroySocket( FCB ); DestroySocket( FCB );
Irp->IoStatus.Status = STATUS_SUCCESS; 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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
* FILE: drivers/net/afd/afd/read.c * FILE: drivers/net/afd/afd/read.c
@ -416,7 +416,8 @@ PacketSocketRecvComplete(
AFD_DbgPrint(MID_TRACE,("Signalling\n")); AFD_DbgPrint(MID_TRACE,("Signalling\n"));
FCB->PollState |= AFD_EVENT_RECEIVE; FCB->PollState |= AFD_EVENT_RECEIVE;
PollReeval( FCB->DeviceExt, FCB->FileObject ); PollReeval( FCB->DeviceExt, FCB->FileObject );
} } else
FCB->PollState &= ~AFD_EVENT_RECEIVE;
if( NT_SUCCESS(Irp->IoStatus.Status) ) { if( NT_SUCCESS(Irp->IoStatus.Status) ) {
/* Now relaunch the datagram request */ /* Now relaunch the datagram request */
@ -483,9 +484,6 @@ AfdPacketSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
return UnlockAndMaybeComplete return UnlockAndMaybeComplete
( FCB, Status, Irp, RecvReq->BufferArray[0].len, NULL, TRUE ); ( FCB, Status, Irp, RecvReq->BufferArray[0].len, NULL, TRUE );
} else { } else {
if( IsListEmpty( &FCB->DatagramList ) )
FCB->PollState &= ~AFD_EVENT_RECEIVE;
Status = SatisfyPacketRecvRequest Status = SatisfyPacketRecvRequest
( FCB, Irp, DatagramRecv, ( FCB, Irp, DatagramRecv,
(PUINT)&Irp->IoStatus.Information ); (PUINT)&Irp->IoStatus.Information );
@ -493,10 +491,12 @@ AfdPacketSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
( FCB, Status, Irp, Irp->IoStatus.Information, NULL, TRUE ); ( FCB, Status, Irp, Irp->IoStatus.Information, NULL, TRUE );
} }
} else if( RecvReq->AfdFlags & AFD_IMMEDIATE ) { } else if( RecvReq->AfdFlags & AFD_IMMEDIATE ) {
FCB->PollState &= ~AFD_EVENT_RECEIVE;
AFD_DbgPrint(MID_TRACE,("Nonblocking\n")); AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
Status = STATUS_CANT_WAIT; Status = STATUS_CANT_WAIT;
return UnlockAndMaybeComplete( FCB, Status, Irp, 0, NULL, TRUE ); return UnlockAndMaybeComplete( FCB, Status, Irp, 0, NULL, TRUE );
} else { } else {
FCB->PollState &= ~AFD_EVENT_RECEIVE;
return LeaveIrpUntilLater( FCB, Irp, FUNCTION_RECV ); 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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
* FILE: drivers/net/afd/afd/select.c * FILE: drivers/net/afd/afd/select.c
@ -26,58 +26,36 @@ VOID ZeroEvents( PAFD_HANDLE HandleArray,
UINT HandleCount ) { UINT HandleCount ) {
UINT i; UINT i;
for( i = 0; i < HandleCount; i++ ) { for( i = 0; i < HandleCount; i++ )
HandleArray[i].Events = 0;
HandleArray[i].Status = 0; HandleArray[i].Status = 0;
}
} }
NTSTATUS STDCALL VOID RemoveSelect( PAFD_ACTIVE_POLL Poll ) {
ScanForImmediateTrigger( PAFD_HANDLE HandleArray, AFD_DbgPrint(MID_TRACE,("Called\n"));
UINT HandleCount,
PUINT HandlesSet ) {
NTSTATUS Status = STATUS_SUCCESS;
PFILE_OBJECT FileObject;
PAFD_FCB FCB;
UINT i;
BOOLEAN ShouldReturnNow = FALSE;
for( i = 0; i < HandleCount && NT_SUCCESS(Status); i++ ) { RemoveEntryList( &Poll->ListEntry );
HandleArray[i].Status = 0; KeCancelTimer( &Poll->Timer );
Status =
ObReferenceObjectByHandle
( (PVOID)HandleArray[i].Handle,
FILE_ALL_ACCESS,
NULL,
KernelMode,
(PVOID*)&FileObject,
NULL );
if( NT_SUCCESS(Status) ) { ExFreePool( Poll );
FCB = FileObject->FsContext;
/* Check select bits */
AFD_DbgPrint(MID_TRACE,("Locking socket state\n")); AFD_DbgPrint(MID_TRACE,("Done\n"));
}
if( !SocketAcquireStateLock( FCB ) ) { VOID SignalSocket( PAFD_ACTIVE_POLL Poll, PAFD_POLL_INFO PollReq,
AFD_DbgPrint(MID_TRACE,("Failed to get a socket state\n")); NTSTATUS Status, UINT Collected ) {
Status = STATUS_UNSUCCESSFUL; PIRP Irp = Poll->Irp;
} else { AFD_DbgPrint(MID_TRACE,("Called (Status %x Events %d)\n",
AFD_DbgPrint(MID_TRACE,("Got a socket state\n")); Status, Collected));
Status = STATUS_SUCCESS; Poll->Irp->IoStatus.Status = Status;
HandleArray[i].Status = Poll->Irp->IoStatus.Information = Collected;
FCB->PollState & HandleArray[i].Events; CopyBackStatus( PollReq->Handles,
if( HandleArray[i].Status ) ShouldReturnNow = TRUE; PollReq->HandleCount );
ObDereferenceObject( (PVOID)HandleArray[i].Handle ); UnlockHandles( PollReq->InternalUse, PollReq->HandleCount );
AFD_DbgPrint(MID_TRACE,("Unlocking\n")); AFD_DbgPrint(MID_TRACE,("Completing\n"));
SocketStateUnlock( FCB ); IoCompleteRequest( Irp, IO_NETWORK_INCREMENT );
AFD_DbgPrint(MID_TRACE,("Unlocked\n")); RemoveEntryList( &Poll->ListEntry );
} RemoveSelect( Poll );
} AFD_DbgPrint(MID_TRACE,("Done\n"));
}
if( !NT_SUCCESS(Status) || ShouldReturnNow ) return Status;
else return STATUS_PENDING;
} }
VOID SelectTimeout( PKDPC Dpc, VOID SelectTimeout( PKDPC Dpc,
@ -86,33 +64,31 @@ VOID SelectTimeout( PKDPC Dpc,
PVOID SystemArgument2 ) { PVOID SystemArgument2 ) {
PAFD_ACTIVE_POLL Poll = DeferredContext; PAFD_ACTIVE_POLL Poll = DeferredContext;
PAFD_POLL_INFO PollReq; PAFD_POLL_INFO PollReq;
PAFD_DEVICE_EXTENSION DeviceExt;
PIRP Irp; PIRP Irp;
KIRQL OldIrql; KIRQL OldIrql;
PAFD_DEVICE_EXTENSION DeviceExt;
AFD_DbgPrint(MID_TRACE,("Called\n"));
Irp = Poll->Irp; Irp = Poll->Irp;
DeviceExt = Poll->DeviceExt; DeviceExt = Poll->DeviceExt;
PollReq = Irp->AssociatedIrp.SystemBuffer; PollReq = Irp->AssociatedIrp.SystemBuffer;
KeAcquireSpinLock( &DeviceExt->Lock, &OldIrql );
RemoveEntryList( &Poll->ListEntry );
KeReleaseSpinLock( &DeviceExt->Lock, OldIrql );
ExFreePool( Poll );
ZeroEvents( PollReq->Handles, PollReq->HandleCount ); ZeroEvents( PollReq->Handles, PollReq->HandleCount );
Irp->IoStatus.Status = STATUS_TIMEOUT; KeAcquireSpinLock( &DeviceExt->Lock, &OldIrql );
Irp->IoStatus.Information = -1; SignalSocket( Poll, PollReq, STATUS_TIMEOUT, 0 );
KeReleaseSpinLock( &DeviceExt->Lock, OldIrql );
IoCompleteRequest( Irp, IO_NO_INCREMENT ); AFD_DbgPrint(MID_TRACE,("Timeout\n"));
} }
NTSTATUS STDCALL NTSTATUS STDCALL
AfdSelect( PDEVICE_OBJECT DeviceObject, PIRP Irp, AfdSelect( PDEVICE_OBJECT DeviceObject, PIRP Irp,
PIO_STACK_LOCATION IrpSp ) { PIO_STACK_LOCATION IrpSp ) {
NTSTATUS Status = STATUS_NO_MEMORY; NTSTATUS Status = STATUS_NO_MEMORY;
PAFD_FCB FCB;
PFILE_OBJECT FileObject;
PAFD_POLL_INFO PollReq = Irp->AssociatedIrp.SystemBuffer; PAFD_POLL_INFO PollReq = Irp->AssociatedIrp.SystemBuffer;
PAFD_DEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension; PAFD_DEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension;
PAFD_ACTIVE_POLL Poll = NULL; PAFD_ACTIVE_POLL Poll = NULL;
@ -120,115 +96,122 @@ AfdSelect( PDEVICE_OBJECT DeviceObject, PIRP Irp,
UINT AllocSize = UINT AllocSize =
CopySize + sizeof(AFD_ACTIVE_POLL) - sizeof(AFD_POLL_INFO); CopySize + sizeof(AFD_ACTIVE_POLL) - sizeof(AFD_POLL_INFO);
KIRQL OldIrql; KIRQL OldIrql;
UINT HandlesSignalled; UINT i, Signalled = 0;
AFD_DbgPrint(MID_TRACE,("Called (HandleCount %d Timeout %d)\n", AFD_DbgPrint(MID_TRACE,("Called (HandleCount %d Timeout %d)\n",
PollReq->HandleCount, PollReq->HandleCount,
(INT)(PollReq->Timeout.QuadPart * -1))); (INT)(PollReq->Timeout.QuadPart)));
Status = ScanForImmediateTrigger( PollReq->Handles, PollReq->InternalUse =
PollReq->HandleCount, LockHandles( PollReq->Handles, PollReq->HandleCount );
&HandlesSignalled );
if( Status == STATUS_PENDING ) { if( !PollReq->InternalUse ) {
Poll = ExAllocatePool( NonPagedPool, AllocSize ); Irp->IoStatus.Status = STATUS_NO_MEMORY;
Irp->IoStatus.Information = -1;
if( Poll ) { IoCompleteRequest( Irp, IO_NETWORK_INCREMENT );
KeAcquireSpinLock( &DeviceExt->Lock, &OldIrql ); return Irp->IoStatus.Status;
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;
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 );
} }
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)); 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; return Status;
} }
VOID SignalSocket( PAFD_ACTIVE_POLL Poll, PAFD_POLL_INFO PollReq, UINT i ) { /* * * NOTE ALWAYS CALLED AT DISPATCH_LEVEL * * */
/* 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 );
}
BOOLEAN UpdatePollWithFCB( PAFD_ACTIVE_POLL Poll, PFILE_OBJECT FileObject ) { BOOLEAN UpdatePollWithFCB( PAFD_ACTIVE_POLL Poll, PFILE_OBJECT FileObject ) {
UINT i; UINT i;
NTSTATUS Status;
PFILE_OBJECT TargetFile;
PAFD_FCB FCB; PAFD_FCB FCB;
UINT Signalled = 0;
PAFD_POLL_INFO PollReq = Poll->Irp->AssociatedIrp.SystemBuffer; PAFD_POLL_INFO PollReq = Poll->Irp->AssociatedIrp.SystemBuffer;
ASSERT( KeGetCurrentIrql() == DISPATCH_LEVEL );
for( i = 0; i < PollReq->HandleCount; i++ ) { for( i = 0; i < PollReq->HandleCount; i++ ) {
Status = if( !PollReq->InternalUse[i].Handle ) continue;
ObReferenceObjectByHandle
( (PVOID)PollReq->Handles[i].Handle,
FILE_ALL_ACCESS,
NULL,
KernelMode,
(PVOID*)&TargetFile,
NULL );
if( !NT_SUCCESS(Status) ) { 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; PollReq->Handles[i].Status = AFD_EVENT_CLOSE;
SignalSocket( Poll, PollReq, i ); Signalled++;
return TRUE;
} else { } else {
FCB = FileObject->FsContext; PollReq->Handles[i].Status =
PollReq->Handles[i].Events & FCB->PollState;
AFD_DbgPrint(MID_TRACE,("Locking socket state\n")); if( PollReq->Handles[i].Status ) {
AFD_DbgPrint(MID_TRACE,("Signalling %x with %x\n",
if( !SocketAcquireStateLock( FCB ) ) { FCB, FCB->PollState));
PollReq->Handles[i].Status = AFD_EVENT_CLOSE; Signalled++;
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 );
} }
return TRUE;
} }
} }
return FALSE; return Signalled ? 1 : 0;
} }
VOID PollReeval( PAFD_DEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject ) { VOID PollReeval( PAFD_DEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject ) {
PAFD_ACTIVE_POLL Poll = NULL; PAFD_ACTIVE_POLL Poll = NULL;
PLIST_ENTRY ThePollEnt = NULL; PLIST_ENTRY ThePollEnt = NULL;
KIRQL OldIrql; KIRQL OldIrql;
PAFD_POLL_INFO PollReq;
AFD_DbgPrint(MID_TRACE,("Called: DeviceExt %x FileObject %x\n", AFD_DbgPrint(MID_TRACE,("Called: DeviceExt %x FileObject %x\n",
DeviceExt, FileObject)); DeviceExt, FileObject));
@ -239,9 +222,13 @@ VOID PollReeval( PAFD_DEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject ) {
while( ThePollEnt != &DeviceExt->Polls ) { while( ThePollEnt != &DeviceExt->Polls ) {
Poll = CONTAINING_RECORD( ThePollEnt, AFD_ACTIVE_POLL, ListEntry ); 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 ) ) { if( UpdatePollWithFCB( Poll, FileObject ) ) {
ThePollEnt = ThePollEnt->Flink; ThePollEnt = ThePollEnt->Flink;
RemoveEntryList( &Poll->ListEntry ); AFD_DbgPrint(MID_TRACE,("Signalling socket\n"));
SignalSocket( Poll, PollReq, STATUS_SUCCESS, 1 );
} else } else
ThePollEnt = ThePollEnt->Flink; 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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -186,6 +186,8 @@ NTSTATUS DDKAPI UnlockAndMaybeComplete
BOOL ShouldUnlockIrp ); BOOL ShouldUnlockIrp );
VOID SocketStateUnlock( PAFD_FCB FCB ); VOID SocketStateUnlock( PAFD_FCB FCB );
NTSTATUS LostSocket( PIRP Irp, BOOL ShouldUnlockIrp ); 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 ); PVOID LockRequest( PIRP Irp, PIO_STACK_LOCATION IrpSp );
VOID UnlockRequest( PIRP Irp, PIO_STACK_LOCATION IrpSp ); VOID UnlockRequest( PIRP Irp, PIO_STACK_LOCATION IrpSp );
VOID SocketCalloutEnter( PAFD_FCB FCB ); VOID SocketCalloutEnter( PAFD_FCB FCB );

View file

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

View file

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

View file

@ -413,113 +413,142 @@ WSPSelect(
struct timeval *timeout, struct timeval *timeout,
LPINT lpErrno) LPINT lpErrno)
{ {
IO_STATUS_BLOCK IOSB; IO_STATUS_BLOCK IOSB;
PAFD_POLL_INFO PollInfo; PAFD_POLL_INFO PollInfo;
NTSTATUS Status; NTSTATUS Status;
ULONG HandleCount; ULONG HandleCount, OutCount = 0;
ULONG PollBufferSize; ULONG PollBufferSize;
LARGE_INTEGER uSec; LARGE_INTEGER uSec;
PVOID PollBuffer; PVOID PollBuffer;
ULONG i, j = 0; ULONG i, j = 0, x;
HANDLE SockEvent; HANDLE SockEvent;
Status = NtCreateEvent( &SockEvent, GENERIC_READ | GENERIC_WRITE, Status = NtCreateEvent( &SockEvent, GENERIC_READ | GENERIC_WRITE,
NULL, 1, FALSE ); NULL, 1, FALSE );
if( !NT_SUCCESS(Status) ) return -1; if( !NT_SUCCESS(Status) ) return -1;
/* Find out how many sockets we have, and how large the buffer needs to be */ /* Find out how many sockets we have, and how large the buffer needs
HandleCount = ( readfds ? readfds->fd_count : 0 ) + * to be */
( writefds ? writefds->fd_count : 0 ) +
( exceptfds ? exceptfds->fd_count : 0 );
PollBufferSize = sizeof(*PollInfo) + (HandleCount * sizeof(AFD_HANDLE));
/* Allocate */ HandleCount =
PollBuffer = HeapAlloc(GlobalHeap, 0, PollBufferSize); ( readfds ? readfds->fd_count : 0 ) +
PollInfo = (PAFD_POLL_INFO)PollBuffer; ( writefds ? writefds->fd_count : 0 ) +
( exceptfds ? exceptfds->fd_count : 0 );
PollBufferSize = sizeof(*PollInfo) +
(HandleCount * sizeof(AFD_HANDLE));
/* Convert Timeout to NT Format */ /* Allocate */
if (timeout == NULL) { PollBuffer = HeapAlloc(GlobalHeap, 0, PollBufferSize);
PollInfo->Timeout.u.LowPart = -1; PollInfo = (PAFD_POLL_INFO)PollBuffer;
PollInfo->Timeout.u.HighPart = 0x7FFFFFFF;
} else { RtlZeroMemory( PollInfo, PollBufferSize );
PollInfo->Timeout = RtlEnlargedIntegerMultiply(timeout->tv_sec, -10000000);
uSec = RtlEnlargedIntegerMultiply(timeout->tv_usec, -10); /* Convert Timeout to NT Format */
PollInfo->Timeout.QuadPart += uSec.QuadPart; 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; if (exceptfds != NULL) {
PollInfo->Unknown = 0; for (i = 0; i < exceptfds->fd_count; i++, j++) {
PollInfo->Handles[j].Handle = exceptfds->fd_array[i];
if (readfds != NULL) { PollInfo->Handles[j].Events |=
for (i = 0; i < readfds->fd_count; i++, j++) { AFD_EVENT_OOB_RECEIVE | AFD_EVENT_CONNECT_FAIL;
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;
}
} }
}
/* Send IOCTL */ /* Send IOCTL */
Status = NtDeviceIoControlFile( (HANDLE)Sockets[0]->Handle, Status = NtDeviceIoControlFile( (HANDLE)Sockets[0]->Handle,
SockEvent, SockEvent,
NULL, NULL,
NULL, NULL,
&IOSB, &IOSB,
IOCTL_AFD_SELECT, IOCTL_AFD_SELECT,
PollInfo, PollInfo,
PollBufferSize, PollBufferSize,
PollInfo, PollInfo,
PollBufferSize); PollBufferSize);
/* Wait for Completition */ AFD_DbgPrint(MID_TRACE,("DeviceIoControlFile => %x\n", Status));
if (Status == STATUS_PENDING) {
WaitForSingleObject(SockEvent, 0); /* 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 */ NtClose( SockEvent );
readfds ? FD_ZERO(readfds) : 0; switch( IOSB.Status ) {
writefds ? FD_ZERO(writefds) : 0; case STATUS_SUCCESS:
exceptfds ? FD_ZERO(exceptfds) : 0; case STATUS_TIMEOUT: *lpErrno = 0; break;
default: *lpErrno = WSAEINVAL;
}
/* Loop through return structure */ AFD_DbgPrint(MID_TRACE,("%d events\n", OutCount));
HandleCount = PollInfo->HandleCount;
/* Return in FDSET Format */ return OutCount;
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;
} }
SOCKET 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 = ../.. PATH_TO_TOP = ../..
@ -19,7 +19,6 @@ TARGET_CFLAGS = \
-fno-builtin \ -fno-builtin \
-DUNICODE \ -DUNICODE \
-DLE \ -DLE \
-DDBG \
-D__USE_W32API -D__USE_W32API
# require os code to explicitly request A/W version of structs/functions # require os code to explicitly request A/W version of structs/functions

View file

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

View file

@ -636,23 +636,6 @@ WSACancelAsyncRequest(
return 0; 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 */ /* WinSock Service Provider support functions */
/* /*