[Spice-devel] [RFC PATCH vdagent 02/16] Provide support for Windows 10 CCD API
Frediano Ziglio
fziglio at redhat.com
Mon Jul 18 07:33:12 UTC 2016
>
> 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>
> +
Can't we use relative directories here?
> <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
> +
Are we sure we can do this freely?
These definitions came from Microsoft.
Either website or some header I don't think we can copy and
past and change licensing.
> +//
> +// 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
This patch is massive!
Frediano
More information about the Spice-devel
mailing list