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

[win-pv-devel] [PATCH 1/3] Split xeniface specific parts out of CXenAgent into CXenIfaceCreator



In preparation for supporting more than one device interface, the
one-to-one correspondence between the IDeviceCreator interface and the
CXenAgent object needs to be broken.

This patch separates all code that interacts with the CXenIfaceDevice
object (as well as the CDevice and CDeviceList instances for the xeniface
interface) into a new CXenIfaceCreator object.

Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx>
---
 src/xenagent/service.cpp | 603 +++++++++++++++++++++++++----------------------
 src/xenagent/service.h   |  81 ++++---
 2 files changed, 371 insertions(+), 313 deletions(-)

diff --git a/src/xenagent/service.cpp b/src/xenagent/service.cpp
index 9bc5c20..a2deca1 100644
--- a/src/xenagent/service.cpp
+++ b/src/xenagent/service.cpp
@@ -58,148 +58,10 @@ CCritSec::~CCritSec()
     LeaveCriticalSection(m_crit);
 }
 
-int CALLBACK WinMain(
-    _In_     HINSTANCE hInstance,
-    _In_opt_ HINSTANCE hPrevious,
-    _In_     LPSTR     lpCmdLine,
-    _In_     int       nCmdShow)
-{
-    UNREFERENCED_PARAMETER(hInstance);
-    UNREFERENCED_PARAMETER(hPrevious);
-    UNREFERENCED_PARAMETER(nCmdShow);
-
-    if (strlen(lpCmdLine) != 0) {
-        if (!strcmp(lpCmdLine, "-i") || !strcmp(lpCmdLine, "\"-i\""))
-            return CXenAgent::ServiceInstall();
-        if (!strcmp(lpCmdLine, "-u") || !strcmp(lpCmdLine, "\"-u\""))
-            return CXenAgent::ServiceUninstall();
-    }
-    return CXenAgent::ServiceEntry();
-}
-
-static CXenAgent s_service;
-
-/*static*/ void CXenAgent::Log(const char* fmt, ...)
-{
-    char message[XENIFACE_LOG_MAX_LENGTH];
-    va_list args;
-
-    va_start(args, fmt);
-    vsnprintf_s(message, sizeof(message), sizeof(message)/sizeof(message[0]) - 
1, fmt, args);
-    va_end(args);
-
-    OutputDebugString(message);
-
-    // if possible, send to xeniface to forward to logs
-    CCritSec crit(&s_service.m_crit);
-    if (s_service.m_device) {
-        s_service.m_device->Log(message);
-    }
-}
-
-/*static*/ int CXenAgent::ServiceInstall()
-{
-    SC_HANDLE   svc, mgr;
-    char        path[MAX_PATH+1];
-
-    mgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
-    if (mgr == NULL)
-        return -1;
-
-    if (GetModuleFileNameA(NULL, path, MAX_PATH) == 0) {
-        CloseServiceHandle(mgr);
-        return -1;
-    }
-    path[MAX_PATH] = 0;
-
-    svc = CreateServiceA(mgr, SVC_NAME, SVC_DISPLAYNAME, SERVICE_ALL_ACCESS,
-                        SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START,
-                        SERVICE_ERROR_NORMAL, path,
-                        NULL, NULL, NULL, NULL, NULL);
-    if (svc == NULL) {
-        CloseServiceHandle(mgr);
-        return -2;
-    }
-
-    CloseServiceHandle(svc);
-    CloseServiceHandle(mgr);
-    return 0;
-}
-
-/*static*/ int CXenAgent::ServiceUninstall()
-{
-    SC_HANDLE   svc, mgr;
-
-    mgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
-    if (mgr == NULL)
-        return -1;
-
-    svc = OpenService(mgr, SVC_NAME, SERVICE_ALL_ACCESS);
-    if (svc == NULL) {
-        CloseServiceHandle(mgr);
-        return -2;
-    }
-
-    // try to stop the service
-    if (ControlService(svc, SERVICE_CONTROL_STOP, &s_service.m_status))
-    {
-        Sleep( 1000 );
-
-        while (QueryServiceStatus(svc, &s_service.m_status))
-        {
-            if (s_service.m_status.dwCurrentState != SERVICE_STOP_PENDING)
-                break;
-            Sleep(1000);
-        }
-    }
-
-    // now remove the service
-    DeleteService(svc);
-    CloseServiceHandle(svc);
-    CloseServiceHandle(mgr);
-    return 0;
-}
-
-/*static*/ int CXenAgent::ServiceEntry()
-{
-    SERVICE_TABLE_ENTRY ServiceTable[2] =
-    {
-        { SVC_NAME, (LPSERVICE_MAIN_FUNCTION)ServiceMain },
-        { NULL, NULL }
-    };
-
-    if (!StartServiceCtrlDispatcher(ServiceTable)) {
-        CXenAgent::Log("Failed to start dispatcher\n");
-        return -1;
-    }
-    return 0;
-}
-
-/*static*/ void WINAPI CXenAgent::ServiceMain(int argc, char** argv)
-{
-    s_service.__ServiceMain(argc, argv);
-}
-
-/*static*/ DWORD WINAPI CXenAgent::ServiceControlHandlerEx(DWORD req, DWORD 
evt, LPVOID data, LPVOID ctxt)
-{
-    return s_service.__ServiceControlHandlerEx(req, evt, data, ctxt);
-}
-
-CXenAgent::CXenAgent() : m_handle(NULL), m_evtlog(NULL),
+CXenIfaceCreator::CXenIfaceCreator(CXenAgent& agent) :
     m_devlist(GUID_INTERFACE_XENIFACE), m_device(NULL),
