Statistics
| Branch: | Revision:

root / qga / commands-win32.c @ dc1c13d9

History | View | Annotate | Download (7 kB)

1 d8ca685a Michael Roth
/*
2 d8ca685a Michael Roth
 * QEMU Guest Agent win32-specific command implementations
3 d8ca685a Michael Roth
 *
4 d8ca685a Michael Roth
 * Copyright IBM Corp. 2012
5 d8ca685a Michael Roth
 *
6 d8ca685a Michael Roth
 * Authors:
7 d8ca685a Michael Roth
 *  Michael Roth      <mdroth@linux.vnet.ibm.com>
8 aa59637e Gal Hammer
 *  Gal Hammer        <ghammer@redhat.com>
9 d8ca685a Michael Roth
 *
10 d8ca685a Michael Roth
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
11 d8ca685a Michael Roth
 * See the COPYING file in the top-level directory.
12 d8ca685a Michael Roth
 */
13 d8ca685a Michael Roth
14 d8ca685a Michael Roth
#include <glib.h>
15 aa59637e Gal Hammer
#include <wtypes.h>
16 aa59637e Gal Hammer
#include <powrprof.h>
17 d8ca685a Michael Roth
#include "qga/guest-agent-core.h"
18 d8ca685a Michael Roth
#include "qga-qmp-commands.h"
19 d8ca685a Michael Roth
#include "qerror.h"
20 d8ca685a Michael Roth
21 546b60d0 Michael Roth
#ifndef SHTDN_REASON_FLAG_PLANNED
22 546b60d0 Michael Roth
#define SHTDN_REASON_FLAG_PLANNED 0x80000000
23 546b60d0 Michael Roth
#endif
24 546b60d0 Michael Roth
25 aa59637e Gal Hammer
static void acquire_privilege(const char *name, Error **err)
26 d8ca685a Michael Roth
{
27 546b60d0 Michael Roth
    HANDLE token;
28 546b60d0 Michael Roth
    TOKEN_PRIVILEGES priv;
29 aa59637e Gal Hammer
    Error *local_err = NULL;
30 aa59637e Gal Hammer
31 aa59637e Gal Hammer
    if (error_is_set(err)) {
32 aa59637e Gal Hammer
        return;
33 aa59637e Gal Hammer
    }
34 aa59637e Gal Hammer
35 aa59637e Gal Hammer
    if (OpenProcessToken(GetCurrentProcess(),
36 aa59637e Gal Hammer
        TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &token))
37 aa59637e Gal Hammer
    {
38 aa59637e Gal Hammer
        if (!LookupPrivilegeValue(NULL, name, &priv.Privileges[0].Luid)) {
39 aa59637e Gal Hammer
            error_set(&local_err, QERR_QGA_COMMAND_FAILED,
40 aa59637e Gal Hammer
                      "no luid for requested privilege");
41 aa59637e Gal Hammer
            goto out;
42 aa59637e Gal Hammer
        }
43 aa59637e Gal Hammer
44 aa59637e Gal Hammer
        priv.PrivilegeCount = 1;
45 aa59637e Gal Hammer
        priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
46 aa59637e Gal Hammer
47 aa59637e Gal Hammer
        if (!AdjustTokenPrivileges(token, FALSE, &priv, 0, NULL, 0)) {
48 aa59637e Gal Hammer
            error_set(&local_err, QERR_QGA_COMMAND_FAILED,
49 aa59637e Gal Hammer
                      "unable to acquire requested privilege");
50 aa59637e Gal Hammer
            goto out;
51 aa59637e Gal Hammer
        }
52 aa59637e Gal Hammer
53 aa59637e Gal Hammer
        CloseHandle(token);
54 aa59637e Gal Hammer
    } else {
55 aa59637e Gal Hammer
        error_set(&local_err, QERR_QGA_COMMAND_FAILED,
56 aa59637e Gal Hammer
                  "failed to open privilege token");
57 aa59637e Gal Hammer
    }
58 aa59637e Gal Hammer
59 aa59637e Gal Hammer
out:
60 aa59637e Gal Hammer
    if (local_err) {
61 aa59637e Gal Hammer
        error_propagate(err, local_err);
62 aa59637e Gal Hammer
    }
63 aa59637e Gal Hammer
}
64 aa59637e Gal Hammer
65 aa59637e Gal Hammer
static void execute_async(DWORD WINAPI (*func)(LPVOID), LPVOID opaque, Error **err)
66 aa59637e Gal Hammer
{
67 aa59637e Gal Hammer
    Error *local_err = NULL;
68 aa59637e Gal Hammer
69 aa59637e Gal Hammer
    if (error_is_set(err)) {
70 aa59637e Gal Hammer
        return;
71 aa59637e Gal Hammer
    }
72 aa59637e Gal Hammer
    HANDLE thread = CreateThread(NULL, 0, func, opaque, 0, NULL);
73 aa59637e Gal Hammer
    if (!thread) {
74 aa59637e Gal Hammer
        error_set(&local_err, QERR_QGA_COMMAND_FAILED,
75 aa59637e Gal Hammer
                  "failed to dispatch asynchronous command");
76 aa59637e Gal Hammer
        error_propagate(err, local_err);
77 aa59637e Gal Hammer
    }
78 aa59637e Gal Hammer
}
79 aa59637e Gal Hammer
80 aa59637e Gal Hammer
void qmp_guest_shutdown(bool has_mode, const char *mode, Error **err)
81 aa59637e Gal Hammer
{
82 546b60d0 Michael Roth
    UINT shutdown_flag = EWX_FORCE;
83 546b60d0 Michael Roth
84 546b60d0 Michael Roth
    slog("guest-shutdown called, mode: %s", mode);
85 546b60d0 Michael Roth
86 546b60d0 Michael Roth
    if (!has_mode || strcmp(mode, "powerdown") == 0) {
87 546b60d0 Michael Roth
        shutdown_flag |= EWX_POWEROFF;
88 546b60d0 Michael Roth
    } else if (strcmp(mode, "halt") == 0) {
89 546b60d0 Michael Roth
        shutdown_flag |= EWX_SHUTDOWN;
90 546b60d0 Michael Roth
    } else if (strcmp(mode, "reboot") == 0) {
91 546b60d0 Michael Roth
        shutdown_flag |= EWX_REBOOT;
92 546b60d0 Michael Roth
    } else {
93 546b60d0 Michael Roth
        error_set(err, QERR_INVALID_PARAMETER_VALUE, "mode",
94 546b60d0 Michael Roth
                  "halt|powerdown|reboot");
95 546b60d0 Michael Roth
        return;
96 546b60d0 Michael Roth
    }
97 546b60d0 Michael Roth
98 546b60d0 Michael Roth
    /* Request a shutdown privilege, but try to shut down the system
99 546b60d0 Michael Roth
       anyway. */
100 aa59637e Gal Hammer
    acquire_privilege(SE_SHUTDOWN_NAME, err);
101 aa59637e Gal Hammer
    if (error_is_set(err)) {
102 aa59637e Gal Hammer
        return;
103 546b60d0 Michael Roth
    }
104 546b60d0 Michael Roth
105 546b60d0 Michael Roth
    if (!ExitWindowsEx(shutdown_flag, SHTDN_REASON_FLAG_PLANNED)) {
106 546b60d0 Michael Roth
        slog("guest-shutdown failed: %d", GetLastError());
107 546b60d0 Michael Roth
        error_set(err, QERR_UNDEFINED_ERROR);
108 546b60d0 Michael Roth
    }
109 d8ca685a Michael Roth
}
110 d8ca685a Michael Roth
111 d8ca685a Michael Roth
int64_t qmp_guest_file_open(const char *path, bool has_mode, const char *mode, Error **err)
112 d8ca685a Michael Roth
{
113 d8ca685a Michael Roth
    error_set(err, QERR_UNSUPPORTED);
114 d8ca685a Michael Roth
    return 0;
115 d8ca685a Michael Roth
}
116 d8ca685a Michael Roth
117 d8ca685a Michael Roth
void qmp_guest_file_close(int64_t handle, Error **err)
118 d8ca685a Michael Roth
{
119 d8ca685a Michael Roth
    error_set(err, QERR_UNSUPPORTED);
120 d8ca685a Michael Roth
}
121 d8ca685a Michael Roth
122 d8ca685a Michael Roth
GuestFileRead *qmp_guest_file_read(int64_t handle, bool has_count,
123 d8ca685a Michael Roth
                                   int64_t count, Error **err)
