[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [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> --- 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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |