summaryrefslogtreecommitdiffstats
path: root/private/ntos/tdi/loopback/endpoint.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--private/ntos/tdi/loopback/endpoint.c373
1 files changed, 373 insertions, 0 deletions
diff --git a/private/ntos/tdi/loopback/endpoint.c b/private/ntos/tdi/loopback/endpoint.c
new file mode 100644
index 000000000..fd252d291
--- /dev/null
+++ b/private/ntos/tdi/loopback/endpoint.c
@@ -0,0 +1,373 @@
+/*++
+
+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
+