-    m_ctxt_shutdown(NULL), m_ctxt_suspend(NULL)
+    m_ctxt_shutdown(NULL), m_ctxt_suspend(NULL), m_agent(agent)
 {
-    m_status.dwServiceType        = SERVICE_WIN32;
-    m_status.dwCurrentState       = SERVICE_START_PENDING;
-    m_status.dwControlsAccepted   = SERVICE_ACCEPT_STOP |
-                                    SERVICE_ACCEPT_SHUTDOWN |
-                                    SERVICE_ACCEPT_POWEREVENT;
-    m_status.dwWin32ExitCode      = 0;
-    m_status.dwServiceSpecificExitCode = 0;
-    m_status.dwCheckPoint         = 0;
-    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);
     m_count = 0;
@@ -207,49 +69,49 @@ CXenAgent::CXenAgent() : m_handle(NULL), m_evtlog(NULL),
     InitializeCriticalSection(&m_crit);
 }
 
-CXenAgent::~CXenAgent()
+CXenIfaceCreator::~CXenIfaceCreator()
 {
     CloseHandle(m_evt_suspend);
     CloseHandle(m_evt_shutdown);
-    CloseHandle(m_svc_stop);
 
     DeleteCriticalSection(&m_crit);
 }
 
-/*virtual*/ CDevice* CXenAgent::Create(const wchar_t* path)
+bool CXenIfaceCreator::Start(HANDLE svc)
 {
-    return new CXenIfaceDevice(path);
+    return m_devlist.Start(svc, this);
 }
 
-void CXenAgent::StartShutdownWatch()
+void CXenIfaceCreator::Stop()
 {
-    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");
+    m_devlist.Stop();
 }
 
-void CXenAgent::StopShutdownWatch()
+void CXenIfaceCreator::OnDeviceEvent(DWORD evt, LPVOID data)
 {
-    if (!m_ctxt_shutdown)
-        return;
+    m_devlist.OnDeviceEvent(evt, data);
+}
 
-    m_device->StoreRemove("control/feature-poweroff");
-    m_device->StoreRemove("control/feature-reboot");
-    m_device->StoreRemove("control/feature-s3");
-    m_device->StoreRemove("control/feature-s4");
+void CXenIfaceCreator::OnPowerEvent(DWORD evt, LPVOID data)
+{
+    m_devlist.OnPowerEvent(evt, data);
+}
 
