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/client/channels.h> 
   43#include "../disp_common.h" 
   49  DispClientContext* context;
 
   50  UINT32 MaxNumMonitors;
 
   51  UINT32 MaxMonitorAreaFactorA;
 
   52  UINT32 MaxMonitorAreaFactorB;
 
   66  DISP_PLUGIN* disp = NULL;
 
   67  UINT32 MonitorLayoutSize = 0;
 
   70  WINPR_ASSERT(callback);
 
   71  WINPR_ASSERT(Monitors || (NumMonitors == 0));
 
   73  disp = (DISP_PLUGIN*)callback->plugin;
 
   76  MonitorLayoutSize = DISPLAY_CONTROL_MONITOR_LAYOUT_SIZE;
 
   77  header.length = 8 + 8 + (NumMonitors * MonitorLayoutSize);
 
   78  header.type = DISPLAY_CONTROL_PDU_TYPE_MONITOR_LAYOUT;
 
   80  s = Stream_New(NULL, header.length);
 
   84    WLog_ERR(TAG, 
"Stream_New failed!");
 
   85    return CHANNEL_RC_NO_MEMORY;
 
   88  if ((status = disp_write_header(s, &header)))
 
   90    WLog_ERR(TAG, 
"Failed to write header with error %" PRIu32 
"!", status);
 
   94  if (NumMonitors > disp->MaxNumMonitors)
 
   95    NumMonitors = disp->MaxNumMonitors;
 
   97  Stream_Write_UINT32(s, MonitorLayoutSize); 
 
   98  Stream_Write_UINT32(s, NumMonitors);       
 
   99  WLog_DBG(TAG, 
"NumMonitors=%" PRIu32 
"", NumMonitors);
 
  101  for (UINT32 index = 0; index < NumMonitors; index++)
 
  104    current.Width -= (current.Width % 2);
 
  106    if (current.Width < 200)
 
  109    if (current.Width > 8192)
 
  110      current.Width = 8192;
 
  112    if (current.Width % 2)
 
  115    if (current.Height < 200)
 
  116      current.Height = 200;
 
  118    if (current.Height > 8192)
 
  119      current.Height = 8192;
 
  121    Stream_Write_UINT32(s, current.Flags);              
 
  122    Stream_Write_INT32(s, current.Left);                
 
  123    Stream_Write_INT32(s, current.Top);                 
 
  124    Stream_Write_UINT32(s, current.Width);              
 
  125    Stream_Write_UINT32(s, current.Height);             
 
  126    Stream_Write_UINT32(s, current.PhysicalWidth);      
 
  127    Stream_Write_UINT32(s, current.PhysicalHeight);     
 
  128    Stream_Write_UINT32(s, current.Orientation);        
 
  129    Stream_Write_UINT32(s, current.DesktopScaleFactor); 
 
  130    Stream_Write_UINT32(s, current.DeviceScaleFactor);  
 
  132             "\t%" PRIu32 
" : Flags: 0x%08" PRIX32 
" Left/Top: (%" PRId32 
",%" PRId32
 
  133             ") W/H=%" PRIu32 
"x%" PRIu32 
")",
 
  134             index, current.Flags, current.Left, current.Top, current.Width, current.Height);
 
  136             "\t   PhysicalWidth: %" PRIu32 
