Blame server/shadow/Win/win_shadow.c

Packit Service fa4841
/**
Packit Service fa4841
 * FreeRDP: A Remote Desktop Protocol Implementation
Packit Service fa4841
 *
Packit Service fa4841
 * Copyright 2011-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
Packit Service fa4841
 *
Packit Service fa4841
 * Licensed under the Apache License, Version 2.0 (the "License");
Packit Service fa4841
 * you may not use this file except in compliance with the License.
Packit Service fa4841
 * You may obtain a copy of the License at
Packit Service fa4841
 *
Packit Service fa4841
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit Service fa4841
 *
Packit Service fa4841
 * Unless required by applicable law or agreed to in writing, software
Packit Service fa4841
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit Service fa4841
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit Service fa4841
 * See the License for the specific language governing permissions and
Packit Service fa4841
 * limitations under the License.
Packit Service fa4841
 */
Packit Service fa4841
Packit Service b1ea74
#include <windows.h>
Packit Service b1ea74
Packit Service fa4841
#include <winpr/crt.h>
Packit Service fa4841
#include <winpr/synch.h>
Packit Service fa4841
#include <winpr/sysinfo.h>
Packit Service fa4841
Packit Service fa4841
#include <freerdp/log.h>
Packit Service fa4841
#include <freerdp/codec/color.h>
Packit Service fa4841
#include <freerdp/codec/region.h>
Packit Service fa4841
Packit Service fa4841
#include "win_shadow.h"
Packit Service fa4841
Packit Service fa4841
#define TAG SERVER_TAG("shadow.win")
Packit Service fa4841
Packit Service b1ea74
/* https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-mouse_event
Packit Service b1ea74
 * does not mention this flag is only supported if building for _WIN32_WINNT >= 0x0600
Packit Service b1ea74
 */
Packit Service b1ea74
#ifndef MOUSEEVENTF_HWHEEL
Packit Service b1ea74
#define MOUSEEVENTF_HWHEEL 0x1000
Packit Service b1ea74
#endif
Packit Service b1ea74
Packit Service b1ea74
static BOOL win_shadow_input_synchronize_event(rdpShadowSubsystem* subsystem,
Packit Service b1ea74
                                               rdpShadowClient* client, UINT32 flags)
