commands-win32.c (cb4e0f9ddf7d45de7e4716cbab661ea568bd0b6c) commands-win32.c (c6bd8c706a799eb0fece99f468aaa22b818036f3)
1/*
2 * QEMU Guest Agent win32-specific command implementations
3 *
4 * Copyright IBM Corp. 2012
5 *
6 * Authors:
7 * Michael Roth <mdroth@linux.vnet.ibm.com>
8 * Gal Hammer <ghammer@redhat.com>

--- 168 unchanged lines hidden (view full) ---

177 HANDLE token = NULL;
178 TOKEN_PRIVILEGES priv;
179 Error *local_err = NULL;
180
181 if (OpenProcessToken(GetCurrentProcess(),
182 TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &token))
183 {
184 if (!LookupPrivilegeValue(NULL, name, &priv.Privileges[0].Luid)) {
1/*
2 * QEMU Guest Agent win32-specific command implementations
3 *
4 * Copyright IBM Corp. 2012
5 *
6 * Authors:
7 * Michael Roth <mdroth@linux.vnet.ibm.com>
8 * Gal Hammer <ghammer@redhat.com>

--- 168 unchanged lines hidden (view full) ---

177 HANDLE token = NULL;
178 TOKEN_PRIVILEGES priv;
179 Error *local_err = NULL;
180
181 if (OpenProcessToken(GetCurrentProcess(),
182 TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &token))
183 {
184 if (!LookupPrivilegeValue(NULL, name, &priv.Privileges[0].Luid)) {
185 error_set(&local_err, QERR_QGA_COMMAND_FAILED,
186 "no luid for requested privilege");
185 error_setg(&local_err, QERR_QGA_COMMAND_FAILED,
186 "no luid for requested privilege");
187 goto out;
188 }
189
190 priv.PrivilegeCount = 1;
191 priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
192
193 if (!AdjustTokenPrivileges(token, FALSE, &priv, 0, NULL, 0)) {
187 goto out;
188 }
189
190 priv.PrivilegeCount = 1;
191 priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
192
193 if (!AdjustTokenPrivileges(token, FALSE, &priv, 0, NULL, 0)) {
194 error_set(&local_err, QERR_QGA_COMMAND_FAILED,
195 "unable to acquire requested privilege");
194 error_setg(&local_err, QERR_QGA_COMMAND_FAILED,
195 "unable to acquire requested privilege");
196 goto out;
197 }
198
199 } else {
196 goto out;
197 }
198
199 } else {
200 error_set(&local_err, QERR_QGA_COMMAND_FAILED,
201 "failed to open privilege token");
200 error_setg(&local_err, QERR_QGA_COMMAND_FAILED,
201 "failed to open privilege token");
202 }
203
204out:
205 if (token) {
206 CloseHandle(token);
207 }
208 if (local_err) {
209 error_propagate(errp, local_err);
210 }
211}
212
213static void execute_async(DWORD WINAPI (*func)(LPVOID), LPVOID opaque,
214 Error **errp)
215{
216 Error *local_err = NULL;
217
218 HANDLE thread = CreateThread(NULL, 0, func, opaque, 0, NULL);
219 if (!thread) {
202 }
203
204out:
205 if (token) {
206 CloseHandle(token);
207 }
208 if (local_err) {
209 error_propagate(errp, local_err);
210 }
211}
212
213static void execute_async(DWORD WINAPI (*func)(LPVOID), LPVOID opaque,
214 Error **errp)
215{
216 Error *local_err = NULL;
217
218 HANDLE thread = CreateThread(NULL, 0, func, opaque, 0, NULL);
219 if (!thread) {
220 error_set(&local_err, QERR_QGA_COMMAND_FAILED,
221 "failed to dispatch asynchronous command");
220 error_setg(&local_err, QERR_QGA_COMMAND_FAILED,
221 "failed to dispatch asynchronous command");
222 error_propagate(errp, local_err);
223 }
224}
225
226void qmp_guest_shutdown(bool has_mode, const char *mode, Error **errp)
227{
228 Error *local_err = NULL;
229 UINT shutdown_flag = EWX_FORCE;
230
231 slog("guest-shutdown called, mode: %s", mode);
232
233 if (!has_mode || strcmp(mode, "powerdown") == 0) {
234 shutdown_flag |= EWX_POWEROFF;
235 } else if (strcmp(mode, "halt") == 0) {
236 shutdown_flag |= EWX_SHUTDOWN;
237 } else if (strcmp(mode, "reboot") == 0) {
238 shutdown_flag |= EWX_REBOOT;
239 } else {
222 error_propagate(errp, local_err);
223 }
224}
225
226void qmp_guest_shutdown(bool has_mode, const char *mode, Error **errp)
227{
228 Error *local_err = NULL;
229 UINT shutdown_flag = EWX_FORCE;
230
231 slog("guest-shutdown called, mode: %s", mode);
232
233 if (!has_mode || strcmp(mode, "powerdown") == 0) {
234 shutdown_flag |= EWX_POWEROFF;
235 } else if (strcmp(mode, "halt") == 0) {
236 shutdown_flag |= EWX_SHUTDOWN;
237 } else if (strcmp(mode, "reboot") == 0) {
238 shutdown_flag |= EWX_REBOOT;
239 } else {
240 error_set(errp, QERR_INVALID_PARAMETER_VALUE, "mode",
241 "halt|powerdown|reboot");
240 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "mode",
241 "halt|powerdown|reboot");
242 return;
243 }
244
245 /* Request a shutdown privilege, but try to shut down the system
246 anyway. */
247 acquire_privilege(SE_SHUTDOWN_NAME, &local_err);
248 if (local_err) {
249 error_propagate(errp, local_err);
250 return;
251 }
252
253 if (!ExitWindowsEx(shutdown_flag, SHTDN_REASON_FLAG_PLANNED)) {
254 slog("guest-shutdown failed: %lu", GetLastError());
242 return;
243 }
244
245 /* Request a shutdown privilege, but try to shut down the system
246 anyway. */
247 acquire_privilege(SE_SHUTDOWN_NAME, &local_err);
248 if (local_err) {
249 error_propagate(errp, local_err);
250 return;
251 }
252
253 if (!ExitWindowsEx(shutdown_flag, SHTDN_REASON_FLAG_PLANNED)) {
254 slog("guest-shutdown failed: %lu", GetLastError());
255 error_set(errp, QERR_UNDEFINED_ERROR);
255 error_setg(errp, QERR_UNDEFINED_ERROR);
256 }
257}
258
259GuestFileRead *qmp_guest_file_read(int64_t handle, bool has_count,
260 int64_t count, Error **errp)
261{
262 GuestFileRead *read_data = NULL;
263 guchar *buf;

--- 115 unchanged lines hidden (view full) ---

379
380static void guest_file_init(void)
381{
382 QTAILQ_INIT(&guest_file_state.filehandles);
383}
384
385GuestFilesystemInfoList *qmp_guest_get_fsinfo(Error **errp)
386{
256 }
257}
258
259GuestFileRead *qmp_guest_file_read(int64_t handle, bool has_count,
260 int64_t count, Error **errp)
261{
262 GuestFileRead *read_data = NULL;
263 guchar *buf;

--- 115 unchanged lines hidden (view full) ---

379
380static void guest_file_init(void)
381{
382 QTAILQ_INIT(&guest_file_state.filehandles);
383}
384
385GuestFilesystemInfoList *qmp_guest_get_fsinfo(Error **errp)
386{
387 error_set(errp, QERR_UNSUPPORTED);
387 error_setg(errp, QERR_UNSUPPORTED);
388 return NULL;
389}
390
391/*
392 * Return status of freeze/thaw
393 */
394GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **errp)
395{
396 if (!vss_initialized()) {
388 return NULL;
389}
390
391/*
392 * Return status of freeze/thaw
393 */
394GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **errp)
395{
396 if (!vss_initialized()) {
397 error_set(errp, QERR_UNSUPPORTED);
397 error_setg(errp, QERR_UNSUPPORTED);
398 return 0;
399 }
400
401 if (ga_is_frozen(ga_state)) {
402 return GUEST_FSFREEZE_STATUS_FROZEN;
403 }
404
405 return GUEST_FSFREEZE_STATUS_THAWED;

--- 4 unchanged lines hidden (view full) ---

410 * The frozen state is limited for up to 10 seconds by VSS.
411 */
412int64_t qmp_guest_fsfreeze_freeze(Error **errp)
413{
414 int i;
415 Error *local_err = NULL;
416
417 if (!vss_initialized()) {
398 return 0;
399 }
400
401 if (ga_is_frozen(ga_state)) {
402 return GUEST_FSFREEZE_STATUS_FROZEN;
403 }
404
405 return GUEST_FSFREEZE_STATUS_THAWED;

--- 4 unchanged lines hidden (view full) ---

410 * The frozen state is limited for up to 10 seconds by VSS.
411 */
412int64_t qmp_guest_fsfreeze_freeze(Error **errp)
413{
414 int i;
415 Error *local_err = NULL;
416
417 if (!vss_initialized()) {
418 error_set(errp, QERR_UNSUPPORTED);
418 error_setg(errp, QERR_UNSUPPORTED);
419 return 0;
420 }
421
422 slog("guest-fsfreeze called");
423
424 /* cannot risk guest agent blocking itself on a write in this state */
425 ga_set_frozen(ga_state);
426

--- 14 unchanged lines hidden (view full) ---

441 }
442 return 0;
443}
444
445int64_t qmp_guest_fsfreeze_freeze_list(bool has_mountpoints,
446 strList *mountpoints,
447 Error **errp)
448{
419 return 0;
420 }
421
422 slog("guest-fsfreeze called");
423
424 /* cannot risk guest agent blocking itself on a write in this state */
425 ga_set_frozen(ga_state);
426

--- 14 unchanged lines hidden (view full) ---

441 }
442 return 0;
443}
444
445int64_t qmp_guest_fsfreeze_freeze_list(bool has_mountpoints,
446 strList *mountpoints,
447 Error **errp)
448{
449 error_set(errp, QERR_UNSUPPORTED);
449 error_setg(errp, QERR_UNSUPPORTED);
450
451 return 0;
452}
453
454/*
455 * Thaw local file systems using Volume Shadow-copy Service.
456 */
457int64_t qmp_guest_fsfreeze_thaw(Error **errp)
458{
459 int i;
460
461 if (!vss_initialized()) {
450
451 return 0;
452}
453
454/*
455 * Thaw local file systems using Volume Shadow-copy Service.
456 */
457int64_t qmp_guest_fsfreeze_thaw(Error **errp)
458{
459 int i;
460
461 if (!vss_initialized()) {
462 error_set(errp, QERR_UNSUPPORTED);
462 error_setg(errp, QERR_UNSUPPORTED);
463 return 0;
464 }
465
466 qga_vss_fsfreeze(&i, errp, false);
467
468 ga_unset_frozen(ga_state);
469 return i;
470}

--- 19 unchanged lines hidden (view full) ---

490}
491
492/*
493 * Walk list of mounted file systems in the guest, and discard unused
494 * areas.
495 */
496void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **errp)
497{
463 return 0;
464 }
465
466 qga_vss_fsfreeze(&i, errp, false);
467
468 ga_unset_frozen(ga_state);
469 return i;
470}