-    m_device->StoreRemoveWatch(m_ctxt_shutdown);
-    m_ctxt_shutdown = NULL;
+void CXenIfaceCreator::Log(const char* message)
+{
+    // if possible, send to xeniface to forward to logs
+    CCritSec crit(&m_crit);
+    if (m_device) {
+        m_device->Log(message);
+    }
 }
 
+/*virtual*/ CDevice* CXenIfaceCreator::Create(const wchar_t* path)
+{
+    return new CXenIfaceDevice(path);
+}
 
-/*virtual*/ void CXenAgent::OnDeviceAdded(CDevice* dev)
+/*virtual*/ void CXenIfaceCreator::OnDeviceAdded(CDevice* dev)
 {
     CXenAgent::Log("OnDeviceAdded(%ws)\n", dev->Path());
 
@@ -263,7 +125,7 @@ void CXenAgent::StopShutdownWatch()
     }
 }
 
-/*virtual*/ void CXenAgent::OnDeviceRemoved(CDevice* dev)
+/*virtual*/ void CXenIfaceCreator::OnDeviceRemoved(CDevice* dev)
 {
     CXenAgent::Log("OnDeviceRemoved(%ws)\n", dev->Path());
 
@@ -279,69 +141,130 @@ void CXenAgent::StopShutdownWatch()
     }
 }
 
-/*virtual*/ void CXenAgent::OnDeviceSuspend(CDevice* dev)
+/*virtual*/ void CXenIfaceCreator::OnDeviceSuspend(CDevice* dev)
 {
     CXenAgent::Log("OnDeviceSuspend(%ws)\n", dev->Path());
     StopShutdownWatch();
 }
 
-/*virtual*/ void CXenAgent::OnDeviceResume(CDevice* dev)
+/*virtual*/ void CXenIfaceCreator::OnDeviceResume(CDevice* dev)
 {
     CXenAgent::Log("OnDeviceResume(%ws)\n", dev->Path());
     StartShutdownWatch();
 }
 
-void CXenAgent::OnServiceStart()
+bool CXenIfaceCreator::CheckShutdown()
 {
-    CXenAgent::Log("OnServiceStart()\n");
-    m_devlist.Start(m_handle, this);
-}
+    CCritSec crit(&m_crit);
+    if (m_device == NULL)
+        return false;
 
-void CXenAgent::OnServiceStop()
-{
-    CXenAgent::Log("OnServiceStop()\n");
-    m_devlist.Stop();
-}
+    std::string type;
+    if (!m_device->StoreRead("control/shutdown", type))
+        return false;
 
-void CXenAgent::OnDeviceEvent(DWORD evt, LPVOID data)
-{
-    m_devlist.OnDeviceEvent(evt, data);
+    CXenAgent::Log("Shutdown(%ws) = %s\n", m_device->Path(), type.c_str());
+
+    if (type == "poweroff") {
+        m_agent.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());
+        }
+        return true;
+    } else if (type == "reboot") {
+        m_agent.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());
+        }
+        return true;
+    } else if (type == "s4") {
+        m_agent.EventLog(EVENT_XENUSER_S4);
+
+        m_device->StoreWrite("control/shutdown", "");
+        AcquireShutdownPrivilege();
+        if (!SetSystemPowerState(FALSE, FALSE)) {
+            CXenAgent::Log("SetSystemPowerState failed %08x\n", 
GetLastError());
+        }
+        return true;
+    } else if (type == "s3") {
+        m_agent.EventLog(EVENT_XENUSER_S3);
+
+        m_device->StoreWrite("control/shutdown", "");
+        AcquireShutdownPrivilege();
+        if (!SetSuspendState(FALSE, TRUE, FALSE)) {
+            CXenAgent::Log("SetSuspendState failed %08x\n", GetLastError());
+        }
+        return true;
+    }
+
+    return false;
 }
 
