[Spice-devel] [RFC PATCH vdagent 02/16] Provide support for Windows 10 CCD API

Christophe Fergeau cfergeau at redhat.com
Wed Jul 20 15:46:44 UTC 2016


What is this CCD API, why is it needed? Is this Win10 only, or did older
Windows version have an equivalent?
Does the old code keeps working after this commit?

Given the size of thecommits I'd expect many more explanations as to
what's being done and why.

Christophe

On Mon, Jul 18, 2016 at 09:34:36AM +0300, Dmitry Fleytman wrote:
> From: Sandy Stutsman <sstutsma at redhat.com>
> 
> ---
>  Spice.props                       |  38 ++
>  vdagent.sln                       |  94 ++--
>  vdagent/CCD.h                     | 259 +++++++++++
>  vdagent/D3Dkmt.h                  | 134 ++++++
>  vdagent/desktop_layout.cpp        | 152 ++-----
>  vdagent/desktop_layout.h          |   9 +-
>  vdagent/display_configuration.cpp | 889 ++++++++++++++++++++++++++++++++++++++
>  vdagent/display_configuration.h   | 192 ++++++++
>  vdagent/vdagent.vcxproj           | 380 ++++++++++++++++
>  vdservice/vdservice.vcxproj       | 197 +++++++++
>  10 files changed, 2185 insertions(+), 159 deletions(-)
>  create mode 100644 Spice.props
>  create mode 100644 vdagent/CCD.h
>  create mode 100644 vdagent/D3Dkmt.h
>  create mode 100644 vdagent/display_configuration.cpp
>  create mode 100644 vdagent/display_configuration.h
>  create mode 100644 vdagent/vdagent.vcxproj
>  create mode 100644 vdservice/vdservice.vcxproj
> 
> diff --git a/Spice.props b/Spice.props
> new file mode 100644
> index 0000000..217bfc7
> --- /dev/null
> +++ b/Spice.props
> @@ -0,0 +1,38 @@
> +<?xml version="1.0" encoding="utf-8"?>
> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
> +  <ImportGroup Label="PropertySheets" />
> +  <PropertyGroup Label="UserMacros">
> +    <SPICE_PROTOCOL_DIR>D:\SANDBOX\Master\spice-protocol</SPICE_PROTOCOL_DIR>
> +    <SPICE_LIBS>D:\Sandbox\WSpice\</SPICE_LIBS>
> +    <SPICE_LIB_LIST>cximage.lib;jasper.lib;jbig.lib;jpeg.lib;libdcr.lib;mng.lib;png.lib;tiff.lib;zlib.lib</SPICE_LIB_LIST>
> +    <SPICE_DEBUG_LIB_LIST>cximage.lib;jasper.lib;jbig.lib;jpeg.lib;libdcr.lib;mng.lib;png.lib;tiff.lib;zlib.lib</SPICE_DEBUG_LIB_LIST>
> +    <SPICE_LIBS_DIR>$(SPICE_LIBS)\$(Platform)\Release</SPICE_LIBS_DIR>
> +    <SPICE_DEBUG_LIBS_DIR>$(SPICE_LIBS)\$(Platform)\Debug</SPICE_DEBUG_LIBS_DIR>
> +  </PropertyGroup>
> +  <PropertyGroup />
> +  <ItemDefinitionGroup />
> +  <ItemGroup>
> +    <BuildMacro Include="SPICE_PROTOCOL_DIR">
> +      <Value>$(SPICE_PROTOCOL_DIR)</Value>
> +      <EnvironmentVariable>true</EnvironmentVariable>
> +    </BuildMacro>
> +    <BuildMacro Include="SPICE_LIBS">
> +      <Value>$(SPICE_LIBS)</Value>
> +      <EnvironmentVariable>true</EnvironmentVariable>
> +    </BuildMacro>
> +    <BuildMacro Include="SPICE_LIB_LIST">
> +      <Value>$(SPICE_LIB_LIST)</Value>
> +      <EnvironmentVariable>true</EnvironmentVariable>
> +    </BuildMacro>
> +    <BuildMacro Include="SPICE_DEBUG_LIB_LIST">
> +      <Value>$(SPICE_DEBUG_LIB_LIST)</Value>
> +      <EnvironmentVariable>true</EnvironmentVariable>
> +    </BuildMacro>
> +    <BuildMacro Include="SPICE_LIBS_DIR">
> +      <Value>$(SPICE_LIBS_DIR)</Value>
> +    </BuildMacro>
> +    <BuildMacro Include="SPICE_DEBUG_LIBS_DIR">
> +      <Value>$(SPICE_DEBUG_LIBS_DIR)</Value>
> +    </BuildMacro>
> +  </ItemGroup>
> +</Project>
> \ No newline at end of file
> diff --git a/vdagent.sln b/vdagent.sln
> index 2622f2e..1c29664 100644
> --- a/vdagent.sln
> +++ b/vdagent.sln
> @@ -1,36 +1,58 @@
> -
> -Microsoft Visual Studio Solution File, Format Version 10.00
> -# Visual Studio 2008
> -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vdagent", "vdagent\vdagent.vcproj", "{CAD5A7E6-E9F5-4071-AFDA-25F76FDA5442}"
> -EndProject
> -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vdservice", "vdservice\vdservice.vcproj", "{ADFE5E22-31D0-4343-AE9E-8102CC0051F9}"
> -EndProject
> -Global
> -	GlobalSection(SolutionConfigurationPlatforms) = preSolution
> -		Debug|Win32 = Debug|Win32
> -		Debug|x64 = Debug|x64
> -		Release|Win32 = Release|Win32
> -		Release|x64 = Release|x64
> -	EndGlobalSection
> -	GlobalSection(ProjectConfigurationPlatforms) = postSolution
> -		{CAD5A7E6-E9F5-4071-AFDA-25F76FDA5442}.Debug|Win32.ActiveCfg = Debug|Win32
> -		{CAD5A7E6-E9F5-4071-AFDA-25F76FDA5442}.Debug|Win32.Build.0 = Debug|Win32
> -		{CAD5A7E6-E9F5-4071-AFDA-25F76FDA5442}.Debug|x64.ActiveCfg = Debug|x64
> -		{CAD5A7E6-E9F5-4071-AFDA-25F76FDA5442}.Debug|x64.Build.0 = Debug|x64
> -		{CAD5A7E6-E9F5-4071-AFDA-25F76FDA5442}.Release|Win32.ActiveCfg = Release|Win32
> -		{CAD5A7E6-E9F5-4071-AFDA-25F76FDA5442}.Release|Win32.Build.0 = Release|Win32
> -		{CAD5A7E6-E9F5-4071-AFDA-25F76FDA5442}.Release|x64.ActiveCfg = Release|x64
> -		{CAD5A7E6-E9F5-4071-AFDA-25F76FDA5442}.Release|x64.Build.0 = Release|x64
> -		{ADFE5E22-31D0-4343-AE9E-8102CC0051F9}.Debug|Win32.ActiveCfg = Debug|Win32
> -		{ADFE5E22-31D0-4343-AE9E-8102CC0051F9}.Debug|Win32.Build.0 = Debug|Win32
> -		{ADFE5E22-31D0-4343-AE9E-8102CC0051F9}.Debug|x64.ActiveCfg = Debug|x64
> -		{ADFE5E22-31D0-4343-AE9E-8102CC0051F9}.Debug|x64.Build.0 = Debug|x64
> -		{ADFE5E22-31D0-4343-AE9E-8102CC0051F9}.Release|Win32.ActiveCfg = Release|Win32
> -		{ADFE5E22-31D0-4343-AE9E-8102CC0051F9}.Release|Win32.Build.0 = Release|Win32
> -		{ADFE5E22-31D0-4343-AE9E-8102CC0051F9}.Release|x64.ActiveCfg = Release|x64
> -		{ADFE5E22-31D0-4343-AE9E-8102CC0051F9}.Release|x64.Build.0 = Release|x64
> -	EndGlobalSection
> -	GlobalSection(SolutionProperties) = preSolution
> -		HideSolutionNode = FALSE
> -	EndGlobalSection
> -EndGlobal
> +
> +Microsoft Visual Studio Solution File, Format Version 12.00
> +# Visual Studio 14
> +VisualStudioVersion = 14.0.23107.0
> +MinimumVisualStudioVersion = 10.0.40219.1
> +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vdagent", "vdagent\vdagent.vcxproj", "{CAD5A7E6-E9F5-4071-AFDA-25F76FDA5442}"
> +EndProject
> +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vdservice", "vdservice\vdservice.vcxproj", "{ADFE5E22-31D0-4343-AE9E-8102CC0051F9}"
> +EndProject
> +Global
> +	GlobalSection(SolutionConfigurationPlatforms) = preSolution
> +		Debug|Win32 = Debug|Win32
> +		Debug|x64 = Debug|x64
> +		Release|Win32 = Release|Win32
> +		Release|x64 = Release|x64
> +		Win10 Debug|Win32 = Win10 Debug|Win32
> +		Win10 Debug|x64 = Win10 Debug|x64
> +		Win10 Release|Win32 = Win10 Release|Win32
> +		Win10 Release|x64 = Win10 Release|x64
> +	EndGlobalSection
> +	GlobalSection(ProjectConfigurationPlatforms) = postSolution
> +		{CAD5A7E6-E9F5-4071-AFDA-25F76FDA5442}.Debug|Win32.ActiveCfg = Debug|Win32
> +		{CAD5A7E6-E9F5-4071-AFDA-25F76FDA5442}.Debug|Win32.Build.0 = Debug|Win32
> +		{CAD5A7E6-E9F5-4071-AFDA-25F76FDA5442}.Debug|x64.ActiveCfg = Debug|x64
> +		{CAD5A7E6-E9F5-4071-AFDA-25F76FDA5442}.Debug|x64.Build.0 = Debug|x64
> +		{CAD5A7E6-E9F5-4071-AFDA-25F76FDA5442}.Release|Win32.ActiveCfg = Release|Win32
> +		{CAD5A7E6-E9F5-4071-AFDA-25F76FDA5442}.Release|Win32.Build.0 = Release|Win32
> +		{CAD5A7E6-E9F5-4071-AFDA-25F76FDA5442}.Release|x64.ActiveCfg = Release|x64
> +		{CAD5A7E6-E9F5-4071-AFDA-25F76FDA5442}.Release|x64.Build.0 = Release|x64
> +		{CAD5A7E6-E9F5-4071-AFDA-25F76FDA5442}.Win10 Debug|Win32.ActiveCfg = Win10 Debug|Win32
> +		{CAD5A7E6-E9F5-4071-AFDA-25F76FDA5442}.Win10 Debug|Win32.Build.0 = Win10 Debug|Win32
> +		{CAD5A7E6-E9F5-4071-AFDA-25F76FDA5442}.Win10 Debug|x64.ActiveCfg = Win10 Debug|x64
> +		{CAD5A7E6-E9F5-4071-AFDA-25F76FDA5442}.Win10 Debug|x64.Build.0 = Win10 Debug|x64
> +		{CAD5A7E6-E9F5-4071-AFDA-25F76FDA5442}.Win10 Release|Win32.ActiveCfg = Win10 Release|Win32
> +		{CAD5A7E6-E9F5-4071-AFDA-25F76FDA5442}.Win10 Release|Win32.Build.0 = Win10 Release|Win32
> +		{CAD5A7E6-E9F5-4071-AFDA-25F76FDA5442}.Win10 Release|x64.ActiveCfg = Win10 Release|x64
> +		{CAD5A7E6-E9F5-4071-AFDA-25F76FDA5442}.Win10 Release|x64.Build.0 = Win10 Release|x64
> +		{ADFE5E22-31D0-4343-AE9E-8102CC0051F9}.Debug|Win32.ActiveCfg = Debug|Win32
> +		{ADFE5E22-31D0-4343-AE9E-8102CC0051F9}.Debug|Win32.Build.0 = Debug|Win32
> +		{ADFE5E22-31D0-4343-AE9E-8102CC0051F9}.Debug|x64.ActiveCfg = Debug|x64
> +		{ADFE5E22-31D0-4343-AE9E-8102CC0051F9}.Debug|x64.Build.0 = Debug|x64
> +		{ADFE5E22-31D0-4343-AE9E-8102CC0051F9}.Release|Win32.ActiveCfg = Release|Win32
> +		{ADFE5E22-31D0-4343-AE9E-8102CC0051F9}.Release|Win32.Build.0 = Release|Win32
> +		{ADFE5E22-31D0-4343-AE9E-8102CC0051F9}.Release|x64.ActiveCfg = Release|x64
> +		{ADFE5E22-31D0-4343-AE9E-8102CC0051F9}.Release|x64.Build.0 = Release|x64
> +		{ADFE5E22-31D0-4343-AE9E-8102CC0051F9}.Win10 Debug|Win32.ActiveCfg = Debug|Win32
> +		{ADFE5E22-31D0-4343-AE9E-8102CC0051F9}.Win10 Debug|Win32.Build.0 = Debug|Win32
> +		{ADFE5E22-31D0-4343-AE9E-8102CC0051F9}.Win10 Debug|x64.ActiveCfg = Debug|x64
> +		{ADFE5E22-31D0-4343-AE9E-8102CC0051F9}.Win10 Debug|x64.Build.0 = Debug|x64
> +		{ADFE5E22-31D0-4343-AE9E-8102CC0051F9}.Win10 Release|Win32.ActiveCfg = Release|Win32
> +		{ADFE5E22-31D0-4343-AE9E-8102CC0051F9}.Win10 Release|Win32.Build.0 = Release|Win32
> +		{ADFE5E22-31D0-4343-AE9E-8102CC0051F9}.Win10 Release|x64.ActiveCfg = Release|x64
> +		{ADFE5E22-31D0-4343-AE9E-8102CC0051F9}.Win10 Release|x64.Build.0 = Release|x64
> +	EndGlobalSection
> +	GlobalSection(SolutionProperties) = preSolution
> +		HideSolutionNode = FALSE
> +	EndGlobalSection
> +EndGlobal
> diff --git a/vdagent/CCD.h b/vdagent/CCD.h
> new file mode 100644
> index 0000000..a457fc1
> --- /dev/null
> +++ b/vdagent/CCD.h
> @@ -0,0 +1,259 @@
> +/*
> +Copyright (C) 2015 Red Hat, Inc.
> +
> +This program is free software; you can redistribute it and/or
> +modify it under the terms of the GNU General Public License as
> +published by the Free Software Foundation; either version 2 of
> +the License, or (at your option) any later version.
> +
> +This program is distributed in the hope that it will be useful,
> +but WITHOUT ANY WARRANTY; without even the implied warranty of
> +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +GNU General Public License for more details.
> +
> +You should have received a copy of the GNU General Public License
> +along with this program.  If not, see <http://www.gnu.org/licenses/>.
> +*/
> +
> +//This file provides defines and structures required by Windows CCD API and
> +//not currently supplied by the MINGW32 header files.
> +#pragma once
> +
> +//
> +// Definitions used by QueryDisplayConfig.
> +//
> +
> +#if (_WIN32_WINNT < 0X0601)
> +#define QDC_ALL_PATHS                    0x00000001
> +#define QDC_ONLY_ACTIVE_PATHS            0x00000002
> +#define QDC_DATABASE_CURRENT             0x00000004
> +#define QDC_VIRTUAL_MODE_AWARE           0x00000010
> +
> +//
> +// Definitions used by SetDisplayConfig.
> +//
> +
> +#define SDC_TOPOLOGY_INTERNAL            0x00000001
> +#define SDC_TOPOLOGY_CLONE               0x00000002
> +#define SDC_TOPOLOGY_EXTEND              0x00000004
> +#define SDC_TOPOLOGY_EXTERNAL            0x00000008
> +#define SDC_TOPOLOGY_SUPPLIED            0x00000010
> +#define SDC_USE_DATABASE_CURRENT         (SDC_TOPOLOGY_INTERNAL | SDC_TOPOLOGY_CLONE | SDC_TOPOLOGY_EXTEND | SDC_TOPOLOGY_EXTERNAL)
> +
> +#define SDC_USE_SUPPLIED_DISPLAY_CONFIG  0x00000020
> +#define SDC_VALIDATE                     0x00000040
> +#define SDC_APPLY                        0x00000080
> +#define SDC_NO_OPTIMIZATION              0x00000100
> +#define SDC_SAVE_TO_DATABASE             0x00000200
> +#define SDC_ALLOW_CHANGES                0x00000400
> +#define SDC_PATH_PERSIST_IF_REQUIRED     0x00000800
> +#define SDC_FORCE_MODE_ENUMERATION       0x00001000
> +#define SDC_ALLOW_PATH_ORDER_CHANGES     0x00002000
> +#define SDC_VIRTUAL_MODE_AWARE           0x00008000
> +
> +#define DISPLAYCONFIG_PATH_ACTIVE               0x00000001
> +#define DISPLAYCONFIG_PATH_MODE_IDX_INVALID     0xffffffff
> +
> +typedef enum {
> +    DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME = 1,
> +    DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME = 2,
> +    DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_PREFERRED_MODE = 3,
> +    DISPLAYCONFIG_DEVICE_INFO_GET_ADAPTER_NAME = 4,
> +    DISPLAYCONFIG_DEVICE_INFO_SET_TARGET_PERSISTENCE = 5,
> +    DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_BASE_TYPE = 6,
> +    DISPLAYCONFIG_DEVICE_INFO_GET_SUPPORT_VIRTUAL_RESOLUTION = 7,
> +    DISPLAYCONFIG_DEVICE_INFO_SET_SUPPORT_VIRTUAL_RESOLUTION = 8,
> +    DISPLAYCONFIG_DEVICE_INFO_FORCE_UINT32 = 0xFFFFFFFF
> +} DISPLAYCONFIG_DEVICE_INFO_TYPE;
> +
> +
> +typedef enum {
> +	DISPLAYCONFIG_OUTPUT_TECHNOLOGY_OTHER                = -1,
> +	DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HD15                 = 0,
> +	DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SVIDEO               = 1,
> +	DISPLAYCONFIG_OUTPUT_TECHNOLOGY_COMPOSITE_VIDEO      = 2,
> +	DISPLAYCONFIG_OUTPUT_TECHNOLOGY_COMPONENT_VIDEO      = 3,
> +	DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DVI                  = 4,
> +	DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HDMI                 = 5,
> +	DISPLAYCONFIG_OUTPUT_TECHNOLOGY_LVDS                 = 6,
> +	DISPLAYCONFIG_OUTPUT_TECHNOLOGY_D_JPN                = 8,
> +	DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SDI                  = 9,
> +	DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EXTERNAL = 10,
> +	DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EMBEDDED = 11,
> +	DISPLAYCONFIG_OUTPUT_TECHNOLOGY_UDI_EXTERNAL         = 12,
> +	DISPLAYCONFIG_OUTPUT_TECHNOLOGY_UDI_EMBEDDED         = 13,
> +	DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SDTVDONGLE           = 14,
> +	DISPLAYCONFIG_OUTPUT_TECHNOLOGY_MIRACAST             = 15,
> +	DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INTERNAL             = 0x80000000,
> +	DISPLAYCONFIG_OUTPUT_TECHNOLOGY_FORCE_UINT32         = 0xFFFFFFFF
> +} DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY;
> +
> +
> +typedef enum {
> +	DISPLAYCONFIG_ROTATION_IDENTITY     = 1,
> +	DISPLAYCONFIG_ROTATION_ROTATE90     = 2,
> +	DISPLAYCONFIG_ROTATION_ROTATE180    = 3,
> +	DISPLAYCONFIG_ROTATION_ROTATE270    = 4,
> +	DISPLAYCONFIG_ROTATION_FORCE_UINT32 = 0xFFFFFFFF
> +} DISPLAYCONFIG_ROTATION;
> +
> +typedef enum {
> +	DISPLAYCONFIG_SCANLINE_ORDERING_UNSPECIFIED                = 0,
> +	DISPLAYCONFIG_SCANLINE_ORDERING_PROGRESSIVE                = 1,
> +	DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED                 = 2,
> +	DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED_UPPERFIELDFIRST = DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED,
> +	DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED_LOWERFIELDFIRST = 3,
> +	DISPLAYCONFIG_SCANLINE_ORDERING_FORCE_UINT32               = 0xFFFFFFFF
> +} DISPLAYCONFIG_SCANLINE_ORDERING;
> +
> +
> +typedef enum {
> +	DISPLAYCONFIG_SCALING_IDENTITY               = 1,
> +	DISPLAYCONFIG_SCALING_CENTERED               = 2,
> +	DISPLAYCONFIG_SCALING_STRETCHED              = 3,
> +	DISPLAYCONFIG_SCALING_ASPECTRATIOCENTEREDMAX = 4,
> +	DISPLAYCONFIG_SCALING_CUSTOM                 = 5,
> +	DISPLAYCONFIG_SCALING_PREFERRED              = 128,
> +	DISPLAYCONFIG_SCALING_FORCE_UINT32           = 0xFFFFFFFF
> +} DISPLAYCONFIG_SCALING;
> +
> +
> +typedef enum {
> +	DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE        = 1,
> +	DISPLAYCONFIG_MODE_INFO_TYPE_TARGET        = 2,
> +	DISPLAYCONFIG_MODE_INFO_TYPE_DESKTOP_IMAGE = 3,
> +	DISPLAYCONFIG_MODE_INFO_TYPE_FORCE_UINT32  = 0xFFFFFFFF
> +} DISPLAYCONFIG_MODE_INFO_TYPE;
> +
> +
> +typedef enum {
> +	DISPLAYCONFIG_PIXELFORMAT_8BPP         = 1,
> +	DISPLAYCONFIG_PIXELFORMAT_16BPP        = 2,
> +	DISPLAYCONFIG_PIXELFORMAT_24BPP        = 3,
> +	DISPLAYCONFIG_PIXELFORMAT_32BPP        = 4,
> +	DISPLAYCONFIG_PIXELFORMAT_NONGDI       = 5,
> +	DISPLAYCONFIG_PIXELFORMAT_FORCE_UINT32 = 0xffffffff
> +} DISPLAYCONFIG_PIXELFORMAT;
> +
> +typedef enum {
> +	DISPLAYCONFIG_TOPOLOGY_INTERNAL     = 0x00000001,
> +	DISPLAYCONFIG_TOPOLOGY_CLONE        = 0x00000002,
> +	DISPLAYCONFIG_TOPOLOGY_EXTEND       = 0x00000004,
> +	DISPLAYCONFIG_TOPOLOGY_EXTERNAL     = 0x00000008,
> +	DISPLAYCONFIG_TOPOLOGY_FORCE_UINT32 = 0xFFFFFFFF
> +} DISPLAYCONFIG_TOPOLOGY_ID;
> +
> +
> +typedef struct DISPLAYCONFIG_DEVICE_INFO_HEADER {
> +	DISPLAYCONFIG_DEVICE_INFO_TYPE  type;
> +	UINT32                          size;
> +	LUID                            adapterId;
> +	UINT32                          id;
> +} DISPLAYCONFIG_DEVICE_INFO_HEADER;
> +
> +typedef struct DISPLAYCONFIG_SOURCE_DEVICE_NAME {
> +	DISPLAYCONFIG_DEVICE_INFO_HEADER            header;
> +	WCHAR                                       viewGdiDeviceName[CCHDEVICENAME];
> +} DISPLAYCONFIG_SOURCE_DEVICE_NAME;
> +
> +typedef struct DISPLAYCONFIG_DESKTOP_IMAGE_INFO {
> +	POINTL PathSourceSize;
> +	RECTL DesktopImageRegion;
> +	RECTL DesktopImageClip;
> +} DISPLAYCONFIG_DESKTOP_IMAGE_INFO;
> +
> +typedef struct DISPLAYCONFIG_RATIONAL {
> +	UINT32    Numerator;
> +	UINT32    Denominator;
> +} DISPLAYCONFIG_RATIONAL;
> +
> +typedef struct DISPLAYCONFIG_PATH_SOURCE_INFO {
> +    LUID    adapterId;
> +    UINT32  id;
> +    union {
> +        UINT32 modeInfoIdx;
> +        struct {
> +            UINT32 cloneGroupId : 16;
> +            UINT32 sourceModeInfoIdx : 16;
> +        } DUMMYSTRUCTNAME;
> +    } DUMMYUNIONNAME;
> +
> +    UINT32  statusFlags;
> +} DISPLAYCONFIG_PATH_SOURCE_INFO;
> +
> +
> +typedef struct DISPLAYCONFIG_PATH_TARGET_INFO {
> +    LUID                                    adapterId;
> +    UINT32                                  id;
> +    union {
> +        UINT32                                  modeInfoIdx;
> +        struct {
> +            UINT32 desktopModeInfoIdx : 16;
> +            UINT32 targetModeInfoIdx : 16;
> +        } DUMMYSTRUCTNAME;
> +    } DUMMYUNIONNAME;
> +    DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY   outputTechnology;
> +    DISPLAYCONFIG_ROTATION                  rotation;
> +    DISPLAYCONFIG_SCALING                   scaling;
> +    DISPLAYCONFIG_RATIONAL                  refreshRate;
> +    DISPLAYCONFIG_SCANLINE_ORDERING         scanLineOrdering;
> +    BOOL                                    targetAvailable;
> +    UINT32                                  statusFlags;
> +} DISPLAYCONFIG_PATH_TARGET_INFO;
> +
> +typedef struct DISPLAYCONFIG_PATH_INFO {
> +    DISPLAYCONFIG_PATH_SOURCE_INFO  sourceInfo;
> +    DISPLAYCONFIG_PATH_TARGET_INFO  targetInfo;
> +    UINT32                          flags;
> +} DISPLAYCONFIG_PATH_INFO;
> +
> +typedef struct DISPLAYCONFIG_2DREGION {
> +	UINT32 cx;
> +	UINT32 cy;
> +} DISPLAYCONFIG_2DREGION;
> +
> +typedef struct DISPLAYCONFIG_VIDEO_SIGNAL_INFO {
> +	UINT64                          pixelRate;
> +	DISPLAYCONFIG_RATIONAL          hSyncFreq;
> +	DISPLAYCONFIG_RATIONAL          vSyncFreq;
> +	DISPLAYCONFIG_2DREGION          activeSize;
> +	DISPLAYCONFIG_2DREGION          totalSize;
> +
> +	union {
> +		struct {
> +			UINT32 videoStandard : 16;
> +
> +			UINT32 vSyncFreqDivider : 6;
> +
> +			UINT32 reserved : 10;
> +		} AdditionalSignalInfo;
> +
> +		UINT32 videoStandard;
> +	} DUMMYUNIONNAME;
> +
> +	DISPLAYCONFIG_SCANLINE_ORDERING scanLineOrdering;
> +} DISPLAYCONFIG_VIDEO_SIGNAL_INFO;
> +
> +typedef struct DISPLAYCONFIG_TARGET_MODE {
> +	DISPLAYCONFIG_VIDEO_SIGNAL_INFO   targetVideoSignalInfo;
> +} DISPLAYCONFIG_TARGET_MODE;
> +
> +typedef struct DISPLAYCONFIG_SOURCE_MODE {
> +	UINT32                      width;
> +	UINT32                      height;
> +	DISPLAYCONFIG_PIXELFORMAT   pixelFormat;
> +	POINTL                      position;
> +} DISPLAYCONFIG_SOURCE_MODE;
> +
> +typedef struct DISPLAYCONFIG_MODE_INFO {
> +	DISPLAYCONFIG_MODE_INFO_TYPE    infoType;
> +	UINT32                          id;
> +	LUID                            adapterId;
> +	union {
> +		DISPLAYCONFIG_TARGET_MODE   targetMode;
> +		DISPLAYCONFIG_SOURCE_MODE   sourceMode;
> +		DISPLAYCONFIG_DESKTOP_IMAGE_INFO    desktopImageInfo;
> +	} DUMMYUNIONNAME;
> +} DISPLAYCONFIG_MODE_INFO;
> +
> +#endif
> \ No newline at end of file
> diff --git a/vdagent/D3Dkmt.h b/vdagent/D3Dkmt.h
> new file mode 100644
> index 0000000..81530fb
> --- /dev/null
> +++ b/vdagent/D3Dkmt.h
> @@ -0,0 +1,134 @@
> +
> +/*
> +Copyright (C) 2015 Red Hat, Inc.
> +
> +This program is free software; you can redistribute it and/or
> +modify it under the terms of the GNU General Public License as
> +published by the Free Software Foundation; either version 2 of
> +the License, or (at your option) any later version.
> +
> +This program is distributed in the hope that it will be useful,
> +but WITHOUT ANY WARRANTY; without even the implied warranty of
> +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +GNU General Public License for more details.
> +
> +You should have received a copy of the GNU General Public License
> +along with this program.  If not, see <http://www.gnu.org/licenses/>.
> +*/
> +
> +//File provides definitions and structures for the D3D KMT interface calls
> +//make by WDDM vd agent interface
> +
> +#pragma once
> +#include <winnt.h>
> +typedef UINT D3DKMT_HANDLE;
> +typedef UINT  D3DDDI_VIDEO_PRESENT_SOURCE_ID;
> +
> +typedef struct _D3DKMT_OPENADAPTERFROMHDC {
> +    HDC                             hDc;            
> +    D3DKMT_HANDLE                   hAdapter;       
> +    LUID                            AdapterLuid;    
> +    D3DDDI_VIDEO_PRESENT_SOURCE_ID  VidPnSourceId;  
> +} D3DKMT_OPENADAPTERFROMHDC;
> +
> +typedef struct _D3DKMT_CLOSEADAPTER {
> +    D3DKMT_HANDLE   hAdapter;   
> +} D3DKMT_CLOSEADAPTER;
> +
> +typedef enum _D3DKMT_ESCAPETYPE {
> +    D3DKMT_ESCAPE_DRIVERPRIVATE = 0,
> +    D3DKMT_ESCAPE_VIDMM = 1,
> +    D3DKMT_ESCAPE_TDRDBGCTRL = 2,
> +    D3DKMT_ESCAPE_VIDSCH = 3,
> +    D3DKMT_ESCAPE_DEVICE = 4,
> +    D3DKMT_ESCAPE_DMM = 5,
> +    D3DKMT_ESCAPE_DEBUG_SNAPSHOT = 6,
> +    D3DKMT_ESCAPE_SETDRIVERUPDATESTATUS = 7,
> +    D3DKMT_ESCAPE_DRT_TEST = 8,
> +#if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WIN8)
> +    D3DKMT_ESCAPE_DIAGNOSTICS = 9,
> +    D3DKMT_ESCAPE_OUTPUTDUPL_SNAPSHOT = 10,
> +    D3DKMT_ESCAPE_OUTPUTDUPL_DIAGNOSTICS = 11,
> +    D3DKMT_ESCAPE_BDD_PNP = 12,
> +    D3DKMT_ESCAPE_BDD_FALLBACK = 13,
> +    D3DKMT_ESCAPE_ACTIVATE_SPECIFIC_DIAG = 14,
> +    D3DKMT_ESCAPE_MODES_PRUNED_OUT = 15,
> +    D3DKMT_ESCAPE_WHQL_INFO = 16,
> +    D3DKMT_ESCAPE_BRIGHTNESS = 17,
> +    D3DKMT_ESCAPE_EDID_CACHE = 18,
> +    D3DKMT_ESCAPE_GENERIC_ADAPTER_DIAG_INFO = 19,
> +#if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WDDM1_3)
> +    D3DKMT_ESCAPE_MIRACAST_DISPLAY_REQUEST = 20,
> +    D3DKMT_ESCAPE_HISTORY_BUFFER_STATUS = 21,
> +    D3DKMT_ESCAPE_MIRACAST_ADAPTER_DIAG_INFO = 23,
> +#if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WDDM2_0)
> +    D3DKMT_ESCAPE_FORCE_BDDFALLBACK_HEADLESS = 24,
> +    D3DKMT_ESCAPE_REQUEST_MACHINE_CRASH = 25,
> +#endif
> +#endif 
> +
> +    D3DKMT_ESCAPE_WIN32K_START = 1024,
> +    D3DKMT_ESCAPE_WIN32K_HIP_DEVICE_INFO = 1024,
> +    D3DKMT_ESCAPE_WIN32K_QUERY_CD_ROTATION_BLOCK = 1025,
> +#if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WDDM1_3)
> +    D3DKMT_ESCAPE_WIN32K_DPI_INFO = 1026, 
> +    D3DKMT_ESCAPE_WIN32K_PRESENTER_VIEW_INFO = 1027,
> +    D3DKMT_ESCAPE_WIN32K_SYSTEM_DPI = 1028,
> +#if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WDDM2_0)
> +    D3DKMT_ESCAPE_WIN32K_BDD_FALLBACK = 1029,
> +    D3DKMT_ESCAPE_WIN32K_DDA_TEST_CTL = 1030,
> +    D3DKMT_ESCAPE_WIN32K_USER_DETECTED_BLACK_SCREEN = 1031,
> +#endif // DXGKDDI_INTERFACE_VERSION_WDDM2_0
> +#endif // DXGKDDI_INTERFACE_VERSION_WDDM1_3
> +#endif // DXGKDDI_INTERFACE_VERSION_WIN8
> +} D3DKMT_ESCAPETYPE;
> +
> +
> +typedef struct _D3DDDI_ESCAPEFLAGS {
> +    union {
> +        struct {
> +            UINT    HardwareAccess : 1;   
> +#if ((DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WDDM1_3) || \
> +     (D3D_UMD_INTERFACE_VERSION >= D3D_UMD_INTERFACE_VERSION_WDDM1_3))
> +            UINT    DeviceStatusQuery : 1;   
> +            UINT    ChangeFrameLatency : 1;    
> +            UINT    Reserved : 29;    
> +#else
> +            UINT    Reserved : 31;    
> +#endif // WDDM1_3
> +        };
> +        UINT        Value;
> +    };
> +} D3DDDI_ESCAPEFLAGS;
> +
> +typedef struct _D3DKMT_ESCAPE {
> +    D3DKMT_HANDLE       hAdapter;               
> +    D3DKMT_HANDLE       hDevice;                
> +    D3DKMT_ESCAPETYPE   Type;                   
> +    D3DDDI_ESCAPEFLAGS  Flags;                  
> +    VOID*               pPrivateDriverData;     
> +    UINT                PrivateDriverDataSize;  
> +    D3DKMT_HANDLE       hContext;               
> +} D3DKMT_ESCAPE;
> +
> +
> +typedef struct _D3DKMT_OPENADAPTERFROMDEVICENAME {
> +	PCWSTR                          pDeviceName;    
> +	D3DKMT_HANDLE                   hAdapter;       
> +	LUID                            AdapterLuid;    
> +} D3DKMT_OPENADAPTERFROMDEVICENAME;
> +
> +typedef UINT  D3DDDI_VIDEO_PRESENT_SOURCE_ID;
> +
> +typedef struct _D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME {
> +	WCHAR                           DeviceName[32];
> +	D3DKMT_HANDLE                   hAdapter;       
> +	LUID                            AdapterLuid;    
> +	D3DDDI_VIDEO_PRESENT_SOURCE_ID  VidPnSourceId;  
> +} D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME;
> +
> +typedef NTSTATUS(APIENTRY* PFND3DKMT_ESCAPE)(CONST D3DKMT_ESCAPE*);
> +typedef NTSTATUS(APIENTRY* PFND3DKMT_OPENADAPTERFROMGDIDISPLAYNAME)(D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME*);
> +typedef NTSTATUS(APIENTRY* PFND3DKMT_OPENADAPTERFROMDEVICENAME)(D3DKMT_OPENADAPTERFROMDEVICENAME*);
> +typedef NTSTATUS(APIENTRY* PFND3DKMT_CLOSEADAPTER)(D3DKMT_CLOSEADAPTER*);
> +typedef NTSTATUS(APIENTRY* PFND3DKMT_OPENADAPTERFROMHDC)(D3DKMT_OPENADAPTERFROMHDC*);
> \ No newline at end of file
> diff --git a/vdagent/desktop_layout.cpp b/vdagent/desktop_layout.cpp
> index a7666ca..7aff7e7 100644
> --- a/vdagent/desktop_layout.cpp
> +++ b/vdagent/desktop_layout.cpp
> @@ -18,8 +18,8 @@
>  #include <spice/qxl_windows.h>
>  #include <spice/qxl_dev.h>
>  #include "desktop_layout.h"
> +#include "display_configuration.h"
>  #include "vdlog.h"
> -
>  #ifdef __MINGW32__
>  using std::min;
>  using std::max;
> @@ -35,15 +35,19 @@ void DisplayMode::set_res(DWORD width, DWORD height, DWORD depth)
>  DesktopLayout::DesktopLayout()
>      : _total_width (0)
>      , _total_height (0)
> -    , _send_monitors_position(false)
> +    , _display_config(NULL)
>  {
>      MUTEX_INIT(_mutex);
> +    _display_config = DISPLAY_CONFIG::create_config();
>      get_displays();
>  }
>  
>  DesktopLayout::~DesktopLayout()
>  {
>      clean_displays();
> +    if (_display_config){
> +        delete _display_config;
> +    }
>  }
>  
>  void DesktopLayout::get_displays()
> @@ -59,6 +63,7 @@ void DesktopLayout::get_displays()
>          unlock();
>          return;
>      }
> +    _display_config->update_config_path();
>      clean_displays();
>      ZeroMemory(&dev_info, sizeof(dev_info));
>      dev_info.cb = sizeof(dev_info);
> @@ -82,12 +87,13 @@ void DesktopLayout::get_displays()
>                  _displays[i] = NULL;
>              }
>          }
> -        attached = !!(dev_info.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP);
> +        attached = _display_config->is_attached(&dev_info);
> +
>          EnumDisplaySettings(dev_info.DeviceName, ENUM_CURRENT_SETTINGS, &mode);
>          _displays[display_id] = new DisplayMode(mode.dmPosition.x, mode.dmPosition.y,
>                                                  mode.dmPelsWidth, mode.dmPelsHeight,
>                                                  mode.dmBitsPerPel, attached);
> -        update_monitor_config(dev_info.DeviceName, _displays[display_id]);
> +        _display_config->update_monitor_config(dev_info.DeviceName, _displays[display_id], &mode);
>      }
>      normalize_displays_pos();
>      unlock();
> @@ -121,6 +127,7 @@ void DesktopLayout::set_displays()
>          unlock();
>          return;
>      }
> +    _display_config->update_config_path();
>      ZeroMemory(&dev_info, sizeof(dev_info));
>      dev_info.cb = sizeof(dev_info);
>      ZeroMemory(&dev_mode, sizeof(dev_mode));
> @@ -146,28 +153,32 @@ void DesktopLayout::set_displays()
>              break;
>          }
>          DisplayMode * mode(_displays.at(display_id));
> -        if (!init_dev_mode(dev_info.DeviceName, &dev_mode, mode, normal_x, normal_y, true)) {
> +        if (!init_dev_mode(dev_info.DeviceName, &dev_mode, mode)) {
>              vd_printf("No suitable mode found for display %S", dev_info.DeviceName);
>              break;
>          }
>          vd_printf("Set display mode %lux%lu", dev_mode.dmPelsWidth, dev_mode.dmPelsHeight);
> -        LONG ret = ChangeDisplaySettingsEx(dev_info.DeviceName, &dev_mode, NULL,
> -                                           CDS_UPDATEREGISTRY | CDS_NORESET, NULL);
> -        if (ret == DISP_CHANGE_SUCCESSFUL) {
> +        if(_display_config->update_dev_mode_position(dev_info.DeviceName, &dev_mode,
> +                                                     mode->_pos_x - normal_x,
> +                                                     mode->_pos_y - normal_y)) {
>              dev_sets++;
> -            update_monitor_config(dev_info.DeviceName, mode);
> +            _display_config->update_monitor_config(dev_info.DeviceName, mode, &dev_mode);
>          }
>          if (!is_qxl) {
>              display_id++;
>          }
>      }
>      if (dev_sets) {
> -        ChangeDisplaySettingsEx(NULL, NULL, NULL, 0, NULL);
> +        _display_config->update_display_settings();
>          normalize_displays_pos();
>      }
>      unlock();
>  }
>  
> +void DesktopLayout::set_position_configurable(bool flag) {
> +    _display_config->set_monitors_config(flag);
> +}
> +
>  // Normalize all display positions to non-negative coordinates and update total width and height of
>  // the virtual desktop. Caller is responsible to lock() & unlock().
>  void DesktopLayout::normalize_displays_pos()
> @@ -265,125 +276,30 @@ bool DesktopLayout::get_qxl_device_id(WCHAR* device_key, DWORD* device_id)
>      return key_found;
>  }
>  
> -bool DesktopLayout::init_dev_mode(LPCTSTR dev_name, DEVMODE* dev_mode, DisplayMode* mode,
> -                                  LONG normal_x, LONG normal_y, bool set_pos)
> +bool DesktopLayout::init_dev_mode(LPCTSTR dev_name, DEVMODE* dev_mode, DisplayMode* mode)
>  {
> -    DWORD closest_diff = -1;
> -    DWORD best = -1;
> -    QXLEscapeSetCustomDisplay custom;
> -    HDC hdc = NULL;
> -    LONG ret;
> -
>      ZeroMemory(dev_mode, sizeof(DEVMODE));
>      dev_mode->dmSize = sizeof(DEVMODE);
> -    if (!mode || !mode->_attached) {
> -        //Detach monitor
> -        dev_mode->dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_POSITION;
> +    
> +    //Update monitor state
> +    MONITOR_STATE monitor_state = (!mode || !mode->_attached)? MONITOR_DETACHED : MONITOR_ATTACHED;
> +    _display_config->set_monitor_state(dev_name, dev_mode, monitor_state);
> +    if (monitor_state == MONITOR_DETACHED) {
>          return true;
>      }
>  
> -    hdc = CreateDC(dev_name, NULL, NULL, NULL);
> -    if (!hdc) {
> -        // for some reason, windows want those 3 flags to enable monitor
> -        dev_mode->dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_POSITION;
> -        dev_mode->dmPelsWidth = mode->_width;
> -        dev_mode->dmPelsHeight = mode->_height;
> -        ret = ChangeDisplaySettingsEx(dev_name, dev_mode, NULL, CDS_UPDATEREGISTRY, NULL);
> -        if (ret == DISP_CHANGE_BADMODE) {
> -            // custom resolution might not be set yet, use known resolution
> -            // FIXME: this causes client temporary resize... a
> -            // solution would involve passing custom resolution before
> -            // driver initialization, perhaps through registry
> -            dev_mode->dmPelsWidth = 640;
> -            dev_mode->dmPelsHeight = 480;
> -            ret = ChangeDisplaySettingsEx(dev_name, dev_mode, NULL, CDS_UPDATEREGISTRY, NULL);
> -        }
> -
> -        vd_printf("attach %ld", ret);
> -        hdc = CreateDC(dev_name, NULL, NULL, NULL);
> -    }
> -
> -    if (!hdc) {
> -        vd_printf("failed to create DC");
> +    // Update custom resolution
> +    dev_mode->dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_POSITION;
> +    dev_mode->dmPelsWidth = mode->_width;
> +    dev_mode->dmPelsHeight = mode->_height;
> +    dev_mode->dmBitsPerPel = mode->_depth;
> +    if (!_display_config->custom_display_escape(dev_name, dev_mode))
>          return false;
> -    } else {
> -        // Update custom resolution
> -        custom.xres = mode->_width;
> -        custom.yres = mode->_height;
> -        custom.bpp = mode->_depth;
> -
> -        int err = ExtEscape(hdc, QXL_ESCAPE_SET_CUSTOM_DISPLAY,
> -                            sizeof(QXLEscapeSetCustomDisplay), (LPCSTR)&custom, 0, NULL);
> -        if (err <= 0) {
> -            vd_printf("can't set custom display, perhaps an old driver");
> -        }
> -        DeleteDC(hdc);
> -    }
> -
> -    // force refresh mode table
> -    DEVMODE tempDevMode;
> -    ZeroMemory(&tempDevMode, sizeof (tempDevMode));
> -    tempDevMode.dmSize = sizeof(DEVMODE);
> -    EnumDisplaySettings(dev_name, 0xffffff, &tempDevMode);
> -
> -    //Find the closest size which will fit within the monitor
> -    for (DWORD i = 0; EnumDisplaySettings(dev_name, i, dev_mode); i++) {
> -        if (dev_mode->dmPelsWidth > mode->_width ||
> -            dev_mode->dmPelsHeight > mode->_height ||
> -            dev_mode->dmBitsPerPel != mode->_depth) {
> -            continue;
> -        }
> -        DWORD wdiff = mode->_width - dev_mode->dmPelsWidth;
> -        DWORD hdiff = mode->_height - dev_mode->dmPelsHeight;
> -        DWORD diff = wdiff * wdiff + hdiff * hdiff;
> -        if (diff < closest_diff) {
> -            closest_diff = diff;
> -            best = i;
> -        }
> -    }
> -    if (best == (DWORD)-1 || !EnumDisplaySettings(dev_name, best, dev_mode)) {
> -        return false;
> -    }
> -    dev_mode->dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
> -    if (set_pos) {
> -        //Convert the position so that the primary is always at (0,0)
> -        dev_mode->dmPosition.x = mode->_pos_x - normal_x;
> -        dev_mode->dmPosition.y = mode->_pos_y - normal_y;
> -        dev_mode->dmFields |= DM_POSITION;
> -    }
>  
>      // update current DisplayMode (so mouse scaling works properly)
>      mode->_width = dev_mode->dmPelsWidth;
>      mode->_height = dev_mode->dmPelsHeight;
> -
>      return true;
> -}
> -
> -bool DesktopLayout::update_monitor_config(LPCTSTR dev_name, DisplayMode* mode)
> -{
> -    QXLHead monitor_config;
>  
> -    if (!mode || !mode->get_attached())
> -        return false;
> -
> -    //Don't configure monitors unless the client supports it
> -    if(!_send_monitors_position) return FALSE;
> -
> -    HDC hdc = CreateDC(dev_name, NULL, NULL, NULL);
> -
> -    memset(&monitor_config, 0, sizeof(monitor_config));
> -    monitor_config.x = mode->_pos_x;
> -    monitor_config.y = mode->_pos_y;
> -    monitor_config.width = mode->_width;
> -    monitor_config.height = mode->_height;
> -
> -    int err = ExtEscape(hdc, QXL_ESCAPE_MONITOR_CONFIG,
> -        sizeof(QXLHead), (LPCSTR) &monitor_config, 0, NULL);
> -
> -    if (err < 0){
> -        vd_printf("can't update monitor config, may have an older driver");
> -    }
> -
> -    DeleteDC(hdc);
> -    return (err >= 0);
>  }
> +
> diff --git a/vdagent/desktop_layout.h b/vdagent/desktop_layout.h
> index ece3946..fd6af76 100644
> --- a/vdagent/desktop_layout.h
> +++ b/vdagent/desktop_layout.h
> @@ -60,6 +60,7 @@ private:
>  };
>  
>  typedef std::vector<DisplayMode*> Displays;
> +class DisplayConfig;
>  
>  class DesktopLayout {
>  public:
> @@ -73,23 +74,21 @@ public:
>      size_t get_display_count() { return _displays.size();}
>      DWORD get_total_width() { return _total_width;}
>      DWORD get_total_height() { return _total_height;}
> -    void set_position_configurable(bool flag) { _send_monitors_position = flag; }
> +    void set_position_configurable(bool flag);
>  private:
>      void clean_displays();
>      void normalize_displays_pos();
>      DisplayMode * get_primary_display();
> -    bool update_monitor_config(LPCTSTR dev_name, DisplayMode* mode);
> +    bool init_dev_mode(LPCTSTR dev_name, DEVMODE* dev_mode, DisplayMode* mode);
>      static bool consistent_displays();
>      static bool is_attached(LPCTSTR dev_name);
>      static bool get_qxl_device_id(WCHAR* device_key, DWORD* device_id);
> -    static bool init_dev_mode(LPCTSTR dev_name, DEVMODE* dev_mode, DisplayMode* mode,
> -                              LONG normal_x, LONG normal_y, bool set_pos);
>  private:
>      mutex_t _mutex;
>      Displays _displays;
>      DWORD _total_width;
>      DWORD _total_height;
> -    bool _send_monitors_position;
> +    DisplayConfig* _display_config;
>  };
>  
>  #endif
> diff --git a/vdagent/display_configuration.cpp b/vdagent/display_configuration.cpp
> new file mode 100644
> index 0000000..19641e9
> --- /dev/null
> +++ b/vdagent/display_configuration.cpp
> @@ -0,0 +1,889 @@
> +/*
> +Copyright (C) 2015 Red Hat, Inc.
> +
> +This program is free software; you can redistribute it and/or
> +modify it under the terms of the GNU General Public License as
> +published by the Free Software Foundation; either version 2 of
> +the License, or (at your option) any later version.
> +
> +This program is distributed in the hope that it will be useful,
> +but WITHOUT ANY WARRANTY; without even the implied warranty of
> +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +GNU General Public License for more details.
> +
> +You should have received a copy of the GNU General Public License
> +along with this program.  If not, see <http://www.gnu.org/licenses/>.
> +*/
> +
> +#include "display_configuration.h"
> +#include <winternl.h>
> +//#include <ntstatus.h>
> +
> +typedef struct QXL_MONITOR_ESCAPE { 
> +    QXL_MONITOR_ESCAPE(DEVMODE* dev_mode) 
> +    {
> +        ZeroMemory(&_head, sizeof(_head));
> +        _head.x = dev_mode->dmPosition.x;
> +        _head.y = dev_mode->dmPosition.y;
> +        _head.width = dev_mode->dmPelsWidth;
> +        _head.height = dev_mode->dmPelsHeight;
> +
> +    }
> +    QXLHead _head;
> +}QXL_MONITOR_ESCAPE;
> +
> +typedef struct QxlCustomEscapeObj : public QXLEscapeSetCustomDisplay {
> +    QxlCustomEscapeObj(uint32_t bitsPerPel, uint32_t width, uint32_t height)
> +    {
> +        xres = width;
> +        yres = height;
> +        bpp = bitsPerPel;
> +    }
> +    QxlCustomEscapeObj() {};
> +}QxlCustomEscapeObj;
> +
> +#if (_WIN32_WINNT == _WIN32_WINNT_WIN10)
> +typedef  struct WDDM_CUSTOM_DISPLAY_ESCAPE {
> +    WDDM_CUSTOM_DISPLAY_ESCAPE(DEVMODE* dev_mode) 
> +    {
> +        _ioctl = QXL_ESCAPE_SET_CUSTOM_DISPLAY;
> +        _custom.bpp  = dev_mode->dmBitsPerPel;
> +        _custom.xres = dev_mode->dmPelsWidth;
> +        _custom.yres = dev_mode->dmPelsHeight;
> +    }
> +    int                         _ioctl;
> +    QXLEscapeSetCustomDisplay   _custom;
> +} WDDM_CUSTOM_DISPLAY_ESCAPE;
> +typedef struct WDDM_MONITOR_CONFIG_ESCAPE {
> +    WDDM_MONITOR_CONFIG_ESCAPE(DisplayMode* mode)
> +    {
> +        _ioctl = QXL_ESCAPE_MONITOR_CONFIG;
> +        _head.id = _head.surface_id = 0;
> +        _head.x = mode->get_pos_x();
> +        _head.y = mode->get_pos_y();
> +        _head.width = mode->get_width();
> +        _head.height = mode->get_height();
> +    }
> +    int         _ioctl;
> +    QXLHead     _head;
> +} WDDM_MONITOR_CONFIG_ESCAPE;
> +#endif
> +DisplayConfig* DisplayConfig::create_config() 
> +{
> +    DisplayConfig* new_interface;
> +#if (_WIN32_WINNT == _WIN32_WINNT_WIN10)
> +    //Try to open a WDDM adapter.
> +    new_interface = new  WDDMInterface();
> +    if(new_interface->type() == WDDM) {
> +        return new_interface;
> +    }
> +    //If that failed so clean up and assume we have an XPDM driver
> +    delete new_interface;
> +#endif
> +
> +    new_interface = new XPDMInterface();
> +    return new_interface;
> +}
> +
> +DisplayConfig::DisplayConfig()
> +    : _driver_type(INVALID_DRIVER)
> +    , _send_monitors_config(false)
> +{}
> +
> +bool XPDMInterface::is_attached(DISPLAY_DEVICE* dev_info)
> +{
> +    return !!(dev_info->StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP);
> +}
> +
> +bool XPDMInterface::set_monitor_state(LPCTSTR device_name, DEVMODE* dev_mode, MONITOR_STATE state)
> +{
> +    dev_mode->dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_POSITION;
> +    if(state == MONITOR_ATTACHED) {
> +        return true;
> +    }
> +    
> +    LONG status = ChangeDisplaySettingsEx(device_name, dev_mode, NULL, CDS_UPDATEREGISTRY, NULL);
> +    return (status == DISP_CHANGE_SUCCESSFUL);
> +}
> +
> +LONG XPDMInterface::update_display_settings()
> +{
> +    return ChangeDisplaySettingsEx(NULL, NULL, NULL, 0, NULL);
> +}
> +
> +bool XPDMInterface::update_dev_mode_position(LPCTSTR device_name, 
> +                                             DEVMODE* dev_mode, LONG x, LONG y)
> +{
> +    //Convert the position so that the primary is always at (0,0)
> +    dev_mode->dmPosition.x = x;
> +    dev_mode->dmPosition.y = y;
> +    dev_mode->dmFields |= DM_POSITION;
> +    vd_printf("%s: setting %S at (%lu, %lu)", __FUNCTION__, device_name, dev_mode->dmPosition.x,
> +        dev_mode->dmPosition.y);
> +    
> +    LONG status = ChangeDisplaySettingsEx(device_name, dev_mode, NULL, 
> +                                          CDS_UPDATEREGISTRY | CDS_NORESET, NULL);
> +    return (status == DISP_CHANGE_SUCCESSFUL);
> +}
> +
> +bool XPDMInterface::custom_display_escape(LPCTSTR device_name, DEVMODE* dev_mode)
> +{
> +    LONG        ret;
> +    NTSTATUS    Status (ERROR_SUCCESS);
> +    HDC         hdc = CreateDC(device_name, NULL, NULL, NULL);
> +
> +    if (!hdc) {
> +        ret = ChangeDisplaySettingsEx(device_name, dev_mode, NULL, CDS_UPDATEREGISTRY, NULL);
> +        if (ret == DISP_CHANGE_BADMODE) {
> +            // custom resolution might not be set yet, use known resolution
> +            // FIXME: this causes client temporary resize... a
> +            // solution would involve passing custom resolution before
> +            // driver initialization, perhaps through registry
> +            dev_mode->dmPelsWidth = 640;
> +            dev_mode->dmPelsHeight = 480;
> +            ret = ChangeDisplaySettingsEx(device_name, dev_mode, NULL, CDS_UPDATEREGISTRY, NULL);
> +        }
> +
> +        vd_printf("attach %ld", ret);
> +        if (!(hdc = CreateDC(device_name, NULL, NULL, NULL))) {
> +            vd_printf("%s: failed to create DC", __FUNCTION__);
> +            return false;
> +        }
> +    }
> +
> +    QxlCustomEscapeObj custom_escape(dev_mode->dmBitsPerPel,
> +                                            dev_mode->dmPelsWidth, dev_mode->dmPelsHeight);
> +
> +    int err = ExtEscape(hdc, QXL_ESCAPE_SET_CUSTOM_DISPLAY,
> +              sizeof(QXLEscapeSetCustomDisplay), (LPCSTR) &custom_escape, 0, NULL);
> +    if (err <= 0) {
> +        vd_printf("%s: Can't set custom display, perhaps running with an older driver?",
> +            __FUNCTION__);
> +    }
> +
> +    if(!find_best_mode(device_name, dev_mode)) {
> +        Status = E_FAIL;
> +    }
> +
> +    DeleteDC(hdc);
> +    return NT_SUCCESS(Status);
> +}
> +
> +bool XPDMInterface::update_monitor_config(LPCTSTR device_name, DisplayMode* mode,
> +                                           DEVMODE* dev_mode)
> +{
> +    if(!mode || !mode->get_attached()) {
> +        return false;
> +    }
> +
> +    QXL_MONITOR_ESCAPE  monitor_config(dev_mode);
> +    HDC hdc(CreateDC(device_name, NULL, NULL, NULL));
> +    int err(0);
> +    
> +    if (!hdc || !_send_monitors_config) {
> +        return false;
> +    }
> +
> +    err = ExtEscape(hdc, QXL_ESCAPE_MONITOR_CONFIG, sizeof(QXLHead),
> +                    (LPCSTR) &monitor_config, 0, NULL);
> +    if (err < 0) {
> +        vd_printf("%s: %S can't update monitor config, may have old, old driver",
> +		         __FUNCTION__, device_name);
> +    }
> +    DeleteDC(hdc);
> +    return (err >= 0);
> +}
> +
> +bool XPDMInterface::find_best_mode(LPCTSTR Device, DEVMODE* dev_mode)
> +{
> +    DWORD closest_diff = -1;
> +    DWORD best = -1;
> +
> +    // force refresh mode table
> +    DEVMODE test_dev_mode;
> +    ZeroMemory(&test_dev_mode, sizeof(test_dev_mode));
> +    test_dev_mode.dmSize = sizeof(DEVMODE);
> +    EnumDisplaySettings(Device, 0xffffff, &test_dev_mode);
> +
> +    //Find the closest size which will fit within the monitor
> +    for(DWORD i = 0; EnumDisplaySettings(Device, i, &test_dev_mode); i++) {
> +        if (dev_mode->dmPelsWidth > test_dev_mode.dmPelsWidth ||
> +            dev_mode->dmPelsHeight > test_dev_mode.dmPelsHeight ||
> +            dev_mode->dmBitsPerPel != test_dev_mode.dmBitsPerPel) {
> +            continue;
> +        }
> +        DWORD wdiff = dev_mode->dmPelsWidth - test_dev_mode.dmPelsWidth;
> +        DWORD hdiff = dev_mode->dmPelsHeight - test_dev_mode.dmPelsHeight;
> +        DWORD diff = wdiff * wdiff + hdiff * hdiff;
> +        if (diff < closest_diff) {
> +            closest_diff = diff;
> +            best = i;
> +        }
> +    }
> +    vd_printf("%s: closest_diff at %lu best %lu", __FUNCTION__, closest_diff, best);
> +    if (best == (DWORD) -1 || !EnumDisplaySettings(Device, best, dev_mode)) {
> +        return false;
> +    }
> +
> +    //Change to the best fit
> +    LONG status = ChangeDisplaySettingsEx(Device, dev_mode, NULL, 
> +                                          CDS_UPDATEREGISTRY | CDS_NORESET, NULL);
> +    return NT_SUCCESS(status);
> +}
> +#if (_WIN32_WINNT == _WIN32_WINNT_WIN10)
> +WDDMInterface::WDDMInterface()
> +    : _pfnOpen_adapter_hdc(NULL)
> +    , _pfnClose_adapter(NULL)
> +    , _pfnEscape(NULL)
> +    , _pfnOpen_adapter_device_name(NULL)
> +    , _pfnOpen_adapter_gdi_name(NULL)
> +{
> +    _driver_type = INVALID_DRIVER;
> +    
> +    //Did the CCD load?
> +    if(_ccd.error() == ERROR_NOT_SUPPORTED){
> +        return;
> +    }
> +
> +    //Can we find the D3D calls we need?
> +    if (!init_d3d_api()) {
> +        return;
> +    }
> +
> +    //Initialize  CCD path stuff 
> +    if (!_ccd.query_display_config()){
> +        return;;
> +    }
> +    if(!_ccd.set_display_config()) {
> +        return;
> +    }
> +    _driver_type = WDDM;
> +}
> +
> +WDDMInterface::~WDDMInterface()
> +{
> +    if (_driver_type != WDDM) {
> +        vd_printf("%s called with invalid driver type of %d", __FUNCTION__, _driver_type);
> +        return;
> +    }
> +}
> +
> +bool WDDMInterface::is_attached(DISPLAY_DEVICE* dev_info)
> +{
> +    return _ccd.is_attached(dev_info->DeviceName);
> +}
> +
> +bool WDDMInterface::set_monitor_state(LPCTSTR device_name, DEVMODE* dev_mode, MONITOR_STATE state)
> +{
> +   return  _ccd.set_path_state(device_name, state);
> +}
> +
> +bool WDDMInterface::custom_display_escape(LPCTSTR device_name, DEVMODE* dev_mode)
> +{
> +    DISPLAYCONFIG_MODE_INFO* mode = _ccd.get_active_mode(device_name, false);
> +    if (!mode) {
> +        return false;
> +    }
> +
> +    //Don't bother if we are already set to the new resolution
> +    if (mode->sourceMode.width == dev_mode->dmPelsWidth &&
> +        mode->sourceMode.height == dev_mode->dmPelsHeight) {
> +        return true;
> +    }
> +
> +    vd_printf("%s: updating %S resolution\n", __FUNCTION__, device_name);
> +
> +    WDDM_CUSTOM_DISPLAY_ESCAPE  wddm_escape (dev_mode);
> +    if(escape(device_name, &wddm_escape, sizeof(wddm_escape))) {
> +        return _ccd.update_mode_size(device_name, dev_mode);
> +    }
> +
> +    vd_printf("%s: (%dx%d)", __FUNCTION__, mode->sourceMode.width, mode->sourceMode.height);
> +    return false;
> +}
> +
> +bool WDDMInterface::update_monitor_config(LPCTSTR device_name, DisplayMode* display_mode,
> +                                           DEVMODE* dev_mode)
> +{
> +    if(!display_mode || !display_mode->get_attached()) {
> +        return false;
> +    }
> +    DISPLAYCONFIG_MODE_INFO* mode = _ccd.get_active_mode(device_name, false);
> +    if (!mode || !_send_monitors_config)
> +        return false;
> +
> +    WDDM_MONITOR_CONFIG_ESCAPE wddm_escape(display_mode);
> +    if(escape(device_name, &wddm_escape, sizeof(wddm_escape))) {
> +        //Update the path position
> +        return _ccd.update_mode_position(device_name, dev_mode);
> +    }
> +    
> +    vd_printf("%s: %S failed", __FUNCTION__, device_name);
> +    return false;
> +
> +}
> +
> +LONG WDDMInterface::update_display_settings()
> +{    
> +    //If we removed the primary monitor since the last call, we need to
> +    //reorder the other monitors, making the leftmost one the primary
> +    _ccd.verify_primary_position();
> +
> +    if (!_ccd.set_display_config()) {
> +        if(_ccd._error != ERROR_INVALID_PARAMETER) {
> +            vd_printf("%s: set_display_config failed", __FUNCTION__);
> +        }
> +        else {
> +            vd_printf("%s: Invalid parameter!", __FUNCTION__);
> +            _ccd.debug_print_config("After error");
> +        }
> +    }
> +    return _ccd.error();
> +}
> +
> +void WDDMInterface::update_config_path() 
> +{
> +    _ccd.query_display_config();
> +}
> +
> +bool WDDMInterface::update_dev_mode_position(LPCTSTR device_name, DEVMODE* dev_mode,
> +                                             LONG x, LONG y) 
> +{
> +    //Convert the position so that the primary is always at (0,0)
> +    dev_mode->dmPosition.x = x;
> +    dev_mode->dmPosition.y = y;
> +    _ccd.update_mode_position(device_name, dev_mode);
> +    return true;
> +}
> +
> +bool WDDMInterface::init_d3d_api()
> +{
> +    HMODULE hModule = LoadLibrary(L"gdi32.dll");
> +
> +    //Look for the gdi32 functions we need to perform driver escapes
> +    if(!hModule) {
> +        vd_printf("%s something wildly wrong as we can't open gdi32.dll", __FUNCTION__);
> +        _driver_type = INVALID_DRIVER;
> +        return false;
> +    }
> +
> +    do {
> +        _pfnClose_adapter = (PFND3DKMT_CLOSEADAPTER)
> +            GetProcAddress(hModule, "D3DKMTCloseAdapter");
> +        if (!_pfnClose_adapter) {
> +            break;
> +        }
> +
> +        _pfnEscape = (PFND3DKMT_ESCAPE) GetProcAddress(hModule, "D3DKMTEscape");
> +        if (!_pfnEscape) {
> +            break;
> +        }
> +
> +        _pfnOpen_adapter_hdc = (PFND3DKMT_OPENADAPTERFROMHDC)
> +            GetProcAddress(hModule, "D3DKMTOpenAdapterFromHdc");
> +        if (!_pfnOpen_adapter_hdc) {
> +            break;
> +        }
> +
> +        _pfnOpen_adapter_device_name = (PFND3DKMT_OPENADAPTERFROMDEVICENAME)
> +            GetProcAddress(hModule, "D3DKMTOpenAdapterFromDeviceName");
> +        if (!_pfnOpen_adapter_device_name) {
> +            break;
> +        }
> +
> +        _pfnOpen_adapter_gdi_name = (PFND3DKMT_OPENADAPTERFROMGDIDISPLAYNAME)
> +            GetProcAddress(hModule, "D3DKMTOpenAdapterFromGdiDisplayName");
> +        if (!_pfnOpen_adapter_gdi_name) {
> +            break;
> +        }
> +
> +    }
> +    while(0);
> +
> +    FreeLibrary(hModule);
> +
> +    //Did we get them ?
> +    if (!_pfnClose_adapter || !_pfnOpen_adapter_hdc || !_pfnEscape)  {
> +        return false;
> +    }
> +    _driver_type = WDDM;
> +    return true;
> +}
> +
> +D3DKMT_HANDLE WDDMInterface::adapter_handle(LPCTSTR device_name)
> +{
> +    D3DKMT_HANDLE hAdapter(0);
> +    
> +    //For some reason, unknown to me, this call will occasionally fail. 
> +    if ((hAdapter = handle_from_DC(device_name))) {
> +        return hAdapter;
> +    }
> +        //So try other available methods.
> +    if (_pfnOpen_adapter_device_name && (hAdapter = handle_from_device_name(device_name))) {
> +        return hAdapter;
> +    }
> +    //One last chance to open this guy
> +    if(_pfnOpen_adapter_gdi_name) {
> +        hAdapter = handle_from_GDI_name(device_name);
> +    }
> +
> +    if(!hAdapter) {
> +        vd_printf("%s: failed to open adapter %S", __FUNCTION__, device_name);
> +    }
> +
> +    return hAdapter;
> +}
> +
> +D3DKMT_HANDLE WDDMInterface::handle_from_DC(LPCTSTR adapter_name)
> +{
> +    NTSTATUS status;
> +    D3DKMT_OPENADAPTERFROMHDC open_data;
> +    HDC hDc(CreateDC(adapter_name, NULL, NULL, NULL));
> +
> +    if (!hDc) {
> +        vd_printf("%s: %S CreateDC failed with %lu", __FUNCTION__, adapter_name, GetLastError());
> +        return 0;
> +    }
> +
> +    ZeroMemory(&open_data, sizeof(D3DKMT_OPENADAPTERFROMHDC));
> +    open_data.hDc = hDc;
> +
> +    if (!NT_SUCCESS(status = _pfnOpen_adapter_hdc(&open_data))) {
> +        vd_printf("%s: %S open adapter from hdc failed with %lu", __FUNCTION__, adapter_name,
> +            status);
> +        open_data.hAdapter = 0;
> +    }
> +
> +    DeleteDC(hDc);
> +    return open_data.hAdapter;
> +}
> +
> +D3DKMT_HANDLE WDDMInterface::handle_from_device_name(LPCTSTR adapter_name)
> +{
> +    D3DKMT_OPENADAPTERFROMDEVICENAME display_name_data;
> +    NTSTATUS  status;
> +
> +    ZeroMemory(&display_name_data, sizeof(display_name_data));
> +    display_name_data.pDeviceName = adapter_name;
> +
> +    if (NT_SUCCESS(status = _pfnOpen_adapter_device_name(&display_name_data))) {
> +        return display_name_data.hAdapter;
> +    }
> +
> +    vd_printf("%s %S failed with 0x%lx", __FUNCTION__, adapter_name, status);
> +    return 0;
> +}
> +
> +D3DKMT_HANDLE WDDMInterface::handle_from_GDI_name(LPCTSTR adapter_name)
> +{
> +    D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME gdi_display_name;
> +    NTSTATUS status;
> +
> +    ZeroMemory(&gdi_display_name, sizeof(gdi_display_name));
> +    memcpy((void *) gdi_display_name.DeviceName, adapter_name, sizeof(TCHAR)* CCHDEVICENAME);
> +
> +    if (NT_SUCCESS(status = _pfnOpen_adapter_gdi_name(&gdi_display_name))) {
> +        return  gdi_display_name.hAdapter;
> +    }
> +
> +    vd_printf("%s: %S aurrrgghh nothing works..error  is 0x%lx", __FUNCTION__, adapter_name,
> +            status);
> +    return 0;
> +}
> +
> +void WDDMInterface::close_adapter(D3DKMT_HANDLE handle)
> +{
> +    D3DKMT_CLOSEADAPTER closeData;
> +    if (handle ){
> +        closeData.hAdapter = handle;
> +        _pfnClose_adapter(&closeData);
> +    }
> +}
> +
> +bool WDDMInterface::escape(LPCTSTR device_name, void* data, UINT size_data)
> +{
> +    D3DKMT_ESCAPE   escapeData;
> +    NTSTATUS        status;
> +    D3DKMT_HANDLE   hAdapter(0);
> +
> +    if (!(hAdapter = adapter_handle(device_name)))
> +        return false;
> +
> +    escapeData.hAdapter = hAdapter;
> +    escapeData.hDevice = 0;
> +    escapeData.hContext = 0;
> +    escapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
> +    escapeData.Flags.Value = 0;
> +    escapeData.pPrivateDriverData = data;
> +    escapeData.PrivateDriverDataSize = size_data;
> +
> +    status = _pfnEscape(&escapeData);   
> +
> +    if (!NT_SUCCESS(status)) {
> +        vd_printf("%s: this should never happen. Status is 0x%lx", __FUNCTION__, status);
> +        _driver_type = INVALID_DRIVER;
> +    }
> +
> +    //Close the handle to this device
> +    close_adapter(hAdapter);
> +    return NT_SUCCESS(status);
> +}
> +
> +CCD::CCD()
> +    :_NumPathElements(0)
> +    ,_NumModeElements(0)
> +    ,_pPathInfo(NULL)
> +    ,_pModeInfo(NULL)
> +    ,_pfnGetDeviceInfo(NULL)
> +    ,_pfnGetDisplayConfigBufferSizes(NULL)
> +    ,_pfnQueryDisplayConfig(NULL)
> +    ,_pfnSetDisplayConfig(NULL)
> +    ,_error(0)
> +    ,_primary_detached(false)
> +    ,_path_state(PATH_UPDATED)
> +{
> +    if(load_api()) {
> +        get_config_buffers();
> +    }
> +}
> +
> +CCD::~CCD()
> +{
> +    free_config_buffers();
> +}
> +
> +bool CCD::query_display_config()
> +{
> +    LONG query_error(ERROR_SUCCESS);
> +
> +    //Until we get it or error != ERROR_INSUFFICIENT_BUFFER
> +    do {
> +        query_error = _pfnQueryDisplayConfig(QDC_ALL_PATHS, &_NumPathElements, _pPathInfo,
> +            &_NumModeElements, _pModeInfo, NULL);
> +
> +        // if ERROR_INSUFFICIENT_BUFFER need to retry QueryDisplayConfig
> +        // to get a new set of config buffers
> +        //(see https://msdn.microsoft.com/en-us/library/windows/hardware/ff569215(v=vs.85).aspx )
> +        if (query_error) {
> +             if (query_error == ERROR_INSUFFICIENT_BUFFER) {
> +                free_config_buffers();
> +                if (!get_config_buffers())
> +                    return false;
> +            }
> +            else {
> +                _error = query_error;
> +                vd_printf("%s failed QueryDisplayConfig with 0x%lx", __FUNCTION__, _error);
> +                return false;
> +            }
> +        }
> +    } while(query_error);
> +    _path_state = PATH_CURRENT;
> +    return true;
> +}
> +
> +DISPLAYCONFIG_MODE_INFO* CCD::get_active_mode(LPCTSTR device_name, bool return_on_error)
> +{
> +    DISPLAYCONFIG_PATH_INFO* active_path;
> +
> +    active_path = get_device_path(device_name, true);
> +
> +    if (!active_path ) {
> +        vd_printf("%s:%S failed", __FUNCTION__, device_name);
> +        return NULL;
> +    }
> +    return &_pModeInfo[active_path->sourceInfo.modeInfoIdx];
> +}
> +
> +bool CCD::set_display_config() {
> +
> +    debug_print_config("Before SetDisplayConfig");
> +
> +    if (_path_state == PATH_CURRENT) {
> +        vd_printf("%s: path states says nothing changed", __FUNCTION__);
> +        return true;
> +    }
> +
> +    if(!(_error = _pfnSetDisplayConfig(_NumPathElements, _pPathInfo,
> +            _NumModeElements, _pModeInfo,
> +            SDC_APPLY | SDC_USE_SUPPLIED_DISPLAY_CONFIG | SDC_FORCE_MODE_ENUMERATION))) 
> +    {
> +        return true;
> +    }
> +
> +    vd_printf("%s failed SetDisplayConfig with 0x%lx", __FUNCTION__, _error);
> +    debug_print_config("After failed SetDisplayConfig");
> +    return false;
> +}
> +
> +DISPLAYCONFIG_PATH_INFO* CCD::get_device_path(LPCTSTR device_name, bool bActive)
> +{
> +    //Search for device's active path
> +    for(UINT32 i = 0; i < _NumPathElements; i++) {
> +        DISPLAYCONFIG_PATH_INFO* path_info = &_pPathInfo[i];
> +        
> +        //if bActive, return only paths that are currently active
> +        if(bActive && !is_active_path(path_info))
> +            continue;
> +        if (!is_device_path(device_name, path_info))
> +            continue;
> +        return path_info;
> +    }
> +    _error = ERROR_GEN_FAILURE;
> +    return NULL;
> +}
> +
> +void CCD::debug_print_config(const char* prefix)
> +{
> +    TCHAR dev_name[CCHDEVICENAME];
> +    for (UINT32 i = 0; i < _NumPathElements; i++) {
> +        DISPLAYCONFIG_PATH_INFO* path_info = &_pPathInfo[i];
> +        if (!(path_info->flags & DISPLAYCONFIG_PATH_ACTIVE))
> +            continue;
> +        get_device_name_config(path_info, dev_name);
> +
> +        if (path_info->sourceInfo.modeInfoIdx == DISPLAYCONFIG_PATH_MODE_IDX_INVALID) {
> +            vd_printf("%s: %S  [%s] This path is active but has invalid mode set.", __FUNCTION__,
> +                dev_name, prefix);
> +            continue;
> +        }
> +        DISPLAYCONFIG_MODE_INFO* mode = &_pModeInfo[path_info->sourceInfo.modeInfoIdx];
> +        vd_printf("%s: %S [%s] (%u,%u) (%ux%u).", __FUNCTION__, dev_name, prefix,
> +            mode->sourceMode.position.x, mode->sourceMode.position.y,
> +            mode->sourceMode.width, mode->sourceMode.height);
> +    }
> +}
> +
> +bool CCD::load_api() 
> +{
> +    HMODULE hModule = LoadLibrary(L"user32.dll");
> +    if(!hModule) {
> +        return false;
> +    }
> +
> +    bool bFound_all(false);
> +    do {
> +        if(!(_pfnGetDeviceInfo = (PDISPLAYCONFIG_GETDEVICEINFO)
> +            GetProcAddress(hModule, "DisplayConfigGetDeviceInfo"))) {
> +            break;
> +        }
> +
> +        if(!(_pfnGetDisplayConfigBufferSizes = (PGETDISPLAYCONFIG_BUFFERSIZES)
> +            GetProcAddress(hModule, "GetDisplayConfigBufferSizes"))) {
> +            break;
> +        }
> +
> +        if(!(_pfnQueryDisplayConfig = (PQUERYDISPLAYCONFIG)
> +            GetProcAddress(hModule, "QueryDisplayConfig"))) {
> +            break;
> +        }
> +
> +        if(!(_pfnSetDisplayConfig = (PSETDISPLAYCONFIG)
> +            GetProcAddress(hModule, "SetDisplayConfig"))) {
> +            break;
> +        }
> +        bFound_all = true;
> +    }
> +    while(0);
> +
> +    FreeLibrary(hModule);
> +    return bFound_all;
> +}
> +
> +bool CCD::get_config_buffers()
> +{
> +    //Get Config Buffer Sizes
> +    free_config_buffers();
> +    _error = _pfnGetDisplayConfigBufferSizes(QDC_ALL_PATHS, &_NumPathElements,
> +                                            &_NumModeElements);
> +    if (_error) {
> +        vd_printf("%s: GetDisplayConfigBufferSizes failed with 0x%lx", __FUNCTION__, _error);
> +        return false;
> +    }
> +
> +    //Allocate arrays
> +    _pPathInfo = ((DISPLAYCONFIG_PATH_INFO*) malloc(sizeof(DISPLAYCONFIG_PATH_INFO) * _NumPathElements));
> +    _pModeInfo = ((DISPLAYCONFIG_MODE_INFO*) malloc(sizeof(DISPLAYCONFIG_MODE_INFO) * _NumModeElements));
> +
> +    if (!_pPathInfo || !_pModeInfo) {
> +        vd_printf("%s OOM ", __FUNCTION__);
> +        return false;
> +    }
> +
> +    ///clear the above arrays
> +    ZeroMemory(_pPathInfo, sizeof(DISPLAYCONFIG_PATH_INFO) * _NumPathElements);
> +    ZeroMemory(_pModeInfo, sizeof(DISPLAYCONFIG_MODE_INFO) * _NumModeElements);
> +    return true;
> +}
> +
> +void CCD::free_config_buffers() 
> +{
> +    if (_pModeInfo) {
> +        free(_pModeInfo);
> +        _pModeInfo = NULL;
> +    }
> +    if (_pPathInfo) {
> +        free(_pPathInfo);
> +        _pPathInfo = NULL;
> +    }
> +    _NumModeElements = _NumPathElements = 0;
> +}
> +
> +bool  CCD::get_device_name_config(DISPLAYCONFIG_PATH_INFO* path, LPCTSTR dev_name)
> +{
> +    DISPLAYCONFIG_SOURCE_DEVICE_NAME source_name;
> +    source_name.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME;
> +    source_name.header.size = sizeof(DISPLAYCONFIG_SOURCE_DEVICE_NAME);
> +    source_name.header.adapterId = path->sourceInfo.adapterId;
> +    source_name.header.id = path->sourceInfo.id;
> +
> +    _error = _pfnGetDeviceInfo(&source_name.header);
> +    if (_error) {
> +        vd_printf("%s DisplayConfigGetDeviceInfo failed with %lu", __FUNCTION__, _error);
> +        return false;
> +    }
> +    memcpy((void *)dev_name, source_name.viewGdiDeviceName, CCHDEVICENAME* sizeof(TCHAR));
> +    return true;
> +}
> +
> +bool CCD::is_device_path(LPCTSTR device_name, DISPLAYCONFIG_PATH_INFO* path)
> +{
> +    //Does this path belong to device_name?
> +    TCHAR dev_name[CCHDEVICENAME];
> +    if (!get_device_name_config(path, dev_name)) {
> +        return false;
> +    }
> +    if (_tcscmp(dev_name, device_name)) {
> +        return false;
> +    }
> +    return true;
> +}
> +
> +// If we have detached the primary monitor, then we need to reset the positions of the remaining
> +// monitors to insure that at least one is positioned at (0,0)
> +bool CCD::verify_primary_position()
> +{
> +    LONG leftmost_x(0);
> +    if(!_primary_detached) {
> +        return true;
> +    }
> +    _primary_detached = false;
> +    
> +    for (UINT32 i = 0; i < _NumPathElements; i++) {
> +        DISPLAYCONFIG_PATH_INFO* path_info = &_pPathInfo[i];
> +        if (!(path_info->flags & DISPLAYCONFIG_PATH_ACTIVE))
> +            continue;
> +
> +        DISPLAYCONFIG_MODE_INFO* mode = &_pModeInfo[path_info->sourceInfo.modeInfoIdx];
> +        if (leftmost_x > mode->sourceMode.position.x) {
> +            leftmost_x = mode->sourceMode.position.x;
> +        }
> +    }
> +
> +    if (leftmost_x == 0) {
> +        return false;
> +    }
> +
> +    for (UINT32 i = 0; i < _NumPathElements; i++) {
> +        DISPLAYCONFIG_PATH_INFO* path_info = &_pPathInfo[i];
> +        if ((!(path_info->flags & DISPLAYCONFIG_PATH_ACTIVE)))
> +            continue;
> +        DISPLAYCONFIG_MODE_INFO* mode = &_pModeInfo[path_info->sourceInfo.modeInfoIdx];
> +        vd_printf("%s: setting mode x to %lu", __FUNCTION__, mode->sourceMode.position.x);
> +        mode->sourceMode.position.x -= leftmost_x;
> +    }
> +    _path_state = PATH_UPDATED;
> +    return true;
> +}
> +
> +bool CCD::update_mode_position(LPCTSTR device_name, DEVMODE* dev_mode)
> +{
> +    DISPLAYCONFIG_MODE_INFO* mode = get_active_mode(device_name, false);
> +    if (!mode)
> +        return false;
> +
> +    mode->sourceMode.position.x = dev_mode->dmPosition.x;
> +    mode->sourceMode.position.y = dev_mode->dmPosition.y;
> +    vd_printf("%s: %S updated path mode to (%lu, %lu) - (%u x%u)", __FUNCTION__,
> +        device_name,
> +        mode->sourceMode.position.x, mode->sourceMode.position.y,
> +        mode->sourceMode.width, mode->sourceMode.height);
> +    _path_state = PATH_UPDATED;
> +    return true;
> +
> +}
> +
> +bool CCD::update_mode_size(LPCTSTR device_name, DEVMODE* dev_mode)
> +{
> +    DISPLAYCONFIG_MODE_INFO* mode = get_active_mode(device_name, false);
> +    if (!mode) {
> +        return false;
> +    }
> +
> +    mode->sourceMode.width = dev_mode->dmPelsWidth;
> +    mode->sourceMode.height = dev_mode->dmPelsHeight;
> +    vd_printf("%s: %S updated path mode to (%lu, %lu - (%u x %u)", __FUNCTION__,
> +        device_name,
> +        mode->sourceMode.position.x, mode->sourceMode.position.y,
> +        mode->sourceMode.width, mode->sourceMode.height);
> +    _path_state = PATH_UPDATED;
> +    return true;
> +}
> +
> +void CCD::update_detached_primary_state(LPCTSTR device_name, DISPLAYCONFIG_PATH_INFO * path_info)
> +{
> +    DISPLAYCONFIG_MODE_INFO* mode(get_active_mode(device_name, false));
> +
> +    //will need to reset monitor positions if primary detached
> +    path_info->flags = path_info->flags & ~DISPLAYCONFIG_PATH_ACTIVE;
> +    if (!mode|| mode->sourceMode.position.x != 0 || mode->sourceMode.position.y != 0) {
> +        return ;
> +    }
> +    _primary_detached = true;
> +}
> +
> +bool CCD::set_path_state(LPCTSTR device_name, MONITOR_STATE new_state)
> +{
> +    DISPLAYCONFIG_PATH_INFO* path(get_device_path(device_name, false));
> +    MONITOR_STATE current_path_state(MONITOR_DETACHED);
> +
> +    if(path && (path->flags & DISPLAYCONFIG_PATH_ACTIVE)) {
> +        current_path_state = MONITOR_ATTACHED;
> +    }
> +    
> +    //If state didn't change, nothing to do
> +    if(current_path_state == new_state ) {
> +        return true;
> +    }
> +
> +    if(!path) {
> +        return false;
> +    }
> +    
> +    _path_state = PATH_UPDATED;
> +    if (new_state == MONITOR_DETACHED) {
> +        update_detached_primary_state(device_name, path);
> +    }
> +    else {
> +        path->flags = path->flags | DISPLAYCONFIG_PATH_ACTIVE;
> +    }
> +    return true;
> +}
> +
> +bool CCD::is_attached(LPCTSTR device_name)
> +{
> +    DISPLAYCONFIG_PATH_INFO* path(get_device_path(device_name, false));
> +    if(!path) {
> +        return false;
> +    }
> +    return (path->flags & DISPLAYCONFIG_PATH_ACTIVE);
> +}
> +
> +bool CCD::is_active_path(DISPLAYCONFIG_PATH_INFO * path) 
> +{
> +    if(!path || !(path->flags & DISPLAYCONFIG_PATH_ACTIVE) ||
> +        (path->sourceInfo.modeInfoIdx == DISPLAYCONFIG_PATH_MODE_IDX_INVALID)) {
> +        return false;
> +    }
> +    return true;
> +}
> +#endif
> \ No newline at end of file
> diff --git a/vdagent/display_configuration.h b/vdagent/display_configuration.h
> new file mode 100644
> index 0000000..eeba1c2
> --- /dev/null
> +++ b/vdagent/display_configuration.h
> @@ -0,0 +1,192 @@
> +/*
> +Copyright (C) 2015 Red Hat, Inc.
> +
> +This program is free software; you can redistribute it and/or
> +modify it under the terms of the GNU General Public License as
> +published by the Free Software Foundation; either version 2 of
> +the License, or (at your option) any later version.
> +
> +This program is distributed in the hope that it will be useful,
> +but WITHOUT ANY WARRANTY; without even the implied warranty of
> +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +GNU General Public License for more details.
> +
> +You should have received a copy of the GNU General Public License
> +along with this program.  If not, see <http://www.gnu.org/licenses/>.
> +*/
> +#pragma once
> +#include <sdkddkver.h>
> +#include <windows.h>
> +#include <d3dtypes.h>
> +#include "vdlog.h"
> +
> +#ifdef __MINGW32__
> +#include "d3dkmt.h"
> +#include "CCD.h"
> +#endif
> +
> +//Check for a reasonable SDK
> +#if (_WIN32_WINNT < _WIN32_WINNT_WINXP)
> +#error required Windows WDK not found
> +#endif
> +
> +//Windows 10 build only
> +#if (_WIN32_WINNT == _WIN32_WINNT_WIN10)
> +#include <d3dumddi.h>
> +#include <km/D3dkmthk.h>
> +#endif
> +
> +#include <spice/qxl_windows.h>
> +#include <spice/qxl_dev.h>
> +#include "desktop_layout.h"
> +#include "vdlog.h"
> +
> +typedef enum {
> +    XPDM,
> +    WDDM,
> +    INVALID_DRIVER,
> +}DRIVER_TYPE;
> +
> +typedef enum {
> +    MONITOR_DETACHED,
> +    MONITOR_ATTACHED,
> +}MONITOR_STATE;
> +
> +typedef enum {
> +    PATH_UPDATED,
> +    PATH_CURRENT,
> +}PATH_STATE;
> +
> +#if (_WIN32_WINNT == _WIN32_WINNT_WIN10)
> +//Makes calls into the CCD API for getting/setting display settings on WDDM drivers
> +//Use is exclusive to wddm display config class
> +
> +typedef LONG(APIENTRY* PDISPLAYCONFIG_GETDEVICEINFO)(DISPLAYCONFIG_DEVICE_INFO_HEADER*);
> +typedef LONG(APIENTRY* PGETDISPLAYCONFIG_BUFFERSIZES)(UINT32, UINT32*, UINT32*);
> +typedef LONG(APIENTRY* PQUERYDISPLAYCONFIG)(UINT32, UINT32*, DISPLAYCONFIG_PATH_INFO*, UINT32*,
> +                                            DISPLAYCONFIG_MODE_INFO*, DISPLAYCONFIG_TOPOLOGY_ID*);
> +typedef LONG(APIENTRY* PSETDISPLAYCONFIG)(UINT32, DISPLAYCONFIG_PATH_INFO*, UINT32, 
> +                                          DISPLAYCONFIG_MODE_INFO*, UINT32);
> +
> +class CCD {
> +protected:
> +    CCD();
> +    ~CCD();
> +
> +    bool query_display_config();
> +    bool set_display_config();
> +    bool update_mode_position(LPCTSTR device_name, DEVMODE* dev_mode);
> +    bool update_mode_size(LPCTSTR DeviceNmae, DEVMODE* dev_mode);
> +    void update_detached_primary_state(LPCTSTR device_name, DISPLAYCONFIG_PATH_INFO * path_info);
> +    bool set_path_state(LPCTSTR device_name, MONITOR_STATE state);
> +    bool is_attached(LPCTSTR device_name);
> +    bool is_active_path(DISPLAYCONFIG_PATH_INFO * path);
> +    LONG error() { return _error; }
> +
> +private:
> +    bool load_api();
> +    bool get_config_buffers();
> +    void free_config_buffers();
> +    bool verify_primary_position();
> +    bool is_device_path(LPCTSTR device_name, DISPLAYCONFIG_PATH_INFO* path);
> +    DISPLAYCONFIG_MODE_INFO* get_active_mode(LPCTSTR device_name, bool return_on_error);
> +    DISPLAYCONFIG_PATH_INFO* get_device_path(LPCTSTR device_name, bool bActive);
> +    bool get_device_name_config(DISPLAYCONFIG_PATH_INFO* path, LPCTSTR dev_name);
> +    void debug_print_config(const char* prefix = NULL);
> +
> +private:
> +    //CCD API stuff
> +    UINT32 _NumPathElements;
> +    UINT32 _NumModeElements;
> +    DISPLAYCONFIG_PATH_INFO* _pPathInfo;
> +    DISPLAYCONFIG_MODE_INFO* _pModeInfo;
> +
> +    //CCD API function pointers
> +    PDISPLAYCONFIG_GETDEVICEINFO _pfnGetDeviceInfo;
> +    PGETDISPLAYCONFIG_BUFFERSIZES _pfnGetDisplayConfigBufferSizes;
> +    PQUERYDISPLAYCONFIG _pfnQueryDisplayConfig;
> +    PSETDISPLAYCONFIG _pfnSetDisplayConfig;
> +	
> +    LONG  _error;
> +    bool  _primary_detached;
> +    PATH_STATE _path_state;
> +    friend class WDDMInterface;
> +};
> +#endif
> +
> +class DisplayMode;
> +
> +//Class provides interface to get/set display configurations
> +class DisplayConfig {
> +public:
> +    static DisplayConfig* create_config();
> +    DisplayConfig();;
> +    virtual ~DisplayConfig() {};
> +
> +    virtual bool is_attached(DISPLAY_DEVICE* dev_info) = 0;
> +    virtual bool custom_display_escape(LPCTSTR device, DEVMODE* mode) = 0;
> +    virtual bool update_monitor_config(LPCTSTR device, DisplayMode* mode, DEVMODE* dev_mode) = 0;
> +    virtual bool set_monitor_state(LPCTSTR device_name, DEVMODE* dev_mode, MONITOR_STATE state) = 0;
> +    virtual LONG update_display_settings() = 0;
> +    virtual bool update_dev_mode_position(LPCTSTR dev_name, DEVMODE* dev_mode, LONG x, LONG y) = 0;
> +    DRIVER_TYPE type() { return _driver_type; };
> +    void set_monitors_config(bool flag) { _send_monitors_config = flag; }
> +    virtual void update_config_path() {};
> +
> +protected:
> +    DRIVER_TYPE _driver_type;
> +    bool _send_monitors_config;
> +};
> +
> +//DisplayConfig implementation for guest with XPDM graphics drivers
> +class XPDMInterface : public DisplayConfig {
> +public:
> +    XPDMInterface() :DisplayConfig() { _driver_type = XPDM; };
> +    ~XPDMInterface() {}
> +    bool is_attached(DISPLAY_DEVICE* dev_info);;
> +    bool custom_display_escape(LPCTSTR device_name, DEVMODE* dev_mode);
> +    bool update_monitor_config(LPCTSTR device_name, DisplayMode* mode, DEVMODE* dev_mode);
> +    bool set_monitor_state(LPCTSTR device_name, DEVMODE* dev_mode, MONITOR_STATE state);
> +    LONG update_display_settings();
> +    bool update_dev_mode_position(LPCTSTR device_name, DEVMODE * dev_mode, LONG x, LONG y);
> +
> +private:
> +    bool find_best_mode(LPCTSTR Device, DEVMODE* dev_mode);
> +};
> +#if (_WIN32_WINNT == _WIN32_WINNT_WIN10)
> +//DisplayConfig implementation for guest with WDDM graphics drivers
> +class WDDMInterface : public DisplayConfig {
> +public:
> +    WDDMInterface();
> +    ~WDDMInterface();
> +    bool is_attached(DISPLAY_DEVICE* dev_info);
> +    bool set_monitor_state(LPCTSTR device_name, DEVMODE* dev_mode, MONITOR_STATE state);
> +    LONG update_display_settings();
> +    bool custom_display_escape(LPCTSTR device_name, DEVMODE* dev_mode);
> +    bool update_monitor_config(LPCTSTR device_name, DisplayMode* mode, DEVMODE* dev_mode);
> +    bool update_dev_mode_position(LPCTSTR device_name, DEVMODE * dev_mode, LONG x, LONG y);
> +    void update_config_path();
> +
> +private:
> +    bool init_d3d_api();
> +    D3DKMT_HANDLE adapter_handle(LPCTSTR device_name);
> +    D3DKMT_HANDLE handle_from_DC(LPCTSTR adapter_name);
> +    D3DKMT_HANDLE handle_from_device_name(LPCTSTR adapter_name);
> +    D3DKMT_HANDLE handle_from_GDI_name(LPCTSTR adapter_name);
> +
> +    void close_adapter(D3DKMT_HANDLE handle);
> +    bool escape(LPCTSTR device_name, void* data, UINT sizeData);
> +
> +private:
> +    //GDI Function pointers
> +    PFND3DKMT_OPENADAPTERFROMHDC _pfnOpen_adapter_hdc;
> +    PFND3DKMT_CLOSEADAPTER  _pfnClose_adapter;
> +    PFND3DKMT_ESCAPE _pfnEscape;
> +    PFND3DKMT_OPENADAPTERFROMDEVICENAME _pfnOpen_adapter_device_name;
> +    PFND3DKMT_OPENADAPTERFROMGDIDISPLAYNAME _pfnOpen_adapter_gdi_name;
> +
> +    //object handles the CCD API
> +    CCD _ccd;
> +};
> +#endif
> +typedef class DisplayConfig DISPLAY_CONFIG;
> diff --git a/vdagent/vdagent.vcxproj b/vdagent/vdagent.vcxproj
> new file mode 100644
> index 0000000..4f6f54a
> --- /dev/null
> +++ b/vdagent/vdagent.vcxproj
> @@ -0,0 +1,380 @@
> +<?xml version="1.0" encoding="utf-8"?>
> +<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
> +  <ItemGroup Label="ProjectConfigurations">
> +    <ProjectConfiguration Include="Debug|Win32">
> +      <Configuration>Debug</Configuration>
> +      <Platform>Win32</Platform>
> +    </ProjectConfiguration>
> +    <ProjectConfiguration Include="Debug|x64">
> +      <Configuration>Debug</Configuration>
> +      <Platform>x64</Platform>
> +    </ProjectConfiguration>
> +    <ProjectConfiguration Include="Release|Win32">
> +      <Configuration>Release</Configuration>
> +      <Platform>Win32</Platform>
> +    </ProjectConfiguration>
> +    <ProjectConfiguration Include="Release|x64">
> +      <Configuration>Release</Configuration>
> +      <Platform>x64</Platform>
> +    </ProjectConfiguration>
> +    <ProjectConfiguration Include="Win10 Debug|Win32">
> +      <Configuration>Win10 Debug</Configuration>
> +      <Platform>Win32</Platform>
> +    </ProjectConfiguration>
> +    <ProjectConfiguration Include="Win10 Debug|x64">
> +      <Configuration>Win10 Debug</Configuration>
> +      <Platform>x64</Platform>
> +    </ProjectConfiguration>
> +    <ProjectConfiguration Include="Win10 Release|Win32">
> +      <Configuration>Win10 Release</Configuration>
> +      <Platform>Win32</Platform>
> +    </ProjectConfiguration>
> +    <ProjectConfiguration Include="Win10 Release|x64">
> +      <Configuration>Win10 Release</Configuration>
> +      <Platform>x64</Platform>
> +    </ProjectConfiguration>
> +  </ItemGroup>
> +  <PropertyGroup Label="Globals">
> +    <ProjectGuid>{CAD5A7E6-E9F5-4071-AFDA-25F76FDA5442}</ProjectGuid>
> +    <RootNamespace>redagent</RootNamespace>
> +    <Keyword>Win32Proj</Keyword>
> +    <WindowsTargetPlatformVersion>10.0.10240.0</WindowsTargetPlatformVersion>
> +  </PropertyGroup>
> +  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
> +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
> +    <ConfigurationType>Application</ConfigurationType>
> +    <PlatformToolset>v140</PlatformToolset>
> +    <CharacterSet>Unicode</CharacterSet>
> +    <WholeProgramOptimization>true</WholeProgramOptimization>
> +  </PropertyGroup>
> +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
> +    <ConfigurationType>Application</ConfigurationType>
> +    <PlatformToolset>v140</PlatformToolset>
> +    <CharacterSet>Unicode</CharacterSet>
> +  </PropertyGroup>
> +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win10 Debug|Win32'" Label="Configuration">
> +    <ConfigurationType>Application</ConfigurationType>
> +    <PlatformToolset>v140</PlatformToolset>
> +    <CharacterSet>Unicode</CharacterSet>
> +  </PropertyGroup>
> +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
> +    <ConfigurationType>Application</ConfigurationType>
> +    <PlatformToolset>v140</PlatformToolset>
> +    <CharacterSet>Unicode</CharacterSet>
> +    <WholeProgramOptimization>true</WholeProgramOptimization>
> +  </PropertyGroup>
> +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
> +    <ConfigurationType>Application</ConfigurationType>
> +    <PlatformToolset>v140</PlatformToolset>
> +    <CharacterSet>Unicode</CharacterSet>
> +  </PropertyGroup>
> +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win10 Debug|x64'" Label="Configuration">
> +    <ConfigurationType>Application</ConfigurationType>
> +    <PlatformToolset>v140</PlatformToolset>
> +    <CharacterSet>Unicode</CharacterSet>
> +  </PropertyGroup>
> +  <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Win10 Release|Win32'">
> +    <PlatformToolset>v140</PlatformToolset>
> +    <CharacterSet>Unicode</CharacterSet>
> +  </PropertyGroup>
> +  <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Win10 Release|x64'">
> +    <PlatformToolset>v140</PlatformToolset>
> +    <CharacterSet>Unicode</CharacterSet>
> +  </PropertyGroup>
> +  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
> +  <ImportGroup Label="ExtensionSettings">
> +  </ImportGroup>
> +  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
> +    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
> +    <Import Project="..\Spice.props" />
> +  </ImportGroup>
> +  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
> +    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
> +    <Import Project="..\Spice.props" />
> +  </ImportGroup>
> +  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Win10 Debug|Win32'" Label="PropertySheets">
> +    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
> +    <Import Project="..\Spice.props" />
> +  </ImportGroup>
> +  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
> +    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
> +    <Import Project="..\Spice.props" />
> +  </ImportGroup>
> +  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
> +    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
> +    <Import Project="..\Spice.props" />
> +  </ImportGroup>
> +  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Win10 Debug|x64'" Label="PropertySheets">
> +    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
> +    <Import Project="..\Spice.props" />
> +  </ImportGroup>
> +  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Win10 Release|x64'">
> +    <Import Project="..\Spice.props" />
> +  </ImportGroup>
> +  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Win10 Release|Win32'">
> +    <Import Project="..\Spice.props" />
> +  </ImportGroup>
> +  <PropertyGroup Label="UserMacros" />
> +  <PropertyGroup>
> +    <_ProjectFileVersion>14.0.23107.0</_ProjectFileVersion>
> +  </PropertyGroup>
> +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
> +    <OutDir>$(SolutionDir)$(Configuration)\</OutDir>
> +    <IntDir>$(Configuration)\</IntDir>
> +    <LinkIncremental>true</LinkIncremental>
> +  </PropertyGroup>
> +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win10 Debug|Win32'">
> +    <OutDir>$(SolutionDir)$(Configuration)\</OutDir>
> +    <IntDir>$(Configuration)\</IntDir>
> +    <LinkIncremental>true</LinkIncremental>
> +  </PropertyGroup>
> +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
> +    <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
> +    <IntDir>$(Platform)\$(Configuration)\</IntDir>
> +    <LinkIncremental>true</LinkIncremental>
> +  </PropertyGroup>
> +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win10 Debug|x64'">
> +    <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
> +    <IntDir>$(Platform)\$(Configuration)\</IntDir>
> +    <LinkIncremental>true</LinkIncremental>
> +  </PropertyGroup>
> +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
> +    <OutDir>$(SolutionDir)$(Configuration)\</OutDir>
> +    <IntDir>$(Configuration)\</IntDir>
> +    <LinkIncremental>false</LinkIncremental>
> +  </PropertyGroup>
> +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
> +    <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
> +    <IntDir>$(Platform)\$(Configuration)\</IntDir>
> +    <LinkIncremental>false</LinkIncremental>
> +  </PropertyGroup>
> +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win10 Release|x64'">
> +    <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
> +  </PropertyGroup>
> +  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
> +    <ClCompile>
> +      <Optimization>Disabled</Optimization>
> +      <AdditionalIncludeDirectories>..\common;$(SPICE_PROTOCOL_DIR);$(SPICE_LIBS)\include\CxImage;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
> +      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_WIN32_WINNT=0x0501;%(PreprocessorDefinitions)</PreprocessorDefinitions>
> +      <MinimalRebuild>true</MinimalRebuild>
> +      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
> +      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
> +      <PrecompiledHeader />
> +      <WarningLevel>Level3</WarningLevel>
> +      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
> +    </ClCompile>
> +    <Link>
> +      <AdditionalDependencies>Version.lib;$(SPICE_DEBUG_LIB_LIST);wtsapi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
> +      <AdditionalLibraryDirectories>$(SPICE_DEBUG_LIBS_DIR);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
> +      <GenerateDebugInformation>true</GenerateDebugInformation>
> +      <SubSystem>Windows</SubSystem>
> +      <RandomizedBaseAddress>false</RandomizedBaseAddress>
> +      <DataExecutionPrevention />
> +      <TargetMachine>MachineX86</TargetMachine>
> +    </Link>
> +    <PostBuildEvent>
> +      <Command>
> +      </Command>
> +    </PostBuildEvent>
> +  </ItemDefinitionGroup>
> +  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Win10 Debug|Win32'">
> +    <ClCompile>
> +      <Optimization>Disabled</Optimization>
> +      <AdditionalIncludeDirectories>..\common;$(SPICE_PROTOCOL_DIR);$(SPICE_LIBS)\include\CxImage;$(WindowsSdkDir)\Include\$(TargetPlatformVersion);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
> +      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_WIN32_WINNT=_WIN32_WINNT_WIN10;%(PreprocessorDefinitions)</PreprocessorDefinitions>
> +      <MinimalRebuild>true</MinimalRebuild>
> +      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
> +      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
> +      <PrecompiledHeader>
> +      </PrecompiledHeader>
> +      <WarningLevel>Level3</WarningLevel>
> +      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
> +    </ClCompile>
> +    <Link>
> +      <AdditionalDependencies>Version.lib;$(SPICE_DEBUG_LIB_LIST);wtsapi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
> +      <AdditionalLibraryDirectories>$(SPICE_DEBUG_LIBS_DIR);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
> +      <GenerateDebugInformation>true</GenerateDebugInformation>
> +      <SubSystem>Windows</SubSystem>
> +      <RandomizedBaseAddress>false</RandomizedBaseAddress>
> +      <DataExecutionPrevention>
> +      </DataExecutionPrevention>
> +      <TargetMachine>MachineX86</TargetMachine>
> +    </Link>
> +    <PostBuildEvent>
> +      <Command>
> +      </Command>
> +    </PostBuildEvent>
> +  </ItemDefinitionGroup>
> +  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
> +    <Midl>
> +      <TargetEnvironment>X64</TargetEnvironment>
> +    </Midl>
> +    <ClCompile>
> +      <Optimization>Disabled</Optimization>
> +      <AdditionalIncludeDirectories>..\common;$(SPICE_PROTOCOL_DIR);$(SPICE_LIBS)\include\CxImage;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
> +      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_WIN32_WINNT=0x0501;%(PreprocessorDefinitions)</PreprocessorDefinitions>
> +      <MinimalRebuild>true</MinimalRebuild>
> +      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
> +      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
> +      <PrecompiledHeader />
> +      <WarningLevel>Level3</WarningLevel>
> +      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
> +    </ClCompile>
> +    <Link>
> +      <AdditionalDependencies>Version.lib;$(SPICE_DEBUG_LIB_LIST);wtsapi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
> +      <AdditionalLibraryDirectories>$(SPICE_DEBUG_LIBS_DIR);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
> +      <GenerateDebugInformation>true</GenerateDebugInformation>
> +      <SubSystem>Windows</SubSystem>
> +      <RandomizedBaseAddress>false</RandomizedBaseAddress>
> +      <DataExecutionPrevention />
> +      <TargetMachine>MachineX64</TargetMachine>
> +    </Link>
> +    <PostBuildEvent>
> +      <Command>
> +      </Command>
> +    </PostBuildEvent>
> +  </ItemDefinitionGroup>
> +  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Win10 Debug|x64'">
> +    <Midl>
> +      <TargetEnvironment>X64</TargetEnvironment>
> +    </Midl>
> +    <ClCompile>
> +      <Optimization>Disabled</Optimization>
> +      <AdditionalIncludeDirectories>..\common;$(SPICE_PROTOCOL_DIR);$(SPICE_LIBS)\include\CxImage;$(WindowsSdkDir)\Include\$(TargetPlatformVersion);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
> +      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
> +      <MinimalRebuild>true</MinimalRebuild>
> +      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
> +      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
> +      <PrecompiledHeader>
> +      </PrecompiledHeader>
> +      <WarningLevel>Level3</WarningLevel>
> +      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
> +    </ClCompile>
> +    <Link>
> +      <AdditionalDependencies>Version.lib;$(SPICE_DEBUG_LIB_LIST);wtsapi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
> +      <AdditionalLibraryDirectories>$(SPICE_DEBUG_LIBS_DIR);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
> +      <GenerateDebugInformation>true</GenerateDebugInformation>
> +      <SubSystem>Windows</SubSystem>
> +      <RandomizedBaseAddress>false</RandomizedBaseAddress>
> +      <DataExecutionPrevention>
> +      </DataExecutionPrevention>
> +      <TargetMachine>MachineX64</TargetMachine>
> +    </Link>
> +    <PostBuildEvent>
> +      <Command>
> +      </Command>
> +    </PostBuildEvent>
> +  </ItemDefinitionGroup>
> +  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
> +    <ClCompile>
> +      <AdditionalIncludeDirectories>..\common;$(SPICE_PROTOCOL_DIR);$(SPICE_LIBS)\include\CxImage;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
> +      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_WIN32_WINNT=0x0501;%(PreprocessorDefinitions)</PreprocessorDefinitions>
> +      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
> +      <PrecompiledHeader />
> +      <WarningLevel>Level3</WarningLevel>
> +      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
> +    </ClCompile>
> +    <Link>
> +      <AdditionalDependencies>Version.lib;$(SPICE_LIB_LIST);wtsapi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
> +      <AdditionalLibraryDirectories>$(SPICE_LIBS_DIR);$(SPICE_LIBS_DIR);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
> +      <GenerateDebugInformation>true</GenerateDebugInformation>
> +      <SubSystem>Windows</SubSystem>
> +      <OptimizeReferences>true</OptimizeReferences>
> +      <EnableCOMDATFolding>true</EnableCOMDATFolding>
> +      <RandomizedBaseAddress>false</RandomizedBaseAddress>
> +      <DataExecutionPrevention />
> +      <TargetMachine>MachineX86</TargetMachine>
> +    </Link>
> +    <PostBuildEvent>
> +      <Command>
> +      </Command>
> +    </PostBuildEvent>
> +  </ItemDefinitionGroup>
> +  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
> +    <Midl>
> +      <TargetEnvironment>X64</TargetEnvironment>
> +    </Midl>
> +    <ClCompile>
> +      <AdditionalIncludeDirectories>..\common;$(SPICE_PROTOCOL_DIR);$(SPICE_LIBS)\include\CxImage;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
> +      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_WIN32_WINNT=0x0501;%(PreprocessorDefinitions)</PreprocessorDefinitions>
> +      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
> +      <PrecompiledHeader />
> +      <WarningLevel>Level3</WarningLevel>
> +      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
> +    </ClCompile>
> +    <Link>
> +      <AdditionalDependencies>Version.lib;$(SPICE_LIB_LIST);wtsapi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
> +      <AdditionalLibraryDirectories>$(SPICE_LIBS_DIR);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
> +      <GenerateDebugInformation>true</GenerateDebugInformation>
> +      <SubSystem>Windows</SubSystem>
> +      <OptimizeReferences>true</OptimizeReferences>
> +      <EnableCOMDATFolding>true</EnableCOMDATFolding>
> +      <RandomizedBaseAddress>false</RandomizedBaseAddress>
> +      <DataExecutionPrevention />
> +      <TargetMachine>MachineX64</TargetMachine>
> +    </Link>
> +    <PostBuildEvent>
> +      <Command>
> +      </Command>
> +    </PostBuildEvent>
> +  </ItemDefinitionGroup>
> +  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Win10 Release|x64'">
> +    <ClCompile>
> +      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_WIN32_WINNT=_WIN32_WINNT_WIN10;%(PreprocessorDefinitions)</PreprocessorDefinitions>
> +      <AdditionalIncludeDirectories>..\common;$(SPICE_PROTOCOL_DIR);$(SPICE_LIBS)\include\CxImage;$(WindowsSdkDir)\Include\$(TargetPlatformVersion);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
> +      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
> +    </ClCompile>
> +    <Link>
> +      <AdditionalDependencies>Version.lib;$(SPICE_LIB_LIST);wtsapi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
> +      <AdditionalLibraryDirectories>$(SPICE_LIBS_DIR);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
> +    </Link>
> +    <PostBuildEvent>
> +      <Command>
> +      </Command>
> +    </PostBuildEvent>
> +  </ItemDefinitionGroup>
> +  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Win10 Release|Win32'">
> +    <ClCompile>
> +      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_WIN32_WINNT=_WIN32_WINNT_WIN10;%(PreprocessorDefinitions)</PreprocessorDefinitions>
> +      <AdditionalIncludeDirectories>..\common;$(SPICE_PROTOCOL_DIR);$(SPICE_LIBS)\include\CxImage;$(WindowsSdkDir)\Include\$(TargetPlatformVersion);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
> +      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
> +      <WholeProgramOptimization>true</WholeProgramOptimization>
> +    </ClCompile>
> +    <Link>
> +      <AdditionalDependencies>Version.lib;$(SPICE_LIB_LIST);wtsapi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
> +      <AdditionalLibraryDirectories>$(SPICE_LIBS_DIR);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
> +    </Link>
> +    <PostBuildEvent>
> +      <Command>
> +      </Command>
> +    </PostBuildEvent>
> +  </ItemDefinitionGroup>
> +  <ItemGroup>
> +    <ClCompile Include="..\common\vdcommon.cpp" />
> +    <ClCompile Include="..\common\vdlog.cpp" />
> +    <ClCompile Include="as_user.cpp" />
> +    <ClCompile Include="desktop_layout.cpp" />
> +    <ClCompile Include="display_configuration.cpp" />
> +    <ClCompile Include="display_setting.cpp" />
> +    <ClCompile Include="file_xfer.cpp" />
> +    <ClCompile Include="vdagent.cpp" />
> +  </ItemGroup>
> +  <ItemGroup>
> +    <ClInclude Include="..\common\vdcommon.h" />
> +    <ClInclude Include="..\common\vdlog.h" />
> +    <ClInclude Include="as_user.h" />
> +    <ClInclude Include="CCD.h" />
> +    <ClInclude Include="desktop_layout.h" />
> +    <ClInclude Include="display_configuration.h" />
> +    <ClInclude Include="display_setting.h" />
> +    <ClInclude Include="driver_interface.h" />
> +    <ClInclude Include="file_xfer.h" />
> +    <ClInclude Include="resource.h" />
> +  </ItemGroup>
> +  <ItemGroup>
> +    <ResourceCompile Include="vdagent.rc" />
> +  </ItemGroup>
> +  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
> +  <ImportGroup Label="ExtensionTargets">
> +  </ImportGroup>
> +</Project>
> \ No newline at end of file
> diff --git a/vdservice/vdservice.vcxproj b/vdservice/vdservice.vcxproj
> new file mode 100644
> index 0000000..7ea66ea
> --- /dev/null
> +++ b/vdservice/vdservice.vcxproj
> @@ -0,0 +1,197 @@
> +<?xml version="1.0" encoding="utf-8"?>
> +<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
> +  <ItemGroup Label="ProjectConfigurations">
> +    <ProjectConfiguration Include="Debug|Win32">
> +      <Configuration>Debug</Configuration>
> +      <Platform>Win32</Platform>
> +    </ProjectConfiguration>
> +    <ProjectConfiguration Include="Debug|x64">
> +      <Configuration>Debug</Configuration>
> +      <Platform>x64</Platform>
> +    </ProjectConfiguration>
> +    <ProjectConfiguration Include="Release|Win32">
> +      <Configuration>Release</Configuration>
> +      <Platform>Win32</Platform>
> +    </ProjectConfiguration>
> +    <ProjectConfiguration Include="Release|x64">
> +      <Configuration>Release</Configuration>
> +      <Platform>x64</Platform>
> +    </ProjectConfiguration>
> +  </ItemGroup>
> +  <PropertyGroup Label="Globals">
> +    <ProjectGuid>{ADFE5E22-31D0-4343-AE9E-8102CC0051F9}</ProjectGuid>
> +    <RootNamespace>redservice</RootNamespace>
> +    <Keyword>Win32Proj</Keyword>
> +    <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
> +  </PropertyGroup>
> +  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
> +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
> +    <ConfigurationType>Application</ConfigurationType>
> +    <PlatformToolset>v140</PlatformToolset>
> +    <CharacterSet>Unicode</CharacterSet>
> +    <WholeProgramOptimization>true</WholeProgramOptimization>
> +  </PropertyGroup>
> +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
> +    <ConfigurationType>Application</ConfigurationType>
> +    <PlatformToolset>v140</PlatformToolset>
> +    <CharacterSet>Unicode</CharacterSet>
> +  </PropertyGroup>
> +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
> +    <ConfigurationType>Application</ConfigurationType>
> +    <PlatformToolset>v140</PlatformToolset>
> +    <CharacterSet>Unicode</CharacterSet>
> +    <WholeProgramOptimization>true</WholeProgramOptimization>
> +  </PropertyGroup>
> +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
> +    <ConfigurationType>Application</ConfigurationType>
> +    <PlatformToolset>v140</PlatformToolset>
> +    <CharacterSet>Unicode</CharacterSet>
> +  </PropertyGroup>
> +  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
> +  <ImportGroup Label="ExtensionSettings">
> +  </ImportGroup>
> +  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
> +    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
> +    <Import Project="..\Spice.props" />
> +  </ImportGroup>
> +  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
> +    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
> +    <Import Project="..\Spice.props" />
> +  </ImportGroup>
> +  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
> +    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
> +    <Import Project="..\Spice.props" />
> +  </ImportGroup>
> +  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
> +    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
> +    <Import Project="..\Spice.props" />
> +  </ImportGroup>
> +  <PropertyGroup Label="UserMacros" />
> +  <PropertyGroup>
> +    <_ProjectFileVersion>14.0.23107.0</_ProjectFileVersion>
> +  </PropertyGroup>
> +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
> +    <OutDir>$(SolutionDir)$(Configuration)\</OutDir>
> +    <IntDir>$(Configuration)\</IntDir>
> +    <LinkIncremental>true</LinkIncremental>
> +  </PropertyGroup>
> +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
> +    <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
> +    <IntDir>$(Platform)\$(Configuration)\</IntDir>
> +    <LinkIncremental>true</LinkIncremental>
> +  </PropertyGroup>
> +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
> +    <OutDir>$(SolutionDir)$(Configuration)\</OutDir>
> +    <IntDir>$(Configuration)\</IntDir>
> +    <LinkIncremental>false</LinkIncremental>
> +  </PropertyGroup>
> +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
> +    <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
> +    <IntDir>$(Platform)\$(Configuration)\</IntDir>
> +    <LinkIncremental>false</LinkIncremental>
> +  </PropertyGroup>
> +  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
> +    <ClCompile>
> +      <Optimization>Disabled</Optimization>
> +      <AdditionalIncludeDirectories>..\common;$(SPICE_PROTOCOL_DIR);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
> +      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;%(PreprocessorDefinitions)</PreprocessorDefinitions>
> +      <MinimalRebuild>true</MinimalRebuild>
> +      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
> +      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
> +      <PrecompiledHeader />
> +      <WarningLevel>Level3</WarningLevel>
> +      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
> +    </ClCompile>
> +    <Link>
> +      <AdditionalDependencies>WtsApi32.lib;Userenv.lib;Version.lib;%(AdditionalDependencies)</AdditionalDependencies>
> +      <GenerateDebugInformation>true</GenerateDebugInformation>
> +      <SubSystem>Console</SubSystem>
> +      <RandomizedBaseAddress>false</RandomizedBaseAddress>
> +      <DataExecutionPrevention />
> +      <TargetMachine>MachineX86</TargetMachine>
> +    </Link>
> +  </ItemDefinitionGroup>
> +  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
> +    <Midl>
> +      <TargetEnvironment>X64</TargetEnvironment>
> +    </Midl>
> +    <ClCompile>
> +      <Optimization>Disabled</Optimization>
> +      <AdditionalIncludeDirectories>..\common;$(SPICE_PROTOCOL_DIR);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
> +      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;%(PreprocessorDefinitions)</PreprocessorDefinitions>
> +      <MinimalRebuild>true</MinimalRebuild>
> +      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
> +      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
> +      <PrecompiledHeader />
> +      <WarningLevel>Level3</WarningLevel>
> +      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
> +    </ClCompile>
> +    <Link>
> +      <AdditionalDependencies>WtsApi32.lib;Userenv.lib;Version.lib;%(AdditionalDependencies)</AdditionalDependencies>
> +      <GenerateDebugInformation>true</GenerateDebugInformation>
> +      <SubSystem>Console</SubSystem>
> +      <RandomizedBaseAddress>false</RandomizedBaseAddress>
> +      <DataExecutionPrevention />
> +      <TargetMachine>MachineX64</TargetMachine>
> +    </Link>
> +  </ItemDefinitionGroup>
> +  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
> +    <ClCompile>
> +      <AdditionalIncludeDirectories>..\common;$(SPICE_PROTOCOL_DIR);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
> +      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_WIN32_WINNT=0x0501;%(PreprocessorDefinitions)</PreprocessorDefinitions>
> +      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
> +      <PrecompiledHeader />
> +      <WarningLevel>Level3</WarningLevel>
> +      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
> +    </ClCompile>
> +    <Link>
> +      <AdditionalDependencies>WtsApi32.lib;Userenv.lib;Version.lib;%(AdditionalDependencies)</AdditionalDependencies>
> +      <GenerateDebugInformation>true</GenerateDebugInformation>
> +      <SubSystem>Console</SubSystem>
> +      <OptimizeReferences>true</OptimizeReferences>
> +      <EnableCOMDATFolding>true</EnableCOMDATFolding>
> +      <RandomizedBaseAddress>false</RandomizedBaseAddress>
> +      <DataExecutionPrevention />
> +      <TargetMachine>MachineX86</TargetMachine>
> +    </Link>
> +  </ItemDefinitionGroup>
> +  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
> +    <Midl>
> +      <TargetEnvironment>X64</TargetEnvironment>
> +    </Midl>
> +    <ClCompile>
> +      <AdditionalIncludeDirectories>..\common;$(SPICE_PROTOCOL_DIR);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
> +      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_WIN32_WINNT=0x0501;%(PreprocessorDefinitions)</PreprocessorDefinitions>
> +      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
> +      <PrecompiledHeader />
> +      <WarningLevel>Level3</WarningLevel>
> +      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
> +    </ClCompile>
> +    <Link>
> +      <AdditionalDependencies>WtsApi32.lib;Userenv.lib;Version.lib;%(AdditionalDependencies)</AdditionalDependencies>
> +      <GenerateDebugInformation>true</GenerateDebugInformation>
> +      <SubSystem>Console</SubSystem>
> +      <OptimizeReferences>true</OptimizeReferences>
> +      <EnableCOMDATFolding>true</EnableCOMDATFolding>
> +      <RandomizedBaseAddress>false</RandomizedBaseAddress>
> +      <DataExecutionPrevention />
> +      <TargetMachine>MachineX64</TargetMachine>
> +    </Link>
> +  </ItemDefinitionGroup>
> +  <ItemGroup>
> +    <ClInclude Include="..\common\vdcommon.h" />
> +    <ClInclude Include="..\common\vdlog.h" />
> +    <ClInclude Include="resource.h" />
> +  </ItemGroup>
> +  <ItemGroup>
> +    <ResourceCompile Include="vdservice.rc" />
> +  </ItemGroup>
> +  <ItemGroup>
> +    <ClCompile Include="..\common\vdcommon.cpp" />
> +    <ClCompile Include="..\common\vdlog.cpp" />
> +    <ClCompile Include="vdservice.cpp" />
> +  </ItemGroup>
> +  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
> +  <ImportGroup Label="ExtensionTargets">
> +  </ImportGroup>
> +</Project>
> \ No newline at end of file
> -- 
> 1.8.3.1
> 
> _______________________________________________
> Spice-devel mailing list
> Spice-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/spice-devel
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <https://lists.freedesktop.org/archives/spice-devel/attachments/20160720/c22bfd67/attachment-0001.sig>


More information about the Spice-devel mailing list