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, channel->dvc_total_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 Stream_Write(channel->receiveData, Stream_ConstPointer(s), length);
267 if (Stream_GetPosition(channel->receiveData) >= channel->dvc_total_length)
269 ret = wts_queue_receive_data(channel, Stream_Buffer(channel->receiveData),
270 channel->dvc_total_length,
nullptr, 0);
271 channel->dvc_total_length = 0;
278 ret = wts_queue_receive_data(channel, Stream_ConstPointer(s), length,
nullptr, 0);
284static void wts_read_drdynvc_close_response(rdpPeerChannel* channel)
286 WINPR_ASSERT(channel);
287 DEBUG_DVC(
"ChannelId %" PRIu32
" close response", channel->channelId);
288 channel->dvc_open_state = DVC_OPEN_STATE_CLOSED;
289 MessageQueue_PostQuit(channel->queue, 0);
293static BOOL wts_read_drdynvc_pdu_ready_guarded(
wStream* s, UINT8 Cmd, UINT8 Sp, UINT32 ChannelId,
298 case CREATE_REQUEST_PDU:
299 return wts_read_drdynvc_create_response(dvc, s);
302 if (dvc->dvc_open_state != DVC_OPEN_STATE_SUCCEEDED)
305 "ChannelId %" PRIu32
" did not open successfully. "
306 "Ignoring DYNVC_DATA_FIRST PDU",
311 return wts_read_drdynvc_data_first(dvc, s, Sp);
314 if (dvc->dvc_open_state != DVC_OPEN_STATE_SUCCEEDED)
317 "ChannelId %" PRIu32
" did not open successfully. "
318 "Ignoring DYNVC_DATA PDU",
323 return wts_read_drdynvc_data(dvc, s);
325 case CLOSE_REQUEST_PDU:
326 wts_read_drdynvc_close_response(dvc);
329 case DATA_FIRST_COMPRESSED_PDU:
330 case DATA_COMPRESSED_PDU:
331 WLog_ERR(TAG,
"Compressed data not handled");
334 case SOFT_SYNC_RESPONSE_PDU:
335 WLog_ERR(TAG,
"SoftSync response not handled yet(and rather strange to receive "
336 "that packet as our code doesn't send SoftSync requests");
339 case SOFT_SYNC_REQUEST_PDU:
340 WLog_ERR(TAG,
"Not expecting a SoftSyncRequest on the server");
344 WLog_ERR(TAG,
"Cmd %d not recognized.", Cmd);
351static BOOL wts_read_drdynvc_pdu_ready(rdpPeerChannel* channel,
wStream* s, UINT8 Cmd, UINT8 Sp,
354 WINPR_ASSERT(channel);
356 BOOL haveChannelId = 0;
359 case SOFT_SYNC_REQUEST_PDU:
360 case SOFT_SYNC_RESPONSE_PDU:
361 haveChannelId = FALSE;
364 haveChannelId = TRUE;
368 UINT32 ChannelId = 0;
369 rdpPeerChannel* dvc =
nullptr;
370 wHashTable* table =
nullptr;
373 const unsigned val = wts_read_variable_uint(s, cbChId, &ChannelId);
377 DEBUG_DVC(
"Cmd %s ChannelId %" PRIu32
" length %" PRIuz
"", drdynvc_get_packet_type(Cmd),
378 ChannelId, Stream_GetRemainingLength(s));
379 table = channel->vcm->dynamicVirtualChannels;
382 HashTable_Lock(table);
383 dvc = wts_get_dvc_channel_by_id(channel->vcm, ChannelId);
386 DEBUG_DVC(
"ChannelId %" PRIu32
" does not exist.", ChannelId);
387 HashTable_Unlock(table);
392 const BOOL rc = wts_read_drdynvc_pdu_ready_guarded(s, Cmd, Sp, ChannelId, dvc);
394 HashTable_Unlock(table);
399static BOOL wts_read_drdynvc_pdu(rdpPeerChannel* channel)
401 WINPR_ASSERT(channel);
402 WINPR_ASSERT(channel->vcm);
404 const size_t slength = Stream_GetPosition(channel->receiveData);
405 if ((slength < 1) || (slength > UINT32_MAX))
408 Stream_ResetPosition(channel->receiveData);
409 wStream buffer = WINPR_C_ARRAY_INIT;
410 wStream* s = Stream_StaticConstInit(&buffer, Stream_Buffer(channel->receiveData), slength);
411 const UINT8 value = Stream_Get_UINT8(s);
412 const UINT8 Cmd = (value & 0xf0) >> 4;
413 const UINT8 Sp = (value & 0x0c) >> 2;
414 const UINT8 cbChId = (value & 0x03) >> 0;
416 if (Cmd == CAPABILITY_REQUEST_PDU)
417 return wts_read_drdynvc_capabilities_response(channel, s);
419 if (channel->vcm->drdynvc_state == DRDYNVC_STATE_READY)
420 return wts_read_drdynvc_pdu_ready(channel, s, Cmd, Sp, cbChId);
422 WLog_ERR(TAG,
"received Cmd %d but channel is not ready.", Cmd);
427static int wts_write_variable_uint(
wStream* s, UINT32 val)
435 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, val));
437 else if (val <= 0xFFFF)
440 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, val));
445 Stream_Write_UINT32(s, val);
451static void wts_write_drdynvc_header(
wStream* s, BYTE Cmd, UINT32 ChannelId)
455 BYTE* bm = Stream_PointerAs(s, BYTE);
456 Stream_Seek_UINT8(s);
457 const int cbChId = wts_write_variable_uint(s, ChannelId);
458 *bm = (((Cmd & 0x0F) << 4) | cbChId) & 0xFF;
461static BOOL wts_write_drdynvc_create_request(
wStream* s, UINT32 ChannelId,
const char* ChannelName)
466 WINPR_ASSERT(ChannelName);
468 wts_write_drdynvc_header(s, CREATE_REQUEST_PDU, ChannelId);
469 len = strlen(ChannelName) + 1;
471 if (!Stream_EnsureRemainingCapacity(s, len))
474 Stream_Write(s, ChannelName, len);
478static BOOL WTSProcessChannelData(rdpPeerChannel* channel, UINT16 channelId,
const BYTE* data,
479 size_t s, UINT32 flags,
size_t t)
483 const size_t totalSize = t;
485 WINPR_ASSERT(channel);
486 WINPR_ASSERT(channel->vcm);
487 WINPR_UNUSED(channelId);
489 if (channel->channelFlags & CHANNEL_OPTION_SHOW_PROTOCOL)
491 BOOL firstPass = TRUE;
495 const UINT32 payloadLen = (size > CHANNEL_CHUNK_LENGTH)
496 ? CHANNEL_CHUNK_LENGTH
497 : WINPR_ASSERTING_INT_CAST(UINT32, size);
507 if (flags & CHANNEL_FLAG_FIRST)
508 newFlags = CHANNEL_FLAG_FIRST;
511 if (!size && (flags & CHANNEL_FLAG_LAST))
512 newFlags |= CHANNEL_FLAG_LAST;
515 .length = payloadLen,
519 if (!wts_queue_receive_data(channel, (
const BYTE*)&header,
sizeof(header), data,
528 if ((flags & CHANNEL_FLAG_FIRST) != 0)
530 Stream_ResetPosition(channel->receiveData);
533 if (!Stream_EnsureRemainingCapacity(channel->receiveData, size))
536 Stream_Write(channel->receiveData, data, size);
538 if ((flags & CHANNEL_FLAG_LAST) != 0)
540 if (Stream_GetPosition(channel->receiveData) != totalSize)
542 WLog_ERR(TAG,
"read error");
545 if (channel == channel->vcm->drdynvc_channel)
547 ret = wts_read_drdynvc_pdu(channel);
551 const size_t pos = Stream_GetPosition(channel->receiveData);
552 if (pos > UINT32_MAX)
555 ret = wts_queue_receive_data(channel, Stream_Buffer(channel->receiveData), pos,
559 Stream_ResetPosition(channel->receiveData);
565static BOOL WTSReceiveChannelData(freerdp_peer* client, UINT16 channelId,
const BYTE* data,
566 size_t size, UINT32 flags,
size_t totalSize)
568 rdpMcs* mcs =
nullptr;
570 WINPR_ASSERT(client);
571 WINPR_ASSERT(client->context);
572 WINPR_ASSERT(client->context->rdp);
574 mcs = client->context->rdp->mcs;
577 for (UINT32 i = 0; i < mcs->channelCount; i++)
579 rdpMcsChannel* cur = &mcs->channels[i];
580 if (cur->ChannelId == channelId)
582 rdpPeerChannel* channel = (rdpPeerChannel*)cur->handle;
585 return WTSProcessChannelData(channel, channelId, data, size, flags, totalSize);
589 WLog_WARN(TAG,
"unknown channelId %" PRIu16
" ignored", channelId);
594#if defined(WITH_FREERDP_DEPRECATED)
595void WTSVirtualChannelManagerGetFileDescriptor(HANDLE hServer,
void** fds,
int* fds_count)
601 WINPR_ASSERT(fds_count);
603 fd = GetEventWaitObject(MessageQueue_Event(vcm->queue));
607 fds[*fds_count] = fd;
613 if (vcm->drdynvc_channel)
615 fd = GetEventWaitObject(vcm->drdynvc_channel->receiveEvent);
619 fds[*fds_count] = fd;
628BOOL WTSVirtualChannelManagerOpen(HANDLE hServer)
635 if (vcm->drdynvc_state == DRDYNVC_STATE_NONE)
637 rdpPeerChannel* channel =
nullptr;
640 vcm->drdynvc_state = DRDYNVC_STATE_INITIALIZED;
641 channel = (rdpPeerChannel*)WTSVirtualChannelOpen((HANDLE)vcm, WTS_CURRENT_SESSION,
642 DRDYNVC_SVC_CHANNEL_NAME);
646 BYTE capaBuffer[12] = WINPR_C_ARRAY_INIT;
647 wStream staticS = WINPR_C_ARRAY_INIT;
648 wStream* s = Stream_StaticInit(&staticS, capaBuffer,
sizeof(capaBuffer));
650 vcm->drdynvc_channel = channel;
651 vcm->dvc_spoken_version = 1;
652 Stream_Write_UINT8(s, 0x50);
653 Stream_Write_UINT8(s, 0x00);
654 Stream_Write_UINT16(s, 0x0001);
658 const size_t pos = Stream_GetPosition(s);
659 WINPR_ASSERT(pos <= UINT32_MAX);
661 if (!WTSVirtualChannelWrite(channel, (PCHAR)capaBuffer, (UINT32)pos, &written))
669BOOL WTSVirtualChannelManagerCheckFileDescriptorEx(HANDLE hServer, BOOL autoOpen)
671 wMessage message = WINPR_C_ARRAY_INIT;
675 if (!hServer || hServer == INVALID_HANDLE_VALUE)
682 if (!WTSVirtualChannelManagerOpen(hServer))
686 while (MessageQueue_Peek(vcm->queue, &message, TRUE))
688 BYTE* buffer =
nullptr;
690 UINT16 channelId = 0;
691 channelId = (UINT16)(UINT_PTR)message.context;
692 buffer = (BYTE*)message.wParam;
693 length = (UINT32)(UINT_PTR)message.lParam;
695 WINPR_ASSERT(vcm->client);
696 WINPR_ASSERT(vcm->client->SendChannelData);
697 if (!vcm->client->SendChannelData(vcm->client, channelId, buffer, length))
711BOOL WTSVirtualChannelManagerCheckFileDescriptor(HANDLE hServer)
713 return WTSVirtualChannelManagerCheckFileDescriptorEx(hServer, TRUE);
716HANDLE WTSVirtualChannelManagerGetEventHandle(HANDLE hServer)
720 return MessageQueue_Event(vcm->queue);
723static rdpMcsChannel* wts_get_joined_channel_by_name(rdpMcs* mcs,
const char* channel_name)
725 if (!mcs || !channel_name || !strnlen(channel_name, CHANNEL_NAME_LEN + 1))
728 for (UINT32 index = 0; index < mcs->channelCount; index++)
730 rdpMcsChannel* mchannel = &mcs->channels[index];
731 if (mchannel->joined)
733 if (_strnicmp(mchannel->Name, channel_name, CHANNEL_NAME_LEN + 1) == 0)
741static rdpMcsChannel* wts_get_joined_channel_by_id(rdpMcs* mcs,
const UINT16 channel_id)
743 if (!mcs || !channel_id)
746 WINPR_ASSERT(mcs->channels);
747 for (UINT32 index = 0; index < mcs->channelCount; index++)
749 rdpMcsChannel* mchannel = &mcs->channels[index];
750 if (mchannel->joined)
752 if (mchannel->ChannelId == channel_id)
753 return &mcs->channels[index];
760BOOL WTSIsChannelJoinedByName(freerdp_peer* client,
const char* channel_name)
762 if (!client || !client->context || !client->context->rdp)
765 return (wts_get_joined_channel_by_name(client->context->rdp->mcs, channel_name) !=
nullptr);
768BOOL WTSIsChannelJoinedById(freerdp_peer* client, UINT16 channel_id)
770 if (!client || !client->context || !client->context->rdp)
773 return (wts_get_joined_channel_by_id(client->context->rdp->mcs, channel_id) !=
nullptr);
776BOOL WTSVirtualChannelManagerIsChannelJoined(HANDLE hServer,
const char* name)
780 if (!vcm || !vcm->rdp)
783 return (wts_get_joined_channel_by_name(vcm->rdp->mcs, name) !=
nullptr);
786BYTE WTSVirtualChannelManagerGetDrdynvcState(HANDLE hServer)
790 return vcm->drdynvc_state;
793void WTSVirtualChannelManagerSetDVCCreationCallback(HANDLE hServer, psDVCCreationStatusCallback cb,
800 vcm->dvc_creation_status = cb;
801 vcm->dvc_creation_status_userdata = userdata;
804UINT16 WTSChannelGetId(freerdp_peer* client,
const char* channel_name)
806 rdpMcsChannel* channel =
nullptr;
808 WINPR_ASSERT(channel_name);
809 if (!client || !client->context || !client->context->rdp)
812 channel = wts_get_joined_channel_by_name(client->context->rdp->mcs, channel_name);
817 return channel->ChannelId;
820UINT32 WTSChannelGetIdByHandle(HANDLE hChannelHandle)
822 rdpPeerChannel* channel = hChannelHandle;
824 WINPR_ASSERT(channel);
826 return channel->channelId;
829BOOL WTSChannelSetHandleByName(freerdp_peer* client,
const char* channel_name,
void* handle)
831 rdpMcsChannel* channel =
nullptr;
833 WINPR_ASSERT(channel_name);
834 if (!client || !client->context || !client->context->rdp)
837 channel = wts_get_joined_channel_by_name(client->context->rdp->mcs, channel_name);
842 channel->handle = handle;
846BOOL WTSChannelSetHandleById(freerdp_peer* client, UINT16 channel_id,
void* handle)
848 rdpMcsChannel* channel =
nullptr;
850 if (!client || !client->context || !client->context->rdp)
853 channel = wts_get_joined_channel_by_id(client->context->rdp->mcs, channel_id);
858 channel->handle = handle;
862void* WTSChannelGetHandleByName(freerdp_peer* client,
const char* channel_name)
864 rdpMcsChannel* channel =
nullptr;
866 WINPR_ASSERT(channel_name);
867 if (!client || !client->context || !client->context->rdp)
870 channel = wts_get_joined_channel_by_name(client->context->rdp->mcs, channel_name);
875 return channel->handle;
878void* WTSChannelGetHandleById(freerdp_peer* client, UINT16 channel_id)
880 rdpMcsChannel* channel =
nullptr;
882 if (!client || !client->context || !client->context->rdp)
885 channel = wts_get_joined_channel_by_id(client->context->rdp->mcs, channel_id);
890 return channel->handle;
893const char* WTSChannelGetName(freerdp_peer* client, UINT16 channel_id)
895 rdpMcsChannel* channel =
nullptr;
897 if (!client || !client->context || !client->context->rdp)
900 channel = wts_get_joined_channel_by_id(client->context->rdp->mcs, channel_id);
905 return (
const char*)channel->Name;
908char** WTSGetAcceptedChannelNames(freerdp_peer* client,
size_t* count)
910 rdpMcs* mcs =
nullptr;
911 char** names =
nullptr;
913 if (!client || !client->context || !count)
916 WINPR_ASSERT(client->context->rdp);
917 mcs = client->context->rdp->mcs;
919 *count = mcs->channelCount;
921 names = (
char**)calloc(mcs->channelCount,
sizeof(
char*));
925 for (UINT32 index = 0; index < mcs->channelCount; index++)
927 rdpMcsChannel* mchannel = &mcs->channels[index];
928 names[index] = mchannel->Name;
934INT64 WTSChannelGetOptions(freerdp_peer* client, UINT16 channel_id)
936 rdpMcsChannel* channel =
nullptr;
938 if (!client || !client->context || !client->context->rdp)
941 channel = wts_get_joined_channel_by_id(client->context->rdp->mcs, channel_id);
946 return (INT64)channel->options;
949BOOL WINAPI FreeRDP_WTSStartRemoteControlSessionW(WINPR_ATTR_UNUSED LPWSTR pTargetServerName,
950 WINPR_ATTR_UNUSED ULONG TargetLogonId,
951 WINPR_ATTR_UNUSED BYTE HotkeyVk,
952 WINPR_ATTR_UNUSED USHORT HotkeyModifiers)
954 WLog_ERR(
"TODO",
"TODO: implement");
958BOOL WINAPI FreeRDP_WTSStartRemoteControlSessionA(WINPR_ATTR_UNUSED LPSTR pTargetServerName,
959 WINPR_ATTR_UNUSED ULONG TargetLogonId,
960 WINPR_ATTR_UNUSED BYTE HotkeyVk,
961 WINPR_ATTR_UNUSED USHORT HotkeyModifiers)
963 WLog_ERR(
"TODO",
"TODO: implement");
967BOOL WINAPI FreeRDP_WTSStartRemoteControlSessionExW(WINPR_ATTR_UNUSED LPWSTR pTargetServerName,
968 WINPR_ATTR_UNUSED ULONG TargetLogonId,
969 WINPR_ATTR_UNUSED BYTE HotkeyVk,
970 WINPR_ATTR_UNUSED USHORT HotkeyModifiers,
971 WINPR_ATTR_UNUSED DWORD flags)
973 WLog_ERR(
"TODO",
"TODO: implement");
977BOOL WINAPI FreeRDP_WTSStartRemoteControlSessionExA(WINPR_ATTR_UNUSED LPSTR pTargetServerName,
978 WINPR_ATTR_UNUSED ULONG TargetLogonId,
979 WINPR_ATTR_UNUSED BYTE HotkeyVk,
980 WINPR_ATTR_UNUSED USHORT HotkeyModifiers,
981 WINPR_ATTR_UNUSED DWORD flags)
983 WLog_ERR(
"TODO",
"TODO: implement");
987BOOL WINAPI FreeRDP_WTSStopRemoteControlSession(WINPR_ATTR_UNUSED ULONG LogonId)
989 WLog_ERR(
"TODO",
"TODO: implement");
993BOOL WINAPI FreeRDP_WTSConnectSessionW(WINPR_ATTR_UNUSED ULONG LogonId,
994 WINPR_ATTR_UNUSED ULONG TargetLogonId,
995 WINPR_ATTR_UNUSED PWSTR pPassword,
996 WINPR_ATTR_UNUSED BOOL bWait)
998 WLog_ERR(
"TODO",
"TODO: implement");
1002BOOL WINAPI FreeRDP_WTSConnectSessionA(WINPR_ATTR_UNUSED ULONG LogonId,
1003 WINPR_ATTR_UNUSED ULONG TargetLogonId,
1004 WINPR_ATTR_UNUSED PSTR pPassword,
1005 WINPR_ATTR_UNUSED BOOL bWait)
1007 WLog_ERR(
"TODO",
"TODO: implement");
1011BOOL WINAPI FreeRDP_WTSEnumerateServersW(WINPR_ATTR_UNUSED LPWSTR pDomainName,
1012 WINPR_ATTR_UNUSED DWORD Reserved,
1013 WINPR_ATTR_UNUSED DWORD Version,
1015 WINPR_ATTR_UNUSED DWORD* pCount)
1017 WLog_ERR(
"TODO",
"TODO: implement");
1021BOOL WINAPI FreeRDP_WTSEnumerateServersA(WINPR_ATTR_UNUSED LPSTR pDomainName,
1022 WINPR_ATTR_UNUSED DWORD Reserved,
1023 WINPR_ATTR_UNUSED DWORD Version,
1025 WINPR_ATTR_UNUSED DWORD* pCount)
1027 WLog_ERR(
"TODO",
"TODO: implement");
1031HANDLE WINAPI FreeRDP_WTSOpenServerW(WINPR_ATTR_UNUSED LPWSTR pServerName)
1033 WLog_ERR(
"TODO",
"TODO: implement");
1034 return INVALID_HANDLE_VALUE;
1037static void wts_virtual_channel_manager_free_message(
void* obj)
1039 wMessage* msg = (wMessage*)obj;
1043 BYTE* buffer = (BYTE*)msg->wParam;
1050static void channel_free(rdpPeerChannel* channel)
1052 server_channel_common_free(channel);
1055static void array_channel_free(
void* ptr)
1057 rdpPeerChannel* channel = ptr;
1058 channel_free(channel);
1061static BOOL dynChannelMatch(
const void* v1,
const void* v2)
1063 const UINT32* p1 = (
const UINT32*)v1;
1064 const UINT32* p2 = (
const UINT32*)v2;
1068static UINT32 channelId_Hash(
const void* key)
1070 const UINT32* v = (
const UINT32*)key;
1074static void clearHandles(
void)
1076 HashTable_Free(g_ServerHandles);
1077 g_ServerHandles =
nullptr;
1080static BOOL CALLBACK initializeHandles(WINPR_ATTR_UNUSED
PINIT_ONCE once,
1081 WINPR_ATTR_UNUSED PVOID param,
1082 WINPR_ATTR_UNUSED PVOID* context)
1084 WINPR_ASSERT(g_ServerHandles ==
nullptr);
1085 g_ServerHandles = HashTable_New(TRUE);
1086 (void)winpr_atexit(clearHandles);
1087 return g_ServerHandles !=
nullptr;
1090static bool setup(
void)
1092 return InitOnceExecuteOnce(&g_HandleInitializer, initializeHandles,
nullptr,
nullptr);
1099 HashTable_Lock(g_ServerHandles);
1103#ifdef __clang_analyzer__
1104 const BOOL valid = vcm !=
nullptr;
1106 const BOOL valid = (vcm !=
nullptr) && (vcm != INVALID_HANDLE_VALUE);
1110 HashTable_Remove(g_ServerHandles, (
void*)(UINT_PTR)vcm->SessionId);
1112 HashTable_Free(vcm->dynamicVirtualChannels);
1114 if (vcm->drdynvc_channel)
1117 (void)WTSVirtualChannelClose(vcm->drdynvc_channel);
1118 vcm->drdynvc_channel =
nullptr;
1121 MessageQueue_Free(vcm->queue);
1124 HashTable_Unlock(g_ServerHandles);
1127HANDLE WINAPI FreeRDP_WTSOpenServerA(LPSTR pServerName)
1129 wObject queueCallbacks = WINPR_C_ARRAY_INIT;
1131 rdpContext* context = WINPR_PACKED_ALIGN_CAST(rdpContext*, pServerName);
1133 if (!setup() || !context)
1134 return INVALID_HANDLE_VALUE;
1136 freerdp_peer* client = context->peer;
1140 SetLastError(ERROR_INVALID_DATA);
1141 return INVALID_HANDLE_VALUE;
1149 vcm->client = client;
1150 vcm->rdp = context->rdp;
1152 queueCallbacks.
fnObjectFree = wts_virtual_channel_manager_free_message;
1153 vcm->queue = MessageQueue_New(&queueCallbacks);
1158 vcm->dvc_channel_id_seq = 0;
1159 vcm->dynamicVirtualChannels = HashTable_New(TRUE);
1161 if (!vcm->dynamicVirtualChannels)
1164 if (!HashTable_SetHashFunction(vcm->dynamicVirtualChannels, channelId_Hash))
1168 wObject* obj = HashTable_ValueObject(vcm->dynamicVirtualChannels);
1172 obj = HashTable_KeyObject(vcm->dynamicVirtualChannels);
1175 client->ReceiveChannelData = WTSReceiveChannelData;
1177 HashTable_Lock(g_ServerHandles);
1178 vcm->SessionId = g_SessionId++;
1180 HashTable_Insert(g_ServerHandles, (
void*)(UINT_PTR)vcm->SessionId, (
void*)vcm);
1181 HashTable_Unlock(g_ServerHandles);
1186 HANDLE hServer = (HANDLE)vcm;
1190 wtsCloseVCM(vcm,
false);
1191 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1192 return INVALID_HANDLE_VALUE;
1195HANDLE WINAPI FreeRDP_WTSOpenServerExW(WINPR_ATTR_UNUSED LPWSTR pServerName)
1197 WLog_ERR(
"TODO",
"TODO: implement");
1198 return INVALID_HANDLE_VALUE;
1201HANDLE WINAPI FreeRDP_WTSOpenServerExA(LPSTR pServerName)
1203 return FreeRDP_WTSOpenServerA(pServerName);
1206VOID WINAPI FreeRDP_WTSCloseServer(HANDLE hServer)
1209 wtsCloseVCM(vcm,
true);
1212BOOL WINAPI FreeRDP_WTSEnumerateSessionsW(WINPR_ATTR_UNUSED HANDLE hServer,
1213 WINPR_ATTR_UNUSED DWORD Reserved,
1214 WINPR_ATTR_UNUSED DWORD Version,
1216 WINPR_ATTR_UNUSED DWORD* pCount)
1218 WLog_ERR(
"TODO",
"TODO: implement");
1222BOOL WINAPI FreeRDP_WTSEnumerateSessionsA(WINPR_ATTR_UNUSED HANDLE hServer,
1223 WINPR_ATTR_UNUSED DWORD Reserved,
1224 WINPR_ATTR_UNUSED DWORD Version,
1226 WINPR_ATTR_UNUSED DWORD* pCount)
1228 WLog_ERR(
"TODO",
"TODO: implement");
1232BOOL WINAPI FreeRDP_WTSEnumerateSessionsExW(WINPR_ATTR_UNUSED HANDLE hServer,
1233 WINPR_ATTR_UNUSED DWORD* pLevel,
1234 WINPR_ATTR_UNUSED DWORD Filter,
1236 WINPR_ATTR_UNUSED DWORD* pCount)
1238 WLog_ERR(
"TODO",
"TODO: implement");
1242BOOL WINAPI FreeRDP_WTSEnumerateSessionsExA(WINPR_ATTR_UNUSED HANDLE hServer,
1243 WINPR_ATTR_UNUSED DWORD* pLevel,
1244 WINPR_ATTR_UNUSED DWORD Filter,
1246 WINPR_ATTR_UNUSED DWORD* pCount)
1248 WLog_ERR(
"TODO",
"TODO: implement");
1252BOOL WINAPI FreeRDP_WTSEnumerateProcessesW(WINPR_ATTR_UNUSED HANDLE hServer,
1253 WINPR_ATTR_UNUSED DWORD Reserved,
1254 WINPR_ATTR_UNUSED DWORD Version,
1256 WINPR_ATTR_UNUSED DWORD* pCount)
1258 WLog_ERR(
"TODO",
"TODO: implement");
1262BOOL WINAPI FreeRDP_WTSEnumerateProcessesA(WINPR_ATTR_UNUSED HANDLE hServer,
1263 WINPR_ATTR_UNUSED DWORD Reserved,
1264 WINPR_ATTR_UNUSED DWORD Version,
1266 WINPR_ATTR_UNUSED DWORD* pCount)
1268 WLog_ERR(
"TODO",
"TODO: implement");
1272BOOL WINAPI FreeRDP_WTSTerminateProcess(WINPR_ATTR_UNUSED HANDLE hServer,
1273 WINPR_ATTR_UNUSED DWORD ProcessId,
1274 WINPR_ATTR_UNUSED DWORD ExitCode)
1276 WLog_ERR(
"TODO",
"TODO: implement");
1280BOOL WINAPI FreeRDP_WTSQuerySessionInformationW(WINPR_ATTR_UNUSED HANDLE hServer,
1281 WINPR_ATTR_UNUSED DWORD SessionId,
1282 WINPR_ATTR_UNUSED WTS_INFO_CLASS WTSInfoClass,
1283 WINPR_ATTR_UNUSED LPWSTR* ppBuffer,
1284 WINPR_ATTR_UNUSED DWORD* pBytesReturned)
1286 WLog_ERR(
"TODO",
"TODO: implement");
1290BOOL WINAPI FreeRDP_WTSQuerySessionInformationA(HANDLE hServer, WINPR_ATTR_UNUSED DWORD SessionId,
1291 WTS_INFO_CLASS WTSInfoClass, LPSTR* ppBuffer,
1292 DWORD* pBytesReturned)
1294 DWORD BytesReturned = 0;
1301 if (WTSInfoClass == WTSSessionId)
1303 ULONG* pBuffer =
nullptr;
1304 BytesReturned =
sizeof(ULONG);
1305 pBuffer = (ULONG*)malloc(
sizeof(BytesReturned));
1309 SetLastError(g_err_oom);
1313 *pBuffer = vcm->SessionId;
1314 *ppBuffer = (LPSTR)pBuffer;
1315 *pBytesReturned = BytesReturned;
1322BOOL WINAPI FreeRDP_WTSQueryUserConfigW(WINPR_ATTR_UNUSED LPWSTR pServerName,
1323 WINPR_ATTR_UNUSED LPWSTR pUserName,
1324 WINPR_ATTR_UNUSED WTS_CONFIG_CLASS WTSConfigClass,
1325 WINPR_ATTR_UNUSED LPWSTR* ppBuffer,
1326 WINPR_ATTR_UNUSED DWORD* pBytesReturned)
1328 WLog_ERR(
"TODO",
"TODO: implement");
1332BOOL WINAPI FreeRDP_WTSQueryUserConfigA(WINPR_ATTR_UNUSED LPSTR pServerName,
1333 WINPR_ATTR_UNUSED LPSTR pUserName,
1334 WINPR_ATTR_UNUSED WTS_CONFIG_CLASS WTSConfigClass,
1335 WINPR_ATTR_UNUSED LPSTR* ppBuffer,
1336 WINPR_ATTR_UNUSED DWORD* pBytesReturned)
1338 WLog_ERR(
"TODO",
"TODO: implement");
1342BOOL WINAPI FreeRDP_WTSSetUserConfigW(WINPR_ATTR_UNUSED LPWSTR pServerName,
1343 WINPR_ATTR_UNUSED LPWSTR pUserName,
1344 WINPR_ATTR_UNUSED WTS_CONFIG_CLASS WTSConfigClass,
1345 WINPR_ATTR_UNUSED LPWSTR pBuffer,
1346 WINPR_ATTR_UNUSED DWORD DataLength)
1348 WLog_ERR(
"TODO",
"TODO: implement");
1352BOOL WINAPI FreeRDP_WTSSetUserConfigA(WINPR_ATTR_UNUSED LPSTR pServerName,
1353 WINPR_ATTR_UNUSED LPSTR pUserName,
1354 WINPR_ATTR_UNUSED WTS_CONFIG_CLASS WTSConfigClass,
1355 WINPR_ATTR_UNUSED LPSTR pBuffer,
1356 WINPR_ATTR_UNUSED DWORD DataLength)
1358 WLog_ERR(
"TODO",
"TODO: implement");
1363FreeRDP_WTSSendMessageW(WINPR_ATTR_UNUSED HANDLE hServer, WINPR_ATTR_UNUSED DWORD SessionId,
1364 WINPR_ATTR_UNUSED LPWSTR pTitle, WINPR_ATTR_UNUSED DWORD TitleLength,
1365 WINPR_ATTR_UNUSED LPWSTR pMessage, WINPR_ATTR_UNUSED DWORD MessageLength,
1366 WINPR_ATTR_UNUSED DWORD Style, WINPR_ATTR_UNUSED DWORD Timeout,
1367 WINPR_ATTR_UNUSED DWORD* pResponse, WINPR_ATTR_UNUSED BOOL bWait)
1369 WLog_ERR(
"TODO",
"TODO: implement");
1374FreeRDP_WTSSendMessageA(WINPR_ATTR_UNUSED HANDLE hServer, WINPR_ATTR_UNUSED DWORD SessionId,
1375 WINPR_ATTR_UNUSED LPSTR pTitle, WINPR_ATTR_UNUSED DWORD TitleLength,
1376 WINPR_ATTR_UNUSED LPSTR pMessage, WINPR_ATTR_UNUSED DWORD MessageLength,
1377 WINPR_ATTR_UNUSED DWORD Style, WINPR_ATTR_UNUSED DWORD Timeout,
1378 WINPR_ATTR_UNUSED DWORD* pResponse, WINPR_ATTR_UNUSED BOOL bWait)
1380 WLog_ERR(
"TODO",
"TODO: implement");
1384BOOL WINAPI FreeRDP_WTSDisconnectSession(WINPR_ATTR_UNUSED HANDLE hServer,
1385 WINPR_ATTR_UNUSED DWORD SessionId,
1386 WINPR_ATTR_UNUSED BOOL bWait)
1388 WLog_ERR(
"TODO",
"TODO: implement");
1392BOOL WINAPI FreeRDP_WTSLogoffSession(WINPR_ATTR_UNUSED HANDLE hServer,
1393 WINPR_ATTR_UNUSED DWORD SessionId,
1394 WINPR_ATTR_UNUSED BOOL bWait)
1396 WLog_ERR(
"TODO",
"TODO: implement");
1400BOOL WINAPI FreeRDP_WTSShutdownSystem(WINPR_ATTR_UNUSED HANDLE hServer,
1401 WINPR_ATTR_UNUSED DWORD ShutdownFlag)
1403 WLog_ERR(
"TODO",
"TODO: implement");
1407BOOL WINAPI FreeRDP_WTSWaitSystemEvent(WINPR_ATTR_UNUSED HANDLE hServer,
1408 WINPR_ATTR_UNUSED DWORD EventMask,
1409 WINPR_ATTR_UNUSED DWORD* pEventFlags)
1411 WLog_ERR(
"TODO",
"TODO: implement");
1415static void peer_channel_queue_free_message(
void* obj)
1417 wMessage* msg = (wMessage*)obj;
1422 msg->context =
nullptr;
1426 UINT32 ChannelId, UINT16 index, UINT16 type,
size_t chunkSize,
1427 const char* name, UINT32 flags)
1429 wObject queueCallbacks = WINPR_C_ARRAY_INIT;
1430 queueCallbacks.
fnObjectFree = peer_channel_queue_free_message;
1432 rdpPeerChannel* channel =
1433 server_channel_common_new(client, index, ChannelId, chunkSize, &queueCallbacks, name);
1436 WINPR_ASSERT(client);
1442 channel->channelType = type;
1443 channel->creationStatus =
1444 (type == RDP_PEER_CHANNEL_TYPE_SVC) ? ERROR_SUCCESS : ERROR_OPERATION_IN_PROGRESS;
1445 channel->channelFlags = flags;
1449 channel_free(channel);
1453static HANDLE WINAPI FreeRDP_WTSVirtualChannelOpenStatic(HANDLE hServer,
1454 WINPR_ATTR_UNUSED DWORD SessionId,
1455 LPSTR pVirtualName, UINT32 Flags)
1460 SetLastError(ERROR_INVALID_DATA);
1464 freerdp_peer* client = vcm->client;
1465 WINPR_ASSERT(client);
1467 rdpContext* context = client->context;
1468 WINPR_ASSERT(context);
1469 WINPR_ASSERT(context->rdp);
1470 WINPR_ASSERT(context->settings);
1472 rdpMcs* mcs = context->rdp->mcs;
1475 size_t length = strnlen(pVirtualName, CHANNEL_NAME_LEN + 1);
1476 if (length > CHANNEL_NAME_LEN)
1478 SetLastError(ERROR_NOT_FOUND);
1482 rdpMcsChannel* joined_channel =
nullptr;
1484 for (; index < mcs->channelCount; index++)
1486 rdpMcsChannel* mchannel = &mcs->channels[index];
1487 if (mchannel->joined && (strncmp(mchannel->Name, pVirtualName, length) == 0))
1489 joined_channel = mchannel;
1494 if (!joined_channel)
1496 SetLastError(ERROR_NOT_FOUND);
1500 rdpPeerChannel* channel = (rdpPeerChannel*)joined_channel->handle;
1503 const UINT32 VCChunkSize =
1506 WINPR_ASSERT(index <= UINT16_MAX);
1507 channel = channel_new(vcm, client, joined_channel->ChannelId, (UINT16)index,
1508 RDP_PEER_CHANNEL_TYPE_SVC, VCChunkSize, pVirtualName, Flags);
1513 joined_channel->handle = channel;
1516 HANDLE hChannelHandle = (HANDLE)channel;
1517 return hChannelHandle;
1519 channel_free(channel);
1520 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1524HANDLE WINAPI FreeRDP_WTSVirtualChannelOpen(HANDLE hServer, DWORD SessionId, LPSTR pVirtualName)
1526 return FreeRDP_WTSVirtualChannelOpenStatic(hServer, SessionId, pVirtualName, 0);
1529HANDLE WINAPI FreeRDP_WTSVirtualChannelOpenEx(DWORD SessionId, LPSTR pVirtualName, DWORD flags)
1532 rdpPeerChannel* channel =
nullptr;
1533 BOOL joined = FALSE;
1539 if (SessionId == WTS_CURRENT_SESSION)
1542 HashTable_Lock(g_ServerHandles);
1544 g_ServerHandles, (
void*)(UINT_PTR)SessionId);
1549 if (!(flags & WTS_CHANNEL_OPTION_DYNAMIC))
1551 HashTable_Unlock(g_ServerHandles);
1552 return FreeRDP_WTSVirtualChannelOpenStatic((HANDLE)vcm, SessionId, pVirtualName, flags);
1555 freerdp_peer* client = vcm->client;
1556 WINPR_ASSERT(client);
1557 WINPR_ASSERT(client->context);
1558 WINPR_ASSERT(client->context->rdp);
1560 rdpMcs* mcs = client->context->rdp->mcs;
1563 for (UINT32 index = 0; index < mcs->channelCount; index++)
1565 rdpMcsChannel* mchannel = &mcs->channels[index];
1566 if (mchannel->joined &&
1567 (strncmp(mchannel->Name, DRDYNVC_SVC_CHANNEL_NAME, CHANNEL_NAME_LEN + 1) == 0))
1576 SetLastError(ERROR_NOT_FOUND);
1580 if (!vcm->drdynvc_channel || (vcm->drdynvc_state != DRDYNVC_STATE_READY))
1582 SetLastError(ERROR_NOT_READY);
1586 WINPR_ASSERT(client);
1587 WINPR_ASSERT(client->context);
1588 WINPR_ASSERT(client->context->settings);
1590 const UINT32 VCChunkSize =
1593 channel_new(vcm, client, 0, 0, RDP_PEER_CHANNEL_TYPE_DVC, VCChunkSize, pVirtualName, flags);
1597 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1601 const LONG hdl = InterlockedIncrement(&vcm->dvc_channel_id_seq);
1602 channel->channelId = WINPR_ASSERTING_INT_CAST(uint32_t, hdl);
1604 if (!HashTable_Insert(vcm->dynamicVirtualChannels, &channel->channelId, channel))
1606 channel_free(channel);
1610 s = Stream_New(
nullptr, 64);
1615 if (!wts_write_drdynvc_create_request(s, channel->channelId, pVirtualName))
1619 const size_t pos = Stream_GetPosition(s);
1620 WINPR_ASSERT(pos <= UINT32_MAX);
1621 if (!WTSVirtualChannelWrite(vcm->drdynvc_channel, Stream_BufferAs(s,
char), (UINT32)pos,
1627 Stream_Free(s, TRUE);
1628 HashTable_Unlock(g_ServerHandles);
1632 Stream_Free(s, TRUE);
1634 HashTable_Remove(vcm->dynamicVirtualChannels, &channel->channelId);
1635 HashTable_Unlock(g_ServerHandles);
1637 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1641BOOL WINAPI FreeRDP_WTSVirtualChannelClose(HANDLE hChannelHandle)
1644 rdpMcs* mcs =
nullptr;
1646 rdpPeerChannel* channel = (rdpPeerChannel*)hChannelHandle;
1654 WINPR_ASSERT(vcm->client);
1655 WINPR_ASSERT(vcm->client->context);
1656 WINPR_ASSERT(vcm->client->context->rdp);
1657 mcs = vcm->client->context->rdp->mcs;
1659 if (channel->channelType == RDP_PEER_CHANNEL_TYPE_SVC)
1661 if (channel->index < mcs->channelCount)
1663 rdpMcsChannel* cur = &mcs->channels[channel->index];
1664 rdpPeerChannel* peerChannel = (rdpPeerChannel*)cur->handle;
1665 channel_free(peerChannel);
1666 cur->handle =
nullptr;
1671 if (channel->dvc_open_state == DVC_OPEN_STATE_SUCCEEDED)
1674 s = Stream_New(
nullptr, 8);
1678 WLog_ERR(TAG,
"Stream_New failed!");
1683 wts_write_drdynvc_header(s, CLOSE_REQUEST_PDU, channel->channelId);
1685 const size_t pos = Stream_GetPosition(s);
1686 WINPR_ASSERT(pos <= UINT32_MAX);
1687 ret = WTSVirtualChannelWrite(vcm->drdynvc_channel, Stream_BufferAs(s,
char),
1688 (UINT32)pos, &written);
1689 Stream_Free(s, TRUE);
1692 HashTable_Remove(vcm->dynamicVirtualChannels, &channel->channelId);
1699BOOL WINAPI FreeRDP_WTSVirtualChannelRead(HANDLE hChannelHandle, WINPR_ATTR_UNUSED ULONG TimeOut,
1700 PCHAR Buffer, ULONG BufferSize, PULONG pBytesRead)
1702 BYTE* buffer =
nullptr;
1703 wMessage message = WINPR_C_ARRAY_INIT;
1704 wtsChannelMessage* messageCtx =
nullptr;
1705 rdpPeerChannel* channel = (rdpPeerChannel*)hChannelHandle;
1707 WINPR_ASSERT(channel);
1709 if (!MessageQueue_Peek(channel->queue, &message, FALSE))
1711 SetLastError(ERROR_NO_DATA);
1716 messageCtx = message.context;
1718 if (messageCtx ==
nullptr)
1721 buffer = (BYTE*)(messageCtx + 1);
1722 *pBytesRead = messageCtx->length - messageCtx->offset;
1724 if (Buffer ==
nullptr || BufferSize == 0)
1729 if (*pBytesRead > BufferSize)
1730 *pBytesRead = BufferSize;
1732 CopyMemory(Buffer, buffer + messageCtx->offset, *pBytesRead);
1733 messageCtx->offset += *pBytesRead;
1735 if (messageCtx->offset >= messageCtx->length)
1737 const int rc = MessageQueue_Peek(channel->queue, &message, TRUE);
1738 peer_channel_queue_free_message(&message);
1746BOOL WINAPI FreeRDP_WTSVirtualChannelWrite(HANDLE hChannelHandle, PCHAR Buffer, ULONG uLength,
1747 PULONG pBytesWritten)
1753 BYTE* buffer =
nullptr;
1754 size_t totalWritten = 0;
1755 rdpPeerChannel* channel = (rdpPeerChannel*)hChannelHandle;
1761 EnterCriticalSection(&channel->writeLock);
1762 WINPR_ASSERT(channel->vcm);
1763 if (channel->channelType == RDP_PEER_CHANNEL_TYPE_SVC)
1765 buffer = (BYTE*)malloc(uLength);
1769 SetLastError(g_err_oom);
1773 CopyMemory(buffer, Buffer, uLength);
1774 totalWritten = uLength;
1775 if (!wts_queue_send_item(channel, buffer, uLength))
1778 else if (!channel->vcm->drdynvc_channel || (channel->vcm->drdynvc_state != DRDYNVC_STATE_READY))
1780 DEBUG_DVC(
"drdynvc not ready");
1787 size_t Length = uLength;
1790 s = Stream_New(
nullptr, DVC_MAX_DATA_PDU_SIZE);
1794 WLog_ERR(TAG,
"Stream_New failed!");
1795 SetLastError(g_err_oom);
1799 buffer = Stream_Buffer(s);
1800 Stream_Seek_UINT8(s);
1801 cbChId = wts_write_variable_uint(s, channel->channelId);
1803 if (first && (Length > Stream_GetRemainingLength(s)))
1805 cbLen = wts_write_variable_uint(s, WINPR_ASSERTING_INT_CAST(uint32_t, Length));
1806 buffer[0] = ((DATA_FIRST_PDU << 4) | (cbLen << 2) | cbChId) & 0xFF;
1810 buffer[0] = ((DATA_PDU << 4) | cbChId) & 0xFF;
1814 size_t written = Stream_GetRemainingLength(s);
1816 if (written > Length)
1819 Stream_Write(s, Buffer, written);
1820 const size_t length = Stream_GetPosition(s);
1821 Stream_Free(s, FALSE);
1822 if (length > UINT32_MAX)
1826 totalWritten += written;
1827 if (!wts_queue_send_item(channel->vcm->drdynvc_channel, buffer, (UINT32)length))
1833 *pBytesWritten = WINPR_ASSERTING_INT_CAST(uint32_t, totalWritten);
1837 LeaveCriticalSection(&channel->writeLock);
1841BOOL WINAPI FreeRDP_WTSVirtualChannelPurgeInput(WINPR_ATTR_UNUSED HANDLE hChannelHandle)
1843 WLog_ERR(
"TODO",
"TODO: implement");
1847BOOL WINAPI FreeRDP_WTSVirtualChannelPurgeOutput(WINPR_ATTR_UNUSED HANDLE hChannelHandle)
1849 WLog_ERR(
"TODO",
"TODO: implement");
1853BOOL WINAPI FreeRDP_WTSVirtualChannelQuery(HANDLE hChannelHandle, WTS_VIRTUAL_CLASS WtsVirtualClass,
1854 PVOID* ppBuffer, DWORD* pBytesReturned)
1856 void* pfd =
nullptr;
1858 void* fds[10] = WINPR_C_ARRAY_INIT;
1859 HANDLE hEvent =
nullptr;
1861 BOOL status = FALSE;
1862 rdpPeerChannel* channel = (rdpPeerChannel*)hChannelHandle;
1864 WINPR_ASSERT(channel);
1866 switch ((UINT32)WtsVirtualClass)
1868 case WTSVirtualFileHandle:
1869 hEvent = MessageQueue_Event(channel->queue);
1870 pfd = GetEventWaitObject(hEvent);
1874 fds[fds_count] = pfd;
1878 *ppBuffer = malloc(
sizeof(
void*));
1882 SetLastError(g_err_oom);
1886 CopyMemory(*ppBuffer, (
void*)&fds[0],
sizeof(
void*));
1887 *pBytesReturned =
sizeof(
void*);
1893 case WTSVirtualEventHandle:
1894 hEvent = MessageQueue_Event(channel->queue);
1896 *ppBuffer = malloc(
sizeof(HANDLE));
1900 SetLastError(g_err_oom);
1904 CopyMemory(*ppBuffer, (
void*)&hEvent,
sizeof(HANDLE));
1905 *pBytesReturned =
sizeof(
void*);
1911 case WTSVirtualChannelReady:
1912 if (channel->channelType == RDP_PEER_CHANNEL_TYPE_SVC)
1919 switch (channel->dvc_open_state)
1921 case DVC_OPEN_STATE_NONE:
1926 case DVC_OPEN_STATE_SUCCEEDED:
1932 *ppBuffer =
nullptr;
1933 *pBytesReturned = 0;
1938 *ppBuffer = malloc(
sizeof(BOOL));
1942 SetLastError(g_err_oom);
1947 CopyMemory(*ppBuffer, &bval,
sizeof(BOOL));
1948 *pBytesReturned =
sizeof(BOOL);
1952 case WTSVirtualChannelOpenStatus:
1954 INT32 value = channel->creationStatus;
1957 *ppBuffer = malloc(
sizeof(value));
1960 SetLastError(g_err_oom);
1965 CopyMemory(*ppBuffer, &value,
sizeof(value));
1966 *pBytesReturned =
sizeof(value);
1977VOID WINAPI FreeRDP_WTSFreeMemory(PVOID pMemory)
1982BOOL WINAPI FreeRDP_WTSFreeMemoryExW(WINPR_ATTR_UNUSED WTS_TYPE_CLASS WTSTypeClass,
1983 WINPR_ATTR_UNUSED PVOID pMemory,
1984 WINPR_ATTR_UNUSED ULONG NumberOfEntries)
1986 WLog_ERR(
"TODO",
"TODO: implement");
1990BOOL WINAPI FreeRDP_WTSFreeMemoryExA(WINPR_ATTR_UNUSED WTS_TYPE_CLASS WTSTypeClass,
1991 WINPR_ATTR_UNUSED PVOID pMemory,
1992 WINPR_ATTR_UNUSED ULONG NumberOfEntries)
1994 WLog_ERR(
"TODO",
"TODO: implement");
1998BOOL WINAPI FreeRDP_WTSRegisterSessionNotification(WINPR_ATTR_UNUSED HWND hWnd,
1999 WINPR_ATTR_UNUSED DWORD dwFlags)
2001 WLog_ERR(
"TODO",
"TODO: implement");
2005BOOL WINAPI FreeRDP_WTSUnRegisterSessionNotification(WINPR_ATTR_UNUSED HWND hWnd)
2007 WLog_ERR(
"TODO",
"TODO: implement");
2011BOOL WINAPI FreeRDP_WTSRegisterSessionNotificationEx(WINPR_ATTR_UNUSED HANDLE hServer,
2012 WINPR_ATTR_UNUSED HWND hWnd,
2013 WINPR_ATTR_UNUSED DWORD dwFlags)
2015 WLog_ERR(
"TODO",
"TODO: implement");
2019BOOL WINAPI FreeRDP_WTSUnRegisterSessionNotificationEx(WINPR_ATTR_UNUSED HANDLE hServer,
2020 WINPR_ATTR_UNUSED HWND hWnd)
2022 WLog_ERR(
"TODO",
"TODO: implement");
2026BOOL WINAPI FreeRDP_WTSQueryUserToken(WINPR_ATTR_UNUSED ULONG SessionId,
2027 WINPR_ATTR_UNUSED PHANDLE phToken)
2029 WLog_ERR(
"TODO",
"TODO: implement");
2033BOOL WINAPI FreeRDP_WTSEnumerateProcessesExW(WINPR_ATTR_UNUSED HANDLE hServer,
2034 WINPR_ATTR_UNUSED DWORD* pLevel,
2035 WINPR_ATTR_UNUSED DWORD SessionId,
2036 WINPR_ATTR_UNUSED LPWSTR* ppProcessInfo,
2037 WINPR_ATTR_UNUSED DWORD* pCount)
2039 WLog_ERR(
"TODO",
"TODO: implement");
2043BOOL WINAPI FreeRDP_WTSEnumerateProcessesExA(WINPR_ATTR_UNUSED HANDLE hServer,
2044 WINPR_ATTR_UNUSED DWORD* pLevel,
2045 WINPR_ATTR_UNUSED DWORD SessionId,
2046 WINPR_ATTR_UNUSED LPSTR* ppProcessInfo,
2047 WINPR_ATTR_UNUSED DWORD* pCount)
2049 WLog_ERR(
"TODO",
"TODO: implement");
2053BOOL WINAPI FreeRDP_WTSEnumerateListenersW(WINPR_ATTR_UNUSED HANDLE hServer,
2054 WINPR_ATTR_UNUSED PVOID pReserved,
2055 WINPR_ATTR_UNUSED DWORD Reserved,
2056 WINPR_ATTR_UNUSED PWTSLISTENERNAMEW pListeners,
2057 WINPR_ATTR_UNUSED DWORD* pCount)
2059 WLog_ERR(
"TODO",
"TODO: implement");
2063BOOL WINAPI FreeRDP_WTSEnumerateListenersA(WINPR_ATTR_UNUSED HANDLE hServer,
2064 WINPR_ATTR_UNUSED PVOID pReserved,
2065 WINPR_ATTR_UNUSED DWORD Reserved,
2066 WINPR_ATTR_UNUSED PWTSLISTENERNAMEA pListeners,
2067 WINPR_ATTR_UNUSED DWORD* pCount)
2069 WLog_ERR(
"TODO",
"TODO: implement");
2073BOOL WINAPI FreeRDP_WTSQueryListenerConfigW(WINPR_ATTR_UNUSED HANDLE hServer,
2074 WINPR_ATTR_UNUSED PVOID pReserved,
2075 WINPR_ATTR_UNUSED DWORD Reserved,
2076 WINPR_ATTR_UNUSED LPWSTR pListenerName,
2079 WLog_ERR(
"TODO",
"TODO: implement");
2083BOOL WINAPI FreeRDP_WTSQueryListenerConfigA(WINPR_ATTR_UNUSED HANDLE hServer,
2084 WINPR_ATTR_UNUSED PVOID pReserved,
2085 WINPR_ATTR_UNUSED DWORD Reserved,
2086 WINPR_ATTR_UNUSED LPSTR pListenerName,
2089 WLog_ERR(
"TODO",
"TODO: implement");
2093BOOL WINAPI FreeRDP_WTSCreateListenerW(WINPR_ATTR_UNUSED HANDLE hServer,
2094 WINPR_ATTR_UNUSED PVOID pReserved,
2095 WINPR_ATTR_UNUSED DWORD Reserved,
2096 WINPR_ATTR_UNUSED LPWSTR pListenerName,
2098 WINPR_ATTR_UNUSED DWORD flag)
2100 WLog_ERR(
"TODO",
"TODO: implement");
2104BOOL WINAPI FreeRDP_WTSCreateListenerA(WINPR_ATTR_UNUSED HANDLE hServer,
2105 WINPR_ATTR_UNUSED PVOID pReserved,
2106 WINPR_ATTR_UNUSED DWORD Reserved,
2107 WINPR_ATTR_UNUSED LPSTR pListenerName,
2109 WINPR_ATTR_UNUSED DWORD flag)
2111 WLog_ERR(
"TODO",
"TODO: implement");
2115BOOL WINAPI FreeRDP_WTSSetListenerSecurityW(
2116 WINPR_ATTR_UNUSED HANDLE hServer, WINPR_ATTR_UNUSED PVOID pReserved,
2117 WINPR_ATTR_UNUSED DWORD Reserved, WINPR_ATTR_UNUSED LPWSTR pListenerName,
2118 WINPR_ATTR_UNUSED SECURITY_INFORMATION SecurityInformation,
2119 WINPR_ATTR_UNUSED PSECURITY_DESCRIPTOR pSecurityDescriptor)
2121 WLog_ERR(
"TODO",
"TODO: implement");
2125BOOL WINAPI FreeRDP_WTSSetListenerSecurityA(
2126 WINPR_ATTR_UNUSED HANDLE hServer, WINPR_ATTR_UNUSED PVOID pReserved,
2127 WINPR_ATTR_UNUSED DWORD Reserved, WINPR_ATTR_UNUSED LPSTR pListenerName,
2128 WINPR_ATTR_UNUSED SECURITY_INFORMATION SecurityInformation,
2129 WINPR_ATTR_UNUSED PSECURITY_DESCRIPTOR pSecurityDescriptor)
2131 WLog_ERR(
"TODO",
"TODO: implement");
2135BOOL WINAPI FreeRDP_WTSGetListenerSecurityW(
2136 WINPR_ATTR_UNUSED HANDLE hServer, WINPR_ATTR_UNUSED PVOID pReserved,
2137 WINPR_ATTR_UNUSED DWORD Reserved, WINPR_ATTR_UNUSED LPWSTR pListenerName,
2138 WINPR_ATTR_UNUSED SECURITY_INFORMATION SecurityInformation,
2139 WINPR_ATTR_UNUSED PSECURITY_DESCRIPTOR pSecurityDescriptor, WINPR_ATTR_UNUSED DWORD nLength,
2140 WINPR_ATTR_UNUSED LPDWORD lpnLengthNeeded)
2142 WLog_ERR(
"TODO",
"TODO: implement");
2146BOOL WINAPI FreeRDP_WTSGetListenerSecurityA(
2147 WINPR_ATTR_UNUSED HANDLE hServer, WINPR_ATTR_UNUSED PVOID pReserved,
2148 WINPR_ATTR_UNUSED DWORD Reserved, WINPR_ATTR_UNUSED LPSTR pListenerName,
2149 WINPR_ATTR_UNUSED SECURITY_INFORMATION SecurityInformation,
2150 WINPR_ATTR_UNUSED PSECURITY_DESCRIPTOR pSecurityDescriptor, WINPR_ATTR_UNUSED DWORD nLength,
2151 WINPR_ATTR_UNUSED LPDWORD lpnLengthNeeded)
2153 WLog_ERR(
"TODO",
"TODO: implement");
2157BOOL CDECL FreeRDP_WTSEnableChildSessions(WINPR_ATTR_UNUSED BOOL bEnable)
2159 WLog_ERR(
"TODO",
"TODO: implement");
2163BOOL CDECL FreeRDP_WTSIsChildSessionsEnabled(WINPR_ATTR_UNUSED PBOOL pbEnabled)
2165 WLog_ERR(
"TODO",
"TODO: implement");
2169BOOL CDECL FreeRDP_WTSGetChildSessionId(WINPR_ATTR_UNUSED PULONG pSessionId)
2171 WLog_ERR(
"TODO",
"TODO: implement");
2175DWORD WINAPI FreeRDP_WTSGetActiveConsoleSessionId(
void)
2177 WLog_ERR(
"TODO",
"TODO: implement");
2180BOOL WINAPI FreeRDP_WTSLogoffUser(WINPR_ATTR_UNUSED HANDLE hServer)
2182 WLog_ERR(
"TODO",
"TODO: implement");
2186BOOL WINAPI FreeRDP_WTSLogonUser(WINPR_ATTR_UNUSED HANDLE hServer,
2187 WINPR_ATTR_UNUSED LPCSTR username,
2188 WINPR_ATTR_UNUSED LPCSTR password, WINPR_ATTR_UNUSED LPCSTR domain)
2190 WLog_ERR(
"TODO",
"TODO: implement");
2194void server_channel_common_free(rdpPeerChannel* channel)
2198 MessageQueue_Free(channel->queue);
2199 Stream_Free(channel->receiveData, TRUE);
2200 DeleteCriticalSection(&channel->writeLock);
2204rdpPeerChannel* server_channel_common_new(freerdp_peer* client, UINT16 index, UINT32 channelId,
2205 size_t chunkSize,
const wObject* callback,
2208 rdpPeerChannel* channel = (rdpPeerChannel*)calloc(1,
sizeof(rdpPeerChannel));
2212 InitializeCriticalSection(&channel->writeLock);
2214 channel->receiveData = Stream_New(
nullptr, chunkSize);
2215 if (!channel->receiveData)
2218 channel->queue = MessageQueue_New(callback);
2219 if (!channel->queue)
2222 channel->index = index;
2223 channel->client = client;
2224 channel->channelId = channelId;
2225 strncpy(channel->channelName, name, ARRAYSIZE(channel->channelName) - 1);
2228 WINPR_PRAGMA_DIAG_PUSH
2229 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
2230 server_channel_common_free(channel);
2231 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