[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 1/2] Refactor XenAgent


  • To: <win-pv-devel@xxxxxxxxxxxxxxxxxxxx>
  • From: Owen Smith <owen.smith@xxxxxxxxxx>
  • Date: Mon, 5 Jul 2021 13:59:50 +0100
  • Authentication-results: esa4.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none
  • Cc: Owen Smith <owen.smith@xxxxxxxxxx>
  • Delivery-date: Mon, 05 Jul 2021 13:00:04 +0000
  • Ironport-hdrordr: A9a23:GfeJoqldaUKLTB6qz+zUNhOHcr/pDfIf3DAbv31ZSRFFG/Fwz/ re/sjzpiWE7Qr5OUtQ4OxoV5PvfZqxz/VICMwqTNSftWrdyROVxeNZjLcKqgeIcxEWtNQ86U 4KScVD4ajLYmSS+vyX3ODXKbwdKZK8gcSVbK/lvhBQpC9RGsdd0zs=
  • Ironport-sdr: deABC9fdQbxw+seHIRRvxS9aVe31ZHV69OPA8KAAWBlqURMLiPpJtSN4h8pSGnkWTXUkdoT5im 5Zb39VtQNKA5OjU30VpEjhgxeGNztnY82T0hUBbbGONE31TesRGyPYrnNiHV883DE4y0fRTn8Y UqLFj3PrCAf6GWfpPOOTN4rVpLVgloRKVhgxTyiuAZV+zXCBGzSzow4xyAeD/Edbj3Lr5+1p5t DGxtiRrCHp/Iv/nvnTkKEyebumv1vCXTSpNAujp7FdE28IOjZ7AS486rG+woIk+KDMJkR/a1ug od4=
  • List-id: Developer list for the Windows PV Drivers subproject <win-pv-devel.lists.xenproject.org>

- Merge IDeviceCreator interface into CDeviceList base class
- Add CXenIfaceDeviceList and CConvDeviceList, derived from CDeviceList
- Moves IFace functionality to CXenIfaceDeviceList
- Moves Conv device functionality to CConvDeviceList
- Seperate RegisterDeviceNotification from SetupApi enumeration, so that static
  devices do not need to hold the handle open (i.e. Conv device)
- CConvDeviceList only opens the handle when neccessary, as the MS driver for
  the ACPI device only allows 1 open handle at a time.

Signed-off-by: Owen Smith <owen.smith@xxxxxxxxxx>
---
 src/xenagent/convdevice.cpp     |  59 +++-
 src/xenagent/convdevice.h       |  22 ++
 src/xenagent/devicelist.cpp     | 166 ++++++-----
 src/xenagent/devicelist.h       |  57 ++--
 src/xenagent/service.cpp        | 486 +-------------------------------
 src/xenagent/service.h          |  86 +-----
 src/xenagent/xenifacedevice.cpp | 348 +++++++++++++++++++++++
 src/xenagent/xenifacedevice.h   |  43 +++
 8 files changed, 619 insertions(+), 648 deletions(-)

diff --git a/src/xenagent/convdevice.cpp b/src/xenagent/convdevice.cpp
index 5ac40ff..5a25be1 100644
--- a/src/xenagent/convdevice.cpp
+++ b/src/xenagent/convdevice.cpp
@@ -29,6 +29,7 @@
  * SUCH DAMAGE.
  */
 
+#define INITGUID
 #include <windows.h>
 #include <stdio.h>
 #include <powrprof.h>
@@ -37,6 +38,11 @@
 #include "service.h"
 #include "convdevice.h"
 #include "devicelist.h"
+#include "messages.h"
+
+/* 317fc439-3f77-41c8-b09e-08ad63272aa3 */
+DEFINE_GUID(GUID_GPIOBUTTONS_LAPTOPSLATE_INTERFACE, \
+            0x317fc439, 0x3f77, 0x41c8, 0xb0, 0x9e, 0x08, 0xad, 0x63, 0x27, 
0x2a, 0xa3);
 
 CConvDevice::CConvDevice(const wchar_t* path) : CDevice(path)
 {
@@ -65,7 +71,11 @@ void CConvDevice::SetMode(DWORD new_mode)
         if (current_mode == new_mode)
             break;
 
-        Write(&buffer, sizeof(buffer));
+        if (Open()) {
+            Write(&buffer, sizeof(buffer));
+            Close();
+        }
+
         Sleep(1000); // yield
     }
 }
@@ -135,3 +145,50 @@ fail2:
 fail1:
     return false;
 }
+
+CConvDeviceList::CConvDeviceList(CXenAgent* agent) : 
CDeviceList(GUID_GPIOBUTTONS_LAPTOPSLATE_INTERFACE), m_agent(agent)
+{}
+
+/*virtual*/ CConvDeviceList::~CConvDeviceList()
+{}
+
+/*virtual*/ CDevice* CConvDeviceList::Create(const wchar_t* path)
+{
+    return new CConvDevice(path);
+}
+
+/*virtual*/ void CConvDeviceList::OnDeviceAdded(CDevice* dev)
+{
+    UNREFERENCED_PARAMETER(dev);
+}
+
+/*virtual*/ void CConvDeviceList::OnDeviceRemoved(CDevice* dev)
+{
+    UNREFERENCED_PARAMETER(dev);
+}
+
+/*virtual*/ void CConvDeviceList::OnDeviceSuspend(CDevice* dev)
+{
+    UNREFERENCED_PARAMETER(dev);
+}
+
+/*virtual*/ void CConvDeviceList::OnDeviceResume(CDevice* dev)
+{
+    UNREFERENCED_PARAMETER(dev);
+}
+
+void CConvDeviceList::SetSlateMode(std::string& mode)
+{
+    CCritSec crit(&m_crit);
+    CConvDevice* device = (CConvDevice*)GetFirstDevice();
+
+    if (device == NULL)
+        return;
+
+    m_agent->EventLog(EVENT_XENUSER_MODE_SWITCH);
+
+    if (mode == "laptop")
+        device->SetMode(CCONV_DEVICE_LAPTOP_MODE);
+    else if (mode == "slate")
+        device->SetMode(CCONV_DEVICE_SLATE_MODE);
+}
diff --git a/src/xenagent/convdevice.h b/src/xenagent/convdevice.h
index 90f8035..088ff15 100644
--- a/src/xenagent/convdevice.h
+++ b/src/xenagent/convdevice.h
@@ -56,4 +56,26 @@ private:
     bool GetMode(DWORD *mode);
 };
 
