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