/*++ Copyright (c) 1999-2000 Microsoft Corporation Module Name : session.h Abstract: Session object is created to handle redirection for this session Revision History: --*/ #pragma once typedef enum enmSessionStatus { // cs csDisconnected, // Not yet connected, or disconnected csPendingClientConfirm, // ServerAnnounce sent, waiting for ClientConfirm csPendingClientReconfirm, // Insisted on ClientId, waiting for second ClientConfirm csConnected, // All connected, ready for devices or I/O csExpired // This client is gone } SessionState; class DrDevice; typedef struct tagWriteContext { IO_STATUS_BLOCK IoStatusBlock; SmartPtr Session; PVOID BufferToFree; PVOID AdditionalContext; ISessionPacketSender *PacketSender; DrWriteCallback WriteCallback; } DrWriteContext; // // Server capability set // typedef struct tagRDPDR_SERVER_COMBINED_CAPABILITYSET { RDPDR_CAPABILITY_SET_HEADER Header; #define RDPDR_NUM_SERVER_CAPABILITIES 5 RDPDR_GENERAL_CAPABILITY GeneralCap; #define RDPDR_SERVER_IO_CODES 0xFFFF RDPDR_PRINT_CAPABILITY PrintCap; RDPDR_PORT_CAPABILITY PortCap; RDPDR_FS_CAPABILITY FileSysCap; RDPDR_SMARTCARD_CAPABILITY SmartCardCap; } RDPDR_SERVER_COMBINED_CAPABILITYSET, *PRDPDR_SERVER_COMBINED_CAPABILITYSET; // // Server default capability set sent to client // const RDPDR_SERVER_COMBINED_CAPABILITYSET SERVER_CAPABILITY_SET_DEFAULT = { // Capability Set Header { { RDPDR_CTYP_CORE, DR_CORE_SERVER_CAPABILITY }, RDPDR_NUM_SERVER_CAPABILITIES, 0 }, // General Capability { RDPDR_GENERAL_CAPABILITY_TYPE, sizeof(RDPDR_GENERAL_CAPABILITY), RDPDR_GENERAL_CAPABILITY_VERSION_01, RDPDR_OS_TYPE_WINNT, // the OS type 0, // don't care about the version RDPDR_MAJOR_VERSION, RDPDR_MINOR_VERSION, RDPDR_SERVER_IO_CODES, 0, RDPDR_DEVICE_REMOVE_PDUS | RDPDR_CLIENT_DISPLAY_NAME_PDU, 0, 0 }, // Printing Capability { RDPDR_PRINT_CAPABILITY_TYPE, sizeof(RDPDR_PRINT_CAPABILITY), RDPDR_PRINT_CAPABILITY_VERSION_01 }, // Port Capability { RDPDR_PORT_CAPABILITY_TYPE, sizeof(RDPDR_PORT_CAPABILITY), RDPDR_PORT_CAPABILITY_VERSION_01 }, // FileSystem Capability { RDPDR_FS_CAPABILITY_TYPE, sizeof(RDPDR_FS_CAPABILITY), RDPDR_FS_CAPABILITY_VERSION_01 }, // SmartCard Capability { RDPDR_SMARTCARD_CAPABILITY_TYPE, sizeof(RDPDR_SMARTCARD_CAPABILITY), RDPDR_SMARTCARD_CAPABILITY_VERSION_01 } }; // // Default client capability set sent from client // const RDPDR_SERVER_COMBINED_CAPABILITYSET CLIENT_CAPABILITY_SET_DEFAULT = { // Capability Set Header { { RDPDR_CTYP_CORE, DR_CORE_CLIENT_CAPABILITY }, RDPDR_NUM_SERVER_CAPABILITIES, 0 }, // General Capability { RDPDR_GENERAL_CAPABILITY_TYPE, sizeof(RDPDR_GENERAL_CAPABILITY), 0, 0, // Need to specify the OS type 0, // Need to specify the OS version 0, 0, 0, 0, 0, 0, 0 }, // Printing Capability { RDPDR_PRINT_CAPABILITY_TYPE, sizeof(RDPDR_PRINT_CAPABILITY), 0 }, // Port Capability { RDPDR_PORT_CAPABILITY_TYPE, sizeof(RDPDR_PORT_CAPABILITY), 0 }, // FileSystem Capability { RDPDR_FS_CAPABILITY_TYPE, sizeof(RDPDR_FS_CAPABILITY), 0 }, // SmartCard Capability { RDPDR_SMARTCARD_CAPABILITY_TYPE, sizeof(RDPDR_SMARTCARD_CAPABILITY), 0 } }; // // The session is not like other RefCount objects, in that releasing the last // reference both deletes the object and removes it from the SessionMgr. As // a result, we need a special RefCount implementation that accomodates the // SessionMgr lock as well as the deletion of the object in an atomic operation // class DrSession : public TopObj, public ISessionPacketReceiver, public ISessionPacketSender { private: LONG _crefs; SmartPtr _Channel; DoubleList _PacketReceivers; KernelResource _ConnectNotificationLock; KernelResource _ConnectRDPDYNNotificationLock; // Need granular locking on notifying // RDPDYN so we don't deadlock. KernelResource _ChannelLock; ULONG _AutoClientDrives : 1; // Automatically map client drives ULONG _AutoClientLpts : 1; // Automatically install client printers ULONG _ForceClientLptDef : 1; // Set default printer to client default ULONG _DisableCpm : 1; // Disable Print mapping completely ULONG _DisableCdm : 1; // Disable Drive mapping ULONG _DisableCcm : 1; // Disable COM mapping ULONG _DisableLPT : 1; // Disable LPT port ULONG _DisableClip : 1; // Automatically redirect clipboard ULONG _DisableExe : 1; // I have no idea ULONG _DisableCam : 1; // Disable Audio mapping SessionState _SessionState; LONG _ConnectCount; PBYTE _ChannelBuffer; ULONG _ChannelBufferSize; KernelEvent _ChannelDeletionEvent; IO_STATUS_BLOCK _ReadStatus; ULONG _ClientId; // Id for this client (identifies SrvCall) DrExchangeManager _ExchangeManager; ULONG _PartialPacketData; WCHAR _ClientName[RDPDR_MAX_COMPUTER_NAME_LENGTH]; WCHAR _ClientDisplayName[RDPDR_MAX_CLIENT_DISPLAY_NAME]; DrDeviceManager _DeviceManager; ULONG _SessionId; RDPDR_VERSION _ClientVersion; RDPDR_SERVER_COMBINED_CAPABILITYSET _CliCapabilitySet; RDPDR_SERVER_COMBINED_CAPABILITYSET _SrvCapabilitySet; BOOL _Initialized; #if DBG LONG _BufCount; #define DEBUG_REF_BUF() /*ASSERT (InterlockedIncrement(&_BufCount) == 1)*/ #define DEBUG_DEREF_BUF() /*ASSERT (InterlockedDecrement(&_BufCount) == 0)*/ #else #define DEBUG_REF_BUF() #define DEBUG_DEREF_BUF() #endif VOID SetSessionState(SessionState inSessionState) { _SessionState = inSessionState; } #if DBG BOOL PacketReceiverExists(ISessionPacketReceiver *PacketReceiver); #endif // DBG BOOL FindChannelFromConnectIn(PULONG ChannelId, PCHANNEL_CONNECT_IN ConnectIn); VOID DeleteChannel(BOOL Wait); VOID SetChannel(SmartPtr &Channel); VOID RemoveDevices(); VOID CancelClientIO(); VOID ChannelIoFailed(); NTSTATUS ReallocateChannelBuffer(ULONG ulNewBufferSize, ULONG ulSaveBytes); // // Generic Sending and Receiving data // NTSTATUS PrivateSendToClient(PVOID Buffer, ULONG Length, ISessionPacketSender *PacketSender, DrWriteCallback WriteCallback, BOOL bWorkerItem, BOOL LowPrioWrite = FALSE, PVOID AdditionalContext = NULL); static NTSTATUS SendCompletionRoutine(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context); static NTSTATUS ReadCompletionRoutine(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context); VOID SendCompletion(DrWriteContext *WriteContext, PIO_STATUS_BLOCK IoStatusBlock); VOID ReadCompletion(PIO_STATUS_BLOCK IoStatusBlock); VOID ReadPacket(); virtual NTSTATUS SendCompleted(PVOID Context, PIO_STATUS_BLOCK IoStatusBlock); // // Packet sending // NTSTATUS ServerAnnounceWrite(); VOID SendClientConfirm(); VOID SendClientCapability(); VOID SendDeviceReply(ULONG DeviceId, NTSTATUS Result); // // Packets received // NTSTATUS OnClientIdConfirm(PRDPDR_HEADER RdpdrHeader, ULONG cbPacket, BOOL *DoDefaultRead); NTSTATUS InitClientCapability(PRDPDR_CAPABILITY_HEADER pCapHdr, ULONG *pPacketLen, BOOL *pCapSupported); NTSTATUS OnClientCapability(PRDPDR_HEADER RdpdrHeader, ULONG cbPacket, BOOL *DoDefaultRead); NTSTATUS OnClientName(PRDPDR_HEADER RdpdrHeader, ULONG cbPacket, BOOL *DoDefaultRead); NTSTATUS OnClientDisplayName(PRDPDR_HEADER RdpdrHeader, ULONG cbPacket, BOOL *DoDefaultRead); public: #if DBG LONG _ApcCount; LONG _ApcChannelRef; #endif DrSession(); virtual ~DrSession(); // // Lock/Unlock connect notification. // void LockConnectStateChange() { _ConnectNotificationLock.AcquireResourceExclusive(); } void UnlockConnectStateChange() { _ConnectNotificationLock.ReleaseResource(); } void LockRDPDYNConnectStateChange() { _ConnectRDPDYNNotificationLock.AcquireResourceExclusive(); } void UnlockRDPDYNConnectStateChange() { _ConnectRDPDYNNotificationLock.ReleaseResource(); } // // Session specific refcounting as discussed above // void AddRef(void) { ULONG crefs = InterlockedIncrement(&_crefs); } void Release(void); PBYTE GetBuffer() { return _ChannelBuffer; } BOOL IsConnected() { return _SessionState == csConnected; } PWCHAR GetClientName() { return &_ClientName[0]; } PWCHAR GetClientDisplayName() { if (_ClientDisplayName[0] != L'\0') { return &_ClientDisplayName[0]; } else { return &_ClientName[0]; } } ULONG GetSessionId() { return _SessionId; } void SetSessionId(ULONG SessionId) { _SessionId = SessionId; } ULONG GetState() { return _SessionState; } ULONG GetClientId() { return _ClientId; } RDPDR_VERSION &GetClientVersion() { return _ClientVersion; } RDPDR_SERVER_COMBINED_CAPABILITYSET &GetClientCapabilitySet() { return _CliCapabilitySet; } BOOL AutomapDrives() { return _AutoClientDrives != 0; } BOOL AutoInstallPrinters() { return _AutoClientLpts != 0; } BOOL SetDefaultPrinter() { return _ForceClientLptDef != 0; } BOOL DisablePrinterMapping() { return _DisableCpm != 0; } BOOL DisableDriveMapping() { return _DisableCdm != 0; } BOOL DisableComPortMapping() { return _DisableCcm != 0; } BOOL DisableLptPortMapping() { return _DisableLPT != 0; } BOOL DisableClipboardMapping() { return _DisableClip != 0; } BOOL DisableExe() { return _DisableExe != 0; } BOOL DisableAudioMapping() { return _DisableCam != 0; } DrExchangeManager &GetExchangeManager() { return _ExchangeManager; } virtual BOOL RecognizePacket(PRDPDR_HEADER RdpdrHeader); virtual NTSTATUS HandlePacket(PRDPDR_HEADER RdpdrHeader, ULONG Length, BOOL *DoDefaultRead); BOOL ReadMore(ULONG cbSaveData, ULONG cbWantData = 0); BOOL Initialize(); NTSTATUS RegisterPacketReceiver(ISessionPacketReceiver *PacketReceiver); VOID RemovePacketReceiver(ISessionPacketReceiver *PacketReceiver); NTSTATUS SendToClient(PVOID Buffer, ULONG Length, ISessionPacketSender *PacketSender, BOOL bWorkerItem, BOOL LowPrioSend = FALSE, PVOID AdditionalContext = NULL); NTSTATUS SendToClient(PVOID Buffer, ULONG Length, DrWriteCallback WriteCallback, BOOL bWorkerItem, BOOL LowPrioSend = FALSE, PVOID AdditionalContext = NULL); BOOL GetChannel(SmartPtr &Channel); BOOL Connect(PCHANNEL_CONNECT_IN ConnectIn, PCHANNEL_CONNECT_OUT ConnectOut); VOID Disconnect(PCHANNEL_DISCONNECT_IN DisconnectIn, PCHANNEL_DISCONNECT_OUT DisconnectOut); BOOL FindDeviceById(ULONG DeviceId, SmartPtr &DeviceFound, BOOL fMustBeValid = FALSE) { return _DeviceManager.FindDeviceById(DeviceId, DeviceFound, fMustBeValid); } BOOL FindDeviceByDosName(UCHAR* DeviceDosName, SmartPtr &DeviceFound, BOOL fMustBeValid = FALSE) { return _DeviceManager.FindDeviceByDosName(DeviceDosName, DeviceFound, fMustBeValid); } DrDeviceManager &GetDevMgr() { return _DeviceManager; } #if DBG VOID DumpUserConfigSettings(); #endif // DBG };