mirror of https://github.com/lianthony/NT4.0
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
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
|
|
|