/*****************************************************************************/ staticvoid
init_libh264_loaded(struct xrdp_mm *self)
{ #ifdefined(XRDP_OPENH264) // Note that if this fails, and x264 is also configured, x264 // will not be considered as a fallback.
self->libh264_loaded = xrdp_encoder_openh264_install_ok(); if (!self->libh264_loaded)
{
LOG(LOG_LEVEL_ERROR, "OpenH264 Codec is not installed correctly. " "H.264 will not be used");
} #elifdefined (XRDP_H264)
self->libh264_loaded = 1; #else
self->libh264_loaded = 0; #endif
}
self->uid = -1; /* Never good to default UIDs to 0 */
// Resize queue support. The resize queue is available early on, // but isn't processed until start_processing_resize_queue() is // called.
self->resize_queue = list_create();
self->resize_queue->auto_free = 1;
self->resize_data = NULL;
self->resize_ready = NULL_WAIT_OBJ;
/*****************************************************************************/ /* called from main thread */ staticlong
xrdp_mm_sync_unload(long param1, long param2)
{ return g_free_library(param1);
}
/*****************************************************************************/ /* called from main thread */ staticlong
xrdp_mm_sync_load(long param1, long param2)
{ long rv; char *libname;
if (self->wm->hide_log_window)
{ /* make sure autologin is off */
self->wm->session->client_info->rdp_autologin = 0;
xrdp_wm_set_login_state(self->wm, WMLS_RESET); /* reset session */
}
/**************************************************************************//**
* Looks for a string value in the login_names/login_values array
*
* In the event of multiple matches, the LAST value matched is returned.
* This currently allows for values to be replaced by writing a new value
* to the end of the list
*
* Returned strings are valid until the module is destroyed.
*
* @param self This module
* @param aname Name to lookup (case-insensitive)
*
* @return pointer to value, or NULL ifnot found.
*/ staticconstchar *
xrdp_mm_get_value(struct xrdp_mm *self, constchar *aname)
{ constchar *name; constchar *value = NULL; unsignedint index = self->login_names->count;
while (index > 0 && value == NULL)
{
--index;
name = (constchar *)list_get_item(self->login_names, index);
if (name != NULL && g_strcasecmp(name, aname) == 0)
{
value = (constchar *)list_get_item(self->login_values, index);
}
}
return value;
} /**************************************************************************//**
* Looks for a numeric value in the login_names/login_values array
*
* Returned strings are valid until the module is destroyed.
*
* @param self This module
* @param aname Name to lookup (case-insensitive)
* @param def Default to returnif value not found.
*
* @return value from name, or the specified default.
*/ staticint
xrdp_mm_get_value_int(struct xrdp_mm *self, constchar *aname, int def)
{ constchar *value = xrdp_mm_get_value(self, aname);
return (value == NULL) ? def : g_atoi(value);
}
/*****************************************************************************/ /* Send gateway login information to sesman */ staticint
xrdp_mm_send_sys_login_request(struct xrdp_mm *self, constchar *username, constchar *password)
{
xrdp_wm_log_msg(self->wm, LOG_LEVEL_DEBUG, "sending login info to session manager, please wait...");
if ((lib = xrdp_mm_get_value(self, "lib")) == NULL)
{
xrdp_wm_log_msg(self->wm, LOG_LEVEL_ERROR, "no library name specified in xrdp.ini, please add " "lib=libxrdp-vnc.so or similar");
return1;
}
if (lib[0] == 0)
{
xrdp_wm_log_msg(self->wm, LOG_LEVEL_ERROR, "empty library name specified in xrdp.ini, please " "add lib=libxrdp-vnc.so or similar");
return1;
}
if (self->mod_handle == 0)
{
g_snprintf(text, sizeof(text), "%s/%s", XRDP_MODULE_PATH, lib); /* Let the main thread load the lib,*/
self->mod_handle = g_xrdp_sync(xrdp_mm_sync_load, (tintptr)text, 0);
if (self->mod_handle != 0)
{
func = g_get_proc_address(self->mod_handle, "mod_init");
if (func == 0)
{
func = g_get_proc_address(self->mod_handle, "_mod_init");
}
if (func == 0)
{
xrdp_wm_log_msg(self->wm, LOG_LEVEL_ERROR, "error finding proc mod_init in %s, " "not a valid xrdp backend", lib);
}
/* id self->mod is null, there must be a problem */ if (self->mod == 0)
{
LOG(LOG_LEVEL_ERROR, "problem loading lib in xrdp_mm_setup_mod1"); return1;
}
return0;
}
/*****************************************************************************/ staticint
xrdp_mm_setup_mod2(struct xrdp_mm *self)
{ char text[256]; constchar *name; constchar *value; int i; int rv; int key_flags; int device_flags;
if (!g_is_wait_obj_set(self->wm->pro_layer->self_term_event))
{ /* this adds the port to the end of the list, it will already be in thelistas-1
the module should use the last one */ if (g_strlen(text) > 0)
{
list_add_strdup(self->login_names, "port");
list_add_strdup(self->login_values, text);
}
for (i = 0; i < self->login_names->count; i++)
{
name = (constchar *) list_get_item(self->login_names, i);
value = (constchar *) list_get_item(self->login_values, i);
self->mod->mod_set_param(self->mod, name, value);
}
if (self->mod != 0)
{ if (self->mod->mod_event != 0)
{
self->mod->mod_event(self->mod, WM_KEYBRD_SYNC, key_flags,
device_flags, key_flags, device_flags);
}
}
}
return rv;
}
/*****************************************************************************/ /* returns error
send a list of channels to the channel handler */ staticint
xrdp_mm_trans_send_channel_setup(struct xrdp_mm *self, struct trans *trans)
{ int chan_count; /* This value should be the same as chan_count, but we need to
* cater for a possible failure of libxrdp_query_channel() */ int output_chan_count; int chan_id; int chan_flags; int size; struct stream *s; char chan_name[CHANNEL_NAME_LEN + 1];
/*****************************************************************************/ /* returns error
data coming in from the channel handler, send it to the client */ staticint
xrdp_mm_trans_process_channel_data(struct xrdp_mm *self, struct stream *s)
{ unsignedint size; unsignedint total_size; int chan_id; int chan_flags; int rv = 0;
/*****************************************************************************/ /* returns error
process rail create window order */ staticint
xrdp_mm_process_rail_create_window(struct xrdp_mm *self, struct stream *s)
{ int flags; int window_id; int title_bytes; int index; int bytes; int rv; struct rail_window_state_order rwso;
#if0 /*****************************************************************************/ /* returns error
process rail configure window order */ staticint
xrdp_mm_process_rail_configure_window(struct xrdp_mm *self, struct stream *s)
{ int flags; int window_id; int index; int bytes; int rv; struct rail_window_state_order rwso;
/*****************************************************************************/ /* returns error
process rail update window (title) order */ staticint
xrdp_mm_process_rail_update_window_text(struct xrdp_mm *self, struct stream *s)
{ int size; int flags; int rv; int window_id; struct rail_window_state_order rwso;
/******************************************************************************/ int
xrdp_mm_egfx_send_planar_bitmap(struct xrdp_mm *self, struct xrdp_bitmap *bitmap, struct xrdp_rect *rect, int surface_id, int x, int y)
{ struct xrdp_egfx_rect gfx_rect; struct stream *comp_s; struct stream *temp_s; char *pixels; char *src8; char *dst8; int index; int lines; int comp_bytes; int xindex; int yindex; int bwidth; int bheight; int cx; int cy; int rv = 0;
// Only invalidate the WM screen if the module is using the WM screen, // or we haven't loaded the module yet. // // Otherwise we may send client updates which conflict with the // updates sent directly from the module via the encoder. if (self->mod_uses_wm_screen_for_gfx || self->mod_handle == 0)
{ struct xrdp_bitmap *screen = self->wm->screen; struct xrdp_rect xr_rect;
/******************************************************************************/ staticint
xrdp_mm_egfx_create_surfaces(struct xrdp_mm *self)
{ int surface_id; int index; int count; int left; int top; int width; int height; struct monitor_info *mi; struct xrdp_bitmap *screen;
/******************************************************************************/ staticint
xrdp_mm_egfx_caps_advertise(void *user, int caps_count, int *versions, int *flagss)
{ struct xrdp_mm *self; struct xrdp_bitmap *screen; int index; int best_h264_index; int best_pro_index; int error; int version; int flags; struct ver_flags_t *ver_flags;
encoder = self->encoder; if (encoder == NULL)
{ // Can't pass the ack to the encoder. Tell the module all // frames are ACK'd if (self->mod != NULL)
{
self->mod->mod_frame_ack(self->mod, 0, INT_MAX);
}
} else
{ int fif = encoder->frames_in_flight; if (encoder->frame_id_client + fif > encoder->frame_id_server)
{ if (encoder->frame_id_server > encoder->frame_id_server_sent)
{
LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_mm_update_module_ack: " "frame_id_server %d", encoder->frame_id_server);
encoder->frame_id_server_sent = encoder->frame_id_server; if (self->mod != NULL)
{
self->mod->mod_frame_ack(self->mod, 0,
encoder->frame_id_server);
}
}
}
} return0;
}
staticint
xrdp_mm_egfx_frame_ack(void *user, uint32_t queue_depth, int frame_id, int frames_decoded)
{ struct xrdp_mm *self; struct xrdp_encoder *encoder;
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_mm_egfx_frame_ack:");
self = (struct xrdp_mm *) user;
encoder = self->encoder; if (encoder == NULL)
{
LOG(LOG_LEVEL_INFO, "xrdp_mm_egfx_frame_ack: encoder is nil"); return0;
} if (queue_depth == XR_SUSPEND_FRAME_ACKNOWLEDGEMENT)
{
LOG(LOG_LEVEL_INFO, "xrdp_mm_egfx_frame_ack: " "queue_depth %d frame_id %d frames_decoded %d",
queue_depth, frame_id, frames_decoded); if (encoder->gfx_ack_off == 0)
{
LOG(LOG_LEVEL_INFO, "xrdp_mm_egfx_frame_ack: " "client request turn off frame acks.");
encoder->gfx_ack_off = 1;
frame_id = -1;
}
} else
{ if (encoder->gfx_ack_off)
{
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_mm_egfx_frame_ack: " "client request turn on frame acks");
encoder->gfx_ack_off = 0;
}
}
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_mm_egfx_frame_ack: " "incoming %d, client %d, server %d",
frame_id, encoder->frame_id_client, encoder->frame_id_server); if (frame_id < 0 || frame_id > encoder->frame_id_server)
{ /* if frame_id is negative or bigger then what server last sent
just ack all sent frames */ /* some clients can send big number just to clear all
pending frames */
encoder->frame_id_client = encoder->frame_id_server;
} else
{ /* frame acks can come out of order so ignore older one */
encoder->frame_id_client = MAX(frame_id, encoder->frame_id_client);
}
xrdp_mm_update_module_frame_ack(self); return0;
}
// See if there's already a previous item on the queue if (self->resize_queue->count > 0)
{ int prev_num = self->resize_queue->count - 1; struct resize_queue_item *prev;
prev = (struct resize_queue_item *)
list_get_item(self->resize_queue, prev_num); // If this is a RQ_FROM_CLIENT, and the previous item on the // resize_queue is also RQ_FROM_CLIENT, and it hasn't yet been // processed, we can simply ignore it if (src == RQ_FROM_CLIENT && prev->src == RQ_FROM_CLIENT)
{
LOG_DEVEL(LOG_LEVEL_DEBUG, "dynamic_monitor_data: Removing unactioned resize request" " width %d, height %d.",
prev->description.session_width,
prev->description.session_height);
list_remove_item(self->resize_queue, prev_num);
}
} if (!list_add_item(self->resize_queue, (tintptr)resize_queue_item))
{
free(resize_queue_item);
rv = 1;
} else
{ // This call only has an effect if the wait_obj is not // NULL_WAIT_OBJ
g_set_wait_obj(self->resize_ready);
}
}
return rv;
}
/******************************************************************************/ staticint
dynamic_monitor_data(intptr_t id, int chan_id, char *data, int bytes)
{ int error = 0; struct stream ls; struct stream *s; int msg_type; int msg_length; struct xrdp_process *pro; struct xrdp_wm *wm; int monitor_layout_size; struct display_size_description description;
if (invalid_dimensions)
{
LOG(LOG_LEVEL_DEBUG, "dynamic_monitor_process_queue: Not allowing" " resize due to invalid dimensions (w: %d x h: %d)",
queued_size->session_width,
queued_size->session_height);
}
if (already_this_size)
{
LOG(LOG_LEVEL_DEBUG, "dynamic_monitor_process_queue: Not resizing." " Already this size. (w: %d x h: %d)",
queued_size->session_width,
queued_size->session_height);
}
if (self->resize_data->state == WMRZ_COMPLETE)
{
LOG(LOG_LEVEL_INFO, "dynamic_monitor_process_queue: Clearing" " completed resize (w: %d x h: %d). It took %d milliseconds.",
self->resize_data->description.session_width,
self->resize_data->description.session_height,
g_time3() - self->resize_data->start_time);
g_set_wait_obj(self->resize_ready);
} elseif (self->resize_data->state == WMRZ_ERROR)
{
LOG(LOG_LEVEL_INFO, "dynamic_monitor_process_queue: Clearing" " failed request to resize to: (w: %d x h: %d)",
self->resize_data->description.session_width,
self->resize_data->description.session_height);
g_set_wait_obj(self->resize_ready);
} else
{ // No errors, process it! return process_display_control_monitor_layout_data(self->wm);
}
g_free(self->resize_data);
self->resize_data = NULL; return0;
}
/******************************************************************************/ int
dynamic_monitor_initialize(struct xrdp_mm *self)
{ struct xrdp_drdynvc_procs d_procs; int flags; int error;
/*****************************************************************************/ /* open response from client going to channel server */ staticint
xrdp_mm_drdynvc_open_response(intptr_t id, int chan_id, int creation_status)
{ struct trans *trans; struct stream *s; struct xrdp_wm *wm; struct xrdp_process *pro; int chansrv_chan_id;
LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_mm_drdynvc_open_response: " " chan_id %d creation_status %d",
chan_id, creation_status);
pro = (struct xrdp_process *) id;
wm = pro->wm;
trans = wm->mm->chan_trans;
s = trans_get_out_s(trans, 8192); if (s == NULL)
{ return1;
}
out_uint32_le(s, 0); /* version */
out_uint32_le(s, 24); /* size */
out_uint32_le(s, 13); /* msg id */
out_uint32_le(s, 16); /* size */
chansrv_chan_id = wm->mm->xr2cr_cid_map[chan_id];
out_uint32_le(s, chansrv_chan_id);
out_uint32_le(s, creation_status); /* status */
s_mark_end(s); return trans_write_copy(trans);
}
/*****************************************************************************/ /* close response from client going to channel server */ staticint
xrdp_mm_drdynvc_close_response(intptr_t id, int chan_id)
{ struct trans *trans; struct stream *s; struct xrdp_wm *wm; struct xrdp_process *pro; int chansrv_chan_id;
pro = (struct xrdp_process *) id;
wm = pro->wm;
trans = wm->mm->chan_trans;
s = trans_get_out_s(trans, 8192); if (s == NULL)
{ return1;
}
out_uint32_le(s, 0); /* version */
out_uint32_le(s, 20); /* size */
out_uint32_le(s, 15); /* msg id */
out_uint32_le(s, 12); /* size */
chansrv_chan_id = wm->mm->xr2cr_cid_map[chan_id];
out_uint32_le(s, chansrv_chan_id);
s_mark_end(s); return trans_write_copy(trans);
}
/*****************************************************************************/ /* part data from client going to channel server */ staticint
xrdp_mm_drdynvc_data_first(intptr_t id, int chan_id, char *data, int bytes, int total_bytes)
{ struct trans *trans; struct stream *s; struct xrdp_wm *wm; struct xrdp_process *pro; int chansrv_chan_id;
pro = (struct xrdp_process *) id;
wm = pro->wm; // Size of PDU sent to chansrv int pdu_size = 8 + 8 + 4 + 4 + 4 + bytes;
trans = wm->mm->chan_trans;
s = trans_get_out_s(trans, pdu_size); if (s == NULL)
{ return1;
}
out_uint32_le(s, 0); /* version */
out_uint32_le(s, pdu_size);
out_uint32_le(s, 17); /* msg id */
out_uint32_le(s, pdu_size - 8);
chansrv_chan_id = wm->mm->xr2cr_cid_map[chan_id];
out_uint32_le(s, chansrv_chan_id);
out_uint32_le(s, bytes);
out_uint32_le(s, total_bytes);
out_uint8a(s, data, bytes);
s_mark_end(s); return trans_write_copy(trans);
}
/*****************************************************************************/ /* data from client going to channel server */ staticint
xrdp_mm_drdynvc_data(intptr_t id, int chan_id, char *data, int bytes)
{ struct trans *trans; struct stream *s; struct xrdp_wm *wm; struct xrdp_process *pro; int chansrv_chan_id;
pro = (struct xrdp_process *) id;
wm = pro->wm; // Size of PDU sent to chansrv int pdu_size = 8 + 8 + 4 + 4 + bytes;
trans = wm->mm->chan_trans;
s = trans_get_out_s(trans, pdu_size); if (s == NULL)
{ return1;
}
out_uint32_le(s, 0); /* version */
out_uint32_le(s, pdu_size);
out_uint32_le(s, 19); /* msg id */
out_uint32_le(s, pdu_size - 8);
chansrv_chan_id = wm->mm->xr2cr_cid_map[chan_id];
out_uint32_le(s, chansrv_chan_id);
out_uint32_le(s, bytes);
out_uint8a(s, data, bytes);
s_mark_end(s); return trans_write_copy(trans);
}
/*****************************************************************************/ /* open message from channel server going to client */ staticint
xrdp_mm_trans_process_drdynvc_channel_open(struct xrdp_mm *self, struct stream *s)
{ int name_bytes; int flags; int error; int chan_id; int chansrv_chan_id; char name[1024 + 1]; struct xrdp_drdynvc_procs procs;
if (!s_check_rem(s, 4))
{ return1;
}
in_uint32_le(s, name_bytes); if ((name_bytes < 1) || (name_bytes > (int)(sizeof(name) - 1)))
{ return1;
} if (!s_check_rem(s, name_bytes))
{ return1;
}
in_uint8a(s, name, name_bytes);
name[name_bytes] = 0; if (!s_check_rem(s, 8))
{ return1;
}
in_uint32_le(s, flags);
in_uint32_le(s, chansrv_chan_id); if (chansrv_chan_id < 0 || chansrv_chan_id > 255)
{
LOG(LOG_LEVEL_ERROR, "Attempting to open invalid chansrv channel %d",
chansrv_chan_id); return1;
}
/*****************************************************************************/ /* close message from channel server going to client */ staticint
xrdp_mm_trans_process_drdynvc_channel_close(struct xrdp_mm *self, struct stream *s)
{ int chansrv_chan_id; int chan_id; int error;
if (!s_check_rem(s, 4))
{ return1;
}
in_uint32_le(s, chansrv_chan_id); if (chansrv_chan_id < 0 || chansrv_chan_id > 255)
{
LOG(LOG_LEVEL_ERROR, "Attempting to close invalid chansrv channel %d",
chansrv_chan_id); return1;
}
chan_id = self->cs2xr_cid_map[chansrv_chan_id]; /* close dynamic channel */
error = libxrdp_drdynvc_close(self->wm->session, chan_id); if (error != 0)
{ return1;
} return0;
}
/*****************************************************************************/ /* data from channel server going to client */ staticint
xrdp_mm_trans_process_drdynvc_data_first(struct xrdp_mm *self, struct stream *s)
{ int chansrv_chan_id; int chan_id; int error; int data_bytes; int total_bytes; char *data;
/*****************************************************************************/ /* data from channel server going to client */ staticint
xrdp_mm_trans_process_drdynvc_data(struct xrdp_mm *self, struct stream *s)
{ int chansrv_chan_id; int chan_id; int error; int data_bytes; char *data;
/*****************************************************************************/ /* returns error
process a message for the channel handler */ staticint
xrdp_mm_chan_process_msg(struct xrdp_mm *self, struct trans *trans, struct stream *s)
{ int rv; int id; int size; char *next_msg; char *s_end;
/*****************************************************************************/ /* this is callback from trans obj
returns error */ staticint
xrdp_mm_chan_data_in(struct trans *trans)
{ struct xrdp_mm *self; struct stream *s; int size; int error;
if (trans == NULL)
{ return1;
}
self = (struct xrdp_mm *)(trans->callback_data);
s = trans_get_in_s(trans);
if (s == 0)
{ return1;
}
if (trans->extra_flags == 0)
{
in_uint8s(s, 4); /* id */
in_uint32_le(s, size);
LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_mm_chan_data_in: got header, size %d", size); if (size > 8)
{
self->chan_trans->header_size = size;
trans->extra_flags = 1; return0;
}
} /* here, the entire message block is read in, process it */
error = xrdp_mm_chan_process_msg(self, trans, s);
self->chan_trans->header_size = 8;
trans->extra_flags = 0;
init_stream(s, 0);
LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_mm_chan_data_in: got whole message, reset for " "next header"); return error;
}
/*****************************************************************************/ /* does the section in xrdp.ini has any channel.*=true | false */ staticint
xrdp_mm_update_allowed_channels(struct xrdp_mm *self)
{ int index; int count; int chan_id; int disabled; constchar *name; constchar *value; constchar *chan_name; struct xrdp_session *session;
session = self->wm->session;
count = self->login_names->count; for (index = 0; index < count; index++)
{
name = (constchar *) list_get_item(self->login_names, index); if (g_strncasecmp(name, "channel.", 8) == 0)
{
value = (constchar *) list_get_item(self->login_values, index);
chan_name = name + 8;
chan_id = libxrdp_get_channel_id(session, chan_name);
disabled = !g_text2bool(value);
libxrdp_disable_channel(session, chan_id, disabled); if (disabled)
{
LOG(LOG_LEVEL_INFO, "xrdp_mm_update_allowed_channels: channel %s " "channel id %d is disabled", chan_name, chan_id);
} else
{
LOG(LOG_LEVEL_INFO, "xrdp_mm_update_allowed_channels: channel %s " "channel id %d is allowed", chan_name, chan_id);
}
}
} return0;
}
/*****************************************************************************/ staticint
xrdp_mm_get_sesman_port(char *port, int port_bytes)
{ int fd; int error; int index; char *val; char cfg_file[256]; struct list *names; struct list *values;
g_memset(cfg_file, 0, sizeof(char) * 256); /* default to port 3350 */
g_strncpy(port, "3350", port_bytes - 1); /* see if port is in sesman.ini file */
g_snprintf(cfg_file, 255, "%s/sesman.ini", XRDP_CFG_PATH);
fd = g_file_open_ro(cfg_file);
/*****************************************************************************/ /* returns error
data coming from client that need to go to channel handler */ int
xrdp_mm_process_channel_data(struct xrdp_mm *self, tbus param1, tbus param2,
tbus param3, tbus param4)
{ int rv = 0;
if ((self->chan_trans != 0) && self->chan_trans->status == TRANS_STATUS_UP)
{ int id = LOWORD(param1); int flags = HIWORD(param1); int length = param2; constchar *data = (constchar *)param3; int total_length = param4;
if (self->wm->client_info->require_credentials)
{ /* Credentials had to be specified, but were invalid */
g_set_wait_obj(self->wm->pro_layer->self_term_event);
LOG(LOG_LEVEL_ERROR, "require_credentials is set, " "but the user could not be logged in");
}
if (server_closed)
{ if (login_result == E_SCP_LOGIN_NOT_AUTHENTICATED)
{
xrdp_wm_log_msg(self->wm, LOG_LEVEL_INFO, "%s", "Login retry limit reached");
}
xrdp_wm_log_msg(self->wm, LOG_LEVEL_INFO, "%s", "Close the log window to exit.");
self->wm->fatal_error_in_log_window = 1; /* Transport can be deleted now */
self->delete_sesman_trans = 1;
} /* If the server hasn't closed, inform the window manager *ofthefail,butleavethesesmanconnectionopenfor
* further login attempts */
xrdp_wm_mod_connect_done(self->wm, 1);
} else
{ /* login successful */
xrdp_mm_connect_sm(self);
}
}
/* Sort out some logging information */ if ((username = xrdp_mm_get_value(self, "username")) == NULL)
{
username = "???";
}
if (status == E_SCP_SCREATE_OK)
{
xrdp_wm_log_msg(self->wm, LOG_LEVEL_INFO, "session is available on display %d for user %s",
display, username);
/* Carry on with the connect state machine */
self->display = display;
self->guid = guid;
xrdp_mm_connect_sm(self);
} else
{ char buff[128];
scp_screate_status_to_str(status, buff, sizeof(buff));
xrdp_wm_log_msg(self->wm, LOG_LEVEL_INFO, "Can't create session for user %s - %s",
username, buff); /* Leave the sesman connection open for further login attenpts */
xrdp_wm_mod_connect_done(self->wm, 1);
}
}
return rv;
}
/*****************************************************************************/ /* This is the callback registered for sesman communication replies. */ staticint
xrdp_mm_scp_data_in(struct trans *trans)
{ int rv = 0; int available;
/*****************************************************************************/ /* This routine clears all states to make sure that our next login will be *asexpected.Iftheuserdoesnotpressokonthelogwindowandtryto *connectagainwemustmakesurethatnopreviousinformationisstored. * *Thisroutinedoesnotclearasesman_transifitisallocated,asthis
* would break the password retry limit mechanism */ staticvoid
cleanup_states(struct xrdp_mm *self)
{ if (self != NULL)
{
self->connect_state = MMCS_CONNECT_TO_SESMAN;
self->use_sesman = 0; /* true if this is a sesman session */
self->use_chansrv = 0; /* true if chansrvport is set in xrdp.ini or using sesman */
self->use_gw_login = 0; /* true if we're to use the gateway login facility */ //self->sesman_trans = NULL; /* connection to sesman */
self->chan_trans = NULL; /* connection to chansrv */
self->delete_sesman_trans = 0;
self->display = 0; /* 10 for :10.0, 11 for :11.0, etc */
guid_clear(&self->guid);
self->code = 0; /* ???_SESSION_CODE value */
}
}
/*************************************************************************//**
* Parses a chansrvport string
*
* This will be in one of the following formats:-
* <path> UNIX path to a domain socket
* DISPLAY(<num>) Use chansrv on X Display <num>
*
* @param value assigned to chansrvport
* @param dest Output buffer
* @param dest_size Total size of output buffer, including terminator space
* @param uid of destination
*
* Pass in dest of NULL, dest_size of 0and uid of -1 to simply see if
* the string parses OK.
*
* @return0for success
*/
staticint
parse_chansrvport(constchar *value, char *dest, int dest_size, int uid)
{ int rv = 0; int dnum = 0;
/* make sure we start in correct state */
cleanup_states(self);
/* *StandardVNCsessionscannotbesupportedinFIPSmode,so
* don't default to this session type */ if ((p = xrdp_mm_get_value(self, "code")) != NULL)
{
self->code = g_atoi(p);
} elseif (g_fips_mode_enabled())
{
LOG(LOG_LEVEL_INFO, "FIPS: defaulting to a VNC session over UDS");
self->code = XVNC_UDS_SESSION_CODE;
} else
{
LOG(LOG_LEVEL_INFO, "non-FIPS: defaulting to a VNC session over TCP");
self->code = XVNC_SESSION_CODE;
}
/* Look at our module parameters to decide if we need to connect
* to sesman or not */
if (port != NULL && g_strcmp(port, "-1") == 0)
{
self->use_sesman = 1; /* Connecting to a remote sesman is no longer supported. For purely *localsessiontypes,thissettingcouldberemoved. *The'ip'valueisstillusedfornon-UDSXvncsessions,tofind
* the TCP address that the X server is listening on */ if (xrdp_mm_get_value(self, "ip") != NULL)
{ if (self->code != XVNC_SESSION_CODE)
{
xrdp_wm_log_msg(self->wm,
LOG_LEVEL_WARNING, "'ip' is not needed for this connection" " - please remove");
}
}
}
if (gw_username != NULL)
{ /* Connecting to a remote sesman is no longer supported */ if (xrdp_mm_get_value(self, "pamsessionmng") != NULL)
{
xrdp_wm_log_msg(self->wm,
LOG_LEVEL_WARNING, "Parameter 'pamsessionmng' is obsolete." " Please remove from config");
}
self->use_gw_login = 1;
}
/* Will we need chansrv ? We use it unconditionally for a
* sesman session, but the user can also request it separately */ if (self->use_sesman)
{
self->use_chansrv = 1;
} else
{ constchar *csp = xrdp_mm_get_value(self, "chansrvport"); /* It's defined, but is it a valid string? */ if (csp != NULL && parse_chansrvport(csp, NULL, 0, -1) == 0)
{
self->use_chansrv = 1;
}
}
xrdp_mm_connect_sm(self);
}
/*****************************************************************************/ /** *Startresizequeueprocessing * *Thexrdploginscreendoesnotcurrentlysupportclient-sideresizes.We *currentlyaddressthisbynotprocessingtheresizequeueuntilweare *abletodoso. * *Weimplementthisbynotcreatingtheresize_readywaitobjectuntil *weareabletoprocessthequeue.Callsmadetoanemptywaitobject *aresimplyignored. * *@paramselfMMmodule
*/ staticvoid
start_processing_resize_queue(struct xrdp_mm *self)
{ if (self->resize_ready == NULL_WAIT_OBJ)
{ char buf[32]; int outstanding =
(self->resize_queue != NULL) ? self->resize_queue->count : 0; int pid = g_getpid();
g_snprintf(buf, sizeof(buf), "xrdp_%8.8x_resize_ready", pid);
self->resize_ready = g_create_wait_obj(buf);
LOG(LOG_LEVEL_INFO, "xrdp can now process resize requests (%d outstanding)",
outstanding); if (outstanding > 0)
{
g_set_wait_obj(self->resize_ready);
}
}
}
/*****************************************************************************/ staticvoid
xrdp_mm_connect_sm(struct xrdp_mm *self)
{ int status = 0;
/* we set self->mmcs_expecting_msg in the loop when we've send a
message to sesman, and we need to wait for a response */
self->mmcs_expecting_msg = 0;
while (status == 0 && !self->mmcs_expecting_msg &&
self->connect_state != MMCS_DONE)
{ switch (self->connect_state)
{ case MMCS_CONNECT_TO_SESMAN:
{ if (self->sesman_trans == NULL &&
(self->use_sesman || self->use_gw_login))
{ /* Synchronous call */
status = xrdp_mm_sesman_connect(self);
}
} break;
case MMCS_GATEWAY_LOGIN:
{ if (self->use_gw_login)
{ constchar *gw_username; constchar *gw_password;
gw_username = xrdp_mm_get_value(self, "pamusername");
gw_password = xrdp_mm_get_value(self, "pampassword"); // gw_username shouldn't be NULL here, but we'll // check it anyway before dereferencing. if (gw_username != NULL &&
!g_strcmp(gw_username, "same"))
{
gw_username = xrdp_mm_get_value(self, "username");
}
// Default the password to the usual one if the // user hasn't specified one, or specified 'same' if (gw_password == NULL ||
!g_strcmp(gw_password, "same"))
{
gw_password = xrdp_mm_get_value(self, "password");
}
if (gw_username == NULL || gw_password == NULL)
{
xrdp_wm_log_msg(self->wm, LOG_LEVEL_ERROR, "Can't determine username and/or " "password for gateway login");
status = 1;
} else
{
xrdp_wm_log_msg(self->wm, LOG_LEVEL_INFO, "Performing access control for %s",
gw_username);
status = xrdp_mm_send_sys_login_request(self,
gw_username,
gw_password); if (status == 0)
{ /* Now waiting for a reply from sesman - see
xrdp_mm_process_login_response() */
self->mmcs_expecting_msg = 1;
}
}
}
} break;
case MMCS_SESSION_LOGIN:
{ // Finished with the gateway login // Leave the UID set in case we need it for the chansrvport // string if (self->use_gw_login)
{
xrdp_wm_log_msg(self->wm, LOG_LEVEL_INFO, "access control check was successful"); // No reply needed for this one
status = scp_send_logout_request(self->sesman_trans);
}
username = xrdp_mm_get_value(self, "username");
password = xrdp_mm_get_value(self, "password"); if (username == NULL || username[0] == '\0')
{
xrdp_wm_log_msg(self->wm, LOG_LEVEL_ERROR, "No username is available");
status = 1;
} elseif (password == NULL)
{ /* Can't find a password definition at all - even
* an empty one */
xrdp_wm_log_msg(self->wm, LOG_LEVEL_ERROR, "No password field is available");
status = 1;
} else
{
xrdp_wm_log_msg(self->wm, LOG_LEVEL_INFO, "Performing login request for %s",
username);
status = xrdp_mm_send_sys_login_request(self,
username,
password); if (status == 0)
{ /* Now waiting for a reply from sesman - see
xrdp_mm_process_create_session_response() */
self->mmcs_expecting_msg = 1;
}
}
}
} break;
case MMCS_CREATE_SESSION: if (self->use_sesman)
{
xrdp_wm_log_msg(self->wm, LOG_LEVEL_INFO, "login was successful - creating session"); if ((status = xrdp_mm_create_session(self)) == 0)
{ /* Now waiting for a reply from sesman. Note that *whenitarrives,sesmanisexpectingusto *closetheconnection-wecandonothingelse
* with it */
self->mmcs_expecting_msg = 1;
}
} break;
case MMCS_CONNECT_TO_SESSION:
{
xrdp_wm_log_msg(self->wm, LOG_LEVEL_INFO, "Connecting to session"); /* This is synchronous - no reply message expected */
status = xrdp_mm_user_session_connect(self); if (status == 0)
{ // This is as good a place as any to start processing // the resize_queue
start_processing_resize_queue(self);
}
} break;
case MMCS_CONNECT_TO_CHANSRV:
{ if (self->use_chansrv)
{ char portbuff[XRDP_SOCKETS_MAXPATH]; if (self->use_sesman)
{
g_snprintf(portbuff, sizeof(portbuff),
XRDP_CHANSRV_STR, self->uid, self->display);
xrdp_wm_log_msg(self->wm, LOG_LEVEL_INFO, "Connecting to chansrv");
} else
{ constchar *cp = xrdp_mm_get_value(self, "chansrvport"); if (parse_chansrvport(cp, portbuff, sizeof(portbuff),
self->uid) == 0)
{
xrdp_wm_log_msg(self->wm, LOG_LEVEL_INFO, "Connecting to chansrv on %s",
portbuff);
} else
{ // An error has already been logged
portbuff[0] = '\0';
}
}
case MMCS_DONE:
{ /* Shouldn't get here */
LOG(LOG_LEVEL_ERROR, "xrdp_mm_connect_sm: state machine error");
status = 1;
} break;
}
/* Move to the next state */ if (self->connect_state < MMCS_DONE)
{
self->connect_state = (enum mm_connect_state)
(self->connect_state + 1);
}
}
if (!self->mmcs_expecting_msg)
{ /* We don't need the sesman transport anymore */ if (self->sesman_trans != NULL)
{
self->delete_sesman_trans = 1;
}
xrdp_wm_mod_connect_done(self->wm, status); /* Make sure the module is cleaned up if we weren't successful */ if (status != 0)
{
xrdp_mm_module_cleanup(self);
}
}
}
#define MIN_MS_BETWEEN_FRAMES 40 #define MIN_MS_TO_WAIT_FOR_MORE_UPDATES 0 /*****************************************************************************/ int
xrdp_mm_get_wait_objs(struct xrdp_mm *self,
tbus *read_objs, int *rcount,
tbus *write_objs, int *wcount, int *timeout)
{ int rv = 0;
/*****************************************************************************/ int
xrdp_mm_check_chan(struct xrdp_mm *self)
{
LOG(LOG_LEVEL_TRACE, "xrdp_mm_check_chan:"); if ((self->chan_trans != 0) && self->chan_trans->status == TRANS_STATUS_UP)
{ if (trans_check_wait_objs(self->chan_trans) != 0)
{ /* This is safe to do here, as we're not in a chansrv
* transport callback */
trans_delete(self->chan_trans);
self->chan_trans = 0;
}
}
return0;
}
/*****************************************************************************/ staticint
xrdp_mm_process_enc_done(struct xrdp_mm *self)
{
XRDP_ENC_DATA *enc;
XRDP_ENC_DATA_DONE *enc_done; int x; int y; int cx; int cy; int is_gfx; int got_frame_id; int client_ack;
/*****************************************************************************/ int
xrdp_mm_check_wait_objs(struct xrdp_mm *self)
{ int rv;
if (self == 0)
{ return0;
}
rv = 0;
if (self->sesman_trans != NULL &&
!self->delete_sesman_trans &&
self->sesman_trans->status == TRANS_STATUS_UP)
{ if (trans_check_wait_objs(self->sesman_trans) != 0)
{ if (self->mmcs_expecting_msg)
{ /* The sesman transport has failed with an
* outstanding message */
xrdp_wm_log_msg(self->wm, LOG_LEVEL_ERROR, "Unexpected sesman failure - check sesman log");
xrdp_wm_mod_connect_done(self->wm, 1);
}
self->delete_sesman_trans = 1; if (self->wm->hide_log_window)
{ /* if hide_log_window, this is fatal */
rv = 1;
}
}
} if (self->delete_sesman_trans)
{
trans_delete(self->sesman_trans);
self->sesman_trans = NULL;
}
if (self->chan_trans != NULL &&
self->chan_trans->status == TRANS_STATUS_UP)
{ if (trans_check_wait_objs(self->chan_trans) != 0)
{ /* This is safe to do here, as we're not in a chansrv
* transport callback */
trans_delete(self->chan_trans);
self->chan_trans = NULL;
}
}
if (self->mod != NULL)
{ if (self->mod->mod_check_wait_objs != NULL)
{
rv = self->mod->mod_check_wait_objs(self->mod);
}
}
if (g_is_wait_obj_set(self->resize_ready))
{
g_reset_wait_obj(self->resize_ready);
dynamic_monitor_process_queue(self);
}
if (self->encoder != NULL)
{ if (g_is_wait_obj_set(self->encoder->xrdp_encoder_event_processed))
{
g_reset_wait_obj(self->encoder->xrdp_encoder_event_processed);
xrdp_mm_process_enc_done(self);
}
}
if (self->wm->screen_dirty_region != NULL)
{ if (xrdp_region_not_empty(self->wm->screen_dirty_region))
{ int now = g_time3(); int diff = now - self->wm->last_screen_draw_time;
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_mm_check_wait_objs: not empty diff %d", diff); if ((diff < 0) || (diff >= 40))
{ if (self->egfx_up)
{
rv = xrdp_mm_draw_dirty(self);
xrdp_region_delete(self->wm->screen_dirty_region);
self->wm->screen_dirty_region = NULL;
self->wm->last_screen_draw_time = now;
} else
{
LOG(LOG_LEVEL_TRACE, "xrdp_mm_check_wait_objs: egfx is not up");
}
}
}
}
return rv;
}
/*****************************************************************************/ /* frame ack from client */ int
xrdp_mm_frame_ack(struct xrdp_mm *self, int frame_id)
{ struct xrdp_encoder *encoder;
LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_mm_frame_ack:"); if (self->wm->client_info->use_frame_acks == 0)
{ return1;
} if ((encoder = self->encoder) == NULL)
{ /* No encoder - Possibly a late frame ack with a resize in progress */
LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_mm_frame_ack: " "Frame ack incoming %d with no encoder!", frame_id);
} else
{
LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_mm_frame_ack: " "incoming %d, client %d, server %d", frame_id,
encoder->frame_id_client, encoder->frame_id_server); if ((frame_id < 0) || (frame_id > encoder->frame_id_server))
{ /* if frame_id is negative or bigger then what server last sent
just ack all sent frames */ /* some clients can send big number just to clear all
pending frames */
encoder->frame_id_client = encoder->frame_id_server;
} else
{ /* frame acks can come out of order so ignore older one */
encoder->frame_id_client = MAX(frame_id, encoder->frame_id_client);
}
}
xrdp_mm_update_module_frame_ack(self); return0;
}
/*****************************************************************************/ /* got bell signal... try to send to client */ int
server_bell_trigger(struct xrdp_mod *mod)
{ struct xrdp_wm *wm;
/*****************************************************************************/ /* Chansrv in use on this configuration? */ int
server_chansrv_in_use(struct xrdp_mod *mod)
{ struct xrdp_wm *wm;
/*****************************************************************************/ int
server_fill_rect(struct xrdp_mod *mod, int x, int y, int cx, int cy)
{ struct xrdp_wm *wm; struct xrdp_painter *p;
/*****************************************************************************/ int
server_screen_blt(struct xrdp_mod *mod, int x, int y, int cx, int cy, int srcx, int srcy)
{ struct xrdp_wm *wm; struct xrdp_painter *p;
/*****************************************************************************/ int
server_paint_rect(struct xrdp_mod *mod, int x, int y, int cx, int cy, char *data, int width, int height, int srcx, int srcy)
{ struct xrdp_wm *wm; struct xrdp_bitmap *b; struct xrdp_painter *p;
/*****************************************************************************/ int
server_paint_rect_bpp(struct xrdp_mod *mod, int x, int y, int cx, int cy, char *data, int width, int height, int srcx, int srcy, int bpp)
{ struct xrdp_wm *wm; struct xrdp_bitmap *b; struct xrdp_painter *p;
p = (struct xrdp_painter *)(mod->painter); if (p == 0)
{ return0;
}
wm = (struct xrdp_wm *)(mod->wm);
b = xrdp_bitmap_create_with_data(width, height, bpp, data, wm);
xrdp_painter_copy(p, b, wm->target_surface, x, y, cx, cy, srcx, srcy);
xrdp_bitmap_delete(b); return0;
}
/*****************************************************************************/ int
server_composite(struct xrdp_mod *mod, int srcidx, int srcformat, int srcwidth, int srcrepeat, int *srctransform, int mskflags, int mskidx, int mskformat, int mskwidth, int mskrepeat, int op, int srcx, int srcy, int mskx, int msky, int dstx, int dsty, int width, int height, int dstformat)
{ struct xrdp_wm *wm; struct xrdp_bitmap *b; struct xrdp_bitmap *msk; struct xrdp_painter *p; struct xrdp_os_bitmap_item *bi;
p = (struct xrdp_painter *)(mod->painter); if (p == 0)
{ return0;
}
wm = (struct xrdp_wm *)(mod->wm);
b = 0;
msk = 0;
bi = xrdp_cache_get_os_bitmap(wm->cache, srcidx); if (bi != 0)
{
b = bi->bitmap;
} if (mskflags & 1)
{
bi = xrdp_cache_get_os_bitmap(wm->cache, mskidx); if (bi != 0)
{
msk = bi->bitmap;
}
} if (b != 0)
{
xrdp_painter_composite(p, b, srcformat, srcwidth, srcrepeat,
wm->target_surface, srctransform,
mskflags, msk, mskformat, mskwidth, mskrepeat,
op, srcx, srcy, mskx, msky, dstx, dsty,
width, height, dstformat);
} else
{
LOG(LOG_LEVEL_WARNING, "server_composite: error finding id %d or %d", srcidx, mskidx);
} return0;
}
/*****************************************************************************/ int
server_paint_rects(struct xrdp_mod *mod, int num_drects, short *drects, int num_crects, short *crects, char *data, int width, int height, int flags, int frame_id)
{ return server_paint_rects_ex(mod, num_drects, drects, num_crects, crects,
data, 0, 0, width, height, flags, frame_id,
NULL, 0);
}
/*****************************************************************************/ int
server_paint_rects_ex(struct xrdp_mod *mod, int num_drects, short *drects, int num_crects, short *crects, char *data, int left, int top, int width, int height, int flags, int frame_id, void *shmem_ptr, int shmem_bytes)
{ struct xrdp_wm *wm; struct xrdp_mm *mm; struct xrdp_painter *p; struct xrdp_bitmap *b; short *s; int index;
XRDP_ENC_DATA *enc_data;
/* insert into fifo for encoder thread to process */
tc_mutex_lock(mm->encoder->mutex);
fifo_add_item(mm->encoder->fifo_to_proc, (void *) enc_data);
tc_mutex_unlock(mm->encoder->mutex);
/* signal xrdp_encoder thread */
g_set_wait_obj(mm->encoder->xrdp_encoder_event_to_proc);
return0;
}
if (wm->client_info->gfx)
{
LOG(LOG_LEVEL_DEBUG, "server_paint_rects: gfx session and no encoder");
mm->mod->mod_frame_ack(mm->mod, flags, frame_id); return0;
}
p = (struct xrdp_painter *)(mod->painter); if (p == 0)
{ return0;
}
b = xrdp_bitmap_create_with_data(width, height, wm->screen->bpp,
data, wm);
s = crects; for (index = 0; index < num_crects; index++)
{
xrdp_painter_copy(p, b, wm->target_surface, s[0], s[1], s[2], s[3],
s[0], s[1]);
s += 4;
}
xrdp_bitmap_delete(b);
mm->mod->mod_frame_ack(mm->mod, flags, frame_id); if (shmem_ptr != NULL)
{
g_munmap(shmem_ptr, shmem_bytes);
} return0;
}
/*****************************************************************************/ int
server_session_info(struct xrdp_mod *mod, constchar *data, int data_bytes)
{ struct xrdp_wm *wm;
/*****************************************************************************/ int
server_egfx_cmd(struct xrdp_mod *mod, char *cmd, int cmd_bytes, char *data, int data_bytes)
{
XRDP_ENC_DATA *enc; struct xrdp_wm *wm; struct xrdp_mm *mm;
wm = (struct xrdp_wm *)(mod->wm);
mm = wm->mm; if (mm->encoder == NULL)
{ // This can happen when we are in the resize state machine, if // there are messages queued up by the X server if (data != NULL)
{
g_munmap(data, data_bytes);
} return0;
}
enc = g_new0(struct xrdp_enc_data, 1); if (enc == NULL)
{ if (data != NULL)
{
g_munmap(data, data_bytes);
} return1;
}
ENC_SET_BIT(enc->flags, ENC_FLAGS_GFX_BIT);
enc->u.gfx.cmd = g_new(char, cmd_bytes); if (enc->u.gfx.cmd == NULL)
{ if (data != NULL)
{
g_munmap(data, data_bytes);
}
g_free(enc); return1;
}
g_memcpy(enc->u.gfx.cmd, cmd, cmd_bytes);
enc->u.gfx.cmd_bytes = cmd_bytes;
enc->u.gfx.data = data;
enc->u.gfx.data_bytes = data_bytes;
enc->shmem_ptr = data;
enc->shmem_bytes = data_bytes; /* insert into fifo for encoder thread to process */
tc_mutex_lock(mm->encoder->mutex);
fifo_add_item(mm->encoder->fifo_to_proc, enc);
tc_mutex_unlock(mm->encoder->mutex); /* signal xrdp_encoder thread */
g_set_wait_obj(mm->encoder->xrdp_encoder_event_to_proc); return0;
}
/*****************************************************************************/ int
server_set_pointer_system(struct xrdp_mod *mod, int pointer_type)
{ struct xrdp_wm *wm;
/*****************************************************************************/ int
server_set_pointer_position(struct xrdp_mod *mod, int x, int y)
{ struct xrdp_wm *wm;
/*****************************************************************************/ int
server_set_pointer(struct xrdp_mod *mod, int x, int y, char *data, char *mask)
{ struct xrdp_wm *wm;
/*****************************************************************************/ int
server_set_pointer_ex(struct xrdp_mod *mod, int x, int y, char *data, char *mask, int bpp)
{ struct xrdp_wm *wm;
/*****************************************************************************/ int
server_set_pointer_large(struct xrdp_mod *mod, int x, int y, char *data, char *mask, int bpp, int width, int height)
{ struct xrdp_wm *wm;
/*****************************************************************************/ int
server_set_clip(struct xrdp_mod *mod, int x, int y, int cx, int cy)
{ struct xrdp_painter *p;
p = (struct xrdp_painter *)(mod->painter);
if (p == 0)
{ return0;
}
return xrdp_painter_set_clip(p, x, y, cx, cy);
}
/*****************************************************************************/ int
server_reset_clip(struct xrdp_mod *mod)
{ struct xrdp_painter *p;
p = (struct xrdp_painter *)(mod->painter);
if (p == 0)
{ return0;
}
return xrdp_painter_clr_clip(p);
}
/*****************************************************************************/ int
server_set_fgcolor(struct xrdp_mod *mod, int fgcolor)
{ struct xrdp_painter *p;
/*****************************************************************************/ int
server_set_bgcolor(struct xrdp_mod *mod, int bgcolor)
{ struct xrdp_painter *p;
p = (struct xrdp_painter *)(mod->painter);
if (p == 0)
{ return0;
}
p->bg_color = bgcolor; return0;
}
/*****************************************************************************/ int
server_set_opcode(struct xrdp_mod *mod, int opcode)
{ struct xrdp_painter *p;
p = (struct xrdp_painter *)(mod->painter);
if (p == 0)
{ return0;
}
p->rop = opcode; return0;
}
/*****************************************************************************/ int
server_set_mixmode(struct xrdp_mod *mod, int mixmode)
{ struct xrdp_painter *p;
p = (struct xrdp_painter *)(mod->painter);
if (p == 0)
{ return0;
}
p->mix_mode = mixmode; return0;
}
/*****************************************************************************/ int
server_set_brush(struct xrdp_mod *mod, int x_origin, int y_origin, int style, char *pattern)
{ struct xrdp_painter *p;
/*****************************************************************************/ int
server_set_pen(struct xrdp_mod *mod, int style, int width)
{ struct xrdp_painter *p;
/*****************************************************************************/ int
server_draw_line(struct xrdp_mod *mod, int x1, int y1, int x2, int y2)
{ struct xrdp_wm *wm; struct xrdp_painter *p;
/*****************************************************************************/ int
server_add_char(struct xrdp_mod *mod, int font, int character, int offset, int baseline, int width, int height, char *data)
{ struct xrdp_font_char fi;
/*****************************************************************************/ int
server_draw_text(struct xrdp_mod *mod, int font, int flags, int mixmode, int clip_left, int clip_top, int clip_right, int clip_bottom, int box_left, int box_top, int box_right, int box_bottom, int x, int y, char *data, int data_len)
{ struct xrdp_wm *wm; struct xrdp_painter *p;
/*****************************************************************************/ int
client_monitor_resize(struct xrdp_mod *mod, int width, int height, int num_monitors, conststruct monitor_info *monitors)
{ int error = 0; struct xrdp_wm *wm; struct display_size_description description;
/* Note : if this is called on a multimon setup, the client is resized
* to a single monitor */ int
server_monitor_resize_done(struct xrdp_mod *mod)
{ struct xrdp_wm *wm; struct xrdp_mm *mm;
wm = (struct xrdp_wm *)(mod->wm); if (wm == 0)
{ return1;
}
mm = wm->mm; if (mm == 0)
{ return1;
}
if (wm->client_info == 0)
{ return1;
}
if (mm->resize_data != NULL
&& mm->resize_data->state
== WMRZ_SERVER_MONITOR_MESSAGE_PROCESSING)
{
LOG(LOG_LEVEL_INFO, "server_monitor_resize_done: Advancing server monitor resized.");
advance_resize_state_machine(
mm, WMRZ_SERVER_MONITOR_MESSAGE_PROCESSED);
} return0;
}
/*****************************************************************************/ /*return -1 if channels are controlled by chansrv */ int
server_get_channel_count(struct xrdp_mod *mod)
{ struct xrdp_wm *wm;
wm = (struct xrdp_wm *)(mod->wm);
if (wm->mm->use_chansrv)
{ return -1;
}
return libxrdp_get_channel_count(wm->session);
}
/*****************************************************************************/ /*return 0 if the index is not found*/ int
server_query_channel(struct xrdp_mod *mod, int index, char *channel_name, int *channel_flags)
{ struct xrdp_wm *wm;
/*****************************************************************************/ int
server_send_to_channel(struct xrdp_mod *mod, int channel_id, char *data, int data_len, int total_data_len, int flags)
{ struct xrdp_wm *wm;
wm = (struct xrdp_wm *)(mod->wm);
if (wm->mm->use_chansrv)
{ /* Modules should not be calling this if chansrv is running -
* they can use server_chansrv_in_use() to avoid doing this */
LOG_DEVEL(LOG_LEVEL_ERROR, "Bad call of server_send_to_channel() detected"); return1;
}
/*****************************************************************************/ int
server_create_os_surface(struct xrdp_mod *mod, int rdpindex, int width, int height)
{ struct xrdp_wm *wm; struct xrdp_bitmap *bitmap; int error;
/*****************************************************************************/ int
server_create_os_surface_bpp(struct xrdp_mod *mod, int rdpindex, int width, int height, int bpp)
{ struct xrdp_wm *wm; struct xrdp_bitmap *bitmap; int error;
/*****************************************************************************/ int
server_paint_rect_os(struct xrdp_mod *mod, int x, int y, int cx, int cy, int rdpindex, int srcx, int srcy)
{ struct xrdp_wm *wm; struct xrdp_bitmap *b; struct xrdp_painter *p; struct xrdp_os_bitmap_item *bi;
p = (struct xrdp_painter *)(mod->painter);
if (p == 0)
{ return0;
}
wm = (struct xrdp_wm *)(mod->wm);
bi = xrdp_cache_get_os_bitmap(wm->cache, rdpindex);
if (bi != 0)
{
b = bi->bitmap;
xrdp_painter_copy(p, b, wm->target_surface, x, y, cx, cy, srcx, srcy);
} else
{
LOG(LOG_LEVEL_ERROR, "server_paint_rect_os: error finding id %d", rdpindex);
}
return0;
}
/*****************************************************************************/ int
server_set_hints(struct xrdp_mod *mod, int hints, int mask)
{ struct xrdp_wm *wm;
/*****************************************************************************/ int
server_window_icon(struct xrdp_mod *mod, int window_id, int cache_entry, int cache_id, struct rail_icon_info *icon_info, int flags)
{ struct xrdp_wm *wm;
/*****************************************************************************/ int
server_window_cached_icon(struct xrdp_mod *mod, int window_id, int cache_entry, int cache_id, int flags)
{ struct xrdp_wm *wm;
/*****************************************************************************/ int
server_notify_new_update(struct xrdp_mod *mod, int window_id, int notify_id, struct rail_notify_state_order *notify_state, int flags)
{ struct xrdp_wm *wm;
/*****************************************************************************/ int
server_notify_delete(struct xrdp_mod *mod, int window_id, int notify_id)
{ struct xrdp_wm *wm;
/*****************************************************************************/ int
server_add_char_alpha(struct xrdp_mod *mod, int font, int character, int offset, int baseline, int width, int height, char *data)
{ struct xrdp_font_char fi;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.