-void CXenAgent::OnPowerEvent(DWORD evt, LPVOID data)
+void CXenIfaceCreator::CheckSuspend()
 {
-    m_devlist.OnPowerEvent(evt, data);
+    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 shutdown watch, as suspending deactivated the watch
+    StopShutdownWatch();
+    StartShutdownWatch();
+    SetXenTime();
+    m_count = count;
 }
 
-bool CXenAgent::ServiceMainLoop()
+void CXenIfaceCreator::StartShutdownWatch()
 {
-    HANDLE  events[3] = { m_svc_stop, m_evt_shutdown, m_evt_suspend };
-    DWORD   wait = WaitForMultipleObjectsEx(3, events, FALSE, 60000, TRUE);
+    if (m_ctxt_shutdown)
+        return;
 
-    switch (wait) {
-    case WAIT_OBJECT_0:
-        return false; // exit loop
+    m_device->StoreAddWatch("control/shutdown", m_evt_shutdown, 
&m_ctxt_shutdown);
 
-    case WAIT_OBJECT_0+1:
-        return !CheckShutdown();
+    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");
+}
 
-    case WAIT_OBJECT_0+2:
-        CheckSuspend();
-        return true; // continue loop
+void CXenIfaceCreator::StopShutdownWatch()
+{
+    if (!m_ctxt_shutdown)
+        return;
 
-    case WAIT_IO_COMPLETION:
-    case WAIT_TIMEOUT:
-        CheckSuspend();
-        return !CheckShutdown();
+    m_device->StoreRemove("control/feature-poweroff");
+    m_device->StoreRemove("control/feature-reboot");
+    m_device->StoreRemove("control/feature-s3");
+    m_device->StoreRemove("control/feature-s4");
 
-    default:
-        CXenAgent::Log("WaitForMultipleObjects failed (%08x)\n", wait);
-        EventLog(EVENT_XENUSER_UNEXPECTED);
-        return true; // continue loop
-    }
+    m_device->StoreRemoveWatch(m_ctxt_shutdown);
+    m_ctxt_shutdown = NULL;
 }
 
-void CXenAgent::AcquireShutdownPrivilege()
+void CXenIfaceCreator::AcquireShutdownPrivilege()
 {
     HANDLE          token;
     TOKEN_PRIVILEGES tp;
@@ -360,22 +283,7 @@ void CXenAgent::AcquireShutdownPrivilege()
     CloseHandle(token);
 }
 
-void CXenAgent::EventLog(DWORD evt)
-{
-    if (m_evtlog) {
-        ReportEvent(m_evtlog,
-                    EVENTLOG_SUCCESS,
-                    0,
-                    evt,
-                    NULL,
-                    0,
-                    0,
-                    NULL,
-                    NULL);
-    }
-}
-
-bool CXenAgent::IsHostTimeUTC()
+bool CXenIfaceCreator::IsHostTimeUTC()
 {
 #ifdef _WIN64
     // Check SOFTWARE\Wow6432Node\$(VENDOR_NAME_STR)\$(REG_KEY_NAME) 
$(REG_UTC_NAME) == UTC
@@ -389,7 +297,7 @@ bool CXenAgent::IsHostTimeUTC()
     return false;
 }
 
-void CXenAgent::AdjustXenTimeToUTC(FILETIME* now)
+void CXenIfaceCreator::AdjustXenTimeToUTC(FILETIME* now)
 {
     std::string vm;
     if (!m_device->StoreRead("vm", vm))
@@ -411,7 +319,7 @@ void CXenAgent::AdjustXenTimeToUTC(FILETIME* now)
     now->dwHighDateTime = lnow.HighPart;
 }
 
-bool CXenAgent::RegCheckIsUTC(const char* rootpath)
+bool CXenIfaceCreator::RegCheckIsUTC(const char* rootpath)
 {
     HKEY    key;
     LRESULT lr;
@@ -459,7 +367,7 @@ fail1:
     return match;
 }
 
-void CXenAgent::SetXenTime()
+void CXenIfaceCreator::SetXenTime()
 {
     // Set VM's time to Xen's time (adjust for UTC settings of VM and guest)
     FILETIME now = { 0 };
@@ -490,93 +398,199 @@ void CXenAgent::SetXenTime()
         SetLocalTime(&sys);
 }
 
