You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
399 lines
13 KiB
399 lines
13 KiB
/*++
|
|
|
|
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<DrSession> 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<VirtualChannel> _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<VirtualChannel> &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<VirtualChannel> &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<DrDevice> &DeviceFound,
|
|
BOOL fMustBeValid = FALSE)
|
|
{
|
|
return _DeviceManager.FindDeviceById(DeviceId, DeviceFound, fMustBeValid);
|
|
}
|
|
BOOL FindDeviceByDosName(UCHAR* DeviceDosName, SmartPtr<DrDevice> &DeviceFound,
|
|
BOOL fMustBeValid = FALSE)
|
|
{
|
|
return _DeviceManager.FindDeviceByDosName(DeviceDosName, DeviceFound, fMustBeValid);
|
|
}
|
|
|
|
DrDeviceManager &GetDevMgr() {
|
|
return _DeviceManager;
|
|
}
|
|
|
|
#if DBG
|
|
VOID DumpUserConfigSettings();
|
|
#endif // DBG
|
|
};
|