+class CXenAgent;
+
+class CConvDeviceList : public CDeviceList
+{
+public:
+    CConvDeviceList(CXenAgent* agent);
+    virtual ~CConvDeviceList();
+
+protected: // CDeviceList
+    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);
+
+public:
+    void SetSlateMode(std::string& mode);
+
+private:
+    CXenAgent*  m_agent;
+};
+
 #endif
diff --git a/src/xenagent/devicelist.cpp b/src/xenagent/devicelist.cpp
index 4acf532..d6af5d4 100644
--- a/src/xenagent/devicelist.cpp
+++ b/src/xenagent/devicelist.cpp
@@ -65,6 +65,15 @@ static void DebugPrint(const wchar_t* fmt, ...)
     OutputDebugStringW(buffer);
 }
 
+CCritSec::CCritSec(LPCRITICAL_SECTION crit) : m_crit(crit)
+{
+    EnterCriticalSection(m_crit);
+}
+CCritSec::~CCritSec()
+{
+    LeaveCriticalSection(m_crit);
+}
+
 CDevice::CDevice(const wchar_t* path) :
     m_handle(INVALID_HANDLE_VALUE), m_path(path), m_notify(NULL)
 {
@@ -81,6 +90,11 @@ const wchar_t* CDevice::Path() const
     return m_path.c_str();
 }
 
+HDEVNOTIFY CDevice::Notify() const
+{
+    return m_notify;
+}
+
 bool CDevice::Open()
 {
     Close();
@@ -104,7 +118,7 @@ void CDevice::Close()
     m_handle = INVALID_HANDLE_VALUE;
 }
 
-HDEVNOTIFY CDevice::Register(HANDLE svc)
+bool CDevice::Register(HANDLE svc)
 {
     Unregister();
 
@@ -114,7 +128,7 @@ HDEVNOTIFY CDevice::Register(HANDLE svc)
     devhdl.dbch_handle = m_handle;
 
     m_notify = RegisterDeviceNotification(svc, &devhdl, 
DEVICE_NOTIFY_SERVICE_HANDLE);
-    return m_notify;
+    return (m_notify != NULL);
 }
 
 void CDevice::Unregister()
@@ -162,24 +176,32 @@ bool CDevice::Ioctl(DWORD ioctl, void* in, DWORD insz, 
void* out, DWORD outsz, D
 }
 
 CDeviceList::CDeviceList(const GUID& itf) :
-    m_guid(itf), m_notify(NULL), m_handle(NULL), m_impl(NULL)
+    m_guid(itf), m_notify(NULL), m_handle(NULL)
 {
+    InitializeCriticalSection(&m_crit);
 }
 
 CDeviceList::~CDeviceList()
 {
-    Stop();
+    UnregisterForDeviceChange();
+    CleanupDeviceList();
+
+    DeleteCriticalSection(&m_crit);
 }
 
-#pragma warning(push)
-#pragma warning(disable:6102) // Using value from failed function call
+CDevice* CDeviceList::GetFirstDevice()
+{
+    DeviceMap::iterator it = m_devs.begin();
+    if (it == m_devs.end())
+        return NULL;
+    return *it;
+}
 
-bool CDeviceList::Start(HANDLE handle, IDeviceCreator* impl)
+bool CDeviceList::RegisterForDeviceChange(HANDLE handle)
 {
-    Stop();
+    UnregisterForDeviceChange();
 
     m_handle = handle;
-    m_impl = impl;
 
     DEV_BROADCAST_DEVICEINTERFACE dev = { 0 };
     dev.dbcc_size = sizeof(dev);
@@ -187,9 +209,21 @@ bool CDeviceList::Start(HANDLE handle, IDeviceCreator* 
impl)
     dev.dbcc_classguid = m_guid;
 
     m_notify = RegisterDeviceNotificationA(handle, &dev, 
DEVICE_NOTIFY_SERVICE_HANDLE);
-    if (m_notify == NULL)
-        return false;
+    return m_notify != NULL;
+}
+
+void CDeviceList::UnregisterForDeviceChange()
+{
+    if (m_notify != NULL)
+        UnregisterDeviceNotification(m_notify);
+    m_notify = NULL;
+}
 
+#pragma warning(push)
+#pragma warning(disable:6102) // Using value from failed function call
+
+void CDeviceList::EnumerateDevices()
+{
     HDEVINFO                            info;
     SP_DEVICE_INTERFACE_DATA            itf;
     PSP_DEVICE_INTERFACE_DETAIL_DATA    detail;
@@ -201,7 +235,7 @@ bool CDeviceList::Start(HANDLE handle, IDeviceCreator* impl)
                                NULL,
                                DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
     if (info == INVALID_HANDLE_VALUE)
-        return true; // non fatal, just missing already present device(s)
+        return; // non fatal, just missing already present device(s)
 
     itf.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
     for (idx = 0;
@@ -229,23 +263,17 @@ bool CDeviceList::Start(HANDLE handle, IDeviceCreator* 
impl)
         itf.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
     }
     SetupDiDestroyDeviceInfoList(info);
-    return true;
 }
 
 #pragma warning(pop)
 
-void CDeviceList::Stop()
+void CDeviceList::CleanupDeviceList()
 {
-    if (m_notify != NULL)
-        UnregisterDeviceNotification(m_notify);
-    m_notify = NULL;
-
     for (DeviceMap::iterator it = m_devs.begin();
          it != m_devs.end();
          ++it) {
-        if (m_impl)
-            m_impl->OnDeviceRemoved(it->second);
-        delete it->second;
+        OnDeviceRemoved(*it);
+        delete *it;
     }
     m_devs.clear();
 }
@@ -302,14 +330,14 @@ void CDeviceList::OnPowerEvent(DWORD evt, LPVOID data)
         for (DeviceMap::iterator it = m_devs.begin();
              it != m_devs.end();
              ++it)
-            m_impl->OnDeviceResume(it->second);
+            OnDeviceResume(*it);
         break;
 
     case PBT_APMSUSPEND:
         for (DeviceMap::iterator it = m_devs.begin();
              it != m_devs.end();
              ++it)
-            m_impl->OnDeviceSuspend(it->second);
+            OnDeviceSuspend(*it);
         break;
 
     default:
