/* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. xrdp: A Remote Desktop Protocol server. Copyright (C) Jay Sorg 2010 freerdp wrapper */ #include "xrdp-freerdp.h" #include "xrdp-color.h" #define GET_MOD(_inst) ((struct mod*)((_inst)->param1)) #define SET_MOD(_inst, _mod) ((_inst)->param1) = _mod struct my_bitmap { char* data; int width; int height; int bpp; }; struct my_cursor { char* andmask; int andbpp; char* xormask; int xorbpp; int width; int height; int hotx; int hoty; }; /*****************************************************************************/ /* return error */ static int DEFAULT_CC lib_mod_start(struct mod* mod, int w, int h, int bpp) { LIB_DEBUG(mod, "in lib_mod_start"); g_writeln("lib_mod_start: w %d h %d bpp %d", w, h, bpp); mod->width = w; mod->height = h; mod->bpp = bpp; if (bpp == 24) { mod->settings->server_depth = 32; } else { mod->settings->server_depth = mod->bpp; } mod->settings->width = mod->width; mod->settings->height = mod->height; LIB_DEBUG(mod, "out lib_mod_start"); return 0; } /******************************************************************************/ /* return error */ static int DEFAULT_CC lib_mod_connect(struct mod* mod) { int code; LIB_DEBUG(mod, "in lib_mod_connect"); code = mod->inst->rdp_connect(mod->inst); g_writeln("lib_mod_connect: code %d", code); LIB_DEBUG(mod, "out lib_mod_connect"); return code; } /******************************************************************************/ /* return error */ static int DEFAULT_CC lib_mod_event(struct mod* mod, int msg, long param1, long param2, long param3, long param4) { LIB_DEBUG(mod, "in lib_mod_event"); int ext; //g_writeln("%d %d %d %d %d", msg, param1, param2, param3, param4); switch (msg) { case 15: ext = param4 & 0x100 ? 1 : 0; mod->inst->rdp_send_input_scancode(mod->inst, 0, ext, param3); break; case 16: ext = param4 & 0x100 ? 1 : 0; mod->inst->rdp_send_input_scancode(mod->inst, 1, ext, param3); break; case 17: mod->inst->rdp_sync_input(mod->inst, param4); break; case 100: mod->inst->rdp_send_input_mouse(mod->inst, PTRFLAGS_MOVE, param1, param2); break; case 101: mod->inst->rdp_send_input_mouse(mod->inst, PTRFLAGS_BUTTON1, param1, param2); break; case 102: mod->inst->rdp_send_input_mouse(mod->inst, PTRFLAGS_BUTTON1 | PTRFLAGS_DOWN, param1, param2); break; case 103: mod->inst->rdp_send_input_mouse(mod->inst, PTRFLAGS_BUTTON2, param1, param2); break; case 104: mod->inst->rdp_send_input_mouse(mod->inst, PTRFLAGS_BUTTON2 | PTRFLAGS_DOWN, param1, param2); break; case 105: mod->inst->rdp_send_input_mouse(mod->inst, PTRFLAGS_BUTTON3, param1, param2); break; case 106: mod->inst->rdp_send_input_mouse(mod->inst, PTRFLAGS_BUTTON3 | PTRFLAGS_DOWN, param1, param2); break; case 107: mod->inst->rdp_send_input_mouse(mod->inst, PTRFLAGS_WHEEL | 0x0078, 0, 0); break; case 108: break; case 109: mod->inst->rdp_send_input_mouse(mod->inst, PTRFLAGS_WHEEL | PTRFLAGS_WHEEL_NEGATIVE | 0x0088, 0, 0); break; case 110: break; } LIB_DEBUG(mod, "out lib_mod_event"); return 0; } /******************************************************************************/ /* return error */ static int DEFAULT_CC lib_mod_signal(struct mod* mod) { LIB_DEBUG(mod, "in lib_mod_signal"); g_writeln("lib_mod_signal:"); LIB_DEBUG(mod, "out lib_mod_signal"); return 0; } /******************************************************************************/ /* return error */ static int DEFAULT_CC lib_mod_end(struct mod* mod) { g_writeln("lib_mod_end:"); return 0; } /******************************************************************************/ /* return error */ static int DEFAULT_CC lib_mod_set_param(struct mod* mod, char* name, char* value) { g_writeln("lib_mod_set_param: name [%s] value [%s]", name, value); if (g_strcmp(name, "hostname") == 0) { g_strncpy(mod->settings->hostname, value, sizeof(mod->settings->hostname)); } else if (g_strcmp(name, "ip") == 0) { g_strncpy(mod->settings->server, value, sizeof(mod->settings->server)); } else if (g_strcmp(name, "port") == 0) { mod->settings->tcp_port_rdp = g_atoi(value); } else if (g_strcmp(name, "keylayout") == 0) { mod->settings->keyboard_layout = g_atoi(value); } else if (g_strcmp(name, "name") == 0) { } else if (g_strcmp(name, "lib") == 0) { } else { g_writeln("lib_mod_set_param: unknown name [%s] value [%s]", name, value); } return 0; } /******************************************************************************/ static int DEFAULT_CC mod_session_change(struct mod* v, int a, int b) { g_writeln("mod_session_change:"); return 0; } /******************************************************************************/ static int DEFAULT_CC mod_get_wait_objs(struct mod* v, tbus* read_objs, int* rcount, tbus* write_objs, int* wcount, int* timeout) { void** rfds; void** wfds; rfds = (void**)read_objs; wfds = (void**)write_objs; return v->inst->rdp_get_fds(v->inst, rfds, rcount, wfds, wcount); } /******************************************************************************/ static int DEFAULT_CC mod_check_wait_objs(struct mod* v) { return v->inst->rdp_check_fds(v->inst); } /******************************************************************************/ static void DEFAULT_CC ui_error(rdpInst* inst, const char* text) { g_writeln("ui_error: %s", text); } /******************************************************************************/ static void DEFAULT_CC ui_warning(rdpInst* inst, const char* text) { g_writeln("ui_warning: %s", text); } /******************************************************************************/ static void DEFAULT_CC ui_unimpl(rdpInst* inst, const char* text) { g_writeln("ui_unimpl: %s", text); } /******************************************************************************/ static void DEFAULT_CC ui_begin_update(rdpInst* inst) { struct mod* mod; mod = GET_MOD(inst); mod->server_begin_update(mod); } /******************************************************************************/ static void DEFAULT_CC ui_end_update(rdpInst* inst) { struct mod* mod; mod = GET_MOD(inst); mod->server_end_update(mod); } /******************************************************************************/ static void DEFAULT_CC ui_desktop_save(rdpInst* inst, int offset, int x, int y, int cx, int cy) { g_writeln("ui_desktop_save:"); } /******************************************************************************/ static void DEFAULT_CC ui_desktop_restore(rdpInst* inst, int offset, int x, int y, int cx, int cy) { g_writeln("ui_desktop_restore:"); } /******************************************************************************/ static RD_HBITMAP DEFAULT_CC ui_create_bitmap(rdpInst* inst, int width, int height, uint8* data) { struct my_bitmap* bm; struct mod* mod; int size; int bpp; char* bmpdata; mod = GET_MOD(inst); bpp = mod->bpp == 24 ? 32 : mod->bpp; bm = (struct my_bitmap*)g_malloc(sizeof(struct my_bitmap), 1); bm->width = width; bm->height = height; bm->bpp = bpp; bmpdata = convert_bitmap(mod->settings->server_depth, bpp, data, width, height, mod->cmap); if (bmpdata == (char*)data) { size = width * height * ((bpp + 7) / 8); bm->data = (char*)g_malloc(size, 0); g_memcpy(bm->data, bmpdata, size); } else { bm->data = bmpdata; } return bm; } /******************************************************************************/ static void DEFAULT_CC ui_paint_bitmap(rdpInst* inst, int x, int y, int cx, int cy, int width, int height, uint8* data) { struct mod* mod; char* bmpdata; mod = GET_MOD(inst); bmpdata = convert_bitmap(mod->settings->server_depth, mod->bpp, data, width, height, mod->cmap); if (bmpdata != 0) { mod->server_paint_rect(mod, x, y, cx, cy, bmpdata, width, height, 0, 0); } if (bmpdata != (char*)data) { g_free(bmpdata); } } /******************************************************************************/ static void DEFAULT_CC ui_destroy_bitmap(rdpInst* inst, RD_HBITMAP bmp) { struct my_bitmap* bm; bm = (struct my_bitmap*)bmp; g_free(bm->data); g_free(bm); } /******************************************************************************/ static void DEFAULT_CC ui_line(rdpInst* inst, uint8 opcode, int startx, int starty, int endx, int endy, RD_PEN* pen) { g_writeln("ui_line:"); } /******************************************************************************/ static void DEFAULT_CC ui_rect(rdpInst* inst, int x, int y, int cx, int cy, uint32 color) { struct mod* mod; mod = GET_MOD(inst); color = convert_color(mod->settings->server_depth, mod->bpp, color, mod->cmap); mod->server_set_fgcolor(mod, color); mod->server_fill_rect(mod, x, y, cx, cy); } /******************************************************************************/ static void DEFAULT_CC ui_polygon(rdpInst* inst, uint8 opcode, uint8 fillmode, RD_POINT* point, int npoints, RD_BRUSH* brush, uint32 bgcolor, uint32 fgcolor) { g_writeln("ui_polygon:"); } /******************************************************************************/ static void DEFAULT_CC ui_polyline(rdpInst* inst, uint8 opcode, RD_POINT* points, int npoints, RD_PEN* pen) { g_writeln("ui_polyline:"); } /******************************************************************************/ static void DEFAULT_CC ui_ellipse(rdpInst* inst, uint8 opcode, uint8 fillmode, int x, int y, int cx, int cy, RD_BRUSH* brush, uint32 bgcolor, uint32 fgcolor) { g_writeln("ui_ellipse:"); } /******************************************************************************/ static void DEFAULT_CC ui_add_char(rdpInst * inst, uint8 font, uint16 character, sint16 offset, sint16 baseline, uint16 width, uint16 height, uint8 * data) { struct mod* mod; //g_writeln("ui_add_char:"); mod = GET_MOD(inst); mod->server_add_char(mod, font, character, offset, baseline, width, height, (char*)data); } /******************************************************************************/ static void DEFAULT_CC ui_draw_text(rdpInst* inst, uint8 font, uint8 flags, uint8 opcode, int mixmode, int x, int y, int clipx, int clipy, int clipcx, int clipcy, int boxx, int boxy, int boxcx, int boxcy, RD_BRUSH * brush, uint32 bgcolor, uint32 fgcolor, uint8 * text, uint8 length) { struct mod* mod; //g_writeln("ui_draw_text: flags %d mixmode %d x %d y %d", flags, mixmode, x, y); //g_writeln("%d %d %d %d %d %d %d %d", clipx, clipy, clipcx, clipcy, boxx, boxy, boxcx, boxcy); mod = GET_MOD(inst); fgcolor = convert_color(mod->settings->server_depth, mod->bpp, fgcolor, mod->cmap); mod->server_set_fgcolor(mod, fgcolor); bgcolor = convert_color(mod->settings->server_depth, mod->bpp, bgcolor, mod->cmap); mod->server_set_bgcolor(mod, bgcolor); mod->server_draw_text(mod, font, flags, mixmode, clipx, clipy, clipx + clipcx, clipy + clipcy, boxx, boxy, boxx + boxcx, boxy + boxcy, x, y, (char*)text, length); } /******************************************************************************/ static void DEFAULT_CC ui_start_draw_glyphs(rdpInst* inst, uint32 bgcolor, uint32 fgcolor) { g_writeln("ui_start_draw_glyphs:"); } /******************************************************************************/ static void DEFAULT_CC ui_draw_glyph(rdpInst* inst, int x, int y, int cx, int cy, RD_HGLYPH glyph) { g_writeln("ui_draw_glyph:"); } /******************************************************************************/ static void DEFAULT_CC ui_end_draw_glyphs(rdpInst* inst, int x, int y, int cx, int cy) { g_writeln("ui_end_draw_glyphs:"); } /******************************************************************************/ static uint32 DEFAULT_CC ui_get_toggle_keys_state(rdpInst* inst) { g_writeln("ui_get_toggle_keys_state:"); return 0; } /******************************************************************************/ static void DEFAULT_CC ui_bell(rdpInst* inst) { g_writeln("ui_bell:"); } /******************************************************************************/ static void DEFAULT_CC ui_destblt(rdpInst* inst, uint8 opcode, int x, int y, int cx, int cy) { struct mod* mod; g_writeln("ui_destblt:"); mod = GET_MOD(inst); mod->server_set_opcode(mod, opcode); mod->server_fill_rect(mod, x, y, cx, cy); mod->server_set_opcode(mod, 0xcc); } /******************************************************************************/ static void DEFAULT_CC ui_patblt(rdpInst* inst, uint8 opcode, int x, int y, int cx, int cy, RD_BRUSH* brush, uint32 bgcolor, uint32 fgcolor) { struct mod* mod; uint8 idata[8]; int index; mod = GET_MOD(inst); mod->server_set_opcode(mod, opcode); fgcolor = convert_color(mod->settings->server_depth, mod->bpp, fgcolor, mod->cmap); mod->server_set_fgcolor(mod, fgcolor); bgcolor = convert_color(mod->settings->server_depth, mod->bpp, bgcolor, mod->cmap); mod->server_set_bgcolor(mod, bgcolor); mod->server_set_mixmode(mod, 1); if (brush->bd != 0) { if (brush->bd->color_code == 1) /* 8x8 1 bpp */ { for (index = 0; index < 8; index++) { idata[index] = ~(brush->bd->data[index]); } mod->server_set_brush(mod, brush->xorigin, brush->yorigin, brush->style, idata); } else { g_writeln("ui_patblt: error color_code %d", brush->bd->color_code); } } else { for (index = 0; index < 8; index++) { idata[index] = ~(brush->pattern[index]); } mod->server_set_brush(mod, brush->xorigin, brush->yorigin, brush->style, idata); } mod->server_fill_rect(mod, x, y, cx, cy); mod->server_set_opcode(mod, 0xcc); mod->server_set_mixmode(mod, 0); } /******************************************************************************/ static void DEFAULT_CC ui_screenblt(rdpInst* inst, uint8 opcode, int x, int y, int cx, int cy, int srcx, int srcy) { struct mod* mod; mod = GET_MOD(inst); mod->server_set_opcode(mod, opcode); mod->server_screen_blt(mod, x, y, cx, cy, srcx, srcy); mod->server_set_opcode(mod, 0xcc); } /******************************************************************************/ static void DEFAULT_CC ui_memblt(rdpInst* inst, uint8 opcode, int x, int y, int cx, int cy, RD_HBITMAP src, int srcx, int srcy) { struct my_bitmap* bitmap; struct mod* mod; char* bmpdata; mod = GET_MOD(inst); bitmap = (struct my_bitmap*)src; mod->server_set_opcode(mod, opcode); mod->server_paint_rect(mod, x, y, cx, cy, bitmap->data, bitmap->width, bitmap->height, srcx, srcy); mod->server_set_opcode(mod, 0xcc); } /******************************************************************************/ static void DEFAULT_CC ui_triblt(rdpInst* inst, uint8 opcode, int x, int y, int cx, int cy, RD_HBITMAP src, int srcx, int srcy, RD_BRUSH* brush, uint32 bgcolor, uint32 fgcolor) { g_writeln("ui_triblt:"); } /******************************************************************************/ static RD_HGLYPH DEFAULT_CC ui_create_glyph(rdpInst* inst, int width, int height, uint8* data) { g_writeln("ui_create_glyph:"); return 0; } /******************************************************************************/ static void DEFAULT_CC ui_destroy_glyph(rdpInst* inst, RD_HGLYPH glyph) { g_writeln("ui_destroy_glyph:"); } /******************************************************************************/ static int DEFAULT_CC ui_select(rdpInst* inst, int rdp_socket) { return 1; } /******************************************************************************/ static void DEFAULT_CC ui_set_clip(rdpInst* inst, int x, int y, int cx, int cy) { struct mod* mod; mod = GET_MOD(inst); mod->server_set_clip(mod, x, y, cx, cy); } /******************************************************************************/ static void DEFAULT_CC ui_reset_clip(rdpInst* inst) { struct mod* mod; mod = GET_MOD(inst); mod->server_reset_clip(mod); } /******************************************************************************/ static void DEFAULT_CC ui_resize_window(rdpInst* inst) { g_writeln("ui_resize_window:"); } /******************************************************************************/ static void DEFAULT_CC ui_set_cursor(rdpInst* inst, RD_HCURSOR cursor) { struct mod* mod; struct my_cursor* cur; //g_writeln("ui_set_cursor:"); mod = GET_MOD(inst); cur = (struct my_cursor*)cursor; if (cur != 0) { mod->server_set_cursor(mod, cur->hotx, cur->hoty, cur->xormask, cur->andmask); } else { g_writeln("ui_set_cursor: nil cursor"); } } /******************************************************************************/ static void DEFAULT_CC ui_destroy_cursor(rdpInst* inst, RD_HCURSOR cursor) { struct my_cursor* cur; //g_writeln("ui_destroy_cursor:"); cur = (struct my_cursor*)cursor; if (cur != 0) { g_free(cur->andmask); g_free(cur->xormask); } g_free(cur); } #define RGB24(_r, _g, _b) \ (_r << 16) | (_g << 8) | _b; /******************************************************************************/ static int l_get_pixel(tui8* data, int x, int y, int width, int height, int bpp) { int start; int shift; tui16* src16; tui32* src32; int red, green, blue; switch (bpp) { case 1: width = (width + 7) / 8; start = (y * width) + x / 8; shift = x % 8; return (data[start] & (0x80 >> shift)) != 0; case 8: return data[y * width + x]; case 15: case 16: src16 = (uint16*) data; return src16[y * width + x]; case 24: data += y * width * 3; data += x * 3; red = data[0]; green = data[1]; blue = data[2]; return RGB24(red, green, blue); case 32: src32 = (uint32*) data; return src32[y * width + x]; default: g_writeln("l_get_pixel: unknown bpp %d", bpp); break; } return 0; } /******************************************************************************/ static void l_set_pixel(tui8* data, int x, int y, int width, int height, int bpp, int pixel) { int start; int shift; int* dst32; tui8* dst8; if (bpp == 1) { width = (width + 7) / 8; start = (y * width) + x / 8; shift = x % 8; if (pixel) data[start] = data[start] | (0x80 >> shift); else data[start] = data[start] & ~(0x80 >> shift); } else if (bpp == 24) { dst8 = data + (y * width + x) * 3; *(dst8++) = (pixel >> 16) & 0xff; *(dst8++) = (pixel >> 8) & 0xff; *(dst8++) = (pixel >> 0) & 0xff; } else if (bpp == 32) { dst32 = (int*) data; dst32[y * width + x] = pixel; } else { g_writeln("l_set_pixel: unknown bpp %d", bpp); } } /******************************************************************************/ /* andmask = mask = 32 * 32 / 8 xormask = data = 32 * 32 * 3 */ static RD_HCURSOR DEFAULT_CC ui_create_cursor(rdpInst* inst, unsigned int x, unsigned int y, int width, int height, uint8* andmask, uint8* xormask, int bpp) { struct mod* mod; struct my_cursor* cur; int i; int j; int jj; int apixel; int xpixel; char* dst; mod = GET_MOD(inst); g_writeln("ui_create_cursor: x %d y %d width %d height %d bpp %d", x, y, width, height, bpp); cur = (struct my_cursor*)g_malloc(sizeof(struct my_cursor), 1); cur->width = width; cur->height = height; cur->hotx = x; cur->hoty = y; cur->andmask = g_malloc(32 * 32 * 4, 1); cur->xormask = g_malloc(32 * 32 * 4, 1); for (j = 0; j < height; j++) { jj = (bpp != 1) ? j : (height - 1) - j; for (i = 0; i < width; i++) { apixel = l_get_pixel(andmask, i, jj, width, height, 1); xpixel = l_get_pixel(xormask, i, jj, width, height, bpp); xpixel = convert_color(bpp, 24, xpixel, mod->cmap); l_set_pixel(cur->andmask, i, j, width, height, 1, apixel); l_set_pixel(cur->xormask, i, j, width, height, 24, xpixel); } } return (RD_HCURSOR)cur; } /******************************************************************************/ static void DEFAULT_CC ui_set_null_cursor(rdpInst* inst) { g_writeln("ui_set_null_cursor:"); } /******************************************************************************/ static void DEFAULT_CC ui_set_default_cursor(rdpInst* inst) { g_writeln("ui_set_default_cursor:"); } /******************************************************************************/ static RD_HPALETTE DEFAULT_CC ui_create_palette(rdpInst* inst, RD_PALETTE* colors) { struct mod* mod; int index; int red; int green; int blue; int pixel; int count; int* cmap; mod = GET_MOD(inst); g_writeln("ui_create_palette:"); count = 256; if (count > colors->count) { count = colors->count; } cmap = (int*)g_malloc(256 * 4, 1); for (index = 0; index < count; index++) { red = colors->entries[index].red; green = colors->entries[index].green; blue = colors->entries[index].blue; pixel = COLOR24RGB(red, green, blue); cmap[index] = pixel; } return (RD_HPALETTE)cmap; } /******************************************************************************/ static void DEFAULT_CC ui_move_pointer(rdpInst* inst, int x, int y) { g_writeln("ui_move_pointer:"); } /******************************************************************************/ static void DEFAULT_CC ui_set_palette(rdpInst* inst, RD_HPALETTE map) { struct mod* mod; mod = GET_MOD(inst); g_writeln("ui_set_palette:"); g_memcpy(mod->cmap, map, 256 * 4); g_free(map); } /******************************************************************************/ static RD_HBITMAP DEFAULT_CC ui_create_surface(rdpInst* inst, int width, int height, RD_HBITMAP old) { g_writeln("ui_create_surface:"); return 0; } /******************************************************************************/ static void DEFAULT_CC ui_set_surface(rdpInst* inst, RD_HBITMAP surface) { g_writeln("ui_set_surface:"); } /******************************************************************************/ static void DEFAULT_CC ui_destroy_surface(rdpInst* inst, RD_HBITMAP surface) { g_writeln("ui_destroy_surface:"); } /******************************************************************************/ static void DEFAULT_CC ui_channel_data(rdpInst* inst, int chan_id, char* data, int data_size, int flags, int total_size) { g_writeln("ui_channel_data:"); } /******************************************************************************/ static RD_BOOL DEFAULT_CC ui_authenticate(rdpInst * inst) { return 1; } /******************************************************************************/ static int DEFAULT_CC ui_decode(rdpInst * inst, uint8 * data, int data_size) { return 0; } /******************************************************************************/ static RD_BOOL DEFAULT_CC ui_check_certificate(rdpInst * inst, const char * fingerprint, const char * subject, const char * issuer, RD_BOOL verified) { return 1; } /******************************************************************************/ struct mod* EXPORT_CC mod_init(void) { struct mod* mod; //g_writeln("1"); //freerdp_global_init(); //g_writeln("2"); mod = (struct mod*)g_malloc(sizeof(struct mod), 1); mod->size = sizeof(struct mod); mod->version = CURRENT_MOD_VER; mod->handle = (tbus)mod; mod->mod_connect = lib_mod_connect; mod->mod_start = lib_mod_start; mod->mod_event = lib_mod_event; mod->mod_signal = lib_mod_signal; mod->mod_end = lib_mod_end; mod->mod_set_param = lib_mod_set_param; mod->mod_session_change = mod_session_change; mod->mod_get_wait_objs = mod_get_wait_objs; mod->mod_check_wait_objs = mod_check_wait_objs; mod->settings = (struct rdp_set*)g_malloc(sizeof(struct rdp_set), 1); mod->settings->width = 1280; mod->settings->height = 1024; mod->settings->encryption = 1; mod->settings->rdp_security = 1; mod->settings->tls_security = 1; mod->settings->server_depth = 16; mod->settings->bitmap_cache = 1; mod->settings->bitmap_compression = 1; mod->settings->performanceflags = PERF_DISABLE_WALLPAPER | PERF_DISABLE_FULLWINDOWDRAG | PERF_DISABLE_MENUANIMATIONS; mod->settings->new_cursors = 1; mod->settings->rdp_version = 5; mod->settings->text_flags = 1; mod->inst = freerdp_new(mod->settings); if (mod->inst == 0) { return 0; } SET_MOD(mod->inst, mod); mod->inst->ui_error = ui_error; mod->inst->ui_warning = ui_warning; mod->inst->ui_unimpl = ui_unimpl; mod->inst->ui_begin_update = ui_begin_update; mod->inst->ui_end_update = ui_end_update; mod->inst->ui_desktop_save = ui_desktop_save; mod->inst->ui_desktop_restore = ui_desktop_restore; mod->inst->ui_create_bitmap = ui_create_bitmap; mod->inst->ui_paint_bitmap = ui_paint_bitmap; mod->inst->ui_destroy_bitmap = ui_destroy_bitmap; mod->inst->ui_line = ui_line; mod->inst->ui_rect = ui_rect; mod->inst->ui_polygon = ui_polygon; mod->inst->ui_polyline = ui_polyline; mod->inst->ui_ellipse = ui_ellipse; mod->inst->ui_add_char = ui_add_char; mod->inst->ui_draw_text = ui_draw_text; mod->inst->ui_start_draw_glyphs = ui_start_draw_glyphs; mod->inst->ui_draw_glyph = ui_draw_glyph; mod->inst->ui_end_draw_glyphs = ui_end_draw_glyphs; mod->inst->ui_get_toggle_keys_state = ui_get_toggle_keys_state; mod->inst->ui_bell = ui_bell; mod->inst->ui_destblt = ui_destblt; mod->inst->ui_patblt = ui_patblt; mod->inst->ui_screenblt = ui_screenblt; mod->inst->ui_memblt = ui_memblt; mod->inst->ui_triblt = ui_triblt; mod->inst->ui_create_glyph = ui_create_glyph; mod->inst->ui_destroy_glyph = ui_destroy_glyph; mod->inst->ui_select = ui_select; mod->inst->ui_set_clip = ui_set_clip; mod->inst->ui_reset_clip = ui_reset_clip; mod->inst->ui_resize_window = ui_resize_window; mod->inst->ui_set_cursor = ui_set_cursor; mod->inst->ui_destroy_cursor = ui_destroy_cursor; mod->inst->ui_create_cursor = ui_create_cursor; mod->inst->ui_set_null_cursor = ui_set_null_cursor; mod->inst->ui_set_default_cursor = ui_set_default_cursor; mod->inst->ui_create_palette = ui_create_palette; mod->inst->ui_move_pointer = ui_move_pointer; mod->inst->ui_set_palette = ui_set_palette; mod->inst->ui_create_surface = ui_create_surface; mod->inst->ui_set_surface = ui_set_surface; mod->inst->ui_destroy_surface = ui_destroy_surface; mod->inst->ui_channel_data = ui_channel_data; mod->inst->ui_authenticate = ui_authenticate; mod->inst->ui_decode = ui_decode; mod->inst->ui_check_certificate = ui_check_certificate; return mod; } /******************************************************************************/ int EXPORT_CC mod_exit(struct mod* mod) { if (mod == 0) { return 0; } freerdp_free(mod->inst); g_free(mod->settings); g_free(mod); //freerdp_global_finish(); return 0; }