" PhysicalHeight: %" PRIu32 
" Orientation: %" PRIu32
 
  138             current.PhysicalWidth, current.PhysicalHeight, current.Orientation);
 
  142  Stream_SealLength(s);
 
  143  status = callback->channel->Write(callback->channel, (UINT32)Stream_Length(s), Stream_Buffer(s),
 
  145  Stream_Free(s, TRUE);
 
  156  DISP_PLUGIN* disp = NULL;
 
  157  DispClientContext* context = NULL;
 
  158  UINT ret = CHANNEL_RC_OK;
 
  160  WINPR_ASSERT(callback);
 
  163  disp = (DISP_PLUGIN*)callback->plugin;
 
  166  context = disp->context;
 
  167  WINPR_ASSERT(context);
 
  169  if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
 
  170    return ERROR_INVALID_DATA;
 
  172  Stream_Read_UINT32(s, disp->MaxNumMonitors);        
 
  173  Stream_Read_UINT32(s, disp->MaxMonitorAreaFactorA); 
 
  174  Stream_Read_UINT32(s, disp->MaxMonitorAreaFactorB); 
 
  176  if (context->DisplayControlCaps)
 
  177    ret = context->DisplayControlCaps(context, disp->MaxNumMonitors,
 
  178                                      disp->MaxMonitorAreaFactorA, disp->MaxMonitorAreaFactorB);
 
  193  WINPR_ASSERT(callback);
 
  196  if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
 
  197    return ERROR_INVALID_DATA;
 
  199  if ((error = disp_read_header(s, &header)))
 
  201    WLog_ERR(TAG, 
"disp_read_header failed with error %" PRIu32 
"!", error);
 
  205  if (!Stream_EnsureRemainingCapacity(s, header.length))
 
  207    WLog_ERR(TAG, 
"not enough remaining data");
 
  208    return ERROR_INVALID_DATA;
 
  213    case DISPLAY_CONTROL_PDU_TYPE_CAPS:
 
  214      return disp_recv_display_control_caps_pdu(callback, s);
 
  217      WLog_ERR(TAG, 
"Type %" PRIu32 
" not recognized!", header.type);
 
  218      return ERROR_INTERNAL_ERROR;
 
  227static UINT disp_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, 
wStream* data)
 
  230  return disp_recv_pdu(callback, data);
 
  238static UINT disp_on_close(IWTSVirtualChannelCallback* pChannelCallback)
 
  240  free(pChannelCallback);
 
  241  return CHANNEL_RC_OK;
 
  253static UINT disp_send_monitor_layout(DispClientContext* context, UINT32 NumMonitors,
 
  256  DISP_PLUGIN* disp = NULL;
 
  259  WINPR_ASSERT(context);
 
  261  disp = (DISP_PLUGIN*)context->handle;
 
  264  callback = disp->base.listener_callback->channel_callback;
 
  266  return disp_send_display_control_monitor_layout_pdu(callback, NumMonitors, Monitors);
 
  275                                   WINPR_ATTR_UNUSED rdpContext* rcontext,
 
  276                                   WINPR_ATTR_UNUSED rdpSettings* settings)
 
  278  DispClientContext* context = NULL;
 
  279  DISP_PLUGIN* disp = (DISP_PLUGIN*)base;
 
  282  disp->MaxNumMonitors = 16;
 
  283  disp->MaxMonitorAreaFactorA = 8192;
 
  284  disp->MaxMonitorAreaFactorB = 8192;
 
  286  context = (DispClientContext*)calloc(1, 
sizeof(DispClientContext));
 
  289    WLog_Print(base->log, WLOG_ERROR, 
"unable to allocate DispClientContext");
 
  290    return CHANNEL_RC_NO_MEMORY;
 
  293  context->handle = (
void*)disp;
 
  294  context->SendMonitorLayout = disp_send_monitor_layout;
 
  296  disp->base.iface.pInterface = disp->context = context;
 
  298  return CHANNEL_RC_OK;
 
  303  DISP_PLUGIN* disp = (DISP_PLUGIN*)base;
 
  310static const IWTSVirtualChannelCallback disp_callbacks = { disp_on_data_received, NULL, 
 
  311                                                         disp_on_close, NULL };
 
  318FREERDP_ENTRY_POINT(UINT VCAPITYPE disp_DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints))
 
  320  return freerdp_generic_DVCPluginEntry(pEntryPoints, TAG, DISP_DVC_CHANNEL_NAME,
 
  322                                        &disp_callbacks, disp_plugin_initialize,
 
  323                                        disp_plugin_terminated);