mirror of https://github.com/xemu-project/xemu.git
qemu-ga patch queue
* new commands: guest-get-timezone, guest-get-users, guest-get-host-name * fix hang on w32 when stopping qemu-ga service while fs frozen * fix missing setting of can-offline in guest-get-vcpus * make qemu-ga VSS w32 service on-demand rather than on-startup * fix unecessary errors to EventLog on w32 * improvements to fsfreeze documentation v2: * document 'zone' field of guest-get-timezone as informational-only (Daniel, Eric) * fix build error for glib < 2.32 (Peter) -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJZAYUOAAoJEDNTyc7xCLWEILEH/iyom0A3PQ/OnAX51ep+J3EK 2k8hU207bynbASv3rVo+RZORQAJ3LncU+ZnS27iRhAZI3MUjMM0YzLROfBqO5lSl aMWjX5mDcEsJgiHWkmN6t01tUyxayShn228xP8VsTKNEVHq+xwC0QSHv8fDMCPmc qD51GVC53DO2HSpDFMBFOI8uVFxMIuaB/yBCpOQKtTuW+2HDmJm8797ypvIqhrmN 0PXldJaRcsPbApwv6K/9qa3cESb1IKRLAoerUjhtXa3uaHXth/n8h3VNaFuTtO1X aQygV/6SlowTZwdiJi3Jpv7q3OL+OpK9BrUbMfg3ag49BmsZfkrq5T/sn5w5JR4= =hhMj -----END PGP SIGNATURE----- Merge remote-tracking branch 'mdroth/tags/qga-pull-2017-04-25-v2-tag' into staging qemu-ga patch queue * new commands: guest-get-timezone, guest-get-users, guest-get-host-name * fix hang on w32 when stopping qemu-ga service while fs frozen * fix missing setting of can-offline in guest-get-vcpus * make qemu-ga VSS w32 service on-demand rather than on-startup * fix unecessary errors to EventLog on w32 * improvements to fsfreeze documentation v2: * document 'zone' field of guest-get-timezone as informational-only (Daniel, Eric) * fix build error for glib < 2.32 (Peter) # gpg: Signature made Thu 27 Apr 2017 06:43:42 AM BST # gpg: using RSA key 0x3353C9CEF108B584 # gpg: Good signature from "Michael Roth <flukshun@gmail.com>" # gpg: aka "Michael Roth <mdroth@utexas.edu>" # gpg: aka "Michael Roth <mdroth@linux.vnet.ibm.com>" # Primary key fingerprint: CEAC C9E1 5534 EBAB B82D 3FA0 3353 C9CE F108 B584 * mdroth/tags/qga-pull-2017-04-25-v2-tag: qga: Add `guest-get-timezone` command qga: Add 'guest-get-users' command qga: improve fsfreeze documentations qga: Add 'guest-get-host-name' command qga-win: Fix Event Viewer errors caused by qemu-ga qga-win: Fix a bug where qemu-ga service is stuck during stop operation qga-win: Enable 'can-offline' field in 'guest-get-vcpus' reply qemu-ga: Make QGA VSS provider service run only when needed Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
commit
7ad691ec98
|
@ -743,7 +743,7 @@ if test "$mingw32" = "yes" ; then
|
|||
sysconfdir="\${prefix}"
|
||||
local_statedir=
|
||||
confsuffix=""
|
||||
libs_qga="-lws2_32 -lwinmm -lpowrprof -liphlpapi -lnetapi32 $libs_qga"
|
||||
libs_qga="-lws2_32 -lwinmm -lpowrprof -lwtsapi32 -liphlpapi -lnetapi32 $libs_qga"
|
||||
fi
|
||||
|
||||
werror=""
|
||||
|
|
|
@ -217,6 +217,12 @@ static inline void g_hash_table_add(GHashTable *hash_table, gpointer key)
|
|||
{
|
||||
g_hash_table_replace(hash_table, key, key);
|
||||
}
|
||||
|
||||
static inline gboolean g_hash_table_contains(GHashTable *hash_table,
|
||||
gpointer key)
|
||||
{
|
||||
return g_hash_table_lookup_extended(hash_table, key, NULL, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef g_assert_true
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <sys/ioctl.h>
|
||||
#include <sys/wait.h>
|
||||
#include <dirent.h>
|
||||
#include <utmpx.h>
|
||||
#include "qga/guest-agent-core.h"
|
||||
#include "qga-qmp-commands.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
|
@ -2517,3 +2518,62 @@ void ga_command_state_init(GAState *s, GACommandState *cs)
|
|||
ga_command_state_add(cs, NULL, guest_fsfreeze_cleanup);
|
||||
#endif
|
||||
}
|
||||
|
||||
#define QGA_MICRO_SECOND_TO_SECOND 1000000
|
||||
|
||||
static double ga_get_login_time(struct utmpx *user_info)
|
||||
{
|
||||
double seconds = (double)user_info->ut_tv.tv_sec;
|
||||
double useconds = (double)user_info->ut_tv.tv_usec;
|
||||
useconds /= QGA_MICRO_SECOND_TO_SECOND;
|
||||
return seconds + useconds;
|
||||
}
|
||||
|
||||
GuestUserList *qmp_guest_get_users(Error **err)
|
||||
{
|
||||
GHashTable *cache = NULL;
|
||||
GuestUserList *head = NULL, *cur_item = NULL;
|
||||
struct utmpx *user_info = NULL;
|
||||
gpointer value = NULL;
|
||||
GuestUser *user = NULL;
|
||||
GuestUserList *item = NULL;
|
||||
double login_time = 0;
|
||||
|
||||
cache = g_hash_table_new(g_str_hash, g_str_equal);
|
||||
setutxent();
|
||||
|
||||
for (;;) {
|
||||
user_info = getutxent();
|
||||
if (user_info == NULL) {
|
||||
break;
|
||||
} else if (user_info->ut_type != USER_PROCESS) {
|
||||
continue;
|
||||
} else if (g_hash_table_contains(cache, user_info->ut_user)) {
|
||||
value = g_hash_table_lookup(cache, user_info->ut_user);
|
||||
user = (GuestUser *)value;
|
||||
login_time = ga_get_login_time(user_info);
|
||||
/* We're ensuring the earliest login time to be sent */
|
||||
if (login_time < user->login_time) {
|
||||
user->login_time = login_time;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
item = g_new0(GuestUserList, 1);
|
||||
item->value = g_new0(GuestUser, 1);
|
||||
item->value->user = g_strdup(user_info->ut_user);
|
||||
item->value->login_time = ga_get_login_time(user_info);
|
||||
|
||||
g_hash_table_insert(cache, item->value->user, item->value);
|
||||
|
||||
if (!cur_item) {
|
||||
head = cur_item = item;
|
||||
} else {
|
||||
cur_item->next = item;
|
||||
cur_item = item;
|
||||
}
|
||||
}
|
||||
endutxent();
|
||||
g_hash_table_destroy(cache);
|
||||
return head;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef _WIN32_WINNT
|
||||
# define _WIN32_WINNT 0x0600
|
||||
#endif
|
||||
#include "qemu/osdep.h"
|
||||
#include <wtypes.h>
|
||||
#include <powrprof.h>
|
||||
|
@ -25,6 +28,7 @@
|
|||
#include <initguid.h>
|
||||
#endif
|
||||
#include <lm.h>
|
||||
#include <wtsapi32.h>
|
||||
|
||||
#include "qga/guest-agent-core.h"
|
||||
#include "qga/vss-win32.h"
|
||||
|
@ -1344,7 +1348,7 @@ GuestLogicalProcessorList *qmp_guest_get_vcpus(Error **errp)
|
|||
vcpu = g_malloc0(sizeof *vcpu);
|
||||
vcpu->logical_id = current++;
|
||||
vcpu->online = true;
|
||||
vcpu->has_can_offline = false;
|
||||
vcpu->has_can_offline = true;
|
||||
|
||||
entry = g_malloc0(sizeof *entry);
|
||||
entry->value = vcpu;
|
||||
|
@ -1536,3 +1540,102 @@ void ga_command_state_init(GAState *s, GACommandState *cs)
|
|||
ga_command_state_add(cs, NULL, guest_fsfreeze_cleanup);
|
||||
}
|
||||
}
|
||||
|
||||
/* MINGW is missing two fields: IncomingFrames & OutgoingFrames */
|
||||
typedef struct _GA_WTSINFOA {
|
||||
WTS_CONNECTSTATE_CLASS State;
|
||||
DWORD SessionId;
|
||||
DWORD IncomingBytes;
|
||||
DWORD OutgoingBytes;
|
||||
DWORD IncomingFrames;
|
||||
DWORD OutgoingFrames;
|
||||
DWORD IncomingCompressedBytes;
|
||||
DWORD OutgoingCompressedBy;
|
||||
CHAR WinStationName[WINSTATIONNAME_LENGTH];
|
||||
CHAR Domain[DOMAIN_LENGTH];
|
||||
CHAR UserName[USERNAME_LENGTH + 1];
|
||||
LARGE_INTEGER ConnectTime;
|
||||
LARGE_INTEGER DisconnectTime;
|
||||
LARGE_INTEGER LastInputTime;
|
||||
LARGE_INTEGER LogonTime;
|
||||
LARGE_INTEGER CurrentTime;
|
||||
|
||||
} GA_WTSINFOA;
|
||||
|
||||
GuestUserList *qmp_guest_get_users(Error **err)
|
||||
{
|
||||
#if (_WIN32_WINNT >= 0x0600)
|
||||
#define QGA_NANOSECONDS 10000000
|
||||
|
||||
GHashTable *cache = NULL;
|
||||
GuestUserList *head = NULL, *cur_item = NULL;
|
||||
|
||||
DWORD buffer_size = 0, count = 0, i = 0;
|
||||
GA_WTSINFOA *info = NULL;
|
||||
WTS_SESSION_INFOA *entries = NULL;
|
||||
GuestUserList *item = NULL;
|
||||
GuestUser *user = NULL;
|
||||
gpointer value = NULL;
|
||||
INT64 login = 0;
|
||||
double login_time = 0;
|
||||
|
||||
cache = g_hash_table_new(g_str_hash, g_str_equal);
|
||||
|
||||
if (WTSEnumerateSessionsA(NULL, 0, 1, &entries, &count)) {
|
||||
for (i = 0; i < count; ++i) {
|
||||
buffer_size = 0;
|
||||
info = NULL;
|
||||
if (WTSQuerySessionInformationA(
|
||||
NULL,
|
||||
entries[i].SessionId,
|
||||
WTSSessionInfo,
|
||||
(LPSTR *)&info,
|
||||
&buffer_size
|
||||
)) {
|
||||
|
||||
if (strlen(info->UserName) == 0) {
|
||||
WTSFreeMemory(info);
|
||||
continue;
|
||||
}
|
||||
|
||||
login = info->LogonTime.QuadPart;
|
||||
login -= W32_FT_OFFSET;
|
||||
login_time = ((double)login) / QGA_NANOSECONDS;
|
||||
|
||||
if (g_hash_table_contains(cache, info->UserName)) {
|
||||
value = g_hash_table_lookup(cache, info->UserName);
|
||||
user = (GuestUser *)value;
|
||||
if (user->login_time > login_time) {
|
||||
user->login_time = login_time;
|
||||
}
|
||||
} else {
|
||||
item = g_new0(GuestUserList, 1);
|
||||
item->value = g_new0(GuestUser, 1);
|
||||
|
||||
item->value->user = g_strdup(info->UserName);
|
||||
item->value->domain = g_strdup(info->Domain);
|
||||
item->value->has_domain = true;
|
||||
|
||||
item->value->login_time = login_time;
|
||||
|
||||
g_hash_table_add(cache, item->value->user);
|
||||
|
||||
if (!cur_item) {
|
||||
head = cur_item = item;
|
||||
} else {
|
||||
cur_item->next = item;
|
||||
cur_item = item;
|
||||
}
|
||||
}
|
||||
}
|
||||
WTSFreeMemory(info);
|
||||
}
|
||||
WTSFreeMemory(entries);
|
||||
}
|
||||
g_hash_table_destroy(cache);
|
||||
return head;
|
||||
#else
|
||||
error_setg(err, QERR_UNSUPPORTED);
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -499,3 +499,52 @@ int ga_parse_whence(GuestFileWhence *whence, Error **errp)
|
|||
error_setg(errp, "invalid whence code %"PRId64, whence->u.value);
|
||||
return -1;
|
||||
}
|
||||
|
||||
GuestHostName *qmp_guest_get_host_name(Error **err)
|
||||
{
|
||||
GuestHostName *result = NULL;
|
||||
gchar const *hostname = g_get_host_name();
|
||||
if (hostname != NULL) {
|
||||
result = g_new0(GuestHostName, 1);
|
||||
result->host_name = g_strdup(hostname);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
GuestTimezone *qmp_guest_get_timezone(Error **errp)
|
||||
{
|
||||
#if GLIB_CHECK_VERSION(2, 28, 0)
|
||||
GuestTimezone *info = NULL;
|
||||
GTimeZone *tz = NULL;
|
||||
gint64 now = 0;
|
||||
gint32 intv = 0;
|
||||
gchar const *name = NULL;
|
||||
|
||||
info = g_new0(GuestTimezone, 1);
|
||||
tz = g_time_zone_new_local();
|
||||
if (tz == NULL) {
|
||||
error_setg(errp, QERR_QGA_COMMAND_FAILED,
|
||||
"Couldn't retrieve local timezone");
|
||||
goto error;
|
||||
}
|
||||
|
||||
now = g_get_real_time() / G_USEC_PER_SEC;
|
||||
intv = g_time_zone_find_interval(tz, G_TIME_TYPE_UNIVERSAL, now);
|
||||
info->offset = g_time_zone_get_offset(tz, intv);
|
||||
name = g_time_zone_get_abbreviation(tz, intv);
|
||||
if (name != NULL) {
|
||||
info->has_zone = true;
|
||||
info->zone = g_strdup(name);
|
||||
}
|
||||
g_time_zone_unref(tz);
|
||||
|
||||
return info;
|
||||
|
||||
error:
|
||||
g_free(info);
|
||||
return NULL;
|
||||
#else
|
||||
error_setg(errp, QERR_UNSUPPORTED);
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
|
23
qga/main.c
23
qga/main.c
|
@ -131,9 +131,32 @@ static void quit_handler(int sig)
|
|||
* unless all log/pid files are on unfreezable filesystems. there's
|
||||
* also a very likely chance killing the agent before unfreezing
|
||||
* the filesystems is a mistake (or will be viewed as one later).
|
||||
* On Windows the freeze interval is limited to 10 seconds, so
|
||||
* we should quit, but first we should wait for the timeout, thaw
|
||||
* the filesystem and quit.
|
||||
*/
|
||||
if (ga_is_frozen(ga_state)) {
|
||||
#ifdef _WIN32
|
||||
int i = 0;
|
||||
Error *err = NULL;
|
||||
HANDLE hEventTimeout;
|
||||
|
||||
g_debug("Thawing filesystems before exiting");
|
||||
|
||||
hEventTimeout = OpenEvent(EVENT_ALL_ACCESS, FALSE, EVENT_NAME_TIMEOUT);
|
||||
if (hEventTimeout) {
|
||||
WaitForSingleObject(hEventTimeout, 0);
|
||||
CloseHandle(hEventTimeout);
|
||||
}
|
||||
qga_vss_fsfreeze(&i, false, &err);
|
||||
if (err) {
|
||||
g_debug("Error unfreezing filesystems prior to exiting: %s",
|
||||
error_get_pretty(err));
|
||||
error_free(err);
|
||||
}
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
g_debug("received signal num %d, quitting", sig);
|
||||
|
||||
|
|
|
@ -426,7 +426,13 @@
|
|||
##
|
||||
# @guest-fsfreeze-freeze:
|
||||
#
|
||||
# Sync and freeze all freezable, local guest filesystems
|
||||
# Sync and freeze all freezable, local guest filesystems. If this
|
||||
# command succeeded, you may call @guest-fsfreeze-thaw later to
|
||||
# unfreeze.
|
||||
#
|
||||
# Note: On Windows, the command is implemented with the help of a
|
||||
# Volume Shadow-copy Service DLL helper. The frozen state is limited
|
||||
# for up to 10 seconds by VSS.
|
||||
#
|
||||
# Returns: Number of file systems currently frozen. On error, all filesystems
|
||||
# will be thawed.
|
||||
|
@ -439,10 +445,12 @@
|
|||
##
|
||||
# @guest-fsfreeze-freeze-list:
|
||||
#
|
||||
# Sync and freeze specified guest filesystems
|
||||
# Sync and freeze specified guest filesystems.
|
||||
# See also @guest-fsfreeze-freeze.
|
||||
#
|
||||
# @mountpoints: an array of mountpoints of filesystems to be frozen.
|
||||
# If omitted, every mounted filesystem is frozen.
|
||||
# Invalid mount points are ignored.
|
||||
#
|
||||
# Returns: Number of file systems currently frozen. On error, all filesystems
|
||||
# will be thawed.
|
||||
|
@ -1042,3 +1050,79 @@
|
|||
'data': { 'path': 'str', '*arg': ['str'], '*env': ['str'],
|
||||
'*input-data': 'str', '*capture-output': 'bool' },
|
||||
'returns': 'GuestExec' }
|
||||
|
||||
|
||||
##
|
||||
# @GuestHostName:
|
||||
# @host-name: Fully qualified domain name of the guest OS
|
||||
#
|
||||
# Since: 2.10
|
||||
##
|
||||
{ 'struct': 'GuestHostName',
|
||||
'data': { 'host-name': 'str' } }
|
||||
|
||||
##
|
||||
# @guest-get-host-name:
|
||||
#
|
||||
# Return a name for the machine.
|
||||
#
|
||||
# The returned name is not necessarily a fully-qualified domain name, or even
|
||||
# present in DNS or some other name service at all. It need not even be unique
|
||||
# on your local network or site, but usually it is.
|
||||
#
|
||||
# Returns: the host name of the machine on success
|
||||
#
|
||||
# Since: 2.10
|
||||
##
|
||||
{ 'command': 'guest-get-host-name',
|
||||
'returns': 'GuestHostName' }
|
||||
|
||||
|
||||
##
|
||||
# @GuestUser:
|
||||
# @user: Username
|
||||
# @domain: Logon domain (windows only)
|
||||
# @login-time: Time of login of this user on the computer. If multiple
|
||||
# instances of the user are logged in, the earliest login time is
|
||||
# reported. The value is in fractional seconds since epoch time.
|
||||
#
|
||||
# Since: 2.10
|
||||
##
|
||||
{ 'struct': 'GuestUser',
|
||||
'data': { 'user': 'str', 'login-time': 'number', '*domain': 'str' } }
|
||||
|
||||
##
|
||||
# @guest-get-users:
|
||||
# Retrieves a list of currently active users on the VM.
|
||||
#
|
||||
# Returns: A unique list of users.
|
||||
#
|
||||
# Since: 2.10
|
||||
##
|
||||
{ 'command': 'guest-get-users',
|
||||
'returns': ['GuestUser'] }
|
||||
|
||||
##
|
||||
# @GuestTimezone:
|
||||
#
|
||||
# @zone: Timezone name. These values may differ depending on guest/OS and
|
||||
# should only be used for informational purposes.
|
||||
# @offset: Offset to UTC in seconds, negative numbers for time zones west of
|
||||
# GMT, positive numbers for east
|
||||
#
|
||||
# Since: 2.10
|
||||
##
|
||||
{ 'struct': 'GuestTimezone',
|
||||
'data': { '*zone': 'str', 'offset': 'int' } }
|
||||
|
||||
##
|
||||
# @guest-get-timezone:
|
||||
#
|
||||
# Retrieves the timezone information from the guest.
|
||||
#
|
||||
# Returns: A GuestTimezone dictionary.
|
||||
#
|
||||
# Since: 2.10
|
||||
##
|
||||
{ 'command': 'guest-get-timezone',
|
||||
'returns': 'GuestTimezone' }
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#ifndef VSS_WIN32_H
|
||||
#define VSS_WIN32_H
|
||||
|
||||
#include "qga/vss-win32/vss-handles.h"
|
||||
|
||||
bool vss_init(bool init_requester);
|
||||
void vss_deinit(bool deinit_requester);
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
#include "vss-common.h"
|
||||
#include <inc/win2003/vscoordint.h>
|
||||
#include <comadmin.h>
|
||||
#include "install.h"
|
||||
#include <wbemidl.h>
|
||||
#include <comdef.h>
|
||||
#include <comutil.h>
|
||||
|
@ -276,7 +276,7 @@ STDAPI COMRegister(void)
|
|||
|
||||
chk(pCatalog->CreateServiceForApplication(
|
||||
_bstr_t(QGA_PROVIDER_LNAME), _bstr_t(QGA_PROVIDER_LNAME),
|
||||
_bstr_t(L"SERVICE_AUTO_START"), _bstr_t(L"SERVICE_ERROR_NORMAL"),
|
||||
_bstr_t(L"SERVICE_DEMAND_START"), _bstr_t(L"SERVICE_ERROR_NORMAL"),
|
||||
_bstr_t(L""), _bstr_t(L".\\localsystem"), _bstr_t(L""), FALSE));
|
||||
chk(pCatalog->InstallComponent(_bstr_t(QGA_PROVIDER_LNAME),
|
||||
_bstr_t(dllPath), _bstr_t(tlbPath),
|
||||
|
@ -461,3 +461,27 @@ namespace _com_util
|
|||
return bstr;
|
||||
}
|
||||
}
|
||||
|
||||
/* Stop QGA VSS provider service from COM+ Application Admin Catalog */
|
||||
|
||||
STDAPI StopService(void)
|
||||
{
|
||||
HRESULT hr;
|
||||
COMInitializer initializer;
|
||||
COMPointer<IUnknown> pUnknown;
|
||||
COMPointer<ICOMAdminCatalog2> pCatalog;
|
||||
|
||||
int count = 0;
|
||||
|
||||
chk(QGAProviderFind(QGAProviderCount, (void *)&count));
|
||||
if (count) {
|
||||
chk(CoCreateInstance(CLSID_COMAdminCatalog, NULL, CLSCTX_INPROC_SERVER,
|
||||
IID_IUnknown, (void **)pUnknown.replace()));
|
||||
chk(pUnknown->QueryInterface(IID_ICOMAdminCatalog2,
|
||||
(void **)pCatalog.replace()));
|
||||
chk(pCatalog->ShutdownApplication(_bstr_t(QGA_PROVIDER_LNAME)));
|
||||
}
|
||||
|
||||
out:
|
||||
return hr;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* QEMU Guest Agent VSS requester declarations
|
||||
*
|
||||
* Copyright Hitachi Data Systems Corp. 2013
|
||||
*
|
||||
* Authors:
|
||||
* Tomoki Sekiyama <tomoki.sekiyama@hds.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef INSTALL_H
|
||||
#define INSTALL_H
|
||||
|
||||
#include <comadmin.h>
|
||||
|
||||
STDAPI StopService(void);
|
||||
|
||||
#endif
|
|
@ -377,7 +377,6 @@ STDMETHODIMP CQGAVssProvider::CommitSnapshots(VSS_ID SnapshotSetId)
|
|||
if (WaitForSingleObject(hEventThaw, VSS_TIMEOUT_MSEC) != WAIT_OBJECT_0) {
|
||||
/* Send event to qemu-ga to notify the provider is timed out */
|
||||
SetEvent(hEventTimeout);
|
||||
hr = E_ABORT;
|
||||
}
|
||||
|
||||
CloseHandle(hEventThaw);
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "qemu/osdep.h"
|
||||
#include "vss-common.h"
|
||||
#include "requester.h"
|
||||
#include "install.h"
|
||||
#include <inc/win2003/vswriter.h>
|
||||
#include <inc/win2003/vsbackup.h>
|
||||
|
||||
|
@ -501,4 +502,5 @@ void requester_thaw(int *num_vols, ErrorSet *errset)
|
|||
requester_cleanup();
|
||||
|
||||
CoUninitialize();
|
||||
StopService();
|
||||
}
|
||||
|
|
|
@ -51,21 +51,12 @@
|
|||
* http://www.microsoft.com/en-us/download/details.aspx?id=23490
|
||||
*/
|
||||
#include <inc/win2003/vss.h>
|
||||
#include "vss-handles.h"
|
||||
|
||||
/* Macros to convert char definitions to wchar */
|
||||
#define _L(a) L##a
|
||||
#define L(a) _L(a)
|
||||
|
||||
/* Constants for QGA VSS Provider */
|
||||
|
||||
#define QGA_PROVIDER_NAME "QEMU Guest Agent VSS Provider"
|
||||
#define QGA_PROVIDER_LNAME L(QGA_PROVIDER_NAME)
|
||||
#define QGA_PROVIDER_VERSION L(QEMU_VERSION)
|
||||
|
||||
#define EVENT_NAME_FROZEN "Global\\QGAVSSEvent-frozen"
|
||||
#define EVENT_NAME_THAW "Global\\QGAVSSEvent-thaw"
|
||||
#define EVENT_NAME_TIMEOUT "Global\\QGAVSSEvent-timeout"
|
||||
|
||||
const GUID g_gProviderId = { 0x3629d4ed, 0xee09, 0x4e0e,
|
||||
{0x9a, 0x5c, 0x6d, 0x8b, 0xa2, 0x87, 0x2a, 0xef} };
|
||||
const GUID g_gProviderVersion = { 0x11ef8b15, 0xcac6, 0x40d6,
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
#ifndef VSS_HANDLES
|
||||
#define VSS_HANDLES
|
||||
|
||||
/* Constants for QGA VSS Provider */
|
||||
|
||||
#define QGA_PROVIDER_NAME "QEMU Guest Agent VSS Provider"
|
||||
#define QGA_PROVIDER_LNAME L(QGA_PROVIDER_NAME)
|
||||
#define QGA_PROVIDER_VERSION L(QEMU_VERSION)
|
||||
|
||||
#define EVENT_NAME_FROZEN "Global\\QGAVSSEvent-frozen"
|
||||
#define EVENT_NAME_THAW "Global\\QGAVSSEvent-thaw"
|
||||
#define EVENT_NAME_TIMEOUT "Global\\QGAVSSEvent-timeout"
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue