/*++ Copyright (c) 1991 Microsoft Corporation Module Name: loopback.h Abstract: This module is the main include file for the LAN Manager loopback driver. Author: Chuck Lenzmeier (chuckl) 27-Jun-1991 Revision History: --*/ #ifndef _LOOP_ #define _LOOP_ // // "System" include files // #include #include // // Network include files. // #include "status.h" // // Local, independent include files // #include "loopdbg.h" #define LOOPBACK_DEVICE_NAME "\\Device\\Loop" // // The length of a NetBIOS name. Fixed by the protocol. // #define NETBIOS_NAME_LENGTH 16 // // Simple MIN and MAX macros. Watch out for side effects! // #define MIN(a,b) ( ((a) < (b)) ? (a) : (b) ) #define MAX(a,b) ( ((a) < (b)) ? (b) : (a) ) // // Macros for accessing the block header structure. // // *** Note that the existing usage of these macros assumes that the block // header is the first element in the block! // #define GET_BLOCK_STATE(block) ( ((PBLOCK_HEADER)(block))->State ) #define SET_BLOCK_STATE(block,state) ( ((PBLOCK_HEADER)(block))->State = state ) #define GET_BLOCK_TYPE(block) ( ((PBLOCK_HEADER)(block))->Type ) #define SET_BLOCK_TYPE(block,type) ( ((PBLOCK_HEADER)(block))->Type = type ) #define GET_BLOCK_SIZE(block) ( ((PBLOCK_HEADER)(block))->Size ) #define SET_BLOCK_SIZE(block,size) ( ((PBLOCK_HEADER)(block))->Size = size ) // // Local macros // // // Macros for lock debugging. // // *** Note that the test for recursion only works on uniprocessors. // #if LOOPDBG && defined(LOOPLOCK) #define ACQUIRE_LOOP_LOCK(instance) { \ IF_DEBUG(LOOP5) \ DbgPrint( "Acquire loop lock, %s\n", \ (instance) ); \ if ( LoopDeviceObject->SavedIrql != (KIRQL)-1 ) { \ DbgPrint( "Recursive lock acquisition attempt\n" ); \ DbgBreakPoint( ); \ } \ KeAcquireSpinLock( \ &LoopDeviceObject->SpinLock, \ &LoopDeviceObject->SavedIrql \ ); \ } #define RELEASE_LOOP_LOCK(instance) { \ KIRQL oldIrql; \ IF_DEBUG(LOOP5) \ DbgPrint( "Release loop lock, %s\n", \ (instance) ); \ ASSERT( LoopDeviceObject->SavedIrql != (KIRQL)-1 ); \ oldIrql = LoopDeviceObject->SavedIrql; \ LoopDeviceObject->SavedIrql = (KIRQL)-1; \ KeReleaseSpinLock( \ &LoopDeviceObject->SpinLock, \ oldIrql \ ); \ } #else // LOOPDBG && defined(LOOPLOCK) #define ACQUIRE_LOOP_LOCK(instance) \ KeAcquireSpinLock( \ &LoopDeviceObject->SpinLock, \ &LoopDeviceObject->SavedIrql \ ) \ #define RELEASE_LOOP_LOCK(instance) \ KeReleaseSpinLock( \ &LoopDeviceObject->SpinLock, \ LoopDeviceObject->SavedIrql \ ) \ #endif // else LOOPDBG && defined(LOOPLOCK) // // Local types // // // The loopback driver's device object is a standard I/O system device // object followed by fields specific to the device. // typedef struct _LOOP_DEVICE_OBJECT { DEVICE_OBJECT DeviceObject; // // List of active address endpoints. // LIST_ENTRY EndpointList; // // List of active connection endpoints. // LIST_ENTRY ConnectionList; // // Spin lock synchronizing access to fields in the device object // and to structures maintained by the device driver. // KSPIN_LOCK SpinLock; // // SavedIrql is used so that one routine can call another with the // lock held and the called routine can release (and possibly // reacquire it). SavedIrql is set *after* the lock is acquired. // KIRQL SavedIrql; } LOOP_DEVICE_OBJECT, *PLOOP_DEVICE_OBJECT; #define LOOP_DEVICE_EXTENSION_LENGTH (sizeof(LOOP_DEVICE_OBJECT) - \ sizeof(DEVICE_OBJECT)) // // BLOCK_TYPE is an enumerated type defining the various types of // data blocks used by the driver. // typedef enum _BLOCK_TYPE { BlockTypeGarbage = 0, BlockTypeLoopConnection = 0x29290001, BlockTypeLoopEndpoint = 0x29290002 } BLOCK_TYPE, *PBLOCK_TYPE; // // BLOCK_STATE is an enumerated type defining the various states that // blocks can be in. Initializing is used (relatively rarely) to // indicate that creation/initialization of a block is in progress. // Active is the state blocks are usually in. Closing is used to // indicate that a block is being prepared for deletion; when the // reference count on the block reaches 0, the block will be deleted. // Dead is used when debugging code is enabled to indicate that the // block has been deleted. // typedef enum _BLOCK_STATE { BlockStateDead, BlockStateUnbound, BlockStateBound, BlockStateConnecting, BlockStateActive, BlockStateDisconnecting, BlockStateClosing, BlockStateClosed, // The following is defined just to know how many states there are BlockStateMax } BLOCK_STATE, *PBLOCK_STATE; // // BLOCK_HEADER is the standard block header that appears at the // beginning of most driver-private data structures. This header is // used primarily for debugging and tracing. The Type and State fields // are described above. The Size field indicates how much space was // allocated for the block. ReferenceCount indicates the number of // reasons why the block should not be deallocated. The count is set to // 2 by the allocation routine, to account for 1) the fact that the // block is "open" and 2) the pointer returned to the caller. When the // block is closed, State is set to Closing, and the ReferenceCount is // decremented. When all references (pointers) to the block are // deleted, and the reference count reaches 0, the block is deleted. // typedef struct _BLOCK_HEADER { BLOCK_TYPE Type; BLOCK_STATE State; ULONG ReferenceCount; CLONG Size; } BLOCK_HEADER, *PBLOCK_HEADER; // // The file object obtained when the loopback Transport Provider is // opened points to a LOOP_ENDPOINT record, which has context consisting // of a pointer to the file object and a list of connections created // over the endpoint. // typedef struct _LOOP_ENDPOINT { BLOCK_HEADER BlockHeader; LIST_ENTRY DeviceListEntry; LIST_ENTRY ConnectionList; LIST_ENTRY PendingListenList; LIST_ENTRY IncomingConnectList; PIRP IndicatingConnectIrp; PLOOP_DEVICE_OBJECT DeviceObject; PFILE_OBJECT FileObject; PTDI_IND_CONNECT ConnectHandler; PVOID ConnectContext; PTDI_IND_RECEIVE ReceiveHandler; PVOID ReceiveContext; PTDI_IND_RECEIVE_DATAGRAM ReceiveDatagramHandler; PVOID ReceiveDatagramContext; PTDI_IND_RECEIVE_EXPEDITED ReceiveExpeditedHandler; PVOID ReceiveExpeditedContext; PTDI_IND_DISCONNECT DisconnectHandler; PVOID DisconnectContext; PTDI_IND_ERROR ErrorHandler; PVOID ErrorContext; PIRP CloseIrp; CHAR NetbiosName[NETBIOS_NAME_LENGTH+1]; } LOOP_ENDPOINT, *PLOOP_ENDPOINT; // // Each connection is represented by two LOOP_CONNECTION structures, one // for each end of the connection. // typedef struct _LOOP_CONNECTION { BLOCK_HEADER BlockHeader; LIST_ENTRY DeviceListEntry; LIST_ENTRY EndpointListEntry; PLOOP_ENDPOINT Endpoint; PLOOP_DEVICE_OBJECT DeviceObject; PFILE_OBJECT FileObject; struct _LOOP_CONNECTION *RemoteConnection; PVOID ConnectionContext; LIST_ENTRY PendingReceiveList; LIST_ENTRY IncomingSendList; PIRP IndicatingSendIrp; PIRP ConnectOrListenIrp; PIRP DisconnectIrp; PIRP CloseIrp; } LOOP_CONNECTION, *PLOOP_CONNECTION; // // Global variables // // // The address of the loopback device object (there's only one) is kept // in global storage to avoid having to pass it from routine to routine. // extern PLOOP_DEVICE_OBJECT LoopDeviceObject; // // LoopProviderInfo is a structure containing information that may be // obtained using TdiQueryInformation. // extern TDI_PROVIDER_INFO LoopProviderInfo; // // Global declarations // NTSTATUS LoopAccept ( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ); NTSTATUS LoopAssociateAddress ( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ); NTSTATUS LoopConnect ( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ); VOID LoopCopyData ( IN PMDL Destination, IN PMDL Source, IN ULONG Length ); NTSTATUS LoopCreate ( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ); VOID LoopDereferenceConnection ( IN PLOOP_CONNECTION Connection ); VOID LoopDereferenceEndpoint ( IN PLOOP_ENDPOINT Endpoint ); NTSTATUS LoopDisassociateAddress ( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ); NTSTATUS LoopDisconnect ( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ); VOID LoopDoDisconnect ( IN PLOOP_CONNECTION Conection, IN BOOLEAN ClientInitiated ); PLOOP_ENDPOINT LoopFindBoundAddress ( IN PCHAR NetbiosName ); PVOID LoopGetConnectionContextFromEa ( PFILE_FULL_EA_INFORMATION Ea ); NTSTATUS LoopGetEndpointTypeFromEa ( PFILE_FULL_EA_INFORMATION Ea, PBLOCK_TYPE Type ); NTSTATUS LoopListen ( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ); NTSTATUS LoopParseAddress ( IN PTA_NETBIOS_ADDRESS Address, OUT PCHAR NetbiosName ); NTSTATUS LoopParseAddressFromEa ( IN PFILE_FULL_EA_INFORMATION Ea, OUT PCHAR NetbiosName ); NTSTATUS LoopQueryInformation ( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ); NTSTATUS LoopReceive ( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ); NTSTATUS LoopSend ( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ); NTSTATUS LoopSetEventHandler ( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ); NTSTATUS LoopVerifyEndpoint ( IN PLOOP_ENDPOINT Endpoint ); #endif // def _LOOP_