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);
228 if ((value == 0) || (channel->dvc_total_length == 0))
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;
616BOOL WTSVirtualChannelManagerOpen(HANDLE hServer)
623 if (vcm->drdynvc_state == DRDYNVC_STATE_NONE)
625 rdpPeerChannel* channel =
nullptr;
628 vcm->drdynvc_state = DRDYNVC_STATE_INITIALIZED;
629 channel = (rdpPeerChannel*)WTSVirtualChannelOpen((HANDLE)vcm, WTS_CURRENT_SESSION,
630 DRDYNVC_SVC_CHANNEL_NAME);
634 BYTE capaBuffer[12] = WINPR_C_ARRAY_INIT;
635 wStream staticS = WINPR_C_ARRAY_INIT;
636 wStream* s = Stream_StaticInit(&staticS, capaBuffer,
sizeof(capaBuffer));
638 vcm->drdynvc_channel = channel;
639 vcm->dvc_spoken_version = 1;
640 Stream_Write_UINT8(s, 0x50);
641 Stream_Write_UINT8(s, 0x00);
642 Stream_Write_UINT16(s, 0x0001);
646 const size_t pos = Stream_GetPosition(s);
647 WINPR_ASSERT(pos <= UINT32_MAX);
649 if (!WTSVirtualChannelWrite(channel, (PCHAR)capaBuffer, (UINT32)pos, &written))
657BOOL WTSVirtualChannelManagerCheckFileDescriptorEx(HANDLE hServer, BOOL autoOpen)
659 wMessage message = WINPR_C_ARRAY_INIT;
663 if (!hServer || hServer == INVALID_HANDLE_VALUE)
670 if (!WTSVirtualChannelManagerOpen(hServer))
674 while (MessageQueue_Peek(vcm->queue, &message, TRUE))
676 BYTE* buffer =
nullptr;
678 UINT16 channelId = 0;
679 channelId = (UINT16)(UINT_PTR)message.context;
680 buffer = (BYTE*)message.wParam;
681 length = (UINT32)(UINT_PTR)message.lParam;
683 WINPR_ASSERT(vcm->client);
684 WINPR_ASSERT(vcm->client->SendChannelData);
685 if (!vcm->client->SendChannelData(vcm->client, channelId, buffer, length))
699BOOL WTSVirtualChannelManagerCheckFileDescriptor(HANDLE hServer)
701 return WTSVirtualChannelManagerCheckFileDescriptorEx(hServer, TRUE);
704HANDLE WTSVirtualChannelManagerGetEventHandle(HANDLE hServer)
708 return MessageQueue_Event(vcm->queue);
711static rdpMcsChannel* wts_get_joined_channel_by_name(rdpMcs* mcs,
const char* channel_name)
713 if (!mcs || !channel_name || !strnlen(channel_name, CHANNEL_NAME_LEN + 1))
716 for (UINT32 index = 0; index < mcs->channelCount; index++)
718 rdpMcsChannel* mchannel = &mcs->channels[index];
719 if (mchannel->joined)
721 if (_strnicmp(mchannel->Name, channel_name, CHANNEL_NAME_LEN + 1) == 0)
729static rdpMcsChannel* wts_get_joined_channel_by_id(rdpMcs* mcs,
const UINT16 channel_id)
731 if (!mcs || !channel_id)
734 WINPR_ASSERT(mcs->channels);
735 for (UINT32 index = 0; index < mcs->channelCount; index++)
737 rdpMcsChannel* mchannel = &mcs->channels[index];
738 if (mchannel->joined)
740 if (mchannel->ChannelId == channel_id)
741 return &mcs->channels[index];
748BOOL WTSIsChannelJoinedByName(freerdp_peer* client,
const char* channel_name)
750 if (!client || !client->context || !client->context->rdp)
753 return (wts_get_joined_channel_by_name(client->context->rdp->mcs, channel_name) !=
nullptr);
756BOOL WTSIsChannelJoinedById(freerdp_peer* client, UINT16 channel_id)
758 if (!client || !client->context || !client->context->rdp)
761 return (wts_get_joined_channel_by_id(client->context->rdp->mcs, channel_id) !=
nullptr);
764BOOL WTSVirtualChannelManagerIsChannelJoined(HANDLE hServer,
const char* name)
768 if (!vcm || !vcm->rdp)
771 return (wts_get_joined_channel_by_name(vcm->rdp->mcs, name) !=
nullptr);
774BYTE WTSVirtualChannelManagerGetDrdynvcState(HANDLE hServer)
778 return vcm->drdynvc_state;
781void WTSVirtualChannelManagerSetDVCCreationCallback(HANDLE hServer, psDVCCreationStatusCallback cb,
788 vcm->dvc_creation_status = cb;
789 vcm->dvc_creation_status_userdata = userdata;
792UINT16 WTSChannelGetId(freerdp_peer* client,
const char* channel_name)
794 rdpMcsChannel* channel =
nullptr;
796 WINPR_ASSERT(channel_name);
797 if (!client || !client->context || !client->context->rdp)
800 channel = wts_get_joined_channel_by_name(client->context->rdp->mcs, channel_name);
805 return channel->ChannelId;
808UINT32 WTSChannelGetIdByHandle(HANDLE hChannelHandle)
810 rdpPeerChannel* channel = hChannelHandle;
812 WINPR_ASSERT(channel);
814 return channel->channelId;
817BOOL WTSChannelSetHandleByName(freerdp_peer* client,
const char* channel_name,
void* handle)
819 rdpMcsChannel* channel =
nullptr;
821 WINPR_ASSERT(channel_name);
822 if (!client || !client->context || !client->context->rdp)
825 channel = wts_get_joined_channel_by_name(client->context->rdp->mcs, channel_name);
830 channel->handle = handle;
834BOOL WTSChannelSetHandleById(freerdp_peer* client, UINT16 channel_id,
void* handle)
836 rdpMcsChannel* channel =
nullptr;
838 if (!client || !client->context || !client->context->rdp)
841 channel = wts_get_joined_channel_by_id(client->context->rdp->mcs, channel_id);
846 channel->handle = handle;
850void* WTSChannelGetHandleByName(freerdp_peer* client,
const char* channel_name)
852 rdpMcsChannel* channel =
nullptr;
854 WINPR_ASSERT(channel_name);
855 if (!client || !client->context || !client->context->rdp)
858 channel = wts_get_joined_channel_by_name(client->context->rdp->mcs, channel_name);
863 return channel->handle;
866void* WTSChannelGetHandleById(freerdp_peer* client, UINT16 channel_id)
868 rdpMcsChannel* channel =
nullptr;
870 if (!client || !client->context || !client->context->rdp)
873 channel = wts_get_joined_channel_by_id(client->context->rdp->mcs, channel_id);
878 return channel->handle;
881const char* WTSChannelGetName(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 (
const char*)channel->Name;
896char** WTSGetAcceptedChannelNames(freerdp_peer* client,
size_t* count)
898 rdpMcs* mcs =
nullptr;
899 char** names =
nullptr;
901 if (!client || !client->context || !count)
904 WINPR_ASSERT(client->context->rdp);
905 mcs = client->context->rdp->mcs;
907 *count = mcs->channelCount;
909 names = (
char**)calloc(mcs->channelCount,
sizeof(
char*));
913 for (UINT32 index = 0; index < mcs->channelCount; index++)
915 rdpMcsChannel* mchannel = &mcs->channels[index];
916 names[index] = mchannel->Name;
922INT64 WTSChannelGetOptions(freerdp_peer* client, UINT16 channel_id)
924 rdpMcsChannel* channel =
nullptr;
926 if (!client || !client->context || !client->context->rdp)
929 channel = wts_get_joined_channel_by_id(client->context->rdp->mcs, channel_id);
934 return (INT64)channel->options;
937BOOL WINAPI FreeRDP_WTSStartRemoteControlSessionW(WINPR_ATTR_UNUSED LPWSTR pTargetServerName,
938 WINPR_ATTR_UNUSED ULONG TargetLogonId,
939 WINPR_ATTR_UNUSED BYTE HotkeyVk,
940 WINPR_ATTR_UNUSED USHORT HotkeyModifiers)
942 WLog_ERR(
"TODO",
"TODO: implement");
946BOOL WINAPI FreeRDP_WTSStartRemoteControlSessionA(WINPR_ATTR_UNUSED LPSTR pTargetServerName,
947 WINPR_ATTR_UNUSED ULONG TargetLogonId,
948 WINPR_ATTR_UNUSED BYTE HotkeyVk,
949 WINPR_ATTR_UNUSED USHORT HotkeyModifiers)
951 WLog_ERR(
"TODO",
"TODO: implement");
955BOOL WINAPI FreeRDP_WTSStartRemoteControlSessionExW(WINPR_ATTR_UNUSED LPWSTR pTargetServerName,
956 WINPR_ATTR_UNUSED ULONG TargetLogonId,
957 WINPR_ATTR_UNUSED BYTE HotkeyVk,
958 WINPR_ATTR_UNUSED USHORT HotkeyModifiers,
959 WINPR_ATTR_UNUSED DWORD flags)
961 WLog_ERR(
"TODO",
"TODO: implement");
965BOOL WINAPI FreeRDP_WTSStartRemoteControlSessionExA(WINPR_ATTR_UNUSED LPSTR pTargetServerName,
966 WINPR_ATTR_UNUSED ULONG TargetLogonId,
967 WINPR_ATTR_UNUSED BYTE HotkeyVk,
968 WINPR_ATTR_UNUSED USHORT HotkeyModifiers,
969 WINPR_ATTR_UNUSED DWORD flags)
971 WLog_ERR(
"TODO",
"TODO: implement");
975BOOL WINAPI FreeRDP_WTSStopRemoteControlSession(WINPR_ATTR_UNUSED ULONG LogonId)
977 WLog_ERR(
"TODO",
"TODO: implement");
981BOOL WINAPI FreeRDP_WTSConnectSessionW(WINPR_ATTR_UNUSED ULONG LogonId,
982 WINPR_ATTR_UNUSED ULONG TargetLogonId,
983 WINPR_ATTR_UNUSED PWSTR pPassword,
984 WINPR_ATTR_UNUSED BOOL bWait)
986 WLog_ERR(
"TODO",
"TODO: implement");
990BOOL WINAPI FreeRDP_WTSConnectSessionA(WINPR_ATTR_UNUSED ULONG LogonId,
991 WINPR_ATTR_UNUSED ULONG TargetLogonId,
992 WINPR_ATTR_UNUSED PSTR pPassword,
993 WINPR_ATTR_UNUSED BOOL bWait)
995 WLog_ERR(
"TODO",
"TODO: implement");
999BOOL WINAPI FreeRDP_WTSEnumerateServersW(WINPR_ATTR_UNUSED LPWSTR pDomainName,
1000 WINPR_ATTR_UNUSED DWORD Reserved,
1001 WINPR_ATTR_UNUSED DWORD Version,
1003 WINPR_ATTR_UNUSED DWORD* pCount)
1005 WLog_ERR(
"TODO",
"TODO: implement");
1009BOOL WINAPI FreeRDP_WTSEnumerateServersA(WINPR_ATTR_UNUSED LPSTR pDomainName,
1010 WINPR_ATTR_UNUSED DWORD Reserved,
1011 WINPR_ATTR_UNUSED DWORD Version,
1013 WINPR_ATTR_UNUSED DWORD* pCount)
1015 WLog_ERR(
"TODO",
"TODO: implement");
1019HANDLE WINAPI FreeRDP_WTSOpenServerW(WINPR_ATTR_UNUSED LPWSTR pServerName)
1021 WLog_ERR(
"TODO",
"TODO: implement");
1022 return INVALID_HANDLE_VALUE;
1025static void wts_virtual_channel_manager_free_message(
void* obj)
1027 wMessage* msg = (wMessage*)obj;
1031 BYTE* buffer = (BYTE*)msg->wParam;
1038static void channel_free(rdpPeerChannel* channel)
1040 server_channel_common_free(channel);
1043static void array_channel_free(
void* ptr)
1045 rdpPeerChannel* channel = ptr;
1046 channel_free(channel);
1049static BOOL dynChannelMatch(
const void* v1,
const void* v2)
1051 const UINT32* p1 = (
const UINT32*)v1;
1052 const UINT32* p2 = (
const UINT32*)v2;
1056static UINT32 channelId_Hash(
const void* key)
1058 const UINT32* v = (
const UINT32*)key;
1062static void clearHandles(
void)
1064 HashTable_Free(g_ServerHandles);
1065 g_ServerHandles =
nullptr;
1068static BOOL CALLBACK initializeHandles(WINPR_ATTR_UNUSED
PINIT_ONCE once,
1069 WINPR_ATTR_UNUSED PVOID param,
1070 WINPR_ATTR_UNUSED PVOID* context)
1072 WINPR_ASSERT(g_ServerHandles ==
nullptr);
1073 g_ServerHandles = HashTable_New(TRUE);
1074 (void)winpr_atexit(clearHandles);
1075 return g_ServerHandles !=
nullptr;
1078static bool setup(
void)
1080 return InitOnceExecuteOnce(&g_HandleInitializer, initializeHandles,
nullptr,
nullptr);
1087 HashTable_Lock(g_ServerHandles);
1091#ifdef __clang_analyzer__
1092 const BOOL valid = vcm !=
nullptr;
1094 const BOOL valid = (vcm !=
nullptr) && (vcm != INVALID_HANDLE_VALUE);
1098 HashTable_Remove(g_ServerHandles, (
void*)(UINT_PTR)vcm->SessionId);
1100 HashTable_Free(vcm->dynamicVirtualChannels);
1102 if (vcm->drdynvc_channel)
1105 (void)WTSVirtualChannelClose(vcm->drdynvc_channel);
1106 vcm->drdynvc_channel =
nullptr;
1109 MessageQueue_Free(vcm->queue);
1112 HashTable_Unlock(g_ServerHandles);
1115HANDLE WINAPI FreeRDP_WTSOpenServerA(LPSTR pServerName)
1117 wObject queueCallbacks = WINPR_C_ARRAY_INIT;
1119 rdpContext* context = WINPR_PACKED_ALIGN_CAST(rdpContext*, pServerName);
1121 if (!setup() || !context)
1122 return INVALID_HANDLE_VALUE;
1124 freerdp_peer* client = context->peer;
1128 SetLastError(ERROR_INVALID_DATA);
1129 return INVALID_HANDLE_VALUE;
1137 vcm->client = client;
1138 vcm->rdp = context->rdp;
1140 queueCallbacks.
fnObjectFree = wts_virtual_channel_manager_free_message;
1141 vcm->queue = MessageQueue_New(&queueCallbacks);
1146 vcm->dvc_channel_id_seq = 0;
1147 vcm->dynamicVirtualChannels = HashTable_New(TRUE);
1149 if (!vcm->dynamicVirtualChannels)
1152 if (!HashTable_SetHashFunction(vcm->dynamicVirtualChannels, channelId_Hash))
1156 wObject* obj = HashTable_ValueObject(vcm->dynamicVirtualChannels);
1160 obj = HashTable_KeyObject(vcm->dynamicVirtualChannels);
1163 client->ReceiveChannelData = WTSReceiveChannelData;
1165 HashTable_Lock(g_ServerHandles);
1166 vcm->SessionId = g_SessionId++;
1168 HashTable_Insert(g_ServerHandles, (
void*)(UINT_PTR)vcm->SessionId, (
void*)vcm);
1169 HashTable_Unlock(g_ServerHandles);
1174 HANDLE hServer = (HANDLE)vcm;
1178 wtsCloseVCM(vcm,
false);
1179 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1180 return INVALID_HANDLE_VALUE;
1183HANDLE WINAPI FreeRDP_WTSOpenServerExW(WINPR_ATTR_UNUSED LPWSTR pServerName)
1185 WLog_ERR(
"TODO",
"TODO: implement");
1186 return INVALID_HANDLE_VALUE;
1189HANDLE WINAPI FreeRDP_WTSOpenServerExA(LPSTR pServerName)
1191 return FreeRDP_WTSOpenServerA(pServerName);
1194VOID WINAPI FreeRDP_WTSCloseServer(HANDLE hServer)
1197 wtsCloseVCM(vcm,
true);
1200BOOL WINAPI FreeRDP_WTSEnumerateSessionsW(WINPR_ATTR_UNUSED HANDLE hServer,
1201 WINPR_ATTR_UNUSED DWORD Reserved,
1202 WINPR_ATTR_UNUSED DWORD Version,
1204 WINPR_ATTR_UNUSED DWORD* pCount)
1206 WLog_ERR(
"TODO",
"TODO: implement");
1210BOOL WINAPI FreeRDP_WTSEnumerateSessionsA(WINPR_ATTR_UNUSED HANDLE hServer,
1211 WINPR_ATTR_UNUSED DWORD Reserved,
1212 WINPR_ATTR_UNUSED DWORD Version,
1214 WINPR_ATTR_UNUSED DWORD* pCount)
1216 WLog_ERR(
"TODO",
"TODO: implement");
1220BOOL WINAPI FreeRDP_WTSEnumerateSessionsExW(WINPR_ATTR_UNUSED HANDLE hServer,
1221 WINPR_ATTR_UNUSED DWORD* pLevel,
1222 WINPR_ATTR_UNUSED DWORD Filter,
1224 WINPR_ATTR_UNUSED DWORD* pCount)
1226 WLog_ERR(
"TODO",
"TODO: implement");
1230BOOL WINAPI FreeRDP_WTSEnumerateSessionsExA(WINPR_ATTR_UNUSED HANDLE hServer,
1231 WINPR_ATTR_UNUSED DWORD* pLevel,
1232 WINPR_ATTR_UNUSED DWORD Filter,
1234 WINPR_ATTR_UNUSED DWORD* pCount)
1236 WLog_ERR(
"TODO",
"TODO: implement");
1240BOOL WINAPI FreeRDP_WTSEnumerateProcessesW(WINPR_ATTR_UNUSED HANDLE hServer,
1241 WINPR_ATTR_UNUSED DWORD Reserved,
1242 WINPR_ATTR_UNUSED DWORD Version,
1244 WINPR_ATTR_UNUSED DWORD* pCount)
1246 WLog_ERR(
"TODO",
"TODO: implement");
1250BOOL WINAPI FreeRDP_WTSEnumerateProcessesA(WINPR_ATTR_UNUSED HANDLE hServer,
1251 WINPR_ATTR_UNUSED DWORD Reserved,
1252 WINPR_ATTR_UNUSED DWORD Version,
1254 WINPR_ATTR_UNUSED DWORD* pCount)
1256 WLog_ERR(
"TODO",
"TODO: implement");
1260BOOL WINAPI FreeRDP_WTSTerminateProcess(WINPR_ATTR_UNUSED HANDLE hServer,
1261 WINPR_ATTR_UNUSED DWORD ProcessId,
1262 WINPR_ATTR_UNUSED DWORD ExitCode)
1264 WLog_ERR(
"TODO",
"TODO: implement");
1268BOOL WINAPI FreeRDP_WTSQuerySessionInformationW(WINPR_ATTR_UNUSED HANDLE hServer,
1269 WINPR_ATTR_UNUSED DWORD SessionId,
1270 WINPR_ATTR_UNUSED WTS_INFO_CLASS WTSInfoClass,
1271 WINPR_ATTR_UNUSED LPWSTR* ppBuffer,
1272 WINPR_ATTR_UNUSED DWORD* pBytesReturned)
1274 WLog_ERR(
"TODO",
"TODO: implement");
1278BOOL WINAPI FreeRDP_WTSQuerySessionInformationA(HANDLE hServer, WINPR_ATTR_UNUSED DWORD SessionId,
1279 WTS_INFO_CLASS WTSInfoClass, LPSTR* ppBuffer,
1280 DWORD* pBytesReturned)
1282 DWORD BytesReturned = 0;
1289 if (WTSInfoClass == WTSSessionId)
1291 ULONG* pBuffer =
nullptr;
1292 BytesReturned =
sizeof(ULONG);
1293 pBuffer = (ULONG*)malloc(
sizeof(BytesReturned));
1297 SetLastError(g_err_oom);
1301 *pBuffer = vcm->SessionId;
1302 *ppBuffer = (LPSTR)pBuffer;
1303 *pBytesReturned = BytesReturned;
1310BOOL WINAPI FreeRDP_WTSQueryUserConfigW(WINPR_ATTR_UNUSED LPWSTR pServerName,
1311 WINPR_ATTR_UNUSED LPWSTR pUserName,
1312 WINPR_ATTR_UNUSED WTS_CONFIG_CLASS WTSConfigClass,
1313 WINPR_ATTR_UNUSED LPWSTR* ppBuffer,
1314 WINPR_ATTR_UNUSED DWORD* pBytesReturned)
1316 WLog_ERR(
"TODO",
"TODO: implement");
1320BOOL WINAPI FreeRDP_WTSQueryUserConfigA(WINPR_ATTR_UNUSED LPSTR pServerName,
1321 WINPR_ATTR_UNUSED LPSTR pUserName,
1322 WINPR_ATTR_UNUSED WTS_CONFIG_CLASS WTSConfigClass,
1323 WINPR_ATTR_UNUSED LPSTR* ppBuffer,
1324 WINPR_ATTR_UNUSED DWORD* pBytesReturned)
1326 WLog_ERR(
"TODO",
"TODO: implement");
1330BOOL WINAPI FreeRDP_WTSSetUserConfigW(WINPR_ATTR_UNUSED LPWSTR pServerName,
1331 WINPR_ATTR_UNUSED LPWSTR pUserName,
1332 WINPR_ATTR_UNUSED WTS_CONFIG_CLASS WTSConfigClass,
1333 WINPR_ATTR_UNUSED LPWSTR pBuffer,
1334 WINPR_ATTR_UNUSED DWORD DataLength)
1336 WLog_ERR(
"TODO",
"TODO: implement");
1340BOOL WINAPI FreeRDP_WTSSetUserConfigA(WINPR_ATTR_UNUSED LPSTR pServerName,
1341 WINPR_ATTR_UNUSED LPSTR pUserName,
1342 WINPR_ATTR_UNUSED WTS_CONFIG_CLASS WTSConfigClass,
1343 WINPR_ATTR_UNUSED LPSTR pBuffer,
1344 WINPR_ATTR_UNUSED DWORD DataLength)
1346 WLog_ERR(
"TODO",
"TODO: implement");
1351FreeRDP_WTSSendMessageW(WINPR_ATTR_UNUSED HANDLE hServer, WINPR_ATTR_UNUSED DWORD SessionId,
1352 WINPR_ATTR_UNUSED LPWSTR pTitle, WINPR_ATTR_UNUSED DWORD TitleLength,
1353 WINPR_ATTR_UNUSED LPWSTR pMessage, WINPR_ATTR_UNUSED DWORD MessageLength,
1354 WINPR_ATTR_UNUSED DWORD Style, WINPR_ATTR_UNUSED DWORD Timeout,
1355 WINPR_ATTR_UNUSED DWORD* pResponse, WINPR_ATTR_UNUSED BOOL bWait)
1357 WLog_ERR(
"TODO",
"TODO: implement");
1362FreeRDP_WTSSendMessageA(WINPR_ATTR_UNUSED HANDLE hServer, WINPR_ATTR_UNUSED DWORD SessionId,
1363 WINPR_ATTR_UNUSED LPSTR pTitle, WINPR_ATTR_UNUSED DWORD TitleLength,
1364 WINPR_ATTR_UNUSED LPSTR pMessage, WINPR_ATTR_UNUSED DWORD MessageLength,
1365 WINPR_ATTR_UNUSED DWORD Style, WINPR_ATTR_UNUSED DWORD Timeout,
1366 WINPR_ATTR_UNUSED DWORD* pResponse, WINPR_ATTR_UNUSED BOOL bWait)
1368 WLog_ERR(
"TODO",
"TODO: implement");
1372BOOL WINAPI FreeRDP_WTSDisconnectSession(WINPR_ATTR_UNUSED HANDLE hServer,
1373 WINPR_ATTR_UNUSED DWORD SessionId,
1374 WINPR_ATTR_UNUSED BOOL bWait)
1376 WLog_ERR(
"TODO",
"TODO: implement");
1380BOOL WINAPI FreeRDP_WTSLogoffSession(WINPR_ATTR_UNUSED HANDLE hServer,
1381 WINPR_ATTR_UNUSED DWORD SessionId,
1382 WINPR_ATTR_UNUSED BOOL bWait)
1384 WLog_ERR(
"TODO",
"TODO: implement");
1388BOOL WINAPI FreeRDP_WTSShutdownSystem(WINPR_ATTR_UNUSED HANDLE hServer,
1389 WINPR_ATTR_UNUSED DWORD ShutdownFlag)
1391 WLog_ERR(
"TODO",
"TODO: implement");
1395BOOL WINAPI FreeRDP_WTSWaitSystemEvent(WINPR_ATTR_UNUSED HANDLE hServer,
1396 WINPR_ATTR_UNUSED DWORD EventMask,
1397 WINPR_ATTR_UNUSED DWORD* pEventFlags)
1399 WLog_ERR(
"TODO",
"TODO: implement");
1403static void peer_channel_queue_free_message(
void* obj)
1405 wMessage* msg = (wMessage*)obj;
1410 msg->context =
nullptr;
1414 UINT32 ChannelId, UINT16 index, UINT16 type,
size_t chunkSize,
1415 const char* name, UINT32 flags)
1417 wObject queueCallbacks = WINPR_C_ARRAY_INIT;
1418 queueCallbacks.
fnObjectFree = peer_channel_queue_free_message;
1420 rdpPeerChannel* channel =
1421 server_channel_common_new(client, index, ChannelId, chunkSize, &queueCallbacks, name);
1424 WINPR_ASSERT(client);
1430 channel->channelType = type;
1431 channel->creationStatus =
1432 (type == RDP_PEER_CHANNEL_TYPE_SVC) ? ERROR_SUCCESS : ERROR_OPERATION_IN_PROGRESS;
1433 channel->channelFlags = flags;
1437 channel_free(channel);
1441static HANDLE WINAPI FreeRDP_WTSVirtualChannelOpenStatic(HANDLE hServer,
1442 WINPR_ATTR_UNUSED DWORD SessionId,
1443 LPSTR pVirtualName, UINT32 Flags)
1448 SetLastError(ERROR_INVALID_DATA);
1452 freerdp_peer* client = vcm->client;
1453 WINPR_ASSERT(client);
1455 rdpContext* context = client->context;
1456 WINPR_ASSERT(context);
1457 WINPR_ASSERT(context->rdp);
1458 WINPR_ASSERT(context->settings);
1460 rdpMcs* mcs = context->rdp->mcs;
1463 size_t length = strnlen(pVirtualName, CHANNEL_NAME_LEN + 1);
1464 if (length > CHANNEL_NAME_LEN)
1466 SetLastError(ERROR_NOT_FOUND);
1470 rdpMcsChannel* joined_channel =
nullptr;
1472 for (; index < mcs->channelCount; index++)
1474 rdpMcsChannel* mchannel = &mcs->channels[index];
1475 if (mchannel->joined && (strncmp(mchannel->Name, pVirtualName, length) == 0))
1477 joined_channel = mchannel;
1482 if (!joined_channel)
1484 SetLastError(ERROR_NOT_FOUND);
1488 rdpPeerChannel* channel = (rdpPeerChannel*)joined_channel->handle;
1491 const UINT32 VCChunkSize =
1494 WINPR_ASSERT(index <= UINT16_MAX);
1495 channel = channel_new(vcm, client, joined_channel->ChannelId, (UINT16)index,
1496 RDP_PEER_CHANNEL_TYPE_SVC, VCChunkSize, pVirtualName, Flags);
1501 joined_channel->handle = channel;
1504 HANDLE hChannelHandle = (HANDLE)channel;
1505 return hChannelHandle;
1507 channel_free(channel);
1508 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1512HANDLE WINAPI FreeRDP_WTSVirtualChannelOpen(HANDLE hServer, DWORD SessionId, LPSTR pVirtualName)
1514 return FreeRDP_WTSVirtualChannelOpenStatic(hServer, SessionId, pVirtualName, 0);
1517HANDLE WINAPI FreeRDP_WTSVirtualChannelOpenEx(DWORD SessionId, LPSTR pVirtualName, DWORD flags)
1520 rdpPeerChannel* channel =
nullptr;
1521 BOOL joined = FALSE;
1527 if (SessionId == WTS_CURRENT_SESSION)
1530 HashTable_Lock(g_ServerHandles);
1532 g_ServerHandles, (
void*)(UINT_PTR)SessionId);
1537 if (!(flags & WTS_CHANNEL_OPTION_DYNAMIC))
1539 HashTable_Unlock(g_ServerHandles);
1540 return FreeRDP_WTSVirtualChannelOpenStatic((HANDLE)vcm, SessionId, pVirtualName, flags);
1543 freerdp_peer* client = vcm->client;
1544 WINPR_ASSERT(client);
1545 WINPR_ASSERT(client->context);
1546 WINPR_ASSERT(client->context->rdp);
1548 rdpMcs* mcs = client->context->rdp->mcs;
1551 for (UINT32 index = 0; index < mcs->channelCount; index++)
1553 rdpMcsChannel* mchannel = &mcs->channels[index];
1554 if (mchannel->joined &&
1555 (strncmp(mchannel->Name, DRDYNVC_SVC_CHANNEL_NAME, CHANNEL_NAME_LEN + 1) == 0))
1564 SetLastError(ERROR_NOT_FOUND);
1568 if (!vcm->drdynvc_channel || (vcm->drdynvc_state != DRDYNVC_STATE_READY))
1570 SetLastError(ERROR_NOT_READY);
1574 WINPR_ASSERT(client);
1575 WINPR_ASSERT(client->context);
1576 WINPR_ASSERT(client->context->settings);
1578 const UINT32 VCChunkSize =
1581 channel_new(vcm, client, 0, 0, RDP_PEER_CHANNEL_TYPE_DVC, VCChunkSize, pVirtualName, flags);
1585 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1589 const LONG hdl = InterlockedIncrement(&vcm->dvc_channel_id_seq);
1590 channel->channelId = WINPR_ASSERTING_INT_CAST(uint32_t, hdl);
1592 if (!HashTable_Insert(vcm->dynamicVirtualChannels, &channel->channelId, channel))
1594 channel_free(channel);
1598 s = Stream_New(
nullptr, 64);
1603 if (!wts_write_drdynvc_create_request(s, channel->channelId, pVirtualName))
1607 const size_t pos = Stream_GetPosition(s);
1608 WINPR_ASSERT(pos <= UINT32_MAX);
1609 if (!WTSVirtualChannelWrite(vcm->drdynvc_channel, Stream_BufferAs(s,
char), (UINT32)pos,
1615 Stream_Free(s, TRUE);
1616 HashTable_Unlock(g_ServerHandles);
1620 Stream_Free(s, TRUE);
1622 HashTable_Remove(vcm->dynamicVirtualChannels, &channel->channelId);
1623 HashTable_Unlock(g_ServerHandles);
1625 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1629BOOL WINAPI FreeRDP_WTSVirtualChannelClose(HANDLE hChannelHandle)
1632 rdpMcs* mcs =
nullptr;
1634 rdpPeerChannel* channel = (rdpPeerChannel*)hChannelHandle;
1642 WINPR_ASSERT(vcm->client);
1643 WINPR_ASSERT(vcm->client->context);
1644 WINPR_ASSERT(vcm->client->context->rdp);
1645 mcs = vcm->client->context->rdp->mcs;
1647 if (channel->channelType == RDP_PEER_CHANNEL_TYPE_SVC)
1649 if (channel->index < mcs->channelCount)
1651 rdpMcsChannel* cur = &mcs->channels[channel->index];
1652 rdpPeerChannel* peerChannel = (rdpPeerChannel*)cur->handle;
1653 channel_free(peerChannel);
1654 cur->handle =
nullptr;
1659 if (channel->dvc_open_state == DVC_OPEN_STATE_SUCCEEDED)
1662 s = Stream_New(
nullptr, 8);
1666 WLog_ERR(TAG,
"Stream_New failed!");
1671 wts_write_drdynvc_header(s, CLOSE_REQUEST_PDU, channel->channelId);
1673 const size_t pos = Stream_GetPosition(s);
1674 WINPR_ASSERT(pos <= UINT32_MAX);
1675 ret = WTSVirtualChannelWrite(vcm->drdynvc_channel, Stream_BufferAs(s,
char),
1676 (UINT32)pos, &written);
1677 Stream_Free(s, TRUE);
1680 HashTable_Remove(vcm->dynamicVirtualChannels, &channel->channelId);
1687BOOL WINAPI FreeRDP_WTSVirtualChannelRead(HANDLE hChannelHandle, WINPR_ATTR_UNUSED ULONG TimeOut,
1688 PCHAR Buffer, ULONG BufferSize, PULONG pBytesRead)
1690 BYTE* buffer =
nullptr;
1691 wMessage message = WINPR_C_ARRAY_INIT;
1692 wtsChannelMessage* messageCtx =
nullptr;
1693 rdpPeerChannel* channel = (rdpPeerChannel*)hChannelHandle;
1695 WINPR_ASSERT(channel);
1697 if (!MessageQueue_Peek(channel->queue, &message, FALSE))
1699 SetLastError(ERROR_NO_DATA);
1704 messageCtx = message.context;
1706 if (messageCtx ==
nullptr)
1709 buffer = (BYTE*)(messageCtx + 1);
1710 *pBytesRead = messageCtx->length - messageCtx->offset;
1712 if (Buffer ==
nullptr || BufferSize == 0)
1717 if (*pBytesRead > BufferSize)
1718 *pBytesRead = BufferSize;
1720 CopyMemory(Buffer, buffer + messageCtx->offset, *pBytesRead);
1721 messageCtx->offset += *pBytesRead;
1723 if (messageCtx->offset >= messageCtx->length)
1725 const int rc = MessageQueue_Peek(channel->queue, &message, TRUE);
1726 peer_channel_queue_free_message(&message);
1734BOOL WINAPI FreeRDP_WTSVirtualChannelWrite(HANDLE hChannelHandle, PCHAR Buffer, ULONG uLength,
1735 PULONG pBytesWritten)
1741 BYTE* buffer =
nullptr;
1742 size_t totalWritten = 0;
1743 rdpPeerChannel* channel = (rdpPeerChannel*)hChannelHandle;
1749 EnterCriticalSection(&channel->writeLock);
1750 WINPR_ASSERT(channel->vcm);
1751 if (channel->channelType == RDP_PEER_CHANNEL_TYPE_SVC)
1753 buffer = (BYTE*)malloc(uLength);
1757 SetLastError(g_err_oom);
1761 CopyMemory(buffer, Buffer, uLength);
1762 totalWritten = uLength;
1763 if (!wts_queue_send_item(channel, buffer, uLength))
1766 else if (!channel->vcm->drdynvc_channel || (channel->vcm->drdynvc_state != DRDYNVC_STATE_READY))
1768 DEBUG_DVC(
"drdynvc not ready");
1775 size_t Length = uLength;
1778 s = Stream_New(
nullptr, DVC_MAX_DATA_PDU_SIZE);
1782 WLog_ERR(TAG,
"Stream_New failed!");
1783 SetLastError(g_err_oom);
1787 buffer = Stream_Buffer(s);
1788 Stream_Seek_UINT8(s);
1789 cbChId = wts_write_variable_uint(s, channel->channelId);
1791 if (first && (Length > Stream_GetRemainingLength(s)))
1793 cbLen = wts_write_variable_uint(s, WINPR_ASSERTING_INT_CAST(uint32_t, Length));
1794 buffer[0] = ((DATA_FIRST_PDU << 4) | (cbLen << 2) | cbChId) & 0xFF;
1798 buffer[0] = ((DATA_PDU << 4) | cbChId) & 0xFF;
1802 size_t written = Stream_GetRemainingLength(s);
1804 if (written > Length)
1807 Stream_Write(s, Buffer, written);
1808 const size_t length = Stream_GetPosition(s);
1809 Stream_Free(s, FALSE);
1810 if (length > UINT32_MAX)
1814 totalWritten += written;
1815 if (!wts_queue_send_item(channel->vcm->drdynvc_channel, buffer, (UINT32)length))
1821 *pBytesWritten = WINPR_ASSERTING_INT_CAST(uint32_t, totalWritten);
1825 LeaveCriticalSection(&channel->writeLock);
1829BOOL WINAPI FreeRDP_WTSVirtualChannelPurgeInput(WINPR_ATTR_UNUSED HANDLE hChannelHandle)
1831 WLog_ERR(
"TODO",
"TODO: implement");
1835BOOL WINAPI FreeRDP_WTSVirtualChannelPurgeOutput(WINPR_ATTR_UNUSED HANDLE hChannelHandle)
1837 WLog_ERR(
"TODO",
"TODO: implement");
1841BOOL WINAPI FreeRDP_WTSVirtualChannelQuery(HANDLE hChannelHandle, WTS_VIRTUAL_CLASS WtsVirtualClass,
1842 PVOID* ppBuffer, DWORD* pBytesReturned)
1844 void* pfd =
nullptr;
1846 void* fds[10] = WINPR_C_ARRAY_INIT;
1847 HANDLE hEvent =
nullptr;
1849 BOOL status = FALSE;
1850 rdpPeerChannel* channel = (rdpPeerChannel*)hChannelHandle;
1852 WINPR_ASSERT(channel);
1854 switch ((UINT32)WtsVirtualClass)
1856 case WTSVirtualFileHandle:
1857 hEvent = MessageQueue_Event(channel->queue);
1858 pfd = GetEventWaitObject(hEvent);
1862 fds[fds_count] = pfd;
1866 *ppBuffer = malloc(
sizeof(
void*));
1870 SetLastError(g_err_oom);
1874 CopyMemory(*ppBuffer, (
void*)&fds[0],
sizeof(
void*));
1875 *pBytesReturned =
sizeof(
void*);
1881 case WTSVirtualEventHandle:
1882 hEvent = MessageQueue_Event(channel->queue);
1884 *ppBuffer = malloc(
sizeof(HANDLE));
1888 SetLastError(g_err_oom);
1892 CopyMemory(*ppBuffer, (
void*)&hEvent,
sizeof(HANDLE));
1893 *pBytesReturned =
sizeof(
void*);
1899 case WTSVirtualChannelReady:
1900 if (channel->channelType == RDP_PEER_CHANNEL_TYPE_SVC)
1907 switch (channel->dvc_open_state)
1909 case DVC_OPEN_STATE_NONE:
1914 case DVC_OPEN_STATE_SUCCEEDED:
1920 *ppBuffer =
nullptr;
1921 *pBytesReturned = 0;
1926 *ppBuffer = malloc(
sizeof(BOOL));
1930 SetLastError(g_err_oom);
1935 CopyMemory(*ppBuffer, &bval,
sizeof(BOOL));
1936 *pBytesReturned =
sizeof(BOOL);
1940 case WTSVirtualChannelOpenStatus:
1942 INT32 value = channel->creationStatus;
1945 *ppBuffer = malloc(
sizeof(value));
1948 SetLastError(g_err_oom);
1953 CopyMemory(*ppBuffer, &value,
sizeof(value));
1954 *pBytesReturned =
sizeof(value);
1965VOID WINAPI FreeRDP_WTSFreeMemory(PVOID pMemory)
1970BOOL WINAPI FreeRDP_WTSFreeMemoryExW(WINPR_ATTR_UNUSED WTS_TYPE_CLASS WTSTypeClass,
1971 WINPR_ATTR_UNUSED PVOID pMemory,
1972 WINPR_ATTR_UNUSED ULONG NumberOfEntries)
1974 WLog_ERR(
"TODO",
"TODO: implement");
1978BOOL WINAPI FreeRDP_WTSFreeMemoryExA(WINPR_ATTR_UNUSED WTS_TYPE_CLASS WTSTypeClass,
1979 WINPR_ATTR_UNUSED PVOID pMemory,
1980 WINPR_ATTR_UNUSED ULONG NumberOfEntries)
1982 WLog_ERR(
"TODO",
"TODO: implement");
1986BOOL WINAPI FreeRDP_WTSRegisterSessionNotification(WINPR_ATTR_UNUSED HWND hWnd,
1987 WINPR_ATTR_UNUSED DWORD dwFlags)
1989 WLog_ERR(
"TODO",
"TODO: implement");
1993BOOL WINAPI FreeRDP_WTSUnRegisterSessionNotification(WINPR_ATTR_UNUSED HWND hWnd)
1995 WLog_ERR(
"TODO",
"TODO: implement");
1999BOOL WINAPI FreeRDP_WTSRegisterSessionNotificationEx(WINPR_ATTR_UNUSED HANDLE hServer,
2000 WINPR_ATTR_UNUSED HWND hWnd,
2001 WINPR_ATTR_UNUSED DWORD dwFlags)
2003 WLog_ERR(
"TODO",
"TODO: implement");
2007BOOL WINAPI FreeRDP_WTSUnRegisterSessionNotificationEx(WINPR_ATTR_UNUSED HANDLE hServer,
2008 WINPR_ATTR_UNUSED HWND hWnd)
2010 WLog_ERR(
"TODO",
"TODO: implement");
2014BOOL WINAPI FreeRDP_WTSQueryUserToken(WINPR_ATTR_UNUSED ULONG SessionId,
2015 WINPR_ATTR_UNUSED PHANDLE phToken)
2017 WLog_ERR(
"TODO",
"TODO: implement");
2021BOOL WINAPI FreeRDP_WTSEnumerateProcessesExW(WINPR_ATTR_UNUSED HANDLE hServer,
2022 WINPR_ATTR_UNUSED DWORD* pLevel,
2023 WINPR_ATTR_UNUSED DWORD SessionId,
2024 WINPR_ATTR_UNUSED LPWSTR* ppProcessInfo,
2025 WINPR_ATTR_UNUSED DWORD* pCount)
2027 WLog_ERR(
"TODO",
"TODO: implement");
2031BOOL WINAPI FreeRDP_WTSEnumerateProcessesExA(WINPR_ATTR_UNUSED HANDLE hServer,
2032 WINPR_ATTR_UNUSED DWORD* pLevel,
2033 WINPR_ATTR_UNUSED DWORD SessionId,
2034 WINPR_ATTR_UNUSED LPSTR* ppProcessInfo,
2035 WINPR_ATTR_UNUSED DWORD* pCount)
2037 WLog_ERR(
"TODO",
"TODO: implement");
2041BOOL WINAPI FreeRDP_WTSEnumerateListenersW(WINPR_ATTR_UNUSED HANDLE hServer,
2042 WINPR_ATTR_UNUSED PVOID pReserved,
2043 WINPR_ATTR_UNUSED DWORD Reserved,
2044 WINPR_ATTR_UNUSED PWTSLISTENERNAMEW pListeners,
2045 WINPR_ATTR_UNUSED DWORD* pCount)
2047 WLog_ERR(
"TODO",
"TODO: implement");
2051BOOL WINAPI FreeRDP_WTSEnumerateListenersA(WINPR_ATTR_UNUSED HANDLE hServer,
2052 WINPR_ATTR_UNUSED PVOID pReserved,
2053 WINPR_ATTR_UNUSED DWORD Reserved,
2054 WINPR_ATTR_UNUSED PWTSLISTENERNAMEA pListeners,
2055 WINPR_ATTR_UNUSED DWORD* pCount)
2057 WLog_ERR(
"TODO",
"TODO: implement");
2061BOOL WINAPI FreeRDP_WTSQueryListenerConfigW(WINPR_ATTR_UNUSED HANDLE hServer,
2062 WINPR_ATTR_UNUSED PVOID pReserved,
2063 WINPR_ATTR_UNUSED DWORD Reserved,
2064 WINPR_ATTR_UNUSED LPWSTR pListenerName,
2067 WLog_ERR(
"TODO",
"TODO: implement");
2071BOOL WINAPI FreeRDP_WTSQueryListenerConfigA(WINPR_ATTR_UNUSED HANDLE hServer,
2072 WINPR_ATTR_UNUSED PVOID pReserved,
2073 WINPR_ATTR_UNUSED DWORD Reserved,
2074 WINPR_ATTR_UNUSED LPSTR pListenerName,
2077 WLog_ERR(
"TODO",
"TODO: implement");
2081BOOL WINAPI FreeRDP_WTSCreateListenerW(WINPR_ATTR_UNUSED HANDLE hServer,
2082 WINPR_ATTR_UNUSED PVOID pReserved,
2083 WINPR_ATTR_UNUSED DWORD Reserved,
2084 WINPR_ATTR_UNUSED LPWSTR pListenerName,
2086 WINPR_ATTR_UNUSED DWORD flag)
2088 WLog_ERR(
"TODO",
"TODO: implement");
2092BOOL WINAPI FreeRDP_WTSCreateListenerA(WINPR_ATTR_UNUSED HANDLE hServer,
2093 WINPR_ATTR_UNUSED PVOID pReserved,
2094 WINPR_ATTR_UNUSED DWORD Reserved,
2095 WINPR_ATTR_UNUSED LPSTR pListenerName,
2097 WINPR_ATTR_UNUSED DWORD flag)
2099 WLog_ERR(
"TODO",
"TODO: implement");
2103BOOL WINAPI FreeRDP_WTSSetListenerSecurityW(
2104 WINPR_ATTR_UNUSED HANDLE hServer, WINPR_ATTR_UNUSED PVOID pReserved,
2105 WINPR_ATTR_UNUSED DWORD Reserved, WINPR_ATTR_UNUSED LPWSTR pListenerName,
2106 WINPR_ATTR_UNUSED SECURITY_INFORMATION SecurityInformation,
2107 WINPR_ATTR_UNUSED PSECURITY_DESCRIPTOR pSecurityDescriptor)
2109 WLog_ERR(
"TODO",
"TODO: implement");
2113BOOL WINAPI FreeRDP_WTSSetListenerSecurityA(
2114 WINPR_ATTR_UNUSED HANDLE hServer, WINPR_ATTR_UNUSED PVOID pReserved,
2115 WINPR_ATTR_UNUSED DWORD Reserved, WINPR_ATTR_UNUSED LPSTR pListenerName,
2116 WINPR_ATTR_UNUSED SECURITY_INFORMATION SecurityInformation,
2117 WINPR_ATTR_UNUSED PSECURITY_DESCRIPTOR pSecurityDescriptor)
2119 WLog_ERR(
"TODO",
"TODO: implement");
2123BOOL WINAPI FreeRDP_WTSGetListenerSecurityW(
2124 WINPR_ATTR_UNUSED HANDLE hServer, WINPR_ATTR_UNUSED PVOID pReserved,
2125 WINPR_ATTR_UNUSED DWORD Reserved, WINPR_ATTR_UNUSED LPWSTR pListenerName,
2126 WINPR_ATTR_UNUSED SECURITY_INFORMATION SecurityInformation,
2127 WINPR_ATTR_UNUSED PSECURITY_DESCRIPTOR pSecurityDescriptor, WINPR_ATTR_UNUSED DWORD nLength,
2128 WINPR_ATTR_UNUSED LPDWORD lpnLengthNeeded)
2130 WLog_ERR(
"TODO",
"TODO: implement");
2134BOOL WINAPI FreeRDP_WTSGetListenerSecurityA(
2135 WINPR_ATTR_UNUSED HANDLE hServer, WINPR_ATTR_UNUSED PVOID pReserved,
2136 WINPR_ATTR_UNUSED DWORD Reserved, WINPR_ATTR_UNUSED LPSTR pListenerName,
2137 WINPR_ATTR_UNUSED SECURITY_INFORMATION SecurityInformation,
2138 WINPR_ATTR_UNUSED PSECURITY_DESCRIPTOR pSecurityDescriptor, WINPR_ATTR_UNUSED DWORD nLength,
2139 WINPR_ATTR_UNUSED LPDWORD lpnLengthNeeded)
2141 WLog_ERR(
"TODO",
"TODO: implement");
2145BOOL CDECL FreeRDP_WTSEnableChildSessions(WINPR_ATTR_UNUSED BOOL bEnable)
2147 WLog_ERR(
"TODO",
"TODO: implement");
2151BOOL CDECL FreeRDP_WTSIsChildSessionsEnabled(WINPR_ATTR_UNUSED PBOOL pbEnabled)
2153 WLog_ERR(
"TODO",
"TODO: implement");
2157BOOL CDECL FreeRDP_WTSGetChildSessionId(WINPR_ATTR_UNUSED PULONG pSessionId)
2159 WLog_ERR(
"TODO",
"TODO: implement");
2163DWORD WINAPI FreeRDP_WTSGetActiveConsoleSessionId(
void)
2165 WLog_ERR(
"TODO",
"TODO: implement");
2168BOOL WINAPI FreeRDP_WTSLogoffUser(WINPR_ATTR_UNUSED HANDLE hServer)
2170 WLog_ERR(
"TODO",
"TODO: implement");
2174BOOL WINAPI FreeRDP_WTSLogonUser(WINPR_ATTR_UNUSED HANDLE hServer,
2175 WINPR_ATTR_UNUSED LPCSTR username,
2176 WINPR_ATTR_UNUSED LPCSTR password, WINPR_ATTR_UNUSED LPCSTR domain)
2178 WLog_ERR(
"TODO",
"TODO: implement");
2182void server_channel_common_free(rdpPeerChannel* channel)
2186 MessageQueue_Free(channel->queue);
2187 Stream_Free(channel->receiveData, TRUE);
2188 DeleteCriticalSection(&channel->writeLock);
2192rdpPeerChannel* server_channel_common_new(freerdp_peer* client, UINT16 index, UINT32 channelId,
2193 size_t chunkSize,
const wObject* callback,
2196 rdpPeerChannel* channel = (rdpPeerChannel*)calloc(1,
sizeof(rdpPeerChannel));
2200 InitializeCriticalSection(&channel->writeLock);
2202 channel->receiveData = Stream_New(
nullptr, chunkSize);
2203 if (!channel->receiveData)
2206 channel->queue = MessageQueue_New(callback);
2207 if (!channel->queue)
2210 channel->index = index;
2211 channel->client = client;
2212 channel->channelId = channelId;
2213 strncpy(channel->channelName, name, ARRAYSIZE(channel->channelName) - 1);
2216 WINPR_PRAGMA_DIAG_PUSH
2217 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
2218 server_channel_common_free(channel);
2219 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