--- 19 unchanged lines hidden (view full) ---

490}
491
492/*
493 * Walk list of mounted file systems in the guest, and discard unused
494 * areas.
495 */
496void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **errp)
497{
498 error_set(errp, QERR_UNSUPPORTED);
498 error_setg(errp, QERR_UNSUPPORTED);
499}
500
501typedef enum {
502 GUEST_SUSPEND_MODE_DISK,
503 GUEST_SUSPEND_MODE_RAM
504} GuestSuspendMode;
505
506static void check_suspend_mode(GuestSuspendMode mode, Error **errp)
507{
508 SYSTEM_POWER_CAPABILITIES sys_pwr_caps;
509 Error *local_err = NULL;
510
511 ZeroMemory(&sys_pwr_caps, sizeof(sys_pwr_caps));
512 if (!GetPwrCapabilities(&sys_pwr_caps)) {
499}
500
501typedef enum {
502 GUEST_SUSPEND_MODE_DISK,
503 GUEST_SUSPEND_MODE_RAM
504} GuestSuspendMode;
505
506static void check_suspend_mode(GuestSuspendMode mode, Error **errp)
507{
508 SYSTEM_POWER_CAPABILITIES sys_pwr_caps;
509 Error *local_err = NULL;
510
511 ZeroMemory(&sys_pwr_caps, sizeof(sys_pwr_caps));
512 if (!GetPwrCapabilities(&sys_pwr_caps)) {
513 error_set(&local_err, QERR_QGA_COMMAND_FAILED,
514 "failed to determine guest suspend capabilities");
513 error_setg(&local_err, QERR_QGA_COMMAND_FAILED,
514 "failed to determine guest suspend capabilities");
515 goto out;
516 }
517
518 switch (mode) {
519 case GUEST_SUSPEND_MODE_DISK:
520 if (!sys_pwr_caps.SystemS4) {
515 goto out;
516 }
517
518 switch (mode) {
519 case GUEST_SUSPEND_MODE_DISK:
520 if (!sys_pwr_caps.SystemS4) {
521 error_set(&local_err, QERR_QGA_COMMAND_FAILED,
522 "suspend-to-disk not supported by OS");
521 error_setg(&local_err, QERR_QGA_COMMAND_FAILED,
522 "suspend-to-disk not supported by OS");
523 }
524 break;
525 case GUEST_SUSPEND_MODE_RAM:
526 if (!sys_pwr_caps.SystemS3) {
523 }
524 break;
525 case GUEST_SUSPEND_MODE_RAM:
526 if (!sys_pwr_caps.SystemS3) {
527 error_set(&local_err, QERR_QGA_COMMAND_FAILED,
528 "suspend-to-ram not supported by OS");
527 error_setg(&local_err, QERR_QGA_COMMAND_FAILED,
528 "suspend-to-ram not supported by OS");
529 }
530 break;
531 default:
529 }
530 break;
531 default:
532 error_set(&local_err, QERR_INVALID_PARAMETER_VALUE, "mode",
533 "GuestSuspendMode");
532 error_setg(&local_err, QERR_INVALID_PARAMETER_VALUE, "mode",
533 "GuestSuspendMode");
534 }
535
536out:
537 if (local_err) {
538 error_propagate(errp, local_err);
539 }
540}
541

--- 39 unchanged lines hidden (view full) ---

581 if (local_err) {
582 error_propagate(errp, local_err);
583 g_free(mode);
584 }
585}
586
587void qmp_guest_suspend_hybrid(Error **errp)
588{
534 }
535
536out:
537 if (local_err) {
538 error_propagate(errp, local_err);
539 }
540}
541

