22 #include <freerdp/config.h>
29 #include <winpr/wtypes.h>
30 #include <winpr/crt.h>
31 #include <winpr/synch.h>
32 #include <winpr/stream.h>
34 #include <freerdp/log.h>
35 #include <freerdp/constants.h>
36 #include <freerdp/server/channels.h>
37 #include <freerdp/channels/drdynvc.h>
38 #include <freerdp/utils/drdynvc.h>
44 #define TAG FREERDP_TAG("core.server")
46 #define DEBUG_DVC(...) WLog_DBG(TAG, __VA_ARGS__)
48 #define DEBUG_DVC(...) \
54 #define DVC_MAX_DATA_PDU_SIZE 1600
64 static DWORD g_SessionId = 1;
65 static wHashTable* g_ServerHandles = NULL;
70 return HashTable_GetItemValue(vcm->dynamicVirtualChannels, &ChannelId);
73 static BOOL wts_queue_receive_data(rdpPeerChannel* channel,
const BYTE* Buffer, UINT32 Length)
76 wtsChannelMessage* messageCtx = NULL;
78 WINPR_ASSERT(channel);
79 messageCtx = (wtsChannelMessage*)malloc(
sizeof(wtsChannelMessage) + Length);
84 messageCtx->channelId = channel->channelId;
85 messageCtx->length = Length;
86 messageCtx->offset = 0;
87 buffer = (BYTE*)(messageCtx + 1);
88 CopyMemory(buffer, Buffer, Length);
89 return MessageQueue_Post(channel->queue, messageCtx, 0, NULL, NULL);
92 static BOOL wts_queue_send_item(rdpPeerChannel* channel, BYTE* Buffer, UINT32 Length)
97 WINPR_ASSERT(channel);
98 WINPR_ASSERT(channel->vcm);
101 channelId = channel->channelId;
102 return MessageQueue_Post(channel->vcm->queue, (
void*)(UINT_PTR)channelId, 0, (
void*)buffer,
103 (
void*)(UINT_PTR)length);
106 static unsigned wts_read_variable_uint(
wStream* s,
int cbLen, UINT32* val)
113 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
116 Stream_Read_UINT8(s, *val);
120 if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))
123 Stream_Read_UINT16(s, *val);
127 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
130 Stream_Read_UINT32(s, *val);
134 WLog_ERR(TAG,
"invalid wts variable uint len %d", cbLen);
139 static BOOL wts_read_drdynvc_capabilities_response(rdpPeerChannel* channel, UINT32 length)
143 WINPR_ASSERT(channel);
144 WINPR_ASSERT(channel->vcm);
148 Stream_Seek_UINT8(channel->receiveData);
149 Stream_Read_UINT16(channel->receiveData, Version);
150 DEBUG_DVC(
"Version: %" PRIu16
"", Version);
154 WLog_ERR(TAG,
"invalid version %" PRIu16
" for DRDYNVC", Version);
159 vcm->drdynvc_state = DRDYNVC_STATE_READY;
162 vcm->dvc_spoken_version = MAX(Version, 1);
164 return SetEvent(MessageQueue_Event(vcm->queue));
167 static BOOL wts_read_drdynvc_create_response(rdpPeerChannel* channel,
wStream* s, UINT32 length)
169 UINT32 CreationStatus = 0;
172 WINPR_ASSERT(channel);
177 Stream_Read_UINT32(s, CreationStatus);
179 if ((INT32)CreationStatus < 0)
181 DEBUG_DVC(
"ChannelId %" PRIu32
" creation failed (%" PRId32
")", channel->channelId,
182 (INT32)CreationStatus);
183 channel->dvc_open_state = DVC_OPEN_STATE_FAILED;
187 DEBUG_DVC(
"ChannelId %" PRIu32
" creation succeeded", channel->channelId);
188 channel->dvc_open_state = DVC_OPEN_STATE_SUCCEEDED;
191 channel->creationStatus = (INT32)CreationStatus;
192 IFCALLRET(channel->vcm->dvc_creation_status, status, channel->vcm->dvc_creation_status_userdata,
193 channel->channelId, (INT32)CreationStatus);
195 WLog_ERR(TAG,
"vcm->dvc_creation_status failed!");
200 static BOOL wts_read_drdynvc_data_first(rdpPeerChannel* channel,
wStream* s,
int cbLen,
204 WINPR_ASSERT(channel);
206 value = wts_read_variable_uint(s, cbLen, &channel->dvc_total_length);
213 if (length > channel->dvc_total_length)
216 Stream_SetPosition(channel->receiveData, 0);
218 if (!Stream_EnsureRemainingCapacity(channel->receiveData, channel->dvc_total_length))
221 Stream_Write(channel->receiveData, Stream_ConstPointer(s), length);
225 static BOOL wts_read_drdynvc_data(rdpPeerChannel* channel,
wStream* s, UINT32 length)
229 WINPR_ASSERT(channel);
231 if (channel->dvc_total_length > 0)
233 if (Stream_GetPosition(channel->receiveData) + length > channel->dvc_total_length)
235 channel->dvc_total_length = 0;
236 WLog_ERR(TAG,
"incorrect fragment data, discarded.");
240 Stream_Write(channel->receiveData, Stream_ConstPointer(s), length);
242 if (Stream_GetPosition(channel->receiveData) >= channel->dvc_total_length)
244 ret = wts_queue_receive_data(channel, Stream_Buffer(channel->receiveData),
245 channel->dvc_total_length);
246 channel->dvc_total_length = 0;
253 ret = wts_queue_receive_data(channel, Stream_ConstPointer(s), length);
259 static void wts_read_drdynvc_close_response(rdpPeerChannel* channel)
261 WINPR_ASSERT(channel);
262 DEBUG_DVC(
"ChannelId %" PRIu32
" close response", channel->channelId);
263 channel->dvc_open_state = DVC_OPEN_STATE_CLOSED;
264 MessageQueue_PostQuit(channel->queue, 0);
267 static BOOL wts_read_drdynvc_pdu(rdpPeerChannel* channel)
272 UINT32 ChannelId = 0;
273 rdpPeerChannel* dvc = NULL;
275 WINPR_ASSERT(channel);
276 WINPR_ASSERT(channel->vcm);
278 size_t length = Stream_GetPosition(channel->receiveData);
280 if ((length < 1) || (length > UINT32_MAX))
283 Stream_SetPosition(channel->receiveData, 0);
284 const UINT8 value = Stream_Get_UINT8(channel->receiveData);
286 Cmd = (value & 0xf0) >> 4;
287 Sp = (value & 0x0c) >> 2;
288 cbChId = (value & 0x03) >> 0;
290 if (Cmd == CAPABILITY_REQUEST_PDU)
291 return wts_read_drdynvc_capabilities_response(channel, (UINT32)length);
293 if (channel->vcm->drdynvc_state == DRDYNVC_STATE_READY)
295 BOOL haveChannelId = 0;
298 case SOFT_SYNC_REQUEST_PDU:
299 case SOFT_SYNC_RESPONSE_PDU:
300 haveChannelId = FALSE;
303 haveChannelId = TRUE;
309 const unsigned val = wts_read_variable_uint(channel->receiveData, cbChId, &ChannelId);
315 DEBUG_DVC(
"Cmd %s ChannelId %" PRIu32
" length %" PRIuz
"",
316 drdynvc_get_packet_type(Cmd), ChannelId, length);
317 dvc = wts_get_dvc_channel_by_id(channel->vcm, ChannelId);
320 DEBUG_DVC(
"ChannelId %" PRIu32
" does not exist.", ChannelId);
327 case CREATE_REQUEST_PDU:
328 return wts_read_drdynvc_create_response(dvc, channel->receiveData, (UINT32)length);
331 if (dvc->dvc_open_state != DVC_OPEN_STATE_SUCCEEDED)
334 "ChannelId %" PRIu32
" did not open successfully. "
335 "Ignoring DYNVC_DATA_FIRST PDU",
340 return wts_read_drdynvc_data_first(dvc, channel->receiveData, Sp, (UINT32)length);
343 if (dvc->dvc_open_state != DVC_OPEN_STATE_SUCCEEDED)
346 "ChannelId %" PRIu32
" did not open successfully. "
347 "Ignoring DYNVC_DATA PDU",
352 return wts_read_drdynvc_data(dvc, channel->receiveData, (UINT32)length);
354 case CLOSE_REQUEST_PDU:
355 wts_read_drdynvc_close_response(dvc);
358 case DATA_FIRST_COMPRESSED_PDU:
359 case DATA_COMPRESSED_PDU:
360 WLog_ERR(TAG,
"Compressed data not handled");
363 case SOFT_SYNC_RESPONSE_PDU:
364 WLog_ERR(TAG,
"SoftSync response not handled yet(and rather strange to receive "
365 "that packet as our code doesn't send SoftSync requests");
368 case SOFT_SYNC_REQUEST_PDU:
369 WLog_ERR(TAG,
"Not expecting a SoftSyncRequest on the server");
373 WLog_ERR(TAG,
"Cmd %d not recognized.", Cmd);
379 WLog_ERR(TAG,
"received Cmd %d but channel is not ready.", Cmd);
385 static int wts_write_variable_uint(
wStream* s, UINT32 val)
393 Stream_Write_UINT8(s, val);
395 else if (val <= 0xFFFF)
398 Stream_Write_UINT16(s, val);
403 Stream_Write_UINT32(s, val);
409 static void wts_write_drdynvc_header(
wStream* s, BYTE Cmd, UINT32 ChannelId)
416 Stream_GetPointer(s, bm);
417 Stream_Seek_UINT8(s);
418 cbChId = wts_write_variable_uint(s, ChannelId);
419 *bm = ((Cmd & 0x0F) << 4) | cbChId;
422 static BOOL wts_write_drdynvc_create_request(
wStream* s, UINT32 ChannelId,
const char* ChannelName)
427 WINPR_ASSERT(ChannelName);
429 wts_write_drdynvc_header(s, CREATE_REQUEST_PDU, ChannelId);
430 len = strlen(ChannelName) + 1;
432 if (!Stream_EnsureRemainingCapacity(s, len))
435 Stream_Write(s, ChannelName, len);
439 static BOOL WTSProcessChannelData(rdpPeerChannel* channel, UINT16 channelId,
const BYTE* data,
440 size_t s, UINT32 flags,
size_t t)
443 const size_t size = s;
444 const size_t totalSize = t;
446 WINPR_ASSERT(channel);
447 WINPR_ASSERT(channel->vcm);
448 WINPR_UNUSED(channelId);
450 if (flags & CHANNEL_FLAG_FIRST)
452 Stream_SetPosition(channel->receiveData, 0);
455 if (!Stream_EnsureRemainingCapacity(channel->receiveData, size))
458 Stream_Write(channel->receiveData, data, size);
460 if (flags & CHANNEL_FLAG_LAST)
462 if (Stream_GetPosition(channel->receiveData) != totalSize)
464 WLog_ERR(TAG,
"read error");
467 if (channel == channel->vcm->drdynvc_channel)
469 ret = wts_read_drdynvc_pdu(channel);
473 const size_t pos = Stream_GetPosition(channel->receiveData);
474 if (pos > UINT32_MAX)
477 ret = wts_queue_receive_data(channel, Stream_Buffer(channel->receiveData),
481 Stream_SetPosition(channel->receiveData, 0);
487 static BOOL WTSReceiveChannelData(freerdp_peer* client, UINT16 channelId,
const BYTE* data,
488 size_t size, UINT32 flags,
size_t totalSize)
492 WINPR_ASSERT(client);
493 WINPR_ASSERT(client->context);
494 WINPR_ASSERT(client->context->rdp);
496 mcs = client->context->rdp->mcs;
499 for (UINT32 i = 0; i < mcs->channelCount; i++)
501 rdpMcsChannel* cur = &mcs->channels[i];
502 if (cur->ChannelId == channelId)
504 rdpPeerChannel* channel = (rdpPeerChannel*)cur->handle;
507 return WTSProcessChannelData(channel, channelId, data, size, flags, totalSize);
511 WLog_WARN(TAG,
"unknown channelId %" PRIu16
" ignored", channelId);
516 #if defined(WITH_FREERDP_DEPRECATED)
517 void WTSVirtualChannelManagerGetFileDescriptor(HANDLE hServer,
void** fds,
int* fds_count)
523 WINPR_ASSERT(fds_count);
525 fd = GetEventWaitObject(MessageQueue_Event(vcm->queue));
529 fds[*fds_count] = fd;
535 if (vcm->drdynvc_channel)
537 fd = GetEventWaitObject(vcm->drdynvc_channel->receiveEvent);
541 fds[*fds_count] = fd;
550 BOOL WTSVirtualChannelManagerOpen(HANDLE hServer)
557 if (vcm->drdynvc_state == DRDYNVC_STATE_NONE)
559 rdpPeerChannel* channel = NULL;
562 vcm->drdynvc_state = DRDYNVC_STATE_INITIALIZED;
563 channel = (rdpPeerChannel*)WTSVirtualChannelOpen((HANDLE)vcm, WTS_CURRENT_SESSION,
564 DRDYNVC_SVC_CHANNEL_NAME);
568 BYTE capaBuffer[12] = { 0 };
570 wStream* s = Stream_StaticInit(&staticS, capaBuffer,
sizeof(capaBuffer));
572 vcm->drdynvc_channel = channel;
573 vcm->dvc_spoken_version = 1;
574 Stream_Write_UINT8(s, 0x50);
575 Stream_Write_UINT8(s, 0x00);
576 Stream_Write_UINT16(s, 0x0001);
580 const size_t pos = Stream_GetPosition(s);
581 WINPR_ASSERT(pos <= UINT32_MAX);
583 if (!WTSVirtualChannelWrite(channel, (PCHAR)capaBuffer, (UINT32)pos, &written))
591 BOOL WTSVirtualChannelManagerCheckFileDescriptorEx(HANDLE hServer, BOOL autoOpen)
593 wMessage message = { 0 };
597 if (!hServer || hServer == INVALID_HANDLE_VALUE)
604 if (!WTSVirtualChannelManagerOpen(hServer))
608 while (MessageQueue_Peek(vcm->queue, &message, TRUE))
612 UINT16 channelId = 0;
613 channelId = (UINT16)(UINT_PTR)message.context;
614 buffer = (BYTE*)message.wParam;
615 length = (UINT32)(UINT_PTR)message.lParam;
617 WINPR_ASSERT(vcm->client);
618 WINPR_ASSERT(vcm->client->SendChannelData);
619 if (!vcm->client->SendChannelData(vcm->client, channelId, buffer, length))
633 BOOL WTSVirtualChannelManagerCheckFileDescriptor(HANDLE hServer)
635 return WTSVirtualChannelManagerCheckFileDescriptorEx(hServer, TRUE);
638 HANDLE WTSVirtualChannelManagerGetEventHandle(HANDLE hServer)
642 return MessageQueue_Event(vcm->queue);
645 static rdpMcsChannel* wts_get_joined_channel_by_name(rdpMcs* mcs,
const char* channel_name)
647 if (!mcs || !channel_name || !strnlen(channel_name, CHANNEL_NAME_LEN + 1))
650 for (UINT32 index = 0; index < mcs->channelCount; index++)
652 rdpMcsChannel* mchannel = &mcs->channels[index];
653 if (mchannel->joined)
655 if (_strnicmp(mchannel->Name, channel_name, CHANNEL_NAME_LEN + 1) == 0)
663 static rdpMcsChannel* wts_get_joined_channel_by_id(rdpMcs* mcs,
const UINT16 channel_id)
665 if (!mcs || !channel_id)
668 WINPR_ASSERT(mcs->channels);
669 for (UINT32 index = 0; index < mcs->channelCount; index++)
671 rdpMcsChannel* mchannel = &mcs->channels[index];
672 if (mchannel->joined)
674 if (mchannel->ChannelId == channel_id)
675 return &mcs->channels[index];
682 BOOL WTSIsChannelJoinedByName(freerdp_peer* client,
const char* channel_name)
684 if (!client || !client->context || !client->context->rdp)
687 return wts_get_joined_channel_by_name(client->context->rdp->mcs, channel_name) == NULL ? FALSE
691 BOOL WTSIsChannelJoinedById(freerdp_peer* client,
const UINT16 channel_id)
693 if (!client || !client->context || !client->context->rdp)
696 return wts_get_joined_channel_by_id(client->context->rdp->mcs, channel_id) == NULL ? FALSE
700 BOOL WTSVirtualChannelManagerIsChannelJoined(HANDLE hServer,
const char* name)
704 if (!vcm || !vcm->rdp)
707 return wts_get_joined_channel_by_name(vcm->rdp->mcs, name) == NULL ? FALSE : TRUE;
710 BYTE WTSVirtualChannelManagerGetDrdynvcState(HANDLE hServer)
714 return vcm->drdynvc_state;
717 void WTSVirtualChannelManagerSetDVCCreationCallback(HANDLE hServer, psDVCCreationStatusCallback cb,
724 vcm->dvc_creation_status = cb;
725 vcm->dvc_creation_status_userdata = userdata;
728 UINT16 WTSChannelGetId(freerdp_peer* client,
const char* channel_name)
730 rdpMcsChannel* channel = NULL;
732 WINPR_ASSERT(channel_name);
733 if (!client || !client->context || !client->context->rdp)
736 channel = wts_get_joined_channel_by_name(client->context->rdp->mcs, channel_name);
741 return channel->ChannelId;
744 UINT32 WTSChannelGetIdByHandle(HANDLE hChannelHandle)
746 rdpPeerChannel* channel = hChannelHandle;
748 WINPR_ASSERT(channel);
750 return channel->channelId;
753 BOOL WTSChannelSetHandleByName(freerdp_peer* client,
const char* channel_name,
void* handle)
755 rdpMcsChannel* channel = NULL;
757 WINPR_ASSERT(channel_name);
758 if (!client || !client->context || !client->context->rdp)
761 channel = wts_get_joined_channel_by_name(client->context->rdp->mcs, channel_name);
766 channel->handle = handle;
770 BOOL WTSChannelSetHandleById(freerdp_peer* client,
const UINT16 channel_id,
void* handle)
772 rdpMcsChannel* channel = NULL;
774 if (!client || !client->context || !client->context->rdp)
777 channel = wts_get_joined_channel_by_id(client->context->rdp->mcs, channel_id);
782 channel->handle = handle;
786 void* WTSChannelGetHandleByName(freerdp_peer* client,
const char* channel_name)
788 rdpMcsChannel* channel = NULL;
790 WINPR_ASSERT(channel_name);
791 if (!client || !client->context || !client->context->rdp)
794 channel = wts_get_joined_channel_by_name(client->context->rdp->mcs, channel_name);
799 return channel->handle;
802 void* WTSChannelGetHandleById(freerdp_peer* client,
const UINT16 channel_id)
804 rdpMcsChannel* channel = NULL;
806 if (!client || !client->context || !client->context->rdp)
809 channel = wts_get_joined_channel_by_id(client->context->rdp->mcs, channel_id);
814 return channel->handle;
817 const char* WTSChannelGetName(freerdp_peer* client, UINT16 channel_id)
819 rdpMcsChannel* channel = NULL;
821 if (!client || !client->context || !client->context->rdp)
824 channel = wts_get_joined_channel_by_id(client->context->rdp->mcs, channel_id);
829 return (
const char*)channel->Name;
832 char** WTSGetAcceptedChannelNames(freerdp_peer* client,
size_t* count)
837 if (!client || !client->context || !count)
840 WINPR_ASSERT(client->context->rdp);
841 mcs = client->context->rdp->mcs;
843 *count = mcs->channelCount;
845 names = (
char**)calloc(mcs->channelCount,
sizeof(
char*));
849 for (UINT32 index = 0; index < mcs->channelCount; index++)
851 rdpMcsChannel* mchannel = &mcs->channels[index];
852 names[index] = mchannel->Name;
858 INT64 WTSChannelGetOptions(freerdp_peer* client, UINT16 channel_id)
860 rdpMcsChannel* channel = NULL;
862 if (!client || !client->context || !client->context->rdp)
865 channel = wts_get_joined_channel_by_id(client->context->rdp->mcs, channel_id);
870 return (INT64)channel->options;
873 BOOL WINAPI FreeRDP_WTSStartRemoteControlSessionW(LPWSTR pTargetServerName, ULONG TargetLogonId,
874 BYTE HotkeyVk, USHORT HotkeyModifiers)
879 BOOL WINAPI FreeRDP_WTSStartRemoteControlSessionA(LPSTR pTargetServerName, ULONG TargetLogonId,
880 BYTE HotkeyVk, USHORT HotkeyModifiers)
885 BOOL WINAPI FreeRDP_WTSStartRemoteControlSessionExW(LPWSTR pTargetServerName, ULONG TargetLogonId,
886 BYTE HotkeyVk, USHORT HotkeyModifiers,
892 BOOL WINAPI FreeRDP_WTSStartRemoteControlSessionExA(LPSTR pTargetServerName, ULONG TargetLogonId,
893 BYTE HotkeyVk, USHORT HotkeyModifiers,
899 BOOL WINAPI FreeRDP_WTSStopRemoteControlSession(ULONG LogonId)
904 BOOL WINAPI FreeRDP_WTSConnectSessionW(ULONG LogonId, ULONG TargetLogonId, PWSTR pPassword,
910 BOOL WINAPI FreeRDP_WTSConnectSessionA(ULONG LogonId, ULONG TargetLogonId, PSTR pPassword,
916 BOOL WINAPI FreeRDP_WTSEnumerateServersW(LPWSTR pDomainName, DWORD Reserved, DWORD Version,
922 BOOL WINAPI FreeRDP_WTSEnumerateServersA(LPSTR pDomainName, DWORD Reserved, DWORD Version,
928 HANDLE WINAPI FreeRDP_WTSOpenServerW(LPWSTR pServerName)
930 return INVALID_HANDLE_VALUE;
933 static void wts_virtual_channel_manager_free_message(
void* obj)
935 wMessage* msg = (wMessage*)obj;
939 BYTE* buffer = (BYTE*)msg->wParam;
946 static void channel_free(rdpPeerChannel* channel)
948 server_channel_common_free(channel);
951 static void array_channel_free(
void* ptr)
953 rdpPeerChannel* channel = ptr;
954 channel_free(channel);
957 static BOOL dynChannelMatch(
const void* v1,
const void* v2)
959 const UINT32* p1 = (
const UINT32*)v1;
960 const UINT32* p2 = (
const UINT32*)v2;
964 static UINT32 channelId_Hash(
const void* key)
966 const UINT32* v = (
const UINT32*)key;
970 HANDLE WINAPI FreeRDP_WTSOpenServerA(LPSTR pServerName)
972 rdpContext* context = NULL;
973 freerdp_peer* client = NULL;
975 HANDLE hServer = INVALID_HANDLE_VALUE;
976 wObject queueCallbacks = { 0 };
978 context = (rdpContext*)pServerName;
981 return INVALID_HANDLE_VALUE;
983 client = context->peer;
987 SetLastError(ERROR_INVALID_DATA);
988 return INVALID_HANDLE_VALUE;
994 goto error_vcm_alloc;
996 vcm->client = client;
997 vcm->rdp = context->rdp;
998 vcm->SessionId = g_SessionId++;
1000 if (!g_ServerHandles)
1002 g_ServerHandles = HashTable_New(TRUE);
1004 if (!g_ServerHandles)
1008 if (!HashTable_Insert(g_ServerHandles, (
void*)(UINT_PTR)vcm->SessionId, (
void*)vcm))
1011 queueCallbacks.fnObjectFree = wts_virtual_channel_manager_free_message;
1012 vcm->queue = MessageQueue_New(&queueCallbacks);
1017 vcm->dvc_channel_id_seq = 0;
1018 vcm->dynamicVirtualChannels = HashTable_New(TRUE);
1020 if (!vcm->dynamicVirtualChannels)
1021 goto error_dynamicVirtualChannels;
1023 if (!HashTable_SetHashFunction(vcm->dynamicVirtualChannels, channelId_Hash))
1024 goto error_hashFunction;
1027 wObject* obj = HashTable_ValueObject(vcm->dynamicVirtualChannels);
1029 obj->fnObjectFree = array_channel_free;
1031 obj = HashTable_KeyObject(vcm->dynamicVirtualChannels);
1032 obj->fnObjectEquals = dynChannelMatch;
1034 client->ReceiveChannelData = WTSReceiveChannelData;
1035 hServer = (HANDLE)vcm;
1039 HashTable_Free(vcm->dynamicVirtualChannels);
1040 error_dynamicVirtualChannels:
1041 MessageQueue_Free(vcm->queue);
1043 HashTable_Remove(g_ServerHandles, (
void*)(UINT_PTR)vcm->SessionId);
1047 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1048 return INVALID_HANDLE_VALUE;
1051 HANDLE WINAPI FreeRDP_WTSOpenServerExW(LPWSTR pServerName)
1053 return INVALID_HANDLE_VALUE;
1056 HANDLE WINAPI FreeRDP_WTSOpenServerExA(LPSTR pServerName)
1058 return FreeRDP_WTSOpenServerA(pServerName);
1061 VOID WINAPI FreeRDP_WTSCloseServer(HANDLE hServer)
1066 if (vcm && (vcm != INVALID_HANDLE_VALUE))
1068 HashTable_Remove(g_ServerHandles, (
void*)(UINT_PTR)vcm->SessionId);
1070 HashTable_Free(vcm->dynamicVirtualChannels);
1072 if (vcm->drdynvc_channel)
1074 (void)WTSVirtualChannelClose(vcm->drdynvc_channel);
1075 vcm->drdynvc_channel = NULL;
1078 MessageQueue_Free(vcm->queue);
1083 BOOL WINAPI FreeRDP_WTSEnumerateSessionsW(HANDLE hServer, DWORD Reserved, DWORD Version,
1089 BOOL WINAPI FreeRDP_WTSEnumerateSessionsA(HANDLE hServer, DWORD Reserved, DWORD Version,
1095 BOOL WINAPI FreeRDP_WTSEnumerateSessionsExW(HANDLE hServer, DWORD* pLevel, DWORD Filter,
1101 BOOL WINAPI FreeRDP_WTSEnumerateSessionsExA(HANDLE hServer, DWORD* pLevel, DWORD Filter,
1107 BOOL WINAPI FreeRDP_WTSEnumerateProcessesW(HANDLE hServer, DWORD Reserved, DWORD Version,
1113 BOOL WINAPI FreeRDP_WTSEnumerateProcessesA(HANDLE hServer, DWORD Reserved, DWORD Version,
1119 BOOL WINAPI FreeRDP_WTSTerminateProcess(HANDLE hServer, DWORD ProcessId, DWORD ExitCode)
1124 BOOL WINAPI FreeRDP_WTSQuerySessionInformationW(HANDLE hServer, DWORD SessionId,
1125 WTS_INFO_CLASS WTSInfoClass, LPWSTR* ppBuffer,
1126 DWORD* pBytesReturned)
1131 BOOL WINAPI FreeRDP_WTSQuerySessionInformationA(HANDLE hServer, DWORD SessionId,
1132 WTS_INFO_CLASS WTSInfoClass, LPSTR* ppBuffer,
1133 DWORD* pBytesReturned)
1135 DWORD BytesReturned = 0;
1142 if (WTSInfoClass == WTSSessionId)
1144 ULONG* pBuffer = NULL;
1145 BytesReturned =
sizeof(ULONG);
1146 pBuffer = (ULONG*)malloc(
sizeof(BytesReturned));
1150 SetLastError(E_OUTOFMEMORY);
1154 *pBuffer = vcm->SessionId;
1155 *ppBuffer = (LPSTR)pBuffer;
1156 *pBytesReturned = BytesReturned;
1163 BOOL WINAPI FreeRDP_WTSQueryUserConfigW(LPWSTR pServerName, LPWSTR pUserName,
1164 WTS_CONFIG_CLASS WTSConfigClass, LPWSTR* ppBuffer,
1165 DWORD* pBytesReturned)
1170 BOOL WINAPI FreeRDP_WTSQueryUserConfigA(LPSTR pServerName, LPSTR pUserName,
1171 WTS_CONFIG_CLASS WTSConfigClass, LPSTR* ppBuffer,
1172 DWORD* pBytesReturned)
1177 BOOL WINAPI FreeRDP_WTSSetUserConfigW(LPWSTR pServerName, LPWSTR pUserName,
1178 WTS_CONFIG_CLASS WTSConfigClass, LPWSTR pBuffer,
1184 BOOL WINAPI FreeRDP_WTSSetUserConfigA(LPSTR pServerName, LPSTR pUserName,
1185 WTS_CONFIG_CLASS WTSConfigClass, LPSTR pBuffer,
1191 BOOL WINAPI FreeRDP_WTSSendMessageW(HANDLE hServer, DWORD SessionId, LPWSTR pTitle,
1192 DWORD TitleLength, LPWSTR pMessage, DWORD MessageLength,
1193 DWORD Style, DWORD Timeout, DWORD* pResponse, BOOL bWait)
1198 BOOL WINAPI FreeRDP_WTSSendMessageA(HANDLE hServer, DWORD SessionId, LPSTR pTitle,
1199 DWORD TitleLength, LPSTR pMessage, DWORD MessageLength,
1200 DWORD Style, DWORD Timeout, DWORD* pResponse, BOOL bWait)
1205 BOOL WINAPI FreeRDP_WTSDisconnectSession(HANDLE hServer, DWORD SessionId, BOOL bWait)
1210 BOOL WINAPI FreeRDP_WTSLogoffSession(HANDLE hServer, DWORD SessionId, BOOL bWait)
1215 BOOL WINAPI FreeRDP_WTSShutdownSystem(HANDLE hServer, DWORD ShutdownFlag)
1220 BOOL WINAPI FreeRDP_WTSWaitSystemEvent(HANDLE hServer, DWORD EventMask, DWORD* pEventFlags)
1225 static void peer_channel_queue_free_message(
void* obj)
1227 wMessage* msg = (wMessage*)obj;
1232 msg->context = NULL;
1236 UINT32 ChannelId, UINT16 index, UINT16 type,
size_t chunkSize,
1239 wObject queueCallbacks = { 0 };
1240 queueCallbacks.fnObjectFree = peer_channel_queue_free_message;
1242 rdpPeerChannel* channel =
1243 server_channel_common_new(client, index, ChannelId, chunkSize, &queueCallbacks, name);
1246 WINPR_ASSERT(client);
1252 channel->channelType = type;
1253 channel->creationStatus =
1254 (type == RDP_PEER_CHANNEL_TYPE_SVC) ? ERROR_SUCCESS : ERROR_OPERATION_IN_PROGRESS;
1258 channel_free(channel);
1262 HANDLE WINAPI FreeRDP_WTSVirtualChannelOpen(HANDLE hServer, DWORD SessionId, LPSTR pVirtualName)
1266 rdpMcsChannel* joined_channel = NULL;
1267 freerdp_peer* client = NULL;
1268 rdpPeerChannel* channel = NULL;
1270 HANDLE hChannelHandle = NULL;
1271 rdpContext* context = NULL;
1276 SetLastError(ERROR_INVALID_DATA);
1280 client = vcm->client;
1281 WINPR_ASSERT(client);
1283 context = client->context;
1284 WINPR_ASSERT(context);
1285 WINPR_ASSERT(context->rdp);
1286 WINPR_ASSERT(context->settings);
1288 mcs = context->rdp->mcs;
1291 length = strnlen(pVirtualName, CHANNEL_NAME_LEN + 1);
1293 if (length > CHANNEL_NAME_LEN)
1295 SetLastError(ERROR_NOT_FOUND);
1300 for (; index < mcs->channelCount; index++)
1302 rdpMcsChannel* mchannel = &mcs->channels[index];
1303 if (mchannel->joined && (strncmp(mchannel->Name, pVirtualName, length) == 0))
1305 joined_channel = mchannel;
1310 if (!joined_channel)
1312 SetLastError(ERROR_NOT_FOUND);
1316 channel = (rdpPeerChannel*)joined_channel->handle;
1320 const UINT32 VCChunkSize =
1322 channel = channel_new(vcm, client, joined_channel->ChannelId, index,
1323 RDP_PEER_CHANNEL_TYPE_SVC, VCChunkSize, pVirtualName);
1328 joined_channel->handle = channel;
1331 hChannelHandle = (HANDLE)channel;
1332 return hChannelHandle;
1334 channel_free(channel);
1335 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1339 HANDLE WINAPI FreeRDP_WTSVirtualChannelOpenEx(DWORD SessionId, LPSTR pVirtualName, DWORD flags)
1343 BOOL joined = FALSE;
1344 freerdp_peer* client = NULL;
1345 rdpPeerChannel* channel = NULL;
1349 if (SessionId == WTS_CURRENT_SESSION)
1353 (
void*)(UINT_PTR)SessionId);
1358 if (!(flags & WTS_CHANNEL_OPTION_DYNAMIC))
1360 return FreeRDP_WTSVirtualChannelOpen((HANDLE)vcm, SessionId, pVirtualName);
1363 client = vcm->client;
1364 mcs = client->context->rdp->mcs;
1366 for (UINT32 index = 0; index < mcs->channelCount; index++)
1368 rdpMcsChannel* mchannel = &mcs->channels[index];
1369 if (mchannel->joined &&
1370 (strncmp(mchannel->Name, DRDYNVC_SVC_CHANNEL_NAME, CHANNEL_NAME_LEN + 1) == 0))
1379 SetLastError(ERROR_NOT_FOUND);
1383 if (!vcm->drdynvc_channel || (vcm->drdynvc_state != DRDYNVC_STATE_READY))
1385 SetLastError(ERROR_NOT_READY);
1389 WINPR_ASSERT(client);
1390 WINPR_ASSERT(client->context);
1391 WINPR_ASSERT(client->context->settings);
1393 const UINT32 VCChunkSize =
1395 channel = channel_new(vcm, client, 0, 0, RDP_PEER_CHANNEL_TYPE_DVC, VCChunkSize, pVirtualName);
1399 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1403 channel->channelId = InterlockedIncrement(&vcm->dvc_channel_id_seq);
1405 if (!HashTable_Insert(vcm->dynamicVirtualChannels, &channel->channelId, channel))
1407 channel_free(channel);
1411 s = Stream_New(NULL, 64);
1416 if (!wts_write_drdynvc_create_request(s, channel->channelId, pVirtualName))
1419 const size_t pos = Stream_GetPosition(s);
1420 WINPR_ASSERT(pos <= UINT32_MAX);
1421 if (!WTSVirtualChannelWrite(vcm->drdynvc_channel, Stream_BufferAs(s,
char), (UINT32)pos,
1425 Stream_Free(s, TRUE);
1428 Stream_Free(s, TRUE);
1430 HashTable_Remove(vcm->dynamicVirtualChannels, &channel->channelId);
1432 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1436 BOOL WINAPI FreeRDP_WTSVirtualChannelClose(HANDLE hChannelHandle)
1441 rdpPeerChannel* channel = (rdpPeerChannel*)hChannelHandle;
1449 WINPR_ASSERT(vcm->client);
1450 WINPR_ASSERT(vcm->client->context);
1451 WINPR_ASSERT(vcm->client->context->rdp);
1452 mcs = vcm->client->context->rdp->mcs;
1454 if (channel->channelType == RDP_PEER_CHANNEL_TYPE_SVC)
1456 if (channel->index < mcs->channelCount)
1458 rdpMcsChannel* cur = &mcs->channels[channel->index];
1459 rdpPeerChannel* peerChannel = (rdpPeerChannel*)cur->handle;
1460 channel_free(peerChannel);
1466 if (channel->dvc_open_state == DVC_OPEN_STATE_SUCCEEDED)
1469 s = Stream_New(NULL, 8);
1473 WLog_ERR(TAG,
"Stream_New failed!");
1478 wts_write_drdynvc_header(s, CLOSE_REQUEST_PDU, channel->channelId);
1480 const size_t pos = Stream_GetPosition(s);
1481 WINPR_ASSERT(pos <= UINT32_MAX);
1482 ret = WTSVirtualChannelWrite(vcm->drdynvc_channel, Stream_BufferAs(s,
char),
1483 (UINT32)pos, &written);
1484 Stream_Free(s, TRUE);
1487 HashTable_Remove(vcm->dynamicVirtualChannels, &channel->channelId);
1494 BOOL WINAPI FreeRDP_WTSVirtualChannelRead(HANDLE hChannelHandle, ULONG TimeOut, PCHAR Buffer,
1495 ULONG BufferSize, PULONG pBytesRead)
1497 BYTE* buffer = NULL;
1498 wMessage message = { 0 };
1499 wtsChannelMessage* messageCtx = NULL;
1500 rdpPeerChannel* channel = (rdpPeerChannel*)hChannelHandle;
1502 WINPR_ASSERT(channel);
1504 if (!MessageQueue_Peek(channel->queue, &message, FALSE))
1506 SetLastError(ERROR_NO_DATA);
1511 messageCtx = message.context;
1513 if (messageCtx == NULL)
1516 buffer = (BYTE*)(messageCtx + 1);
1517 *pBytesRead = messageCtx->length - messageCtx->offset;
1519 if (Buffer == NULL || BufferSize == 0)
1524 if (*pBytesRead > BufferSize)
1525 *pBytesRead = BufferSize;
1527 CopyMemory(Buffer, buffer + messageCtx->offset, *pBytesRead);
1528 messageCtx->offset += *pBytesRead;
1530 if (messageCtx->offset >= messageCtx->length)
1532 (void)MessageQueue_Peek(channel->queue, &message, TRUE);
1533 peer_channel_queue_free_message(&message);
1539 BOOL WINAPI FreeRDP_WTSVirtualChannelWrite(HANDLE hChannelHandle, PCHAR Buffer, ULONG Length,
1540 PULONG pBytesWritten)
1546 BYTE* buffer = NULL;
1547 UINT32 totalWritten = 0;
1548 rdpPeerChannel* channel = (rdpPeerChannel*)hChannelHandle;
1554 EnterCriticalSection(&channel->writeLock);
1555 WINPR_ASSERT(channel->vcm);
1556 if (channel->channelType == RDP_PEER_CHANNEL_TYPE_SVC)
1558 const ULONG length = Length;
1559 buffer = (BYTE*)malloc(length);
1563 SetLastError(E_OUTOFMEMORY);
1567 CopyMemory(buffer, Buffer, length);
1568 totalWritten = Length;
1569 if (!wts_queue_send_item(channel, buffer, length))
1572 else if (!channel->vcm->drdynvc_channel || (channel->vcm->drdynvc_state != DRDYNVC_STATE_READY))
1574 DEBUG_DVC(
"drdynvc not ready");
1579 rdpContext* context = NULL;
1582 WINPR_ASSERT(channel->client);
1583 context = channel->client->context;
1584 WINPR_ASSERT(context);
1587 s = Stream_New(NULL, DVC_MAX_DATA_PDU_SIZE);
1591 WLog_ERR(TAG,
"Stream_New failed!");
1592 SetLastError(E_OUTOFMEMORY);
1596 buffer = Stream_Buffer(s);
1597 Stream_Seek_UINT8(s);
1598 cbChId = wts_write_variable_uint(s, channel->channelId);
1600 if (first && (Length > Stream_GetRemainingLength(s)))
1602 cbLen = wts_write_variable_uint(s, Length);
1603 buffer[0] = (DATA_FIRST_PDU << 4) | (cbLen << 2) | cbChId;
1607 buffer[0] = (DATA_PDU << 4) | cbChId;
1611 size_t written = Stream_GetRemainingLength(s);
1613 if (written > Length)
1616 Stream_Write(s, Buffer, written);
1617 const size_t length = Stream_GetPosition(s);
1618 Stream_Free(s, FALSE);
1619 if (length > UINT32_MAX)
1623 totalWritten += written;
1624 if (!wts_queue_send_item(channel->vcm->drdynvc_channel, buffer, (UINT32)length))
1630 *pBytesWritten = totalWritten;
1634 LeaveCriticalSection(&channel->writeLock);
1638 BOOL WINAPI FreeRDP_WTSVirtualChannelPurgeInput(HANDLE hChannelHandle)
1643 BOOL WINAPI FreeRDP_WTSVirtualChannelPurgeOutput(HANDLE hChannelHandle)
1648 BOOL WINAPI FreeRDP_WTSVirtualChannelQuery(HANDLE hChannelHandle, WTS_VIRTUAL_CLASS WtsVirtualClass,
1649 PVOID* ppBuffer, DWORD* pBytesReturned)
1653 void* fds[10] = { 0 };
1654 HANDLE hEvent = NULL;
1656 BOOL status = FALSE;
1657 rdpPeerChannel* channel = (rdpPeerChannel*)hChannelHandle;
1659 WINPR_ASSERT(channel);
1661 switch ((UINT32)WtsVirtualClass)
1663 case WTSVirtualFileHandle:
1664 hEvent = MessageQueue_Event(channel->queue);
1665 pfd = GetEventWaitObject(hEvent);
1669 fds[fds_count] = pfd;
1673 *ppBuffer = malloc(
sizeof(
void*));
1677 SetLastError(E_OUTOFMEMORY);
1681 CopyMemory(*ppBuffer, &fds[0],
sizeof(
void*));
1682 *pBytesReturned =
sizeof(
void*);
1688 case WTSVirtualEventHandle:
1689 hEvent = MessageQueue_Event(channel->queue);
1691 *ppBuffer = malloc(
sizeof(HANDLE));
1695 SetLastError(E_OUTOFMEMORY);
1699 CopyMemory(*ppBuffer, &(hEvent),
sizeof(HANDLE));
1700 *pBytesReturned =
sizeof(
void*);
1706 case WTSVirtualChannelReady:
1707 if (channel->channelType == RDP_PEER_CHANNEL_TYPE_SVC)
1714 switch (channel->dvc_open_state)
1716 case DVC_OPEN_STATE_NONE:
1721 case DVC_OPEN_STATE_SUCCEEDED:
1728 *pBytesReturned = 0;
1733 *ppBuffer = malloc(
sizeof(BOOL));
1737 SetLastError(E_OUTOFMEMORY);
1742 CopyMemory(*ppBuffer, &bval,
sizeof(BOOL));
1743 *pBytesReturned =
sizeof(BOOL);
1747 case WTSVirtualChannelOpenStatus:
1749 INT32 value = channel->creationStatus;
1752 *ppBuffer = malloc(
sizeof(value));
1755 SetLastError(E_OUTOFMEMORY);
1760 CopyMemory(*ppBuffer, &value,
sizeof(value));
1761 *pBytesReturned =
sizeof(value);
1772 VOID WINAPI FreeRDP_WTSFreeMemory(PVOID pMemory)
1777 BOOL WINAPI FreeRDP_WTSFreeMemoryExW(WTS_TYPE_CLASS WTSTypeClass, PVOID pMemory,
1778 ULONG NumberOfEntries)
1783 BOOL WINAPI FreeRDP_WTSFreeMemoryExA(WTS_TYPE_CLASS WTSTypeClass, PVOID pMemory,
1784 ULONG NumberOfEntries)
1789 BOOL WINAPI FreeRDP_WTSRegisterSessionNotification(HWND hWnd, DWORD dwFlags)
1794 BOOL WINAPI FreeRDP_WTSUnRegisterSessionNotification(HWND hWnd)
1799 BOOL WINAPI FreeRDP_WTSRegisterSessionNotificationEx(HANDLE hServer, HWND hWnd, DWORD dwFlags)
1804 BOOL WINAPI FreeRDP_WTSUnRegisterSessionNotificationEx(HANDLE hServer, HWND hWnd)
1809 BOOL WINAPI FreeRDP_WTSQueryUserToken(ULONG SessionId, PHANDLE phToken)
1814 BOOL WINAPI FreeRDP_WTSEnumerateProcessesExW(HANDLE hServer, DWORD* pLevel, DWORD SessionId,
1815 LPWSTR* ppProcessInfo, DWORD* pCount)
1820 BOOL WINAPI FreeRDP_WTSEnumerateProcessesExA(HANDLE hServer, DWORD* pLevel, DWORD SessionId,
1821 LPSTR* ppProcessInfo, DWORD* pCount)
1826 BOOL WINAPI FreeRDP_WTSEnumerateListenersW(HANDLE hServer, PVOID pReserved, DWORD Reserved,
1827 PWTSLISTENERNAMEW pListeners, DWORD* pCount)
1832 BOOL WINAPI FreeRDP_WTSEnumerateListenersA(HANDLE hServer, PVOID pReserved, DWORD Reserved,
1833 PWTSLISTENERNAMEA pListeners, DWORD* pCount)
1838 BOOL WINAPI FreeRDP_WTSQueryListenerConfigW(HANDLE hServer, PVOID pReserved, DWORD Reserved,
1844 BOOL WINAPI FreeRDP_WTSQueryListenerConfigA(HANDLE hServer, PVOID pReserved, DWORD Reserved,
1850 BOOL WINAPI FreeRDP_WTSCreateListenerW(HANDLE hServer, PVOID pReserved, DWORD Reserved,
1857 BOOL WINAPI FreeRDP_WTSCreateListenerA(HANDLE hServer, PVOID pReserved, DWORD Reserved,
1863 BOOL WINAPI FreeRDP_WTSSetListenerSecurityW(HANDLE hServer, PVOID pReserved, DWORD Reserved,
1864 LPWSTR pListenerName,
1865 SECURITY_INFORMATION SecurityInformation,
1866 PSECURITY_DESCRIPTOR pSecurityDescriptor)
1871 BOOL WINAPI FreeRDP_WTSSetListenerSecurityA(HANDLE hServer, PVOID pReserved, DWORD Reserved,
1872 LPSTR pListenerName,
1873 SECURITY_INFORMATION SecurityInformation,
1874 PSECURITY_DESCRIPTOR pSecurityDescriptor)
1879 BOOL WINAPI FreeRDP_WTSGetListenerSecurityW(HANDLE hServer, PVOID pReserved, DWORD Reserved,
1880 LPWSTR pListenerName,
1881 SECURITY_INFORMATION SecurityInformation,
1882 PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD nLength,
1883 LPDWORD lpnLengthNeeded)
1888 BOOL WINAPI FreeRDP_WTSGetListenerSecurityA(HANDLE hServer, PVOID pReserved, DWORD Reserved,
1889 LPSTR pListenerName,
1890 SECURITY_INFORMATION SecurityInformation,
1891 PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD nLength,
1892 LPDWORD lpnLengthNeeded)
1897 BOOL CDECL FreeRDP_WTSEnableChildSessions(BOOL bEnable)
1902 BOOL CDECL FreeRDP_WTSIsChildSessionsEnabled(PBOOL pbEnabled)
1907 BOOL CDECL FreeRDP_WTSGetChildSessionId(PULONG pSessionId)
1912 DWORD WINAPI FreeRDP_WTSGetActiveConsoleSessionId(
void)
1916 BOOL WINAPI FreeRDP_WTSLogoffUser(HANDLE hServer)
1921 BOOL WINAPI FreeRDP_WTSLogonUser(HANDLE hServer, LPCSTR username, LPCSTR password, LPCSTR domain)
1926 void server_channel_common_free(rdpPeerChannel* channel)
1930 MessageQueue_Free(channel->queue);
1931 Stream_Free(channel->receiveData, TRUE);
1932 DeleteCriticalSection(&channel->writeLock);
1936 rdpPeerChannel* server_channel_common_new(freerdp_peer* client, UINT16 index, UINT32 channelId,
1937 size_t chunkSize,
const wObject* callback,
1940 rdpPeerChannel* channel = (rdpPeerChannel*)calloc(1,
sizeof(rdpPeerChannel));
1944 InitializeCriticalSection(&channel->writeLock);
1946 channel->receiveData = Stream_New(NULL, chunkSize);
1947 if (!channel->receiveData)
1950 channel->queue = MessageQueue_New(callback);
1951 if (!channel->queue)
1954 channel->index = index;
1955 channel->client = client;
1956 channel->channelId = channelId;
1957 strncpy(channel->channelName, name, ARRAYSIZE(channel->channelName) - 1);
1960 WINPR_PRAGMA_DIAG_PUSH
1961 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
1962 server_channel_common_free(channel);
1963 WINPR_PRAGMA_DIAG_POP
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.