Annotation of qemu/qga/commands-win32.c, revision 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.