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> 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 <stdio.h> 18 #include <string.h> 19 #include <winsock2.h> 20 #include <ws2tcpip.h> 21 #include <iptypes.h> 22 #include <iphlpapi.h> 23 #ifdef CONFIG_QGA_NTDDSCSI 24 #include <winioctl.h> 25 #include <ntddscsi.h> 26 #include <setupapi.h> 27 #include <initguid.h> 28 #endif 29 #include <lm.h> 30 31 #include "qga/guest-agent-core.h" 32 #include "qga/vss-win32.h" 33 #include "qga-qmp-commands.h" 34 #include "qapi/qmp/qerror.h" 35 #include "qemu/queue.h" 36 #include "qemu/host-utils.h" 37 38 #ifndef SHTDN_REASON_FLAG_PLANNED 39 #define SHTDN_REASON_FLAG_PLANNED 0x80000000 40 #endif 41 42 /* multiple of 100 nanoseconds elapsed between windows baseline 43 * (1/1/1601) and Unix Epoch (1/1/1970), accounting for leap years */ 44 #define W32_FT_OFFSET (10000000ULL * 60 * 60 * 24 * \ 45 (365 * (1970 - 1601) + \ 46 (1970 - 1601) / 4 - 3)) 47 48 #define INVALID_SET_FILE_POINTER ((DWORD)-1) 49 50 typedef struct GuestFileHandle { 51 int64_t id; 52 HANDLE fh; 53 QTAILQ_ENTRY(GuestFileHandle) next; 54 } GuestFileHandle; 55 56 static struct { 57 QTAILQ_HEAD(, GuestFileHandle) filehandles; 58 } guest_file_state = { 59 .filehandles = QTAILQ_HEAD_INITIALIZER(guest_file_state.filehandles), 60 }; 61 62 63 typedef struct OpenFlags { 64 const char *forms; 65 DWORD desired_access; 66 DWORD creation_disposition; 67 } OpenFlags; 68 static OpenFlags guest_file_open_modes[] = { 69 {"r", GENERIC_READ, OPEN_EXISTING}, 70 {"rb", GENERIC_READ, OPEN_EXISTING}, 71 {"w", GENERIC_WRITE, CREATE_ALWAYS}, 72 {"wb", GENERIC_WRITE, CREATE_ALWAYS}, 73 {"a", GENERIC_WRITE, OPEN_ALWAYS }, 74 {"r+", GENERIC_WRITE|GENERIC_READ, OPEN_EXISTING}, 75 {"rb+", GENERIC_WRITE|GENERIC_READ, OPEN_EXISTING}, 76 {"r+b", GENERIC_WRITE|GENERIC_READ, OPEN_EXISTING}, 77 {"w+", GENERIC_WRITE|GENERIC_READ, CREATE_ALWAYS}, 78 {"wb+", GENERIC_WRITE|GENERIC_READ, CREATE_ALWAYS}, 79 {"w+b", GENERIC_WRITE|GENERIC_READ, CREATE_ALWAYS}, 80 {"a+", GENERIC_WRITE|GENERIC_READ, OPEN_ALWAYS }, 81 {"ab+", GENERIC_WRITE|GENERIC_READ, OPEN_ALWAYS }, 82 {"a+b", GENERIC_WRITE|GENERIC_READ, OPEN_ALWAYS } 83 }; 84 85 static OpenFlags *find_open_flag(const char *mode_str) 86 { 87 int mode; 88 Error **errp = NULL; 89 90 for (mode = 0; mode < ARRAY_SIZE(guest_file_open_modes); ++mode) { 91 OpenFlags *flags = guest_file_open_modes + mode; 92 93 if (strcmp(flags->forms, mode_str) == 0) { 94 return flags; 95 } 96 } 97 98 error_setg(errp, "invalid file open mode '%s'", mode_str); 99 return NULL; 100 } 101 102 static int64_t guest_file_handle_add(HANDLE fh, Error **errp) 103 { 104 GuestFileHandle *gfh; 105 int64_t handle; 106 107 handle = ga_get_fd_handle(ga_state, errp); 108 if (handle < 0) { 109 return -1; 110 } 111 gfh = g_new0(GuestFileHandle, 1); 112 gfh->id = handle; 113 gfh->fh = fh; 114 QTAILQ_INSERT_TAIL(&guest_file_state.filehandles, gfh, next); 115 116 return handle; 117 } 118 119 static GuestFileHandle *guest_file_handle_find(int64_t id, Error **errp) 120 { 121 GuestFileHandle *gfh; 122 QTAILQ_FOREACH(gfh, &guest_file_state.filehandles, next) { 123 if (gfh->id == id) { 124 return gfh; 125 } 126 } 127 error_setg(errp, "handle '%" PRId64 "' has not been found", id); 128 return NULL; 129 } 130 131 int64_t qmp_guest_file_open(const char *path, bool has_mode, 132 const char *mode, Error **errp) 133 { 134 int64_t fd; 135 HANDLE fh; 136 HANDLE templ_file = NULL; 137 DWORD share_mode = FILE_SHARE_READ; 138 DWORD flags_and_attr = FILE_ATTRIBUTE_NORMAL; 139 LPSECURITY_ATTRIBUTES sa_attr = NULL; 140 OpenFlags *guest_flags; 141 142 if (!has_mode) { 143 mode = "r"; 144 } 145 slog("guest-file-open called, filepath: %s, mode: %s", path, mode); 146 guest_flags = find_open_flag(mode); 147 if (guest_flags == NULL) { 148 error_setg(errp, "invalid file open mode"); 149 return -1; 150 } 151 152 fh = CreateFile(path, guest_flags->desired_access, share_mode, sa_attr, 153 guest_flags->creation_disposition, flags_and_attr, 154 templ_file); 155 if (fh == INVALID_HANDLE_VALUE) { 156 error_setg_win32(errp, GetLastError(), "failed to open file '%s'", 157 path); 158 return -1; 159 } 160 161 fd = guest_file_handle_add(fh, errp); 162 if (fd < 0) { 163 CloseHandle(&fh); 164 error_setg(errp, "failed to add handle to qmp handle table"); 165 return -1; 166 } 167 168 slog("guest-file-open, handle: % " PRId64, fd); 169 return fd; 170 } 171 172 void qmp_guest_file_close(int64_t handle, Error **errp) 173 { 174 bool ret; 175 GuestFileHandle *gfh = guest_file_handle_find(handle, errp); 176 slog("guest-file-close called, handle: %" PRId64, handle); 177 if (gfh == NULL) { 178 return; 179 } 180 ret = CloseHandle(gfh->fh); 181 if (!ret) { 182 error_setg_win32(errp, GetLastError(), "failed close handle"); 183 return; 184 } 185 186 QTAILQ_REMOVE(&guest_file_state.filehandles, gfh, next); 187 g_free(gfh); 188 } 189 190 static void acquire_privilege(const char *name, Error **errp) 191 { 192 HANDLE token = NULL; 193 TOKEN_PRIVILEGES priv; 194 Error *local_err = NULL; 195 196 if (OpenProcessToken(GetCurrentProcess(), 197 TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &token)) 198 { 199 if (!LookupPrivilegeValue(NULL, name, &priv.Privileges[0].Luid)) { 200 error_setg(&local_err, QERR_QGA_COMMAND_FAILED, 201 "no luid for requested privilege"); 202 goto out; 203 } 204 205 priv.PrivilegeCount = 1; 206 priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 207 208 if (!AdjustTokenPrivileges(token, FALSE, &priv, 0, NULL, 0)) { 209 error_setg(&local_err, QERR_QGA_COMMAND_FAILED, 210 "unable to acquire requested privilege"); 211 goto out; 212 } 213 214 } else { 215 error_setg(&local_err, QERR_QGA_COMMAND_FAILED, 216 "failed to open privilege token"); 217 } 218 219 out: 220 if (token) { 221 CloseHandle(token); 222 } 223 if (local_err) { 224 error_propagate(errp, local_err); 225 } 226 } 227 228 static void execute_async(DWORD WINAPI (*func)(LPVOID), LPVOID opaque, 229 Error **errp) 230 { 231 Error *local_err = NULL; 232 233 HANDLE thread = CreateThread(NULL, 0, func, opaque, 0, NULL); 234 if (!thread) { 235 error_setg(&local_err, QERR_QGA_COMMAND_FAILED, 236 "failed to dispatch asynchronous command"); 237 error_propagate(errp, local_err); 238 } 239 } 240 241 void qmp_guest_shutdown(bool has_mode, const char *mode, Error **errp) 242 { 243 Error *local_err = NULL; 244 UINT shutdown_flag = EWX_FORCE; 245 246 slog("guest-shutdown called, mode: %s", mode); 247 248 if (!has_mode || strcmp(mode, "powerdown") == 0) { 249 shutdown_flag |= EWX_POWEROFF; 250 } else if (strcmp(mode, "halt") == 0) { 251 shutdown_flag |= EWX_SHUTDOWN; 252 } else if (strcmp(mode, "reboot") == 0) { 253 shutdown_flag |= EWX_REBOOT; 254 } else { 255 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "mode", 256 "halt|powerdown|reboot"); 257 return; 258 } 259 260 /* Request a shutdown privilege, but try to shut down the system 261 anyway. */ 262 acquire_privilege(SE_SHUTDOWN_NAME, &local_err); 263 if (local_err) { 264 error_propagate(errp, local_err); 265 return; 266 } 267 268 if (!ExitWindowsEx(shutdown_flag, SHTDN_REASON_FLAG_PLANNED)) { 269 slog("guest-shutdown failed: %lu", GetLastError()); 270 error_setg(errp, QERR_UNDEFINED_ERROR); 271 } 272 } 273 274 GuestFileRead *qmp_guest_file_read(int64_t handle, bool has_count, 275 int64_t count, Error **errp) 276 { 277 GuestFileRead *read_data = NULL; 278 guchar *buf; 279 HANDLE fh; 280 bool is_ok; 281 DWORD read_count; 282 GuestFileHandle *gfh = guest_file_handle_find(handle, errp); 283 284 if (!gfh) { 285 return NULL; 286 } 287 if (!has_count) { 288 count = QGA_READ_COUNT_DEFAULT; 289 } else if (count < 0) { 290 error_setg(errp, "value '%" PRId64 291 "' is invalid for argument count", count); 292 return NULL; 293 } 294 295 fh = gfh->fh; 296 buf = g_malloc0(count+1); 297 is_ok = ReadFile(fh, buf, count, &read_count, NULL); 298 if (!is_ok) { 299 error_setg_win32(errp, GetLastError(), "failed to read file"); 300 slog("guest-file-read failed, handle %" PRId64, handle); 301 } else { 302 buf[read_count] = 0; 303 read_data = g_new0(GuestFileRead, 1); 304 read_data->count = (size_t)read_count; 305 read_data->eof = read_count == 0; 306 307 if (read_count != 0) { 308 read_data->buf_b64 = g_base64_encode(buf, read_count); 309 } 310 } 311 g_free(buf); 312 313 return read_data; 314 } 315 316 GuestFileWrite *qmp_guest_file_write(int64_t handle, const char *buf_b64, 317 bool has_count, int64_t count, 318 Error **errp) 319 { 320 GuestFileWrite *write_data = NULL; 321 guchar *buf; 322 gsize buf_len; 323 bool is_ok; 324 DWORD write_count; 325 GuestFileHandle *gfh = guest_file_handle_find(handle, errp); 326 HANDLE fh; 327 328 if (!gfh) { 329 return NULL; 330 } 331 fh = gfh->fh; 332 buf = g_base64_decode(buf_b64, &buf_len); 333 334 if (!has_count) { 335 count = buf_len; 336 } else if (count < 0 || count > buf_len) { 337 error_setg(errp, "value '%" PRId64 338 "' is invalid for argument count", count); 339 goto done; 340 } 341 342 is_ok = WriteFile(fh, buf, count, &write_count, NULL); 343 if (!is_ok) { 344 error_setg_win32(errp, GetLastError(), "failed to write to file"); 345 slog("guest-file-write-failed, handle: %" PRId64, handle); 346 } else { 347 write_data = g_new0(GuestFileWrite, 1); 348 write_data->count = (size_t) write_count; 349 } 350 351 done: 352 g_free(buf); 353 return write_data; 354 } 355 356 GuestFileSeek *qmp_guest_file_seek(int64_t handle, int64_t offset, 357 int64_t whence, Error **errp) 358 { 359 GuestFileHandle *gfh; 360 GuestFileSeek *seek_data; 361 HANDLE fh; 362 LARGE_INTEGER new_pos, off_pos; 363 off_pos.QuadPart = offset; 364 BOOL res; 365 gfh = guest_file_handle_find(handle, errp); 366 if (!gfh) { 367 return NULL; 368 } 369 370 fh = gfh->fh; 371 res = SetFilePointerEx(fh, off_pos, &new_pos, whence); 372 if (!res) { 373 error_setg_win32(errp, GetLastError(), "failed to seek file"); 374 return NULL; 375 } 376 seek_data = g_new0(GuestFileSeek, 1); 377 seek_data->position = new_pos.QuadPart; 378 return seek_data; 379 } 380 381 void qmp_guest_file_flush(int64_t handle, Error **errp) 382 { 383 HANDLE fh; 384 GuestFileHandle *gfh = guest_file_handle_find(handle, errp); 385 if (!gfh) { 386 return; 387 } 388 389 fh = gfh->fh; 390 if (!FlushFileBuffers(fh)) { 391 error_setg_win32(errp, GetLastError(), "failed to flush file"); 392 } 393 } 394 395 #ifdef CONFIG_QGA_NTDDSCSI 396 397 static STORAGE_BUS_TYPE win2qemu[] = { 398 [BusTypeUnknown] = GUEST_DISK_BUS_TYPE_UNKNOWN, 399 [BusTypeScsi] = GUEST_DISK_BUS_TYPE_SCSI, 400 [BusTypeAtapi] = GUEST_DISK_BUS_TYPE_IDE, 401 [BusTypeAta] = GUEST_DISK_BUS_TYPE_IDE, 402 [BusType1394] = GUEST_DISK_BUS_TYPE_IEEE1394, 403 [BusTypeSsa] = GUEST_DISK_BUS_TYPE_SSA, 404 [BusTypeFibre] = GUEST_DISK_BUS_TYPE_SSA, 405 [BusTypeUsb] = GUEST_DISK_BUS_TYPE_USB, 406 [BusTypeRAID] = GUEST_DISK_BUS_TYPE_RAID, 407 #if (_WIN32_WINNT >= 0x0600) 408 [BusTypeiScsi] = GUEST_DISK_BUS_TYPE_ISCSI, 409 [BusTypeSas] = GUEST_DISK_BUS_TYPE_SAS, 410 [BusTypeSata] = GUEST_DISK_BUS_TYPE_SATA, 411 [BusTypeSd] = GUEST_DISK_BUS_TYPE_SD, 412 [BusTypeMmc] = GUEST_DISK_BUS_TYPE_MMC, 413 #endif 414 #if (_WIN32_WINNT >= 0x0601) 415 [BusTypeVirtual] = GUEST_DISK_BUS_TYPE_VIRTUAL, 416 [BusTypeFileBackedVirtual] = GUEST_DISK_BUS_TYPE_FILE_BACKED_VIRTUAL, 417 #endif 418 }; 419 420 static GuestDiskBusType find_bus_type(STORAGE_BUS_TYPE bus) 421 { 422 if (bus > ARRAY_SIZE(win2qemu) || (int)bus < 0) { 423 return GUEST_DISK_BUS_TYPE_UNKNOWN; 424 } 425 return win2qemu[(int)bus]; 426 } 427 428 DEFINE_GUID(GUID_DEVINTERFACE_VOLUME, 429 0x53f5630dL, 0xb6bf, 0x11d0, 0x94, 0xf2, 430 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); 431 432 static GuestPCIAddress *get_pci_info(char *guid, Error **errp) 433 { 434 HDEVINFO dev_info; 435 SP_DEVINFO_DATA dev_info_data; 436 DWORD size = 0; 437 int i; 438 char dev_name[MAX_PATH]; 439 char *buffer = NULL; 440 GuestPCIAddress *pci = NULL; 441 char *name = g_strdup(&guid[4]); 442 443 if (!QueryDosDevice(name, dev_name, ARRAY_SIZE(dev_name))) { 444 error_setg_win32(errp, GetLastError(), "failed to get dos device name"); 445 goto out; 446 } 447 448 dev_info = SetupDiGetClassDevs(&GUID_DEVINTERFACE_VOLUME, 0, 0, 449 DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); 450 if (dev_info == INVALID_HANDLE_VALUE) { 451 error_setg_win32(errp, GetLastError(), "failed to get devices tree"); 452 goto out; 453 } 454 455 dev_info_data.cbSize = sizeof(SP_DEVINFO_DATA); 456 for (i = 0; SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data); i++) { 457 DWORD addr, bus, slot, func, dev, data, size2; 458 while (!SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data, 459 SPDRP_PHYSICAL_DEVICE_OBJECT_NAME, 460 &data, (PBYTE)buffer, size, 461 &size2)) { 462 size = MAX(size, size2); 463 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { 464 g_free(buffer); 465 /* Double the size to avoid problems on 466 * W2k MBCS systems per KB 888609. 467 * https://support.microsoft.com/en-us/kb/259695 */ 468 buffer = g_malloc(size * 2); 469 } else { 470 error_setg_win32(errp, GetLastError(), 471 "failed to get device name"); 472 goto out; 473 } 474 } 475 476 if (g_strcmp0(buffer, dev_name)) { 477 continue; 478 } 479 480 /* There is no need to allocate buffer in the next functions. The size 481 * is known and ULONG according to 482 * https://support.microsoft.com/en-us/kb/253232 483 * https://msdn.microsoft.com/en-us/library/windows/hardware/ff543095(v=vs.85).aspx 484 */ 485 if (!SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data, 486 SPDRP_BUSNUMBER, &data, (PBYTE)&bus, size, NULL)) { 487 break; 488 } 489 490 /* The function retrieves the device's address. This value will be 491 * transformed into device function and number */ 492 if (!SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data, 493 SPDRP_ADDRESS, &data, (PBYTE)&addr, size, NULL)) { 494 break; 495 } 496 497 /* This call returns UINumber of DEVICE_CAPABILITIES structure. 498 * This number is typically a user-perceived slot number. */ 499 if (!SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data, 500 SPDRP_UI_NUMBER, &data, (PBYTE)&slot, size, NULL)) { 501 break; 502 } 503 504 /* SetupApi gives us the same information as driver with 505 * IoGetDeviceProperty. According to Microsoft 506 * https://support.microsoft.com/en-us/kb/253232 507 * FunctionNumber = (USHORT)((propertyAddress) & 0x0000FFFF); 508 * DeviceNumber = (USHORT)(((propertyAddress) >> 16) & 0x0000FFFF); 509 * SPDRP_ADDRESS is propertyAddress, so we do the same.*/ 510 511 func = addr & 0x0000FFFF; 512 dev = (addr >> 16) & 0x0000FFFF; 513 pci = g_malloc0(sizeof(*pci)); 514 pci->domain = dev; 515 pci->slot = slot; 516 pci->function = func; 517 pci->bus = bus; 518 break; 519 } 520 out: 521 g_free(buffer); 522 g_free(name); 523 return pci; 524 } 525 526 static int get_disk_bus_type(HANDLE vol_h, Error **errp) 527 { 528 STORAGE_PROPERTY_QUERY query; 529 STORAGE_DEVICE_DESCRIPTOR *dev_desc, buf; 530 DWORD received; 531 532 dev_desc = &buf; 533 dev_desc->Size = sizeof(buf); 534 query.PropertyId = StorageDeviceProperty; 535 query.QueryType = PropertyStandardQuery; 536 537 if (!DeviceIoControl(vol_h, IOCTL_STORAGE_QUERY_PROPERTY, &query, 538 sizeof(STORAGE_PROPERTY_QUERY), dev_desc, 539 dev_desc->Size, &received, NULL)) { 540 error_setg_win32(errp, GetLastError(), "failed to get bus type"); 541 return -1; 542 } 543 544 return dev_desc->BusType; 545 } 546 547 /* VSS provider works with volumes, thus there is no difference if 548 * the volume consist of spanned disks. Info about the first disk in the 549 * volume is returned for the spanned disk group (LVM) */ 550 static GuestDiskAddressList *build_guest_disk_info(char *guid, Error **errp) 551 { 552 GuestDiskAddressList *list = NULL; 553 GuestDiskAddress *disk; 554 SCSI_ADDRESS addr, *scsi_ad; 555 DWORD len; 556 int bus; 557 HANDLE vol_h; 558 559 scsi_ad = &addr; 560 char *name = g_strndup(guid, strlen(guid)-1); 561 562 vol_h = CreateFile(name, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, 563 0, NULL); 564 if (vol_h == INVALID_HANDLE_VALUE) { 565 error_setg_win32(errp, GetLastError(), "failed to open volume"); 566 goto out_free; 567 } 568 569 bus = get_disk_bus_type(vol_h, errp); 570 if (bus < 0) { 571 goto out_close; 572 } 573 574 disk = g_malloc0(sizeof(*disk)); 575 disk->bus_type = find_bus_type(bus); 576 if (bus == BusTypeScsi || bus == BusTypeAta || bus == BusTypeRAID 577 #if (_WIN32_WINNT >= 0x0600) 578 /* This bus type is not supported before Windows Server 2003 SP1 */ 579 || bus == BusTypeSas 580 #endif 581 ) { 582 /* We are able to use the same ioctls for different bus types 583 * according to Microsoft docs 584 * https://technet.microsoft.com/en-us/library/ee851589(v=ws.10).aspx */ 585 if (DeviceIoControl(vol_h, IOCTL_SCSI_GET_ADDRESS, NULL, 0, scsi_ad, 586 sizeof(SCSI_ADDRESS), &len, NULL)) { 587 disk->unit = addr.Lun; 588 disk->target = addr.TargetId; 589 disk->bus = addr.PathId; 590 disk->pci_controller = get_pci_info(name, errp); 591 } 592 /* We do not set error in this case, because we still have enough 593 * information about volume. */ 594 } else { 595 disk->pci_controller = NULL; 596 } 597 598 list = g_malloc0(sizeof(*list)); 599 list->value = disk; 600 list->next = NULL; 601 out_close: 602 CloseHandle(vol_h); 603 out_free: 604 g_free(name); 605 return list; 606 } 607 608 #else 609 610 static GuestDiskAddressList *build_guest_disk_info(char *guid, Error **errp) 611 { 612 return NULL; 613 } 614 615 #endif /* CONFIG_QGA_NTDDSCSI */ 616 617 static GuestFilesystemInfo *build_guest_fsinfo(char *guid, Error **errp) 618 { 619 DWORD info_size; 620 char mnt, *mnt_point; 621 char fs_name[32]; 622 char vol_info[MAX_PATH+1]; 623 size_t len; 624 GuestFilesystemInfo *fs = NULL; 625 626 GetVolumePathNamesForVolumeName(guid, (LPCH)&mnt, 0, &info_size); 627 if (GetLastError() != ERROR_MORE_DATA) { 628 error_setg_win32(errp, GetLastError(), "failed to get volume name"); 629 return NULL; 630 } 631 632 mnt_point = g_malloc(info_size + 1); 633 if (!GetVolumePathNamesForVolumeName(guid, mnt_point, info_size, 634 &info_size)) { 635 error_setg_win32(errp, GetLastError(), "failed to get volume name"); 636 goto free; 637 } 638 639 len = strlen(mnt_point); 640 mnt_point[len] = '\\'; 641 mnt_point[len+1] = 0; 642 if (!GetVolumeInformation(mnt_point, vol_info, sizeof(vol_info), NULL, NULL, 643 NULL, (LPSTR)&fs_name, sizeof(fs_name))) { 644 if (GetLastError() != ERROR_NOT_READY) { 645 error_setg_win32(errp, GetLastError(), "failed to get volume info"); 646 } 647 goto free; 648 } 649 650 fs_name[sizeof(fs_name) - 1] = 0; 651 fs = g_malloc(sizeof(*fs)); 652 fs->name = g_strdup(guid); 653 if (len == 0) { 654 fs->mountpoint = g_strdup("System Reserved"); 655 } else { 656 fs->mountpoint = g_strndup(mnt_point, len); 657 } 658 fs->type = g_strdup(fs_name); 659 fs->disk = build_guest_disk_info(guid, errp); 660 free: 661 g_free(mnt_point); 662 return fs; 663 } 664 665 GuestFilesystemInfoList *qmp_guest_get_fsinfo(Error **errp) 666 { 667 HANDLE vol_h; 668 GuestFilesystemInfoList *new, *ret = NULL; 669 char guid[256]; 670 671 vol_h = FindFirstVolume(guid, sizeof(guid)); 672 if (vol_h == INVALID_HANDLE_VALUE) { 673 error_setg_win32(errp, GetLastError(), "failed to find any volume"); 674 return NULL; 675 } 676 677 do { 678 GuestFilesystemInfo *info = build_guest_fsinfo(guid, errp); 679 if (info == NULL) { 680 continue; 681 } 682 new = g_malloc(sizeof(*ret)); 683 new->value = info; 684 new->next = ret; 685 ret = new; 686 } while (FindNextVolume(vol_h, guid, sizeof(guid))); 687 688 if (GetLastError() != ERROR_NO_MORE_FILES) { 689 error_setg_win32(errp, GetLastError(), "failed to find next volume"); 690 } 691 692 FindVolumeClose(vol_h); 693 return ret; 694 } 695 696 /* 697 * Return status of freeze/thaw 698 */ 699 GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **errp) 700 { 701 if (!vss_initialized()) { 702 error_setg(errp, QERR_UNSUPPORTED); 703 return 0; 704 } 705 706 if (ga_is_frozen(ga_state)) { 707 return GUEST_FSFREEZE_STATUS_FROZEN; 708 } 709 710 return GUEST_FSFREEZE_STATUS_THAWED; 711 } 712 713 /* 714 * Freeze local file systems using Volume Shadow-copy Service. 715 * The frozen state is limited for up to 10 seconds by VSS. 716 */ 717 int64_t qmp_guest_fsfreeze_freeze(Error **errp) 718 { 719 int i; 720 Error *local_err = NULL; 721 722 if (!vss_initialized()) { 723 error_setg(errp, QERR_UNSUPPORTED); 724 return 0; 725 } 726 727 slog("guest-fsfreeze called"); 728 729 /* cannot risk guest agent blocking itself on a write in this state */ 730 ga_set_frozen(ga_state); 731 732 qga_vss_fsfreeze(&i, &local_err, true); 733 if (local_err) { 734 error_propagate(errp, local_err); 735 goto error; 736 } 737 738 return i; 739 740 error: 741 local_err = NULL; 742 qmp_guest_fsfreeze_thaw(&local_err); 743 if (local_err) { 744 g_debug("cleanup thaw: %s", error_get_pretty(local_err)); 745 error_free(local_err); 746 } 747 return 0; 748 } 749 750 int64_t qmp_guest_fsfreeze_freeze_list(bool has_mountpoints, 751 strList *mountpoints, 752 Error **errp) 753 { 754 error_setg(errp, QERR_UNSUPPORTED); 755 756 return 0; 757 } 758 759 /* 760 * Thaw local file systems using Volume Shadow-copy Service. 761 */ 762 int64_t qmp_guest_fsfreeze_thaw(Error **errp) 763 { 764 int i; 765 766 if (!vss_initialized()) { 767 error_setg(errp, QERR_UNSUPPORTED); 768 return 0; 769 } 770 771 qga_vss_fsfreeze(&i, errp, false); 772 773 ga_unset_frozen(ga_state); 774 return i; 775 } 776 777 static void guest_fsfreeze_cleanup(void) 778 { 779 Error *err = NULL; 780 781 if (!vss_initialized()) { 782 return; 783 } 784 785 if (ga_is_frozen(ga_state) == GUEST_FSFREEZE_STATUS_FROZEN) { 786 qmp_guest_fsfreeze_thaw(&err); 787 if (err) { 788 slog("failed to clean up frozen filesystems: %s", 789 error_get_pretty(err)); 790 error_free(err); 791 } 792 } 793 794 vss_deinit(true); 795 } 796 797 /* 798 * Walk list of mounted file systems in the guest, and discard unused 799 * areas. 800 */ 801 GuestFilesystemTrimResponse * 802 qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **errp) 803 { 804 error_setg(errp, QERR_UNSUPPORTED); 805 return NULL; 806 } 807 808 typedef enum { 809 GUEST_SUSPEND_MODE_DISK, 810 GUEST_SUSPEND_MODE_RAM 811 } GuestSuspendMode; 812 813 static void check_suspend_mode(GuestSuspendMode mode, Error **errp) 814 { 815 SYSTEM_POWER_CAPABILITIES sys_pwr_caps; 816 Error *local_err = NULL; 817 818 ZeroMemory(&sys_pwr_caps, sizeof(sys_pwr_caps)); 819 if (!GetPwrCapabilities(&sys_pwr_caps)) { 820 error_setg(&local_err, QERR_QGA_COMMAND_FAILED, 821 "failed to determine guest suspend capabilities"); 822 goto out; 823 } 824 825 switch (mode) { 826 case GUEST_SUSPEND_MODE_DISK: 827 if (!sys_pwr_caps.SystemS4) { 828 error_setg(&local_err, QERR_QGA_COMMAND_FAILED, 829 "suspend-to-disk not supported by OS"); 830 } 831 break; 832 case GUEST_SUSPEND_MODE_RAM: 833 if (!sys_pwr_caps.SystemS3) { 834 error_setg(&local_err, QERR_QGA_COMMAND_FAILED, 835 "suspend-to-ram not supported by OS"); 836 } 837 break; 838 default: 839 error_setg(&local_err, QERR_INVALID_PARAMETER_VALUE, "mode", 840 "GuestSuspendMode"); 841 } 842 843 out: 844 if (local_err) { 845 error_propagate(errp, local_err); 846 } 847 } 848 849 static DWORD WINAPI do_suspend(LPVOID opaque) 850 { 851 GuestSuspendMode *mode = opaque; 852 DWORD ret = 0; 853 854 if (!SetSuspendState(*mode == GUEST_SUSPEND_MODE_DISK, TRUE, TRUE)) { 855 slog("failed to suspend guest, %lu", GetLastError()); 856 ret = -1; 857 } 858 g_free(mode); 859 return ret; 860 } 861 862 void qmp_guest_suspend_disk(Error **errp) 863 { 864 Error *local_err = NULL; 865 GuestSuspendMode *mode = g_new(GuestSuspendMode, 1); 866 867 *mode = GUEST_SUSPEND_MODE_DISK; 868 check_suspend_mode(*mode, &local_err); 869 acquire_privilege(SE_SHUTDOWN_NAME, &local_err); 870 execute_async(do_suspend, mode, &local_err); 871 872 if (local_err) { 873 error_propagate(errp, local_err); 874 g_free(mode); 875 } 876 } 877 878 void qmp_guest_suspend_ram(Error **errp) 879 { 880 Error *local_err = NULL; 881 GuestSuspendMode *mode = g_new(GuestSuspendMode, 1); 882 883 *mode = GUEST_SUSPEND_MODE_RAM; 884 check_suspend_mode(*mode, &local_err); 885 acquire_privilege(SE_SHUTDOWN_NAME, &local_err); 886 execute_async(do_suspend, mode, &local_err); 887 888 if (local_err) { 889 error_propagate(errp, local_err); 890 g_free(mode); 891 } 892 } 893 894 void qmp_guest_suspend_hybrid(Error **errp) 895 { 896 error_setg(errp, QERR_UNSUPPORTED); 897 } 898 899 static IP_ADAPTER_ADDRESSES *guest_get_adapters_addresses(Error **errp) 900 { 901 IP_ADAPTER_ADDRESSES *adptr_addrs = NULL; 902 ULONG adptr_addrs_len = 0; 903 DWORD ret; 904 905 /* Call the first time to get the adptr_addrs_len. */ 906 GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, 907 NULL, adptr_addrs, &adptr_addrs_len); 908 909 adptr_addrs = g_malloc(adptr_addrs_len); 910 ret = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, 911 NULL, adptr_addrs, &adptr_addrs_len); 912 if (ret != ERROR_SUCCESS) { 913 error_setg_win32(errp, ret, "failed to get adapters addresses"); 914 g_free(adptr_addrs); 915 adptr_addrs = NULL; 916 } 917 return adptr_addrs; 918 } 919 920 static char *guest_wctomb_dup(WCHAR *wstr) 921 { 922 char *str; 923 size_t i; 924 925 i = wcslen(wstr) + 1; 926 str = g_malloc(i); 927 WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, 928 wstr, -1, str, i, NULL, NULL); 929 return str; 930 } 931 932 static char *guest_addr_to_str(IP_ADAPTER_UNICAST_ADDRESS *ip_addr, 933 Error **errp) 934 { 935 char addr_str[INET6_ADDRSTRLEN + INET_ADDRSTRLEN]; 936 DWORD len; 937 int ret; 938 939 if (ip_addr->Address.lpSockaddr->sa_family == AF_INET || 940 ip_addr->Address.lpSockaddr->sa_family == AF_INET6) { 941 len = sizeof(addr_str); 942 ret = WSAAddressToString(ip_addr->Address.lpSockaddr, 943 ip_addr->Address.iSockaddrLength, 944 NULL, 945 addr_str, 946 &len); 947 if (ret != 0) { 948 error_setg_win32(errp, WSAGetLastError(), 949 "failed address presentation form conversion"); 950 return NULL; 951 } 952 return g_strdup(addr_str); 953 } 954 return NULL; 955 } 956 957 #if (_WIN32_WINNT >= 0x0600) 958 static int64_t guest_ip_prefix(IP_ADAPTER_UNICAST_ADDRESS *ip_addr) 959 { 960 /* For Windows Vista/2008 and newer, use the OnLinkPrefixLength 961 * field to obtain the prefix. 962 */ 963 return ip_addr->OnLinkPrefixLength; 964 } 965 #else 966 /* When using the Windows XP and 2003 build environment, do the best we can to 967 * figure out the prefix. 968 */ 969 static IP_ADAPTER_INFO *guest_get_adapters_info(void) 970 { 971 IP_ADAPTER_INFO *adptr_info = NULL; 972 ULONG adptr_info_len = 0; 973 DWORD ret; 974 975 /* Call the first time to get the adptr_info_len. */ 976 GetAdaptersInfo(adptr_info, &adptr_info_len); 977 978 adptr_info = g_malloc(adptr_info_len); 979 ret = GetAdaptersInfo(adptr_info, &adptr_info_len); 980 if (ret != ERROR_SUCCESS) { 981 g_free(adptr_info); 982 adptr_info = NULL; 983 } 984 return adptr_info; 985 } 986 987 static int64_t guest_ip_prefix(IP_ADAPTER_UNICAST_ADDRESS *ip_addr) 988 { 989 int64_t prefix = -1; /* Use for AF_INET6 and unknown/undetermined values. */ 990 IP_ADAPTER_INFO *adptr_info, *info; 991 IP_ADDR_STRING *ip; 992 struct in_addr *p; 993 994 if (ip_addr->Address.lpSockaddr->sa_family != AF_INET) { 995 return prefix; 996 } 997 adptr_info = guest_get_adapters_info(); 998 if (adptr_info == NULL) { 999 return prefix; 1000 } 1001 1002 /* Match up the passed in ip_addr with one found in adaptr_info. 1003 * The matching one in adptr_info will have the netmask. 1004 */ 1005 p = &((struct sockaddr_in *)ip_addr->Address.lpSockaddr)->sin_addr; 1006 for (info = adptr_info; info; info = info->Next) { 1007 for (ip = &info->IpAddressList; ip; ip = ip->Next) { 1008 if (p->S_un.S_addr == inet_addr(ip->IpAddress.String)) { 1009 prefix = ctpop32(inet_addr(ip->IpMask.String)); 1010 goto out; 1011 } 1012 } 1013 } 1014 out: 1015 g_free(adptr_info); 1016 return prefix; 1017 } 1018 #endif 1019 1020 GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp) 1021 { 1022 IP_ADAPTER_ADDRESSES *adptr_addrs, *addr; 1023 IP_ADAPTER_UNICAST_ADDRESS *ip_addr = NULL; 1024 GuestNetworkInterfaceList *head = NULL, *cur_item = NULL; 1025 GuestIpAddressList *head_addr, *cur_addr; 1026 GuestNetworkInterfaceList *info; 1027 GuestIpAddressList *address_item = NULL; 1028 unsigned char *mac_addr; 1029 char *addr_str; 1030 WORD wsa_version; 1031 WSADATA wsa_data; 1032 int ret; 1033 1034 adptr_addrs = guest_get_adapters_addresses(errp); 1035 if (adptr_addrs == NULL) { 1036 return NULL; 1037 } 1038 1039 /* Make WSA APIs available. */ 1040 wsa_version = MAKEWORD(2, 2); 1041 ret = WSAStartup(wsa_version, &wsa_data); 1042 if (ret != 0) { 1043 error_setg_win32(errp, ret, "failed socket startup"); 1044 goto out; 1045 } 1046 1047 for (addr = adptr_addrs; addr; addr = addr->Next) { 1048 info = g_malloc0(sizeof(*info)); 1049 1050 if (cur_item == NULL) { 1051 head = cur_item = info; 1052 } else { 1053 cur_item->next = info; 1054 cur_item = info; 1055 } 1056 1057 info->value = g_malloc0(sizeof(*info->value)); 1058 info->value->name = guest_wctomb_dup(addr->FriendlyName); 1059 1060 if (addr->PhysicalAddressLength != 0) { 1061 mac_addr = addr->PhysicalAddress; 1062 1063 info->value->hardware_address = 1064 g_strdup_printf("%02x:%02x:%02x:%02x:%02x:%02x", 1065 (int) mac_addr[0], (int) mac_addr[1], 1066 (int) mac_addr[2], (int) mac_addr[3], 1067 (int) mac_addr[4], (int) mac_addr[5]); 1068 1069 info->value->has_hardware_address = true; 1070 } 1071 1072 head_addr = NULL; 1073 cur_addr = NULL; 1074 for (ip_addr = addr->FirstUnicastAddress; 1075 ip_addr; 1076 ip_addr = ip_addr->Next) { 1077 addr_str = guest_addr_to_str(ip_addr, errp); 1078 if (addr_str == NULL) { 1079 continue; 1080 } 1081 1082 address_item = g_malloc0(sizeof(*address_item)); 1083 1084 if (!cur_addr) { 1085 head_addr = cur_addr = address_item; 1086 } else { 1087 cur_addr->next = address_item; 1088 cur_addr = address_item; 1089 } 1090 1091 address_item->value = g_malloc0(sizeof(*address_item->value)); 1092 address_item->value->ip_address = addr_str; 1093 address_item->value->prefix = guest_ip_prefix(ip_addr); 1094 if (ip_addr->Address.lpSockaddr->sa_family == AF_INET) { 1095 address_item->value->ip_address_type = 1096 GUEST_IP_ADDRESS_TYPE_IPV4; 1097 } else if (ip_addr->Address.lpSockaddr->sa_family == AF_INET6) { 1098 address_item->value->ip_address_type = 1099 GUEST_IP_ADDRESS_TYPE_IPV6; 1100 } 1101 } 1102 if (head_addr) { 1103 info->value->has_ip_addresses = true; 1104 info->value->ip_addresses = head_addr; 1105 } 1106 } 1107 WSACleanup(); 1108 out: 1109 g_free(adptr_addrs); 1110 return head; 1111 } 1112 1113 int64_t qmp_guest_get_time(Error **errp) 1114 { 1115 SYSTEMTIME ts = {0}; 1116 int64_t time_ns; 1117 FILETIME tf; 1118 1119 GetSystemTime(&ts); 1120 if (ts.wYear < 1601 || ts.wYear > 30827) { 1121 error_setg(errp, "Failed to get time"); 1122 return -1; 1123 } 1124 1125 if (!SystemTimeToFileTime(&ts, &tf)) { 1126 error_setg(errp, "Failed to convert system time: %d", (int)GetLastError()); 1127 return -1; 1128 } 1129 1130 time_ns = ((((int64_t)tf.dwHighDateTime << 32) | tf.dwLowDateTime) 1131 - W32_FT_OFFSET) * 100; 1132 1133 return time_ns; 1134 } 1135 1136 void qmp_guest_set_time(bool has_time, int64_t time_ns, Error **errp) 1137 { 1138 Error *local_err = NULL; 1139 SYSTEMTIME ts; 1140 FILETIME tf; 1141 LONGLONG time; 1142 1143 if (!has_time) { 1144 /* Unfortunately, Windows libraries don't provide an easy way to access 1145 * RTC yet: 1146 * 1147 * https://msdn.microsoft.com/en-us/library/aa908981.aspx 1148 */ 1149 error_setg(errp, "Time argument is required on this platform"); 1150 return; 1151 } 1152 1153 /* Validate time passed by user. */ 1154 if (time_ns < 0 || time_ns / 100 > INT64_MAX - W32_FT_OFFSET) { 1155 error_setg(errp, "Time %" PRId64 "is invalid", time_ns); 1156 return; 1157 } 1158 1159 time = time_ns / 100 + W32_FT_OFFSET; 1160 1161 tf.dwLowDateTime = (DWORD) time; 1162 tf.dwHighDateTime = (DWORD) (time >> 32); 1163 1164 if (!FileTimeToSystemTime(&tf, &ts)) { 1165 error_setg(errp, "Failed to convert system time %d", 1166 (int)GetLastError()); 1167 return; 1168 } 1169 1170 acquire_privilege(SE_SYSTEMTIME_NAME, &local_err); 1171 if (local_err) { 1172 error_propagate(errp, local_err); 1173 return; 1174 } 1175 1176 if (!SetSystemTime(&ts)) { 1177 error_setg(errp, "Failed to set time to guest: %d", (int)GetLastError()); 1178 return; 1179 } 1180 } 1181 1182 GuestLogicalProcessorList *qmp_guest_get_vcpus(Error **errp) 1183 { 1184 error_setg(errp, QERR_UNSUPPORTED); 1185 return NULL; 1186 } 1187 1188 int64_t qmp_guest_set_vcpus(GuestLogicalProcessorList *vcpus, Error **errp) 1189 { 1190 error_setg(errp, QERR_UNSUPPORTED); 1191 return -1; 1192 } 1193 1194 static gchar * 1195 get_net_error_message(gint error) 1196 { 1197 HMODULE module = NULL; 1198 gchar *retval = NULL; 1199 wchar_t *msg = NULL; 1200 int flags, nchars; 1201 1202 flags = FORMAT_MESSAGE_ALLOCATE_BUFFER 1203 |FORMAT_MESSAGE_IGNORE_INSERTS 1204 |FORMAT_MESSAGE_FROM_SYSTEM; 1205 1206 if (error >= NERR_BASE && error <= MAX_NERR) { 1207 module = LoadLibraryExW(L"netmsg.dll", NULL, LOAD_LIBRARY_AS_DATAFILE); 1208 1209 if (module != NULL) { 1210 flags |= FORMAT_MESSAGE_FROM_HMODULE; 1211 } 1212 } 1213 1214 FormatMessageW(flags, module, error, 0, (LPWSTR)&msg, 0, NULL); 1215 1216 if (msg != NULL) { 1217 nchars = wcslen(msg); 1218 1219 if (nchars > 2 && msg[nchars-1] == '\n' && msg[nchars-2] == '\r') { 1220 msg[nchars-2] = '\0'; 1221 } 1222 1223 retval = g_utf16_to_utf8(msg, -1, NULL, NULL, NULL); 1224 1225 LocalFree(msg); 1226 } 1227 1228 if (module != NULL) { 1229 FreeLibrary(module); 1230 } 1231 1232 return retval; 1233 } 1234 1235 void qmp_guest_set_user_password(const char *username, 1236 const char *password, 1237 bool crypted, 1238 Error **errp) 1239 { 1240 NET_API_STATUS nas; 1241 char *rawpasswddata = NULL; 1242 size_t rawpasswdlen; 1243 wchar_t *user, *wpass; 1244 USER_INFO_1003 pi1003 = { 0, }; 1245 1246 if (crypted) { 1247 error_setg(errp, QERR_UNSUPPORTED); 1248 return; 1249 } 1250 1251 rawpasswddata = (char *)g_base64_decode(password, &rawpasswdlen); 1252 rawpasswddata = g_renew(char, rawpasswddata, rawpasswdlen + 1); 1253 rawpasswddata[rawpasswdlen] = '\0'; 1254 1255 user = g_utf8_to_utf16(username, -1, NULL, NULL, NULL); 1256 wpass = g_utf8_to_utf16(rawpasswddata, -1, NULL, NULL, NULL); 1257 1258 pi1003.usri1003_password = wpass; 1259 nas = NetUserSetInfo(NULL, user, 1260 1003, (LPBYTE)&pi1003, 1261 NULL); 1262 1263 if (nas != NERR_Success) { 1264 gchar *msg = get_net_error_message(nas); 1265 error_setg(errp, "failed to set password: %s", msg); 1266 g_free(msg); 1267 } 1268 1269 g_free(user); 1270 g_free(wpass); 1271 g_free(rawpasswddata); 1272 } 1273 1274 GuestMemoryBlockList *qmp_guest_get_memory_blocks(Error **errp) 1275 { 1276 error_setg(errp, QERR_UNSUPPORTED); 1277 return NULL; 1278 } 1279 1280 GuestMemoryBlockResponseList * 1281 qmp_guest_set_memory_blocks(GuestMemoryBlockList *mem_blks, Error **errp) 1282 { 1283 error_setg(errp, QERR_UNSUPPORTED); 1284 return NULL; 1285 } 1286 1287 GuestMemoryBlockInfo *qmp_guest_get_memory_block_info(Error **errp) 1288 { 1289 error_setg(errp, QERR_UNSUPPORTED); 1290 return NULL; 1291 } 1292 1293 /* add unsupported commands to the blacklist */ 1294 GList *ga_command_blacklist_init(GList *blacklist) 1295 { 1296 const char *list_unsupported[] = { 1297 "guest-suspend-hybrid", 1298 "guest-get-vcpus", "guest-set-vcpus", 1299 "guest-get-memory-blocks", "guest-set-memory-blocks", 1300 "guest-get-memory-block-size", 1301 "guest-fsfreeze-freeze-list", 1302 "guest-fstrim", NULL}; 1303 char **p = (char **)list_unsupported; 1304 1305 while (*p) { 1306 blacklist = g_list_append(blacklist, g_strdup(*p++)); 1307 } 1308 1309 if (!vss_init(true)) { 1310 g_debug("vss_init failed, vss commands are going to be disabled"); 1311 const char *list[] = { 1312 "guest-get-fsinfo", "guest-fsfreeze-status", 1313 "guest-fsfreeze-freeze", "guest-fsfreeze-thaw", NULL}; 1314 p = (char **)list; 1315 1316 while (*p) { 1317 blacklist = g_list_append(blacklist, g_strdup(*p++)); 1318 } 1319 } 1320 1321 return blacklist; 1322 } 1323 1324 /* register init/cleanup routines for stateful command groups */ 1325 void ga_command_state_init(GAState *s, GACommandState *cs) 1326 { 1327 if (!vss_initialized()) { 1328 ga_command_state_add(cs, NULL, guest_fsfreeze_cleanup); 1329 } 1330 } 1331