479 lines
9.4 KiB
C
479 lines
9.4 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1989 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
eventsel.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module contains routines for supporting the WinSock 2.0
|
|||
|
WSAEventSelect() and WSAEnumNetworkEvents() APIs.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Keith Moore (keithmo) 02-Aug-1995
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "afdp.h"
|
|||
|
|
|||
|
#ifdef ALLOC_PRAGMA
|
|||
|
#pragma alloc_text( PAGE, AfdEventSelect )
|
|||
|
#pragma alloc_text( PAGE, AfdEnumNetworkEvents )
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
AfdEventSelect (
|
|||
|
IN PIRP Irp,
|
|||
|
IN PIO_STACK_LOCATION IrpSp
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Associates an event object with the socket such that the event object
|
|||
|
will be signalled when any of the specified network events becomes
|
|||
|
active.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Irp - Pointer to I/O request packet.
|
|||
|
|
|||
|
IrpSp - pointer to the IO stack location to use for this request.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS -- Indicates whether the APC was successfully queued.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
NTSTATUS status;
|
|||
|
PAFD_ENDPOINT endpoint;
|
|||
|
PAFD_EVENT_SELECT_INFO eventInfo;
|
|||
|
KIRQL oldIrql;
|
|||
|
PKEVENT eventObject;
|
|||
|
ULONG eventMask;
|
|||
|
|
|||
|
PAGED_CODE( );
|
|||
|
|
|||
|
//
|
|||
|
// Validate the parameters.
|
|||
|
//
|
|||
|
|
|||
|
eventInfo = Irp->AssociatedIrp.SystemBuffer;
|
|||
|
|
|||
|
if( eventInfo == NULL ||
|
|||
|
IrpSp->Parameters.DeviceIoControl.InputBufferLength <
|
|||
|
sizeof(*eventInfo) ||
|
|||
|
( eventInfo->Event == NULL ^
|
|||
|
eventInfo->PollEvents == 0 ) ) {
|
|||
|
|
|||
|
return STATUS_INVALID_PARAMETER;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Reference the target event object.
|
|||
|
//
|
|||
|
|
|||
|
|
|||
|
eventObject = NULL;
|
|||
|
|
|||
|
if( eventInfo->Event != NULL ) {
|
|||
|
|
|||
|
status = AfdReferenceEventObjectByHandle(
|
|||
|
eventInfo->Event,
|
|||
|
Irp->RequestorMode,
|
|||
|
(PVOID *)&eventObject
|
|||
|
);
|
|||
|
|
|||
|
if( !NT_SUCCESS(status) ) {
|
|||
|
|
|||
|
return status;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
ASSERT( eventObject != NULL );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Grab the endpoint from the socket handle.
|
|||
|
//
|
|||
|
|
|||
|
endpoint = IrpSp->FileObject->FsContext;
|
|||
|
ASSERT( IS_AFD_ENDPOINT_TYPE( endpoint ) );
|
|||
|
|
|||
|
//
|
|||
|
// Acquire the spinlock protecting the endpoint.
|
|||
|
//
|
|||
|
|
|||
|
AfdAcquireSpinLock( &endpoint->SpinLock, &oldIrql );
|
|||
|
|
|||
|
//
|
|||
|
// If this endpoint has an active EventSelect, dereference the
|
|||
|
// associated event object.
|
|||
|
//
|
|||
|
|
|||
|
if( endpoint->EventObject != NULL ) {
|
|||
|
|
|||
|
ObDereferenceObject( endpoint->EventObject );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Fill in the info.
|
|||
|
//
|
|||
|
|
|||
|
endpoint->EventObject = eventObject;
|
|||
|
endpoint->EventsEnabled = eventInfo->PollEvents;
|
|||
|
|
|||
|
if( endpoint->State == AfdEndpointStateListening ) {
|
|||
|
|
|||
|
endpoint->EventsDisabled = AFD_DISABLED_LISTENING_POLL_EVENTS;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
endpoint->EventsDisabled = 0;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
IF_DEBUG(EVENT_SELECT) {
|
|||
|
KdPrint((
|
|||
|
"AfdEventSelect:\n"
|
|||
|
));
|
|||
|
|
|||
|
KdPrint((
|
|||
|
" Endpoint %08lX\n",
|
|||
|
endpoint
|
|||
|
));
|
|||
|
|
|||
|
KdPrint((
|
|||
|
" EventObject %08lX\n",
|
|||
|
eventObject
|
|||
|
));
|
|||
|
|
|||
|
KdPrint((
|
|||
|
" EventsEnabled %08lX\n",
|
|||
|
endpoint->EventsEnabled
|
|||
|
));
|
|||
|
|
|||
|
KdPrint((
|
|||
|
" EventsDisabled %08lX\n",
|
|||
|
endpoint->EventsDisabled
|
|||
|
));
|
|||
|
|
|||
|
KdPrint((
|
|||
|
" EventsActive %08lX\n",
|
|||
|
endpoint->EventsActive
|
|||
|
));
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// While we've got the spinlock held, determine if any conditions
|
|||
|
// are met, and if so, signal the event object.
|
|||
|
//
|
|||
|
|
|||
|
eventMask = endpoint->EventsActive & endpoint->EventsEnabled &
|
|||
|
~endpoint->EventsDisabled;
|
|||
|
|
|||
|
if( eventMask != 0 && eventObject != NULL ) {
|
|||
|
|
|||
|
IF_DEBUG(EVENT_SELECT) {
|
|||
|
KdPrint((
|
|||
|
"AfdEventSelect: Setting event %08lX\n",
|
|||
|
eventObject
|
|||
|
));
|
|||
|
}
|
|||
|
|
|||
|
KeSetEvent(
|
|||
|
eventObject,
|
|||
|
AfdPriorityBoost,
|
|||
|
FALSE
|
|||
|
);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Release the spin lock and return.
|
|||
|
//
|
|||
|
|
|||
|
AfdReleaseSpinLock( &endpoint->SpinLock, oldIrql );
|
|||
|
|
|||
|
return STATUS_SUCCESS;
|
|||
|
|
|||
|
} // AfdEventSelect
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
AfdEnumNetworkEvents (
|
|||
|
IN PIRP Irp,
|
|||
|
IN PIO_STACK_LOCATION IrpSp
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Retrieves event select information from the socket.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Irp - Pointer to I/O request packet.
|
|||
|
|
|||
|
IrpSp - pointer to the IO stack location to use for this request.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS -- Indicates whether the APC was successfully queued.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
NTSTATUS status;
|
|||
|
PAFD_ENDPOINT endpoint;
|
|||
|
PAFD_ENUM_NETWORK_EVENTS_INFO eventInfo;
|
|||
|
KIRQL oldIrql;
|
|||
|
PKEVENT eventObject;
|
|||
|
ULONG pollEvents;
|
|||
|
|
|||
|
PAGED_CODE( );
|
|||
|
|
|||
|
//
|
|||
|
// Validate the parameters.
|
|||
|
//
|
|||
|
|
|||
|
eventInfo = Irp->AssociatedIrp.SystemBuffer;
|
|||
|
|
|||
|
if( eventInfo == NULL ||
|
|||
|
IrpSp->Parameters.DeviceIoControl.InputBufferLength <
|
|||
|
sizeof(*eventInfo) ||
|
|||
|
IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
|
|||
|
sizeof(*eventInfo) ) {
|
|||
|
|
|||
|
return STATUS_INVALID_PARAMETER;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Reference the target event object.
|
|||
|
//
|
|||
|
|
|||
|
eventObject = NULL;
|
|||
|
|
|||
|
if( eventInfo->Event != NULL ) {
|
|||
|
|
|||
|
status = AfdReferenceEventObjectByHandle(
|
|||
|
eventInfo->Event,
|
|||
|
Irp->RequestorMode,
|
|||
|
(PVOID *)&eventObject
|
|||
|
);
|
|||
|
|
|||
|
if( !NT_SUCCESS(status) ) {
|
|||
|
|
|||
|
return status;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
ASSERT( eventObject != NULL );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Grab the endpoint from the socket handle.
|
|||
|
//
|
|||
|
|
|||
|
endpoint = IrpSp->FileObject->FsContext;
|
|||
|
ASSERT( IS_AFD_ENDPOINT_TYPE( endpoint ) );
|
|||
|
|
|||
|
//
|
|||
|
// Acquire the spinlock protecting the endpoint.
|
|||
|
//
|
|||
|
|
|||
|
AfdAcquireSpinLock( &endpoint->SpinLock, &oldIrql );
|
|||
|
|
|||
|
IF_DEBUG(EVENT_SELECT) {
|
|||
|
KdPrint((
|
|||
|
"AfdEnumNetworkEvents:\n"
|
|||
|
));
|
|||
|
|
|||
|
KdPrint((
|
|||
|
" Endpoint %08lX\n",
|
|||
|
endpoint
|
|||
|
));
|
|||
|
|
|||
|
KdPrint((
|
|||
|
" EventObject %08lX\n",
|
|||
|
eventObject
|
|||
|
));
|
|||
|
|
|||
|
KdPrint((
|
|||
|
" EventsEnabled %08lX\n",
|
|||
|
endpoint->EventsEnabled
|
|||
|
));
|
|||
|
|
|||
|
KdPrint((
|
|||
|
" EventsDisabled %08lX\n",
|
|||
|
endpoint->EventsDisabled
|
|||
|
));
|
|||
|
|
|||
|
KdPrint((
|
|||
|
" EventsActive %08lX\n",
|
|||
|
endpoint->EventsActive
|
|||
|
));
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Copy the data to the user's structure.
|
|||
|
//
|
|||
|
|
|||
|
pollEvents = endpoint->EventsActive & endpoint->EventsEnabled &
|
|||
|
~endpoint->EventsDisabled;
|
|||
|
eventInfo->PollEvents = pollEvents;
|
|||
|
|
|||
|
RtlCopyMemory(
|
|||
|
eventInfo->EventStatus,
|
|||
|
endpoint->EventStatus,
|
|||
|
sizeof(endpoint->EventStatus)
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// If there was an event object handle passed in with this
|
|||
|
// request, reset and dereference it.
|
|||
|
//
|
|||
|
|
|||
|
if( eventObject != NULL ) {
|
|||
|
|
|||
|
IF_DEBUG(EVENT_SELECT) {
|
|||
|
KdPrint((
|
|||
|
"AfdEnumNetworkEvents: Resetting event %08lX\n",
|
|||
|
eventObject
|
|||
|
));
|
|||
|
}
|
|||
|
|
|||
|
KeResetEvent( eventObject );
|
|||
|
ObDereferenceObject( eventObject );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Release the spin lock and return.
|
|||
|
//
|
|||
|
|
|||
|
AfdReleaseSpinLock( &endpoint->SpinLock, oldIrql );
|
|||
|
|
|||
|
//
|
|||
|
// Before returning, tell the I/O subsystem how may bytes to copy
|
|||
|
// to the user's output buffer.
|
|||
|
//
|
|||
|
|
|||
|
Irp->IoStatus.Information = sizeof(*eventInfo);
|
|||
|
|
|||
|
return STATUS_SUCCESS;
|
|||
|
|
|||
|
} // AfdEnumNetworkEvents
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
AfdIndicateEventSelectEvent (
|
|||
|
IN PAFD_ENDPOINT Endpoint,
|
|||
|
IN ULONG PollEventBit,
|
|||
|
IN NTSTATUS Status
|
|||
|
)
|
|||
|
{
|
|||
|
ULONG event;
|
|||
|
ULONG oldEventsActive;
|
|||
|
|
|||
|
//
|
|||
|
// Sanity check.
|
|||
|
//
|
|||
|
|
|||
|
ASSERT( IS_AFD_ENDPOINT_TYPE( Endpoint ) );
|
|||
|
ASSERT( PollEventBit < AFD_NUM_POLL_EVENTS );
|
|||
|
ASSERT( KeGetCurrentIrql() >= DISPATCH_LEVEL );
|
|||
|
|
|||
|
//
|
|||
|
// Calculate the actual event bit.
|
|||
|
//
|
|||
|
|
|||
|
event = 1 << PollEventBit;
|
|||
|
|
|||
|
oldEventsActive = Endpoint->EventsActive;
|
|||
|
Endpoint->EventsActive |= event;
|
|||
|
Endpoint->EventStatus[PollEventBit] = Status;
|
|||
|
|
|||
|
IF_DEBUG(EVENT_SELECT) {
|
|||
|
KdPrint((
|
|||
|
"AfdIndicateEventSelectEvent:\n"
|
|||
|
));
|
|||
|
|
|||
|
KdPrint((
|
|||
|
" Endpoint %08lX\n",
|
|||
|
Endpoint
|
|||
|
));
|
|||
|
|
|||
|
KdPrint((
|
|||
|
" EventObject %08lX\n",
|
|||
|
Endpoint->EventObject
|
|||
|
));
|
|||
|
|
|||
|
KdPrint((
|
|||
|
" EventsEnabled %08lX\n",
|
|||
|
Endpoint->EventsEnabled
|
|||
|
));
|
|||
|
|
|||
|
KdPrint((
|
|||
|
" EventsDisabled %08lX\n",
|
|||
|
Endpoint->EventsDisabled
|
|||
|
));
|
|||
|
|
|||
|
KdPrint((
|
|||
|
" EventsActive %08lX\n",
|
|||
|
Endpoint->EventsActive
|
|||
|
));
|
|||
|
|
|||
|
KdPrint((
|
|||
|
" Indicated Event %08lX\n",
|
|||
|
event
|
|||
|
));
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Only signal the endpoint's event object if the current event
|
|||
|
// is enabled, AND the current event was not already active, AND
|
|||
|
// there is an event object associated with this endpoint.
|
|||
|
//
|
|||
|
|
|||
|
event &= Endpoint->EventsEnabled & ~Endpoint->EventsDisabled &
|
|||
|
~oldEventsActive;
|
|||
|
|
|||
|
if( event != 0 && Endpoint->EventObject != NULL ) {
|
|||
|
|
|||
|
IF_DEBUG(EVENT_SELECT) {
|
|||
|
KdPrint((
|
|||
|
"AfdIndicateEventSelectEvent: Setting event %08lX\n",
|
|||
|
Endpoint->EventObject
|
|||
|
));
|
|||
|
}
|
|||
|
|
|||
|
KeSetEvent(
|
|||
|
Endpoint->EventObject,
|
|||
|
AfdPriorityBoost,
|
|||
|
FALSE
|
|||
|
);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
} // AfdIndicateEventSelectEvent
|
|||
|
|