@@ -317,37 +345,25 @@ void CDeviceList::OnPowerEvent(DWORD evt, LPVOID data)
     }
 }
 
-CDevice* CDeviceList::GetFirstDevice()
-{
-    DeviceMap::iterator it = m_devs.begin();
-    if (it == m_devs.end())
-        return NULL;
-    return it->second;
-}
-
 void CDeviceList::DeviceArrival(const std::wstring& path)
 {
     DebugPrint(L"DeviceArrival(%ws)\n", path.c_str());
-    CDevice* dev;
-    if (m_impl)
-        dev = m_impl->Create(path.c_str());
-    else
-        dev = new CDevice(path.c_str());
+    CDevice* dev = Create(path.c_str());
     if (dev == NULL)
         goto fail1;
 
+    if (m_handle == NULL)
+        goto done;
+
     if (!dev->Open())
         goto fail2;
 
-    HDEVNOTIFY nfy = dev->Register(m_handle);
-    if (nfy == NULL)
+    if (!dev->Register(m_handle))
         goto fail3;
 
-    m_devs[nfy] = dev;
-
-    if (m_impl)
-        m_impl->OnDeviceAdded(dev);
-
+done:
+    OnDeviceAdded(dev);
+    m_devs.push_back(dev);
     return;
 
 fail3:
@@ -362,44 +378,60 @@ fail1:
 
 void CDeviceList::DeviceRemoved(HDEVNOTIFY nfy)
 {
-    DeviceMap::iterator it = m_devs.find(nfy);
-    if (it == m_devs.end())
-        return; // spurious event?
+    for (DeviceMap::iterator it = m_devs.begin();
+         it != m_devs.end();
+         ++it) {
+        CDevice* dev = *it;
+
+        if (dev->Notify() != nfy)
+            continue;
 
-    CDevice* dev = it->second;
-    DebugPrint(L"DeviceRemoved(%ws)\n", dev->Path());
+        DebugPrint(L"DeviceRemoved(%ws)\n", dev->Path());
 
-    delete dev; // handles unregister()
-    m_devs.erase(it);
+        delete dev; // handles unregister()
+        m_devs.erase(it);
+        return;
+    }
+    // Spurious event?
 }
 
 void CDeviceList::DeviceRemovePending(HDEVNOTIFY nfy)
 {
-    DeviceMap::iterator it = m_devs.find(nfy);
-    if (it == m_devs.end())
-        return; // spurious event?
+    for (DeviceMap::iterator it = m_devs.begin();
+         it != m_devs.end();
+         ++it) {
+        CDevice* dev = *it;
 
-    CDevice* dev = it->second;
-    DebugPrint(L"DeviceRemovePending(%ws)\n", dev->Path());
+        if (dev->Notify() != nfy)
+            continue;
+
+        DebugPrint(L"DeviceRemovePending(%ws)\n", dev->Path());
 
-    if (m_impl)
-        m_impl->OnDeviceRemoved(dev);
+        OnDeviceRemoved(dev);
 
-    dev->Close();
+        dev->Close();
+        return;
+    }
+    // Spurious event?
 }
 
 void CDeviceList::DeviceRemoveFailed(HDEVNOTIFY nfy)
 {
-    DeviceMap::iterator it = m_devs.find(nfy);
-    if (it == m_devs.end())
-        return; // spurious event?
+    for (DeviceMap::iterator it = m_devs.begin();
+         it != m_devs.end();
+         ++it) {
+        CDevice* dev = *it;
 
-    CDevice* dev = it->second;
-    DebugPrint(L"DeviceRemoveFailed(%ws)\n", dev->Path());
+        if (dev->Notify() != nfy)
+            continue;
 
-    if (!dev->Open())
-        DeviceRemoved(nfy);
+        DebugPrint(L"DeviceRemoveFailed(%ws)\n", dev->Path());
+
+        if (!dev->Open())
+            DeviceRemoved(nfy);
 
-    if (m_impl)
-        m_impl->OnDeviceAdded(dev);
+        OnDeviceAdded(dev);
+        return;
+    }
+    // Spurious event?
 }
diff --git a/src/xenagent/devicelist.h b/src/xenagent/devicelist.h
index e96df56..3e260f8 100644
--- a/src/xenagent/devicelist.h
+++ b/src/xenagent/devicelist.h
@@ -34,9 +34,18 @@
 
 #include <windows.h>
 #include <dbt.h>
-#include <map>
+#include <vector>
 #include <string>
 
+class CCritSec
+{
+public:
+    CCritSec(LPCRITICAL_SECTION crit);
+    ~CCritSec();
+private:
+    LPCRITICAL_SECTION m_crit;
+};
+
 class CDevice
 {
 public:
@@ -44,10 +53,11 @@ public:
     virtual ~CDevice();
 
     const wchar_t* Path() const;
+    HDEVNOTIFY Notify() const;
 
     bool Open();
     void Close();
-    HDEVNOTIFY Register(HANDLE svc);
+    bool Register(HANDLE svc);
     void Unregister();
 
 protected:
@@ -60,27 +70,31 @@ private:
     HDEVNOTIFY      m_notify;
 };
 
-class IDeviceCreator
+class CDeviceList
 {
-public:
+protected:
+    CDeviceList(const GUID& itf);
+
     virtual CDevice* Create(const wchar_t* path) = 0;
-    virtual void OnDeviceAdded(CDevice* dev) = 0;
-    virtual void OnDeviceRemoved(CDevice* dev) = 0;
-    virtual void OnDeviceSuspend(CDevice* dev) = 0;
-    virtual void OnDeviceResume(CDevice* dev) = 0;
-};
+    virtual void OnDeviceAdded(CDevice* dev)     = 0;
+    virtual void OnDeviceRemoved(CDevice* dev)   = 0;
+    virtual void OnDeviceSuspend(CDevice* dev)   = 0;
+    virtual void OnDeviceResume(CDevice* dev)    = 0;
+
+    CRITICAL_SECTION    m_crit;
 
-class CDeviceList
-{
 public:
-    CDeviceList(const GUID& itf);
-    ~CDeviceList();
+    virtual ~CDeviceList();
+
+    CDevice* GetFirstDevice();
+
+    bool RegisterForDeviceChange(HANDLE svc);
+    void UnregisterForDeviceChange();
+    void EnumerateDevices();
+    void CleanupDeviceList();
 
-    bool Start(HANDLE svc, IDeviceCreator* impl);
-    void Stop();
     void OnDeviceEvent(DWORD evt, LPVOID data);
     void OnPowerEvent(DWORD evt, LPVOID data);
-    CDevice* GetFirstDevice();
 
 private:
     void DeviceArrival(const std::wstring& path);
@@ -88,13 +102,12 @@ private:
     void DeviceRemovePending(HDEVNOTIFY nfy);
     void DeviceRemoveFailed(HDEVNOTIFY nfy);
 
-    typedef std::map< HDEVNOTIFY, CDevice* > DeviceMap;
+    typedef std::vector< CDevice* > DeviceMap;
 
-    GUID        m_guid;
-    DeviceMap   m_devs;
-    HDEVNOTIFY  m_notify;
-    HANDLE      m_handle;
-    IDeviceCreator* m_impl;
+    GUID                m_guid;
+    DeviceMap           m_devs;
+    HDEVNOTIFY          m_notify;
+    HANDLE              m_handle;
 };
 
 #endif
diff --git a/src/xenagent/service.cpp b/src/xenagent/service.cpp
index 85fac63..535d761 100644
--- a/src/xenagent/service.cpp
+++ b/src/xenagent/service.cpp
@@ -29,478 +29,14 @@
  * SUCH DAMAGE.
  */
 
-#define INITGUID
 #include <windows.h>
 #include <stdio.h>
 #include <powrprof.h>
 #include <winuser.h>
 
-#include <xeniface_ioctls.h>
-
 #include "service.h"
 #include "messages.h"
-
-class CCritSec
-{
-public:
-    CCritSec(LPCRITICAL_SECTION crit);
-    ~CCritSec();
-private:
-    LPCRITICAL_SECTION m_crit;
-};
-
-CCritSec::CCritSec(LPCRITICAL_SECTION crit) : m_crit(crit)
-{
-    EnterCriticalSection(m_crit);
-}
-CCritSec::~CCritSec()
-{
-    LeaveCriticalSection(m_crit);
-}
-
-CXenIfaceCreator::CXenIfaceCreator(CXenAgent& agent) :
-    m_devlist(GUID_INTERFACE_XENIFACE), m_device(NULL),
-    m_ctxt_shutdown(NULL), m_ctxt_suspend(NULL),
-    m_ctxt_slate_mode(NULL), m_agent(agent)
-{
-    m_evt_shutdown = CreateEvent(NULL, TRUE, FALSE, NULL);
-    m_evt_suspend = CreateEvent(NULL, TRUE, FALSE, NULL);
-    m_evt_slate_mode = CreateEvent(NULL, TRUE, FALSE, NULL);
-    m_count = 0;
-
-    InitializeCriticalSection(&m_crit);
-}
-
-CXenIfaceCreator::~CXenIfaceCreator()
-{
-    CloseHandle(m_evt_slate_mode);
-    CloseHandle(m_evt_suspend);
-    CloseHandle(m_evt_shutdown);
-
-    DeleteCriticalSection(&m_crit);
-}
-
-bool CXenIfaceCreator::Start(HANDLE svc)
-{
-    return m_devlist.Start(svc, this);
-}
-
-void CXenIfaceCreator::Stop()
-{
-    // Check if registry key is present, implies Windows Update
-    // require a reboot, which may spend time installing updates
-    LogIfRebootPending();
-
-    m_devlist.Stop();
-}
-
-void CXenIfaceCreator::OnDeviceEvent(DWORD evt, LPVOID data)
-{
-    m_devlist.OnDeviceEvent(evt, data);
-}
-
-void CXenIfaceCreator::OnPowerEvent(DWORD evt, LPVOID data)
-{
-    m_devlist.OnPowerEvent(evt, data);
-}
-
-void CXenIfaceCreator::Log(const char* message)
-{
-    // if possible, send to xeniface to forward to logs
-    if (m_device && TryEnterCriticalSection(&m_crit)) {
-        m_device->Log(message);
-        LeaveCriticalSection(&m_crit);
-    }
-}
-
-/*virtual*/ CDevice* CXenIfaceCreator::Create(const wchar_t* path)
-{
-    return new CXenIfaceDevice(path);
-}
-
-/*virtual*/ void CXenIfaceCreator::OnDeviceAdded(CDevice* dev)
-{
-    CXenAgent::Log("OnDeviceAdded(%ws)\n", dev->Path());
-
-    CCritSec crit(&m_crit);
-    if (m_device == NULL) {
-        m_device = (CXenIfaceDevice*)dev;
-
-        m_device->SuspendRegister(m_evt_suspend, &m_ctxt_suspend);
-
-        StartShutdownWatch();
-
-        if (m_agent.ConvDevicePresent())
-            StartSlateModeWatch();
-
-        SetXenTime();
-    }
-}
-
-/*virtual*/ void CXenIfaceCreator::OnDeviceRemoved(CDevice* dev)
-{
-    CXenAgent::Log("OnDeviceRemoved(%ws)\n", dev->Path());
-
-    CCritSec crit(&m_crit);
-    if (m_device == dev) {
-        if (m_ctxt_suspend) {
-            m_device->SuspendDeregister(m_ctxt_suspend);
-            m_ctxt_suspend = NULL;
-        }
-
-        if (m_agent.ConvDevicePresent())
-            StopSlateModeWatch();
-
-        StopShutdownWatch();
-
-        m_device = NULL;
-    }
-}
-
-/*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()
-{
-    CCritSec crit(&m_crit);
-    if (m_device == NULL)
-        return false;
-
-    std::string type;
-    if (!m_device->StoreRead("control/shutdown", type))
-        return false;
-
-    if (type != "")
-        CXenAgent::Log("Shutdown(%ws) = '%s'\n", m_device->Path(), 
type.c_str());
-
-    if (type == "poweroff") {
-        m_device->StoreWrite("control/shutdown", "");
-        m_agent.EventLog(EVENT_XENUSER_POWEROFF);
-
-        AcquireShutdownPrivilege();
-#pragma warning(suppress:28159) /* Consider using a design alternative... 
Rearchitect to avoid Reboot */
-        if (!InitiateSystemShutdownEx(NULL, NULL, 0, TRUE, FALSE,
-                                      SHTDN_REASON_MAJOR_OTHER |
-                                      SHTDN_REASON_MINOR_ENVIRONMENT |
-                                      SHTDN_REASON_FLAG_PLANNED)) {
-            CXenAgent::Log("InitiateSystemShutdownEx failed %08x\n", 
GetLastError());
-        }
-        return true;
-    } else if (type == "reboot") {
-        m_device->StoreWrite("control/shutdown", "");
-        m_agent.EventLog(EVENT_XENUSER_REBOOT);
-
-        AcquireShutdownPrivilege();
-#pragma warning(suppress:28159) /* Consider using a design alternative... 
Rearchitect to avoid Reboot */
-        if (!InitiateSystemShutdownEx(NULL, NULL, 0, TRUE, TRUE,
-                                      SHTDN_REASON_MAJOR_OTHER |
-                                      SHTDN_REASON_MINOR_ENVIRONMENT |
-                                      SHTDN_REASON_FLAG_PLANNED)) {
-            CXenAgent::Log("InitiateSystemShutdownEx failed %08x\n", 
GetLastError());
-        }
-        return true;
-    } else if (type == "s4") {
-        m_device->StoreWrite("control/shutdown", "");
-        m_agent.EventLog(EVENT_XENUSER_S4);
-
-        AcquireShutdownPrivilege();
-        if (!SetSystemPowerState(FALSE, FALSE)) {
-            CXenAgent::Log("SetSystemPowerState failed %08x\n", 
GetLastError());
-        }
-        return false;
-    } else if (type == "s3") {
-        m_device->StoreWrite("control/shutdown", "");
-        m_agent.EventLog(EVENT_XENUSER_S3);
-
-        AcquireShutdownPrivilege();
-        if (!SetSuspendState(FALSE, TRUE, FALSE)) {
-            CXenAgent::Log("SetSuspendState failed %08x\n", GetLastError());
-        }
-        return false;
-    }
-
-    return false;
-}
-
-void CXenIfaceCreator::CheckXenTime()
-{
-    CCritSec crit(&m_crit);
-    if (m_device == NULL)
-        return;
-
-    SetXenTime();
-}
-
-void CXenIfaceCreator::CheckSuspend()
-{
-    CCritSec crit(&m_crit);
-    if (m_device == NULL)
-        return;
-
-    DWORD count = 0;
-
-    if (!m_device->SuspendGetCount(&count))
-        return;
-
-    if (m_count == count)
-        return;
-
-    CXenAgent::Log("Suspend(%ws)\n", m_device->Path());
-
-    m_agent.EventLog(EVENT_XENUSER_UNSUSPENDED);
-
-    // recreate watches, as suspending deactivated the watch
-    if (m_agent.ConvDevicePresent())
-        StopSlateModeWatch();
-
-    StopShutdownWatch();
-
-    StartShutdownWatch();
-
-    if (m_agent.ConvDevicePresent())
-        StartSlateModeWatch();
-
-    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::LogIfRebootPending()
-{
-    HKEY Key;
-    LONG lResult;
-
-    lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
-                           
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WindowsUpdate\\Auto 
Update\\RebootRequired",
-                           0,
-                           KEY_READ,
-                           &Key);
-    if (lResult != ERROR_SUCCESS)
-        return; // key doesnt exist, dont log anything
-
-    RegCloseKey(Key);
-
-    CXenAgent::Log("RebootRequired detected\n");
-}
-
-void CXenIfaceCreator::StartShutdownWatch()
-{
-    if (m_ctxt_shutdown)
-        return;
-
-    m_device->StoreAddWatch("control/shutdown", m_evt_shutdown, 
&m_ctxt_shutdown);
-
-    m_device->StoreWrite("control/feature-poweroff", "1");
-    m_device->StoreWrite("control/feature-reboot", "1");
-    m_device->StoreWrite("control/feature-s3", "1");
-    m_device->StoreWrite("control/feature-s4", "1");
-}
-
-void CXenIfaceCreator::StopShutdownWatch()
-{
-    if (!m_ctxt_shutdown)
-        return;
-
-    m_device->StoreWrite("control/feature-poweroff", "");
-    m_device->StoreWrite("control/feature-reboot", "");
-    m_device->StoreWrite("control/feature-s3", "");
-    m_device->StoreWrite("control/feature-s4", "");
-
-    m_device->StoreRemoveWatch(m_ctxt_shutdown);
-    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;
-    TOKEN_PRIVILEGES tp;
-
-    LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tp.Privileges[0].Luid);
-    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
-
-    tp.PrivilegeCount = 1;
-
-    if (!OpenProcessToken(GetCurrentProcess(),
-                          TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
-                          &token))
-        return;
-
-    AdjustTokenPrivileges(token, FALSE, &tp, NULL, 0, NULL);
-    CloseHandle(token);
-}
-
-void CXenIfaceCreator::SetXenTime()
-{
-    bool local;
-
-    FILETIME now = { 0 };
-    if (!m_device->SharedInfoGetTime(&now, &local))
-        return;
-
-    SYSTEMTIME cur = { 0 };
-    if (local)
-        GetLocalTime(&cur);
-    else
-        GetSystemTime(&cur);
-
-    SYSTEMTIME sys = { 0 };
-    if (!FileTimeToSystemTime(&now, &sys))
-        return;
-
-    if (memcmp(&cur, &sys, sizeof(SYSTEMTIME)) == 0)
-        return;
-
-    CXenAgent::Log("RTC is in %s\n", local ? "local time" : "UTC");
-    CXenAgent::Log("Time Now = %d/%d/%d %d:%02d:%02d.%d\n",
-                   cur.wYear, cur.wMonth, cur.wDay,
-                   cur.wHour, cur.wMinute, cur.wSecond, cur.wMilliseconds);
-    CXenAgent::Log("New Time = %d/%d/%d %d:%02d:%02d.%d\n",
-                   sys.wYear, sys.wMonth, sys.wDay,
-                   sys.wHour, sys.wMinute, sys.wSecond, sys.wMilliseconds);
-
-    if (local)
-        SetLocalTime(&sys);
-    else
-        SetSystemTime(&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());
-}
+#include "xeniface_ioctls.h"
 
 static CXenAgent s_service;
 
