diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 01:24:41 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 01:24:41 +0000 |
commit | a9bcc81f821d7c66f623779fa5147e728eb3c388 (patch) | |
tree | 98676963bcdd537ae5908a067a8eb110b93486a6 /server/shadow/Win/win_rdp.c | |
parent | Initial commit. (diff) | |
download | freerdp3-a9bcc81f821d7c66f623779fa5147e728eb3c388.tar.xz freerdp3-a9bcc81f821d7c66f623779fa5147e728eb3c388.zip |
Adding upstream version 3.3.0+dfsg1.upstream/3.3.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'server/shadow/Win/win_rdp.c')
-rw-r--r-- | server/shadow/Win/win_rdp.c | 440 |
1 files changed, 440 insertions, 0 deletions
diff --git a/server/shadow/Win/win_rdp.c b/server/shadow/Win/win_rdp.c new file mode 100644 index 0000000..3db073d --- /dev/null +++ b/server/shadow/Win/win_rdp.c @@ -0,0 +1,440 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * + * Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <freerdp/config.h> + +#include <winpr/crt.h> +#include <winpr/assert.h> +#include <winpr/print.h> +#include <winpr/assert.h> + +#include <freerdp/log.h> + +#include "win_rdp.h" + +#define TAG SERVER_TAG("shadow.win") + +static void shw_OnChannelConnectedEventHandler(void* context, const ChannelConnectedEventArgs* e) +{ + shwContext* shw = (shwContext*)context; + WINPR_ASSERT(e); + WLog_INFO(TAG, "OnChannelConnected: %s", e->name); +} + +static void shw_OnChannelDisconnectedEventHandler(void* context, + const ChannelDisconnectedEventArgs* e) +{ + shwContext* shw = (shwContext*)context; + WINPR_ASSERT(e); + WLog_INFO(TAG, "OnChannelDisconnected: %s", e->name); +} + +static BOOL shw_begin_paint(rdpContext* context) +{ + shwContext* shw; + rdpGdi* gdi; + + WINPR_ASSERT(context); + gdi = context->gdi; + WINPR_ASSERT(gdi); + shw = (shwContext*)context; + gdi->primary->hdc->hwnd->invalid->null = TRUE; + gdi->primary->hdc->hwnd->ninvalid = 0; + return TRUE; +} + +static BOOL shw_end_paint(rdpContext* context) +{ + int ninvalid; + HGDI_RGN cinvalid; + RECTANGLE_16 invalidRect; + rdpGdi* gdi = context->gdi; + shwContext* shw = (shwContext*)context; + winShadowSubsystem* subsystem = shw->subsystem; + rdpShadowSurface* surface = subsystem->base.server->surface; + ninvalid = gdi->primary->hdc->hwnd->ninvalid; + cinvalid = gdi->primary->hdc->hwnd->cinvalid; + + for (int index = 0; index < ninvalid; index++) + { + invalidRect.left = cinvalid[index].x; + invalidRect.top = cinvalid[index].y; + invalidRect.right = cinvalid[index].x + cinvalid[index].w; + invalidRect.bottom = cinvalid[index].y + cinvalid[index].h; + region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion), &invalidRect); + } + + SetEvent(subsystem->RdpUpdateEnterEvent); + WaitForSingleObject(subsystem->RdpUpdateLeaveEvent, INFINITE); + ResetEvent(subsystem->RdpUpdateLeaveEvent); + return TRUE; +} + +BOOL shw_desktop_resize(rdpContext* context) +{ + WLog_WARN(TAG, "Desktop resizing not implemented!"); + return TRUE; +} + +static BOOL shw_surface_frame_marker(rdpContext* context, + const SURFACE_FRAME_MARKER* surfaceFrameMarker) +{ + shwContext* shw = (shwContext*)context; + return TRUE; +} + +static BOOL shw_authenticate(freerdp* instance, char** username, char** password, char** domain) +{ + WLog_WARN(TAG, "Authentication not implemented, access granted to everyone!"); + return TRUE; +} + +static int shw_verify_x509_certificate(freerdp* instance, const BYTE* data, size_t length, + const char* hostname, UINT16 port, DWORD flags) +{ + WLog_WARN(TAG, "Certificate checks not implemented, access granted to everyone!"); + return 1; +} + +static void shw_OnConnectionResultEventHandler(void* context, const ConnectionResultEventArgs* e) +{ + shwContext* shw = (shwContext*)context; + WINPR_ASSERT(e); + WLog_INFO(TAG, "OnConnectionResult: %d", e->result); +} + +static BOOL shw_pre_connect(freerdp* instance) +{ + shwContext* shw; + rdpContext* context = instance->context; + shw = (shwContext*)context; + PubSub_SubscribeConnectionResult(context->pubSub, shw_OnConnectionResultEventHandler); + PubSub_SubscribeChannelConnected(context->pubSub, shw_OnChannelConnectedEventHandler); + PubSub_SubscribeChannelDisconnected(context->pubSub, shw_OnChannelDisconnectedEventHandler); + + return TRUE; +} + +static BOOL shw_post_connect(freerdp* instance) +{ + rdpGdi* gdi; + shwContext* shw; + rdpUpdate* update; + rdpSettings* settings; + + WINPR_ASSERT(instance); + + shw = (shwContext*)instance->context; + WINPR_ASSERT(shw); + + update = instance->context->update; + WINPR_ASSERT(update); + + settings = instance->context->settings; + WINPR_ASSERT(settings); + + if (!gdi_init(instance, PIXEL_FORMAT_BGRX32)) + return FALSE; + + gdi = instance->context->gdi; + update->BeginPaint = shw_begin_paint; + update->EndPaint = shw_end_paint; + update->DesktopResize = shw_desktop_resize; + update->SurfaceFrameMarker = shw_surface_frame_marker; + return TRUE; +} + +static DWORD WINAPI shw_client_thread(LPVOID arg) +{ + int index; + BOOL bSuccess; + shwContext* shw; + rdpContext* context; + rdpChannels* channels; + + freerdp* instance = (freerdp*)arg; + WINPR_ASSERT(instance); + + context = (rdpContext*)instance->context; + WINPR_ASSERT(context); + + shw = (shwContext*)context; + + bSuccess = freerdp_connect(instance); + WLog_INFO(TAG, "freerdp_connect: %d", bSuccess); + + if (!bSuccess) + { + ExitThread(0); + return 0; + } + + channels = context->channels; + WINPR_ASSERT(channels); + + while (1) + { + DWORD status; + HANDLE handles[MAXIMUM_WAIT_OBJECTS] = { 0 }; + DWORD count = freerdp_get_event_handles(instance->context, handles, ARRAYSIZE(handles)); + + if ((count == 0) || (count == MAXIMUM_WAIT_OBJECTS)) + { + WLog_ERR(TAG, "Failed to get FreeRDP event handles"); + break; + } + + handles[count++] = freerdp_channels_get_event_handle(instance); + + if (MsgWaitForMultipleObjects(count, handles, FALSE, 1000, QS_ALLINPUT) == WAIT_FAILED) + { + WLog_ERR(TAG, "MsgWaitForMultipleObjects failure: 0x%08lX", GetLastError()); + break; + } + + if (!freerdp_check_fds(instance)) + { + WLog_ERR(TAG, "Failed to check FreeRDP file descriptor"); + break; + } + + if (freerdp_shall_disconnect_context(instance->context)) + { + break; + } + + if (!freerdp_channels_check_fds(channels, instance)) + { + WLog_ERR(TAG, "Failed to check channels file descriptor"); + break; + } + } + + freerdp_free(instance); + ExitThread(0); + return 0; +} + +/** + * Client Interface + */ + +static BOOL shw_freerdp_client_global_init(void) +{ + return TRUE; +} + +static void shw_freerdp_client_global_uninit(void) +{ +} + +static int shw_freerdp_client_start(rdpContext* context) +{ + shwContext* shw; + freerdp* instance = context->instance; + shw = (shwContext*)context; + + if (!(shw->common.thread = CreateThread(NULL, 0, shw_client_thread, instance, 0, NULL))) + { + WLog_ERR(TAG, "Failed to create thread"); + return -1; + } + + return 0; +} + +static int shw_freerdp_client_stop(rdpContext* context) +{ + shwContext* shw = (shwContext*)context; + SetEvent(shw->StopEvent); + return 0; +} + +static BOOL shw_freerdp_client_new(freerdp* instance, rdpContext* context) +{ + shwContext* shw; + rdpSettings* settings; + + WINPR_ASSERT(instance); + WINPR_ASSERT(context); + + shw = (shwContext*)instance->context; + WINPR_ASSERT(shw); + + if (!(shw->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL))) + return FALSE; + + instance->LoadChannels = freerdp_client_load_channels; + instance->PreConnect = shw_pre_connect; + instance->PostConnect = shw_post_connect; + instance->Authenticate = shw_authenticate; + instance->VerifyX509Certificate = shw_verify_x509_certificate; + + settings = context->settings; + WINPR_ASSERT(settings); + + shw->settings = settings; + if (!freerdp_settings_set_bool(settings, FreeRDP_AsyncChannels, FALSE)) + return FALSE; + if (!freerdp_settings_set_bool(settings, FreeRDP_AsyncUpdate, FALSE)) + return FALSE; + if (!freerdp_settings_set_bool(settings, FreeRDP_IgnoreCertificate, TRUE)) + return FALSE; + if (!freerdp_settings_set_bool(settings, FreeRDP_ExternalCertificateManagement, TRUE)) + return FALSE; + if (!freerdp_settings_set_bool(settings, FreeRDP_RdpSecurity, TRUE)) + return FALSE; + if (!freerdp_settings_set_bool(settings, FreeRDP_TlsSecurity, TRUE)) + return FALSE; + if (!freerdp_settings_set_bool(settings, FreeRDP_NlaSecurity, FALSE)) + return FALSE; + if (!freerdp_settings_set_bool(settings, FreeRDP_BitmapCacheEnabled, FALSE)) + return FALSE; + if (!freerdp_settings_set_bool(settings, FreeRDP_BitmapCacheV3Enabled, FALSE)) + return FALSE; + if (!freerdp_settings_set_bool(settings, FreeRDP_OffscreenSupportLevel, FALSE)) + return FALSE; + if (!freerdp_settings_set_uint32(settings, FreeRDP_GlyphSupportLevel, GLYPH_SUPPORT_NONE)) + return FALSE; + if (!freerdp_settings_set_bool(settings, FreeRDP_BrushSupportLevel, FALSE)) + return FALSE; + ZeroMemory(freerdp_settings_get_pointer_writable(settings, FreeRDP_OrderSupport), 32); + if (!freerdp_settings_set_bool(settings, FreeRDP_FrameMarkerCommandEnabled, TRUE)) + return FALSE; + if (!freerdp_settings_set_bool(settings, FreeRDP_SurfaceFrameMarkerEnabled, TRUE)) + return FALSE; + if (!freerdp_settings_set_bool(settings, FreeRDP_AltSecFrameMarkerSupport, TRUE)) + return FALSE; + if (!freerdp_settings_set_uint32(settings, FreeRDP_ColorDepth, 32)) + return FALSE; + if (!freerdp_settings_set_bool(settings, FreeRDP_NSCodec, TRUE)) + return FALSE; + if (!freerdp_settings_set_bool(settings, FreeRDP_RemoteFxCodec, TRUE)) + return FALSE; + if (!freerdp_settings_set_bool(settings, FreeRDP_FastPathInput, TRUE)) + return FALSE; + if (!freerdp_settings_set_bool(settings, FreeRDP_FastPathOutput, TRUE)) + return FALSE; + if (!freerdp_settings_set_bool(settings, FreeRDP_LargePointerFlag, TRUE)) + return FALSE; + if (!freerdp_settings_set_bool(settings, FreeRDP_CompressionEnabled, FALSE)) + return FALSE; + if (!freerdp_settings_set_bool(settings, FreeRDP_AutoReconnectionEnabled, FALSE)) + return FALSE; + if (!freerdp_settings_set_bool(settings, FreeRDP_NetworkAutoDetect, FALSE)) + return FALSE; + if (!freerdp_settings_set_bool(settings, FreeRDP_SupportHeartbeatPdu, FALSE)) + return FALSE; + if (!freerdp_settings_set_bool(settings, FreeRDP_SupportMultitransport, FALSE)) + return FALSE; + if (!freerdp_settings_set_uint32(settings, FreeRDP_ConnectionType, CONNECTION_TYPE_LAN)) + return FALSE; + if (!freerdp_settings_set_bool(settings, FreeRDP_AllowFontSmoothing, TRUE)) + return FALSE; + if (!freerdp_settings_set_bool(settings, FreeRDP_AllowDesktopComposition, TRUE)) + return FALSE; + if (!freerdp_settings_set_bool(settings, FreeRDP_DisableWallpaper, FALSE)) + return FALSE; + if (!freerdp_settings_set_bool(settings, FreeRDP_DisableFullWindowDrag, TRUE)) + return FALSE; + if (!freerdp_settings_set_bool(settings, FreeRDP_DisableMenuAnims, TRUE)) + return FALSE; + if (!freerdp_settings_set_bool(settings, FreeRDP_DisableThemes, FALSE)) + return FALSE; + if (!freerdp_settings_set_bool(settings, FreeRDP_DeviceRedirection, TRUE)) + return FALSE; + if (!freerdp_settings_set_bool(settings, FreeRDP_RedirectClipboard, TRUE)) + return FALSE; + if (!freerdp_settings_set_bool(settings, FreeRDP_SupportDynamicChannels, TRUE)) + return FALSE; + return TRUE; +} + +static void shw_freerdp_client_free(freerdp* instance, rdpContext* context) +{ + shwContext* shw = (shwContext*)instance->context; +} + +int shw_RdpClientEntry(RDP_CLIENT_ENTRY_POINTS* pEntryPoints) +{ + pEntryPoints->Version = 1; + pEntryPoints->Size = sizeof(RDP_CLIENT_ENTRY_POINTS_V1); + pEntryPoints->settings = NULL; + pEntryPoints->ContextSize = sizeof(shwContext); + pEntryPoints->GlobalInit = shw_freerdp_client_global_init; + pEntryPoints->GlobalUninit = shw_freerdp_client_global_uninit; + pEntryPoints->ClientNew = shw_freerdp_client_new; + pEntryPoints->ClientFree = shw_freerdp_client_free; + pEntryPoints->ClientStart = shw_freerdp_client_start; + pEntryPoints->ClientStop = shw_freerdp_client_stop; + return 0; +} + +int win_shadow_rdp_init(winShadowSubsystem* subsystem) +{ + rdpContext* context; + RDP_CLIENT_ENTRY_POINTS clientEntryPoints = { 0 }; + + clientEntryPoints.Size = sizeof(RDP_CLIENT_ENTRY_POINTS); + clientEntryPoints.Version = RDP_CLIENT_INTERFACE_VERSION; + shw_RdpClientEntry(&clientEntryPoints); + + if (!(subsystem->RdpUpdateEnterEvent = CreateEvent(NULL, TRUE, FALSE, NULL))) + goto fail_enter_event; + + if (!(subsystem->RdpUpdateLeaveEvent = CreateEvent(NULL, TRUE, FALSE, NULL))) + goto fail_leave_event; + + if (!(context = freerdp_client_context_new(&clientEntryPoints))) + goto fail_context; + + subsystem->shw = (shwContext*)context; + subsystem->shw->settings = context->settings; + subsystem->shw->subsystem = subsystem; + return 1; +fail_context: + CloseHandle(subsystem->RdpUpdateLeaveEvent); +fail_leave_event: + CloseHandle(subsystem->RdpUpdateEnterEvent); +fail_enter_event: + return -1; +} + +int win_shadow_rdp_start(winShadowSubsystem* subsystem) +{ + int status; + shwContext* shw = subsystem->shw; + rdpContext* context = (rdpContext*)shw; + status = freerdp_client_start(context); + return status; +} + +int win_shadow_rdp_stop(winShadowSubsystem* subsystem) +{ + int status; + shwContext* shw = subsystem->shw; + rdpContext* context = (rdpContext*)shw; + status = freerdp_client_stop(context); + return status; +} + +int win_shadow_rdp_uninit(winShadowSubsystem* subsystem) +{ + win_shadow_rdp_stop(subsystem); + return 1; +} |