-#pragma warning(push)
-#pragma warning(disable:28159)
+static CXenAgent s_service;
 
-bool CXenAgent::CheckShutdown()
+/*static*/ void CXenAgent::Log(const char* fmt, ...)
 {
-    CCritSec crit(&m_crit);
-    if (m_device == NULL)
-        return false;
+    char message[XENIFACE_LOG_MAX_LENGTH];
+    va_list args;
 
-    std::string type;
-    if (!m_device->StoreRead("control/shutdown", type))
-        return false;
+    va_start(args, fmt);
+    vsnprintf_s(message, sizeof(message), sizeof(message)/sizeof(message[0]) - 
1, fmt, args);
+    va_end(args);
 
-    CXenAgent::Log("Shutdown(%ws) = %s\n", m_device->Path(), type.c_str());
+    OutputDebugString(message);
 
-    if (type == "poweroff") {
-        EventLog(EVENT_XENUSER_POWEROFF);
+    s_service.m_xeniface.Log(message);
+}
 
-        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());
-        }
-        return true;
-    } else if (type == "reboot") {
-        EventLog(EVENT_XENUSER_REBOOT);
+/*static*/ int CXenAgent::ServiceInstall()
+{
+    SC_HANDLE   svc, mgr;
+    char        path[MAX_PATH+1];
 
-        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());
-        }
-        return true;
-    } else if (type == "s4") {
-        EventLog(EVENT_XENUSER_S4);
+    mgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+    if (mgr == NULL)
+        return -1;
 
-        m_device->StoreWrite("control/shutdown", "");
-        AcquireShutdownPrivilege();
-        if (!SetSystemPowerState(FALSE, FALSE)) {
-            CXenAgent::Log("SetSystemPowerState failed %08x\n", 
GetLastError());
-        }
-        return true;
-    } else if (type == "s3") {
-        EventLog(EVENT_XENUSER_S3);
+    if (GetModuleFileNameA(NULL, path, MAX_PATH) == 0) {
+        CloseServiceHandle(mgr);
+        return -1;
+    }
+    path[MAX_PATH] = 0;
 
-        m_device->StoreWrite("control/shutdown", "");
-        AcquireShutdownPrivilege();
-        if (!SetSuspendState(FALSE, TRUE, FALSE)) {
-            CXenAgent::Log("SetSuspendState failed %08x\n", GetLastError());
+    svc = CreateServiceA(mgr, SVC_NAME, SVC_DISPLAYNAME, SERVICE_ALL_ACCESS,
+                        SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START,
+                        SERVICE_ERROR_NORMAL, path,
+                        NULL, NULL, NULL, NULL, NULL);
+    if (svc == NULL) {
+        CloseServiceHandle(mgr);
+        return -2;
+    }
+
+    CloseServiceHandle(svc);
+    CloseServiceHandle(mgr);
+    return 0;
+}
+
+/*static*/ int CXenAgent::ServiceUninstall()
+{
+    SC_HANDLE   svc, mgr;
+
+    mgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+    if (mgr == NULL)
+        return -1;
+
+    svc = OpenService(mgr, SVC_NAME, SERVICE_ALL_ACCESS);
+    if (svc == NULL) {
+        CloseServiceHandle(mgr);
+        return -2;
+    }
+
+    // try to stop the service
+    if (ControlService(svc, SERVICE_CONTROL_STOP, &s_service.m_status))
+    {
+        Sleep( 1000 );
+
+        while (QueryServiceStatus(svc, &s_service.m_status))
+        {
+            if (s_service.m_status.dwCurrentState != SERVICE_STOP_PENDING)
+                break;
+            Sleep(1000);
         }
-        return true;
     }
 
-    return false;
+    // now remove the service
+    DeleteService(svc);
+    CloseServiceHandle(svc);
+    CloseServiceHandle(mgr);
+    return 0;
+}
+
+/*static*/ int CXenAgent::ServiceEntry()
+{
+    SERVICE_TABLE_ENTRY ServiceTable[2] =
+    {
+        { SVC_NAME, (LPSERVICE_MAIN_FUNCTION)ServiceMain },
+        { NULL, NULL }
+    };
+
+    if (!StartServiceCtrlDispatcher(ServiceTable)) {
+        CXenAgent::Log("Failed to start dispatcher\n");
+        return -1;
+    }
+    return 0;
+}
+
+/*static*/ void WINAPI CXenAgent::ServiceMain(int argc, char** argv)
+{
+    s_service.__ServiceMain(argc, argv);
+}
+
+/*static*/ DWORD WINAPI CXenAgent::ServiceControlHandlerEx(DWORD req, DWORD 
evt, LPVOID data, LPVOID ctxt)
+{
+    return s_service.__ServiceControlHandlerEx(req, evt, data, ctxt);
+}
+
+#pragma warning(push)
+#pragma warning(disable:4355)
+
+CXenAgent::CXenAgent() : m_handle(NULL), m_evtlog(NULL), m_xeniface(*this)
+{
+    m_status.dwServiceType        = SERVICE_WIN32;
+    m_status.dwCurrentState       = SERVICE_START_PENDING;
+    m_status.dwControlsAccepted   = SERVICE_ACCEPT_STOP |
+                                    SERVICE_ACCEPT_SHUTDOWN |
+                                    SERVICE_ACCEPT_POWEREVENT;
+    m_status.dwWin32ExitCode      = 0;
+    m_status.dwServiceSpecificExitCode = 0;
+    m_status.dwCheckPoint         = 0;
+    m_status.dwWaitHint           = 0;
+
+    m_svc_stop = CreateEvent(FALSE, NULL, NULL, FALSE);
 }
 
 #pragma warning(pop)
 
-void CXenAgent::CheckSuspend()
+CXenAgent::~CXenAgent()
 {
-    CCritSec crit(&m_crit);
-    if (m_device == NULL)
-        return;
+    CloseHandle(m_svc_stop);
+}
 
-    DWORD count = 0;
+void CXenAgent::OnServiceStart()
+{
+    CXenAgent::Log("OnServiceStart()\n");
+    m_xeniface.Start(m_handle);
+}
 
-    if (!m_device->SuspendGetCount(&count))
-        return;
+void CXenAgent::OnServiceStop()
+{
+    CXenAgent::Log("OnServiceStop()\n");
+    m_xeniface.Stop();
+}
 
-    if (m_count == count)
-        return;
+void CXenAgent::OnDeviceEvent(DWORD evt, LPVOID data)
+{
+    m_xeniface.OnDeviceEvent(evt, data);
+}
 
-    CXenAgent::Log("Suspend(%ws)\n", m_device->Path());
+void CXenAgent::OnPowerEvent(DWORD evt, LPVOID data)
+{
+    m_xeniface.OnPowerEvent(evt, data);
+}
 
-    EventLog(EVENT_XENUSER_UNSUSPENDED);
+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);
 