@@ -609,8 +145,8 @@ static CXenAgent s_service;
 #pragma warning(push)
 #pragma warning(disable:4355)
 
-CXenAgent::CXenAgent() noexcept : m_handle(NULL), m_evtlog(NULL), 
m_xeniface(*this),
-                         m_conv(*this)
+CXenAgent::CXenAgent() noexcept : m_handle(NULL), m_evtlog(NULL),
+    m_xeniface(this), m_conv(this)
 {
     m_status.dwServiceType        = SERVICE_WIN32;
     m_status.dwCurrentState       = SERVICE_START_PENDING;
@@ -635,20 +171,22 @@ CXenAgent::~CXenAgent()
 void CXenAgent::OnServiceStart()
 {
     CXenAgent::Log("OnServiceStart()\n");
-    m_conv.Start(m_handle);
-    m_xeniface.Start(m_handle);
+    m_xeniface.RegisterForDeviceChange(m_handle);
+    m_xeniface.EnumerateDevices();
+    m_conv.EnumerateDevices();
 }
 
 void CXenAgent::OnServiceStop()
 {
     CXenAgent::Log("OnServiceStop()\n");
-    m_xeniface.Stop();
-    m_conv.Stop();
+    m_xeniface.LogIfRebootPending();
+    m_xeniface.UnregisterForDeviceChange();
+    m_xeniface.CleanupDeviceList();
+    m_conv.CleanupDeviceList();
 }
 
 void CXenAgent::OnDeviceEvent(DWORD evt, LPVOID data)
 {
-    m_conv.OnDeviceEvent(evt, data);
     m_xeniface.OnDeviceEvent(evt, data);
 }
 
@@ -686,7 +224,7 @@ bool CXenAgent::ServiceMainLoop()
         std::string mode;
 
         ResetEvent(m_xeniface.m_evt_slate_mode);
-        if (m_xeniface.CheckSlateMode(&mode))
+        if (m_xeniface.CheckSlateMode(mode))
             m_conv.SetSlateMode(mode);
 
         return true; // continue loop
@@ -722,7 +260,7 @@ void CXenAgent::EventLog(DWORD evt)
 
 bool CXenAgent::ConvDevicePresent()
 {
-    return m_conv.DevicePresent();
+    return m_conv.GetFirstDevice() != NULL;
 }
 
 void CXenAgent::SetServiceStatus(DWORD state, DWORD exit /*= 0*/, DWORD hint 
/*= 0*/)
diff --git a/src/xenagent/service.h b/src/xenagent/service.h
index e886de6..32a6b8d 100644
--- a/src/xenagent/service.h
+++ b/src/xenagent/service.h
@@ -45,88 +45,6 @@
 #include "xenifacedevice.h"
 #include "convdevice.h"
 
-class CXenAgent;
-
-class CXenIfaceCreator : public IDeviceCreator
-{
-public:
-    CXenIfaceCreator(CXenAgent&);
-    virtual ~CXenIfaceCreator();
-    CXenIfaceCreator& operator=(const CXenIfaceCreator&);
-
-    bool Start(HANDLE svc);
-    void Stop();
-    void OnDeviceEvent(DWORD evt, LPVOID data);
-    void OnPowerEvent(DWORD evt, LPVOID data);
-    void Log(const char *message);
-
-public: // IDeviceCreator
-    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);
-
-public:
-    bool CheckShutdown();
-    void CheckXenTime();
-    void CheckSuspend();
-    bool CheckSlateMode(std::string *mode);
-
-public:
-    HANDLE  m_evt_shutdown;
-    HANDLE  m_evt_suspend;
-    HANDLE  m_evt_slate_mode;
-
-private:
-    void LogIfRebootPending();
-    void StartShutdownWatch();
-    void StopShutdownWatch();
-    void StartSlateModeWatch();
-    void StopSlateModeWatch();
-    void AcquireShutdownPrivilege();
-    bool IsRTCInUTC();
-    void SetXenTime();
-
-private:
-    CXenAgent&          m_agent;
-    CDeviceList         m_devlist;
-    CXenIfaceDevice*    m_device;
-    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
@@ -165,8 +83,8 @@ private: // service support
     SERVICE_STATUS_HANDLE   m_handle;
     HANDLE                  m_evtlog;
     HANDLE                  m_svc_stop;
-    CXenIfaceCreator        m_xeniface;
-    CConvCreator            m_conv;
+    CXenIfaceDeviceList     m_xeniface;
+    CConvDeviceList         m_conv;
 };
 
 #endif