--- 39 unchanged lines hidden (view full) ---

581 if (local_err) {
582 error_propagate(errp, local_err);
583 g_free(mode);
584 }
585}
586
587void qmp_guest_suspend_hybrid(Error **errp)
588{
589 error_set(errp, QERR_UNSUPPORTED);
589 error_setg(errp, QERR_UNSUPPORTED);
590}
591
592GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
593{
590}
591
592GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
593{
594 error_set(errp, QERR_UNSUPPORTED);
594 error_setg(errp, QERR_UNSUPPORTED);
595 return NULL;
596}
597
598int64_t qmp_guest_get_time(Error **errp)
599{
600 SYSTEMTIME ts = {0};
601 int64_t time_ns;
602 FILETIME tf;

--- 58 unchanged lines hidden (view full) ---

661 if (!SetSystemTime(&ts)) {
662 error_setg(errp, "Failed to set time to guest: %d", (int)GetLastError());
663 return;
664 }
665}
666
667GuestLogicalProcessorList *qmp_guest_get_vcpus(Error **errp)
668{
595 return NULL;
596}
597
598int64_t qmp_guest_get_time(Error **errp)
599{
600 SYSTEMTIME ts = {0};
601 int64_t time_ns;
602 FILETIME tf;

--- 58 unchanged lines hidden (view full) ---

661 if (!SetSystemTime(&ts)) {
662 error_setg(errp, "Failed to set time to guest: %d", (int)GetLastError());
663 return;
664 }
665}
666
667GuestLogicalProcessorList *qmp_guest_get_vcpus(Error **errp)
668{
669 error_set(errp, QERR_UNSUPPORTED);
669 error_setg(errp, QERR_UNSUPPORTED);
670 return NULL;
671}
672
673int64_t qmp_guest_set_vcpus(GuestLogicalProcessorList *vcpus, Error **errp)
674{
670 return NULL;
671}
672
673int64_t qmp_guest_set_vcpus(GuestLogicalProcessorList *vcpus, Error **errp)
674{
675 error_set(errp, QERR_UNSUPPORTED);
675 error_setg(errp, QERR_UNSUPPORTED);
676 return -1;
677}
678
679void qmp_guest_set_user_password(const char *username,
680 const char *password,
681 bool crypted,
682 Error **errp)
683{
676 return -1;
677}
678
679void qmp_guest_set_user_password(const char *username,
680 const char *password,
681 bool crypted,
682 Error **errp)
683{
684 error_set(errp, QERR_UNSUPPORTED);
684 error_setg(errp, QERR_UNSUPPORTED);
685}
686
687GuestMemoryBlockList *qmp_guest_get_memory_blocks(Error **errp)
688{
685}
686
687GuestMemoryBlockList *qmp_guest_get_memory_blocks(Error **errp)
688{
689 error_set(errp, QERR_UNSUPPORTED);
689 error_setg(errp, QERR_UNSUPPORTED);
690 return NULL;
691}
692
693GuestMemoryBlockResponseList *
694qmp_guest_set_memory_blocks(GuestMemoryBlockList *mem_blks, Error **errp)
695{
690 return NULL;
691}
692
693GuestMemoryBlockResponseList *
694qmp_guest_set_memory_blocks(GuestMemoryBlockList *mem_blks, Error **errp)
695{
696 error_set(errp, QERR_UNSUPPORTED);
696 error_setg(errp, QERR_UNSUPPORTED);
697 return NULL;
698}
699
700GuestMemoryBlockInfo *qmp_guest_get_memory_block_info(Error **errp)
701{
697 return NULL;
698}
699
700GuestMemoryBlockInfo *qmp_guest_get_memory_block_info(Error **errp)
701{
702 error_set(errp, QERR_UNSUPPORTED);
702 error_setg(errp, QERR_UNSUPPORTED);
703 return NULL;
704}
705
706/* add unsupported commands to the blacklist */
707GList *ga_command_blacklist_init(GList *blacklist)
708{
709 const char *list_unsupported[] = {
710 "guest-suspend-hybrid", "guest-network-get-interfaces",

--- 35 unchanged lines hidden ---
703 return NULL;
704}
705
706/* add unsupported commands to the blacklist */
707GList *ga_command_blacklist_init(GList *blacklist)
708{
709 const char *list_unsupported[] = {
710 "guest-suspend-hybrid", "guest-network-get-interfaces",

--- 35 unchanged lines hidden ---