24#include <freerdp/display.h>
25#include <freerdp/message.h>
26#include <freerdp/session.h>
27#include <winpr/assert.h>
28#include <winpr/image.h>
29#include <winpr/sysinfo.h>
31#include <freerdp/server/proxy/proxy_log.h>
36#include <freerdp/server/proxy/proxy_context.h>
37#include "proxy_modules.h"
39#define TAG PROXY_TAG("update")
42static BOOL pf_server_refresh_rect(rdpContext* context, BYTE count,
const RECTANGLE_16* areas)
44 pServerContext* ps = (pServerContext*)context;
46 WINPR_ASSERT(ps->pdata);
48 pClientContext* pc = proxy_data_get_client_context(ps->pdata);
62 return pf_client_post_message(pc, MakeMessageId(Update, RefreshRect), count, copy);
66static BOOL pf_server_suppress_output(rdpContext* context, BYTE allow,
const RECTANGLE_16* area)
68 pServerContext* ps = (pServerContext*)context;
70 WINPR_ASSERT(ps->pdata);
72 pClientContext* pc = proxy_data_get_client_context(ps->pdata);
86 return pf_client_post_message(pc, MakeMessageId(Update, SuppressOutput), allow, copy);
89BOOL pf_client_process_update_message(pClientContext* pc,
const wMessage* msg)
94 rdpContext* context = &pc->cctx.context;
95 if (!freerdp_is_active_state(context))
98 WINPR_ASSERT(context->update);
99 switch (GetMessageType(msg->id))
101 case Update_RefreshRect:
102 WINPR_ASSERT(context->update->RefreshRect);
103 return context->update->RefreshRect(context, (BYTE)(
size_t)msg->wParam,
105 case Update_SuppressOutput:
106 WINPR_ASSERT(context->update->SuppressOutput);
107 return context->update->SuppressOutput(context, (BYTE)(
size_t)msg->wParam,
121static BOOL pf_client_begin_paint(rdpContext* context)
123 pClientContext* pc = (pClientContext*)context;
126 proxyData* pdata = pc->pdata;
129 pServerContext* ps = proxy_data_get_server_context(pdata);
132 WINPR_ASSERT(ps->context.update);
133 WINPR_ASSERT(ps->context.update->BeginPaint);
134 WLog_DBG(TAG,
"called");
135 return ps->context.update->BeginPaint(&ps->context);
144static BOOL pf_client_end_paint(rdpContext* context)
146 pClientContext* pc = (pClientContext*)context;
149 proxyData* pdata = pc->pdata;
152 pServerContext* ps = proxy_data_get_server_context(pdata);
154 WINPR_ASSERT(ps->context.update);
155 WINPR_ASSERT(ps->context.update->EndPaint);
157 WLog_DBG(TAG,
"called");
160 if (!ps->context.update->EndPaint(&ps->context))
163 if (!pf_modules_run_hook(pdata->module, HOOK_TYPE_CLIENT_END_PAINT, pdata, context))
170static BOOL pf_client_bitmap_update(rdpContext* context,
const BITMAP_UPDATE* bitmap)
172 pClientContext* pc = (pClientContext*)context;
175 proxyData* pdata = pc->pdata;
178 pServerContext* ps = proxy_data_get_server_context(pdata);
180 WINPR_ASSERT(ps->context.update);
181 WINPR_ASSERT(ps->context.update->BitmapUpdate);
182 WLog_DBG(TAG,
"called");
183 return ps->context.update->BitmapUpdate(&ps->context, bitmap);
187static BOOL pf_client_desktop_resize(rdpContext* context)
189 pClientContext* pc = (pClientContext*)context;
192 proxyData* pdata = pc->pdata;
195 pServerContext* ps = proxy_data_get_server_context(pdata);
197 WINPR_ASSERT(ps->context.update);
198 WINPR_ASSERT(ps->context.update->DesktopResize);
199 WINPR_ASSERT(context->settings);
200 WINPR_ASSERT(ps->context.settings);
201 WLog_DBG(TAG,
"called");
206 return ps->context.update->DesktopResize(&ps->context);
210static BOOL pf_client_remote_monitors(rdpContext* context, UINT32 count,
213 pClientContext* pc = (pClientContext*)context;
216 proxyData* pdata = pc->pdata;
219 pServerContext* ps = proxy_data_get_server_context(pdata);
221 WLog_DBG(TAG,
"called");
222 return freerdp_display_send_monitor_layout(&ps->context, count, monitors);
226static BOOL pf_client_send_pointer_system(rdpContext* context,
229 pClientContext* pc = (pClientContext*)context;
232 proxyData* pdata = pc->pdata;
235 pServerContext* ps = proxy_data_get_server_context(pdata);
237 WINPR_ASSERT(ps->context.update);
238 WINPR_ASSERT(ps->context.update->pointer);
239 WINPR_ASSERT(ps->context.update->pointer->PointerSystem);
240 WLog_DBG(TAG,
"called");
241 return ps->context.update->pointer->PointerSystem(&ps->context, pointer_system);
245static BOOL pf_client_send_pointer_position(rdpContext* context,
248 pClientContext* pc = (pClientContext*)context;
251 proxyData* pdata = pc->pdata;
254 pServerContext* ps = proxy_data_get_server_context(pdata);
256 WINPR_ASSERT(ps->context.update);
257 WINPR_ASSERT(ps->context.update->pointer);
258 WINPR_ASSERT(ps->context.update->pointer->PointerPosition);
259 WLog_DBG(TAG,
"called");
260 return ps->context.update->pointer->PointerPosition(&ps->context, pointerPosition);
264static BOOL pf_client_send_pointer_color(rdpContext* context,
267 pClientContext* pc = (pClientContext*)context;
270 proxyData* pdata = pc->pdata;
273 pServerContext* ps = proxy_data_get_server_context(pdata);
275 WINPR_ASSERT(ps->context.update);
276 WINPR_ASSERT(ps->context.update->pointer);
277 WINPR_ASSERT(ps->context.update->pointer->PointerColor);
278 WLog_DBG(TAG,
"called");
279 return ps->context.update->pointer->PointerColor(&ps->context, pointer_color);
283static BOOL pf_client_send_pointer_large(rdpContext* context,
286 pClientContext* pc = (pClientContext*)context;
289 proxyData* pdata = pc->pdata;
292 pServerContext* ps = proxy_data_get_server_context(pdata);
294 WINPR_ASSERT(ps->context.update);
295 WINPR_ASSERT(ps->context.update->pointer);
296 WINPR_ASSERT(ps->context.update->pointer->PointerLarge);
297 WLog_DBG(TAG,
"called");
298 return ps->context.update->pointer->PointerLarge(&ps->context, pointer_large);
302static BOOL pf_client_send_pointer_new(rdpContext* context,
const POINTER_NEW_UPDATE* pointer_new)
304 pClientContext* pc = (pClientContext*)context;
307 proxyData* pdata = pc->pdata;
310 pServerContext* ps = proxy_data_get_server_context(pdata);
312 WINPR_ASSERT(ps->context.update);
313 WINPR_ASSERT(ps->context.update->pointer);
314 WINPR_ASSERT(ps->context.update->pointer->PointerNew);
315 WLog_DBG(TAG,
"called");
316 return ps->context.update->pointer->PointerNew(&ps->context, pointer_new);
320static BOOL pf_client_send_pointer_cached(rdpContext* context,
323 pClientContext* pc = (pClientContext*)context;
326 proxyData* pdata = pc->pdata;
329 pServerContext* ps = proxy_data_get_server_context(pdata);
331 WINPR_ASSERT(ps->context.update);
332 WINPR_ASSERT(ps->context.update->pointer);
333 WINPR_ASSERT(ps->context.update->pointer->PointerCached);
334 WLog_DBG(TAG,
"called");
335 return ps->context.update->pointer->PointerCached(&ps->context, pointer_cached);
339static BOOL pf_client_save_session_info(rdpContext* context, UINT32 type,
const void* data)
341 const logon_info* logonInfo =
nullptr;
342 pClientContext* pc = (pClientContext*)context;
345 proxyData* pdata = pc->pdata;
348 pServerContext* ps = proxy_data_get_server_context(pdata);
350 WINPR_ASSERT(ps->context.update);
351 WINPR_ASSERT(ps->context.update->SaveSessionInfo);
353 WLog_DBG(TAG,
"called");
357 case INFO_TYPE_LOGON:
358 case INFO_TYPE_LOGON_LONG:
360 logonInfo = (
const logon_info*)data;
361 PROXY_LOG_INFO(TAG, pc,
"client logon info: Username: %s, Domain: %s",
362 logonInfo->username, logonInfo->domain);
370 return ps->context.update->SaveSessionInfo(&ps->context, type, data);
374static BOOL pf_client_server_status_info(rdpContext* context, UINT32 status)
376 pClientContext* pc = (pClientContext*)context;
379 proxyData* pdata = pc->pdata;
381 pServerContext* ps = proxy_data_get_server_context(pdata);
383 WINPR_ASSERT(ps->context.update);
384 WINPR_ASSERT(ps->context.update->ServerStatusInfo);
386 WLog_DBG(TAG,
"called");
387 return ps->context.update->ServerStatusInfo(&ps->context, status);
391static BOOL pf_client_set_keyboard_indicators(rdpContext* context, UINT16 led_flags)
393 pClientContext* pc = (pClientContext*)context;
396 proxyData* pdata = pc->pdata;
399 pServerContext* ps = proxy_data_get_server_context(pdata);
401 WINPR_ASSERT(ps->context.update);
402 WINPR_ASSERT(ps->context.update->SetKeyboardIndicators);
404 WLog_DBG(TAG,
"called");
405 return ps->context.update->SetKeyboardIndicators(&ps->context, led_flags);
409static BOOL pf_client_set_keyboard_ime_status(rdpContext* context, UINT16 imeId, UINT32 imeState,
412 pClientContext* pc = (pClientContext*)context;
415 proxyData* pdata = pc->pdata;
418 pServerContext* ps = proxy_data_get_server_context(pdata);
420 WINPR_ASSERT(ps->context.update);
421 WINPR_ASSERT(ps->context.update->SetKeyboardImeStatus);
423 WLog_DBG(TAG,
"called");
424 return ps->context.update->SetKeyboardImeStatus(&ps->context, imeId, imeState, imeConvMode);
428static BOOL pf_client_SurfaceBits(rdpContext* context,
431 pClientContext* pc = (pClientContext*)context;
434 proxyData* pdata = pc->pdata;
437 pServerContext* ps = proxy_data_get_server_context(pdata);
440 WINPR_ASSERT(ps->context.update);
441 WINPR_ASSERT(ps->context.update->SurfaceBits);
443 WLog_DBG(TAG,
"called");
444 return ps->context.update->SurfaceBits(&ps->context, surfaceBitsCommand);
448static BOOL pf_client_SurfaceFrameMarker(rdpContext* context,
451 pClientContext* pc = (pClientContext*)context;
454 proxyData* pdata = pc->pdata;
457 pServerContext* ps = proxy_data_get_server_context(pdata);
460 WINPR_ASSERT(ps->context.update);
461 WINPR_ASSERT(ps->context.update->SurfaceFrameMarker);
463 WLog_DBG(TAG,
"called");
464 return ps->context.update->SurfaceFrameMarker(&ps->context, surfaceFrameMarker);
468static BOOL pf_client_window_create(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo,
471 pClientContext* pc = (pClientContext*)context;
474 proxyData* pdata = pc->pdata;
477 pServerContext* ps = proxy_data_get_server_context(pdata);
479 WINPR_ASSERT(ps->context.update);
480 WINPR_ASSERT(ps->context.update->window);
481 WINPR_ASSERT(ps->context.update->window->WindowCreate);
483 WLog_DBG(TAG,
"called");
484 rdp_update_lock(ps->context.update);
485 const BOOL rc = ps->context.update->window->WindowCreate(&ps->context, orderInfo, windowState);
486 rdp_update_unlock(ps->context.update);
491static BOOL pf_client_window_update(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo,
494 pClientContext* pc = (pClientContext*)context;
497 proxyData* pdata = pc->pdata;
500 pServerContext* ps = proxy_data_get_server_context(pdata);
502 WINPR_ASSERT(ps->context.update);
503 WINPR_ASSERT(ps->context.update->window);
504 WINPR_ASSERT(ps->context.update->window->WindowUpdate);
506 WLog_DBG(TAG,
"called");
507 rdp_update_lock(ps->context.update);
508 const BOOL rc = ps->context.update->window->WindowUpdate(&ps->context, orderInfo, windowState);
509 rdp_update_unlock(ps->context.update);
514static BOOL pf_client_window_icon(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo,
517 pClientContext* pc = (pClientContext*)context;
520 proxyData* pdata = pc->pdata;
523 pServerContext* ps = proxy_data_get_server_context(pdata);
525 WINPR_ASSERT(ps->context.update);
526 WINPR_ASSERT(ps->context.update->window);
527 WINPR_ASSERT(ps->context.update->window->WindowIcon);
529 WLog_DBG(TAG,
"called");
530 rdp_update_lock(ps->context.update);
531 const BOOL rc = ps->context.update->window->WindowIcon(&ps->context, orderInfo, windowIcon);
532 rdp_update_unlock(ps->context.update);
537static BOOL pf_client_window_cached_icon(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo,
540 pClientContext* pc = (pClientContext*)context;
543 proxyData* pdata = pc->pdata;
546 pServerContext* ps = proxy_data_get_server_context(pdata);
548 WINPR_ASSERT(ps->context.update);
549 WINPR_ASSERT(ps->context.update->window);
550 WINPR_ASSERT(ps->context.update->window->WindowCachedIcon);
552 WLog_DBG(TAG,
"called");
553 rdp_update_lock(ps->context.update);
555 ps->context.update->window->WindowCachedIcon(&ps->context, orderInfo, windowCachedIcon);
556 rdp_update_unlock(ps->context.update);
561static BOOL pf_client_window_delete(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo)
563 pClientContext* pc = (pClientContext*)context;
566 proxyData* pdata = pc->pdata;
569 pServerContext* ps = proxy_data_get_server_context(pdata);
571 WINPR_ASSERT(ps->context.update);
572 WINPR_ASSERT(ps->context.update->window);
573 WINPR_ASSERT(ps->context.update->window->WindowDelete);
575 WLog_DBG(TAG,
"called");
576 rdp_update_lock(ps->context.update);
577 const BOOL rc = ps->context.update->window->WindowDelete(&ps->context, orderInfo);
578 rdp_update_unlock(ps->context.update);
583static BOOL pf_client_notify_icon_create(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo,
586 pClientContext* pc = (pClientContext*)context;
589 proxyData* pdata = pc->pdata;
592 pServerContext* ps = proxy_data_get_server_context(pdata);
594 WINPR_ASSERT(ps->context.update);
595 WINPR_ASSERT(ps->context.update->window);
596 WINPR_ASSERT(ps->context.update->window->NotifyIconCreate);
598 WLog_DBG(TAG,
"called");
599 rdp_update_lock(ps->context.update);
601 ps->context.update->window->NotifyIconCreate(&ps->context, orderInfo, notifyIconState);
602 rdp_update_unlock(ps->context.update);
607static BOOL pf_client_notify_icon_update(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo,
610 pClientContext* pc = (pClientContext*)context;
613 proxyData* pdata = pc->pdata;
616 pServerContext* ps = proxy_data_get_server_context(pdata);
618 WINPR_ASSERT(ps->context.update);
619 WINPR_ASSERT(ps->context.update->window);
620 WINPR_ASSERT(ps->context.update->window->NotifyIconUpdate);
622 WLog_DBG(TAG,
"called");
623 rdp_update_lock(ps->context.update);
625 ps->context.update->window->NotifyIconUpdate(&ps->context, orderInfo, notifyIconState);
626 rdp_update_unlock(ps->context.update);
631static BOOL pf_client_notify_icon_delete(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo)
633 pClientContext* pc = (pClientContext*)context;
636 proxyData* pdata = pc->pdata;
639 pServerContext* ps = proxy_data_get_server_context(pdata);
641 WINPR_ASSERT(ps->context.update);
642 WINPR_ASSERT(ps->context.update->window);
643 WINPR_ASSERT(ps->context.update->window->NotifyIconDelete);
645 WLog_DBG(TAG,
"called");
646 rdp_update_lock(ps->context.update);
647 const BOOL rc = ps->context.update->window->NotifyIconDelete(&ps->context, orderInfo);
648 rdp_update_unlock(ps->context.update);
653static BOOL pf_client_monitored_desktop(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo,
656 pClientContext* pc = (pClientContext*)context;
659 proxyData* pdata = pc->pdata;
662 pServerContext* ps = proxy_data_get_server_context(pdata);
664 WINPR_ASSERT(ps->context.update);
665 WINPR_ASSERT(ps->context.update->window);
666 WINPR_ASSERT(ps->context.update->window->MonitoredDesktop);
668 WLog_DBG(TAG,
"called");
669 rdp_update_lock(ps->context.update);
671 ps->context.update->window->MonitoredDesktop(&ps->context, orderInfo, monitoredDesktop);
672 rdp_update_unlock(ps->context.update);
677static BOOL pf_client_non_monitored_desktop(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo)
679 pClientContext* pc = (pClientContext*)context;
682 proxyData* pdata = pc->pdata;
685 pServerContext* ps = proxy_data_get_server_context(pdata);
687 WINPR_ASSERT(ps->context.update);
688 WINPR_ASSERT(ps->context.update->window);
689 WINPR_ASSERT(ps->context.update->window->NonMonitoredDesktop);
691 WLog_DBG(TAG,
"called");
692 rdp_update_lock(ps->context.update);
693 const BOOL rc = ps->context.update->window->NonMonitoredDesktop(&ps->context, orderInfo);
694 rdp_update_unlock(ps->context.update);
698void pf_server_register_update_callbacks(rdpUpdate* update)
700 WINPR_ASSERT(update);
701 update->RefreshRect = pf_server_refresh_rect;
702 update->SuppressOutput = pf_server_suppress_output;
705void pf_client_register_update_callbacks(rdpUpdate* update)
707 WINPR_ASSERT(update);
708 update->BeginPaint = pf_client_begin_paint;
709 update->EndPaint = pf_client_end_paint;
710 update->BitmapUpdate = pf_client_bitmap_update;
711 update->DesktopResize = pf_client_desktop_resize;
712 update->RemoteMonitors = pf_client_remote_monitors;
713 update->SaveSessionInfo = pf_client_save_session_info;
714 update->ServerStatusInfo = pf_client_server_status_info;
715 update->SetKeyboardIndicators = pf_client_set_keyboard_indicators;
716 update->SetKeyboardImeStatus = pf_client_set_keyboard_ime_status;
719 update->SurfaceBits = pf_client_SurfaceBits;
720 update->SurfaceFrameMarker = pf_client_SurfaceFrameMarker;
723 update->window->WindowCreate = pf_client_window_create;
724 update->window->WindowUpdate = pf_client_window_update;
725 update->window->WindowIcon = pf_client_window_icon;
726 update->window->WindowCachedIcon = pf_client_window_cached_icon;
727 update->window->WindowDelete = pf_client_window_delete;
728 update->window->NotifyIconCreate = pf_client_notify_icon_create;
729 update->window->NotifyIconUpdate = pf_client_notify_icon_update;
730 update->window->NotifyIconDelete = pf_client_notify_icon_delete;
731 update->window->MonitoredDesktop = pf_client_monitored_desktop;
732 update->window->NonMonitoredDesktop = pf_client_non_monitored_desktop;
735 update->pointer->PointerSystem = pf_client_send_pointer_system;
736 update->pointer->PointerPosition = pf_client_send_pointer_position;
737 update->pointer->PointerColor = pf_client_send_pointer_color;
738 update->pointer->PointerLarge = pf_client_send_pointer_large;
739 update->pointer->PointerNew = pf_client_send_pointer_new;
740 update->pointer->PointerCached = pf_client_send_pointer_cached;
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_copy_item(rdpSettings *dst, const rdpSettings *src, SSIZE_T id)
copies one setting identified by id from src to dst