434 lines
11 KiB
C
434 lines
11 KiB
C
|
/*++
|
|||
|
|
|||
|
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 <ntos.h>
|
|||
|
|
|||
|
#include <tdikrnl.h>
|
|||
|
|
|||
|
//
|
|||
|
// 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_
|