diff --git a/src/xenagent/xenifacedevice.cpp b/src/xenagent/xenifacedevice.cpp
index 6ebf163..eea63e4 100644
--- a/src/xenagent/xenifacedevice.cpp
+++ b/src/xenagent/xenifacedevice.cpp
@@ -29,12 +29,16 @@
  * SUCH DAMAGE.
  */
 
+#define INITGUID
 #include <windows.h>
 #include <winioctl.h>
+#include <powrprof.h>
 
+#include "service.h"
 #include "xenifacedevice.h"
 #include "devicelist.h"
 #include "xeniface_ioctls.h"
+#include "messages.h"
 
 CXenIfaceDevice::CXenIfaceDevice(const wchar_t* path) : CDevice(path)
 {}
@@ -169,3 +173,347 @@ bool CXenIfaceDevice::Log(const std::string& msg)
                  (void*)msg.c_str(), (DWORD)msg.length() + 1,
                  NULL, 0);
 }
+
+CXenIfaceDeviceList::CXenIfaceDeviceList(CXenAgent* agent) : 
CDeviceList(GUID_INTERFACE_XENIFACE),
+    m_agent(agent),
+    m_ctxt_suspend(NULL),
+    m_ctxt_shutdown(NULL),
+    m_ctxt_slate_mode(NULL)
+{
+    m_evt_shutdown = CreateEvent(NULL, TRUE, FALSE, NULL);
+    m_evt_suspend = CreateEvent(NULL, TRUE, FALSE, NULL);
+    m_evt_slate_mode = CreateEvent(NULL, TRUE, FALSE, NULL);
+    m_count = 0;
+}
+
+/*virtual*/ CXenIfaceDeviceList::~CXenIfaceDeviceList()
+{
+    CloseHandle(m_evt_slate_mode);
+    CloseHandle(m_evt_suspend);
+    CloseHandle(m_evt_shutdown);
+}
+
+/*virtual*/ CDevice* CXenIfaceDeviceList::Create(const wchar_t* path)
+{
+    return new CXenIfaceDevice(path);
+}
+
+/*virtual*/ void CXenIfaceDeviceList::OnDeviceAdded(CDevice* dev)
+{
+    CCritSec crit(&m_crit);
+
+    if (GetFirstDevice() != NULL)
+        return;
+
+    CXenIfaceDevice* device = (CXenIfaceDevice*)dev;
+
+    device->SuspendRegister(m_evt_suspend, &m_ctxt_suspend);
+    StartShutdownWatch(device);
+
+    if (m_agent->ConvDevicePresent())
+        StartSlateModeWatch(device);
+
+    SetXenTime(device);
+}
+
+/*virtual*/ void CXenIfaceDeviceList::OnDeviceRemoved(CDevice* dev)
+{
+    CCritSec crit(&m_crit);
+    CXenIfaceDevice* device = (CXenIfaceDevice*)dev;
+
+    if (dev != GetFirstDevice())
+        return;
+
+    if (m_ctxt_suspend)
+        device->SuspendDeregister(m_ctxt_suspend);
+    m_ctxt_suspend = NULL;
+
+    if (m_agent->ConvDevicePresent())
+        StopSlateModeWatch(device);
+
+    StopShutdownWatch(device);
+}
+
+/*virtual*/ void CXenIfaceDeviceList::OnDeviceSuspend(CDevice* dev)
+{
+    CCritSec crit(&m_crit);
+    CXenIfaceDevice* device = (CXenIfaceDevice*)dev;
+
+    if (dev != GetFirstDevice())
+        return;
+
+    if (m_agent->ConvDevicePresent())
+        StopSlateModeWatch(device);
+
+    StopShutdownWatch(device);
+}
+
+/*virtual*/ void CXenIfaceDeviceList::OnDeviceResume(CDevice* dev)
+{
+    CCritSec crit(&m_crit);
+    CXenIfaceDevice* device = (CXenIfaceDevice*)dev;
+
+    if (dev != GetFirstDevice())
+        return;
+
+    StartShutdownWatch(device);
+
+    if (m_agent->ConvDevicePresent())
+        StartSlateModeWatch(device);
+}
+
+void CXenIfaceDeviceList::Log(const char* message)
+{
+    // if possible, send to xeniface to forward to logs
+    if (TryEnterCriticalSection(&m_crit)) {
+        CXenIfaceDevice* device = (CXenIfaceDevice*)GetFirstDevice();
+        if (device != NULL)
+            device->Log(message);
+        LeaveCriticalSection(&m_crit);
+    }
+}
+
+bool CXenIfaceDeviceList::CheckShutdown()
+{
+    CCritSec crit(&m_crit);
+    CXenIfaceDevice* device = (CXenIfaceDevice*)GetFirstDevice();
+
+    if (device == NULL)
+        return false;
+
+    std::string type;
+    if (!device->StoreRead("control/shutdown", type))
+        return false;
+
+    if (type != "")
+        CXenAgent::Log("Shutdown(%ws) = '%s'\n", device->Path(), type.c_str());
+
+    if (type == "poweroff") {
+        device->StoreWrite("control/shutdown", "");
+        m_agent->EventLog(EVENT_XENUSER_POWEROFF);
+
+        AcquireShutdownPrivilege();
+#pragma warning(suppress:28159) /* Consider using a design alternative... 
Rearchitect to avoid Reboot */
+        if (!InitiateSystemShutdownEx(NULL, NULL, 0, TRUE, FALSE,
+                                      SHTDN_REASON_MAJOR_OTHER |
+                                      SHTDN_REASON_MINOR_ENVIRONMENT |
+                                      SHTDN_REASON_FLAG_PLANNED)) {
+            CXenAgent::Log("InitiateSystemShutdownEx failed %08x\n", 
GetLastError());
+        }
+        return true;
+    } else if (type == "reboot") {
+        device->StoreWrite("control/shutdown", "");
+        m_agent->EventLog(EVENT_XENUSER_REBOOT);
+
+        AcquireShutdownPrivilege();
+#pragma warning(suppress:28159) /* Consider using a design alternative... 
Rearchitect to avoid Reboot */
+        if (!InitiateSystemShutdownEx(NULL, NULL, 0, TRUE, TRUE,
+                                      SHTDN_REASON_MAJOR_OTHER |
+                                      SHTDN_REASON_MINOR_ENVIRONMENT |
+                                      SHTDN_REASON_FLAG_PLANNED)) {
+            CXenAgent::Log("InitiateSystemShutdownEx failed %08x\n", 
GetLastError());
+        }
+        return true;
+    } else if (type == "s4") {
+        device->StoreWrite("control/shutdown", "");
+        m_agent->EventLog(EVENT_XENUSER_S4);
+
+        AcquireShutdownPrivilege();
+        if (!SetSystemPowerState(FALSE, FALSE)) {
+            CXenAgent::Log("SetSystemPowerState failed %08x\n", 
GetLastError());
+        }
+        return false;
+    } else if (type == "s3") {
+        device->StoreWrite("control/shutdown", "");
+        m_agent->EventLog(EVENT_XENUSER_S3);
+
+        AcquireShutdownPrivilege();
+        if (!SetSuspendState(FALSE, TRUE, FALSE)) {
+            CXenAgent::Log("SetSuspendState failed %08x\n", GetLastError());
+        }
+        return false;
+    }
+
+    return false;
+}
+
+void CXenIfaceDeviceList::CheckXenTime()
+{
+    CCritSec crit(&m_crit);
+    CXenIfaceDevice* device = (CXenIfaceDevice*)GetFirstDevice();
+
+    if (device == NULL)
+        return;
+
+    SetXenTime(device);
+}
+
+void CXenIfaceDeviceList::CheckSuspend()
+{
+    CCritSec crit(&m_crit);
+    CXenIfaceDevice* device = (CXenIfaceDevice*)GetFirstDevice();
+
+    if (device == NULL)
+        return;
+
+    DWORD count = 0;
+
+    if (!device->SuspendGetCount(&count))
+        return;
+
+    if (m_count == count)
+        return;
+
+    CXenAgent::Log("Suspend(%ws)\n", device->Path());
+
+    m_agent->EventLog(EVENT_XENUSER_UNSUSPENDED);
+
+    // recreate watches, as suspending deactivated the watch
+    if (m_agent->ConvDevicePresent())
+        StopSlateModeWatch(device);
+
+    StopShutdownWatch(device);
+
+    StartShutdownWatch(device);
+
+    if (m_agent->ConvDevicePresent())
+        StartSlateModeWatch(device);
+
+    m_count = count;
+}
+
+bool CXenIfaceDeviceList::CheckSlateMode(std::string& mode)
+{
+    CCritSec crit(&m_crit);
+    CXenIfaceDevice* device = (CXenIfaceDevice*)GetFirstDevice();
+
+    if (device == NULL)
+        return false;
+
+    if (!device->StoreRead("control/laptop-slate-mode", mode))
+        return false;
+
+    if (mode != "")
+        device->StoreWrite("control/laptop-slate-mode", "");
+
+    return true;
+}
+
+void CXenIfaceDeviceList::LogIfRebootPending()
+{
+    HKEY Key;
+    LONG lResult;
+
+    lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+                           
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WindowsUpdate\\Auto 
Update\\RebootRequired",
+                           0,
+                           KEY_READ,
+                           &Key);
+    if (lResult != ERROR_SUCCESS)
+        return; // key doesnt exist, dont log anything
+
+    RegCloseKey(Key);
+
+    CXenAgent::Log("RebootRequired detected\n");
+}
+
+void CXenIfaceDeviceList::StartShutdownWatch(CXenIfaceDevice* device)
+{
+    if (m_ctxt_shutdown)
+        return;
+
+    device->StoreAddWatch("control/shutdown", m_evt_shutdown, 
&m_ctxt_shutdown);
+
+    device->StoreWrite("control/feature-poweroff", "1");
+    device->StoreWrite("control/feature-reboot", "1");
+    device->StoreWrite("control/feature-s3", "1");
+    device->StoreWrite("control/feature-s4", "1");
+}
+
+void CXenIfaceDeviceList::StopShutdownWatch(CXenIfaceDevice* device)
+{
+    if (!m_ctxt_shutdown)
+        return;
+
+    device->StoreWrite("control/feature-poweroff", "");
+    device->StoreWrite("control/feature-reboot", "");
+    device->StoreWrite("control/feature-s3", "");
+    device->StoreWrite("control/feature-s4", "");
+
+    device->StoreRemoveWatch(m_ctxt_shutdown);
+    m_ctxt_shutdown = NULL;
+}
+
+void CXenIfaceDeviceList::StartSlateModeWatch(CXenIfaceDevice* device)
+{
+    if (m_ctxt_slate_mode)
+        return;
+
+    device->StoreAddWatch("control/laptop-slate-mode", m_evt_slate_mode, 
&m_ctxt_slate_mode);
+    device->StoreWrite("control/feature-laptop-slate-mode", "1");
+}
+
+void CXenIfaceDeviceList::StopSlateModeWatch(CXenIfaceDevice* device)
+{
+    if (!m_ctxt_slate_mode)
+        return;
+
+    device->StoreRemove("control/feature-laptop-slate-mode");
+
+    device->StoreRemoveWatch(m_ctxt_slate_mode);
+    m_ctxt_slate_mode = NULL;
+}
+
+void CXenIfaceDeviceList::AcquireShutdownPrivilege()
+{
+    HANDLE          token;
+    TOKEN_PRIVILEGES tp;
+
+    LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tp.Privileges[0].Luid);
+    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+    tp.PrivilegeCount = 1;
+
+    if (!OpenProcessToken(GetCurrentProcess(),
+                          TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
+                          &token))
+        return;
+
+    AdjustTokenPrivileges(token, FALSE, &tp, NULL, 0, NULL);
+    CloseHandle(token);
+}
+
+void CXenIfaceDeviceList::SetXenTime(CXenIfaceDevice* device)
+{
+    bool local;
+
+    FILETIME now = { 0 };
+    if (!device->SharedInfoGetTime(&now, &local))
+        return;
+
+    SYSTEMTIME cur = { 0 };
+    if (local)
+        GetLocalTime(&cur);
+    else
+        GetSystemTime(&cur);
+
+    SYSTEMTIME sys = { 0 };
+    if (!FileTimeToSystemTime(&now, &sys))
+        return;
+
+    if (memcmp(&cur, &sys, sizeof(SYSTEMTIME)) == 0)
+        return;
+
+    CXenAgent::Log("RTC is in %s\n", local ? "local time" : "UTC");
+    CXenAgent::Log("Time Now = %d/%d/%d %d:%02d:%02d.%d\n",
+                   cur.wYear, cur.wMonth, cur.wDay,
+                   cur.wHour, cur.wMinute, cur.wSecond, cur.wMilliseconds);
+    CXenAgent::Log("New Time = %d/%d/%d %d:%02d:%02d.%d\n",
+                   sys.wYear, sys.wMonth, sys.wDay,
+                   sys.wHour, sys.wMinute, sys.wSecond, sys.wMilliseconds);
+
+    if (local)
+        SetLocalTime(&sys);
+    else
+        SetSystemTime(&sys);
+}
diff --git a/src/xenagent/xenifacedevice.h b/src/xenagent/xenifacedevice.h
index b89b8b1..dcac685 100644
--- a/src/xenagent/xenifacedevice.h
+++ b/src/xenagent/xenifacedevice.h
@@ -61,4 +61,47 @@ public: // logging
     bool Log(const std::string& msg);
 };
 
