/****************************************************************************/ // 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_