Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

478 lines
9.4 KiB

/*++
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