Leaked source code of windows server 2003
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

/*++
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
};