BOOL gdi_init(freerdp* instance, UINT32 flags, BYTE* buffer) { BOOL rgb555; rdpGdi* gdi; rdpCache* cache = NULL; gdi = (rdpGdi*) calloc(1, sizeof(rdpGdi)); if (!gdi) goto fail_gdi; instance->context->gdi = gdi; gdi->context = instance->context; gdi->codecs = instance->context->codecs; gdi->width = instance->settings->DesktopWidth; gdi->height = instance->settings->DesktopHeight; gdi->srcBpp = instance->settings->ColorDepth; gdi->primary_buffer = buffer; /* default internal buffer format */ gdi->dstBpp = 32; gdi->bytesPerPixel = 4; gdi->format = PIXEL_FORMAT_XRGB32; if (flags & CLRCONV_INVERT) gdi->invert = TRUE; rgb555 = (flags & CLRCONV_RGB555) ? TRUE : FALSE; if (gdi->srcBpp > 16) { if (flags & CLRBUF_32BPP) { gdi->dstBpp = 32; gdi->bytesPerPixel = 4; } else if (flags & CLRBUF_16BPP) { gdi->dstBpp = rgb555 ? 15 : 16; gdi->bytesPerPixel = 2; } } else { if (flags & CLRBUF_16BPP) { gdi->dstBpp = rgb555 ? 15 : 16; gdi->bytesPerPixel = 2; } else if (flags & CLRBUF_32BPP) { gdi->dstBpp = 32; gdi->bytesPerPixel = 4; } } if (!gdi->invert) { if (gdi->bytesPerPixel == 4) gdi->format = PIXEL_FORMAT_XRGB32; else if ((gdi->bytesPerPixel == 2) && (gdi->dstBpp == 16)) gdi->format = PIXEL_FORMAT_RGB565; else if ((gdi->bytesPerPixel == 2) && (gdi->dstBpp == 15)) gdi->format = PIXEL_FORMAT_RGB555; } else { if (gdi->bytesPerPixel == 4) gdi->format = PIXEL_FORMAT_XBGR32; else if ((gdi->bytesPerPixel == 2) && (gdi->dstBpp == 16)) gdi->format = PIXEL_FORMAT_BGR565; else if ((gdi->bytesPerPixel == 2) && (gdi->dstBpp == 15)) gdi->format = PIXEL_FORMAT_BGR555; } if (!(gdi->hdc = gdi_GetDC())) goto fail_get_hdc; gdi->hdc->bitsPerPixel = gdi->dstBpp; gdi->hdc->bytesPerPixel = gdi->bytesPerPixel; gdi->hdc->alpha = (flags & CLRCONV_ALPHA) ? TRUE : FALSE; gdi->hdc->invert = (flags & CLRCONV_INVERT) ? TRUE : FALSE; gdi->hdc->rgb555 = (flags & CLRCONV_RGB555) ? TRUE : FALSE; if (!gdi_init_primary(gdi)) goto fail_init_primary; if (!(gdi->tile = gdi_bitmap_new_ex(gdi, 64, 64, 32, NULL))) goto fail_tile_bitmap; if (!(gdi->image = gdi_bitmap_new_ex(gdi, 64, 64, 32, NULL))) goto fail_image_bitmap; if (!instance->context->cache) { if (!(cache = cache_new(instance->settings))) goto fail_cache; instance->context->cache = cache; } gdi_register_update_callbacks(instance->update); brush_cache_register_callbacks(instance->update); glyph_cache_register_callbacks(instance->update); bitmap_cache_register_callbacks(instance->update); offscreen_cache_register_callbacks(instance->update); palette_cache_register_callbacks(instance->update); if (!gdi_register_graphics(instance->context->graphics)) goto fail_register_graphics; instance->update->BitmapUpdate = gdi_bitmap_update; return TRUE; fail_register_graphics: if (cache) { instance->context->cache = NULL; free(cache); } fail_cache: gdi_bitmap_free_ex(gdi->image); fail_image_bitmap: gdi_bitmap_free_ex(gdi->tile); fail_tile_bitmap: gdi_bitmap_free_ex(gdi->primary); fail_init_primary: gdi_DeleteDC(gdi->hdc); fail_get_hdc: free(gdi); fail_gdi: WLog_ERR(TAG, "failed to initialize gdi"); return FALSE; }
BOOL wf_post_connect(freerdp* instance) { rdpGdi* gdi; DWORD dwStyle; rdpCache* cache; wfContext* wfc; rdpContext* context; WCHAR lpWindowName[64]; rdpSettings* settings; EmbedWindowEventArgs e; settings = instance->settings; context = instance->context; wfc = (wfContext*) instance->context; cache = instance->context->cache; wfc->dstBpp = 32; wfc->width = settings->DesktopWidth; wfc->height = settings->DesktopHeight; if (settings->SoftwareGdi) { wfc->primary = wf_image_new(wfc, wfc->width, wfc->height, wfc->dstBpp, NULL); if (!gdi_init(instance, CLRCONV_ALPHA | CLRBUF_32BPP, wfc->primary->pdata)) return FALSE; gdi = instance->context->gdi; wfc->hdc = gdi->primary->hdc; } else { wf_gdi_register_update_callbacks(instance->update); wfc->srcBpp = instance->settings->ColorDepth; wfc->primary = wf_image_new(wfc, wfc->width, wfc->height, wfc->dstBpp, NULL); if (!(wfc->hdc = gdi_GetDC())) return FALSE; wfc->hdc->bitsPerPixel = wfc->dstBpp; wfc->hdc->bytesPerPixel = wfc->dstBpp / 8; wfc->hdc->alpha = wfc->clrconv->alpha; wfc->hdc->invert = wfc->clrconv->invert; wfc->hdc->hwnd = (HGDI_WND) malloc(sizeof(GDI_WND)); wfc->hdc->hwnd->invalid = gdi_CreateRectRgn(0, 0, 0, 0); wfc->hdc->hwnd->invalid->null = 1; wfc->hdc->hwnd->count = 32; wfc->hdc->hwnd->cinvalid = (HGDI_RGN) malloc(sizeof(GDI_RGN) * wfc->hdc->hwnd->count); wfc->hdc->hwnd->ninvalid = 0; if (settings->RemoteFxCodec) { wfc->tile = wf_image_new(wfc, 64, 64, 32, NULL); } } if (settings->WindowTitle != NULL) _snwprintf(lpWindowName, ARRAYSIZE(lpWindowName), L"%S", settings->WindowTitle); else if (settings->ServerPort == 3389) _snwprintf(lpWindowName, ARRAYSIZE(lpWindowName), L"FreeRDP: %S", settings->ServerHostname); else _snwprintf(lpWindowName, ARRAYSIZE(lpWindowName), L"FreeRDP: %S:%d", settings->ServerHostname, settings->ServerPort); if (settings->EmbeddedWindow) settings->Decorations = FALSE; if (wfc->fullscreen) dwStyle = WS_POPUP; else if (!settings->Decorations) dwStyle = WS_CHILD | WS_BORDER; else dwStyle = WS_CAPTION | WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX | WS_SIZEBOX | WS_MAXIMIZEBOX; if (!wfc->hwnd) { wfc->hwnd = CreateWindowEx((DWORD) NULL, wfc->wndClassName, lpWindowName, dwStyle, 0, 0, 0, 0, wfc->hWndParent, NULL, wfc->hInstance, NULL); SetWindowLongPtr(wfc->hwnd, GWLP_USERDATA, (LONG_PTR) wfc); } wf_resize_window(wfc); wf_add_system_menu(wfc); BitBlt(wfc->primary->hdc, 0, 0, wfc->width, wfc->height, NULL, 0, 0, BLACKNESS); wfc->drawing = wfc->primary; EventArgsInit(&e, "wfreerdp"); e.embed = FALSE; e.handle = (void*) wfc->hwnd; PubSub_OnEmbedWindow(context->pubSub, context, &e); ShowWindow(wfc->hwnd, SW_SHOWNORMAL); UpdateWindow(wfc->hwnd); if (settings->SoftwareGdi) { instance->update->BeginPaint = (pBeginPaint) wf_sw_begin_paint; instance->update->EndPaint = (pEndPaint) wf_sw_end_paint; instance->update->DesktopResize = (pDesktopResize) wf_sw_desktop_resize; } else { instance->update->BeginPaint = (pBeginPaint) wf_hw_begin_paint; instance->update->EndPaint = (pEndPaint) wf_hw_end_paint; instance->update->DesktopResize = (pDesktopResize) wf_hw_desktop_resize; } pointer_cache_register_callbacks(instance->update); wf_register_pointer(context->graphics); if (!settings->SoftwareGdi) { brush_cache_register_callbacks(instance->update); bitmap_cache_register_callbacks(instance->update); offscreen_cache_register_callbacks(instance->update); wf_register_graphics(context->graphics); instance->update->BitmapUpdate = wf_gdi_bitmap_update; } if (freerdp_channels_post_connect(context->channels, instance) < 0) return FALSE; if (wfc->fullscreen) floatbar_window_create(wfc); return TRUE; }
BOOL rdp_freerdp_pre_connect(freerdp* instance) { rdpContext* context = instance->context; rdpChannels* channels = context->channels; guac_client* client = ((rdp_freerdp_context*) context)->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_rdp_settings* settings = rdp_client->settings; rdpBitmap* bitmap; rdpGlyph* glyph; rdpPointer* pointer; rdpPrimaryUpdate* primary; CLRCONV* clrconv; guac_rdp_dvc_list* dvc_list = guac_rdp_dvc_list_alloc(); #ifdef HAVE_FREERDP_REGISTER_ADDIN_PROVIDER /* Init FreeRDP add-in provider */ freerdp_register_addin_provider(freerdp_channels_load_static_addin_entry, 0); #endif #ifdef HAVE_FREERDP_EVENT_PUBSUB /* Subscribe to and handle channel connected events */ PubSub_SubscribeChannelConnected(context->pubSub, (pChannelConnectedEventHandler) guac_rdp_channel_connected); #endif #ifdef HAVE_FREERDP_DISPLAY_UPDATE_SUPPORT /* Load "disp" plugin for display update */ if (settings->resize_method == GUAC_RESIZE_DISPLAY_UPDATE) guac_rdp_disp_load_plugin(instance->context, dvc_list); #endif /* Load "AUDIO_INPUT" plugin for audio input*/ if (settings->enable_audio_input) { rdp_client->audio_input = guac_rdp_audio_buffer_alloc(); guac_rdp_audio_load_plugin(instance->context, dvc_list); } /* Load clipboard plugin if not disabled */ if (!(settings->disable_copy && settings->disable_paste) && freerdp_channels_load_plugin(channels, instance->settings, "cliprdr", NULL)) { guac_client_log(client, GUAC_LOG_WARNING, "Failed to load cliprdr plugin. Clipboard will not work."); } /* If RDPSND/RDPDR required, load them */ if (settings->printing_enabled || settings->drive_enabled || settings->audio_enabled) { /* Load RDPDR plugin */ if (freerdp_channels_load_plugin(channels, instance->settings, "guacdr", client)) guac_client_log(client, GUAC_LOG_WARNING, "Failed to load guacdr plugin. Drive redirection and " "printing will not work. Sound MAY not work."); /* Load RDPSND plugin */ if (freerdp_channels_load_plugin(channels, instance->settings, "guacsnd", client)) guac_client_log(client, GUAC_LOG_WARNING, "Failed to load guacsnd alongside guacdr plugin. Sound " "will not work. Drive redirection and printing MAY not " "work."); } /* Load RAIL plugin if RemoteApp in use */ if (settings->remote_app != NULL) { #ifdef LEGACY_FREERDP RDP_PLUGIN_DATA* plugin_data = malloc(sizeof(RDP_PLUGIN_DATA) * 2); plugin_data[0].size = sizeof(RDP_PLUGIN_DATA); plugin_data[0].data[0] = settings->remote_app; plugin_data[0].data[1] = settings->remote_app_dir; plugin_data[0].data[2] = settings->remote_app_args; plugin_data[0].data[3] = NULL; plugin_data[1].size = 0; /* Attempt to load rail */ if (freerdp_channels_load_plugin(channels, instance->settings, "rail", plugin_data)) guac_client_log(client, GUAC_LOG_WARNING, "Failed to load rail plugin. RemoteApp will not work."); #else /* Attempt to load rail */ if (freerdp_channels_load_plugin(channels, instance->settings, "rail", instance->settings)) guac_client_log(client, GUAC_LOG_WARNING, "Failed to load rail plugin. RemoteApp will not work."); #endif } /* Load SVC plugin instances for all static channels */ if (settings->svc_names != NULL) { char** current = settings->svc_names; do { guac_rdp_svc* svc = guac_rdp_alloc_svc(client, *current); /* Attempt to load guacsvc plugin for new static channel */ if (freerdp_channels_load_plugin(channels, instance->settings, "guacsvc", svc)) { guac_client_log(client, GUAC_LOG_WARNING, "Cannot create static channel \"%s\": failed to load guacsvc plugin.", svc->name); guac_rdp_free_svc(svc); } /* Store and log on success */ else { guac_rdp_add_svc(client, svc); guac_client_log(client, GUAC_LOG_INFO, "Created static channel \"%s\"...", svc->name); } } while (*(++current) != NULL); } /* Load DRDYNVC plugin if required */ if (guac_rdp_load_drdynvc(instance->context, dvc_list)) guac_client_log(client, GUAC_LOG_WARNING, "Failed to load drdynvc plugin. Display update and audio " "input support will be disabled."); /* Dynamic virtual channel list is no longer needed */ guac_rdp_dvc_list_free(dvc_list); /* Init color conversion structure */ clrconv = calloc(1, sizeof(CLRCONV)); clrconv->alpha = 1; clrconv->invert = 0; clrconv->rgb555 = 0; clrconv->palette = calloc(1, sizeof(rdpPalette)); ((rdp_freerdp_context*) context)->clrconv = clrconv; /* Init FreeRDP cache */ instance->context->cache = cache_new(instance->settings); /* Set up bitmap handling */ bitmap = calloc(1, sizeof(rdpBitmap)); bitmap->size = sizeof(guac_rdp_bitmap); bitmap->New = guac_rdp_bitmap_new; bitmap->Free = guac_rdp_bitmap_free; bitmap->Paint = guac_rdp_bitmap_paint; bitmap->Decompress = guac_rdp_bitmap_decompress; bitmap->SetSurface = guac_rdp_bitmap_setsurface; graphics_register_bitmap(context->graphics, bitmap); free(bitmap); /* Set up glyph handling */ glyph = calloc(1, sizeof(rdpGlyph)); glyph->size = sizeof(guac_rdp_glyph); glyph->New = guac_rdp_glyph_new; glyph->Free = guac_rdp_glyph_free; glyph->Draw = guac_rdp_glyph_draw; glyph->BeginDraw = guac_rdp_glyph_begindraw; glyph->EndDraw = guac_rdp_glyph_enddraw; graphics_register_glyph(context->graphics, glyph); free(glyph); /* Set up pointer handling */ pointer = calloc(1, sizeof(rdpPointer)); pointer->size = sizeof(guac_rdp_pointer); pointer->New = guac_rdp_pointer_new; pointer->Free = guac_rdp_pointer_free; pointer->Set = guac_rdp_pointer_set; #ifdef HAVE_RDPPOINTER_SETNULL pointer->SetNull = guac_rdp_pointer_set_null; #endif #ifdef HAVE_RDPPOINTER_SETDEFAULT pointer->SetDefault = guac_rdp_pointer_set_default; #endif graphics_register_pointer(context->graphics, pointer); free(pointer); /* Set up GDI */ instance->update->DesktopResize = guac_rdp_gdi_desktop_resize; instance->update->EndPaint = guac_rdp_gdi_end_paint; instance->update->Palette = guac_rdp_gdi_palette_update; instance->update->SetBounds = guac_rdp_gdi_set_bounds; primary = instance->update->primary; primary->DstBlt = guac_rdp_gdi_dstblt; primary->PatBlt = guac_rdp_gdi_patblt; primary->ScrBlt = guac_rdp_gdi_scrblt; primary->MemBlt = guac_rdp_gdi_memblt; primary->OpaqueRect = guac_rdp_gdi_opaquerect; pointer_cache_register_callbacks(instance->update); glyph_cache_register_callbacks(instance->update); brush_cache_register_callbacks(instance->update); bitmap_cache_register_callbacks(instance->update); offscreen_cache_register_callbacks(instance->update); palette_cache_register_callbacks(instance->update); /* Init channels (pre-connect) */ if (freerdp_channels_pre_connect(channels, instance)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Error initializing RDP client channel manager"); return FALSE; } return TRUE; }
BOOL wf_post_connect(freerdp* instance) { rdpGdi* gdi; wfInfo* wfi; rdpCache* cache; wfContext* context; int width, height; wchar_t win_title[64]; rdpSettings* settings; settings = instance->settings; context = (wfContext*) instance->context; cache = instance->context->cache; wfi = context->wfi; wfi->dstBpp = 32; width = settings->DesktopWidth; height = settings->DesktopHeight; if (wfi->sw_gdi) { gdi_init(instance, CLRCONV_ALPHA | CLRCONV_INVERT | CLRBUF_32BPP, NULL); gdi = instance->context->gdi; wfi->hdc = gdi->primary->hdc; wfi->primary = wf_image_new(wfi, width, height, wfi->dstBpp, gdi->primary_buffer); rfx_context_set_cpu_opt((RFX_CONTEXT*) gdi->rfx_context, wfi_detect_cpu()); } else { wf_gdi_register_update_callbacks(instance->update); wfi->srcBpp = instance->settings->ColorDepth; wfi->primary = wf_image_new(wfi, width, height, wfi->dstBpp, NULL); wfi->hdc = gdi_GetDC(); wfi->hdc->bitsPerPixel = wfi->dstBpp; wfi->hdc->bytesPerPixel = wfi->dstBpp / 8; wfi->hdc->alpha = wfi->clrconv->alpha; wfi->hdc->invert = wfi->clrconv->invert; wfi->hdc->hwnd = (HGDI_WND) malloc(sizeof(GDI_WND)); wfi->hdc->hwnd->invalid = gdi_CreateRectRgn(0, 0, 0, 0); wfi->hdc->hwnd->invalid->null = 1; wfi->hdc->hwnd->count = 32; wfi->hdc->hwnd->cinvalid = (HGDI_RGN) malloc(sizeof(GDI_RGN) * wfi->hdc->hwnd->count); wfi->hdc->hwnd->ninvalid = 0; wfi->image = wf_image_new(wfi, 64, 64, 32, NULL); wfi->image->_bitmap.data = NULL; if (settings->RemoteFxCodec) { wfi->tile = wf_image_new(wfi, 64, 64, 32, NULL); wfi->rfx_context = rfx_context_new(); rfx_context_set_cpu_opt(wfi->rfx_context, wfi_detect_cpu()); } if (settings->NSCodec) wfi->nsc_context = nsc_context_new(); } if (settings->WindowTitle != NULL) _snwprintf(win_title, ARRAYSIZE(win_title), L"%S", settings->WindowTitle); else if (settings->ServerPort == 3389) _snwprintf(win_title, ARRAYSIZE(win_title), L"FreeRDP: %S", settings->ServerHostname); else _snwprintf(win_title, ARRAYSIZE(win_title), L"FreeRDP: %S:%d", settings->ServerHostname, settings->ServerPort); if (wfi->hwnd == 0) { wfi->hwnd = CreateWindowEx((DWORD) NULL, g_wnd_class_name, win_title, 0, 0, 0, 0, 0, NULL, NULL, g_hInstance, NULL); SetWindowLongPtr(wfi->hwnd, GWLP_USERDATA, (LONG_PTR) wfi); } if (wfi->fullscreen) { SetWindowLongPtr(wfi->hwnd, GWL_STYLE, WS_POPUP); SetWindowPos(wfi->hwnd, HWND_TOP, 0, 0, width, height, SWP_FRAMECHANGED); } else { POINT diff; RECT rc_client, rc_wnd; SetWindowLongPtr(wfi->hwnd, GWL_STYLE, WS_CAPTION | WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX); /* Now resize to get full canvas size and room for caption and borders */ SetWindowPos(wfi->hwnd, HWND_TOP, 10, 10, width, height, SWP_FRAMECHANGED); GetClientRect(wfi->hwnd, &rc_client); GetWindowRect(wfi->hwnd, &rc_wnd); diff.x = (rc_wnd.right - rc_wnd.left) - rc_client.right; diff.y = (rc_wnd.bottom - rc_wnd.top) - rc_client.bottom; SetWindowPos(wfi->hwnd, HWND_TOP, -1, -1, width + diff.x, height + diff.y, SWP_NOMOVE | SWP_FRAMECHANGED); } BitBlt(wfi->primary->hdc, 0, 0, width, height, NULL, 0, 0, BLACKNESS); wfi->drawing = wfi->primary; ShowWindow(wfi->hwnd, SW_SHOWNORMAL); UpdateWindow(wfi->hwnd); if (wfi->sw_gdi) { instance->update->BeginPaint = wf_sw_begin_paint; instance->update->EndPaint = wf_sw_end_paint; } else { instance->update->BeginPaint = wf_hw_begin_paint; instance->update->EndPaint = wf_hw_end_paint; } pointer_cache_register_callbacks(instance->update); if (wfi->sw_gdi != TRUE) { brush_cache_register_callbacks(instance->update); bitmap_cache_register_callbacks(instance->update); offscreen_cache_register_callbacks(instance->update); } wf_register_graphics(instance->context->graphics); freerdp_channels_post_connect(instance->context->channels, instance); wf_cliprdr_init(wfi, instance->context->channels); return TRUE; }
int __guac_receive_channel_data(freerdp* rdp_inst, UINT16 channelId, BYTE* data, int size, int flags, int total_size) { #else int __guac_receive_channel_data(freerdp* rdp_inst, int channelId, UINT8* data, int size, int flags, int total_size) { #endif return freerdp_channels_data(rdp_inst, channelId, data, size, flags, total_size); } #ifdef HAVE_FREERDP_EVENT_PUBSUB /** * Called whenever a channel connects via the PubSub event system within * FreeRDP. * * @param context The rdpContext associated with the active RDP session. * @param e Event-specific arguments, mainly the name of the channel, and a * reference to the associated plugin loaded for that channel by * FreeRDP. */ static void guac_rdp_channel_connected(rdpContext* context, ChannelConnectedEventArgs* e) { #ifdef HAVE_RDPSETTINGS_SUPPORTDISPLAYCONTROL /* Store reference to the display update plugin once it's connected */ if (strcmp(e->name, DISP_DVC_CHANNEL_NAME) == 0) { DispClientContext* disp = (DispClientContext*) e->pInterface; guac_client* client = ((rdp_freerdp_context*) context)->client; rdp_guac_client_data* guac_client_data = (rdp_guac_client_data*) client->data; /* Init module with current display size */ guac_rdp_disp_set_size(guac_client_data->disp, context, guac_rdp_get_width(context->instance), guac_rdp_get_height(context->instance)); /* Store connected channel */ guac_rdp_disp_connect(guac_client_data->disp, disp); guac_client_log(client, GUAC_LOG_DEBUG, "Display update channel connected."); } #endif } #endif BOOL rdp_freerdp_pre_connect(freerdp* instance) { rdpContext* context = instance->context; guac_client* client = ((rdp_freerdp_context*) context)->client; rdpChannels* channels = context->channels; rdpBitmap* bitmap; rdpGlyph* glyph; rdpPointer* pointer; rdpPrimaryUpdate* primary; CLRCONV* clrconv; rdp_guac_client_data* guac_client_data = (rdp_guac_client_data*) client->data; #ifdef HAVE_FREERDP_REGISTER_ADDIN_PROVIDER /* Init FreeRDP add-in provider */ freerdp_register_addin_provider(freerdp_channels_load_static_addin_entry, 0); #endif #ifdef HAVE_FREERDP_EVENT_PUBSUB /* Subscribe to and handle channel connected events */ PubSub_SubscribeChannelConnected(context->pubSub, (pChannelConnectedEventHandler) guac_rdp_channel_connected); #endif #ifdef HAVE_FREERDP_DISPLAY_UPDATE_SUPPORT /* Load virtual channel management plugin */ if (freerdp_channels_load_plugin(channels, instance->settings, "drdynvc", instance->settings)) guac_client_log(client, GUAC_LOG_WARNING, "Failed to load drdynvc plugin."); /* Init display update plugin */ guac_client_data->disp = guac_rdp_disp_alloc(); guac_rdp_disp_load_plugin(instance->context); #endif /* Load clipboard plugin */ if (freerdp_channels_load_plugin(channels, instance->settings, "cliprdr", NULL)) guac_client_log(client, GUAC_LOG_WARNING, "Failed to load cliprdr plugin. Clipboard will not work."); /* If audio enabled, choose an encoder */ if (guac_client_data->settings.audio_enabled) { guac_client_data->audio = guac_audio_stream_alloc(client, NULL); /* If an encoding is available, load the sound plugin */ if (guac_client_data->audio != NULL) { /* Load sound plugin */ if (freerdp_channels_load_plugin(channels, instance->settings, "guacsnd", guac_client_data->audio)) guac_client_log(client, GUAC_LOG_WARNING, "Failed to load guacsnd plugin. Audio will not work."); } else guac_client_log(client, GUAC_LOG_INFO, "No available audio encoding. Sound disabled."); } /* end if audio enabled */ /* Load filesystem if drive enabled */ if (guac_client_data->settings.drive_enabled) { /* Allocate filesystem */ guac_client_data->filesystem = guac_rdp_fs_alloc(client, guac_client_data->settings.drive_path, guac_client_data->settings.create_drive_path); /* Use for basic uploads if no other handler set */ if (client->file_handler == NULL) client->file_handler = guac_rdp_upload_file_handler; } /* If RDPDR required, load it */ if (guac_client_data->settings.printing_enabled || guac_client_data->settings.drive_enabled || guac_client_data->settings.audio_enabled) { /* Load RDPDR plugin */ if (freerdp_channels_load_plugin(channels, instance->settings, "guacdr", client)) guac_client_log(client, GUAC_LOG_WARNING, "Failed to load guacdr plugin. Drive redirection and printing will not work."); } /* Load RAIL plugin if RemoteApp in use */ if (guac_client_data->settings.remote_app != NULL) { #ifdef LEGACY_FREERDP RDP_PLUGIN_DATA* plugin_data = malloc(sizeof(RDP_PLUGIN_DATA) * 2); plugin_data[0].size = sizeof(RDP_PLUGIN_DATA); plugin_data[0].data[0] = guac_client_data->settings.remote_app; plugin_data[0].data[1] = guac_client_data->settings.remote_app_dir; plugin_data[0].data[2] = guac_client_data->settings.remote_app_args; plugin_data[0].data[3] = NULL; plugin_data[1].size = 0; /* Attempt to load rail */ if (freerdp_channels_load_plugin(channels, instance->settings, "rail", plugin_data)) guac_client_log(client, GUAC_LOG_WARNING, "Failed to load rail plugin. RemoteApp will not work."); #else /* Attempt to load rail */ if (freerdp_channels_load_plugin(channels, instance->settings, "rail", instance->settings)) guac_client_log(client, GUAC_LOG_WARNING, "Failed to load rail plugin. RemoteApp will not work."); #endif } /* Load SVC plugin instances for all static channels */ if (guac_client_data->settings.svc_names != NULL) { char** current = guac_client_data->settings.svc_names; do { guac_rdp_svc* svc = guac_rdp_alloc_svc(client, *current); /* Attempt to load guacsvc plugin for new static channel */ if (freerdp_channels_load_plugin(channels, instance->settings, "guacsvc", svc)) { guac_client_log(client, GUAC_LOG_WARNING, "Cannot create static channel \"%s\": failed to load guacsvc plugin.", svc->name); guac_rdp_free_svc(svc); } /* Store and log on success */ else { guac_rdp_add_svc(client, svc); guac_client_log(client, GUAC_LOG_INFO, "Created static channel \"%s\"...", svc->name); } } while (*(++current) != NULL); } /* Init color conversion structure */ clrconv = calloc(1, sizeof(CLRCONV)); clrconv->alpha = 1; clrconv->invert = 0; clrconv->rgb555 = 0; clrconv->palette = calloc(1, sizeof(rdpPalette)); ((rdp_freerdp_context*) context)->clrconv = clrconv; /* Init FreeRDP cache */ instance->context->cache = cache_new(instance->settings); /* Set up bitmap handling */ bitmap = calloc(1, sizeof(rdpBitmap)); bitmap->size = sizeof(guac_rdp_bitmap); bitmap->New = guac_rdp_bitmap_new; bitmap->Free = guac_rdp_bitmap_free; bitmap->Paint = guac_rdp_bitmap_paint; bitmap->Decompress = guac_rdp_bitmap_decompress; bitmap->SetSurface = guac_rdp_bitmap_setsurface; graphics_register_bitmap(context->graphics, bitmap); free(bitmap); /* Set up glyph handling */ glyph = calloc(1, sizeof(rdpGlyph)); glyph->size = sizeof(guac_rdp_glyph); glyph->New = guac_rdp_glyph_new; glyph->Free = guac_rdp_glyph_free; glyph->Draw = guac_rdp_glyph_draw; glyph->BeginDraw = guac_rdp_glyph_begindraw; glyph->EndDraw = guac_rdp_glyph_enddraw; graphics_register_glyph(context->graphics, glyph); free(glyph); /* Set up pointer handling */ pointer = calloc(1, sizeof(rdpPointer)); pointer->size = sizeof(guac_rdp_pointer); pointer->New = guac_rdp_pointer_new; pointer->Free = guac_rdp_pointer_free; pointer->Set = guac_rdp_pointer_set; #ifdef HAVE_RDPPOINTER_SETNULL pointer->SetNull = guac_rdp_pointer_set_null; #endif #ifdef HAVE_RDPPOINTER_SETDEFAULT pointer->SetDefault = guac_rdp_pointer_set_default; #endif graphics_register_pointer(context->graphics, pointer); free(pointer); /* Set up GDI */ instance->update->DesktopResize = guac_rdp_gdi_desktop_resize; instance->update->EndPaint = guac_rdp_gdi_end_paint; instance->update->Palette = guac_rdp_gdi_palette_update; instance->update->SetBounds = guac_rdp_gdi_set_bounds; primary = instance->update->primary; primary->DstBlt = guac_rdp_gdi_dstblt; primary->PatBlt = guac_rdp_gdi_patblt; primary->ScrBlt = guac_rdp_gdi_scrblt; primary->MemBlt = guac_rdp_gdi_memblt; primary->OpaqueRect = guac_rdp_gdi_opaquerect; pointer_cache_register_callbacks(instance->update); glyph_cache_register_callbacks(instance->update); brush_cache_register_callbacks(instance->update); bitmap_cache_register_callbacks(instance->update); offscreen_cache_register_callbacks(instance->update); palette_cache_register_callbacks(instance->update); /* Init channels (pre-connect) */ if (freerdp_channels_pre_connect(channels, instance)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Error initializing RDP client channel manager"); return FALSE; } return TRUE; }