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

Re: [win-pv-devel] [PATCH 5/6] Add Suspend and Shutdown handlers



> -----Original Message-----
> From: win-pv-devel [mailto:win-pv-devel-bounces@xxxxxxxxxxxxxxxxxxxx] On
> Behalf Of Owen Smith
> Sent: 05 July 2016 11:38
> To: win-pv-devel@xxxxxxxxxxxxxxxxxxxx
> Cc: Owen Smith
> Subject: [win-pv-devel] [PATCH 5/6] Add Suspend and Shutdown handlers
> 
> Suspend needs to re-advertise the shutdown feature
> Shutdown responds to control\shutdown to issue a shutdown, reboot,
> hibernate or S3 transition.
> Suitable event log entries are added when these events are triggered.
> 
> Signed-off-by: Owen Smith <owen.smith@xxxxxxxxxx>

Acked-by: Paul Durrant <paul.durrant@xxxxxxxxxx>

> ---
>  src/xenagent/service.cpp | 147
> ++++++++++++++++++++++++++++++++++++++++++++++-
>  src/xenagent/service.h   |  10 ++++
>  2 files changed, 154 insertions(+), 3 deletions(-)
> 
> diff --git a/src/xenagent/service.cpp b/src/xenagent/service.cpp
> index 84b8814..3e621eb 100644
> --- a/src/xenagent/service.cpp
> +++ b/src/xenagent/service.cpp
> @@ -32,6 +32,8 @@
>  #define INITGUID
>  #include <windows.h>
>  #include <stdio.h>
> +#include <powrprof.h>
> +#include <winuser.h>
> 
>  #include <xeniface_ioctls.h>
> 
> @@ -170,7 +172,8 @@ static CXenAgent s_service;
>  }
> 
>  CXenAgent::CXenAgent() : m_handle(NULL), m_evtlog(NULL),
> -    m_devlist(GUID_INTERFACE_XENIFACE), m_device(NULL)
> +    m_devlist(GUID_INTERFACE_XENIFACE), m_device(NULL),
> +    m_ctxt_shutdown(NULL), m_ctxt_suspend(NULL)
>  {
>      m_status.dwServiceType        = SERVICE_WIN32;
>      m_status.dwCurrentState       = SERVICE_START_PENDING;
> @@ -181,12 +184,16 @@ CXenAgent::CXenAgent() : m_handle(NULL),
> m_evtlog(NULL),
>      m_status.dwWaitHint           = 0;
> 
>      m_svc_stop = CreateEvent(FALSE, NULL, NULL, FALSE);
> +    m_evt_shutdown = CreateEvent(FALSE, NULL, NULL, FALSE);
> +    m_evt_suspend = CreateEvent(FALSE, NULL, NULL, FALSE);
> 
>      InitializeCriticalSection(&m_crit);
>  }
> 
>  CXenAgent::~CXenAgent()
>  {
> +    CloseHandle(m_evt_suspend);
> +    CloseHandle(m_evt_shutdown);
>      CloseHandle(m_svc_stop);
> 
>      DeleteCriticalSection(&m_crit);
> @@ -204,6 +211,13 @@ CXenAgent::~CXenAgent()
>      CCritSec crit(&m_crit);
>      if (m_device == NULL) {
>          m_device = (CXenIfaceDevice*)dev;
> +
> +        // shutdown
> +        m_device->StoreAddWatch("control/shutdown", m_evt_shutdown,
> &m_ctxt_shutdown);
> +        m_device->StoreWrite("control/feature-shutdown", "1");
> +
> +        // suspend
> +        m_device->SuspendRegister(m_evt_suspend, &m_ctxt_suspend);
>      }
>  }
> 
> @@ -213,6 +227,17 @@ CXenAgent::~CXenAgent()
> 
>      CCritSec crit(&m_crit);
>      if (m_device == dev) {
> +        // suspend
> +        if (m_ctxt_suspend)
> +            m_device->SuspendDeregister(m_ctxt_suspend);
> +        m_ctxt_suspend = NULL;
> +
> +        // shutdown
> +        m_device->StoreRemove("control/feature-shutdown");
> +        if (m_ctxt_shutdown)
> +            m_device->StoreRemoveWatch(m_ctxt_shutdown);
> +        m_ctxt_shutdown = NULL;
> +
>          m_device = NULL;
>      }
>  }
> @@ -236,8 +261,124 @@ void CXenAgent::OnDeviceEvent(DWORD evt,
> LPVOID data)
> 
>  bool CXenAgent::ServiceMainLoop()
>  {
> -    WaitForSingleObject(m_svc_stop, INFINITE);
> -    return false;
> +    HANDLE  events[3] = { m_svc_stop, m_evt_shutdown, m_evt_suspend };
> +    DWORD   wait = WaitForMultipleObjects(3, events, FALSE, INFINITE);
> +
> +    switch (wait) {
> +    case WAIT_OBJECT_0:
> +        return false; // exit loop
> +
> +    case WAIT_OBJECT_0+1:
> +        OnShutdown();
> +        return true; // continue loop
> +
> +    case WAIT_OBJECT_0+2:
> +        OnSuspend();
> +        return true; // continue loop
> +
> +    default:
> +        CXenAgent::Log("WaitForMultipleObjects failed (%08x)\n", wait);
> +        EventLog(EVENT_XENUSER_UNEXPECTED);
> +        return true; // continue loop
> +    }
> +}
> +
> +void CXenAgent::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 CXenAgent::EventLog(DWORD evt)
> +{
> +    if (m_evtlog) {
> +        ReportEvent(m_evtlog,
> +                    EVENTLOG_SUCCESS,
> +                    0,
> +                    evt,
> +                    NULL,
> +                    0,
> +                    0,
> +                    NULL,
> +                    NULL);
> +    }
> +}
> +
> +void CXenAgent::OnShutdown()
> +{
> +    CCritSec crit(&m_crit);
> +    if (m_device == NULL)
> +        return;
> +
> +    std::string type;
> +    m_device->StoreRead("control/shutdown", type);
> +
> +    CXenAgent::Log("OnShutdown(%ws) = %s\n", m_device->Path(),
> type.c_str());
> +
> +    if (type == "poweroff" || type == "halt") {
> +        EventLog(EVENT_XENUSER_POWEROFF);
> +
> +        m_device->StoreWrite("control/shutdown", "");
> +        AcquireShutdownPrivilege();
> +        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());
> +        }
> +    } else if (type == "reboot") {
> +        EventLog(EVENT_XENUSER_REBOOT);
> +
> +        m_device->StoreWrite("control/shutdown", "");
> +        AcquireShutdownPrivilege();
> +        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());
> +        }
> +    } else if (type == "hibernate") {
> +        EventLog(EVENT_XENUSER_HIBERNATE);
> +
> +        m_device->StoreWrite("control/shutdown", "");
> +        AcquireShutdownPrivilege();
> +        if (!SetSystemPowerState(FALSE, FALSE)) {
> +            CXenAgent::Log("SetSystemPowerState failed %08x\n",
> GetLastError());
> +        }
> +    } else if (type == "s3") {
> +        EventLog(EVENT_XENUSER_S3);
> +
> +        m_device->StoreWrite("control/shutdown", "");
> +        AcquireShutdownPrivilege();
> +        if (!SetSuspendState(FALSE, TRUE, FALSE)) {
> +            CXenAgent::Log("SetSuspendState failed %08x\n", GetLastError());
> +        }
> +    }
> +}
> +
> +void CXenAgent::OnSuspend()
> +{
> +    CCritSec crit(&m_crit);
> +    if (m_device == NULL)
> +        return;
> +
> +    CXenAgent::Log("OnSuspend(%ws)\n", m_device->Path());
> +    EventLog(EVENT_XENUSER_UNSUSPENDED);
> +
> +    m_device->StoreWrite("control/feature-shutdown", "1");
>  }
> 
>  void CXenAgent::SetServiceStatus(DWORD state, DWORD exit /*= 0*/,
> DWORD hint /*= 0*/)
> diff --git a/src/xenagent/service.h b/src/xenagent/service.h
> index acc4d52..fb8a1ee 100644
> --- a/src/xenagent/service.h
> +++ b/src/xenagent/service.h
> @@ -68,6 +68,12 @@ private: // service events
>      void OnDeviceEvent(DWORD, LPVOID);
>      bool ServiceMainLoop();
> 
> +private: // helpers
> +    void AcquireShutdownPrivilege();
> +    void EventLog(DWORD evt);
> +    void OnShutdown();
> +    void OnSuspend();
> +
>  private: // service support
>      void SetServiceStatus(DWORD state, DWORD exit = 0, DWORD hint = 0);
>      void WINAPI __ServiceMain(int argc, char** argv);
> @@ -77,10 +83,14 @@ private: // service support
>      SERVICE_STATUS_HANDLE   m_handle;
>      HANDLE                  m_evtlog;
>      HANDLE                  m_svc_stop;
> +    HANDLE                  m_evt_shutdown;
> +    HANDLE                  m_evt_suspend;
> 
>      CDeviceList             m_devlist;
>      CXenIfaceDevice*        m_device;
>      CRITICAL_SECTION        m_crit;
> +    void*                   m_ctxt_shutdown;
> +    void*                   m_ctxt_suspend;
>  };
> 
>  #endif
> --
> 1.9.4.msysgit.1
> 
> 
> _______________________________________________
> win-pv-devel mailing list
> win-pv-devel@xxxxxxxxxxxxxxxxxxxx
> http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel
_______________________________________________
win-pv-devel mailing list
win-pv-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

 


Rackspace

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