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