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;
InitializeCriticalSection(&m_crit);
}
bool CXenAgent::ServiceMainLoop()
{
HANDLE events[3] = { m_svc_stop, m_evt_shutdown, m_evt_suspend };
- DWORD wait = WaitForMultipleObjects(3, events, FALSE, INFINITE);
+ DWORD wait = WaitForMultipleObjectsEx(3, events, FALSE, 60000, TRUE);
switch (wait) {
case WAIT_OBJECT_0:
return false; // exit loop
case WAIT_OBJECT_0+1:
- OnShutdown();
- return true; // continue loop
+ return !CheckShutdown();
case WAIT_OBJECT_0+2:
- OnSuspend();
+ CheckSuspend();
return true; // continue loop
+ case WAIT_IO_COMPLETION:
+ case WAIT_TIMEOUT:
+ CheckSuspend();
+ return !CheckShutdown();
+
default:
CXenAgent::Log("WaitForMultipleObjects failed (%08x)\n", wait);
EventLog(EVENT_XENUSER_UNEXPECTED);
#pragma warning(push)
#pragma warning(disable:28159)
-void CXenAgent::OnShutdown()
+bool CXenAgent::CheckShutdown()
{
CCritSec crit(&m_crit);
if (m_device == NULL)
- return;
+ return false;
std::string type;
- m_device->StoreRead("control/shutdown", type);
+ if (!m_device->StoreRead("control/shutdown", type))
+ return false;
- CXenAgent::Log("OnShutdown(%ws) = %s\n", m_device->Path(), type.c_str());
+ CXenAgent::Log("Shutdown(%ws) = %s\n", m_device->Path(), type.c_str());
if (type == "poweroff") {
EventLog(EVENT_XENUSER_POWEROFF);
SHTDN_REASON_FLAG_PLANNED)) {
CXenAgent::Log("InitiateSystemShutdownEx failed %08x\n", GetLastError());
}
+ return true;
} else if (type == "reboot") {
EventLog(EVENT_XENUSER_REBOOT);
SHTDN_REASON_FLAG_PLANNED)) {
CXenAgent::Log("InitiateSystemShutdownEx failed %08x\n", GetLastError());
}
+ return true;
} else if (type == "s4") {
EventLog(EVENT_XENUSER_S4);
if (!SetSystemPowerState(FALSE, FALSE)) {
CXenAgent::Log("SetSystemPowerState failed %08x\n", GetLastError());
}
+ return true;
} else if (type == "s3") {
EventLog(EVENT_XENUSER_S3);
if (!SetSuspendState(FALSE, TRUE, FALSE)) {
CXenAgent::Log("SetSuspendState failed %08x\n", GetLastError());
}
+ return true;
}
+
+ return false;
}
#pragma warning(pop)
-void CXenAgent::OnSuspend()
+void CXenAgent::CheckSuspend()
{
CCritSec crit(&m_crit);
if (m_device == NULL)
return;
- CXenAgent::Log("OnSuspend(%ws)\n", m_device->Path());
+ DWORD count = 0;
+
+ if (!m_device->SuspendGetCount(&count))
+ return;
+
+ if (m_count == count)
+ return;
+
+ CXenAgent::Log("Suspend(%ws)\n", m_device->Path());
+
EventLog(EVENT_XENUSER_UNSUSPENDED);
// recreate shutdown watch, as suspending deactivated the watch
NTSTATUS status;
PCHAR Value;
ULONG Length;
+ BOOLEAN SquashError = FALSE;
status = STATUS_INVALID_BUFFER_SIZE;
if (InLen == 0)
goto fail2;
status = XENBUS_STORE(Read, &Fdo->StoreInterface, NULL, NULL, Buffer, &Value);
- if (!NT_SUCCESS(status))
+ if (!NT_SUCCESS(status)) {
+ if (status == STATUS_OBJECT_NAME_NOT_FOUND)
+ SquashError = TRUE;
+
goto fail3;
+ }
Length = (ULONG)strlen(Value) + 1;
XenIfaceDebugPrint(ERROR, "Fail4 (\"%s\")=(%d < %d)\n", Buffer, OutLen, Length);
XENBUS_STORE(Free, &Fdo->StoreInterface, Value);
fail3:
- XenIfaceDebugPrint(ERROR, "Fail3 (\"%s\")\n", Buffer);
+ if (!SquashError)
+ XenIfaceDebugPrint(ERROR, "Fail3 (\"%s\")\n", Buffer);
fail2:
- XenIfaceDebugPrint(ERROR, "Fail2\n");
+ if (!SquashError)
+ XenIfaceDebugPrint(ERROR, "Fail2\n");
fail1:
- XenIfaceDebugPrint(ERROR, "Fail1 (%08x)\n", status);
+ if (!SquashError)
+ XenIfaceDebugPrint(ERROR, "Fail1 (%08x)\n", status);
+
return status;
}