Annotation of qemu/qga/commands-win32.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.