Packit Service fa4841
{
Packit Service b1ea74
	WLog_WARN(TAG, "%s: TODO: Implement!", __FUNCTION__);
Packit Service b1ea74
	return TRUE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service b1ea74
static BOOL win_shadow_input_keyboard_event(rdpShadowSubsystem* subsystem, rdpShadowClient* client,
Packit Service b1ea74
                                            UINT16 flags, UINT16 code)
Packit Service fa4841
{
Packit Service b1ea74
	UINT rc;
Packit Service fa4841
	INPUT event;
Packit Service fa4841
	event.type = INPUT_KEYBOARD;
Packit Service fa4841
	event.ki.wVk = 0;
Packit Service fa4841
	event.ki.wScan = code;
Packit Service fa4841
	event.ki.dwFlags = KEYEVENTF_SCANCODE;
Packit Service fa4841
	event.ki.dwExtraInfo = 0;
Packit Service fa4841
	event.ki.time = 0;
Packit Service fa4841
Packit Service fa4841
	if (flags & KBD_FLAGS_RELEASE)
Packit Service fa4841
		event.ki.dwFlags |= KEYEVENTF_KEYUP;
Packit Service fa4841
Packit Service fa4841
	if (flags & KBD_FLAGS_EXTENDED)
Packit Service fa4841
		event.ki.dwFlags |= KEYEVENTF_EXTENDEDKEY;
Packit Service fa4841
Packit Service b1ea74
	rc = SendInput(1, &event, sizeof(INPUT));
Packit Service b1ea74
	if (rc == 0)
Packit Service b1ea74
		return FALSE;
Packit Service b1ea74
	return TRUE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service b1ea74
static BOOL win_shadow_input_unicode_keyboard_event(rdpShadowSubsystem* subsystem,
Packit Service b1ea74
                                                    rdpShadowClient* client, UINT16 flags,
Packit Service b1ea74
                                                    UINT16 code)
Packit Service fa4841
{
Packit Service b1ea74
	UINT rc;
Packit Service fa4841
	INPUT event;
Packit Service fa4841
	event.type = INPUT_KEYBOARD;
Packit Service fa4841
	event.ki.wVk = 0;
Packit Service fa4841
	event.ki.wScan = code;
Packit Service fa4841
	event.ki.dwFlags = KEYEVENTF_UNICODE;
Packit Service fa4841
	event.ki.dwExtraInfo = 0;
Packit Service fa4841
	event.ki.time = 0;
Packit Service fa4841
Packit Service fa4841
	if (flags & KBD_FLAGS_RELEASE)
Packit Service fa4841
		event.ki.dwFlags |= KEYEVENTF_KEYUP;
Packit Service fa4841
Packit Service b1ea74
	rc = SendInput(1, &event, sizeof(INPUT));
Packit Service b1ea74
	if (rc == 0)
Packit Service b1ea74
		return FALSE;
Packit Service b1ea74
	return TRUE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service b1ea74
static BOOL win_shadow_input_mouse_event(rdpShadowSubsystem* subsystem, rdpShadowClient* client,
Packit Service b1ea74
                                         UINT16 flags, UINT16 x, UINT16 y)
Packit Service fa4841
{
Packit Service b1ea74
	UINT rc = 1;
Packit Service fa4841
	INPUT event;
Packit Service fa4841
	float width;
Packit Service fa4841
	float height;
Packit Service fa4841
	ZeroMemory(&event, sizeof(INPUT));
Packit Service fa4841
	event.type = INPUT_MOUSE;
Packit Service fa4841
Packit Service b1ea74
	if (flags & (PTR_FLAGS_WHEEL | PTR_FLAGS_HWHEEL))
Packit Service fa4841
	{
Packit Service b1ea74
		if (flags & PTR_FLAGS_WHEEL)
Packit Service b1ea74
			event.mi.dwFlags = MOUSEEVENTF_WHEEL;
Packit Service b1ea74
		else
Packit Service b1ea74
			event.mi.dwFlags = MOUSEEVENTF_HWHEEL;
Packit Service fa4841
		event.mi.mouseData = flags & WheelRotationMask;
Packit Service fa4841
Packit Service fa4841
		if (flags & PTR_FLAGS_WHEEL_NEGATIVE)
Packit Service fa4841
			event.mi.mouseData *= -1;
Packit Service fa4841
Packit Service b1ea74
		rc = SendInput(1, &event, sizeof(INPUT));
Packit Service b1ea74
Packit Service b1ea74
		/* The build target is a system that did not support MOUSEEVENTF_HWHEEL
Packit Service b1ea74
		 * but it may run on newer systems supporting it.
Packit Service b1ea74
		 * Ignore the return value in these cases.
Packit Service b1ea74
		 */
Packit Service b1ea74
#if (_WIN32_WINNT < 0x0600)
Packit Service b1ea74
		if (flags & PTR_FLAGS_HWHEEL)
Packit Service b1ea74
			rc = 1;
Packit Service b1ea74
#endif
Packit Service fa4841
	}
Packit Service fa4841
	else
Packit Service fa4841
	{
Packit Service b1ea74
		width = (float)GetSystemMetrics(SM_CXSCREEN);
Packit Service b1ea74
		height = (float)GetSystemMetrics(SM_CYSCREEN);
Packit Service b1ea74
		event.mi.dx = (LONG)((float)x * (65535.0f / width));
Packit Service b1ea74
		event.mi.dy = (LONG)((float)y * (65535.0f / height));
Packit Service fa4841
		event.mi.dwFlags = MOUSEEVENTF_ABSOLUTE;
Packit Service fa4841
Packit Service fa4841
		if (flags & PTR_FLAGS_MOVE)
Packit Service fa4841
		{
Packit Service fa4841
			event.mi.dwFlags |= MOUSEEVENTF_MOVE;
Packit Service b1ea74
			rc = SendInput(1, &event, sizeof(INPUT));
Packit Service b1ea74
			if (rc == 0)
Packit Service b1ea74
				return FALSE;
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		event.mi.dwFlags = MOUSEEVENTF_ABSOLUTE;
Packit Service fa4841
Packit Service fa4841
		if (flags & PTR_FLAGS_BUTTON1)
Packit Service fa4841
		{
Packit Service fa4841
			if (flags & PTR_FLAGS_DOWN)
Packit Service fa4841
				event.mi.dwFlags |= MOUSEEVENTF_LEFTDOWN;
Packit Service fa4841
			else
Packit Service fa4841
				event.mi.dwFlags |= MOUSEEVENTF_LEFTUP;
Packit Service fa4841
Packit Service b1ea74
			rc = SendInput(1, &event, sizeof(INPUT));
Packit Service fa4841
		}
Packit Service fa4841
		else if (flags & PTR_FLAGS_BUTTON2)
Packit Service fa4841
		{
Packit Service fa4841
			if (flags & PTR_FLAGS_DOWN)
Packit Service fa4841
				event.mi.dwFlags |= MOUSEEVENTF_RIGHTDOWN;
Packit Service fa4841
			else
Packit Service fa4841
				event.mi.dwFlags |= MOUSEEVENTF_RIGHTUP;
Packit Service fa4841
Packit Service b1ea74
			rc = SendInput(1, &event, sizeof(INPUT));
Packit Service fa4841
		}
Packit Service fa4841
		else if (flags & PTR_FLAGS_BUTTON3)
Packit Service fa4841
		{
Packit Service fa4841
			if (flags & PTR_FLAGS_DOWN)
Packit Service fa4841
				event.mi.dwFlags |= MOUSEEVENTF_MIDDLEDOWN;
Packit Service fa4841
			else
Packit Service fa4841
				event.mi.dwFlags |= MOUSEEVENTF_MIDDLEUP;
Packit Service fa4841
Packit Service b1ea74
			rc = SendInput(1, &event, sizeof(INPUT));
Packit Service fa4841
		}
Packit Service fa4841
	}
Packit Service fa4841
Packit Service b1ea74
	if (rc == 0)
Packit Service b1ea74
		return FALSE;
Packit Service b1ea74
	return TRUE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service b1ea74
static BOOL win_shadow_input_extended_mouse_event(rdpShadowSubsystem* subsystem,
Packit Service b1ea74
                                                  rdpShadowClient* client, UINT16 flags, UINT16 x,
Packit Service b1ea74
                                                  UINT16 y)
Packit Service fa4841
{
Packit Service b1ea74
	UINT rc = 1;
Packit Service fa4841
	INPUT event;
Packit Service fa4841
	float width;
Packit Service fa4841
	float height;
Packit Service fa4841
	ZeroMemory(&event, sizeof(INPUT));
Packit Service fa4841
Packit Service fa4841
	if ((flags & PTR_XFLAGS_BUTTON1) || (flags & PTR_XFLAGS_BUTTON2))
Packit Service fa4841
	{
Packit Service fa4841
		event.type = INPUT_MOUSE;
Packit Service fa4841
Packit Service fa4841
		if (flags & PTR_FLAGS_MOVE)
Packit Service fa4841
		{
Packit Service b1ea74
			width = (float)GetSystemMetrics(SM_CXSCREEN);
Packit Service b1ea74
			height = (float)GetSystemMetrics(SM_CYSCREEN);
Packit Service b1ea74
			event.mi.dx = (LONG)((float)x * (65535.0f / width));
Packit Service b1ea74
			event.mi.dy = (LONG)((float)y * (65535.0f / height));
Packit Service fa4841
			event.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE;
Packit Service b1ea74
			rc = SendInput(1, &event, sizeof(INPUT));
Packit Service b1ea74
			if (rc == 0)
Packit Service b1ea74
				return FALSE;
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		event.mi.dx = event.mi.dy = event.mi.dwFlags = 0;
Packit Service fa4841
Packit Service fa4841
		if (flags & PTR_XFLAGS_DOWN)
Packit Service fa4841
			event.mi.dwFlags |= MOUSEEVENTF_XDOWN;
Packit Service fa4841
		else
Packit Service fa4841
			event.mi.dwFlags |= MOUSEEVENTF_XUP;
Packit Service fa4841
Packit Service fa4841
		if (flags & PTR_XFLAGS_BUTTON1)
Packit Service fa4841
			event.mi.mouseData = XBUTTON1;
Packit Service fa4841
		else if (flags & PTR_XFLAGS_BUTTON2)
Packit Service fa4841
			event.mi.mouseData = XBUTTON2;
Packit Service fa4841
Packit Service b1ea74
		rc = SendInput(1, &event, sizeof(INPUT));
Packit Service fa4841
	}
Packit Service fa4841
Packit Service b1ea74
	if (rc == 0)
Packit Service b1ea74
		return FALSE;
Packit Service b1ea74
	return TRUE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service b1ea74
static int win_shadow_invalidate_region(winShadowSubsystem* subsystem, int x, int y, int width,
Packit Service b1ea74
                                        int height)
Packit Service fa4841
{
Packit Service fa4841
	rdpShadowServer* server;
Packit Service fa4841
	rdpShadowSurface* surface;
Packit Service fa4841
	RECTANGLE_16 invalidRect;
Packit Service fa4841
	server = subsystem->base.server;
Packit Service fa4841
	surface = server->surface;
Packit Service fa4841
	invalidRect.left = x;
Packit Service fa4841
	invalidRect.top = y;
Packit Service fa4841
	invalidRect.right = x + width;
Packit Service fa4841
	invalidRect.bottom = y + height;
Packit Service fa4841
	EnterCriticalSection(&(surface->lock));
Packit Service b1ea74
	region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion), &invalidRect);
Packit Service fa4841
	LeaveCriticalSection(&(surface->lock));
Packit Service fa4841
	return 1;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static int win_shadow_surface_copy(winShadowSubsystem* subsystem)
Packit Service fa4841
{
Packit Service fa4841
	int x, y;
Packit Service fa4841
	int width;
Packit Service fa4841
	int height;
Packit Service fa4841
	int count;
Packit Service fa4841
	int status = 1;
Packit Service fa4841
	int nDstStep = 0;
Packit Service fa4841
	DWORD DstFormat;
Packit Service fa4841
	BYTE* pDstData = NULL;
Packit Service fa4841
	rdpShadowServer* server;
Packit Service fa4841
	rdpShadowSurface* surface;
Packit Service fa4841
	RECTANGLE_16 surfaceRect;
Packit Service fa4841
	RECTANGLE_16 invalidRect;
Packit Service fa4841
	const RECTANGLE_16* extents;
Packit Service fa4841
	server = subsystem->base.server;
Packit Service fa4841
	surface = server->surface;
Packit Service fa4841
Packit Service fa4841
	if (ArrayList_Count(server->clients) < 1)
Packit Service fa4841
		return 1;
Packit Service fa4841
Packit Service fa4841
	surfaceRect.left = surface->x;
Packit Service fa4841
	surfaceRect.top = surface->y;
Packit Service fa4841
	surfaceRect.right = surface->x + surface->width;
Packit Service fa4841
	surfaceRect.bottom = surface->y + surface->height;
Packit Service b1ea74
	region16_intersect_rect(&(surface->invalidRegion), &(surface->invalidRegion), &surfaceRect);
Packit Service fa4841
Packit Service fa4841
	if (region16_is_empty(&(surface->invalidRegion)))
Packit Service fa4841
		return 1;
Packit Service fa4841
Packit Service fa4841
	extents = region16_extents(&(surface->invalidRegion));
Packit Service fa4841
	CopyMemory(&invalidRect, extents, sizeof(RECTANGLE_16));
Packit Service fa4841
	shadow_capture_align_clip_rect(&invalidRect, &surfaceRect);
Packit Service fa4841
	x = invalidRect.left;
Packit Service fa4841
	y = invalidRect.top;
Packit Service fa4841
	width = invalidRect.right - invalidRect.left;
Packit Service fa4841
	height = invalidRect.bottom - invalidRect.top;
Packit Service fa4841
Packit Service fa4841
	if (0)
Packit Service fa4841
	{
Packit Service fa4841
		x = 0;
Packit Service fa4841
		y = 0;
Packit Service fa4841
		width = surface->width;
Packit Service fa4841
		height = surface->height;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service b1ea74
	WLog_INFO(TAG, "SurfaceCopy x: %d y: %d width: %d height: %d right: %d bottom: %d", x, y, width,
Packit Service b1ea74
	          height, x + width, y + height);
Packit Service fa4841
#if defined(WITH_WDS_API)
Packit Service fa4841
	{
Packit Service fa4841
		rdpGdi* gdi;
Packit Service fa4841
		shwContext* shw;
Packit Service fa4841
		rdpContext* context;
Packit Service fa4841
		shw = subsystem->shw;
Packit Service fa4841
		context = &shw->context;
Packit Service fa4841
		gdi = context->gdi;
Packit Service fa4841
		pDstData = gdi->primary_buffer;
Packit Service fa4841
		nDstStep = gdi->width * 4;
Packit Service fa4841
		DstFormat = gdi->dstFormat;
Packit Service fa4841
	}
Packit Service fa4841
#elif defined(WITH_DXGI_1_2)
Packit Service fa4841
	DstFormat = PIXEL_FORMAT_BGRX32;
Packit Service b1ea74
	status = win_shadow_dxgi_fetch_frame_data(subsystem, &pDstData, &nDstStep, x, y, width, height);
Packit Service fa4841
#endif
Packit Service fa4841
Packit Service fa4841
	if (status <= 0)
Packit Service fa4841
		return status;
Packit Service fa4841
Packit Service b1ea74
	if (!freerdp_image_copy(surface->data, surface->format, surface->scanline, x, y, width, height,
Packit Service fa4841
	                        pDstData, DstFormat, nDstStep, x, y, NULL, FREERDP_FLIP_NONE))
Packit Service fa4841
		return ERROR_INTERNAL_ERROR;
Packit Service fa4841
Packit Service fa4841
	ArrayList_Lock(server->clients);
Packit Service fa4841
	count = ArrayList_Count(server->clients);
Packit Service fa4841
	shadow_subsystem_frame_update(&subsystem->base);
Packit Service fa4841
	ArrayList_Unlock(server->clients);
Packit Service fa4841
	region16_clear(&(surface->invalidRegion));
Packit Service fa4841
	return 1;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
#if defined(WITH_WDS_API)
Packit Service fa4841
Packit Service fa4841
static DWORD WINAPI win_shadow_subsystem_thread(LPVOID arg)
Packit Service fa4841
{
Packit Service fa4841
	winShadowSubsystem* subsystem = (winShadowSubsystem*)arg;
Packit Service fa4841
	DWORD status;
Packit Service fa4841
	DWORD nCount;
Packit Service fa4841
	HANDLE events[32];
Packit Service fa4841
	HANDLE StopEvent;
Packit Service fa4841
	StopEvent = subsystem->base.server->StopEvent;
Packit Service fa4841
	nCount = 0;
Packit Service fa4841
	events[nCount++] = StopEvent;
Packit Service fa4841
	events[nCount++] = subsystem->RdpUpdateEnterEvent;
Packit Service fa4841
Packit Service fa4841
	while (1)
Packit Service fa4841
	{
Packit Service fa4841
		status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
Packit Service fa4841
Packit Service fa4841
		if (WaitForSingleObject(StopEvent, 0) == WAIT_OBJECT_0)
Packit Service fa4841
		{
Packit Service fa4841
			break;
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		if (WaitForSingleObject(subsystem->RdpUpdateEnterEvent, 0) == WAIT_OBJECT_0)
Packit Service fa4841
		{
Packit Service fa4841
			win_shadow_surface_copy(subsystem);
Packit Service fa4841
			ResetEvent(subsystem->RdpUpdateEnterEvent);
Packit Service fa4841
			SetEvent(subsystem->RdpUpdateLeaveEvent);
Packit Service fa4841
		}
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	ExitThread(0);
Packit Service fa4841
	return 0;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
#elif defined(WITH_DXGI_1_2)
Packit Service fa4841
Packit Service fa4841
static DWORD WINAPI win_shadow_subsystem_thread(LPVOID arg)
Packit Service fa4841
{
Packit Service fa4841
	winShadowSubsystem* subsystem = (winShadowSubsystem*)arg;
Packit Service fa4841
	int fps;
Packit Service fa4841
	DWORD status;
Packit Service fa4841
	DWORD nCount;
Packit Service fa4841
	UINT64 cTime;
Packit Service fa4841
	DWORD dwTimeout;
Packit Service fa4841
	DWORD dwInterval;
Packit Service fa4841
	UINT64 frameTime;
Packit Service fa4841
	HANDLE events[32];
Packit Service fa4841
	HANDLE StopEvent;
Packit Service fa4841
	StopEvent = subsystem->server->StopEvent;
Packit Service fa4841
	nCount = 0;
Packit Service fa4841
	events[nCount++] = StopEvent;
Packit Service fa4841
	fps = 16;
Packit Service fa4841
	dwInterval = 1000 / fps;
Packit Service fa4841
	frameTime = GetTickCount64() + dwInterval;
Packit Service fa4841
Packit Service fa4841
	while (1)
Packit Service fa4841
	{
Packit Service fa4841
		dwTimeout = INFINITE;
Packit Service fa4841
		cTime = GetTickCount64();
Packit Service fa4841
		dwTimeout = (DWORD)((cTime > frameTime) ? 0 : frameTime - cTime);
Packit Service fa4841
		status = WaitForMultipleObjects(nCount, events, FALSE, dwTimeout);
Packit Service fa4841
Packit Service fa4841
		if (WaitForSingleObject(StopEvent, 0) == WAIT_OBJECT_0)
Packit Service fa4841
		{
Packit Service fa4841
			break;
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		if ((status == WAIT_TIMEOUT) || (GetTickCount64() > frameTime))
Packit Service fa4841
		{
Packit Service fa4841
			int dxgi_status;
Packit Service fa4841
			dxgi_status = win_shadow_dxgi_get_next_frame(subsystem);
Packit Service fa4841
Packit Service fa4841
			if (dxgi_status > 0)
Packit Service fa4841
				dxgi_status = win_shadow_dxgi_get_invalid_region(subsystem);
Packit Service fa4841
Packit Service fa4841
			if (dxgi_status > 0)
Packit Service fa4841
				win_shadow_surface_copy(subsystem);
Packit Service fa4841
Packit Service fa4841
			dwInterval = 1000 / fps;
Packit Service fa4841
			frameTime += dwInterval;
Packit Service fa4841
		}
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	ExitThread(0);
Packit Service fa4841
	return 0;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
#endif
Packit Service fa4841
Packit Service fa4841
static UINT32 win_shadow_enum_monitors(MONITOR_DEF* monitors, UINT32 maxMonitors)
Packit Service fa4841
{
Packit Service fa4841
	HDC hdc;
Packit Service fa4841
	int index;
Packit Service fa4841
	int desktopWidth;
Packit Service fa4841
	int desktopHeight;
Packit Service fa4841
	DWORD iDevNum = 0;
Packit Service fa4841
	int numMonitors = 0;
Packit Service fa4841
	MONITOR_DEF* monitor;
Packit Service fa4841
	DISPLAY_DEVICE displayDevice;
Packit Service fa4841
	ZeroMemory(&displayDevice, sizeof(DISPLAY_DEVICE));
Packit Service fa4841
	displayDevice.cb = sizeof(DISPLAY_DEVICE);
Packit Service fa4841
Packit Service fa4841
	if (EnumDisplayDevices(NULL, iDevNum, &displayDevice, 0))
Packit Service fa4841
	{
Packit Service fa4841
		hdc = CreateDC(displayDevice.DeviceName, NULL, NULL, NULL);
Packit Service fa4841
		desktopWidth = GetDeviceCaps(hdc, HORZRES);
Packit Service fa4841
		desktopHeight = GetDeviceCaps(hdc, VERTRES);
Packit Service fa4841
		index = 0;
Packit Service fa4841
		numMonitors = 1;
Packit Service fa4841
		monitor = &monitors[index];
Packit Service fa4841
		monitor->left = 0;
Packit Service fa4841
		monitor->top = 0;
Packit Service fa4841
		monitor->right = desktopWidth;
Packit Service fa4841
		monitor->bottom = desktopHeight;
Packit Service fa4841
		monitor->flags = 1;
Packit Service fa4841
		DeleteDC(hdc);
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	return numMonitors;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static int win_shadow_subsystem_init(rdpShadowSubsystem* arg)
Packit Service fa4841
{
Packit Service fa4841
	winShadowSubsystem* subsystem = (winShadowSubsystem*)arg;
Packit Service fa4841
	int status;
Packit Service fa4841
	MONITOR_DEF* virtualScreen;
Packit Service fa4841
	subsystem->base.numMonitors = win_shadow_enum_monitors(subsystem->base.monitors, 16);
Packit Service fa4841
#if defined(WITH_WDS_API)
Packit Service fa4841
	status = win_shadow_wds_init(subsystem);
Packit Service fa4841
#elif defined(WITH_DXGI_1_2)
Packit Service fa4841
	status = win_shadow_dxgi_init(subsystem);
Packit Service fa4841
#endif
Packit Service fa4841
	virtualScreen = &(subsystem->base.virtualScreen);
Packit Service fa4841
	virtualScreen->left = 0;
Packit Service fa4841
	virtualScreen->top = 0;
Packit Service fa4841
	virtualScreen->right = subsystem->width;
Packit Service fa4841
	virtualScreen->bottom = subsystem->height;
Packit Service fa4841
	virtualScreen->flags = 1;
Packit Service fa4841
	WLog_INFO(TAG, "width: %d height: %d", subsystem->width, subsystem->height);
Packit Service fa4841
	return 1;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static int win_shadow_subsystem_uninit(rdpShadowSubsystem* arg)
Packit Service fa4841
{
Packit Service fa4841
	winShadowSubsystem* subsystem = (winShadowSubsystem*)arg;
Packit Service fa4841
Packit Service fa4841
	if (!subsystem)
Packit Service fa4841
		return -1;
Packit Service fa4841
Packit Service fa4841
#if defined(WITH_WDS_API)
Packit Service fa4841
	win_shadow_wds_uninit(subsystem);
Packit Service fa4841
#elif defined(WITH_DXGI_1_2)
Packit Service fa4841
	win_shadow_dxgi_uninit(subsystem);
Packit Service fa4841
#endif
Packit Service fa4841
	return 1;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static int win_shadow_subsystem_start(rdpShadowSubsystem* arg)
Packit Service fa4841
{
Packit Service fa4841
	winShadowSubsystem* subsystem = (winShadowSubsystem*)arg;
Packit Service fa4841
	HANDLE thread;
Packit Service fa4841
Packit Service fa4841
	if (!subsystem)
Packit Service fa4841
		return -1;
Packit Service fa4841
Packit Service b1ea74
	if (!(thread = CreateThread(NULL, 0, win_shadow_subsystem_thread, (void*)subsystem, 0, NULL)))
Packit Service fa4841
	{
Packit Service fa4841
		WLog_ERR(TAG, "Failed to create thread");
Packit Service fa4841
		return -1;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	return 1;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static int win_shadow_subsystem_stop(rdpShadowSubsystem* arg)
Packit Service fa4841
{
Packit Service fa4841
	winShadowSubsystem* subsystem = (winShadowSubsystem*)arg;
Packit Service fa4841
Packit Service fa4841
	if (!subsystem)
Packit Service fa4841
		return -1;
Packit Service fa4841
Packit Service fa4841
	return 1;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static void win_shadow_subsystem_free(rdpShadowSubsystem* arg)
Packit Service fa4841
{
Packit Service fa4841
	winShadowSubsystem* subsystem = (winShadowSubsystem*)arg;
Packit Service fa4841
Packit Service fa4841
	if (!subsystem)
Packit Service fa4841
		return;
Packit Service fa4841
Packit Service fa4841
	win_shadow_subsystem_uninit(arg);
Packit Service fa4841
	free(subsystem);
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static rdpShadowSubsystem* win_shadow_subsystem_new(void)
Packit Service fa4841
{
Packit Service fa4841
	winShadowSubsystem* subsystem;
Packit Service b1ea74
	subsystem = (winShadowSubsystem*)calloc(1, sizeof(winShadowSubsystem));
Packit Service fa4841
Packit Service fa4841
	if (!subsystem)
Packit Service fa4841
		return NULL;
Packit Service fa4841
Packit Service fa4841
	subsystem->base.SynchronizeEvent = win_shadow_input_synchronize_event;
Packit Service fa4841
	subsystem->base.KeyboardEvent = win_shadow_input_keyboard_event;
Packit Service fa4841
	subsystem->base.UnicodeKeyboardEvent = win_shadow_input_unicode_keyboard_event;
Packit Service fa4841
	subsystem->base.MouseEvent = win_shadow_input_mouse_event;
Packit Service fa4841
	subsystem->base.ExtendedMouseEvent = win_shadow_input_extended_mouse_event;
Packit Service fa4841
	return &subsystem->base;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
FREERDP_API int Win_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints)
Packit Service fa4841
{
Packit Service fa4841
	pEntryPoints->New = win_shadow_subsystem_new;
Packit Service fa4841
	pEntryPoints->Free = win_shadow_subsystem_free;
Packit Service fa4841
	pEntryPoints->Init = win_shadow_subsystem_init;
Packit Service fa4841
	pEntryPoints->Uninit = win_shadow_subsystem_uninit;
Packit Service fa4841
	pEntryPoints->Start = win_shadow_subsystem_start;
Packit Service fa4841
	pEntryPoints->Stop = win_shadow_subsystem_stop;
Packit Service fa4841
	pEntryPoints->EnumMonitors = win_shadow_enum_monitors;
Packit Service fa4841
	return 1;
Packit Service fa4841
}