124 d8ca685a Michael Roth
{
125 d8ca685a Michael Roth
    error_set(err, QERR_UNSUPPORTED);
126 d8ca685a Michael Roth
    return 0;
127 d8ca685a Michael Roth
}
128 d8ca685a Michael Roth
129 d8ca685a Michael Roth
GuestFileWrite *qmp_guest_file_write(int64_t handle, const char *buf_b64,
130 d8ca685a Michael Roth
                                     bool has_count, int64_t count, Error **err)
131 d8ca685a Michael Roth
{
132 d8ca685a Michael Roth
    error_set(err, QERR_UNSUPPORTED);
133 d8ca685a Michael Roth
    return 0;
134 d8ca685a Michael Roth
}
135 d8ca685a Michael Roth
136 d8ca685a Michael Roth
GuestFileSeek *qmp_guest_file_seek(int64_t handle, int64_t offset,
137 d8ca685a Michael Roth
                                   int64_t whence, Error **err)
138 d8ca685a Michael Roth
{
139 d8ca685a Michael Roth
    error_set(err, QERR_UNSUPPORTED);
140 d8ca685a Michael Roth
    return 0;
141 d8ca685a Michael Roth
}
142 d8ca685a Michael Roth
143 d8ca685a Michael Roth
void qmp_guest_file_flush(int64_t handle, Error **err)
144 d8ca685a Michael Roth
{
145 d8ca685a Michael Roth
    error_set(err, QERR_UNSUPPORTED);
146 d8ca685a Michael Roth
}
147 d8ca685a Michael Roth
148 d8ca685a Michael Roth
/*
149 d8ca685a Michael Roth
 * Return status of freeze/thaw
150 d8ca685a Michael Roth
 */
