Commit b39297ae authored by Tomoki Sekiyama's avatar Tomoki Sekiyama Committed by Michael Roth

qemu-ga: Add Windows VSS provider and requester as DLL

Adds VSS provider and requester as a qga-vss.dll, which is loaded by
Windows VSS service as well as by qemu-ga.

"provider.cpp" implements a basic stub of a software VSS provider.
Currently, this module only relays a frozen event from VSS service to the
agent, and thaw event from the agent to VSS service, to block VSS process
to keep the system frozen while snapshots are taken at the host.

To register the provider to the guest system as COM+ application, the type
library (.tlb) for qga-vss.dll is required. To build it from COM IDL (.idl),
VisualC++, MIDL and stdole2.tlb in Windows SDK are required. This patch also
adds pre-compiled .tlb file in the repository in order to enable
cross-compile qemu-ga.exe for Windows with VSS support.

"requester.cpp" provides the VSS requester to kick the VSS snapshot process.
Qemu-ga.exe works without the DLL, although fsfreeze features are disabled.

These functions are only supported in Windows 2003 or later. In older
systems, fsfreeze features are disabled.

In several versions of Windows which don't support attribute
VSS_VOLSNAP_ATTR_NO_AUTORECOVERY, DoSnapshotSet fails with error
VSS_E_OBJECT_NOT_FOUND. In this patch, we just ignore this error.
To solve this fundamentally, we need a framework to handle mount writable
snapshot on guests, which is required by VSS auto-recovery feature
(cleanup phase after a snapshot is taken).
Signed-off-by: 's avatarTomoki Sekiyama <tomoki.sekiyama@hds.com>
Signed-off-by: 's avatarMichael Roth <mdroth@linux.vnet.ibm.com>
parent 20840d4c
......@@ -235,7 +235,7 @@ clean:
rm -f qemu-options.def
find . -name '*.[oda]' -type f -exec rm -f {} +
find . -name '*.l[oa]' -type f -exec rm -f {} +
rm -f $(TOOLS) $(HELPERS-y) qemu-ga TAGS cscope.* *.pod *~ */*~
rm -f $(filter-out %.tlb,$(TOOLS)) $(HELPERS-y) qemu-ga TAGS cscope.* *.pod *~ */*~
rm -Rf .libs
rm -f qemu-img-cmds.h
@# May not be present in GENERATED_HEADERS
......
......@@ -109,6 +109,7 @@ version-lobj-$(CONFIG_WIN32) += $(BUILD_DIR)/version.lo
# FIXME: a few definitions from qapi-types.o/qapi-visit.o are needed
# by libqemuutil.a. These should be moved to a separate .json schema.
qga-obj-y = qga/ qapi-types.o qapi-visit.o
qga-vss-dll-obj-y = qga/
vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
......@@ -120,6 +121,7 @@ nested-vars += \
stub-obj-y \
util-obj-y \
qga-obj-y \
qga-vss-dll-obj-y \
block-obj-y \
common-obj-y
dummy := $(call unnest-vars)
......@@ -3568,8 +3568,11 @@ if test "$softmmu" = yes ; then
fi
fi
if [ "$guest_agent" != "no" ]; then
if [ "$linux" = "yes" -o "$bsd" = "yes" -o "$solaris" = "yes" ] ; then
if [ "$linux" = "yes" -o "$bsd" = "yes" -o "$solaris" = "yes" -o "$mingw32" = "yes" ] ; then
tools="qemu-ga\$(EXESUF) $tools"
if [ "$mingw32" = "yes" -a "$guest_agent_with_vss" = "yes" ]; then
tools="qga/vss-win32/qga-vss.dll qga/vss-win32/qga-vss.tlb $tools"
fi
guest_agent=yes
elif [ "$guest_agent" != yes ]; then
guest_agent=no
......
......@@ -3,3 +3,5 @@ qga-obj-$(CONFIG_POSIX) += commands-posix.o channel-posix.o
qga-obj-$(CONFIG_WIN32) += commands-win32.o channel-win32.o service-win32.o
qga-obj-y += qapi-generated/qga-qapi-types.o qapi-generated/qga-qapi-visit.o
qga-obj-y += qapi-generated/qga-qmp-marshal.o
qga-vss-dll-obj-$(CONFIG_QGA_VSS) += vss-win32/
# rules to build qga-vss.dll
qga-vss-dll-obj-y += requester.o provider.o install.o
obj-qga-vss-dll-obj-y = $(addprefix $(obj)/, $(qga-vss-dll-obj-y))
$(obj-qga-vss-dll-obj-y): QEMU_CXXFLAGS = $(filter-out -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Wold-style-declaration -Wold-style-definition -Wredundant-decls -fstack-protector-all, $(QEMU_CFLAGS)) -Wno-unknown-pragmas -Wno-delete-non-virtual-dtor
$(obj)/qga-vss.dll: LDFLAGS = -shared -Wl,--add-stdcall-alias,--enable-stdcall-fixup -lole32 -loleaut32 -lshlwapi -luuid -static
$(obj)/qga-vss.dll: $(obj-qga-vss-dll-obj-y) $(SRC_PATH)/$(obj)/qga-vss.def
$(call quiet-command,$(CXX) -o $@ $(qga-vss-dll-obj-y) $(SRC_PATH)/qga/vss-win32/qga-vss.def $(CXXFLAGS) $(LDFLAGS)," LINK $(TARGET_DIR)$@")
# rules to build qga-provider.tlb
# Currently, only native build is supported because building .tlb
# (TypeLibrary) from .idl requires WindowsSDK and MIDL (and cl.exe in VC++).
MIDL=$(WIN_SDK)/Bin/midl
$(obj)/qga-vss.tlb: $(SRC_PATH)/$(obj)/qga-vss.idl
ifeq ($(WIN_SDK),"")
$(call quiet-command,cp $(dir $<)qga-vss.tlb $@, " COPY $(TARGET_DIR)$@")
else
$(call quiet-command,$(MIDL) -tlb $@ -I $(WIN_SDK)/Include $<," MIDL $(TARGET_DIR)$@")
endif
This diff is collapsed.
This diff is collapsed.
LIBRARY "QGA-PROVIDER.DLL"
EXPORTS
COMRegister PRIVATE
COMUnregister PRIVATE
DllCanUnloadNow PRIVATE
DllGetClassObject PRIVATE
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE
requester_init PRIVATE
requester_deinit PRIVATE
requester_freeze PRIVATE
requester_thaw PRIVATE
import "oaidl.idl";
import "ocidl.idl";
[
uuid(103B8142-6CE5-48A7-BDE1-794D3192FCF1),
version(1.0),
helpstring("QGAVSSProvider Type Library")
]
library QGAVSSHWProviderLib
{
importlib("stdole2.tlb");
[
uuid(6E6A3492-8D4D-440C-9619-5E5D0CC31CA8),
helpstring("QGAVSSProvider Class")
]
coclass QGAVSSHWProvider
{
[default] interface IUnknown;
};
};
This diff is collapsed.
/*
* 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 VSS_WIN32_REQUESTER_H
#define VSS_WIN32_REQUESTER_H
#include "qemu/compiler.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Callback to set Error; used to avoid linking glib to the DLL */
typedef void (*ErrorSetFunc)(void **errp, int win32_err, int err_class,
const char *fmt, ...) GCC_FMT_ATTR(4, 5);
typedef struct ErrorSet {
ErrorSetFunc error_set;
void **errp;
int err_class;
} ErrorSet;
STDAPI requester_init(void);
STDAPI requester_deinit(void);
typedef void (*QGAVSSRequesterFunc)(int *, ErrorSet *);
void requester_freeze(int *num_vols, ErrorSet *errset);
void requester_thaw(int *num_vols, ErrorSet *errset);
#ifdef __cplusplus
}
#endif
#endif
/*
* QEMU Guest Agent win32 VSS common 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 VSS_WIN32_H
#define VSS_WIN32_H
#define __MIDL_user_allocate_free_DEFINED__
#include "config-host.h"
#include <windows.h>
#include <shlwapi.h>
/* Reduce warnings to include vss.h */
/* Ignore annotations for MS IDE */
#define __in IN
#define __out OUT
#define __RPC_unique_pointer
#define __RPC_string
#define __RPC__deref_inout_opt
#define __RPC__out
#ifndef __RPC__out_ecount_part
#define __RPC__out_ecount_part(x, y)
#endif
#define _declspec(x)
#undef uuid
#define uuid(x)
/* Undef some duplicated error codes redefined in vss.h */
#undef VSS_E_BAD_STATE
#undef VSS_E_PROVIDER_NOT_REGISTERED
#undef VSS_E_PROVIDER_VETO
#undef VSS_E_OBJECT_NOT_FOUND
#undef VSS_E_VOLUME_NOT_SUPPORTED
#undef VSS_E_VOLUME_NOT_SUPPORTED_BY_PROVIDER
#undef VSS_E_OBJECT_ALREADY_EXISTS
#undef VSS_E_UNEXPECTED_PROVIDER_ERROR
#undef VSS_E_INVALID_XML_DOCUMENT
#undef VSS_E_MAXIMUM_NUMBER_OF_VOLUMES_REACHED
#undef VSS_E_MAXIMUM_NUMBER_OF_SNAPSHOTS_REACHED
/*
* VSS headers must be installed from Microsoft VSS SDK 7.2 available at:
* http://www.microsoft.com/en-us/download/details.aspx?id=23490
*/
#include "inc/win2003/vss.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,
{0x8d, 0x5c, 0x8f, 0xfc, 0x16, 0x3f, 0x24, 0xca} };
const CLSID CLSID_QGAVSSProvider = { 0x6e6a3492, 0x8d4d, 0x440c,
{0x96, 0x19, 0x5e, 0x5d, 0x0c, 0xc3, 0x1c, 0xa8} };
const TCHAR g_szClsid[] = TEXT("{6E6A3492-8D4D-440C-9619-5E5D0CC31CA8}");
const TCHAR g_szProgid[] = TEXT("QGAVSSProvider");
/* Enums undefined in VSS SDK 7.2 but defined in newer Windows SDK */
enum __VSS_VOLUME_SNAPSHOT_ATTRIBUTES {
VSS_VOLSNAP_ATTR_NO_AUTORECOVERY = 0x00000002,
VSS_VOLSNAP_ATTR_TXF_RECOVERY = 0x02000000
};
/* COM pointer utility; call ->Release() when it goes out of scope */
template <class T>
class COMPointer {
COMPointer(const COMPointer<T> &p) { } /* no copy */
T *p;
public:
COMPointer &operator=(T *new_p)
{
/* Assignment of a new T* (or NULL) causes release of previous p */
if (p && p != new_p) {
p->Release();
}
p = new_p;
return *this;
}
/* Replace by assignment to the pointer of p */
T **replace(void)
{
*this = NULL;
return &p;
}
/* Make COMPointer be used like T* */
operator T*() { return p; }
T *operator->(void) { return p; }
T &operator*(void) { return *p; }
operator bool() { return !!p; }
COMPointer(T *p = NULL) : p(p) { }
~COMPointer() { *this = NULL; } /* Automatic release */
};
/*
* COM initializer; this should declared before COMPointer to uninitialize COM
* after releasing COM objects.
*/
class COMInitializer {
public:
COMInitializer() { CoInitialize(NULL); }
~COMInitializer() { CoUninitialize(); }
};
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment