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.
 
 
 
 
 
 

373 lines
7.6 KiB

/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
endpoint.c
Abstract:
This module implements endpoint logic for the loopback Transport
Provider driver for NT LAN Manager.
Author:
Chuck Lenzmeier (chuckl) 15-Aug-1991
Revision History:
--*/
#include "loopback.h"
VOID
LoopDereferenceEndpoint (
IN PLOOP_ENDPOINT Endpoint
)
/*++
Routine Description:
This routine is called to dereference an endpoint block. If the
reference count on the block goes to zero, the endpoint block is
deleted.
The Loopback device object's spin lock must be held when this
routine is called.
Arguments:
Endpoint - Supplies a pointer to an endpoint block
Return Value:
None.
--*/
{
PIRP closeIrp;
IF_DEBUG(LOOP3) {
DbgPrint( " Dereferencing endpoint %lx; old refcnt %lx\n",
Endpoint, Endpoint->BlockHeader.ReferenceCount );
}
ASSERT( (LONG)Endpoint->BlockHeader.ReferenceCount > 0 );
if ( --Endpoint->BlockHeader.ReferenceCount != 0 ) {
return;
}
IF_DEBUG(LOOP3) DbgPrint( " Deleting endpoint %lx\n", Endpoint );
RemoveEntryList( &Endpoint->DeviceListEntry );
RELEASE_LOOP_LOCK( "DerefEndp deleting" );
ObDereferenceObject( Endpoint->DeviceObject );
//
// If a Close IRP is pending, complete it now.
//
closeIrp = Endpoint->CloseIrp;
if ( closeIrp != NULL ) {
IF_DEBUG(LOOP3) {
DbgPrint( " Completing Close IRP %lx\n", closeIrp );
}
closeIrp->IoStatus.Status = STATUS_SUCCESS;
closeIrp->IoStatus.Information = 0;
IoCompleteRequest( closeIrp, 2 );
}
DEBUG SET_BLOCK_TYPE( Endpoint, BlockTypeGarbage );
DEBUG SET_BLOCK_STATE( Endpoint, BlockStateDead );
DEBUG SET_BLOCK_SIZE( Endpoint, -1 );
DEBUG Endpoint->BlockHeader.ReferenceCount = -1;
DEBUG Endpoint->DeviceObject = NULL;
ExFreePool( Endpoint );
ACQUIRE_LOOP_LOCK( "DerefEndp done" );
return;
} // LoopDereferenceEndpoint
PLOOP_ENDPOINT
LoopFindBoundAddress (
IN PCHAR NetbiosName
)
/*++
Routine Description:
This routine searches the list of endpoints for the loopback device
for one that has the specified address bound to it.
The loopback device object's spin lock must be owned when this
function is called.
Arguments:
NetbiosName - Pointer to NetBIOS name string, formatted according
to TDI specification.
Return Value:
PLOOP_OBJECT - Pointer to LOOP_ENDPOINT block if matching address
found, else NULL
--*/
{
PLIST_ENTRY listEntry;
PLOOP_ENDPOINT endpoint;
LONG compareResult;
CLONG i;
listEntry = LoopDeviceObject->EndpointList.Flink;
while ( listEntry != &LoopDeviceObject->EndpointList ) {
endpoint = CONTAINING_RECORD(
listEntry,
LOOP_ENDPOINT,
DeviceListEntry
);
if ( GET_BLOCK_STATE(endpoint) == BlockStateActive ) {
compareResult = 0;
for ( i = 0; i < NETBIOS_NAME_LENGTH; i++ ) {
if ( endpoint->NetbiosName[i] != NetbiosName[i] ) {
compareResult = 1;
break;
}
}
if ( compareResult == 0 ) {
return endpoint;
}
}
listEntry = listEntry->Flink;
}
return NULL;
} // LoopFindBoundAddress
NTSTATUS
LoopSetEventHandler (
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpSp
)
/*++
Routine Description:
This routine processes a Set Receive Handler request.
Arguments:
Irp - Pointer to I/O request packet
IrpSp - Pointer to current stack location in IRP
Return Value:
NTSTATUS - Status of request
--*/
{
NTSTATUS status = STATUS_SUCCESS;
PTDI_REQUEST_KERNEL_SET_EVENT setEventRequest;
PLOOP_ENDPOINT endpoint;
PVOID handler;
PVOID context;
PSZ s;
IrpSp; // prevent compiler warnings
IF_DEBUG(LOOP1) DbgPrint( " SetEventHandler request\n" );
setEventRequest = (PTDI_REQUEST_KERNEL_SET_EVENT)&IrpSp->Parameters;
handler = setEventRequest->EventHandler;
context = setEventRequest->EventContext;
//
// Get the endpoint address and update the handler address.
//
ACQUIRE_LOOP_LOCK( "SetEventHandler initial" );
endpoint = (PLOOP_ENDPOINT)IrpSp->FileObject->FsContext;
IF_DEBUG(LOOP2) DbgPrint( " Endpoint address: %lx\n", endpoint );
if ( endpoint == NULL ) {
IF_DEBUG(LOOP2) {
DbgPrint( " Can't SetEventHandler on control channel\n" );
}
status = STATUS_INVALID_PARAMETER;
goto complete;
}
if ( GET_BLOCK_TYPE(endpoint) != BlockTypeLoopEndpoint ) {
status = STATUS_INVALID_PARAMETER;
goto complete;
}
switch ( setEventRequest->EventType ) {
case TDI_EVENT_CONNECT:
IF_DEBUG(LOOP2) s = "connect";
endpoint->ConnectHandler = (PTDI_IND_CONNECT)handler;
endpoint->ConnectContext = context;
break;
case TDI_EVENT_DISCONNECT:
IF_DEBUG(LOOP2) s = "disconnect";
endpoint->DisconnectHandler = (PTDI_IND_DISCONNECT)handler;
endpoint->DisconnectContext = context;
break;
case TDI_EVENT_ERROR:
IF_DEBUG(LOOP2) s = "error";
endpoint->ErrorHandler = (PTDI_IND_ERROR)handler;
endpoint->ErrorContext = context;
break;
case TDI_EVENT_RECEIVE:
IF_DEBUG(LOOP2) s = "receive";
endpoint->ReceiveHandler = (PTDI_IND_RECEIVE)handler;
endpoint->ReceiveContext = context;
break;
case TDI_EVENT_RECEIVE_DATAGRAM:
IF_DEBUG(LOOP2) s = "receive datagram";
endpoint->ReceiveDatagramHandler = (PTDI_IND_RECEIVE_DATAGRAM)handler;
endpoint->ReceiveDatagramContext = context;
break;
case TDI_EVENT_RECEIVE_EXPEDITED:
IF_DEBUG(LOOP2) s = "receive expedited";
endpoint->ReceiveExpeditedHandler =
(PTDI_IND_RECEIVE_EXPEDITED)handler;
endpoint->ReceiveExpeditedContext = context;
break;
default:
DEBUG {
DbgPrint( " Invalid event type: %lx\n",
setEventRequest->EventType );
}
ASSERT( FALSE );
status = STATUS_INVALID_PARAMETER;
goto complete;
}
IF_DEBUG(LOOP2) {
DbgPrint( " New %s handler address: %lx, context: %lx\n",
s, handler, context );
}
complete:
RELEASE_LOOP_LOCK( "SetEventHandler final" );
//
// Complete the I/O request.
//
Irp->IoStatus.Status = status;
IoCompleteRequest( Irp, 2 );
IF_DEBUG(LOOP1) DbgPrint( " SetReceiveHandler request complete\n" );
return status;
} // LoopSetEventHandler
NTSTATUS
LoopVerifyEndpoint (
IN PLOOP_ENDPOINT Endpoint
)
/*++
Routine Description:
This routine verifies that the specified endpoint block is really
an endpoint created by the loopback driver.
The loopback device object's spin lock must be owned when this
function is called.
Arguments:
Endpoint - Pointer to endpoint block
Return Value:
NTSTATUS - STATUS_SUCCESS or STATUS_INVALID_PARAMETER
--*/
{
PLIST_ENTRY listEntry;
listEntry = LoopDeviceObject->EndpointList.Flink;
while ( listEntry != &LoopDeviceObject->EndpointList ) {
if ( CONTAINING_RECORD( listEntry, LOOP_ENDPOINT, DeviceListEntry ) ==
Endpoint ) {
return STATUS_SUCCESS;
}
listEntry = listEntry->Flink;
}
return STATUS_INVALID_PARAMETER;
} // LoopVerifyEndpoint