151 d8ca685a Michael Roth
GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **err)
152 d8ca685a Michael Roth
{
153 d8ca685a Michael Roth
    error_set(err, QERR_UNSUPPORTED);
154 d8ca685a Michael Roth
    return 0;
155 d8ca685a Michael Roth
}
156 d8ca685a Michael Roth
157 d8ca685a Michael Roth
/*
158 d8ca685a Michael Roth
 * Walk list of mounted file systems in the guest, and freeze the ones which
159 d8ca685a Michael Roth
 * are real local file systems.
160 d8ca685a Michael Roth
 */
161 d8ca685a Michael Roth
int64_t qmp_guest_fsfreeze_freeze(Error **err)
162 d8ca685a Michael Roth
{
163 d8ca685a Michael Roth
    error_set(err, QERR_UNSUPPORTED);
164 d8ca685a Michael Roth
    return 0;
165 d8ca685a Michael Roth
}
166 d8ca685a Michael Roth
167 d8ca685a Michael Roth
/*
168 d8ca685a Michael Roth
 * Walk list of frozen file systems in the guest, and thaw them.
169 d8ca685a Michael Roth
 */
170 d8ca685a Michael Roth
int64_t qmp_guest_fsfreeze_thaw(Error **err)
171 d8ca685a Michael Roth
{
172 d8ca685a Michael Roth
    error_set(err, QERR_UNSUPPORTED);
173 d8ca685a Michael Roth
    return 0;
174 d8ca685a Michael Roth
}
175 d8ca685a Michael Roth
176 eab5fd59 Paolo Bonzini
/*
177 eab5fd59 Paolo Bonzini
 * Walk list of mounted file systems in the guest, and discard unused
178 eab5fd59 Paolo Bonzini
 * areas.
179 eab5fd59 Paolo Bonzini
 */
