[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [win-pv-devel] [PATCH 3/3] Add a new CConvCreator object to handle laptop/slate mode switch
This patch adds a new object derived from IDeviceCreator to interact with the laptop/slate mode switch interface provided by a Windows driver that binds to the ACPI CONV device. It also adds code to support the documented PV interface for triggering laptop/slate mode switch [1]. http://xenbits.xen.org/gitweb/?p=xen.git;a=commit;h=3bdb1400 Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx> --- src/xenagent/convdevice.cpp | 137 +++++++++++++++++++++++++++++ src/xenagent/convdevice.h | 59 +++++++++++++ src/xenagent/devicelist.cpp | 16 ++++ src/xenagent/devicelist.h | 1 + src/xenagent/messages.mc | 8 ++ src/xenagent/service.cpp | 183 +++++++++++++++++++++++++++++++++++++-- src/xenagent/service.h | 38 ++++++++ vs2012/xenagent/xenagent.vcxproj | 1 + vs2013/xenagent/xenagent.vcxproj | 1 + vs2015/xenagent/xenagent.vcxproj | 1 + 10 files changed, 439 insertions(+), 6 deletions(-) create mode 100644 src/xenagent/convdevice.cpp create mode 100644 src/xenagent/convdevice.h diff --git a/src/xenagent/convdevice.cpp b/src/xenagent/convdevice.cpp new file mode 100644 index 0000000..5ac40ff --- /dev/null +++ b/src/xenagent/convdevice.cpp @@ -0,0 +1,137 @@ +/* Copyright (c) Citrix Systems Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, + * with or without modification, are permitted provided + * that the following conditions are met: + * + * * Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <windows.h> +#include <stdio.h> +#include <powrprof.h> +#include <winuser.h> + +#include "service.h" +#include "convdevice.h" +#include "devicelist.h" + +CConvDevice::CConvDevice(const wchar_t* path) : CDevice(path) +{ +} + +/*virtual*/ CConvDevice::~CConvDevice() +{ +} + +void CConvDevice::SetMode(DWORD new_mode) +{ + DisablePrompt(); + + CXenAgent::Log("New mode = %s\n", new_mode ? "Laptop" : "Slate"); + + for (;;) { + BYTE buffer(0); + DWORD current_mode(CCONV_DEVICE_UNKNOWN_MODE); + + if (!GetMode(¤t_mode)) + break; + + CXenAgent::Log("Current mode = %s\n", + current_mode ? "Laptop" : "Slate"); + + if (current_mode == new_mode) + break; + + Write(&buffer, sizeof(buffer)); + Sleep(1000); // yield + } +} + +bool CConvDevice::DisablePrompt() +{ + HKEY key; + LRESULT lr; + std::string path; + + path = "System\\CurrentControlSet\\Control\\PriorityControl"; + + lr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, path.c_str(), 0, KEY_ALL_ACCESS, + &key); + if (lr != ERROR_SUCCESS) + goto fail1; + + DWORD type(REG_DWORD); + DWORD val(0); + DWORD length; + + length = sizeof(val); + lr = RegSetValueEx(key, "ConvertibleSlateModePromptPreference", NULL, + type, (LPBYTE)&val, length); + if (lr != ERROR_SUCCESS) + goto fail2; + + RegCloseKey(key); + + return true; + +fail2: + RegCloseKey(key); +fail1: + return false; +} + +bool CConvDevice::GetMode(DWORD *mode) +{ + HKEY key; + LRESULT lr; + std::string path; + + path = "System\\CurrentControlSet\\Control\\PriorityControl"; + + lr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, path.c_str(), 0, KEY_READ, &key); + if (lr != ERROR_SUCCESS) + goto fail1; + + DWORD type; + DWORD val; + DWORD length; + + length = sizeof(val); + lr = RegQueryValueEx(key, "ConvertibleSlateMode", NULL, &type, + (LPBYTE)&val, &length); + if (lr != ERROR_SUCCESS || type != REG_DWORD) + goto fail2; + + RegCloseKey(key); + + *mode = val; + return true; + +fail2: + RegCloseKey(key); +fail1: + return false; +} diff --git a/src/xenagent/convdevice.h b/src/xenagent/convdevice.h new file mode 100644 index 0000000..90f8035 --- /dev/null +++ b/src/xenagent/convdevice.h @@ -0,0 +1,59 @@ +/* Copyright (c) Citrix Systems Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, + * with or without modification, are permitted provided + * that the following conditions are met: + * + * * Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef __XENAGENT_CONVDEVICE_H__ +#define __XENAGENT_CONVDEVICE_H__ + +#include <windows.h> +#include <string> +#include "devicelist.h" + +enum { + CCONV_DEVICE_SLATE_MODE, + CCONV_DEVICE_LAPTOP_MODE, + CCONV_DEVICE_UNKNOWN_MODE +}; + +class CConvDevice : public CDevice +{ +public: + CConvDevice(const wchar_t* path); + virtual ~CConvDevice(); + +public: + void SetMode(DWORD mode); + +private: + bool DisablePrompt(); + bool GetMode(DWORD *mode); +}; + +#endif diff --git a/src/xenagent/devicelist.cpp b/src/xenagent/devicelist.cpp index 2c110bc..b40b252 100644 --- a/src/xenagent/devicelist.cpp +++ b/src/xenagent/devicelist.cpp @@ -101,6 +101,22 @@ void CDevice::Close() m_handle = INVALID_HANDLE_VALUE; } +bool CDevice::Write(void *buf, DWORD bufsz, DWORD *bytes /* = NULL*/) +{ + if (m_handle == INVALID_HANDLE_VALUE) + return false; + + DWORD _bytes; + if (!WriteFile(m_handle, + buf, + bufsz, + (bytes == NULL) ? &_bytes : bytes, + NULL)) + return false; + + return true; +} + bool CDevice::Ioctl(DWORD ioctl, void* in, DWORD insz, void* out, DWORD outsz, DWORD* bytes /*= NULL*/) { if (m_handle == INVALID_HANDLE_VALUE) diff --git a/src/xenagent/devicelist.h b/src/xenagent/devicelist.h index 893bd43..5535ad5 100644 --- a/src/xenagent/devicelist.h +++ b/src/xenagent/devicelist.h @@ -49,6 +49,7 @@ public: void Close(); protected: + bool Write(void *buf, DWORD bufsz, DWORD *bytes = NULL); bool Ioctl(DWORD ioctl, void* in, DWORD insz, void* out, DWORD outsz, DWORD* bytes = NULL); private: diff --git a/src/xenagent/messages.mc b/src/xenagent/messages.mc index a50021a..56f0e5d 100644 --- a/src/xenagent/messages.mc +++ b/src/xenagent/messages.mc @@ -108,3 +108,11 @@ SymbolicName=EVENT_XENUSER_UNEXPECTED Language=English The tools experienced an unexpected error. . + +MessageId=0x0009 +Facility=System +Severity=Informational +SymbolicName=EVENT_XENUSER_MODE_SWITCH +Language=English +The tools requested a mode switch. +. diff --git a/src/xenagent/service.cpp b/src/xenagent/service.cpp index a2deca1..d917821 100644 --- a/src/xenagent/service.cpp +++ b/src/xenagent/service.cpp @@ -60,10 +60,12 @@ CCritSec::~CCritSec() CXenIfaceCreator::CXenIfaceCreator(CXenAgent& agent) : m_devlist(GUID_INTERFACE_XENIFACE), m_device(NULL), - m_ctxt_shutdown(NULL), m_ctxt_suspend(NULL), m_agent(agent) + m_ctxt_shutdown(NULL), m_ctxt_suspend(NULL), + m_ctxt_slate_mode(NULL), m_agent(agent) { m_evt_shutdown = CreateEvent(FALSE, NULL, NULL, FALSE); m_evt_suspend = CreateEvent(FALSE, NULL, NULL, FALSE); + m_evt_slate_mode = CreateEvent(FALSE, NULL, NULL, FALSE); m_count = 0; InitializeCriticalSection(&m_crit); @@ -71,6 +73,7 @@ CXenIfaceCreator::CXenIfaceCreator(CXenAgent& agent) : CXenIfaceCreator::~CXenIfaceCreator() { + CloseHandle(m_evt_slate_mode); CloseHandle(m_evt_suspend); CloseHandle(m_evt_shutdown); @@ -120,7 +123,12 @@ void CXenIfaceCreator::Log(const char* message) m_device = (CXenIfaceDevice*)dev; m_device->SuspendRegister(m_evt_suspend, &m_ctxt_suspend); + StartShutdownWatch(); + + if (m_agent.ConvDevicePresent()) + StartSlateModeWatch(); + SetXenTime(); } } @@ -135,6 +143,10 @@ void CXenIfaceCreator::Log(const char* message) m_device->SuspendDeregister(m_ctxt_suspend); m_ctxt_suspend = NULL; } + + if (m_agent.ConvDevicePresent()) + StopSlateModeWatch(); + StopShutdownWatch(); m_device = NULL; @@ -144,13 +156,21 @@ void CXenIfaceCreator::Log(const char* message) /*virtual*/ void CXenIfaceCreator::OnDeviceSuspend(CDevice* dev) { CXenAgent::Log("OnDeviceSuspend(%ws)\n", dev->Path()); + + if (m_agent.ConvDevicePresent()) + StopSlateModeWatch(); + StopShutdownWatch(); } /*virtual*/ void CXenIfaceCreator::OnDeviceResume(CDevice* dev) { CXenAgent::Log("OnDeviceResume(%ws)\n", dev->Path()); + StartShutdownWatch(); + + if (m_agent.ConvDevicePresent()) + StartSlateModeWatch(); } bool CXenIfaceCreator::CheckShutdown() @@ -230,13 +250,36 @@ void CXenIfaceCreator::CheckSuspend() m_agent.EventLog(EVENT_XENUSER_UNSUSPENDED); - // recreate shutdown watch, as suspending deactivated the watch + // recreate watches, as suspending deactivated the watch + if (m_agent.ConvDevicePresent()) + StopSlateModeWatch(); + StopShutdownWatch(); + StartShutdownWatch(); + + if (m_agent.ConvDevicePresent()) + StartSlateModeWatch(); + SetXenTime(); m_count = count; } +bool CXenIfaceCreator::CheckSlateMode(std::string *mode) +{ + CCritSec crit(&m_crit); + if (m_device == NULL) + return false; + + if (!m_device->StoreRead("control/laptop-slate-mode", *mode)) + return false; + + if (*mode != "") + m_device->StoreWrite("control/laptop-slate-mode", ""); + + return true; +} + void CXenIfaceCreator::StartShutdownWatch() { if (m_ctxt_shutdown) @@ -264,6 +307,26 @@ void CXenIfaceCreator::StopShutdownWatch() m_ctxt_shutdown = NULL; } +void CXenIfaceCreator::StartSlateModeWatch() +{ + if (m_ctxt_slate_mode) + return; + + m_device->StoreAddWatch("control/laptop-slate-mode", m_evt_slate_mode, &m_ctxt_slate_mode); + m_device->StoreWrite("control/feature-laptop-slate-mode", "1"); +} + +void CXenIfaceCreator::StopSlateModeWatch() +{ + if (!m_ctxt_slate_mode) + return; + + m_device->StoreRemove("control/feature-laptop-slate-mode"); + + m_device->StoreRemoveWatch(m_ctxt_slate_mode); + m_ctxt_slate_mode = NULL; +} + void CXenIfaceCreator::AcquireShutdownPrivilege() { HANDLE token; @@ -398,6 +461,94 @@ void CXenIfaceCreator::SetXenTime() SetLocalTime(&sys); } +/* 317fc439-3f77-41c8-b09e-08ad63272aa3 */ +DEFINE_GUID(GUID_GPIOBUTTONS_LAPTOPSLATE_INTERFACE, \ + 0x317fc439, 0x3f77, 0x41c8, 0xb0, 0x9e, 0x08, 0xad, 0x63, 0x27, 0x2a, 0xa3); + +CConvCreator::CConvCreator(CXenAgent& agent) : + m_devlist(GUID_GPIOBUTTONS_LAPTOPSLATE_INTERFACE), m_device(NULL), + m_agent(agent) +{ + InitializeCriticalSection(&m_crit); +} + +CConvCreator::~CConvCreator() +{ + DeleteCriticalSection(&m_crit); +} + +bool CConvCreator::Start(HANDLE svc) +{ + return m_devlist.Start(svc, this); +} + +void CConvCreator::Stop() +{ + m_devlist.Stop(); +} + +void CConvCreator::OnDeviceEvent(DWORD evt, LPVOID data) +{ + m_devlist.OnDeviceEvent(evt, data); +} + +void CConvCreator::OnPowerEvent(DWORD evt, LPVOID data) +{ + m_devlist.OnPowerEvent(evt, data); +} + +void CConvCreator::SetSlateMode(std::string mode) +{ + CCritSec crit(&m_crit); + if (m_device == NULL) + return; + + m_agent.EventLog(EVENT_XENUSER_MODE_SWITCH); + + if (mode == "laptop") + m_device->SetMode(CCONV_DEVICE_LAPTOP_MODE); + else if (mode == "slate") + m_device->SetMode(CCONV_DEVICE_SLATE_MODE); +} + +bool CConvCreator::DevicePresent() +{ + return m_device != NULL; +} + +/*virtual*/ CDevice* CConvCreator::Create(const wchar_t* path) +{ + return new CConvDevice(path); +} + +/*virtual*/ void CConvCreator::OnDeviceAdded(CDevice* dev) +{ + CXenAgent::Log("OnDeviceAdded(%ws)\n", dev->Path()); + + CCritSec crit(&m_crit); + if (m_device == NULL) + m_device = (CConvDevice*)dev; +} + +/*virtual*/ void CConvCreator::OnDeviceRemoved(CDevice* dev) +{ + CXenAgent::Log("OnDeviceRemoved(%ws)\n", dev->Path()); + + CCritSec crit(&m_crit); + if (m_device == dev) + m_device = NULL; +} + +/*virtual*/ void CConvCreator::OnDeviceSuspend(CDevice* dev) +{ + CXenAgent::Log("OnDeviceSuspend(%ws)\n", dev->Path()); +} + +/*virtual*/ void CConvCreator::OnDeviceResume(CDevice* dev) +{ + CXenAgent::Log("OnDeviceResume(%ws)\n", dev->Path()); +} + static CXenAgent s_service; /*static*/ void CXenAgent::Log(const char* fmt, ...) @@ -505,7 +656,8 @@ static CXenAgent s_service; #pragma warning(push) #pragma warning(disable:4355) -CXenAgent::CXenAgent() : m_handle(NULL), m_evtlog(NULL), m_xeniface(*this) +CXenAgent::CXenAgent() : m_handle(NULL), m_evtlog(NULL), m_xeniface(*this), + m_conv(*this) { m_status.dwServiceType = SERVICE_WIN32; m_status.dwCurrentState = SERVICE_START_PENDING; @@ -530,6 +682,7 @@ CXenAgent::~CXenAgent() void CXenAgent::OnServiceStart() { CXenAgent::Log("OnServiceStart()\n"); + m_conv.Start(m_handle); m_xeniface.Start(m_handle); } @@ -537,23 +690,28 @@ void CXenAgent::OnServiceStop() { CXenAgent::Log("OnServiceStop()\n"); m_xeniface.Stop(); + m_conv.Stop(); } void CXenAgent::OnDeviceEvent(DWORD evt, LPVOID data) { + m_conv.OnDeviceEvent(evt, data); m_xeniface.OnDeviceEvent(evt, data); } void CXenAgent::OnPowerEvent(DWORD evt, LPVOID data) { + m_conv.OnPowerEvent(evt, data); m_xeniface.OnPowerEvent(evt, data); } bool CXenAgent::ServiceMainLoop() { - HANDLE events[3] = { m_svc_stop, m_xeniface.m_evt_shutdown, - m_xeniface.m_evt_suspend }; - DWORD wait = WaitForMultipleObjectsEx(3, events, FALSE, 60000, TRUE); + HANDLE events[] = { m_svc_stop, + m_xeniface.m_evt_shutdown, + m_xeniface.m_evt_suspend, + m_xeniface.m_evt_slate_mode }; + DWORD wait = WaitForMultipleObjectsEx(4, events, FALSE, 60000, TRUE); switch (wait) { case WAIT_OBJECT_0: @@ -566,6 +724,14 @@ bool CXenAgent::ServiceMainLoop() m_xeniface.CheckSuspend(); return true; // continue loop + case WAIT_OBJECT_0+3: { + std::string mode; + + if (m_xeniface.CheckSlateMode(&mode)) + m_conv.SetSlateMode(mode); + + return true; // continue loop + } case WAIT_IO_COMPLETION: case WAIT_TIMEOUT: m_xeniface.CheckSuspend(); @@ -593,6 +759,11 @@ void CXenAgent::EventLog(DWORD evt) } } +bool CXenAgent::ConvDevicePresent() +{ + return m_conv.DevicePresent(); +} + void CXenAgent::SetServiceStatus(DWORD state, DWORD exit /*= 0*/, DWORD hint /*= 0*/) { m_status.dwCurrentState = state; diff --git a/src/xenagent/service.h b/src/xenagent/service.h index 6d359fe..60ecb16 100644 --- a/src/xenagent/service.h +++ b/src/xenagent/service.h @@ -39,6 +39,7 @@ #include "devicelist.h" #include "xenifacedevice.h" +#include "convdevice.h" class CXenAgent; @@ -65,14 +66,18 @@ public: // IDeviceCreator public: bool CheckShutdown(); void CheckSuspend(); + bool CheckSlateMode(std::string *mode); public: HANDLE m_evt_shutdown; HANDLE m_evt_suspend; + HANDLE m_evt_slate_mode; private: void StartShutdownWatch(); void StopShutdownWatch(); + void StartSlateModeWatch(); + void StopSlateModeWatch(); void AcquireShutdownPrivilege(); bool IsHostTimeUTC(); void AdjustXenTimeToUTC(FILETIME* time); @@ -86,9 +91,38 @@ private: CRITICAL_SECTION m_crit; void* m_ctxt_shutdown; void* m_ctxt_suspend; + void* m_ctxt_slate_mode; DWORD m_count; }; +class CConvCreator : public IDeviceCreator +{ +public: + CConvCreator(CXenAgent&); + virtual ~CConvCreator(); + CConvCreator& operator=(const CConvCreator&); + + bool Start(HANDLE svc); + void Stop(); + void OnDeviceEvent(DWORD evt, LPVOID data); + void OnPowerEvent(DWORD evt, LPVOID data); + void SetSlateMode(std::string mode); + bool DevicePresent(); + +public: + virtual CDevice* Create(const wchar_t* path); + virtual void OnDeviceAdded(CDevice* dev); + virtual void OnDeviceRemoved(CDevice* dev); + virtual void OnDeviceSuspend(CDevice* dev); + virtual void OnDeviceResume(CDevice* dev); + +private: + CXenAgent& m_agent; + CDeviceList m_devlist; + CConvDevice* m_device; + CRITICAL_SECTION m_crit; +}; + class CXenAgent { public: // statics @@ -108,6 +142,9 @@ public: // ctor/dtor public: void EventLog(DWORD evt); +public: + bool ConvDevicePresent(); + private: // service events void OnServiceStart(); void OnServiceStop(); @@ -125,6 +162,7 @@ private: // service support HANDLE m_evtlog; HANDLE m_svc_stop; CXenIfaceCreator m_xeniface; + CConvCreator m_conv; }; #endif diff --git a/vs2012/xenagent/xenagent.vcxproj b/vs2012/xenagent/xenagent.vcxproj index 7ae655e..f778e90 100644 --- a/vs2012/xenagent/xenagent.vcxproj +++ b/vs2012/xenagent/xenagent.vcxproj @@ -76,6 +76,7 @@ <ClCompile Include="..\..\src\xenagent\service.cpp"/> <ClCompile Include="..\..\src\xenagent\devicelist.cpp"/> <ClCompile Include="..\..\src\xenagent\xenifacedevice.cpp"/> + <ClCompile Include="..\..\src\xenagent\convdevice.cpp"/> </ItemGroup> <ItemGroup> <ResourceCompile Include="..\..\src\xenagent\xenagent.rc" /> diff --git a/vs2013/xenagent/xenagent.vcxproj b/vs2013/xenagent/xenagent.vcxproj index a2ad3f8..e51d8be 100644 --- a/vs2013/xenagent/xenagent.vcxproj +++ b/vs2013/xenagent/xenagent.vcxproj @@ -76,6 +76,7 @@ <ClCompile Include="..\..\src\xenagent\service.cpp"/> <ClCompile Include="..\..\src\xenagent\devicelist.cpp"/> <ClCompile Include="..\..\src\xenagent\xenifacedevice.cpp"/> + <ClCompile Include="..\..\src\xenagent\convdevice.cpp"/> </ItemGroup> <ItemGroup> <ResourceCompile Include="..\..\src\xenagent\xenagent.rc" /> diff --git a/vs2015/xenagent/xenagent.vcxproj b/vs2015/xenagent/xenagent.vcxproj index 5f87e6d..e7fec8e 100644 --- a/vs2015/xenagent/xenagent.vcxproj +++ b/vs2015/xenagent/xenagent.vcxproj @@ -71,6 +71,7 @@ <ClCompile Include="..\..\src\xenagent\service.cpp"/> <ClCompile Include="..\..\src\xenagent\devicelist.cpp"/> <ClCompile Include="..\..\src\xenagent\xenifacedevice.cpp"/> + <ClCompile Include="..\..\src\xenagent\convdevice.cpp"/> </ItemGroup> <ItemGroup> <ResourceCompile Include="..\..\src\xenagent\xenagent.rc" /> -- 2.5.3 _______________________________________________ win-pv-devel mailing list win-pv-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |