388 lines
12 KiB
C
388 lines
12 KiB
C
|
/****************************************************************************/
|
||
|
// icap.h
|
||
|
//
|
||
|
// TermDD private header.
|
||
|
//
|
||
|
// Copyright (C) 1998-2000 Microsoft Corporation
|
||
|
/****************************************************************************/
|
||
|
|
||
|
|
||
|
#define ICA_POOL_TAG ' acI'
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Enumerated ICA object types
|
||
|
*/
|
||
|
typedef enum _ICA_TYPE {
|
||
|
IcaType_Connection,
|
||
|
IcaType_Stack,
|
||
|
IcaType_Channel
|
||
|
} ICA_TYPE;
|
||
|
|
||
|
|
||
|
/*
|
||
|
* ICA dispatch prototype
|
||
|
*/
|
||
|
typedef NTSTATUS (*PICA_DISPATCH) (
|
||
|
IN PVOID IcaObject,
|
||
|
IN PIRP Irp,
|
||
|
IN PIO_STACK_LOCATION IrpSp);
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Deferred trace structure
|
||
|
*/
|
||
|
#pragma warning(disable : 4200) // for Buffer[] nonstandard extension.
|
||
|
typedef struct _DEFERRED_TRACE {
|
||
|
struct _DEFERRED_TRACE *Next;
|
||
|
ULONG Length;
|
||
|
WCHAR Buffer[];
|
||
|
} DEFERRED_TRACE, *PDEFERRED_TRACE;
|
||
|
#pragma warning(default : 4200)
|
||
|
|
||
|
/*
|
||
|
* Trace Information structure
|
||
|
*/
|
||
|
typedef struct _ICA_TRACE_INFO {
|
||
|
ULONG TraceClass; // trace - enabled trace classes (TC_?)
|
||
|
ULONG TraceEnable; // trace - enabled trace types (TT_?)
|
||
|
BOOLEAN fTraceDebugger; // trace - send trace messages to the debugger
|
||
|
BOOLEAN fTraceTimestamp; // trace - time stamp trace messages
|
||
|
PWCHAR pTraceFileName;
|
||
|
PFILE_OBJECT pTraceFileObject;
|
||
|
PDEFERRED_TRACE pDeferredTrace;
|
||
|
} ICA_TRACE_INFO, *PICA_TRACE_INFO;
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Common header for all ICA objects
|
||
|
*/
|
||
|
typedef struct _ICA_HEADER {
|
||
|
ICA_TYPE Type;
|
||
|
PICA_DISPATCH *pDispatchTable;
|
||
|
} ICA_HEADER, *PICA_HEADER;
|
||
|
|
||
|
|
||
|
/*
|
||
|
* ICA connection object
|
||
|
*/
|
||
|
typedef struct _ICA_CONNECTION {
|
||
|
ICA_HEADER Header; // WARNING: This field MUST ALWAYS be first
|
||
|
LONG RefCount; // Reference count for this connection
|
||
|
ERESOURCE Resource; // Resource protecting access to this object
|
||
|
BOOLEAN fPassthruEnabled;
|
||
|
LIST_ENTRY StackHead; // List of stack objects for this connection
|
||
|
LIST_ENTRY ChannelHead; // List of channel objects for this connection
|
||
|
LIST_ENTRY VcBindHead; // List of vcbind objects for this connection
|
||
|
ICA_TRACE_INFO TraceInfo; // trace information
|
||
|
|
||
|
/*
|
||
|
* Channel pointers array. This array should be indexed using the
|
||
|
* channel number plus the virtual channel number. This allows a
|
||
|
* fast lookup of any bound channel given the channel/virtual number.
|
||
|
*/
|
||
|
struct _ICA_CHANNEL *pChannel[CHANNEL_COUNT+VIRTUAL_MAXIMUM];
|
||
|
ERESOURCE ChannelTableLock;
|
||
|
} ICA_CONNECTION, *PICA_CONNECTION;
|
||
|
|
||
|
|
||
|
//
|
||
|
// define the Maximum Low Water Mark setting to resume transmission
|
||
|
//
|
||
|
#define MAX_LOW_WATERMARK ((ULONG)((ULONG_PTR)-1))
|
||
|
/*
|
||
|
* ICA stack object
|
||
|
*/
|
||
|
typedef struct _ICA_STACK {
|
||
|
ICA_HEADER Header; // WARNING: This field MUST ALWAYS be first
|
||
|
LONG RefCount; // Reference count for this stack
|
||
|
ERESOURCE Resource; // Resource protecting access to this object
|
||
|
STACKCLASS StackClass; // Stack type (primary/shadow)
|
||
|
LIST_ENTRY StackEntry; // Links for connection object stack list
|
||
|
LIST_ENTRY SdLinkHead; // Head of SDLINK list for this stack
|
||
|
struct _ICA_STACK *pPassthru; // Pointer to passthru stack
|
||
|
BOOLEAN fIoDisabled;
|
||
|
BOOLEAN fClosing;
|
||
|
BOOLEAN fDoingInput;
|
||
|
BOOLEAN fDisablingIo;
|
||
|
KEVENT IoEndEvent;
|
||
|
LARGE_INTEGER LastInputTime; // last time of keyboard/mouse input
|
||
|
PVOID pBrokenEventObject;
|
||
|
|
||
|
/*
|
||
|
* Pointer to connection object.
|
||
|
* Note this is typed as PUCHAR instead of PICA_CONNECTION to prevent use
|
||
|
* of it directly. All references to the connection object a stack is
|
||
|
* attached to should be made by calling IcaGetConnectionForStack() if
|
||
|
* the stack is already locked, or IcaLockConnectionForStack() otherwise.
|
||
|
* This is required because this is a dynamic pointer, which can be
|
||
|
* modified during stack reconnect.
|
||
|
*/
|
||
|
PUCHAR pConnect; // Pointer to connection object
|
||
|
|
||
|
BOOLEAN fWaitForOutBuf; // outbuf - did we hit the high watermark
|
||
|
ULONG OutBufLength; // outbuf - length of output buffer
|
||
|
ULONG OutBufCount; // outbuf - maximum number of outbufs
|
||
|
ULONG OutBufAllocCount; // outbuf - number of outbufs allocated
|
||
|
KEVENT OutBufEvent; // outbuf - allocate event
|
||
|
ULONG SdOutBufHeader; // reserved output buffer header bytes
|
||
|
ULONG SdOutBufTrailer; // reserved output buffer trailer bytes
|
||
|
|
||
|
CLIENTMODULES ClientModules; // stack driver client module data
|
||
|
PROTOCOLSTATUS ProtocolStatus; // stack driver protocol status
|
||
|
|
||
|
LIST_ENTRY StackNode; // for linking all stacks together
|
||
|
LARGE_INTEGER LastKeepAliveTime; // Time last keepalive packet sent
|
||
|
ULONG OutBufLowWaterMark; // low water mark to resume transmission
|
||
|
} ICA_STACK, *PICA_STACK;
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Channel Filter Input/Output procedure prototype
|
||
|
*/
|
||
|
typedef NTSTATUS
|
||
|
(_stdcall * PFILTERPROC)( PVOID, PCHAR, ULONG, PINBUF * );
|
||
|
|
||
|
/*
|
||
|
* ICA channel filter object
|
||
|
*/
|
||
|
typedef struct _ICA_FILTER {
|
||
|
PFILTERPROC InputFilter; // Input filter procedure
|
||
|
PFILTERPROC OutputFilter; // Output filter procedure
|
||
|
} ICA_FILTER, *PICA_FILTER;
|
||
|
|
||
|
|
||
|
/*
|
||
|
* ICA virtual class bind structure
|
||
|
*/
|
||
|
typedef struct _ICA_VCBIND {
|
||
|
VIRTUALCHANNELNAME VirtualName; // Virtual channel name
|
||
|
VIRTUALCHANNELCLASS VirtualClass; // Virtual channel number (0-31, -1 unbound)
|
||
|
ULONG Flags;
|
||
|
LIST_ENTRY Links; // Links for vcbind structure list
|
||
|
} ICA_VCBIND, *PICA_VCBIND;
|
||
|
|
||
|
|
||
|
/*
|
||
|
* ICA channel object
|
||
|
*/
|
||
|
typedef struct _ICA_CHANNEL {
|
||
|
ICA_HEADER Header; // WARNING: This field MUST ALWAYS be first
|
||
|
LONG RefCount; // Reference count for this channel
|
||
|
ERESOURCE Resource; // Resource protecting access to this object
|
||
|
ULONG Flags; // Channel flags (see CHANNEL_xxx below)
|
||
|
LONG OpenCount; // Count of opens on this object
|
||
|
PICA_CONNECTION pConnect; // Pointer to connection object
|
||
|
PICA_FILTER pFilter; // Pointer to filter object for this channel
|
||
|
CHANNELCLASS ChannelClass; // Channel type
|
||
|
VIRTUALCHANNELNAME VirtualName; // Virtual channel name
|
||
|
VIRTUALCHANNELCLASS VirtualClass; // Virtual channel number (0-31, -1 unbound)
|
||
|
LIST_ENTRY Links; // Links for channel structure list
|
||
|
LIST_ENTRY InputIrpHead; // Head of pending IRP list
|
||
|
LIST_ENTRY InputBufHead; // Head of input buffer list
|
||
|
unsigned InputBufCurSize; // Bytes held in input buffers.
|
||
|
unsigned InputBufMaxSize; // High watermark for input buffers.
|
||
|
PERESOURCE pChannelTableLock;
|
||
|
ULONG CompletionRoutineCount;
|
||
|
} ICA_CHANNEL, *PICA_CHANNEL;
|
||
|
|
||
|
/*
|
||
|
* VirtualClass - virtual channel is not yet bound to a virtual class number
|
||
|
*/
|
||
|
#define UNBOUND_CHANNEL -1
|
||
|
|
||
|
/*
|
||
|
* Channel Flags
|
||
|
*/
|
||
|
#define CHANNEL_MESSAGE_MODE 0x00000001 // This is a message mode channel
|
||
|
#define CHANNEL_SHADOW_IO 0x00000002 // Pass shadow data
|
||
|
#define CHANNEL_SCREENDATA 0x00000004 // This is a screen data channel
|
||
|
#define CHANNEL_CLOSING 0x00000008 // This channel is being closed
|
||
|
#define CHANNEL_SHADOW_PERSISTENT 0x00000010 // Used for virtual channels: still up during shadow
|
||
|
#define CHANNEL_SESSION_DISABLEIO 0x00000020 // Used disable IO for help session while not in shadow mode
|
||
|
#define CHANNEL_CANCEL_READS 0x00000040 // To cancel reads to CommandChannel on Winstation termination
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Stack Driver load structure
|
||
|
* There exists exactly one of these structures for
|
||
|
* each Stack Driver (WD/PD/TD) loaded in the system.
|
||
|
*/
|
||
|
typedef struct _SDLOAD {
|
||
|
WDNAMEW SdName; // Name of this SD
|
||
|
LONG RefCount; // Reference count
|
||
|
LIST_ENTRY Links; // Links for SDLOAD list
|
||
|
PVOID ImageHandle; // Image handle for this driver
|
||
|
PVOID ImageBase; // Image base for this driver
|
||
|
PSDLOADPROC DriverLoad; // Pointer to driver load routine
|
||
|
PFILE_OBJECT FileObject; // Reference to underlying driver
|
||
|
PVOID pUnloadWorkItem;// Pointer to workitem for delayed unload
|
||
|
PDEVICE_OBJECT DeviceObject;// Pointer device object to use the unload safe completion routine
|
||
|
} SDLOAD, *PSDLOAD;
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Stack Driver link structure
|
||
|
* There exists one of these structures for each WD/PD/TD in a stack.
|
||
|
*/
|
||
|
typedef struct _SDLINK {
|
||
|
PICA_STACK pStack; // Pointer to ICA_STACK object for this driver
|
||
|
PSDLOAD pSdLoad; // Pointer to SDLOAD object for this driver
|
||
|
LIST_ENTRY Links; // Links for SDLINK list
|
||
|
LONG RefCount;
|
||
|
SDCONTEXT SdContext; // Contains SD proc table, context value, callup table
|
||
|
ERESOURCE Resource;
|
||
|
} SDLINK, * PSDLINK;
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Lock/Unlock macros
|
||
|
*/
|
||
|
#if DBG
|
||
|
|
||
|
/*
|
||
|
*
|
||
|
* NOTE: Under DBG builds, the following routines will validate
|
||
|
* that the correct locking order is not violated.
|
||
|
* The correct order is:
|
||
|
* 1) Connection
|
||
|
* 2) Stack
|
||
|
* 3) Channel
|
||
|
*/
|
||
|
BOOLEAN IcaLockConnection(PICA_CONNECTION);
|
||
|
void IcaUnlockConnection(PICA_CONNECTION);
|
||
|
|
||
|
BOOLEAN IcaLockStack(PICA_STACK);
|
||
|
void IcaUnlockStack(PICA_STACK);
|
||
|
|
||
|
BOOLEAN IcaLockChannel(PICA_CHANNEL);
|
||
|
void IcaUnlockChannel(PICA_CHANNEL);
|
||
|
|
||
|
#else // DBG
|
||
|
|
||
|
#define IcaLockConnection(p) { \
|
||
|
IcaReferenceConnection( p ); \
|
||
|
KeEnterCriticalRegion(); /* Disable APC calls */ \
|
||
|
ExAcquireResourceExclusiveLite( &p->Resource, TRUE ); \
|
||
|
}
|
||
|
#define IcaUnlockConnection(p) { \
|
||
|
ExReleaseResourceLite( &p->Resource ); \
|
||
|
KeLeaveCriticalRegion(); /* Re-enable APC calls */ \
|
||
|
IcaDereferenceConnection( p ); \
|
||
|
}
|
||
|
|
||
|
#define IcaLockStack(p) { \
|
||
|
IcaReferenceStack( p ); \
|
||
|
KeEnterCriticalRegion(); /* Disable APC calls */ \
|
||
|
ExAcquireResourceExclusiveLite( &p->Resource, TRUE ); \
|
||
|
}
|
||
|
#define IcaUnlockStack(p) { \
|
||
|
ExReleaseResourceLite( &p->Resource ); \
|
||
|
KeLeaveCriticalRegion(); /* Re-enable APC calls */ \
|
||
|
IcaDereferenceStack( p ); \
|
||
|
}
|
||
|
|
||
|
#define IcaLockChannel(p) { \
|
||
|
IcaReferenceChannel( p ); \
|
||
|
KeEnterCriticalRegion(); /* Disable APC calls */ \
|
||
|
ExAcquireResourceExclusiveLite( &p->Resource, TRUE ); \
|
||
|
}
|
||
|
#define IcaUnlockChannel(p) { \
|
||
|
ExReleaseResourceLite( &p->Resource ); \
|
||
|
KeLeaveCriticalRegion(); /* Re-enable APC calls */ \
|
||
|
IcaDereferenceChannel(p); \
|
||
|
}
|
||
|
|
||
|
|
||
|
#endif // DBG
|
||
|
|
||
|
PICA_CONNECTION IcaGetConnectionForStack(PICA_STACK);
|
||
|
|
||
|
PICA_CONNECTION IcaLockConnectionForStack(PICA_STACK);
|
||
|
|
||
|
void IcaUnlockConnectionForStack(PICA_STACK);
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Memory alloc/free macros
|
||
|
*/
|
||
|
#if DBG
|
||
|
|
||
|
PVOID IcaAllocatePool(IN POOL_TYPE, IN ULONG, PCHAR, ULONG, BOOLEAN);
|
||
|
|
||
|
#define ICA_ALLOCATE_POOL(a,b) IcaAllocatePool(a, b, __FILE__, __LINE__, FALSE)
|
||
|
#define ICA_ALLOCATE_POOL_WITH_QUOTA(a,b) IcaAllocatePool(a, b, __FILE__, __LINE__, TRUE)
|
||
|
|
||
|
void IcaFreePool (IN PVOID);
|
||
|
|
||
|
#define ICA_FREE_POOL(a) IcaFreePool(a)
|
||
|
|
||
|
#else // DBG
|
||
|
|
||
|
#define ICA_ALLOCATE_POOL(a,b) ExAllocatePoolWithTag(a,b,ICA_POOL_TAG)
|
||
|
#define ICA_ALLOCATE_POOL_WITH_QUOTA(a,b) ExAllocatePoolWithQuotaTag(a,b,ICA_POOL_TAG)
|
||
|
#define ICA_FREE_POOL(a) ExFreePool(a)
|
||
|
|
||
|
#endif // DBG
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Spinlock acquire/release macros
|
||
|
*/
|
||
|
#if DBG
|
||
|
|
||
|
extern ULONG IcaLocksAcquired;
|
||
|
|
||
|
#define IcaAcquireSpinLock(a,b) KeAcquireSpinLock((a),(b)); IcaLocksAcquired++
|
||
|
|
||
|
#define IcaReleaseSpinLock(a,b) IcaLocksAcquired--; KeReleaseSpinLock((a),(b))
|
||
|
|
||
|
void IcaInitializeDebugData(void);
|
||
|
|
||
|
#else // DBG
|
||
|
|
||
|
#define IcaAcquireSpinLock(a,b) KeAcquireSpinLock((a),(b))
|
||
|
#define IcaReleaseSpinLock(a,b) KeReleaseSpinLock((a),(b))
|
||
|
|
||
|
#endif // DBG
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Trace
|
||
|
*/
|
||
|
extern ICA_TRACE_INFO G_TraceInfo;
|
||
|
|
||
|
#undef TRACE
|
||
|
#undef TRACESTACK
|
||
|
#undef TRACESTACKBUF
|
||
|
#undef TRACECHANNEL
|
||
|
|
||
|
#if DBG
|
||
|
VOID _cdecl _IcaTrace( PICA_CONNECTION, ULONG, ULONG, CHAR *, ... );
|
||
|
VOID _cdecl _IcaStackTrace( PICA_STACK, ULONG, ULONG, CHAR *, ... );
|
||
|
VOID _IcaStackTraceBuffer( PICA_STACK, ULONG, ULONG, PVOID, ULONG );
|
||
|
VOID _cdecl _IcaChannelTrace( PICA_CHANNEL, ULONG, ULONG, CHAR *, ... );
|
||
|
|
||
|
#define TRACE(_arg) _IcaTrace _arg
|
||
|
#define TRACESTACK(_arg) _IcaStackTrace _arg
|
||
|
#define TRACESTACKBUF(_arg) _IcaStackTraceBuffer _arg
|
||
|
#define TRACECHANNEL(_arg) _IcaChannelTrace _arg
|
||
|
|
||
|
#else
|
||
|
|
||
|
#define TRACE(_arg)
|
||
|
#define TRACESTACK(_arg)
|
||
|
#define TRACESTACKBUF(_arg)
|
||
|
#define TRACECHANNEL(_arg)
|
||
|
|
||
|
#endif
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Need to define these to have MP save driver ( proper locked operation will generated for x86)-Bug# 209464
|
||
|
*/
|
||
|
|
||
|
#define _NTSRV_
|
||
|
#define _NTDDK_
|
||
|
|