-    // recreate shutdown watch, as suspending deactivated the watch
-    StopShutdownWatch();
-    StartShutdownWatch();
-    SetXenTime();
-    m_count = count;
+    switch (wait) {
+    case WAIT_OBJECT_0:
+        return false; // exit loop
+
+    case WAIT_OBJECT_0+1:
+        return !m_xeniface.CheckShutdown();
+
+    case WAIT_OBJECT_0+2:
+        m_xeniface.CheckSuspend();
+        return true; // continue loop
+
+    case WAIT_IO_COMPLETION:
+    case WAIT_TIMEOUT:
+        m_xeniface.CheckSuspend();
+        return !m_xeniface.CheckShutdown();
+
+    default:
+        CXenAgent::Log("WaitForMultipleObjects failed (%08x)\n", wait);
+        EventLog(EVENT_XENUSER_UNEXPECTED);
+        return true; // continue loop
+    }
+}
+
+void CXenAgent::EventLog(DWORD evt)
+{
+    if (m_evtlog) {
+        ReportEvent(m_evtlog,
+                    EVENTLOG_SUCCESS,
+                    0,
+                    evt,
+                    NULL,
+                    0,
+                    0,
+                    NULL,
+                    NULL);
+    }
 }
 
 void CXenAgent::SetServiceStatus(DWORD state, DWORD exit /*= 0*/, DWORD hint 
/*= 0*/)
@@ -646,3 +660,22 @@ DWORD WINAPI CXenAgent::__ServiceControlHandlerEx(DWORD 
req, DWORD evt, LPVOID d
     SetServiceStatus(SERVICE_RUNNING);
     return ERROR_CALL_NOT_IMPLEMENTED;
 }
