23#include <freerdp/config.h>
30#include <winpr/assert.h>
31#include <winpr/synch.h>
32#include <winpr/print.h>
33#include <winpr/thread.h>
34#include <winpr/stream.h>
35#include <winpr/sysinfo.h>
36#include <winpr/cmdline.h>
37#include <winpr/collections.h>
39#include <freerdp/addin.h>
40#include <freerdp/utils/string.h>
41#include <freerdp/client/channels.h>
44#include "../disp_common.h"
50 DispClientContext* context;
51 UINT32 MaxNumMonitors;
52 UINT32 MaxMonitorAreaFactorA;
53 UINT32 MaxMonitorAreaFactorB;
65 const DWORD level = WLOG_DEBUG;
68 WINPR_ASSERT(callback);
69 WINPR_ASSERT(Monitors || (NumMonitors == 0));
71 DISP_PLUGIN* disp = (DISP_PLUGIN*)callback->plugin;
74 const UINT32 MonitorLayoutSize = DISPLAY_CONTROL_MONITOR_LAYOUT_SIZE;
76 .type = DISPLAY_CONTROL_PDU_TYPE_MONITOR_LAYOUT };
78 wStream* s = Stream_New(
nullptr, header.length);
82 WLog_Print(disp->base.log, WLOG_ERROR,
"Stream_New failed!");
83 return CHANNEL_RC_NO_MEMORY;
86 if ((status = disp_write_header(s, &header)))
88 WLog_Print(disp->base.log, WLOG_ERROR,
"Failed to write header with error %" PRIu32
"!",
93 if (NumMonitors > disp->MaxNumMonitors)
94 NumMonitors = disp->MaxNumMonitors;
96 Stream_Write_UINT32(s, MonitorLayoutSize);
97 Stream_Write_UINT32(s, NumMonitors);
98 WLog_Print(disp->base.log, level,
"NumMonitors=%" PRIu32
"", NumMonitors);
100 for (UINT32 index = 0; index < NumMonitors; index++)
103 current.Width -= (current.Width % 2);
105 if (current.Width < 200)
108 if (current.Width > 8192)
109 current.Width = 8192;
111 if (current.Width % 2)
114 if (current.Height < 200)
115 current.Height = 200;
117 if (current.Height > 8192)
118 current.Height = 8192;
120 Stream_Write_UINT32(s, current.Flags);
121 Stream_Write_INT32(s, current.Left);
122 Stream_Write_INT32(s, current.Top);
123 Stream_Write_UINT32(s, current.Width);
124 Stream_Write_UINT32(s, current.Height);
125 Stream_Write_UINT32(s, current.PhysicalWidth);
126 Stream_Write_UINT32(s, current.PhysicalHeight);
127 Stream_Write_UINT32(s, current.Orientation);
128 Stream_Write_UINT32(s, current.DesktopScaleFactor);
129 Stream_Write_UINT32(s, current.DeviceScaleFactor);
130 WLog_Print(disp->base.log, level,
131 "\t%" PRIu32
" : Flags: 0x%08" PRIX32
" Left/Top: (%" PRId32
",%" PRId32
132 ") W/H=%" PRIu32
"x%" PRIu32
")",
133 index, current.Flags, current.Left, current.Top, current.Width, current.Height);
134 WLog_Print(disp->base.log, level,
135 "\t PhysicalWidth: %" PRIu32
" PhysicalHeight: %" PRIu32
136 " Orientation: %s DesktopScaleFactor=%" PRIu32
" DeviceScaleFactor=%" PRIu32
"",
137 current.PhysicalWidth, current.PhysicalHeight,
138 freerdp_desktop_rotation_flags_to_string(current.Orientation),
139 current.DesktopScaleFactor, current.DeviceScaleFactor);
143 Stream_SealLength(s);
144 status = callback->channel->Write(callback->channel, (UINT32)Stream_Length(s), Stream_Buffer(s),
146 Stream_Free(s, TRUE);
157 DISP_PLUGIN* disp =
nullptr;
158 DispClientContext* context =
nullptr;
159 UINT ret = CHANNEL_RC_OK;
161 WINPR_ASSERT(callback);
164 disp = (DISP_PLUGIN*)callback->plugin;
167 context = disp->context;
168 WINPR_ASSERT(context);
170 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
171 return ERROR_INVALID_DATA;
173 Stream_Read_UINT32(s, disp->MaxNumMonitors);
174 Stream_Read_UINT32(s, disp->MaxMonitorAreaFactorA);
175 Stream_Read_UINT32(s, disp->MaxMonitorAreaFactorB);
177 if (context->DisplayControlCaps)
178 ret = context->DisplayControlCaps(context, disp->MaxNumMonitors,
179 disp->MaxMonitorAreaFactorA, disp->MaxMonitorAreaFactorB);
194 WINPR_ASSERT(callback);
197 DISP_PLUGIN* disp = (DISP_PLUGIN*)callback->plugin;
200 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
201 return ERROR_INVALID_DATA;
203 if ((error = disp_read_header(s, &header)))
205 WLog_Print(disp->base.log, WLOG_ERROR,
"disp_read_header failed with error %" PRIu32
"!",
210 if (!Stream_EnsureRemainingCapacity(s, header.length))
212 WLog_Print(disp->base.log, WLOG_ERROR,
"not enough remaining data");
213 return ERROR_INVALID_DATA;
218 case DISPLAY_CONTROL_PDU_TYPE_CAPS:
219 return disp_recv_display_control_caps_pdu(callback, s);
222 WLog_Print(disp->base.log, WLOG_ERROR,
"Type %" PRIu32
" not recognized!", header.type);
223 return ERROR_INTERNAL_ERROR;
232static UINT disp_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
wStream* data)
235 return disp_recv_pdu(callback, data);
243static UINT disp_on_close(IWTSVirtualChannelCallback* pChannelCallback)
245 free(pChannelCallback);
246 return CHANNEL_RC_OK;
258static UINT disp_send_monitor_layout(DispClientContext* context, UINT32 NumMonitors,
261 DISP_PLUGIN* disp =
nullptr;
264 WINPR_ASSERT(context);
266 disp = (DISP_PLUGIN*)context->handle;
269 callback = disp->base.listener_callback->channel_callback;
271 return disp_send_display_control_monitor_layout_pdu(callback, NumMonitors, Monitors);
280 WINPR_ATTR_UNUSED rdpContext* rcontext,
281 WINPR_ATTR_UNUSED rdpSettings* settings)
283 DispClientContext* context =
nullptr;
284 DISP_PLUGIN* disp = (DISP_PLUGIN*)base;
287 disp->MaxNumMonitors = 16;
288 disp->MaxMonitorAreaFactorA = 8192;
289 disp->MaxMonitorAreaFactorB = 8192;
291 context = (DispClientContext*)calloc(1,
sizeof(DispClientContext));
294 WLog_Print(base->log, WLOG_ERROR,
"unable to allocate DispClientContext");
295 return CHANNEL_RC_NO_MEMORY;
298 context->handle = (
void*)disp;
299 context->SendMonitorLayout = disp_send_monitor_layout;
301 disp->base.iface.pInterface = disp->context = context;
303 return CHANNEL_RC_OK;
308 DISP_PLUGIN* disp = (DISP_PLUGIN*)base;
315static const IWTSVirtualChannelCallback disp_callbacks = { disp_on_data_received,
317 disp_on_close,
nullptr };
324FREERDP_ENTRY_POINT(UINT VCAPITYPE disp_DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints))
326 return freerdp_generic_DVCPluginEntry(pEntryPoints, TAG, DISP_DVC_CHANNEL_NAME,
328 &disp_callbacks, disp_plugin_initialize,
329 disp_plugin_terminated);