180 eab5fd59 Paolo Bonzini
void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **err)
181 eab5fd59 Paolo Bonzini
{
182 eab5fd59 Paolo Bonzini
    error_set(err, QERR_UNSUPPORTED);
183 eab5fd59 Paolo Bonzini
184 eab5fd59 Paolo Bonzini
    return;
185 eab5fd59 Paolo Bonzini
}
186 eab5fd59 Paolo Bonzini
187 aa59637e Gal Hammer
typedef enum {
188 f54603b6 Michael Roth
    GUEST_SUSPEND_MODE_DISK,
189 f54603b6 Michael Roth
    GUEST_SUSPEND_MODE_RAM
190 aa59637e Gal Hammer
} GuestSuspendMode;
191 aa59637e Gal Hammer
192 aa59637e Gal Hammer
static void check_suspend_mode(GuestSuspendMode mode, Error **err)
193 aa59637e Gal Hammer
{
194 aa59637e Gal Hammer
    SYSTEM_POWER_CAPABILITIES sys_pwr_caps;
195 aa59637e Gal Hammer
    Error *local_err = NULL;
196 aa59637e Gal Hammer
197 aa59637e Gal Hammer
    if (error_is_set(err)) {
198 aa59637e Gal Hammer
        return;
199 aa59637e Gal Hammer
    }
200 aa59637e Gal Hammer
    ZeroMemory(&sys_pwr_caps, sizeof(sys_pwr_caps));
201 aa59637e Gal Hammer
    if (!GetPwrCapabilities(&sys_pwr_caps)) {
202 aa59637e Gal Hammer
        error_set(&local_err, QERR_QGA_COMMAND_FAILED,
203 aa59637e Gal Hammer
                  "failed to determine guest suspend capabilities");
204 aa59637e Gal Hammer
        goto out;
205 aa59637e Gal Hammer
    }
206 aa59637e Gal Hammer
207 f54603b6 Michael Roth
    switch (mode) {
208 f54603b6 Michael Roth
    case GUEST_SUSPEND_MODE_DISK:
209 f54603b6 Michael Roth
        if (!sys_pwr_caps.SystemS4) {
210 f54603b6 Michael Roth
            error_set(&local_err, QERR_QGA_COMMAND_FAILED,
211 f54603b6 Michael Roth
                      "suspend-to-disk not supported by OS");
212 aa59637e Gal Hammer
        }
213 f54603b6 Michael Roth
        break;
214 f54603b6 Michael Roth
    case GUEST_SUSPEND_MODE_RAM:
215 f54603b6 Michael Roth
        if (!sys_pwr_caps.SystemS3) {
216 f54603b6 Michael Roth
            error_set(&local_err, QERR_QGA_COMMAND_FAILED,
217 f54603b6 Michael Roth
                      "suspend-to-ram not supported by OS");
218 f54603b6 Michael Roth
        }
219 f54603b6 Michael Roth
        break;
220 f54603b6 Michael Roth
    default:
221 aa59637e Gal Hammer
        error_set(&local_err, QERR_INVALID_PARAMETER_VALUE, "mode",
222 aa59637e Gal Hammer
                  "GuestSuspendMode");
223 aa59637e Gal Hammer
    }
224 aa59637e Gal Hammer
225 aa59637e Gal Hammer
out:
226 aa59637e Gal Hammer
    if (local_err) {
227 aa59637e Gal Hammer
        error_propagate(err, local_err);
228 aa59637e Gal Hammer
    }
229 aa59637e Gal Hammer
}
230 aa59637e Gal Hammer
231 aa59637e Gal Hammer
static DWORD WINAPI do_suspend(LPVOID opaque)
232 aa59637e Gal Hammer
{
233 aa59637e Gal Hammer
    GuestSuspendMode *mode = opaque;
234 aa59637e Gal Hammer
    DWORD ret = 0;
235 aa59637e Gal Hammer
236 aa59637e Gal Hammer
    if (!SetSuspendState(*mode == GUEST_SUSPEND_MODE_DISK, TRUE, TRUE)) {
237 aa59637e Gal Hammer
        slog("failed to suspend guest, %s", GetLastError());
238 aa59637e Gal Hammer
        ret = -1;
239 aa59637e Gal Hammer
    }
240 aa59637e Gal Hammer
    g_free(mode);
241 aa59637e Gal Hammer
    return ret;
242 aa59637e Gal Hammer
}
243 aa59637e Gal Hammer
244 11d0f125 Luiz Capitulino
void qmp_guest_suspend_disk(Error **err)
245 11d0f125 Luiz Capitulino
{
246 aa59637e Gal Hammer
    GuestSuspendMode *mode = g_malloc(sizeof(GuestSuspendMode));
247 aa59637e Gal Hammer
248 aa59637e Gal Hammer
    *mode = GUEST_SUSPEND_MODE_DISK;
249 aa59637e Gal Hammer
    check_suspend_mode(*mode, err);
250 aa59637e Gal Hammer
    acquire_privilege(SE_SHUTDOWN_NAME, err);
251 aa59637e Gal Hammer
    execute_async(do_suspend, mode, err);
252 aa59637e Gal Hammer
253 aa59637e Gal Hammer
    if (error_is_set(err)) {
254 aa59637e Gal Hammer
        g_free(mode);
255 aa59637e Gal Hammer
    }
256 11d0f125 Luiz Capitulino
}
257 11d0f125 Luiz Capitulino
258 fbf42210 Luiz Capitulino
void qmp_guest_suspend_ram(Error **err)
259 fbf42210 Luiz Capitulino
{
260 f54603b6 Michael Roth
    GuestSuspendMode *mode = g_malloc(sizeof(GuestSuspendMode));
261 f54603b6 Michael Roth
262 f54603b6 Michael Roth
    *mode = GUEST_SUSPEND_MODE_RAM;
263 f54603b6 Michael Roth
    check_suspend_mode(*mode, err);
264 f54603b6 Michael Roth
    acquire_privilege(SE_SHUTDOWN_NAME, err);
265 f54603b6 Michael Roth
    execute_async(do_suspend, mode, err);
266 f54603b6 Michael Roth
267 f54603b6 Michael Roth
    if (error_is_set(err)) {
268 f54603b6 Michael Roth
        g_free(mode);
269 f54603b6 Michael Roth
    }
270 fbf42210 Luiz Capitulino
}
271 fbf42210 Luiz Capitulino
272 95f4f404 Luiz Capitulino
void qmp_guest_suspend_hybrid(Error **err)
273 95f4f404 Luiz Capitulino
{
274 95f4f404 Luiz Capitulino
    error_set(err, QERR_UNSUPPORTED);
275 95f4f404 Luiz Capitulino
}
276 95f4f404 Luiz Capitulino
277 3424fc9f Michal Privoznik
GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **err)
278 3424fc9f Michal Privoznik
{
279 3424fc9f Michal Privoznik
    error_set(err, QERR_UNSUPPORTED);
280 3424fc9f Michal Privoznik
    return NULL;
281 3424fc9f Michal Privoznik
}
282 3424fc9f Michal Privoznik
283 d8ca685a Michael Roth
/* register init/cleanup routines for stateful command groups */
284 d8ca685a Michael Roth
void ga_command_state_init(GAState *s, GACommandState *cs)
285 d8ca685a Michael Roth
{
286 d8ca685a Michael Roth
}