+
+int CALLBACK WinMain(
+    _In_     HINSTANCE hInstance,
+    _In_opt_ HINSTANCE hPrevious,
+    _In_     LPSTR     lpCmdLine,
+    _In_     int       nCmdShow)
+{
+    UNREFERENCED_PARAMETER(hInstance);
+    UNREFERENCED_PARAMETER(hPrevious);
+    UNREFERENCED_PARAMETER(nCmdShow);
+
+    if (strlen(lpCmdLine) != 0) {
+        if (!strcmp(lpCmdLine, "-i") || !strcmp(lpCmdLine, "\"-i\""))
+            return CXenAgent::ServiceInstall();
+        if (!strcmp(lpCmdLine, "-u") || !strcmp(lpCmdLine, "\"-u\""))
+            return CXenAgent::ServiceUninstall();
+    }
+    return CXenAgent::ServiceEntry();
+}
diff --git a/src/xenagent/service.h b/src/xenagent/service.h
index 765887c..6d359fe 100644
--- a/src/xenagent/service.h
+++ b/src/xenagent/service.h
@@ -40,7 +40,56 @@
 #include "devicelist.h"
 #include "xenifacedevice.h"
 
-class CXenAgent : public IDeviceCreator
+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 CheckSuspend();
+
+public:
+    HANDLE  m_evt_shutdown;
+    HANDLE  m_evt_suspend;
+
+private:
+    void StartShutdownWatch();
+    void StopShutdownWatch();
+    void AcquireShutdownPrivilege();
+    bool IsHostTimeUTC();
+    void AdjustXenTimeToUTC(FILETIME* time);
+    bool RegCheckIsUTC(const char* path);
+    void SetXenTime();
+
+private:
+    CXenAgent&          m_agent;
+    CDeviceList         m_devlist;
+    CXenIfaceDevice*    m_device;
+    CRITICAL_SECTION    m_crit;
+    void*               m_ctxt_shutdown;
+    void*               m_ctxt_suspend;
+    DWORD               m_count;
+};
+
+class CXenAgent
 {
 public: // statics
     static void Log(const char* fmt, ...);
@@ -56,12 +105,8 @@ public: // ctor/dtor
     CXenAgent();
     virtual ~CXenAgent();
 
-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:
+    void EventLog(DWORD evt);
 
 private: // service events
     void OnServiceStart();
@@ -70,18 +115,6 @@ private: // service events
     void OnPowerEvent(DWORD, LPVOID);
     bool ServiceMainLoop();
 
-private: // helpers
-    void StartShutdownWatch();
-    void StopShutdownWatch();
-    void AcquireShutdownPrivilege();
-    void EventLog(DWORD evt);
-    bool IsHostTimeUTC();
-    void AdjustXenTimeToUTC(FILETIME* time);
-    bool RegCheckIsUTC(const char* path);
-    void SetXenTime();
-    bool CheckShutdown();
-    void CheckSuspend();
-
 private: // service support
     void SetServiceStatus(DWORD state, DWORD exit = 0, DWORD hint = 0);
     void WINAPI __ServiceMain(int argc, char** argv);
@@ -91,15 +124,7 @@ 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;
-    DWORD                   m_count;
+    CXenIfaceCreator        m_xeniface;
 };
 
 #endif
-- 
2.5.3


_______________________________________________
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®.