Blame client/Windows/wf_client.c

Packit 1fb8d4
/**
Packit 1fb8d4
 * FreeRDP: A Remote Desktop Protocol Implementation
Packit 1fb8d4
 * Windows Client
Packit 1fb8d4
 *
Packit 1fb8d4
 * Copyright 2009-2011 Jay Sorg
Packit 1fb8d4
 * Copyright 2010-2011 Vic Lee
Packit 1fb8d4
 * Copyright 2010-2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
Packit 1fb8d4
 *
Packit 1fb8d4
 * Licensed under the Apache License, Version 2.0 (the "License");
Packit 1fb8d4
 * you may not use this file except in compliance with the License.
Packit 1fb8d4
 * You may obtain a copy of the License at
Packit 1fb8d4
 *
Packit 1fb8d4
 *	 http://www.apache.org/licenses/LICENSE-2.0
Packit 1fb8d4
 *
Packit 1fb8d4
 * Unless required by applicable law or agreed to in writing, software
Packit 1fb8d4
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit 1fb8d4
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit 1fb8d4
 * See the License for the specific language governing permissions and
Packit 1fb8d4
 * limitations under the License.
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
#ifdef HAVE_CONFIG_H
Packit 1fb8d4
#include "config.h"
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
#include <winpr/windows.h>
Packit 1fb8d4
Packit 1fb8d4
#include <winpr/crt.h>
Packit 1fb8d4
#include <winpr/credui.h>
Packit 1fb8d4
Packit 1fb8d4
#include <errno.h>
Packit 1fb8d4
#include <stdio.h>
Packit 1fb8d4
#include <stdlib.h>
Packit 1fb8d4
#include <string.h>
Packit 1fb8d4
#include <tchar.h>
Packit 1fb8d4
#include <assert.h>
Packit 1fb8d4
#include <sys/types.h>
Packit 1fb8d4
Packit 1fb8d4
#include <freerdp/log.h>
Packit 1fb8d4
#include <freerdp/event.h>
Packit 1fb8d4
#include <freerdp/freerdp.h>
Packit 1fb8d4
#include <freerdp/constants.h>
Packit 1fb8d4
Packit 1fb8d4
#include <freerdp/codec/region.h>
Packit 1fb8d4
#include <freerdp/client/cmdline.h>
Packit 1fb8d4
#include <freerdp/client/channels.h>
Packit 1fb8d4
#include <freerdp/channels/channels.h>
Packit 1fb8d4
Packit 1fb8d4
#include "wf_gdi.h"
Packit 1fb8d4
#include "wf_rail.h"
Packit 1fb8d4
#include "wf_channels.h"
Packit 1fb8d4
#include "wf_graphics.h"
Packit 1fb8d4
#include "wf_cliprdr.h"
Packit 1fb8d4
Packit 1fb8d4
#include "wf_client.h"
Packit 1fb8d4
Packit 1fb8d4
#include "resource.h"
Packit 1fb8d4
Packit 1fb8d4
#define TAG CLIENT_TAG("windows")
Packit 1fb8d4
Packit 1fb8d4
static int wf_create_console(void)
Packit 1fb8d4
{
Packit 1fb8d4
	if (!AllocConsole())
Packit 1fb8d4
		return 1;
Packit 1fb8d4
Packit 1fb8d4
	freopen("CONOUT$", "w", stdout);
Packit 1fb8d4
	freopen("CONOUT$", "w", stderr);
Packit 1fb8d4
	WLog_INFO(TAG,  "Debug console created.");
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL wf_end_paint(rdpContext* context)
Packit 1fb8d4
{
Packit 1fb8d4
	int i;
Packit 1fb8d4
	rdpGdi* gdi;
Packit 1fb8d4
	int ninvalid;
Packit 1fb8d4
	RECT updateRect;
Packit 1fb8d4
	HGDI_RGN cinvalid;
Packit 1fb8d4
	REGION16 invalidRegion;
Packit 1fb8d4
	RECTANGLE_16 invalidRect;
Packit 1fb8d4
	const RECTANGLE_16* extents;
Packit 1fb8d4
	wfContext* wfc = (wfContext*)context;
Packit 1fb8d4
	gdi = context->gdi;
Packit 1fb8d4
	ninvalid = gdi->primary->hdc->hwnd->ninvalid;
Packit 1fb8d4
	cinvalid = gdi->primary->hdc->hwnd->cinvalid;
Packit 1fb8d4
Packit 1fb8d4
	if (ninvalid < 1)
Packit 1fb8d4
		return TRUE;
Packit 1fb8d4
Packit 1fb8d4
	region16_init(&invalidRegion);
Packit 1fb8d4
Packit 1fb8d4
	for (i = 0; i < ninvalid; i++)
Packit 1fb8d4
	{
Packit 1fb8d4
		invalidRect.left = cinvalid[i].x;
Packit 1fb8d4
		invalidRect.top = cinvalid[i].y;
Packit 1fb8d4
		invalidRect.right = cinvalid[i].x + cinvalid[i].w;
Packit 1fb8d4
		invalidRect.bottom = cinvalid[i].y + cinvalid[i].h;
Packit 1fb8d4
		region16_union_rect(&invalidRegion, &invalidRegion, &invalidRect);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (!region16_is_empty(&invalidRegion))
Packit 1fb8d4
	{
Packit 1fb8d4
		extents = region16_extents(&invalidRegion);
Packit 1fb8d4
		updateRect.left = extents->left;
Packit 1fb8d4
		updateRect.top = extents->top;
Packit 1fb8d4
		updateRect.right = extents->right;
Packit 1fb8d4
		updateRect.bottom = extents->bottom;
Packit 1fb8d4
		InvalidateRect(wfc->hwnd, &updateRect, FALSE);
Packit 1fb8d4
Packit 1fb8d4
		if (wfc->rail)
Packit 1fb8d4
			wf_rail_invalidate_region(wfc, &invalidRegion);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	region16_uninit(&invalidRegion);
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL wf_begin_paint(rdpContext* context)
Packit 1fb8d4
{
Packit 1fb8d4
	HGDI_DC hdc;
Packit 1fb8d4
Packit 1fb8d4
	if (!context || !context->gdi || !context->gdi->primary || !context->gdi->primary->hdc)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	hdc = context->gdi->primary->hdc;
Packit 1fb8d4
Packit 1fb8d4
	if (!hdc || !hdc->hwnd || !hdc->hwnd->invalid)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	hdc->hwnd->invalid->null = TRUE;
Packit 1fb8d4
	hdc->hwnd->ninvalid = 0;
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL wf_desktop_resize(rdpContext* context)
Packit 1fb8d4
{
Packit 1fb8d4
	BOOL same;
Packit 1fb8d4
	RECT rect;
Packit 1fb8d4
	rdpSettings* settings;
Packit 1fb8d4
	wfContext* wfc = (wfContext*)context;
Packit 1fb8d4
Packit 1fb8d4
	if (!context || !context->settings)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	settings = context->settings;
Packit 1fb8d4
Packit 1fb8d4
	if (wfc->primary)
Packit 1fb8d4
	{
Packit 1fb8d4
		same = (wfc->primary == wfc->drawing) ? TRUE : FALSE;
Packit 1fb8d4
		wf_image_free(wfc->primary);
Packit 1fb8d4
		wfc->primary = wf_image_new(wfc, settings->DesktopWidth,
Packit 1fb8d4
		                            settings->DesktopHeight, context->gdi->dstFormat, NULL);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (!gdi_resize_ex(context->gdi, settings->DesktopWidth,
Packit 1fb8d4
	                   settings->DesktopHeight, 0,
Packit 1fb8d4
	                   context->gdi->dstFormat, wfc->primary->pdata, NULL))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (same)
Packit 1fb8d4
		wfc->drawing = wfc->primary;
Packit 1fb8d4
Packit 1fb8d4
	if (wfc->fullscreen != TRUE)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (wfc->hwnd)
Packit 1fb8d4
			SetWindowPos(wfc->hwnd, HWND_TOP, -1, -1, settings->DesktopWidth + wfc->diff.x,
Packit 1fb8d4
			             settings->DesktopHeight + wfc->diff.y, SWP_NOMOVE);
Packit 1fb8d4
	}
Packit 1fb8d4
	else
Packit 1fb8d4
	{
Packit 1fb8d4
		wf_update_offset(wfc);
Packit 1fb8d4
		GetWindowRect(wfc->hwnd, &rect);
Packit 1fb8d4
		InvalidateRect(wfc->hwnd, &rect, TRUE);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL wf_pre_connect(freerdp* instance)
Packit 1fb8d4
{
Packit 1fb8d4
	wfContext* wfc;
Packit 1fb8d4
	int desktopWidth;
Packit 1fb8d4
	int desktopHeight;
Packit 1fb8d4
	rdpContext* context;
Packit 1fb8d4
	rdpSettings* settings;
Packit 1fb8d4
Packit 1fb8d4
	if (!instance || !instance->context || !instance->settings)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	context = instance->context;
Packit 1fb8d4
	wfc = (wfContext*) instance->context;
Packit 1fb8d4
	settings = instance->settings;
Packit 1fb8d4
	settings->OsMajorType = OSMAJORTYPE_WINDOWS;
Packit 1fb8d4
	settings->OsMinorType = OSMINORTYPE_WINDOWS_NT;
Packit 1fb8d4
	settings->OrderSupport[NEG_DSTBLT_INDEX] = TRUE;
Packit 1fb8d4
	settings->OrderSupport[NEG_PATBLT_INDEX] = TRUE;
Packit 1fb8d4
	settings->OrderSupport[NEG_SCRBLT_INDEX] = TRUE;
Packit 1fb8d4
	settings->OrderSupport[NEG_OPAQUE_RECT_INDEX] = TRUE;
Packit 1fb8d4
	settings->OrderSupport[NEG_DRAWNINEGRID_INDEX] = FALSE;
Packit 1fb8d4
	settings->OrderSupport[NEG_MULTIDSTBLT_INDEX] = FALSE;
Packit 1fb8d4
	settings->OrderSupport[NEG_MULTIPATBLT_INDEX] = FALSE;
Packit 1fb8d4
	settings->OrderSupport[NEG_MULTISCRBLT_INDEX] = FALSE;
Packit 1fb8d4
	settings->OrderSupport[NEG_MULTIOPAQUERECT_INDEX] = TRUE;
Packit 1fb8d4
	settings->OrderSupport[NEG_MULTI_DRAWNINEGRID_INDEX] = FALSE;
Packit 1fb8d4
	settings->OrderSupport[NEG_LINETO_INDEX] = TRUE;
Packit 1fb8d4
	settings->OrderSupport[NEG_POLYLINE_INDEX] = TRUE;
Packit 1fb8d4
	settings->OrderSupport[NEG_MEMBLT_INDEX] = settings->BitmapCacheEnabled;
Packit 1fb8d4
	settings->OrderSupport[NEG_MEM3BLT_INDEX] = settings->BitmapCacheEnabled;
Packit 1fb8d4
	settings->OrderSupport[NEG_MEMBLT_V2_INDEX] = settings->BitmapCacheEnabled;
Packit 1fb8d4
	settings->OrderSupport[NEG_MEM3BLT_V2_INDEX] = settings->BitmapCacheEnabled;
Packit 1fb8d4
	settings->OrderSupport[NEG_SAVEBITMAP_INDEX] = FALSE;
Packit 1fb8d4
	settings->OrderSupport[NEG_GLYPH_INDEX_INDEX] = TRUE;
Packit 1fb8d4
	settings->OrderSupport[NEG_FAST_INDEX_INDEX] = TRUE;
Packit 1fb8d4
	settings->OrderSupport[NEG_FAST_GLYPH_INDEX] = TRUE;
Packit 1fb8d4
	settings->OrderSupport[NEG_POLYGON_SC_INDEX] = TRUE;
Packit 1fb8d4
	settings->OrderSupport[NEG_POLYGON_CB_INDEX] = TRUE;
Packit 1fb8d4
	settings->OrderSupport[NEG_ELLIPSE_SC_INDEX] = FALSE;
Packit 1fb8d4
	settings->OrderSupport[NEG_ELLIPSE_CB_INDEX] = FALSE;
Packit 1fb8d4
	wfc->fullscreen = settings->Fullscreen;
Packit 1fb8d4
	wfc->floatbar_active = settings->Floatbar;
Packit 1fb8d4
Packit 1fb8d4
	if (wfc->fullscreen)
Packit 1fb8d4
		wfc->fs_toggle = 1;
Packit 1fb8d4
Packit 1fb8d4
	desktopWidth = settings->DesktopWidth;
Packit 1fb8d4
	desktopHeight = settings->DesktopHeight;
Packit 1fb8d4
Packit 1fb8d4
	if (wfc->percentscreen > 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		desktopWidth = (GetSystemMetrics(SM_CXSCREEN) * wfc->percentscreen) / 100;
Packit 1fb8d4
		settings->DesktopWidth = desktopWidth;
Packit 1fb8d4
		desktopHeight = (GetSystemMetrics(SM_CYSCREEN) * wfc->percentscreen) / 100;
Packit 1fb8d4
		settings->DesktopHeight = desktopHeight;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (wfc->fullscreen)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (settings->UseMultimon)
Packit 1fb8d4
		{
Packit 1fb8d4
			desktopWidth = GetSystemMetrics(SM_CXVIRTUALSCREEN);
Packit 1fb8d4
			desktopHeight = GetSystemMetrics(SM_CYVIRTUALSCREEN);
Packit 1fb8d4
		}
Packit 1fb8d4
		else
Packit 1fb8d4
		{
Packit 1fb8d4
			desktopWidth = GetSystemMetrics(SM_CXSCREEN);
Packit 1fb8d4
			desktopHeight = GetSystemMetrics(SM_CYSCREEN);
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	/* FIXME: desktopWidth has a limitation that it should be divisible by 4,
Packit 1fb8d4
	 *        otherwise the screen will crash when connecting to an XP desktop.*/
