From 11382eb16af38eec5b03d205728d82bf5cda1062 Mon Sep 17 00:00:00 2001 From: Michael Roth Date: Wed, 7 Mar 2012 11:35:53 -0500 Subject: [PATCH 93/98] qemu-ga: add win32 guest-shutdown command Implement guest-shutdown RPC for Windows. Functionally this should be equivalent to the posix implementation. Original patch by Gal Hammer (cherry picked from commit 546b60d06b9baecfe1cd1afdc41d80482a28942a) Signed-off-by: Jeff Cody Signed-off-by: Michal Novotny --- qga/commands-win32.c | 41 ++++++++++++++++++++++++++++++++++++++++- 1 files changed, 40 insertions(+), 1 deletions(-) diff --git a/qga/commands-win32.c b/qga/commands-win32.c index d96f1ad..4aa0f0d 100644 --- a/qga/commands-win32.c +++ b/qga/commands-win32.c @@ -15,9 +15,48 @@ #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) -- 1.7.7.6