diff options
author | Michael Roth <mdroth@linux.vnet.ibm.com> | 2012-01-22 20:24:37 -0600 |
---|---|---|
committer | Michael Roth <mdroth@linux.vnet.ibm.com> | 2012-02-23 15:43:50 -0600 |
commit | 546b60d06b9baecfe1cd1afdc41d80482a28942a (patch) | |
tree | 09bba71fb297115a1d8ffbf902057b7e198f62cd /qga/commands-win32.c | |
parent | bc62fa039c402740dbae3233618c982f5943f6b1 (diff) |
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 <ghammer@redhat.com>
Diffstat (limited to 'qga/commands-win32.c')
-rw-r--r-- | 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 d96f1adec6..4aa0f0d1e4 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) |