+class CXenAgent;
+
+class CXenIfaceDeviceList : public CDeviceList
+{
+public:
+    CXenIfaceDeviceList(CXenAgent* agent);
+    virtual ~CXenIfaceDeviceList();
+
+protected: // CDeviceList
+    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);
+
+public:
+    HANDLE  m_evt_shutdown;
+    HANDLE  m_evt_suspend;
+    HANDLE  m_evt_slate_mode;
+
+    void Log(const char* message);
+    bool CheckShutdown();
+    void CheckXenTime();
+    void CheckSuspend();
+    bool CheckSlateMode(std::string& mode);
+
+private:
+    void LogIfRebootPending();
+    void StartShutdownWatch(CXenIfaceDevice* device);
+    void StopShutdownWatch(CXenIfaceDevice* device);
+    void StartSlateModeWatch(CXenIfaceDevice* device);
+    void StopSlateModeWatch(CXenIfaceDevice* device);
+    void AcquireShutdownPrivilege();
+    void SetXenTime(CXenIfaceDevice* device);
+
+private:
+    CXenAgent*  m_agent;
+    DWORD       m_count;
+    void*       m_ctxt_suspend;
+    void*       m_ctxt_shutdown;
+    void*       m_ctxt_slate_mode;
+};
+
 #endif
-- 
2.31.1.windows.1




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.