Packit 1fb8d4
	desktopWidth = (desktopWidth + 3) & (~3);
Packit 1fb8d4
Packit 1fb8d4
	if (desktopWidth != settings->DesktopWidth)
Packit 1fb8d4
	{
Packit 1fb8d4
		freerdp_set_param_uint32(settings, FreeRDP_DesktopWidth, desktopWidth);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (desktopHeight != settings->DesktopHeight)
Packit 1fb8d4
	{
Packit 1fb8d4
		freerdp_set_param_uint32(settings, FreeRDP_DesktopHeight, desktopHeight);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if ((settings->DesktopWidth < 64) || (settings->DesktopHeight < 64) ||
Packit 1fb8d4
	    (settings->DesktopWidth > 4096) || (settings->DesktopHeight > 4096))
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "invalid dimensions %lu %lu", settings->DesktopWidth,
Packit 1fb8d4
		         settings->DesktopHeight);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (!freerdp_client_load_addins(context->channels, instance->settings))
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	freerdp_set_param_uint32(settings, FreeRDP_KeyboardLayout,
Packit 1fb8d4
	                         (int) GetKeyboardLayout(0) & 0x0000FFFF);
Packit 1fb8d4
	PubSub_SubscribeChannelConnected(instance->context->pubSub,
Packit 1fb8d4
	                                 wf_OnChannelConnectedEventHandler);
Packit 1fb8d4
	PubSub_SubscribeChannelDisconnected(instance->context->pubSub,
Packit 1fb8d4
	                                    wf_OnChannelDisconnectedEventHandler);
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static void wf_add_system_menu(wfContext* wfc)
Packit 1fb8d4
{
Packit 1fb8d4
	HMENU hMenu = GetSystemMenu(wfc->hwnd, FALSE);
Packit 1fb8d4
	MENUITEMINFO item_info;
Packit 1fb8d4
	ZeroMemory(&item_info, sizeof(MENUITEMINFO));
Packit 1fb8d4
	item_info.fMask = MIIM_CHECKMARKS | MIIM_FTYPE | MIIM_ID | MIIM_STRING |
Packit 1fb8d4
	                  MIIM_DATA;
Packit 1fb8d4
	item_info.cbSize = sizeof(MENUITEMINFO);
Packit 1fb8d4
	item_info.wID = SYSCOMMAND_ID_SMARTSIZING;
Packit 1fb8d4
	item_info.fType = MFT_STRING;
Packit 1fb8d4
	item_info.dwTypeData = _wcsdup(_T("Smart sizing"));
Packit 1fb8d4
	item_info.cch = (UINT) _wcslen(_T("Smart sizing"));
Packit 1fb8d4
	item_info.dwItemData = (ULONG_PTR) wfc;
Packit 1fb8d4
	InsertMenuItem(hMenu, 6, TRUE, &item_info);
Packit 1fb8d4
Packit 1fb8d4
	if (wfc->context.settings->SmartSizing)
Packit 1fb8d4
	{
Packit 1fb8d4
		CheckMenuItem(hMenu, SYSCOMMAND_ID_SMARTSIZING, MF_CHECKED);
Packit 1fb8d4
	}
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL wf_post_connect(freerdp* instance)
Packit 1fb8d4
{
Packit 1fb8d4
	rdpGdi* gdi;
Packit 1fb8d4
	DWORD dwStyle;
Packit 1fb8d4
	rdpCache* cache;
Packit 1fb8d4
	wfContext* wfc;
Packit 1fb8d4
	rdpContext* context;
Packit 1fb8d4
	WCHAR lpWindowName[512];
Packit 1fb8d4
	rdpSettings* settings;
Packit 1fb8d4
	EmbedWindowEventArgs e;
Packit 1fb8d4
	const UINT32 format = PIXEL_FORMAT_BGRX32;
Packit 1fb8d4
	settings = instance->settings;
Packit 1fb8d4
	context = instance->context;
Packit 1fb8d4
	wfc = (wfContext*) instance->context;
Packit 1fb8d4
	cache = instance->context->cache;
Packit 1fb8d4
	wfc->primary = wf_image_new(wfc, settings->DesktopWidth,
Packit 1fb8d4
	                            settings->DesktopHeight, format, NULL);
Packit 1fb8d4
Packit 1fb8d4
	if (!gdi_init_ex(instance, format, 0, wfc->primary->pdata, NULL))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	gdi = instance->context->gdi;
Packit 1fb8d4
Packit 1fb8d4
	if (!settings->SoftwareGdi)
Packit 1fb8d4
	{
Packit 1fb8d4
		wf_gdi_register_update_callbacks(instance->update);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (settings->WindowTitle != NULL)
Packit 1fb8d4
		_snwprintf_s(lpWindowName, ARRAYSIZE(lpWindowName), _TRUNCATE, L"%S", settings->WindowTitle);
Packit 1fb8d4
	else if (settings->ServerPort == 3389)
Packit 1fb8d4
		_snwprintf_s(lpWindowName, ARRAYSIZE(lpWindowName), _TRUNCATE, L"FreeRDP: %S",
Packit 1fb8d4
		             settings->ServerHostname);
Packit 1fb8d4
	else
Packit 1fb8d4
		_snwprintf_s(lpWindowName, ARRAYSIZE(lpWindowName), _TRUNCATE, L"FreeRDP: %S:%u",
Packit 1fb8d4
		             settings->ServerHostname, settings->ServerPort);
Packit 1fb8d4
Packit 1fb8d4
	if (settings->EmbeddedWindow)
Packit 1fb8d4
		settings->Decorations = FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (wfc->fullscreen)
Packit 1fb8d4
		dwStyle = WS_POPUP;
Packit 1fb8d4
	else if (!settings->Decorations)
Packit 1fb8d4
		dwStyle = WS_CHILD | WS_BORDER;
Packit 1fb8d4
	else
Packit 1fb8d4
		dwStyle = WS_CAPTION | WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX | WS_SIZEBOX
Packit 1fb8d4
		          | WS_MAXIMIZEBOX;
Packit 1fb8d4
Packit 1fb8d4
	if (!wfc->hwnd)
Packit 1fb8d4
	{
Packit 1fb8d4
		wfc->hwnd = CreateWindowEx((DWORD) NULL, wfc->wndClassName, lpWindowName,
Packit 1fb8d4
		                           dwStyle,
Packit 1fb8d4
		                           0, 0, 0, 0, wfc->hWndParent, NULL, wfc->hInstance, NULL);
Packit 1fb8d4
		SetWindowLongPtr(wfc->hwnd, GWLP_USERDATA, (LONG_PTR) wfc);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	wf_resize_window(wfc);
Packit 1fb8d4
	wf_add_system_menu(wfc);
Packit 1fb8d4
	BitBlt(wfc->primary->hdc, 0, 0, settings->DesktopWidth, settings->DesktopHeight,
Packit 1fb8d4
	       NULL, 0, 0, BLACKNESS);
Packit 1fb8d4
	wfc->drawing = wfc->primary;
Packit 1fb8d4
	EventArgsInit(&e, "wfreerdp");
Packit 1fb8d4
	e.embed = FALSE;
Packit 1fb8d4
	e.handle = (void*) wfc->hwnd;
Packit 1fb8d4
	PubSub_OnEmbedWindow(context->pubSub, context, &e);
Packit 1fb8d4
	ShowWindow(wfc->hwnd, SW_SHOWNORMAL);
Packit 1fb8d4
	UpdateWindow(wfc->hwnd);
Packit 1fb8d4
	instance->update->BeginPaint = wf_begin_paint;
Packit 1fb8d4
	instance->update->DesktopResize = wf_desktop_resize;
Packit 1fb8d4
	instance->update->EndPaint = wf_end_paint;
Packit 1fb8d4
	wf_register_pointer(context->graphics);
Packit 1fb8d4
Packit 1fb8d4
	if (!settings->SoftwareGdi)
Packit 1fb8d4
	{
Packit 1fb8d4
		wf_register_graphics(context->graphics);
Packit 1fb8d4
		wf_gdi_register_update_callbacks(instance->update);
Packit 1fb8d4
		brush_cache_register_callbacks(instance->update);
Packit 1fb8d4
		glyph_cache_register_callbacks(instance->update);
Packit 1fb8d4
		bitmap_cache_register_callbacks(instance->update);
Packit 1fb8d4
		offscreen_cache_register_callbacks(instance->update);
Packit 1fb8d4
		palette_cache_register_callbacks(instance->update);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (wfc->fullscreen)
Packit 1fb8d4
		floatbar_window_create(wfc);
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL wf_post_disconnect(freerdp* instance)
Packit 1fb8d4
{
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static CREDUI_INFOA wfUiInfo =
Packit 1fb8d4
{
Packit 1fb8d4
	sizeof(CREDUI_INFOA),
Packit 1fb8d4
	NULL,
Packit 1fb8d4
	"Enter your credentials",
Packit 1fb8d4
	"Remote Desktop Security",
Packit 1fb8d4
	NULL
Packit 1fb8d4
};
Packit 1fb8d4
Packit 1fb8d4
static BOOL wf_authenticate_raw(freerdp* instance, const char* title,
Packit 1fb8d4
                                char** username, char** password, char** domain)
Packit 1fb8d4
{
Packit 1fb8d4
	BOOL fSave;
Packit 1fb8d4
	DWORD status;
Packit 1fb8d4
	DWORD dwFlags;
Packit 1fb8d4
	char UserName[CREDUI_MAX_USERNAME_LENGTH + 1];
Packit 1fb8d4
	char Password[CREDUI_MAX_PASSWORD_LENGTH + 1];
Packit 1fb8d4
	char User[CREDUI_MAX_USERNAME_LENGTH + 1];
Packit 1fb8d4
	char Domain[CREDUI_MAX_DOMAIN_TARGET_LENGTH + 1];
Packit 1fb8d4
	fSave = FALSE;
Packit 1fb8d4
	ZeroMemory(UserName, sizeof(UserName));
Packit 1fb8d4
	ZeroMemory(Password, sizeof(Password));
Packit 1fb8d4
	dwFlags = CREDUI_FLAGS_DO_NOT_PERSIST | CREDUI_FLAGS_EXCLUDE_CERTIFICATES;
Packit 1fb8d4
	status = CredUIPromptForCredentialsA(&wfUiInfo, title, NULL, 0,
Packit 1fb8d4
	                                     UserName, CREDUI_MAX_USERNAME_LENGTH + 1,
Packit 1fb8d4
	                                     Password, CREDUI_MAX_PASSWORD_LENGTH + 1, &fSave, dwFlags);
Packit 1fb8d4
Packit 1fb8d4
	if (status != NO_ERROR)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "CredUIPromptForCredentials unexpected status: 0x%08lX", status);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	ZeroMemory(User, sizeof(User));
Packit 1fb8d4
	ZeroMemory(Domain, sizeof(Domain));
Packit 1fb8d4
	status = CredUIParseUserNameA(UserName, User, sizeof(User), Domain,
Packit 1fb8d4
	                              sizeof(Domain));
Packit 1fb8d4
	//WLog_ERR(TAG, "User: %s Domain: %s Password: %s", User, Domain, Password);
Packit 1fb8d4
	*username = _strdup(User);
Packit 1fb8d4
Packit 1fb8d4
	if (!(*username))
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "strdup failed", status);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (strlen(Domain) > 0)
Packit 1fb8d4
		*domain = _strdup(Domain);
Packit 1fb8d4
	else
Packit 1fb8d4
		*domain = _strdup("\0");
Packit 1fb8d4
Packit 1fb8d4
	if (!(*domain))
Packit 1fb8d4
	{
Packit 1fb8d4
		free(*username);
Packit 1fb8d4
		WLog_ERR(TAG, "strdup failed", status);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	*password = _strdup(Password);
Packit 1fb8d4
Packit 1fb8d4
	if (!(*password))
Packit 1fb8d4
	{
Packit 1fb8d4
		free(*username);
Packit 1fb8d4
		free(*domain);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL wf_authenticate(freerdp* instance,
Packit 1fb8d4
                            char** username, char** password, char** domain)
Packit 1fb8d4
{
Packit 1fb8d4
	return wf_authenticate_raw(instance, instance->settings->ServerHostname,
Packit 1fb8d4
	                           username, password, domain);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL wf_gw_authenticate(freerdp* instance,
Packit 1fb8d4
                               char** username, char** password, char** domain)
Packit 1fb8d4
{
Packit 1fb8d4
	char tmp[MAX_PATH];
Packit 1fb8d4
	sprintf_s(tmp, sizeof(tmp), "Gateway %s", instance->settings->GatewayHostname);
Packit 1fb8d4
	return wf_authenticate_raw(instance, tmp, username, password, domain);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static DWORD wf_verify_certificate(freerdp* instance,
Packit 1fb8d4
                                   const char* common_name,
Packit 1fb8d4
                                   const char* subject,
Packit 1fb8d4
                                   const char* issuer,
Packit 1fb8d4
                                   const char* fingerprint,
Packit 1fb8d4
                                   BOOL host_mismatch)
Packit 1fb8d4
{
Packit 1fb8d4
#if 0
Packit 1fb8d4
	DWORD mode;
Packit 1fb8d4
	int read_size;
Packit 1fb8d4
	DWORD read_count;
Packit 1fb8d4
	TCHAR answer[2];
Packit 1fb8d4
	TCHAR* read_buffer;
Packit 1fb8d4
	HANDLE input_handle;
Packit 1fb8d4
#endif
Packit 1fb8d4
	WLog_INFO(TAG, "Certificate details:");
Packit 1fb8d4
	WLog_INFO(TAG, "\tCommonName: %s", common_name);
Packit 1fb8d4
	WLog_INFO(TAG, "\tSubject: %s", subject);
Packit 1fb8d4
	WLog_INFO(TAG, "\tIssuer: %s", issuer);
Packit 1fb8d4
	WLog_INFO(TAG, "\tThumbprint: %s", fingerprint);
Packit 1fb8d4
	WLog_INFO(TAG, "\tHostMismatch: %s", host_mismatch ? "Yes" : "No");
Packit 1fb8d4
	WLog_INFO(TAG,
Packit 1fb8d4
	          "The above X.509 certificate could not be verified, possibly because you do not have "
Packit 1fb8d4
	          "the CA certificate in your certificate store, or the certificate has expired. "
Packit 1fb8d4
	          "Please look at the OpenSSL documentation on how to add a private CA to the store.\n");
Packit 1fb8d4
	/* TODO: ask for user validation */
Packit 1fb8d4
#if 0
Packit 1fb8d4
	input_handle = GetStdHandle(STD_INPUT_HANDLE);
Packit 1fb8d4
	GetConsoleMode(input_handle, &mode);
Packit 1fb8d4
	mode |= ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT;
Packit 1fb8d4
	SetConsoleMode(input_handle, mode);
Packit 1fb8d4
#endif
Packit 1fb8d4
	/* return 1 to accept and store a certificate, 2 to accept
Packit 1fb8d4
	 * a certificate only for this session, 0 otherwise */
Packit 1fb8d4
	return 2;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static DWORD wf_verify_changed_certificate(freerdp* instance,
Packit 1fb8d4
        const char* common_name,
Packit 1fb8d4
        const char* subject, const char* issuer,
Packit 1fb8d4
        const char* fingerprint,
Packit 1fb8d4
        const char* old_subject, const char* old_issuer,
Packit 1fb8d4
        const char* old_fingerprint)
Packit 1fb8d4
{
Packit 1fb8d4
	WLog_ERR(TAG, "!!! Certificate has changed !!!");
Packit 1fb8d4
	WLog_ERR(TAG, "New Certificate details:");
Packit 1fb8d4
	WLog_ERR(TAG, "\tSubject: %s", subject);
Packit 1fb8d4
	WLog_ERR(TAG, "\tIssuer: %s", issuer);
Packit 1fb8d4
	WLog_ERR(TAG, "\tThumbprint: %s", fingerprint);
Packit 1fb8d4
	WLog_ERR(TAG, "Old Certificate details:");
Packit 1fb8d4
	WLog_ERR(TAG, "\tSubject: %s", old_subject);
Packit 1fb8d4
	WLog_ERR(TAG, "\tIssuer: %s", old_issuer);
Packit 1fb8d4
	WLog_ERR(TAG, "\tThumbprint: %s", old_fingerprint);
Packit 1fb8d4
	WLog_ERR(TAG,
Packit 1fb8d4
	         "The above X.509 certificate does not match the certificate used for previous connections. "
Packit 1fb8d4
	         "This may indicate that the certificate has been tampered with."
Packit 1fb8d4
	         "Please contact the administrator of the RDP server and clarify.");
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static DWORD WINAPI wf_input_thread(LPVOID arg)
Packit 1fb8d4
{
Packit 1fb8d4
	int status;
Packit 1fb8d4
	wMessage message;
Packit 1fb8d4
	wMessageQueue* queue;
Packit 1fb8d4
	freerdp* instance = (freerdp*) arg;
Packit 1fb8d4
	assert(NULL != instance);
Packit 1fb8d4
	status = 1;
Packit 1fb8d4
	queue = freerdp_get_message_queue(instance, FREERDP_INPUT_MESSAGE_QUEUE);
Packit 1fb8d4
Packit 1fb8d4
	while (MessageQueue_Wait(queue))
Packit 1fb8d4
	{
Packit 1fb8d4
		while (MessageQueue_Peek(queue, &message, TRUE))
Packit 1fb8d4
		{
Packit 1fb8d4
			status = freerdp_message_queue_process_message(instance,
Packit 1fb8d4
			         FREERDP_INPUT_MESSAGE_QUEUE, &message);
Packit 1fb8d4
Packit 1fb8d4
			if (!status)
Packit 1fb8d4
				break;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (!status)
Packit 1fb8d4
			break;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	ExitThread(0);
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static DWORD WINAPI wf_client_thread(LPVOID lpParam)
Packit 1fb8d4
{
Packit 1fb8d4
	MSG msg;
Packit 1fb8d4
	int width;
Packit 1fb8d4
	int height;
Packit 1fb8d4
	BOOL msg_ret;
Packit 1fb8d4
	int quit_msg;
Packit 1fb8d4
	DWORD nCount;
Packit 1fb8d4
	DWORD error;
Packit 1fb8d4
	HANDLE handles[64];
Packit 1fb8d4
	wfContext* wfc;
Packit 1fb8d4
	freerdp* instance;
Packit 1fb8d4
	rdpContext* context;
Packit 1fb8d4
	rdpChannels* channels;
Packit 1fb8d4
	rdpSettings* settings;
Packit 1fb8d4
	BOOL async_input;
Packit 1fb8d4
	HANDLE input_thread;
Packit 1fb8d4
	instance = (freerdp*) lpParam;
Packit 1fb8d4
	context = instance->context;
Packit 1fb8d4
	wfc = (wfContext*) instance->context;
Packit 1fb8d4
Packit 1fb8d4
	if (!freerdp_connect(instance))
Packit 1fb8d4
		goto end;
Packit 1fb8d4
Packit 1fb8d4
	channels = instance->context->channels;
Packit 1fb8d4
	settings = instance->context->settings;
Packit 1fb8d4
	async_input = settings->AsyncInput;
Packit 1fb8d4
Packit 1fb8d4
	if (async_input)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (!(input_thread = CreateThread(NULL, 0, wf_input_thread,
Packit 1fb8d4
		                                  instance, 0, NULL)))
Packit 1fb8d4
		{
Packit 1fb8d4
			WLog_ERR(TAG, "Failed to create async input thread.");
Packit 1fb8d4
			goto disconnect;
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	while (1)
Packit 1fb8d4
	{
Packit 1fb8d4
		nCount = 0;
Packit 1fb8d4
Packit 1fb8d4
		if (freerdp_focus_required(instance))
Packit 1fb8d4
		{
Packit 1fb8d4
			wf_event_focus_in(wfc);
Packit 1fb8d4
			wf_event_focus_in(wfc);
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		{
Packit 1fb8d4
			DWORD tmp = freerdp_get_event_handles(context, &handles[nCount], 64 - nCount);
Packit 1fb8d4
Packit 1fb8d4
			if (tmp == 0)
Packit 1fb8d4
			{
Packit 1fb8d4
				WLog_ERR(TAG, "freerdp_get_event_handles failed");
Packit 1fb8d4
				break;
Packit 1fb8d4
			}
Packit 1fb8d4
Packit 1fb8d4
			nCount += tmp;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (MsgWaitForMultipleObjects(nCount, handles, FALSE, 1000,
Packit 1fb8d4
		                              QS_ALLINPUT) == WAIT_FAILED)
Packit 1fb8d4
		{
Packit 1fb8d4
			WLog_ERR(TAG, "wfreerdp_run: WaitForMultipleObjects failed: 0x%08lX",
Packit 1fb8d4
			         GetLastError());
Packit 1fb8d4
			break;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		{
Packit 1fb8d4
			if (!freerdp_check_event_handles(context))
Packit 1fb8d4
			{
Packit 1fb8d4
				if (client_auto_reconnect(instance))
Packit 1fb8d4
					continue;
Packit 1fb8d4
Packit 1fb8d4
				WLog_ERR(TAG, "Failed to check FreeRDP file descriptor");
Packit 1fb8d4
				break;
Packit 1fb8d4
			}
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (freerdp_shall_disconnect(instance))
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		quit_msg = FALSE;
Packit 1fb8d4
Packit 1fb8d4
		while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
Packit 1fb8d4
		{
Packit 1fb8d4
			msg_ret = GetMessage(&msg, NULL, 0, 0);
Packit 1fb8d4
Packit 1fb8d4
			if (instance->settings->EmbeddedWindow)
Packit 1fb8d4
			{
Packit 1fb8d4
				if ((msg.message == WM_SETFOCUS) && (msg.lParam == 1))
Packit 1fb8d4
				{
Packit 1fb8d4
					PostMessage(wfc->hwnd, WM_SETFOCUS, 0, 0);
Packit 1fb8d4
				}
Packit 1fb8d4
				else if ((msg.message == WM_KILLFOCUS) && (msg.lParam == 1))
Packit 1fb8d4
				{
Packit 1fb8d4
					PostMessage(wfc->hwnd, WM_KILLFOCUS, 0, 0);
Packit 1fb8d4
				}
Packit 1fb8d4
			}
Packit 1fb8d4
Packit 1fb8d4
			if (msg.message == WM_SIZE)
Packit 1fb8d4
			{
Packit 1fb8d4
				width = LOWORD(msg.lParam);
Packit 1fb8d4
				height = HIWORD(msg.lParam);
Packit 1fb8d4
				SetWindowPos(wfc->hwnd, HWND_TOP, 0, 0, width, height, SWP_FRAMECHANGED);
Packit 1fb8d4
			}
Packit 1fb8d4
Packit 1fb8d4
			if ((msg_ret == 0) || (msg_ret == -1))
Packit 1fb8d4
			{
Packit 1fb8d4
				quit_msg = TRUE;
Packit 1fb8d4
				break;
Packit 1fb8d4
			}
Packit 1fb8d4
Packit 1fb8d4
			TranslateMessage(&msg;;
Packit 1fb8d4
			DispatchMessage(&msg;;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (quit_msg)
Packit 1fb8d4
			break;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	/* cleanup */
Packit 1fb8d4
	if (async_input)
Packit 1fb8d4
	{
Packit 1fb8d4
		wMessageQueue* input_queue;
Packit 1fb8d4
		input_queue = freerdp_get_message_queue(instance, FREERDP_INPUT_MESSAGE_QUEUE);
Packit 1fb8d4
Packit 1fb8d4
		if (MessageQueue_PostQuit(input_queue, 0))
Packit 1fb8d4
			WaitForSingleObject(input_thread, INFINITE);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
disconnect:
Packit 1fb8d4
	freerdp_disconnect(instance);
Packit 1fb8d4
Packit 1fb8d4
	if (async_input)
Packit 1fb8d4
		CloseHandle(input_thread);
Packit 1fb8d4
Packit 1fb8d4
end:
Packit 1fb8d4
	error = freerdp_get_last_error(instance->context);
Packit 1fb8d4
	WLog_DBG(TAG, "Main thread exited with %" PRIu32, error);
Packit 1fb8d4
	ExitThread(error);
Packit 1fb8d4
	return error;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static DWORD WINAPI wf_keyboard_thread(LPVOID lpParam)
Packit 1fb8d4
{
Packit 1fb8d4
	MSG msg;
Packit 1fb8d4
	BOOL status;
Packit 1fb8d4
	wfContext* wfc;
Packit 1fb8d4
	HHOOK hook_handle;
Packit 1fb8d4
	wfc = (wfContext*) lpParam;
Packit 1fb8d4
	assert(NULL != wfc);
Packit 1fb8d4
	hook_handle = SetWindowsHookEx(WH_KEYBOARD_LL, wf_ll_kbd_proc, wfc->hInstance,
Packit 1fb8d4
	                               0);
Packit 1fb8d4
Packit 1fb8d4
	if (hook_handle)
Packit 1fb8d4
	{
Packit 1fb8d4
		while ((status = GetMessage(&msg, NULL, 0, 0)) != 0)
Packit 1fb8d4
		{
Packit 1fb8d4
			if (status == -1)
Packit 1fb8d4
			{
Packit 1fb8d4
				WLog_ERR(TAG, "keyboard thread error getting message");
Packit 1fb8d4
				break;
Packit 1fb8d4
			}
Packit 1fb8d4
			else
Packit 1fb8d4
			{
Packit 1fb8d4
				TranslateMessage(&msg;;
Packit 1fb8d4
				DispatchMessage(&msg;;
Packit 1fb8d4
			}
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		UnhookWindowsHookEx(hook_handle);
Packit 1fb8d4
	}
Packit 1fb8d4
	else
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "failed to install keyboard hook");
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	WLog_DBG(TAG, "Keyboard thread exited.");
Packit 1fb8d4
	ExitThread(0);
Packit 1fb8d4
	return (DWORD) NULL;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static rdpSettings* freerdp_client_get_settings(wfContext* wfc)
Packit 1fb8d4
{
Packit 1fb8d4
	return wfc->context.settings;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static int freerdp_client_focus_in(wfContext* wfc)
Packit 1fb8d4
{
Packit 1fb8d4
	PostThreadMessage(wfc->mainThreadId, WM_SETFOCUS, 0, 1);
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static int freerdp_client_focus_out(wfContext* wfc)
Packit 1fb8d4
{
Packit 1fb8d4
	PostThreadMessage(wfc->mainThreadId, WM_KILLFOCUS, 0, 1);
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static int freerdp_client_set_window_size(wfContext* wfc, int width, int height)
Packit 1fb8d4
{
Packit 1fb8d4
	WLog_DBG(TAG,  "freerdp_client_set_window_size %d, %d", width, height);
Packit 1fb8d4
Packit 1fb8d4
	if ((width != wfc->client_width) || (height != wfc->client_height))
Packit 1fb8d4
	{
Packit 1fb8d4
		PostThreadMessage(wfc->mainThreadId, WM_SIZE, SIZE_RESTORED,
Packit 1fb8d4
		                  ((UINT) height << 16) | (UINT) width);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
void wf_size_scrollbars(wfContext* wfc, UINT32 client_width,
Packit 1fb8d4
                        UINT32 client_height)
Packit 1fb8d4
{
Packit 1fb8d4
	if (wfc->disablewindowtracking)
Packit 1fb8d4
		return;
Packit 1fb8d4
Packit 1fb8d4
	// prevent infinite message loop
Packit 1fb8d4
	wfc->disablewindowtracking = TRUE;
Packit 1fb8d4
Packit 1fb8d4
	if (wfc->context.settings->SmartSizing)
Packit 1fb8d4
	{
Packit 1fb8d4
		wfc->xCurrentScroll = 0;
Packit 1fb8d4
		wfc->yCurrentScroll = 0;
Packit 1fb8d4
Packit 1fb8d4
		if (wfc->xScrollVisible || wfc->yScrollVisible)
Packit 1fb8d4
		{
Packit 1fb8d4
			if (ShowScrollBar(wfc->hwnd, SB_BOTH, FALSE))
Packit 1fb8d4
			{
Packit 1fb8d4
				wfc->xScrollVisible = FALSE;
Packit 1fb8d4
				wfc->yScrollVisible = FALSE;
Packit 1fb8d4
			}
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
	else
Packit 1fb8d4
	{
Packit 1fb8d4
		SCROLLINFO si;
Packit 1fb8d4
		BOOL horiz = wfc->xScrollVisible;
Packit 1fb8d4
		BOOL vert = wfc->yScrollVisible;;
Packit 1fb8d4
Packit 1fb8d4
		if (!horiz && client_width < wfc->context.settings->DesktopWidth)
Packit 1fb8d4
		{
Packit 1fb8d4
			horiz = TRUE;
Packit 1fb8d4
		}
Packit 1fb8d4
		else if (horiz
Packit 1fb8d4
		         && client_width >=
Packit 1fb8d4
		         wfc->context.settings->DesktopWidth/* - GetSystemMetrics(SM_CXVSCROLL)*/)
Packit 1fb8d4
		{
Packit 1fb8d4
			horiz = FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (!vert && client_height < wfc->context.settings->DesktopHeight)
Packit 1fb8d4
		{
Packit 1fb8d4
			vert = TRUE;
Packit 1fb8d4
		}
Packit 1fb8d4
		else if (vert
Packit 1fb8d4
		         && client_height >=
Packit 1fb8d4
		         wfc->context.settings->DesktopHeight/* - GetSystemMetrics(SM_CYHSCROLL)*/)
Packit 1fb8d4
		{
Packit 1fb8d4
			vert = FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (horiz == vert && (horiz != wfc->xScrollVisible
Packit 1fb8d4
		                      && vert != wfc->yScrollVisible))
Packit 1fb8d4
		{
Packit 1fb8d4
			if (ShowScrollBar(wfc->hwnd, SB_BOTH, horiz))
Packit 1fb8d4
			{
Packit 1fb8d4
				wfc->xScrollVisible = horiz;
Packit 1fb8d4
				wfc->yScrollVisible = vert;
Packit 1fb8d4
			}
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (horiz != wfc->xScrollVisible)
Packit 1fb8d4
		{
Packit 1fb8d4
			if (ShowScrollBar(wfc->hwnd, SB_HORZ, horiz))
Packit 1fb8d4
			{
Packit 1fb8d4
				wfc->xScrollVisible = horiz;
Packit 1fb8d4
			}
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (vert != wfc->yScrollVisible)
Packit 1fb8d4
		{
Packit 1fb8d4
			if (ShowScrollBar(wfc->hwnd, SB_VERT, vert))
Packit 1fb8d4
			{
Packit 1fb8d4
				wfc->yScrollVisible = vert;
Packit 1fb8d4
			}
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (horiz)
Packit 1fb8d4
		{
Packit 1fb8d4
			// The horizontal scrolling range is defined by
Packit 1fb8d4
			// (bitmap_width) - (client_width). The current horizontal
Packit 1fb8d4
			// scroll value remains within the horizontal scrolling range.
Packit 1fb8d4
			wfc->xMaxScroll = MAX(wfc->context.settings->DesktopWidth - client_width, 0);
Packit 1fb8d4
			wfc->xCurrentScroll = MIN(wfc->xCurrentScroll, wfc->xMaxScroll);
Packit 1fb8d4
			si.cbSize = sizeof(si);
Packit 1fb8d4
			si.fMask  = SIF_RANGE | SIF_PAGE | SIF_POS;
Packit 1fb8d4
			si.nMin   = wfc->xMinScroll;
Packit 1fb8d4
			si.nMax   = wfc->context.settings->DesktopWidth;
Packit 1fb8d4
			si.nPage  = client_width;
Packit 1fb8d4
			si.nPos   = wfc->xCurrentScroll;
Packit 1fb8d4
			SetScrollInfo(wfc->hwnd, SB_HORZ, &si, TRUE);
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (vert)
Packit 1fb8d4
		{
Packit 1fb8d4
			// The vertical scrolling range is defined by
Packit 1fb8d4
			// (bitmap_height) - (client_height). The current vertical
Packit 1fb8d4
			// scroll value remains within the vertical scrolling range.
Packit 1fb8d4
			wfc->yMaxScroll = MAX(wfc->context.settings->DesktopHeight - client_height,
Packit 1fb8d4
			                      0);
Packit 1fb8d4
			wfc->yCurrentScroll = MIN(wfc->yCurrentScroll, wfc->yMaxScroll);
Packit 1fb8d4
			si.cbSize = sizeof(si);
Packit 1fb8d4
			si.fMask  = SIF_RANGE | SIF_PAGE | SIF_POS;
Packit 1fb8d4
			si.nMin   = wfc->yMinScroll;
Packit 1fb8d4
			si.nMax   = wfc->context.settings->DesktopHeight;
Packit 1fb8d4
			si.nPage  = client_height;
Packit 1fb8d4
			si.nPos   = wfc->yCurrentScroll;
Packit 1fb8d4
			SetScrollInfo(wfc->hwnd, SB_VERT, &si, TRUE);
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	wfc->disablewindowtracking = FALSE;
Packit 1fb8d4
	wf_update_canvas_diff(wfc);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL wfreerdp_client_global_init(void)
Packit 1fb8d4
{
Packit 1fb8d4
	WSADATA wsaData;
Packit 1fb8d4
Packit 1fb8d4
	if (!getenv("HOME"))
Packit 1fb8d4
	{
Packit 1fb8d4
		char home[MAX_PATH * 2] = "HOME=";
Packit 1fb8d4
		strcat(home, getenv("HOMEDRIVE"));
Packit 1fb8d4
		strcat(home, getenv("HOMEPATH"));
Packit 1fb8d4
		_putenv(home);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	WSAStartup(0x101, &wsaData);
Packit 1fb8d4
#if defined(WITH_DEBUG) || defined(_DEBUG)
Packit 1fb8d4
	wf_create_console();
Packit 1fb8d4
#endif
Packit 1fb8d4
	freerdp_register_addin_provider(freerdp_channels_load_static_addin_entry, 0);
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static void wfreerdp_client_global_uninit(void)
Packit 1fb8d4
{
Packit 1fb8d4
	WSACleanup();
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL wfreerdp_client_new(freerdp* instance, rdpContext* context)
Packit 1fb8d4
{
Packit 1fb8d4
	if (!(wfreerdp_client_global_init()))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	instance->PreConnect = wf_pre_connect;
Packit 1fb8d4
	instance->PostConnect = wf_post_connect;
Packit 1fb8d4
	instance->PostDisconnect = wf_post_disconnect;
Packit 1fb8d4
	instance->Authenticate = wf_authenticate;
Packit 1fb8d4
	instance->GatewayAuthenticate = wf_gw_authenticate;
Packit 1fb8d4
	instance->VerifyCertificate = wf_verify_certificate;
Packit 1fb8d4
	instance->VerifyChangedCertificate = wf_verify_changed_certificate;
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static void wfreerdp_client_free(freerdp* instance, rdpContext* context)
Packit 1fb8d4
{
Packit 1fb8d4
	if (!context)
Packit 1fb8d4
		return;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static int wfreerdp_client_start(rdpContext* context)
Packit 1fb8d4
{
Packit 1fb8d4
	HWND hWndParent;
Packit 1fb8d4
	HINSTANCE hInstance;
Packit 1fb8d4
	wfContext* wfc = (wfContext*) context;
Packit 1fb8d4
	freerdp* instance = context->instance;
Packit 1fb8d4
	hInstance = GetModuleHandle(NULL);
Packit 1fb8d4
	hWndParent = (HWND) instance->settings->ParentWindowId;
Packit 1fb8d4
	instance->settings->EmbeddedWindow = (hWndParent) ? TRUE : FALSE;
Packit 1fb8d4
	wfc->hWndParent = hWndParent;
Packit 1fb8d4
	wfc->hInstance = hInstance;
Packit 1fb8d4
	wfc->cursor = LoadCursor(NULL, IDC_ARROW);
Packit 1fb8d4
	wfc->icon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON1));
Packit 1fb8d4
	wfc->wndClassName = _tcsdup(_T("FreeRDP"));
Packit 1fb8d4
	wfc->wndClass.cbSize = sizeof(WNDCLASSEX);
Packit 1fb8d4
	wfc->wndClass.style = CS_HREDRAW | CS_VREDRAW;
Packit 1fb8d4
	wfc->wndClass.lpfnWndProc = wf_event_proc;
Packit 1fb8d4
	wfc->wndClass.cbClsExtra = 0;
Packit 1fb8d4
	wfc->wndClass.cbWndExtra = 0;
Packit 1fb8d4
	wfc->wndClass.hCursor = wfc->cursor;
Packit 1fb8d4
	wfc->wndClass.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH);
Packit 1fb8d4
	wfc->wndClass.lpszMenuName = NULL;
Packit 1fb8d4
	wfc->wndClass.lpszClassName = wfc->wndClassName;
Packit 1fb8d4
	wfc->wndClass.hInstance = hInstance;
Packit 1fb8d4
	wfc->wndClass.hIcon = wfc->icon;
Packit 1fb8d4
	wfc->wndClass.hIconSm = wfc->icon;
Packit 1fb8d4
	RegisterClassEx(&(wfc->wndClass));
Packit 1fb8d4
	wfc->keyboardThread = CreateThread(NULL, 0, wf_keyboard_thread, (void*) wfc, 0,
Packit 1fb8d4
	                                   &wfc->keyboardThreadId);
Packit 1fb8d4
Packit 1fb8d4
	if (!wfc->keyboardThread)
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	wfc->thread = CreateThread(NULL, 0, wf_client_thread, (void*) instance, 0,
Packit 1fb8d4
	                           &wfc->mainThreadId);
Packit 1fb8d4
Packit 1fb8d4
	if (!wfc->thread)
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static int wfreerdp_client_stop(rdpContext* context)
Packit 1fb8d4
{
Packit 1fb8d4
	wfContext* wfc = (wfContext*) context;
Packit 1fb8d4
Packit 1fb8d4
	if (wfc->thread)
Packit 1fb8d4
	{
Packit 1fb8d4
		PostThreadMessage(wfc->mainThreadId, WM_QUIT, 0, 0);
Packit 1fb8d4
		WaitForSingleObject(wfc->thread, INFINITE);
Packit 1fb8d4
		CloseHandle(wfc->thread);
Packit 1fb8d4
		wfc->thread = NULL;
Packit 1fb8d4
		wfc->mainThreadId = 0;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (wfc->keyboardThread)
Packit 1fb8d4
	{
Packit 1fb8d4
		PostThreadMessage(wfc->keyboardThreadId, WM_QUIT, 0, 0);
Packit 1fb8d4
		WaitForSingleObject(wfc->keyboardThread, INFINITE);
Packit 1fb8d4
		CloseHandle(wfc->keyboardThread);
Packit 1fb8d4
		wfc->keyboardThread = NULL;
Packit 1fb8d4
		wfc->keyboardThreadId = 0;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
int RdpClientEntry(RDP_CLIENT_ENTRY_POINTS* pEntryPoints)
Packit 1fb8d4
{
Packit 1fb8d4
	pEntryPoints->Version = 1;
Packit 1fb8d4
	pEntryPoints->Size = sizeof(RDP_CLIENT_ENTRY_POINTS_V1);
Packit 1fb8d4
	pEntryPoints->GlobalInit = wfreerdp_client_global_init;
Packit 1fb8d4
	pEntryPoints->GlobalUninit = wfreerdp_client_global_uninit;
Packit 1fb8d4
	pEntryPoints->ContextSize = sizeof(wfContext);
Packit 1fb8d4
	pEntryPoints->ClientNew = wfreerdp_client_new;
Packit 1fb8d4
	pEntryPoints->ClientFree = wfreerdp_client_free;
Packit 1fb8d4
	pEntryPoints->ClientStart = wfreerdp_client_start;
Packit 1fb8d4
	pEntryPoints->ClientStop = wfreerdp_client_stop;
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}