示例#1
0
文件: gdi.c 项目: BUGgs/FreeRDP
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;
}
示例#2
0
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;
}
示例#3
0
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;

}
示例#4
0
文件: wfreerdp.c 项目: d0rian/FreeRDP
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;
}
示例#5
0
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;

}