]> git.proxmox.com Git - qemu.git/commitdiff
qemu-ga: add win32 guest-shutdown command
authorMichael Roth <mdroth@linux.vnet.ibm.com>
Mon, 23 Jan 2012 02:24:37 +0000 (20:24 -0600)
committerMichael Roth <mdroth@linux.vnet.ibm.com>
Thu, 23 Feb 2012 21:43:50 +0000 (15:43 -0600)
Implement guest-shutdown RPC for Windows. Functionally this should be
equivalent to the posix implementation.

Original patch by Gal Hammer <ghammer@redhat.com>

qga/commands-win32.c

index d96f1adec6348a6e1f06c2cd22caa55e12844ca8..4aa0f0d1e45492479a191f9435575b3d8716f8c7 100644 (file)
 #include "qga-qmp-commands.h"
 #include "qerror.h"
 
+#ifndef SHTDN_REASON_FLAG_PLANNED
+#define SHTDN_REASON_FLAG_PLANNED 0x80000000
+#endif
+
 void qmp_guest_shutdown(bool has_mode, const char *mode, Error **err)
 {
-    error_set(err, QERR_UNSUPPORTED);
+    HANDLE token;
+    TOKEN_PRIVILEGES priv;
+    UINT shutdown_flag = EWX_FORCE;
+
+    slog("guest-shutdown called, mode: %s", mode);
+
+    if (!has_mode || strcmp(mode, "powerdown") == 0) {
+        shutdown_flag |= EWX_POWEROFF;
+    } else if (strcmp(mode, "halt") == 0) {
+        shutdown_flag |= EWX_SHUTDOWN;
+    } else if (strcmp(mode, "reboot") == 0) {
+        shutdown_flag |= EWX_REBOOT;
+    } else {
+        error_set(err, QERR_INVALID_PARAMETER_VALUE, "mode",
+                  "halt|powerdown|reboot");
+        return;
+    }
+
+    /* Request a shutdown privilege, but try to shut down the system
+       anyway. */
+    if (OpenProcessToken(GetCurrentProcess(),
+        TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &token))
+    {
+        LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME,
+            &priv.Privileges[0].Luid);
+
+        priv.PrivilegeCount = 1;
+        priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+        AdjustTokenPrivileges(token, FALSE, &priv, 0, NULL, 0);
+    }
+
+    if (!ExitWindowsEx(shutdown_flag, SHTDN_REASON_FLAG_PLANNED)) {
+        slog("guest-shutdown failed: %d", GetLastError());
+        error_set(err, QERR_UNDEFINED_ERROR);
+    }
 }
 
 int64_t qmp_guest_file_open(const char *path, bool has_mode, const char *mode, Error **err)