22#include <freerdp/config.h>
29#include <winpr/atexit.h>
30#include <winpr/wtypes.h>
32#include <winpr/synch.h>
33#include <winpr/stream.h>
34#include <winpr/assert.h>
35#include <winpr/cast.h>
37#include <freerdp/log.h>
38#include <freerdp/constants.h>
39#include <freerdp/server/channels.h>
40#include <freerdp/channels/drdynvc.h>
41#include <freerdp/utils/drdynvc.h>
47#define TAG FREERDP_TAG("core.server")
49#define DEBUG_DVC(...) WLog_DBG(TAG, __VA_ARGS__)
51#define DEBUG_DVC(...) \
57#define DVC_MAX_DATA_PDU_SIZE 1600
67static const DWORD g_err_oom = WINPR_CXX_COMPAT_CAST(DWORD, E_OUTOFMEMORY);
69static DWORD g_SessionId = 1;
70static wHashTable* g_ServerHandles =
nullptr;
71static INIT_ONCE g_HandleInitializer = INIT_ONCE_STATIC_INIT;
76 return HashTable_GetItemValue(vcm->dynamicVirtualChannels, &ChannelId);
79static BOOL wts_queue_receive_data(rdpPeerChannel* channel,
const BYTE* Buffer1,
size_t Length1,
80 const BYTE* Buffer2,
size_t Length2)
82 WINPR_ASSERT(channel);
84 if (Length1 > UINT32_MAX -
sizeof(wtsChannelMessage))
86 if (Length2 > UINT32_MAX -
sizeof(wtsChannelMessage) - Length1)
88 const size_t len = Length1 + Length2;
89 const size_t tlen =
sizeof(wtsChannelMessage) + len;
90 wtsChannelMessage* messageCtx = (wtsChannelMessage*)malloc(tlen);
94 WINPR_ASSERT(channel->channelId <= UINT16_MAX);
95 messageCtx->channelId = WINPR_ASSERTING_INT_CAST(UINT16, channel->channelId);
96 messageCtx->length = WINPR_ASSERTING_INT_CAST(UINT32, len);
97 messageCtx->offset = 0;
98 BYTE* buffer = (BYTE*)(&messageCtx[1]);
99 CopyMemory(buffer, Buffer1, Length1);
101 WINPR_ASSERT(Buffer2 || (Length2 == 0));
104 CopyMemory(buffer, Buffer2, Length2);
106 return MessageQueue_Post(channel->queue, messageCtx, 0,
nullptr,
nullptr);
109static BOOL wts_queue_send_item(rdpPeerChannel* channel, BYTE* Buffer, UINT32 Length)
111 BYTE* buffer =
nullptr;
114 WINPR_ASSERT(channel);
115 WINPR_ASSERT(channel->vcm);
119 WINPR_ASSERT(channel->channelId <= UINT16_MAX);
120 const UINT16 channelId = (UINT16)channel->channelId;
121 return MessageQueue_Post(channel->vcm->queue, (
void*)(UINT_PTR)channelId, 0, (
void*)buffer,
122 (
void*)(UINT_PTR)length);
125static unsigned wts_read_variable_uint(
wStream* s,
int cbLen, UINT32* val)
132 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
135 Stream_Read_UINT8(s, *val);
139 if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))
142 Stream_Read_UINT16(s, *val);
146 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
149 Stream_Read_UINT32(s, *val);
153 WLog_ERR(TAG,
"invalid wts variable uint len %d", cbLen);
158static BOOL wts_read_drdynvc_capabilities_response(rdpPeerChannel* channel,
wStream* s)
162 WINPR_ASSERT(channel);
163 WINPR_ASSERT(channel->vcm);
164 const size_t length = Stream_GetRemainingLength(s);
168 Stream_Seek_UINT8(s);
169 Stream_Read_UINT16(s, Version);
170 DEBUG_DVC(
"Version: %" PRIu16
"", Version);
174 WLog_ERR(TAG,
"invalid version %" PRIu16
" for DRDYNVC", Version);
179 vcm->drdynvc_state = DRDYNVC_STATE_READY;
182 vcm->dvc_spoken_version = MAX(Version, 1);
184 return SetEvent(MessageQueue_Event(vcm->queue));
187static BOOL wts_read_drdynvc_create_response(rdpPeerChannel* channel,
wStream* s)
189 UINT32 CreationStatus = 0;
192 WINPR_ASSERT(channel);
194 const size_t length = Stream_GetRemainingLength(s);
195 if ((length < 4) || (length > UINT32_MAX))
198 Stream_Read_UINT32(s, CreationStatus);
200 if ((INT32)CreationStatus < 0)
202 DEBUG_DVC(
"ChannelId %" PRIu32
" creation failed (%" PRId32
")", channel->channelId,
203 (INT32)CreationStatus);
204 channel->dvc_open_state = DVC_OPEN_STATE_FAILED;
208 DEBUG_DVC(
"ChannelId %" PRIu32
" creation succeeded", channel->channelId);
209 channel->dvc_open_state = DVC_OPEN_STATE_SUCCEEDED;
212 channel->creationStatus = (INT32)CreationStatus;
213 IFCALLRET(channel->vcm->dvc_creation_status, status, channel->vcm->dvc_creation_status_userdata,
214 channel->channelId, (INT32)CreationStatus);
216 WLog_ERR(TAG,
"vcm->dvc_creation_status failed!");
221static BOOL wts_read_drdynvc_data_first(rdpPeerChannel* channel,
wStream* s,
int cbLen)
223 WINPR_ASSERT(channel);
226 const UINT32 value = wts_read_variable_uint(s, cbLen, &channel->dvc_total_length);
231 const size_t length = Stream_GetRemainingLength(s);
232 if (length > channel->dvc_total_length)
235 Stream_ResetPosition(channel->receiveData);
237 if (!Stream_EnsureRemainingCapacity(channel->receiveData, length))
240 Stream_Write(channel->receiveData, Stream_ConstPointer(s), length);
244static BOOL wts_read_drdynvc_data(rdpPeerChannel* channel,
wStream* s)
248 WINPR_ASSERT(channel);
251 const size_t length = Stream_GetRemainingLength(s);
252 if (channel->dvc_total_length > 0)
254 const size_t pos = Stream_GetPosition(channel->receiveData);
255 if (pos > SIZE_MAX - length)
258 if (pos + length > channel->dvc_total_length)
260 channel->dvc_total_length = 0;
261 WLog_ERR(TAG,
"incorrect fragment data, discarded.");
265 if (!Stream_EnsureRemainingCapacity(channel->receiveData, length))
268 Stream_Write(channel->receiveData, Stream_ConstPointer(s), length);
270 if (Stream_GetPosition(channel->receiveData) >= channel->dvc_total_length)
272 ret = wts_queue_receive_data(channel, Stream_Buffer(channel->receiveData),
273 channel->dvc_total_length,
nullptr, 0);
274 channel->dvc_total_length = 0;
281 ret = wts_queue_receive_data(channel, Stream_ConstPointer(s), length,
nullptr, 0);
287static void wts_read_drdynvc_close_response(rdpPeerChannel* channel)
289 WINPR_ASSERT(channel);
290 DEBUG_DVC(
"ChannelId %" PRIu32
" close response", channel->channelId);
291 channel->dvc_open_state = DVC_OPEN_STATE_CLOSED;
292 MessageQueue_PostQuit(channel->queue, 0);
296static BOOL wts_read_drdynvc_pdu_ready_guarded(
wStream* s, UINT8 Cmd, UINT8 Sp, UINT32 ChannelId,
301 case CREATE_REQUEST_PDU:
302 return wts_read_drdynvc_create_response(dvc, s);
305 if (dvc->dvc_open_state != DVC_OPEN_STATE_SUCCEEDED)
308 "ChannelId %" PRIu32
" did not open successfully. "
309 "Ignoring DYNVC_DATA_FIRST PDU",
314 return wts_read_drdynvc_data_first(dvc, s, Sp);
317 if (dvc->dvc_open_state != DVC_OPEN_STATE_SUCCEEDED)
320 "ChannelId %" PRIu32
" did not open successfully. "
321 "Ignoring DYNVC_DATA PDU",
326 return wts_read_drdynvc_data(dvc, s);
328 case CLOSE_REQUEST_PDU:
329 wts_read_drdynvc_close_response(dvc);
332 case DATA_FIRST_COMPRESSED_PDU:
333 case DATA_COMPRESSED_PDU:
334 WLog_ERR(TAG,
"Compressed data not handled");
337 case SOFT_SYNC_RESPONSE_PDU:
338 WLog_ERR(TAG,
"SoftSync response not handled yet(and rather strange to receive "
339 "that packet as our code doesn't send SoftSync requests");
342 case SOFT_SYNC_REQUEST_PDU:
343 WLog_ERR(TAG,
"Not expecting a SoftSyncRequest on the server");
347 WLog_ERR(TAG,
"Cmd %d not recognized.", Cmd);
354static BOOL wts_read_drdynvc_pdu_ready(rdpPeerChannel* channel,
wStream* s, UINT8 Cmd, UINT8 Sp,
357 WINPR_ASSERT(channel);
359 BOOL haveChannelId = 0;
362 case SOFT_SYNC_REQUEST_PDU:
363 case SOFT_SYNC_RESPONSE_PDU:
364 haveChannelId = FALSE;
367 haveChannelId = TRUE;
371 UINT32 ChannelId = 0;
372 rdpPeerChannel* dvc =
nullptr;
373 wHashTable* table =
nullptr;
376 const unsigned val = wts_read_variable_uint(s, cbChId, &ChannelId);
380 DEBUG_DVC(
"Cmd %s ChannelId %" PRIu32
" length %" PRIuz
"", drdynvc_get_packet_type(Cmd),
381 ChannelId, Stream_GetRemainingLength(s));
382 table = channel->vcm->dynamicVirtualChannels;
385 HashTable_Lock(table);
386 dvc = wts_get_dvc_channel_by_id(channel->vcm, ChannelId);
389 DEBUG_DVC(
"ChannelId %" PRIu32
" does not exist.", ChannelId);
390 HashTable_Unlock(table);
395 const BOOL rc = wts_read_drdynvc_pdu_ready_guarded(s, Cmd, Sp, ChannelId, dvc);
397 HashTable_Unlock(table);
402static BOOL wts_read_drdynvc_pdu(rdpPeerChannel* channel)
404 WINPR_ASSERT(channel);
405 WINPR_ASSERT(channel->vcm);
407 const size_t slength = Stream_GetPosition(channel->receiveData);
408 if ((slength < 1) || (slength > UINT32_MAX))
411 Stream_ResetPosition(channel->receiveData);
412 wStream buffer = WINPR_C_ARRAY_INIT;
413 wStream* s = Stream_StaticConstInit(&buffer, Stream_Buffer(channel->receiveData), slength);
414 const UINT8 value = Stream_Get_UINT8(s);
415 const UINT8 Cmd = (value & 0xf0) >> 4;
416 const UINT8 Sp = (value & 0x0c) >> 2;
417 const UINT8 cbChId = (value & 0x03) >> 0;
419 if (Cmd == CAPABILITY_REQUEST_PDU)
420 return wts_read_drdynvc_capabilities_response(channel, s);
422 if (channel->vcm->drdynvc_state == DRDYNVC_STATE_READY)
423 return wts_read_drdynvc_pdu_ready(channel, s, Cmd, Sp, cbChId);
425 WLog_ERR(TAG,
"received Cmd %d but channel is not ready.", Cmd);
430static int wts_write_variable_uint(
wStream* s, UINT32 val)
438 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, val));
440 else if (val <= 0xFFFF)
443 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, val));
448 Stream_Write_UINT32(s, val);
454static void wts_write_drdynvc_header(
wStream* s, BYTE Cmd, UINT32 ChannelId)
458 BYTE* bm = Stream_PointerAs(s, BYTE);
459 Stream_Seek_UINT8(s);
460 const int cbChId = wts_write_variable_uint(s, ChannelId);
461 *bm = (((Cmd & 0x0F) << 4) | cbChId) & 0xFF;
464static BOOL wts_write_drdynvc_create_request(
wStream* s, UINT32 ChannelId,
const char* ChannelName)
469 WINPR_ASSERT(ChannelName);
471 wts_write_drdynvc_header(s, CREATE_REQUEST_PDU, ChannelId);
472 len = strlen(ChannelName) + 1;
474 if (!Stream_EnsureRemainingCapacity(s, len))
477 Stream_Write(s, ChannelName, len);
481static BOOL WTSProcessChannelData(rdpPeerChannel* channel, UINT16 channelId,
const BYTE* data,
482 size_t s, UINT32 flags,
size_t t)
486 const size_t totalSize = t;
488 WINPR_ASSERT(channel);
489 WINPR_ASSERT(channel->vcm);
490 WINPR_UNUSED(channelId);
492 if (channel->channelFlags & CHANNEL_OPTION_SHOW_PROTOCOL)
494 BOOL firstPass = TRUE;
498 const UINT32 payloadLen = (size > CHANNEL_CHUNK_LENGTH)
499 ? CHANNEL_CHUNK_LENGTH
500 : WINPR_ASSERTING_INT_CAST(UINT32, size);
510 if (flags & CHANNEL_FLAG_FIRST)
511 newFlags = CHANNEL_FLAG_FIRST;
514 if (!size && (flags & CHANNEL_FLAG_LAST))
515 newFlags |= CHANNEL_FLAG_LAST;
518 .length = payloadLen,
522 if (!wts_queue_receive_data(channel, (
const BYTE*)&header,
sizeof(header), data,
531 if ((flags & CHANNEL_FLAG_FIRST) != 0)
533 Stream_ResetPosition(channel->receiveData);
536 if (!Stream_EnsureRemainingCapacity(channel->receiveData, size))
539 Stream_Write(channel->receiveData, data, size);
541 if ((flags & CHANNEL_FLAG_LAST) != 0)
543 if (Stream_GetPosition(channel->receiveData) != totalSize)
546 if (channel == channel->vcm->drdynvc_channel)
548 ret = wts_read_drdynvc_pdu(channel);
552 const size_t pos = Stream_GetPosition(channel->receiveData);
553 if (pos > UINT32_MAX)
556 ret = wts_queue_receive_data(channel, Stream_Buffer(channel->receiveData), pos,
560 Stream_ResetPosition(channel->receiveData);
562 else if (Stream_GetPosition(channel->receiveData) >= totalSize)
568static BOOL WTSReceiveChannelData(freerdp_peer* client, UINT16 channelId,
const BYTE* data,
569 size_t size, UINT32 flags,
size_t totalSize)
571 rdpMcs* mcs =
nullptr;
573 WINPR_ASSERT(client);
574 WINPR_ASSERT(client->context);
575 WINPR_ASSERT(client->context->rdp);
577 mcs = client->context->rdp->mcs;
580 for (UINT32 i = 0; i < mcs->channelCount; i++)
582 rdpMcsChannel* cur = &mcs->channels[i];
583 if (cur->ChannelId == channelId)
585 rdpPeerChannel* channel = (rdpPeerChannel*)cur->handle;
588 return WTSProcessChannelData(channel, channelId, data, size, flags, totalSize);
592 WLog_WARN(TAG,
"unknown channelId %" PRIu16
" ignored", channelId);
597#if defined(WITH_FREERDP_DEPRECATED)
598void WTSVirtualChannelManagerGetFileDescriptor(HANDLE hServer,
void** fds,
int* fds_count)
604 WINPR_ASSERT(fds_count);
606 fd = GetEventWaitObject(MessageQueue_Event(vcm->queue));
610 fds[*fds_count] = fd;
616 if (vcm->drdynvc_channel)
618 fd = GetEventWaitObject(vcm->drdynvc_channel->receiveEvent);
622 fds[*fds_count] = fd;
631BOOL WTSVirtualChannelManagerOpen(HANDLE hServer)
638 if (vcm->drdynvc_state == DRDYNVC_STATE_NONE)
640 rdpPeerChannel* channel =
nullptr;
643 vcm->drdynvc_state = DRDYNVC_STATE_INITIALIZED;
644 channel = (rdpPeerChannel*)WTSVirtualChannelOpen((HANDLE)vcm, WTS_CURRENT_SESSION,
645 DRDYNVC_SVC_CHANNEL_NAME);
649 BYTE capaBuffer[12] = WINPR_C_ARRAY_INIT;
650 wStream staticS = WINPR_C_ARRAY_INIT;
651 wStream* s = Stream_StaticInit(&staticS, capaBuffer,
sizeof(capaBuffer));
653 vcm->drdynvc_channel = channel;
654 vcm->dvc_spoken_version = 1;
655 Stream_Write_UINT8(s, 0x50);
656 Stream_Write_UINT8(s, 0x00);
657 Stream_Write_UINT16(s, 0x0001);
661 const size_t pos = Stream_GetPosition(s);
662 WINPR_ASSERT(pos <= UINT32_MAX);
664 if (!WTSVirtualChannelWrite(channel, (PCHAR)capaBuffer, (UINT32)pos, &written))
672BOOL WTSVirtualChannelManagerCheckFileDescriptorEx(HANDLE hServer, BOOL autoOpen)
674 wMessage message = WINPR_C_ARRAY_INIT;
678 if (!hServer || hServer == INVALID_HANDLE_VALUE)
685 if (!WTSVirtualChannelManagerOpen(hServer))
689 while (MessageQueue_Peek(vcm->queue, &message, TRUE))
691 BYTE* buffer =
nullptr;
693 UINT16 channelId = 0;
694 channelId = (UINT16)(UINT_PTR)message.context;
695 buffer = (BYTE*)message.wParam;
696 length = (UINT32)(UINT_PTR)message.lParam;
698 WINPR_ASSERT(vcm->client);
699 WINPR_ASSERT(vcm->client->SendChannelData);
700 if (!vcm->client->SendChannelData(vcm->client, channelId, buffer, length))
714BOOL WTSVirtualChannelManagerCheckFileDescriptor(HANDLE hServer)
716 return WTSVirtualChannelManagerCheckFileDescriptorEx(hServer, TRUE);
719HANDLE WTSVirtualChannelManagerGetEventHandle(HANDLE hServer)
723 return MessageQueue_Event(vcm->queue);
726static rdpMcsChannel* wts_get_joined_channel_by_name(rdpMcs* mcs,
const char* channel_name)
728 if (!mcs || !channel_name || !strnlen(channel_name, CHANNEL_NAME_LEN + 1))
731 for (UINT32 index = 0; index < mcs->channelCount; index++)
733 rdpMcsChannel* mchannel = &mcs->channels[index];
734 if (mchannel->joined)
736 if (_strnicmp(mchannel->Name, channel_name, CHANNEL_NAME_LEN + 1) == 0)
744static rdpMcsChannel* wts_get_joined_channel_by_id(rdpMcs* mcs,
const UINT16 channel_id)
746 if (!mcs || !channel_id)
749 WINPR_ASSERT(mcs->channels);
750 for (UINT32 index = 0; index < mcs->channelCount; index++)
752 rdpMcsChannel* mchannel = &mcs->channels[index];
753 if (mchannel->joined)
755 if (mchannel->ChannelId == channel_id)
756 return &mcs->channels[index];
763BOOL WTSIsChannelJoinedByName(freerdp_peer* client,
const char* channel_name)
765 if (!client || !client->context || !client->context->rdp)
768 return (wts_get_joined_channel_by_name(client->context->rdp->mcs, channel_name) !=
nullptr);
771BOOL WTSIsChannelJoinedById(freerdp_peer* client, UINT16 channel_id)
773 if (!client || !client->context || !client->context->rdp)
776 return (wts_get_joined_channel_by_id(client->context->rdp->mcs, channel_id) !=
nullptr);
779BOOL WTSVirtualChannelManagerIsChannelJoined(HANDLE hServer,
const char* name)
783 if (!vcm || !vcm->rdp)
786 return (wts_get_joined_channel_by_name(vcm->rdp->mcs, name) !=
nullptr);
789BYTE WTSVirtualChannelManagerGetDrdynvcState(HANDLE hServer)
793 return vcm->drdynvc_state;
796void WTSVirtualChannelManagerSetDVCCreationCallback(HANDLE hServer, psDVCCreationStatusCallback cb,
803 vcm->dvc_creation_status = cb;
804 vcm->dvc_creation_status_userdata = userdata;
807UINT16 WTSChannelGetId(freerdp_peer* client,
const char* channel_name)
809 rdpMcsChannel* channel =
nullptr;
811 WINPR_ASSERT(channel_name);
812 if (!client || !client->context || !client->context->rdp)
815 channel = wts_get_joined_channel_by_name(client->context->rdp->mcs, channel_name);
820 return channel->ChannelId;
823UINT32 WTSChannelGetIdByHandle(HANDLE hChannelHandle)
825 rdpPeerChannel* channel = hChannelHandle;
827 WINPR_ASSERT(channel);
829 return channel->channelId;
832BOOL WTSChannelSetHandleByName(freerdp_peer* client,
const char* channel_name,
void* handle)
834 rdpMcsChannel* channel =
nullptr;
836 WINPR_ASSERT(channel_name);
837 if (!client || !client->context || !client->context->rdp)
840 channel = wts_get_joined_channel_by_name(client->context->rdp->mcs, channel_name);
845 channel->handle = handle;
849BOOL WTSChannelSetHandleById(freerdp_peer* client, UINT16 channel_id,
void* handle)
851 rdpMcsChannel* channel =
nullptr;
853 if (!client || !client->context || !client->context->rdp)
856 channel = wts_get_joined_channel_by_id(client->context->rdp->mcs, channel_id);
861 channel->handle = handle;
865void* WTSChannelGetHandleByName(freerdp_peer* client,
const char* channel_name)
867 rdpMcsChannel* channel =
nullptr;
869 WINPR_ASSERT(channel_name);
870 if (!client || !client->context || !client->context->rdp)
873 channel = wts_get_joined_channel_by_name(client->context->rdp->mcs, channel_name);
878 return channel->handle;
881void* WTSChannelGetHandleById(freerdp_peer* client, UINT16 channel_id)
883 rdpMcsChannel* channel =
nullptr;
885 if (!client || !client->context || !client->context->rdp)
888 channel = wts_get_joined_channel_by_id(client->context->rdp->mcs, channel_id);
893 return channel->handle;
896const char* WTSChannelGetName(freerdp_peer* client, UINT16 channel_id)
898 rdpMcsChannel* channel =
nullptr;
900 if (!client || !client->context || !client->context->rdp)
903 channel = wts_get_joined_channel_by_id(client->context->rdp->mcs, channel_id);
908 return (
const char*)channel->Name;
911char** WTSGetAcceptedChannelNames(freerdp_peer* client,
size_t* count)
913 rdpMcs* mcs =
nullptr;
914 char** names =
nullptr;
916 if (!client || !client->context || !count)
919 WINPR_ASSERT(client->context->rdp);
920 mcs = client->context->rdp->mcs;
922 *count = mcs->channelCount;
924 names = (
char**)calloc(mcs->channelCount,
sizeof(
char*));
928 for (UINT32 index = 0; index < mcs->channelCount; index++)
930 rdpMcsChannel* mchannel = &mcs->channels[index];
931 names[index] = mchannel->Name;
937INT64 WTSChannelGetOptions(freerdp_peer* client, UINT16 channel_id)
939 rdpMcsChannel* channel =
nullptr;
941 if (!client || !client->context || !client->context->rdp)
944 channel = wts_get_joined_channel_by_id(client->context->rdp->mcs, channel_id);
949 return (INT64)channel->options;
952BOOL WINAPI FreeRDP_WTSStartRemoteControlSessionW(WINPR_ATTR_UNUSED LPWSTR pTargetServerName,
953 WINPR_ATTR_UNUSED ULONG TargetLogonId,
954 WINPR_ATTR_UNUSED BYTE HotkeyVk,
955 WINPR_ATTR_UNUSED USHORT HotkeyModifiers)
957 WLog_ERR(
"TODO",
"TODO: implement");
961BOOL WINAPI FreeRDP_WTSStartRemoteControlSessionA(WINPR_ATTR_UNUSED LPSTR pTargetServerName,
962 WINPR_ATTR_UNUSED ULONG TargetLogonId,
963 WINPR_ATTR_UNUSED BYTE HotkeyVk,
964 WINPR_ATTR_UNUSED USHORT HotkeyModifiers)
966 WLog_ERR(
"TODO",
"TODO: implement");
970BOOL WINAPI FreeRDP_WTSStartRemoteControlSessionExW(WINPR_ATTR_UNUSED LPWSTR pTargetServerName,
971 WINPR_ATTR_UNUSED ULONG TargetLogonId,
972 WINPR_ATTR_UNUSED BYTE HotkeyVk,
973 WINPR_ATTR_UNUSED USHORT HotkeyModifiers,
974 WINPR_ATTR_UNUSED DWORD flags)
976 WLog_ERR(
"TODO",
"TODO: implement");
980BOOL WINAPI FreeRDP_WTSStartRemoteControlSessionExA(WINPR_ATTR_UNUSED LPSTR pTargetServerName,
981 WINPR_ATTR_UNUSED ULONG TargetLogonId,
982 WINPR_ATTR_UNUSED BYTE HotkeyVk,
983 WINPR_ATTR_UNUSED USHORT HotkeyModifiers,
984 WINPR_ATTR_UNUSED DWORD flags)
986 WLog_ERR(
"TODO",
"TODO: implement");
990BOOL WINAPI FreeRDP_WTSStopRemoteControlSession(WINPR_ATTR_UNUSED ULONG LogonId)
992 WLog_ERR(
"TODO",
"TODO: implement");
996BOOL WINAPI FreeRDP_WTSConnectSessionW(WINPR_ATTR_UNUSED ULONG LogonId,
997 WINPR_ATTR_UNUSED ULONG TargetLogonId,
998 WINPR_ATTR_UNUSED PWSTR pPassword,
999 WINPR_ATTR_UNUSED BOOL bWait)
1001 WLog_ERR(
"TODO",
"TODO: implement");
1005BOOL WINAPI FreeRDP_WTSConnectSessionA(WINPR_ATTR_UNUSED ULONG LogonId,
1006 WINPR_ATTR_UNUSED ULONG TargetLogonId,
1007 WINPR_ATTR_UNUSED PSTR pPassword,
1008 WINPR_ATTR_UNUSED BOOL bWait)
1010 WLog_ERR(
"TODO",
"TODO: implement");
1014BOOL WINAPI FreeRDP_WTSEnumerateServersW(WINPR_ATTR_UNUSED LPWSTR pDomainName,
1015 WINPR_ATTR_UNUSED DWORD Reserved,
1016 WINPR_ATTR_UNUSED DWORD Version,
1018 WINPR_ATTR_UNUSED DWORD* pCount)
1020 WLog_ERR(
"TODO",
"TODO: implement");
1024BOOL WINAPI FreeRDP_WTSEnumerateServersA(WINPR_ATTR_UNUSED LPSTR pDomainName,
1025 WINPR_ATTR_UNUSED DWORD Reserved,
1026 WINPR_ATTR_UNUSED DWORD Version,
1028 WINPR_ATTR_UNUSED DWORD* pCount)
1030 WLog_ERR(
"TODO",
"TODO: implement");
1034HANDLE WINAPI FreeRDP_WTSOpenServerW(WINPR_ATTR_UNUSED LPWSTR pServerName)
1036 WLog_ERR(
"TODO",
"TODO: implement");
1037 return INVALID_HANDLE_VALUE;
1040static void wts_virtual_channel_manager_free_message(
void* obj)
1042 wMessage* msg = (wMessage*)obj;
1046 BYTE* buffer = (BYTE*)msg->wParam;
1053static void channel_free(rdpPeerChannel* channel)
1055 server_channel_common_free(channel);
1058static void array_channel_free(
void* ptr)
1060 rdpPeerChannel* channel = ptr;
1061 channel_free(channel);
1064static BOOL dynChannelMatch(
const void* v1,
const void* v2)
1066 const UINT32* p1 = (
const UINT32*)v1;
1067 const UINT32* p2 = (
const UINT32*)v2;
1071static UINT32 channelId_Hash(
const void* key)
1073 const UINT32* v = (
const UINT32*)key;
1077static void clearHandles(
void)
1079 HashTable_Free(g_ServerHandles);
1080 g_ServerHandles =
nullptr;
1083static BOOL CALLBACK initializeHandles(WINPR_ATTR_UNUSED
PINIT_ONCE once,
1084 WINPR_ATTR_UNUSED PVOID param,
1085 WINPR_ATTR_UNUSED PVOID* context)
1087 WINPR_ASSERT(g_ServerHandles ==
nullptr);
1088 g_ServerHandles = HashTable_New(TRUE);
1089 (void)winpr_atexit(clearHandles);
1090 return g_ServerHandles !=
nullptr;
1093static bool setup(
void)
1095 return InitOnceExecuteOnce(&g_HandleInitializer, initializeHandles,
nullptr,
nullptr);
1102 HashTable_Lock(g_ServerHandles);
1106#ifdef __clang_analyzer__
1107 const BOOL valid = vcm !=
nullptr;
1109 const BOOL valid = (vcm !=
nullptr) && (vcm != INVALID_HANDLE_VALUE);
1113 HashTable_Remove(g_ServerHandles, (
void*)(UINT_PTR)vcm->SessionId);
1115 HashTable_Free(vcm->dynamicVirtualChannels);
1117 if (vcm->drdynvc_channel)
1120 (void)WTSVirtualChannelClose(vcm->drdynvc_channel);
1121 vcm->drdynvc_channel =
nullptr;
1124 MessageQueue_Free(vcm->queue);
1127 HashTable_Unlock(g_ServerHandles);
1130HANDLE WINAPI FreeRDP_WTSOpenServerA(LPSTR pServerName)
1132 wObject queueCallbacks = WINPR_C_ARRAY_INIT;
1134 rdpContext* context = WINPR_PACKED_ALIGN_CAST(rdpContext*, pServerName);
1136 if (!setup() || !context)
1137 return INVALID_HANDLE_VALUE;
1139 freerdp_peer* client = context->peer;
1143 SetLastError(ERROR_INVALID_DATA);
1144 return INVALID_HANDLE_VALUE;
1152 vcm->client = client;
1153 vcm->rdp = context->rdp;
1155 queueCallbacks.
fnObjectFree = wts_virtual_channel_manager_free_message;
1156 vcm->queue = MessageQueue_New(&queueCallbacks);
1161 vcm->dvc_channel_id_seq = 0;
1162 vcm->dynamicVirtualChannels = HashTable_New(TRUE);
1164 if (!vcm->dynamicVirtualChannels)
1167 if (!HashTable_SetHashFunction(vcm->dynamicVirtualChannels, channelId_Hash))
1171 wObject* obj = HashTable_ValueObject(vcm->dynamicVirtualChannels);
1175 obj = HashTable_KeyObject(vcm->dynamicVirtualChannels);
1178 client->ReceiveChannelData = WTSReceiveChannelData;
1180 HashTable_Lock(g_ServerHandles);
1181 vcm->SessionId = g_SessionId++;
1183 HashTable_Insert(g_ServerHandles, (
void*)(UINT_PTR)vcm->SessionId, (
void*)vcm);
1184 HashTable_Unlock(g_ServerHandles);
1189 HANDLE hServer = (HANDLE)vcm;
1193 wtsCloseVCM(vcm,
false);
1194 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1195 return INVALID_HANDLE_VALUE;
1198HANDLE WINAPI FreeRDP_WTSOpenServerExW(WINPR_ATTR_UNUSED LPWSTR pServerName)
1200 WLog_ERR(
"TODO",
"TODO: implement");
1201 return INVALID_HANDLE_VALUE;
1204HANDLE WINAPI FreeRDP_WTSOpenServerExA(LPSTR pServerName)
1206 return FreeRDP_WTSOpenServerA(pServerName);
1209VOID WINAPI FreeRDP_WTSCloseServer(HANDLE hServer)
1212 wtsCloseVCM(vcm,
true);
1215BOOL WINAPI FreeRDP_WTSEnumerateSessionsW(WINPR_ATTR_UNUSED HANDLE hServer,
1216 WINPR_ATTR_UNUSED DWORD Reserved,
1217 WINPR_ATTR_UNUSED DWORD Version,
1219 WINPR_ATTR_UNUSED DWORD* pCount)
1221 WLog_ERR(
"TODO",
"TODO: implement");
1225BOOL WINAPI FreeRDP_WTSEnumerateSessionsA(WINPR_ATTR_UNUSED HANDLE hServer,
1226 WINPR_ATTR_UNUSED DWORD Reserved,
1227 WINPR_ATTR_UNUSED DWORD Version,
1229 WINPR_ATTR_UNUSED DWORD* pCount)
1231 WLog_ERR(
"TODO",
"TODO: implement");
1235BOOL WINAPI FreeRDP_WTSEnumerateSessionsExW(WINPR_ATTR_UNUSED HANDLE hServer,
1236 WINPR_ATTR_UNUSED DWORD* pLevel,
1237 WINPR_ATTR_UNUSED DWORD Filter,
1239 WINPR_ATTR_UNUSED DWORD* pCount)
1241 WLog_ERR(
"TODO",
"TODO: implement");
1245BOOL WINAPI FreeRDP_WTSEnumerateSessionsExA(WINPR_ATTR_UNUSED HANDLE hServer,
1246 WINPR_ATTR_UNUSED DWORD* pLevel,
1247 WINPR_ATTR_UNUSED DWORD Filter,
1249 WINPR_ATTR_UNUSED DWORD* pCount)
1251 WLog_ERR(
"TODO",
"TODO: implement");
1255BOOL WINAPI FreeRDP_WTSEnumerateProcessesW(WINPR_ATTR_UNUSED HANDLE hServer,
1256 WINPR_ATTR_UNUSED DWORD Reserved,
1257 WINPR_ATTR_UNUSED DWORD Version,
1259 WINPR_ATTR_UNUSED DWORD* pCount)
1261 WLog_ERR(
"TODO",
"TODO: implement");
1265BOOL WINAPI FreeRDP_WTSEnumerateProcessesA(WINPR_ATTR_UNUSED HANDLE hServer,
1266 WINPR_ATTR_UNUSED DWORD Reserved,
1267 WINPR_ATTR_UNUSED DWORD Version,
1269 WINPR_ATTR_UNUSED DWORD* pCount)
1271 WLog_ERR(
"TODO",
"TODO: implement");
1275BOOL WINAPI FreeRDP_WTSTerminateProcess(WINPR_ATTR_UNUSED HANDLE hServer,
1276 WINPR_ATTR_UNUSED DWORD ProcessId,
1277 WINPR_ATTR_UNUSED DWORD ExitCode)
1279 WLog_ERR(
"TODO",
"TODO: implement");
1283BOOL WINAPI FreeRDP_WTSQuerySessionInformationW(WINPR_ATTR_UNUSED HANDLE hServer,
1284 WINPR_ATTR_UNUSED DWORD SessionId,
1285 WINPR_ATTR_UNUSED WTS_INFO_CLASS WTSInfoClass,
1286 WINPR_ATTR_UNUSED LPWSTR* ppBuffer,
1287 WINPR_ATTR_UNUSED DWORD* pBytesReturned)
1289 WLog_ERR(
"TODO",
"TODO: implement");
1293BOOL WINAPI FreeRDP_WTSQuerySessionInformationA(HANDLE hServer, WINPR_ATTR_UNUSED DWORD SessionId,
1294 WTS_INFO_CLASS WTSInfoClass, LPSTR* ppBuffer,
1295 DWORD* pBytesReturned)
1297 DWORD BytesReturned = 0;
1304 if (WTSInfoClass == WTSSessionId)
1306 ULONG* pBuffer =
nullptr;
1307 BytesReturned =
sizeof(ULONG);
1308 pBuffer = (ULONG*)malloc(
sizeof(BytesReturned));
1312 SetLastError(g_err_oom);
1316 *pBuffer = vcm->SessionId;
1317 *ppBuffer = (LPSTR)pBuffer;
1318 *pBytesReturned = BytesReturned;
1325BOOL WINAPI FreeRDP_WTSQueryUserConfigW(WINPR_ATTR_UNUSED LPWSTR pServerName,
1326 WINPR_ATTR_UNUSED LPWSTR pUserName,
1327 WINPR_ATTR_UNUSED WTS_CONFIG_CLASS WTSConfigClass,
1328 WINPR_ATTR_UNUSED LPWSTR* ppBuffer,
1329 WINPR_ATTR_UNUSED DWORD* pBytesReturned)
1331 WLog_ERR(
"TODO",
"TODO: implement");
1335BOOL WINAPI FreeRDP_WTSQueryUserConfigA(WINPR_ATTR_UNUSED LPSTR pServerName,
1336 WINPR_ATTR_UNUSED LPSTR pUserName,
1337 WINPR_ATTR_UNUSED WTS_CONFIG_CLASS WTSConfigClass,
1338 WINPR_ATTR_UNUSED LPSTR* ppBuffer,
1339 WINPR_ATTR_UNUSED DWORD* pBytesReturned)
1341 WLog_ERR(
"TODO",
"TODO: implement");
1345BOOL WINAPI FreeRDP_WTSSetUserConfigW(WINPR_ATTR_UNUSED LPWSTR pServerName,
1346 WINPR_ATTR_UNUSED LPWSTR pUserName,
1347 WINPR_ATTR_UNUSED WTS_CONFIG_CLASS WTSConfigClass,
1348 WINPR_ATTR_UNUSED LPWSTR pBuffer,
1349 WINPR_ATTR_UNUSED DWORD DataLength)
1351 WLog_ERR(
"TODO",
"TODO: implement");
1355BOOL WINAPI FreeRDP_WTSSetUserConfigA(WINPR_ATTR_UNUSED LPSTR pServerName,
1356 WINPR_ATTR_UNUSED LPSTR pUserName,
1357 WINPR_ATTR_UNUSED WTS_CONFIG_CLASS WTSConfigClass,
1358 WINPR_ATTR_UNUSED LPSTR pBuffer,
1359 WINPR_ATTR_UNUSED DWORD DataLength)
1361 WLog_ERR(
"TODO",
"TODO: implement");
1366FreeRDP_WTSSendMessageW(WINPR_ATTR_UNUSED HANDLE hServer, WINPR_ATTR_UNUSED DWORD SessionId,
1367 WINPR_ATTR_UNUSED LPWSTR pTitle, WINPR_ATTR_UNUSED DWORD TitleLength,
1368 WINPR_ATTR_UNUSED LPWSTR pMessage, WINPR_ATTR_UNUSED DWORD MessageLength,
1369 WINPR_ATTR_UNUSED DWORD Style, WINPR_ATTR_UNUSED DWORD Timeout,
1370 WINPR_ATTR_UNUSED DWORD* pResponse, WINPR_ATTR_UNUSED BOOL bWait)
1372 WLog_ERR(
"TODO",
"TODO: implement");
1377FreeRDP_WTSSendMessageA(WINPR_ATTR_UNUSED HANDLE hServer, WINPR_ATTR_UNUSED DWORD SessionId,
1378 WINPR_ATTR_UNUSED LPSTR pTitle, WINPR_ATTR_UNUSED DWORD TitleLength,
1379 WINPR_ATTR_UNUSED LPSTR pMessage, WINPR_ATTR_UNUSED DWORD MessageLength,
1380 WINPR_ATTR_UNUSED DWORD Style, WINPR_ATTR_UNUSED DWORD Timeout,
1381 WINPR_ATTR_UNUSED DWORD* pResponse, WINPR_ATTR_UNUSED BOOL bWait)
1383 WLog_ERR(
"TODO",
"TODO: implement");
1387BOOL WINAPI FreeRDP_WTSDisconnectSession(WINPR_ATTR_UNUSED HANDLE hServer,
1388 WINPR_ATTR_UNUSED DWORD SessionId,
1389 WINPR_ATTR_UNUSED BOOL bWait)
1391 WLog_ERR(
"TODO",
"TODO: implement");
1395BOOL WINAPI FreeRDP_WTSLogoffSession(WINPR_ATTR_UNUSED HANDLE hServer,
1396 WINPR_ATTR_UNUSED DWORD SessionId,
1397 WINPR_ATTR_UNUSED BOOL bWait)
1399 WLog_ERR(
"TODO",
"TODO: implement");
1403BOOL WINAPI FreeRDP_WTSShutdownSystem(WINPR_ATTR_UNUSED HANDLE hServer,
1404 WINPR_ATTR_UNUSED DWORD ShutdownFlag)
1406 WLog_ERR(
"TODO",
"TODO: implement");
1410BOOL WINAPI FreeRDP_WTSWaitSystemEvent(WINPR_ATTR_UNUSED HANDLE hServer,
1411 WINPR_ATTR_UNUSED DWORD EventMask,
1412 WINPR_ATTR_UNUSED DWORD* pEventFlags)
1414 WLog_ERR(
"TODO",
"TODO: implement");
1418static void peer_channel_queue_free_message(
void* obj)
1420 wMessage* msg = (wMessage*)obj;
1425 msg->context =
nullptr;
1429 UINT32 ChannelId, UINT16 index, UINT16 type,
size_t chunkSize,
1430 const char* name, UINT32 flags)
1432 wObject queueCallbacks = WINPR_C_ARRAY_INIT;
1433 queueCallbacks.
fnObjectFree = peer_channel_queue_free_message;
1435 rdpPeerChannel* channel =
1436 server_channel_common_new(client, index, ChannelId, chunkSize, &queueCallbacks, name);
1439 WINPR_ASSERT(client);
1445 channel->channelType = type;
1446 channel->creationStatus =
1447 (type == RDP_PEER_CHANNEL_TYPE_SVC) ? ERROR_SUCCESS : ERROR_OPERATION_IN_PROGRESS;
1448 channel->channelFlags = flags;
1452 channel_free(channel);
1456static HANDLE WINAPI FreeRDP_WTSVirtualChannelOpenStatic(HANDLE hServer,
1457 WINPR_ATTR_UNUSED DWORD SessionId,
1458 LPSTR pVirtualName, UINT32 Flags)
1463 SetLastError(ERROR_INVALID_DATA);
1467 freerdp_peer* client = vcm->client;
1468 WINPR_ASSERT(client);
1470 rdpContext* context = client->context;
1471 WINPR_ASSERT(context);
1472 WINPR_ASSERT(context->rdp);
1473 WINPR_ASSERT(context->settings);
1475 rdpMcs* mcs = context->rdp->mcs;
1478 size_t length = strnlen(pVirtualName, CHANNEL_NAME_LEN + 1);
1479 if (length > CHANNEL_NAME_LEN)
1481 SetLastError(ERROR_NOT_FOUND);
1485 rdpMcsChannel* joined_channel =
nullptr;
1487 for (; index < mcs->channelCount; index++)
1489 rdpMcsChannel* mchannel = &mcs->channels[index];
1490 if (mchannel->joined && (strncmp(mchannel->Name, pVirtualName, length) == 0))
1492 joined_channel = mchannel;
1497 if (!joined_channel)
1499 SetLastError(ERROR_NOT_FOUND);
1503 rdpPeerChannel* channel = (rdpPeerChannel*)joined_channel->handle;
1506 const UINT32 VCChunkSize =
1509 WINPR_ASSERT(index <= UINT16_MAX);
1510 channel = channel_new(vcm, client, joined_channel->ChannelId, (UINT16)index,
1511 RDP_PEER_CHANNEL_TYPE_SVC, VCChunkSize, pVirtualName, Flags);
1516 joined_channel->handle = channel;
1519 HANDLE hChannelHandle = (HANDLE)channel;
1520 return hChannelHandle;
1522 channel_free(channel);
1523 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1527HANDLE WINAPI FreeRDP_WTSVirtualChannelOpen(HANDLE hServer, DWORD SessionId, LPSTR pVirtualName)
1529 return FreeRDP_WTSVirtualChannelOpenStatic(hServer, SessionId, pVirtualName, 0);
1532HANDLE WINAPI FreeRDP_WTSVirtualChannelOpenEx(DWORD SessionId, LPSTR pVirtualName, DWORD flags)
1535 rdpPeerChannel* channel =
nullptr;
1536 BOOL joined = FALSE;
1542 if (SessionId == WTS_CURRENT_SESSION)
1545 HashTable_Lock(g_ServerHandles);
1547 g_ServerHandles, (
void*)(UINT_PTR)SessionId);
1552 if (!(flags & WTS_CHANNEL_OPTION_DYNAMIC))
1554 HashTable_Unlock(g_ServerHandles);
1555 return FreeRDP_WTSVirtualChannelOpenStatic((HANDLE)vcm, SessionId, pVirtualName, flags);
1558 freerdp_peer* client = vcm->client;
1559 WINPR_ASSERT(client);
1560 WINPR_ASSERT(client->context);
1561 WINPR_ASSERT(client->context->rdp);
1563 rdpMcs* mcs = client->context->rdp->mcs;
1566 for (UINT32 index = 0; index < mcs->channelCount; index++)
1568 rdpMcsChannel* mchannel = &mcs->channels[index];
1569 if (mchannel->joined &&
1570 (strncmp(mchannel->Name, DRDYNVC_SVC_CHANNEL_NAME, CHANNEL_NAME_LEN + 1) == 0))
1579 SetLastError(ERROR_NOT_FOUND);
1583 if (!vcm->drdynvc_channel || (vcm->drdynvc_state != DRDYNVC_STATE_READY))
1585 SetLastError(ERROR_NOT_READY);
1589 WINPR_ASSERT(client);
1590 WINPR_ASSERT(client->context);
1591 WINPR_ASSERT(client->context->settings);
1593 const UINT32 VCChunkSize =
1596 channel_new(vcm, client, 0, 0, RDP_PEER_CHANNEL_TYPE_DVC, VCChunkSize, pVirtualName, flags);
1600 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1604 const LONG hdl = InterlockedIncrement(&vcm->dvc_channel_id_seq);
1605 channel->channelId = WINPR_ASSERTING_INT_CAST(uint32_t, hdl);
1607 if (!HashTable_Insert(vcm->dynamicVirtualChannels, &channel->channelId, channel))
1609 channel_free(channel);
1613 s = Stream_New(
nullptr, 64);
1618 if (!wts_write_drdynvc_create_request(s, channel->channelId, pVirtualName))
1622 const size_t pos = Stream_GetPosition(s);
1623 WINPR_ASSERT(pos <= UINT32_MAX);
1624 if (!WTSVirtualChannelWrite(vcm->drdynvc_channel, Stream_BufferAs(s,
char), (UINT32)pos,
1630 Stream_Free(s, TRUE);
1631 HashTable_Unlock(g_ServerHandles);
1635 Stream_Free(s, TRUE);
1637 HashTable_Remove(vcm->dynamicVirtualChannels, &channel->channelId);
1638 HashTable_Unlock(g_ServerHandles);
1640 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1644BOOL WINAPI FreeRDP_WTSVirtualChannelClose(HANDLE hChannelHandle)
1647 rdpMcs* mcs =
nullptr;
1649 rdpPeerChannel* channel = (rdpPeerChannel*)hChannelHandle;
1657 WINPR_ASSERT(vcm->client);
1658 WINPR_ASSERT(vcm->client->context);
1659 WINPR_ASSERT(vcm->client->context->rdp);
1660 mcs = vcm->client->context->rdp->mcs;
1662 if (channel->channelType == RDP_PEER_CHANNEL_TYPE_SVC)
1664 if (channel->index < mcs->channelCount)
1666 rdpMcsChannel* cur = &mcs->channels[channel->index];
1667 rdpPeerChannel* peerChannel = (rdpPeerChannel*)cur->handle;
1668 channel_free(peerChannel);
1669 cur->handle =
nullptr;
1674 if (channel->dvc_open_state == DVC_OPEN_STATE_SUCCEEDED)
1677 s = Stream_New(
nullptr, 8);
1681 WLog_ERR(TAG,
"Stream_New failed!");
1686 wts_write_drdynvc_header(s, CLOSE_REQUEST_PDU, channel->channelId);
1688 const size_t pos = Stream_GetPosition(s);
1689 WINPR_ASSERT(pos <= UINT32_MAX);
1690 ret = WTSVirtualChannelWrite(vcm->drdynvc_channel, Stream_BufferAs(s,
char),
1691 (UINT32)pos, &written);
1692 Stream_Free(s, TRUE);
1695 HashTable_Remove(vcm->dynamicVirtualChannels, &channel->channelId);
1702BOOL WINAPI FreeRDP_WTSVirtualChannelRead(HANDLE hChannelHandle, WINPR_ATTR_UNUSED ULONG TimeOut,
1703 PCHAR Buffer, ULONG BufferSize, PULONG pBytesRead)
1705 BYTE* buffer =
nullptr;
1706 wMessage message = WINPR_C_ARRAY_INIT;
1707 wtsChannelMessage* messageCtx =
nullptr;
1708 rdpPeerChannel* channel = (rdpPeerChannel*)hChannelHandle;
1710 WINPR_ASSERT(channel);
1712 if (!MessageQueue_Peek(channel->queue, &message, FALSE))
1714 SetLastError(ERROR_NO_DATA);
1719 messageCtx = message.context;
1721 if (messageCtx ==
nullptr)
1724 buffer = (BYTE*)(messageCtx + 1);
1725 *pBytesRead = messageCtx->length - messageCtx->offset;
1727 if (Buffer ==
nullptr || BufferSize == 0)
1732 if (*pBytesRead > BufferSize)
1733 *pBytesRead = BufferSize;
1735 CopyMemory(Buffer, buffer + messageCtx->offset, *pBytesRead);
1736 messageCtx->offset += *pBytesRead;
1738 if (messageCtx->offset >= messageCtx->length)
1740 const int rc = MessageQueue_Peek(channel->queue, &message, TRUE);
1741 peer_channel_queue_free_message(&message);
1749BOOL WINAPI FreeRDP_WTSVirtualChannelWrite(HANDLE hChannelHandle, PCHAR Buffer, ULONG uLength,
1750 PULONG pBytesWritten)
1756 BYTE* buffer =
nullptr;
1757 size_t totalWritten = 0;
1758 rdpPeerChannel* channel = (rdpPeerChannel*)hChannelHandle;
1764 EnterCriticalSection(&channel->writeLock);
1765 WINPR_ASSERT(channel->vcm);
1766 if (channel->channelType == RDP_PEER_CHANNEL_TYPE_SVC)
1768 buffer = (BYTE*)malloc(uLength);
1772 SetLastError(g_err_oom);
1776 CopyMemory(buffer, Buffer, uLength);
1777 totalWritten = uLength;
1778 if (!wts_queue_send_item(channel, buffer, uLength))
1781 else if (!channel->vcm->drdynvc_channel || (channel->vcm->drdynvc_state != DRDYNVC_STATE_READY))
1783 DEBUG_DVC(
"drdynvc not ready");
1790 size_t Length = uLength;
1793 s = Stream_New(
nullptr, DVC_MAX_DATA_PDU_SIZE);
1797 WLog_ERR(TAG,
"Stream_New failed!");
1798 SetLastError(g_err_oom);
1802 buffer = Stream_Buffer(s);
1803 Stream_Seek_UINT8(s);
1804 cbChId = wts_write_variable_uint(s, channel->channelId);
1806 if (first && (Length > Stream_GetRemainingLength(s)))
1808 cbLen = wts_write_variable_uint(s, WINPR_ASSERTING_INT_CAST(uint32_t, Length));
1809 buffer[0] = ((DATA_FIRST_PDU << 4) | (cbLen << 2) | cbChId) & 0xFF;
1813 buffer[0] = ((DATA_PDU << 4) | cbChId) & 0xFF;
1817 size_t written = Stream_GetRemainingLength(s);
1819 if (written > Length)
1822 Stream_Write(s, Buffer, written);
1823 const size_t length = Stream_GetPosition(s);
1824 Stream_Free(s, FALSE);
1825 if (length > UINT32_MAX)
1829 totalWritten += written;
1830 if (!wts_queue_send_item(channel->vcm->drdynvc_channel, buffer, (UINT32)length))
1836 *pBytesWritten = WINPR_ASSERTING_INT_CAST(uint32_t, totalWritten);
1840 LeaveCriticalSection(&channel->writeLock);
1844BOOL WINAPI FreeRDP_WTSVirtualChannelPurgeInput(WINPR_ATTR_UNUSED HANDLE hChannelHandle)
1846 WLog_ERR(
"TODO",
"TODO: implement");
1850BOOL WINAPI FreeRDP_WTSVirtualChannelPurgeOutput(WINPR_ATTR_UNUSED HANDLE hChannelHandle)
1852 WLog_ERR(
"TODO",
"TODO: implement");
1856BOOL WINAPI FreeRDP_WTSVirtualChannelQuery(HANDLE hChannelHandle, WTS_VIRTUAL_CLASS WtsVirtualClass,
1857 PVOID* ppBuffer, DWORD* pBytesReturned)
1859 void* pfd =
nullptr;
1861 void* fds[10] = WINPR_C_ARRAY_INIT;
1862 HANDLE hEvent =
nullptr;
1864 BOOL status = FALSE;
1865 rdpPeerChannel* channel = (rdpPeerChannel*)hChannelHandle;
1867 WINPR_ASSERT(channel);
1869 switch ((UINT32)WtsVirtualClass)
1871 case WTSVirtualFileHandle:
1872 hEvent = MessageQueue_Event(channel->queue);
1873 pfd = GetEventWaitObject(hEvent);
1877 fds[fds_count] = pfd;
1881 *ppBuffer = malloc(
sizeof(
void*));
1885 SetLastError(g_err_oom);
1889 CopyMemory(*ppBuffer, (
void*)&fds[0],
sizeof(
void*));
1890 *pBytesReturned =
sizeof(
void*);
1896 case WTSVirtualEventHandle:
1897 hEvent = MessageQueue_Event(channel->queue);
1899 *ppBuffer = malloc(
sizeof(HANDLE));
1903 SetLastError(g_err_oom);
1907 CopyMemory(*ppBuffer, (
void*)&hEvent,
sizeof(HANDLE));
1908 *pBytesReturned =
sizeof(
void*);
1914 case WTSVirtualChannelReady:
1915 if (channel->channelType == RDP_PEER_CHANNEL_TYPE_SVC)
1922 switch (channel->dvc_open_state)
1924 case DVC_OPEN_STATE_NONE:
1929 case DVC_OPEN_STATE_SUCCEEDED:
1935 *ppBuffer =
nullptr;
1936 *pBytesReturned = 0;
1941 *ppBuffer = malloc(
sizeof(BOOL));
1945 SetLastError(g_err_oom);
1950 CopyMemory(*ppBuffer, &bval,
sizeof(BOOL));
1951 *pBytesReturned =
sizeof(BOOL);
1955 case WTSVirtualChannelOpenStatus:
1957 INT32 value = channel->creationStatus;
1960 *ppBuffer = malloc(
sizeof(value));
1963 SetLastError(g_err_oom);
1968 CopyMemory(*ppBuffer, &value,
sizeof(value));
1969 *pBytesReturned =
sizeof(value);
1980VOID WINAPI FreeRDP_WTSFreeMemory(PVOID pMemory)
1985BOOL WINAPI FreeRDP_WTSFreeMemoryExW(WINPR_ATTR_UNUSED WTS_TYPE_CLASS WTSTypeClass,
1986 WINPR_ATTR_UNUSED PVOID pMemory,
1987 WINPR_ATTR_UNUSED ULONG NumberOfEntries)
1989 WLog_ERR(
"TODO",
"TODO: implement");
1993BOOL WINAPI FreeRDP_WTSFreeMemoryExA(WINPR_ATTR_UNUSED WTS_TYPE_CLASS WTSTypeClass,
1994 WINPR_ATTR_UNUSED PVOID pMemory,
1995 WINPR_ATTR_UNUSED ULONG NumberOfEntries)
1997 WLog_ERR(
"TODO",
"TODO: implement");
2001BOOL WINAPI FreeRDP_WTSRegisterSessionNotification(WINPR_ATTR_UNUSED HWND hWnd,
2002 WINPR_ATTR_UNUSED DWORD dwFlags)
2004 WLog_ERR(
"TODO",
"TODO: implement");
2008BOOL WINAPI FreeRDP_WTSUnRegisterSessionNotification(WINPR_ATTR_UNUSED HWND hWnd)
2010 WLog_ERR(
"TODO",
"TODO: implement");
2014BOOL WINAPI FreeRDP_WTSRegisterSessionNotificationEx(WINPR_ATTR_UNUSED HANDLE hServer,
2015 WINPR_ATTR_UNUSED HWND hWnd,
2016 WINPR_ATTR_UNUSED DWORD dwFlags)
2018 WLog_ERR(
"TODO",
"TODO: implement");
2022BOOL WINAPI FreeRDP_WTSUnRegisterSessionNotificationEx(WINPR_ATTR_UNUSED HANDLE hServer,
2023 WINPR_ATTR_UNUSED HWND hWnd)
2025 WLog_ERR(
"TODO",
"TODO: implement");
2029BOOL WINAPI FreeRDP_WTSQueryUserToken(WINPR_ATTR_UNUSED ULONG SessionId,
2030 WINPR_ATTR_UNUSED PHANDLE phToken)
2032 WLog_ERR(
"TODO",
"TODO: implement");
2036BOOL WINAPI FreeRDP_WTSEnumerateProcessesExW(WINPR_ATTR_UNUSED HANDLE hServer,
2037 WINPR_ATTR_UNUSED DWORD* pLevel,
2038 WINPR_ATTR_UNUSED DWORD SessionId,
2039 WINPR_ATTR_UNUSED LPWSTR* ppProcessInfo,
2040 WINPR_ATTR_UNUSED DWORD* pCount)
2042 WLog_ERR(
"TODO",
"TODO: implement");
2046BOOL WINAPI FreeRDP_WTSEnumerateProcessesExA(WINPR_ATTR_UNUSED HANDLE hServer,
2047 WINPR_ATTR_UNUSED DWORD* pLevel,
2048 WINPR_ATTR_UNUSED DWORD SessionId,
2049 WINPR_ATTR_UNUSED LPSTR* ppProcessInfo,
2050 WINPR_ATTR_UNUSED DWORD* pCount)
2052 WLog_ERR(
"TODO",
"TODO: implement");
2056BOOL WINAPI FreeRDP_WTSEnumerateListenersW(WINPR_ATTR_UNUSED HANDLE hServer,
2057 WINPR_ATTR_UNUSED PVOID pReserved,
2058 WINPR_ATTR_UNUSED DWORD Reserved,
2059 WINPR_ATTR_UNUSED PWTSLISTENERNAMEW pListeners,
2060 WINPR_ATTR_UNUSED DWORD* pCount)
2062 WLog_ERR(
"TODO",
"TODO: implement");
2066BOOL WINAPI FreeRDP_WTSEnumerateListenersA(WINPR_ATTR_UNUSED HANDLE hServer,
2067 WINPR_ATTR_UNUSED PVOID pReserved,
2068 WINPR_ATTR_UNUSED DWORD Reserved,
2069 WINPR_ATTR_UNUSED PWTSLISTENERNAMEA pListeners,
2070 WINPR_ATTR_UNUSED DWORD* pCount)
2072 WLog_ERR(
"TODO",
"TODO: implement");
2076BOOL WINAPI FreeRDP_WTSQueryListenerConfigW(WINPR_ATTR_UNUSED HANDLE hServer,
2077 WINPR_ATTR_UNUSED PVOID pReserved,
2078 WINPR_ATTR_UNUSED DWORD Reserved,
2079 WINPR_ATTR_UNUSED LPWSTR pListenerName,
2082 WLog_ERR(
"TODO",
"TODO: implement");
2086BOOL WINAPI FreeRDP_WTSQueryListenerConfigA(WINPR_ATTR_UNUSED HANDLE hServer,
2087 WINPR_ATTR_UNUSED PVOID pReserved,
2088 WINPR_ATTR_UNUSED DWORD Reserved,
2089 WINPR_ATTR_UNUSED LPSTR pListenerName,
2092 WLog_ERR(
"TODO",
"TODO: implement");
2096BOOL WINAPI FreeRDP_WTSCreateListenerW(WINPR_ATTR_UNUSED HANDLE hServer,
2097 WINPR_ATTR_UNUSED PVOID pReserved,
2098 WINPR_ATTR_UNUSED DWORD Reserved,
2099 WINPR_ATTR_UNUSED LPWSTR pListenerName,
2101 WINPR_ATTR_UNUSED DWORD flag)
2103 WLog_ERR(
"TODO",
"TODO: implement");
2107BOOL WINAPI FreeRDP_WTSCreateListenerA(WINPR_ATTR_UNUSED HANDLE hServer,
2108 WINPR_ATTR_UNUSED PVOID pReserved,
2109 WINPR_ATTR_UNUSED DWORD Reserved,
2110 WINPR_ATTR_UNUSED LPSTR pListenerName,
2112 WINPR_ATTR_UNUSED DWORD flag)
2114 WLog_ERR(
"TODO",
"TODO: implement");
2118BOOL WINAPI FreeRDP_WTSSetListenerSecurityW(
2119 WINPR_ATTR_UNUSED HANDLE hServer, WINPR_ATTR_UNUSED PVOID pReserved,
2120 WINPR_ATTR_UNUSED DWORD Reserved, WINPR_ATTR_UNUSED LPWSTR pListenerName,
2121 WINPR_ATTR_UNUSED SECURITY_INFORMATION SecurityInformation,
2122 WINPR_ATTR_UNUSED PSECURITY_DESCRIPTOR pSecurityDescriptor)
2124 WLog_ERR(
"TODO",
"TODO: implement");
2128BOOL WINAPI FreeRDP_WTSSetListenerSecurityA(
2129 WINPR_ATTR_UNUSED HANDLE hServer, WINPR_ATTR_UNUSED PVOID pReserved,
2130 WINPR_ATTR_UNUSED DWORD Reserved, WINPR_ATTR_UNUSED LPSTR pListenerName,
2131 WINPR_ATTR_UNUSED SECURITY_INFORMATION SecurityInformation,
2132 WINPR_ATTR_UNUSED PSECURITY_DESCRIPTOR pSecurityDescriptor)
2134 WLog_ERR(
"TODO",
"TODO: implement");
2138BOOL WINAPI FreeRDP_WTSGetListenerSecurityW(
2139 WINPR_ATTR_UNUSED HANDLE hServer, WINPR_ATTR_UNUSED PVOID pReserved,
2140 WINPR_ATTR_UNUSED DWORD Reserved, WINPR_ATTR_UNUSED LPWSTR pListenerName,
2141 WINPR_ATTR_UNUSED SECURITY_INFORMATION SecurityInformation,
2142 WINPR_ATTR_UNUSED PSECURITY_DESCRIPTOR pSecurityDescriptor, WINPR_ATTR_UNUSED DWORD nLength,
2143 WINPR_ATTR_UNUSED LPDWORD lpnLengthNeeded)
2145 WLog_ERR(
"TODO",
"TODO: implement");
2149BOOL WINAPI FreeRDP_WTSGetListenerSecurityA(
2150 WINPR_ATTR_UNUSED HANDLE hServer, WINPR_ATTR_UNUSED PVOID pReserved,
2151 WINPR_ATTR_UNUSED DWORD Reserved, WINPR_ATTR_UNUSED LPSTR pListenerName,
2152 WINPR_ATTR_UNUSED SECURITY_INFORMATION SecurityInformation,
2153 WINPR_ATTR_UNUSED PSECURITY_DESCRIPTOR pSecurityDescriptor, WINPR_ATTR_UNUSED DWORD nLength,
2154 WINPR_ATTR_UNUSED LPDWORD lpnLengthNeeded)
2156 WLog_ERR(
"TODO",
"TODO: implement");
2160BOOL CDECL FreeRDP_WTSEnableChildSessions(WINPR_ATTR_UNUSED BOOL bEnable)
2162 WLog_ERR(
"TODO",
"TODO: implement");
2166BOOL CDECL FreeRDP_WTSIsChildSessionsEnabled(WINPR_ATTR_UNUSED PBOOL pbEnabled)
2168 WLog_ERR(
"TODO",
"TODO: implement");
2172BOOL CDECL FreeRDP_WTSGetChildSessionId(WINPR_ATTR_UNUSED PULONG pSessionId)
2174 WLog_ERR(
"TODO",
"TODO: implement");
2178DWORD WINAPI FreeRDP_WTSGetActiveConsoleSessionId(
void)
2180 WLog_ERR(
"TODO",
"TODO: implement");
2183BOOL WINAPI FreeRDP_WTSLogoffUser(WINPR_ATTR_UNUSED HANDLE hServer)
2185 WLog_ERR(
"TODO",
"TODO: implement");
2189BOOL WINAPI FreeRDP_WTSLogonUser(WINPR_ATTR_UNUSED HANDLE hServer,
2190 WINPR_ATTR_UNUSED LPCSTR username,
2191 WINPR_ATTR_UNUSED LPCSTR password, WINPR_ATTR_UNUSED LPCSTR domain)
2193 WLog_ERR(
"TODO",
"TODO: implement");
2197void server_channel_common_free(rdpPeerChannel* channel)
2201 MessageQueue_Free(channel->queue);
2202 Stream_Free(channel->receiveData, TRUE);
2203 DeleteCriticalSection(&channel->writeLock);
2207rdpPeerChannel* server_channel_common_new(freerdp_peer* client, UINT16 index, UINT32 channelId,
2208 size_t chunkSize,
const wObject* callback,
2211 rdpPeerChannel* channel = (rdpPeerChannel*)calloc(1,
sizeof(rdpPeerChannel));
2215 InitializeCriticalSection(&channel->writeLock);
2217 channel->receiveData = Stream_New(
nullptr, chunkSize);
2218 if (!channel->receiveData)
2221 channel->queue = MessageQueue_New(callback);
2222 if (!channel->queue)
2225 channel->index = index;
2226 channel->client = client;
2227 channel->channelId = channelId;
2228 strncpy(channel->channelName, name, ARRAYSIZE(channel->channelName) - 1);
2231 WINPR_PRAGMA_DIAG_PUSH
2232 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
2233 server_channel_common_free(channel);
2234 WINPR_PRAGMA_DIAG_POP
WINPR_ATTR_NODISCARD FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
This struct contains function pointer to initialize/free objects.
OBJECT_FREE_FN fnObjectFree
WINPR_ATTR_NODISCARD OBJECT_EQUALS_FN fnObjectEquals