qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [RFC PATCH v2 00/11] qemu-ga: fsfreeze on Windows using VSS
@ 2013-04-12 20:01 Tomoki Sekiyama
  2013-04-12 20:01 ` [Qemu-devel] [RFC PATCH v2 01/11] configure: Support configuring c++ compiler Tomoki Sekiyama
                   ` (11 more replies)
  0 siblings, 12 replies; 15+ messages in thread
From: Tomoki Sekiyama @ 2013-04-12 20:01 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, lcapitulino, vrozenfe, mdroth

Hi,

This patch series is attempts to add fsfreeze support for Windows
qemu-guest-agent.

changes from v1: 
 - Fix out-tree build by stop using recursive Makefile
 - Added script to extract VSS SDK headers on POSIX systems using msitools
   (thanks Paolo)
 - Remove some unnecessary header files

v1: http://lists.gnu.org/archive/html/qemu-devel/2013-02/msg01963.html

* Description
In Windows, VSS (Volume Shadow Copy Service) provides a facility to
quiesce filesystems and applications before disk snapshots are taken.
This patch series implements "fsfreeze" command of qemu-ga using VSS.

* How to build & run qemu-ga with VSS support

 - Download Microsoft VSS SDK from:
   http://www.microsoft.com/en-us/download/details.aspx?id=23490

 - Setup the SDK
   scripts/extract-vsssdk-headers setup.exe (on POSIX-systems)

 - Specify installed SDK directory to configure option as:
   ./configure -with-vss-sdk="path/to/VSS SDK" --cross-prefix=i686-w64-mingw32-

 - Make qemu-ga.exe

 - Install qemu-ga.exe and qga/vss-win32-provider/qga-provider.{dll,tlb} into
   the same directory in guests

 - Run `qemu-ga.exe -s install' and `net start qemu-ga' in the guests

Any feedback are appliciated.

---
Tomoki Sekiyama (11):
      configure: Support configuring c++ compiler
      Fix errors and warnings while compiling with c++ compilier
      Add a script to extract VSS SDK headers on POSIX system
      qemu-ga: Add an configure option to specify path to Windows VSS SDK
      qemu-ga: Add Windows VSS provider to quiesce applications on fsfreeze
      qemu-ga: Add Windows VSS requester to quisce applications and filesystems
      qemu-ga: call Windows VSS requester in fsfreeze command handler
      qemu-ga: install Windows VSS provider on `qemu-ga -s install'
      qemu-ga: Add VSS provider .tlb file in the repository
      QMP/qemu-ga-client: make timeout longer for guest-fsfreeze-freeze command
      QMP/qmp.py: set locale for exceptions to display non-ascii messages correctly


 .gitignore                              |    1 
 Makefile                                |    3 
 Makefile.objs                           |    2 
 QMP/qemu-ga-client                      |    4 
 QMP/qmp.py                              |    4 
 configure                               |   59 ++++
 hmp.c                                   |    2 
 hw/pci/pci.c                            |    2 
 qga/Makefile.objs                       |    7 
 qga/commands-win32.c                    |   74 ++++-
 qga/main.c                              |   41 +++
 qga/vss-win32-provider.h                |   26 ++
 qga/vss-win32-provider/Makefile.objs    |   25 ++
 qga/vss-win32-provider/install.cpp      |  494 +++++++++++++++++++++++++++++++
 qga/vss-win32-provider/provider.cpp     |  474 ++++++++++++++++++++++++++++++
 qga/vss-win32-provider/qga-provider.def |   10 +
 qga/vss-win32-provider/qga-provider.idl |   20 +
 qga/vss-win32-provider/qga-provider.tlb |  Bin
 qga/vss-win32-requester.cpp             |  393 +++++++++++++++++++++++++
 qga/vss-win32-requester.h               |   31 ++
 qga/vss-win32.h                         |   85 +++++
 rules.mak                               |    9 +
 scripts/extract-vsssdk-headers          |   25 ++
 scripts/qapi.py                         |    9 +
 24 files changed, 1785 insertions(+), 15 deletions(-)
 create mode 100644 qga/vss-win32-provider.h
 create mode 100644 qga/vss-win32-provider/Makefile.objs
 create mode 100644 qga/vss-win32-provider/install.cpp
 create mode 100644 qga/vss-win32-provider/provider.cpp
 create mode 100644 qga/vss-win32-provider/qga-provider.def
 create mode 100644 qga/vss-win32-provider/qga-provider.idl
 create mode 100644 qga/vss-win32-provider/qga-provider.tlb
 create mode 100644 qga/vss-win32-requester.cpp
 create mode 100644 qga/vss-win32-requester.h
 create mode 100644 qga/vss-win32.h
 create mode 100755 scripts/extract-vsssdk-headers

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Qemu-devel] [RFC PATCH v2 01/11] configure: Support configuring c++ compiler
  2013-04-12 20:01 [Qemu-devel] [RFC PATCH v2 00/11] qemu-ga: fsfreeze on Windows using VSS Tomoki Sekiyama
@ 2013-04-12 20:01 ` Tomoki Sekiyama
  2013-04-12 20:01 ` [Qemu-devel] [RFC PATCH v2 02/11] Fix errors and warnings while compiling with c++ compilier Tomoki Sekiyama
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Tomoki Sekiyama @ 2013-04-12 20:01 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, lcapitulino, vrozenfe, Tomoki Sekiyama, mdroth

Add configuration for c++ compiler (${corss_prefix}g++ as default) in
configure and Makefiles.

Currently, usage of c++ language is only for access to Windows VSS
using COM+ services in qemu-guest-agent for Windows.

Signed-off-by: Tomoki Sekiyama <tomoki.sekiyama@hds.com>
---
 configure |    6 ++++++
 rules.mak |    9 ++++++++-
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/configure b/configure
index 1ed939a..b74572f 100755
--- a/configure
+++ b/configure
@@ -278,6 +278,7 @@ else
   cc="${CC-${cross_prefix}gcc}"
 fi
 
+cxx="${CXX-${cross_prefix}g++}"
 ar="${AR-${cross_prefix}ar}"
 as="${AS-${cross_prefix}as}"
 cpp="${CPP-$cc -E}"
@@ -615,6 +616,8 @@ for opt do
   ;;
   --host-cc=*) host_cc="$optarg"
   ;;
+  --cxx=*) cxx="$optarg"
+  ;;
   --objcc=*) objcc="$optarg"
   ;;
   --make=*) make="$optarg"
@@ -1053,6 +1056,7 @@ echo "  --cross-prefix=PREFIX    use PREFIX for compile tools [$cross_prefix]"
 echo "  --cc=CC                  use C compiler CC [$cc]"
 echo "  --host-cc=CC             use C compiler CC [$host_cc] for code run at"
 echo "                           build time"
+echo "  --cxx=CXX                use C++ compiler CXX [$cxx]"
 echo "  --objcc=OBJCC            use Objective-C compiler OBJCC [$objcc]"
 echo "  --extra-cflags=CFLAGS    append extra C compiler flags QEMU_CFLAGS"
 echo "  --extra-ldflags=LDFLAGS  append extra linker flags LDFLAGS"
@@ -3349,6 +3353,7 @@ fi
 echo "Source path       $source_path"
 echo "C compiler        $cc"
 echo "Host C compiler   $host_cc"
+echo "C++ compiler      $cxx"
 echo "Objective-C compiler $objcc"
 echo "CFLAGS            $CFLAGS"
 echo "QEMU_CFLAGS       $QEMU_CFLAGS"
@@ -3860,6 +3865,7 @@ echo "PYTHON=$python" >> $config_host_mak
 echo "CC=$cc" >> $config_host_mak
 echo "CC_I386=$cc_i386" >> $config_host_mak
 echo "HOST_CC=$host_cc" >> $config_host_mak
+echo "CXX=$cxx" >> $config_host_mak
 echo "OBJCC=$objcc" >> $config_host_mak
 echo "AR=$ar" >> $config_host_mak
 echo "AS=$as" >> $config_host_mak
diff --git a/rules.mak b/rules.mak
index edc2552..9dfd23a 100644
--- a/rules.mak
+++ b/rules.mak
@@ -8,9 +8,13 @@ MAKEFLAGS += -rR
 %.d:
 %.h:
 %.c:
+%.cpp:
 %.m:
 %.mak:
 
+# Flags for C++ compilation
+QEMU_CXXFLAGS = -D__STDC_LIMIT_MACROS $(filter-out -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Wold-style-declaration -Wold-style-definition -Wredundant-decls, $(QEMU_CFLAGS))
+
 # Flags for dependency generation
 QEMU_DGFLAGS += -MMD -MP -MT $@ -MF $(*D)/$(*F).d
 
@@ -45,6 +49,9 @@ endif
 %.o: %.asm
 	$(call quiet-command,$(AS) $(ASFLAGS) -o $@ $<,"  AS    $(TARGET_DIR)$@")
 
+%.o: %.cpp
+	$(call quiet-command,$(CXX) $(QEMU_INCLUDES) $(QEMU_CXXFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<,"  CXX   $(TARGET_DIR)$@")
+
 %.o: %.m
 	$(call quiet-command,$(OBJCC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<,"  OBJC  $(TARGET_DIR)$@")
 
@@ -65,7 +72,7 @@ quiet-command = $(if $(V),$1,$(if $(2),@echo $2 && $1, @$1))
 cc-option = $(if $(shell $(CC) $1 $2 -S -o /dev/null -xc /dev/null \
               >/dev/null 2>&1 && echo OK), $2, $3)
 
-VPATH_SUFFIXES = %.c %.h %.S %.m %.mak %.texi %.sh
+VPATH_SUFFIXES = %.c %.h %.S %.cpp %.m %.mak %.texi %.sh
 set-vpath = $(if $1,$(foreach PATTERN,$(VPATH_SUFFIXES),$(eval vpath $(PATTERN) $1)))
 
 # find-in-path

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [RFC PATCH v2 02/11] Fix errors and warnings while compiling with c++ compilier
  2013-04-12 20:01 [Qemu-devel] [RFC PATCH v2 00/11] qemu-ga: fsfreeze on Windows using VSS Tomoki Sekiyama
  2013-04-12 20:01 ` [Qemu-devel] [RFC PATCH v2 01/11] configure: Support configuring c++ compiler Tomoki Sekiyama
@ 2013-04-12 20:01 ` Tomoki Sekiyama
  2013-04-12 20:01 ` [Qemu-devel] [RFC PATCH v2 03/11] Add a script to extract VSS SDK headers on POSIX system Tomoki Sekiyama
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Tomoki Sekiyama @ 2013-04-12 20:01 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, lcapitulino, vrozenfe, Tomoki Sekiyama, mdroth

Add C++ keywords to avoid errors in compiling with c++ compiler.
This also renames class member of PciDeviceInfo to q_class.

Signed-off-by: Tomoki Sekiyama <tomoki.sekiyama@hds.com>
---
 hmp.c           |    2 +-
 hw/pci/pci.c    |    2 +-
 scripts/qapi.py |    9 ++++++++-
 3 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/hmp.c b/hmp.c
index dbe9b90..9fa89a4 100644
--- a/hmp.c
+++ b/hmp.c
@@ -484,7 +484,7 @@ static void hmp_info_pci_device(Monitor *mon, const PciDeviceInfo *dev)
     if (dev->class_info.has_desc) {
         monitor_printf(mon, "%s", dev->class_info.desc);
     } else {
-        monitor_printf(mon, "Class %04" PRId64, dev->class_info.class);
+        monitor_printf(mon, "Class %04" PRId64, dev->class_info.q_class);
     }
 
     monitor_printf(mon, ": PCI device %04" PRIx64 ":%04" PRIx64 "\n",
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index d5257ed..a3eaf47 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -1460,7 +1460,7 @@ static PciDeviceInfo *qmp_query_pci_device(PCIDevice *dev, PCIBus *bus,
     info->function = PCI_FUNC(dev->devfn);
 
     class = pci_get_word(dev->config + PCI_CLASS_DEVICE);
-    info->class_info.class = class;
+    info->class_info.q_class = class;
     desc = get_class_desc(class);
     if (desc->desc) {
         info->class_info.has_desc = true;
diff --git a/scripts/qapi.py b/scripts/qapi.py
index afc5f32..b174acb 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -156,9 +156,16 @@ def c_var(name, protect=True):
     # GCC http://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/C-Extensions.html
     # excluding _.*
     gcc_words = set(['asm', 'typeof'])
+    # C++ ISO/IEC 14882:2003 2.11
+    cpp_words = set(['bool', 'catch', 'class', 'const_cast', 'delete',
+                     'dynamic_cast', 'explicit', 'false', 'friend', 'mutable',
+                     'namespace', 'new', 'operator', 'private', 'protected',
+                     'public', 'reinterpret_cast', 'static_cast', 'template',
+                     'this', 'throw', 'true', 'try', 'typeid', 'typename',
+                     'using', 'virtual', 'wchar_t'])
     # namespace pollution:
     polluted_words = set(['unix'])
-    if protect and (name in c89_words | c99_words | c11_words | gcc_words | polluted_words):
+    if protect and (name in c89_words | c99_words | c11_words | gcc_words | cpp_words | polluted_words):
         return "q_" + name
     return name.replace('-', '_').lstrip("*")
 

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [RFC PATCH v2 03/11] Add a script to extract VSS SDK headers on POSIX system
  2013-04-12 20:01 [Qemu-devel] [RFC PATCH v2 00/11] qemu-ga: fsfreeze on Windows using VSS Tomoki Sekiyama
  2013-04-12 20:01 ` [Qemu-devel] [RFC PATCH v2 01/11] configure: Support configuring c++ compiler Tomoki Sekiyama
  2013-04-12 20:01 ` [Qemu-devel] [RFC PATCH v2 02/11] Fix errors and warnings while compiling with c++ compilier Tomoki Sekiyama
@ 2013-04-12 20:01 ` Tomoki Sekiyama
  2013-04-12 20:01 ` [Qemu-devel] [RFC PATCH v2 04/11] qemu-ga: Add an configure option to specify path to Windows VSS SDK Tomoki Sekiyama
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Tomoki Sekiyama @ 2013-04-12 20:01 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, lcapitulino, vrozenfe, Tomoki Sekiyama, mdroth

VSS SDK(*) setup.exe is only runnable on Windows. This adds a script
to extract VSS SDK headers on POSIX-systems using msitools.

  * http://www.microsoft.com/en-us/download/details.aspx?id=23490

From: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Tomoki Sekiyama <tomoki.sekiyama@hds.com>
---
 scripts/extract-vsssdk-headers |   25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)
 create mode 100755 scripts/extract-vsssdk-headers

diff --git a/scripts/extract-vsssdk-headers b/scripts/extract-vsssdk-headers
new file mode 100755
index 0000000..5877137
--- /dev/null
+++ b/scripts/extract-vsssdk-headers
@@ -0,0 +1,25 @@
+#! /bin/bash
+
+# extract-vsssdk-headers
+# Author: Paolo Bonzini <pbonzini@redhat.com>
+
+set -e
+if test $# = 0 || ! test -f "$1"; then
+  echo 'Usage: extract-vsssdk-headers /path/to/setup.exe'
+  exit 1
+fi
+
+# Extract .MSI file in the .exe, looking for the OLE compound
+# document signature.  Extra data at the end does not matter.
+export LC_ALL=C
+MAGIC=$'\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1'
+offset=`grep -abom1 "$MAGIC" "$1" | sed -n 's/:/\n/; P' `
+(dd of=/dev/null skip=$offset bs=1 count=0; cat) < "$1" > vsssdk.msi
+
+# Now extract the files.
+tmpdir=tmp$$
+mkdir $tmpdir
+msiextract -C $tmpdir vsssdk.msi
+mv "$tmpdir/Program Files/Microsoft/VSSSDK72/inc" inc
+rm -rf $tmpdir vsssdk.msi
+exit 0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [RFC PATCH v2 04/11] qemu-ga: Add an configure option to specify path to Windows VSS SDK
  2013-04-12 20:01 [Qemu-devel] [RFC PATCH v2 00/11] qemu-ga: fsfreeze on Windows using VSS Tomoki Sekiyama
                   ` (2 preceding siblings ...)
  2013-04-12 20:01 ` [Qemu-devel] [RFC PATCH v2 03/11] Add a script to extract VSS SDK headers on POSIX system Tomoki Sekiyama
@ 2013-04-12 20:01 ` Tomoki Sekiyama
  2013-04-12 20:01 ` [Qemu-devel] [RFC PATCH v2 05/11] qemu-ga: Add Windows VSS provider to quiesce applications on fsfreeze Tomoki Sekiyama
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Tomoki Sekiyama @ 2013-04-12 20:01 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, lcapitulino, vrozenfe, Tomoki Sekiyama, mdroth

To enable VSS support in qemu-ga for Windows, header files included in
VSS SDK is required.
The VSS support is enabled when the option like below:
  ./configure --with-vss-sdk="/pass/to/VSS SDK"

VSS SDK is available from:
  http://www.microsoft.com/en-us/download/details.aspx?id=23490

To cross-compilie using mingw32 for Linux, you need to setup the SDK on
Windows environments to extract headers. You can also extract the SDK
headers using scripts/extract-vss-headers, written by Paolo Bonzini.

Signed-off-by: Tomoki Sekiyama <tomoki.sekiyama@hds.com>
---
 .gitignore |    1 +
 Makefile   |    1 +
 configure  |   48 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 50 insertions(+)

diff --git a/.gitignore b/.gitignore
index 487813a..b98e851 100644
--- a/.gitignore
+++ b/.gitignore
@@ -79,6 +79,7 @@ fsdev/virtfs-proxy-helper.pod
 *.la
 *.pc
 .libs
+.sdk
 *.swp
 *.orig
 .pc
diff --git a/Makefile b/Makefile
index 0b6e6a1..8d4506f 100644
--- a/Makefile
+++ b/Makefile
@@ -261,6 +261,7 @@ distclean: clean
 	for d in $(TARGET_DIRS); do \
 	rm -rf $$d || exit 1 ; \
         done
+	rm -Rf .sdk
 	if test -f pixman/config.log; then make -C pixman distclean; fi
 
 KEYMAPS=da     en-gb  et  fr     fr-ch  is  lt  modifiers  no  pt-br  sv \
diff --git a/configure b/configure
index b74572f..310bf9f 100755
--- a/configure
+++ b/configure
@@ -230,6 +230,8 @@ usb_redir=""
 glx=""
 zlib="yes"
 guest_agent="yes"
+guest_agent_with_vss="no"
+vss_win32_sdk=""
 want_tools="yes"
 libiscsi=""
 coroutine=""
@@ -901,6 +903,12 @@ for opt do
   ;;
   --disable-guest-agent) guest_agent="no"
   ;;
+  --with-vss-sdk) vss_win32_sdk=""
+  ;;
+  --with-vss-sdk=*) vss_win32_sdk="$optarg"
+  ;;
+  --without-vss-sdk) vss_win32_sdk="no"
+  ;;
   --enable-tools) want_tools="yes"
   ;;
   --disable-tools) want_tools="no"
@@ -1177,6 +1185,7 @@ echo "  --disable-usb-redir      disable usb network redirection support"
 echo "  --enable-usb-redir       enable usb network redirection support"
 echo "  --disable-guest-agent    disable building of the QEMU Guest Agent"
 echo "  --enable-guest-agent     enable building of the QEMU Guest Agent"
+echo "  --with-vss-sdk=SDK-path  enable Windows VSS support in QEMU Guest Agent"
 echo "  --disable-seccomp        disable seccomp support"
 echo "  --enable-seccomp         enables seccomp support"
 echo "  --with-coroutine=BACKEND coroutine backend. Supported options:"
@@ -2948,6 +2957,41 @@ if test "$usb_redir" != "no" ; then
 fi
 
 ##########################################
+# check if we have VSS SDK headers for win
+
+if test "$mingw32" = "yes" -a "$guest_agent" = "yes" -a "$vss_win32_sdk" != "no" ; then
+  case "$vss_win32_sdk" in
+    "")   vss_win32_include="-I$source_path" ;;
+    *\ *) # The SDK is installed in "Program Files" by default, but we cannot
+          # handle path with spaces. So we symlink the headers into ".sdk/vss".
+          vss_win32_include="-I$source_path/.sdk/vss"
+	  symlink "$vss_win32_sdk/inc" "$source_path/.sdk/vss/inc"
+	  ;;
+    *)    vss_win32_include="-I$vss_win32_sdk"
+  esac
+  cat > $TMPC << EOF
+#define __MIDL_user_allocate_free_DEFINED__
+#include <inc/win2003/vss.h>
+int main(void) { return VSS_CTX_BACKUP; }
+EOF
+  if compile_prog "$vss_win32_include" "" ; then
+    guest_agent_with_vss="yes"
+    QEMU_CFLAGS="$QEMU_CFLAGS $vss_win32_include"
+    libs_qga="-lole32 -loleaut32 -lshlwapi -luuid -lstdc++ -Wl,--enable-stdcall-fixup $libs_qga"
+  else
+    if test "$vss_win32_sdk" != "" ; then
+      echo "ERROR: Please download and install Microsoft VSS SDK:"
+      echo "ERROR:   http://www.microsoft.com/en-us/download/details.aspx?id=23490"
+      echo "ERROR: On POSIX-systems, you can extract the SDK headers by:"
+      echo "ERROR:   scripts/extract-vsssdk-headers setup.exe"
+      echo "ERROR: The headers are extracted in the directory \`inc'."
+      feature_not_found "VSS support"
+    fi
+    guest_agent_with_vss="no"
+  fi
+fi
+
+##########################################
 
 ##########################################
 # check if we have fdatasync
@@ -3433,6 +3477,7 @@ echo "usb net redir     $usb_redir"
 echo "GLX support       $glx"
 echo "libiscsi support  $libiscsi"
 echo "build guest agent $guest_agent"
+echo "QGA VSS support   $guest_agent_with_vss"
 echo "seccomp support   $seccomp"
 echo "coroutine backend $coroutine"
 echo "GlusterFS support $glusterfs"
@@ -3496,6 +3541,9 @@ if test "$mingw32" = "yes" ; then
   version_micro=0
   echo "CONFIG_FILEVERSION=$version_major,$version_minor,$version_subminor,$version_micro" >> $config_host_mak
   echo "CONFIG_PRODUCTVERSION=$version_major,$version_minor,$version_subminor,$version_micro" >> $config_host_mak
+  if test "$guest_agent_with_vss" = "yes" ; then
+    echo "CONFIG_QGA_VSS=y" >> $config_host_mak
+  fi
 else
   echo "CONFIG_POSIX=y" >> $config_host_mak
 fi

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [RFC PATCH v2 05/11] qemu-ga: Add Windows VSS provider to quiesce applications on fsfreeze
  2013-04-12 20:01 [Qemu-devel] [RFC PATCH v2 00/11] qemu-ga: fsfreeze on Windows using VSS Tomoki Sekiyama
                   ` (3 preceding siblings ...)
  2013-04-12 20:01 ` [Qemu-devel] [RFC PATCH v2 04/11] qemu-ga: Add an configure option to specify path to Windows VSS SDK Tomoki Sekiyama
@ 2013-04-12 20:01 ` Tomoki Sekiyama
  2013-04-12 20:01 ` [Qemu-devel] [RFC PATCH v2 06/11] qemu-ga: Add Windows VSS requester to quisce applications and filesystems Tomoki Sekiyama
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Tomoki Sekiyama @ 2013-04-12 20:01 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, lcapitulino, vrozenfe, Tomoki Sekiyama, mdroth

Implements a basic stub of software VSS provider. Currently, this modules
only provides a relay function of events between qemu-guest-agent and
Windows VSS when VSS finished filesystem freeze and when qemu snapshot
is done.

In the future, this module could be extended to support the other VSS
functions, such as query for snapshot volumes and recovery.

Signed-off-by: Tomoki Sekiyama <tomoki.sekiyama@hds.com>
---
 Makefile.objs                           |    2 
 configure                               |    5 
 qga/Makefile.objs                       |    6 
 qga/vss-win32-provider.h                |   26 ++
 qga/vss-win32-provider/Makefile.objs    |   21 +
 qga/vss-win32-provider/install.cpp      |  494 +++++++++++++++++++++++++++++++
 qga/vss-win32-provider/provider.cpp     |  474 ++++++++++++++++++++++++++++++
 qga/vss-win32-provider/qga-provider.def |   10 +
 qga/vss-win32-provider/qga-provider.idl |   20 +
 qga/vss-win32.h                         |   85 +++++
 10 files changed, 1142 insertions(+), 1 deletion(-)
 create mode 100644 qga/vss-win32-provider.h
 create mode 100644 qga/vss-win32-provider/Makefile.objs
 create mode 100644 qga/vss-win32-provider/install.cpp
 create mode 100644 qga/vss-win32-provider/provider.cpp
 create mode 100644 qga/vss-win32-provider/qga-provider.def
 create mode 100644 qga/vss-win32-provider/qga-provider.idl
 create mode 100644 qga/vss-win32.h

diff --git a/Makefile.objs b/Makefile.objs
index e568c01..15264a1 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -96,6 +96,7 @@ common-obj-y += disas/
 # 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-prv-obj-y = qga/
 
 vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
 
@@ -107,6 +108,7 @@ nested-vars += \
 	stub-obj-y \
 	util-obj-y \
 	qga-obj-y \
+	qga-prv-obj-y \
 	block-obj-y \
 	common-obj-y
 dummy := $(call unnest-vars)
diff --git a/configure b/configure
index 310bf9f..ebc4114 100755
--- a/configure
+++ b/configure
@@ -3360,9 +3360,12 @@ if test "$softmmu" = yes ; then
       virtfs=no
     fi
   fi
-  if [ "$linux" = "yes" -o "$bsd" = "yes" -o "$solaris" = "yes" ] ; then
+  if [ "$linux" = "yes" -o "$bsd" = "yes" -o "$solaris" = "yes" -o "$mingw32" = "yes" ] ; then
     if [ "$guest_agent" = "yes" ]; then
       tools="qemu-ga\$(EXESUF) $tools"
+      if [ "$mingw32" = "yes" ]; then
+        tools="qga/vss-win32-provider/qga-provider.dll qga/vss-win32-provider/qga-provider.tlb $tools"
+      fi
     fi
   fi
 fi
diff --git a/qga/Makefile.objs b/qga/Makefile.objs
index b8d7cd0..8d93866 100644
--- a/qga/Makefile.objs
+++ b/qga/Makefile.objs
@@ -3,3 +3,9 @@ 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
+
+ifeq ($(CONFIG_QGA_VSS),y)
+QEMU_CFLAGS += -DHAS_VSS_SDK
+qga-obj-y += vss-win32-provider/
+qga-prv-obj-y += vss-win32-provider/
+endif
diff --git a/qga/vss-win32-provider.h b/qga/vss-win32-provider.h
new file mode 100644
index 0000000..a437e71
--- /dev/null
+++ b/qga/vss-win32-provider.h
@@ -0,0 +1,26 @@
+/*
+ * QEMU Guest Agent win32 VSS provider 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_PROVIDER_H
+#define VSS_WIN32_PROVIDER_H
+
+#include <windows.h>
+
+STDAPI VSSCheckOSVersion(void);
+
+STDAPI COMRegister(void);
+STDAPI COMUnregister(void);
+
+STDAPI DllRegisterServer(void);
+STDAPI DllUnregisterServer(void);
+
+#endif
diff --git a/qga/vss-win32-provider/Makefile.objs b/qga/vss-win32-provider/Makefile.objs
new file mode 100644
index 0000000..73ef752
--- /dev/null
+++ b/qga/vss-win32-provider/Makefile.objs
@@ -0,0 +1,21 @@
+# rules to build qga-provider.dll
+
+qga-obj-y += qga-provider.dll
+qga-prv-obj-y += provider.o install.o
+
+obj-qga-prv-obj-y = $(addprefix $(obj)/, $(qga-prv-obj-y))
+$(obj-qga-prv-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-provider.dll: LDFLAGS = -shared -Wl,--add-stdcall-alias,--enable-stdcall-fixup -lole32 -loleaut32 -lshlwapi -luuid -static
+$(obj)/qga-provider.dll: $(obj-qga-prv-obj-y) $(SRC_PATH)/$(obj)/qga-provider.def $(obj)/qga-provider.tlb
+	$(call quiet-command,$(CXX) -o $@ $(qga-prv-obj-y) $(SRC_PATH)/qga/vss-win32-provider/qga-provider.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 (included in VC++).
+MIDL=midl
+WINSDK="C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\Include"
+
+$(obj)/qga-provider.tlb: $(SRC_PATH)/$(obj)/qga-provider.idl
+	$(call quiet-command,$(MIDL) -m64 -o $@ -I $(WINSDK) $<,"  MIDL  $(TARGET_DIR)$@")
diff --git a/qga/vss-win32-provider/install.cpp b/qga/vss-win32-provider/install.cpp
new file mode 100644
index 0000000..2cf8741
--- /dev/null
+++ b/qga/vss-win32-provider/install.cpp
@@ -0,0 +1,494 @@
+/*
+ * QEMU Guest Agent win32 VSS Provider installer
+ *
+ * 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.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "../vss-win32.h"
+#include "inc/win2003/vscoordint.h"
+#include "../vss-win32-provider.h"
+
+#include <comadmin.h>
+#include <wbemidl.h>
+#include <comutil.h>
+
+extern HINSTANCE g_hinstDll;
+
+const GUID CLSID_COMAdminCatalog =
+{0xF618C514, 0xDFB8, 0x11d1, {0xA2, 0xCF, 0x00, 0x80, 0x5F, 0xC7, 0x92, 0x35}};
+const GUID IID_ICOMAdminCatalog =
+{0xDD662187, 0xDFC2, 0x11d1, {0xA2, 0xCF, 0x00, 0x80, 0x5F, 0xC7, 0x92, 0x35}};
+const GUID CLSID_WbemLocator =
+{0x4590f811, 0x1d3a, 0x11d0, {0x89, 0x1f, 0x00, 0xaa, 0x00, 0x4b, 0x2e, 0x24}};
+const GUID IID_IWbemLocator =
+{0xdc12a687, 0x737f, 0x11cf, {0x88, 0x4d, 0x00, 0xaa, 0x00, 0x4b, 0x2e, 0x24}};
+
+static void errmsg(DWORD err, const char *text)
+{
+    char *msg = NULL, *nul = strchr(text, '(');
+    int len = nul ? nul - text : -1;
+
+    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+                  FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+                  NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+                  (char *)&msg, 0, NULL);
+    printf("%.*s. (Error: %lx) %s\n", len, text, err, msg);
+    LocalFree(msg);
+}
+
+static void errmsg_dialog(DWORD err, const char *text, const char *opt = "")
+{
+    char *msg, buf[512];
+
+    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+                  FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+                  NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+                  (char *)&msg, 0, NULL);
+    snprintf(buf, sizeof(buf), "%s%s. (Error: %lx) %s\n", text, opt, err, msg);
+    MessageBox(NULL, buf, "Error from " QGA_PROVIDER_NAME, MB_OK|MB_ICONERROR);
+    LocalFree(msg);
+}
+
+#define _chk(hr, status, msg, err_label)	\
+    do {                                        \
+        hr = (status);                          \
+        if (FAILED(hr)) {                       \
+            errmsg(hr, msg);                    \
+            goto err_label;                     \
+        }                                       \
+    } while(0)
+
+#define chk(status) _chk(hr, status, "Failed to " #status, out)
+
+template<class T>
+HRESULT put_Value(ICatalogObject *pObj, LPCWSTR name, T val)
+{
+    return pObj->put_Value(_bstr_t(name), _variant_t(val));
+}
+
+/* Check whether this OS version supports VSS providers */
+STDAPI VSSCheckOSVersion(void)
+{
+    OSVERSIONINFO OSver;
+
+    OSver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+    GetVersionEx(&OSver);
+    if((OSver.dwMajorVersion == 5 && OSver.dwMinorVersion >= 2) ||
+       OSver.dwMajorVersion > 5) {
+        return S_OK;
+    }
+    return S_FALSE;
+}
+
+/* Lookup Administrators group name from winmgmt */
+static HRESULT GetAdminName(_bstr_t &name)
+{
+    HRESULT hr;
+    IWbemLocator *pLoc = NULL;
+    IWbemServices *pSvc = NULL;
+    IEnumWbemClassObject *pEnum = NULL;
+    IWbemClassObject *pWobj = NULL;
+    ULONG returned;
+    _variant_t var;
+
+    chk( CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER,
+                          IID_IWbemLocator, (LPVOID*)&pLoc) );
+    chk( pLoc->ConnectServer(_bstr_t(L"ROOT\\CIMV2"), NULL, NULL, NULL,
+                             0, 0, 0, &pSvc) );
+    chk( CoSetProxyBlanket(pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE,
+                           NULL, RPC_C_AUTHN_LEVEL_CALL,
+                           RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE) );
+    chk( pSvc->ExecQuery(
+             _bstr_t(L"WQL"),
+             _bstr_t(L"select * from Win32_Account where "
+                     "SID='S-1-5-32-544' and localAccount=TRUE"),
+             WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY,
+             NULL, &pEnum) );
+    if (!pEnum) {
+        errmsg(E_FAIL, "Failed to query for Administrators");
+        goto out;
+    }
+    chk( pEnum->Next(WBEM_INFINITE, 1, &pWobj, &returned) );
+    if (returned == 0) {
+        errmsg(E_FAIL, "Failed to query for Administrators");
+        goto out;
+    }
+
+    chk( pWobj->Get(_bstr_t(L"Name"), 0, &var, 0, 0) );
+    name = var;
+out:
+    if (pLoc) {
+        pLoc->Release();
+    }
+    if (pSvc) {
+        pSvc->Release();
+    }
+    if (pEnum) {
+        pEnum->Release();
+    }
+    if (pWobj) {
+        pWobj->Release();
+    }
+    return hr;
+}
+
+/* Register this module to COM+ Applications Catalog */
+STDAPI COMRegister(void)
+{
+    HRESULT hr = E_FAIL;
+    IUnknown *pUnknown = NULL;
+    ICOMAdminCatalog *pCatalog = NULL;
+    ICatalogCollection *pApps = NULL, *pRoles = NULL, *pUsersInRole = NULL;
+    ICatalogObject *pObj = NULL;
+    long n;
+    _bstr_t name;
+    _variant_t key;
+    CHAR dllPath[MAX_PATH], tlbPath[MAX_PATH];
+
+    if (!g_hinstDll) {
+        errmsg(E_FAIL, "Failed to initialize DLL");
+        goto out;
+    }
+
+    if (VSSCheckOSVersion() == S_FALSE) {
+        printf("VSS provider is not supported in this OS version.\n");
+        return S_FALSE; /* VSS feature is disabled */
+    }
+
+    COMUnregister();
+
+    chk( CoInitialize(NULL) );
+    chk( CoCreateInstance(CLSID_COMAdminCatalog, NULL, CLSCTX_INPROC_SERVER,
+                          IID_IUnknown, (void**)&pUnknown) );
+    chk( pUnknown->QueryInterface(IID_ICOMAdminCatalog, (void**)&pCatalog) );
+
+    /* Install COM+ Component */
+
+    chk( pCatalog->GetCollection(_bstr_t(L"Applications"),
+                                 (IDispatch**)&pApps) );
+    chk( pApps->Populate() );
+    chk( pApps->Add((IDispatch**)&pObj) );
+    chk( put_Value(pObj, L"Name",        QGA_PROVIDER_LNAME) );
+    chk( put_Value(pObj, L"Description", QGA_PROVIDER_LNAME) );
+    chk( put_Value(pObj, L"ApplicationAccessChecksEnabled", true) );
+    chk( put_Value(pObj, L"Authentication",                 short(6)) );
+    chk( put_Value(pObj, L"AuthenticationCapability",       short(2)) );
+    chk( put_Value(pObj, L"ImpersonationLevel",             short(2)) );
+    chk( pApps->SaveChanges(&n) );
+    chk( pObj->get_Key(&key) );
+
+    pObj->Release();
+    pObj = NULL;
+
+    if (!GetModuleFileName(g_hinstDll, dllPath, sizeof(dllPath))) {
+        errmsg(GetLastError(), "GetModuleFileName failed");
+        goto out;
+    }
+    n = strlen(dllPath);
+    if (n < 3) {
+        errmsg(E_FAIL, "Failed to lookup dll");
+    }
+    strcpy(tlbPath, dllPath);
+    strcpy(tlbPath+n-3, "TLB");
+    printf("Registering " QGA_PROVIDER_NAME ":\n");
+    printf("  %s\n", dllPath);
+    printf("  %s\n", tlbPath);
+    if (!PathFileExists(tlbPath)) {
+        errmsg(ERROR_FILE_NOT_FOUND, "Failed to lookup tlb");
+        goto out;
+    }
+
+    chk( pCatalog->InstallComponent(_bstr_t(QGA_PROVIDER_LNAME),
+                                    _bstr_t(dllPath), _bstr_t(tlbPath),
+                                    _bstr_t("")) );
+
+    /* Setup roles of the applicaion */
+
+    chk( pApps->GetCollection(_bstr_t(L"Roles"), key,
+                              (IDispatch**)&pRoles) );
+    chk( pRoles->Populate() );
+    chk( pRoles->Add((IDispatch**)&pObj) );
+    chk( put_Value(pObj, L"Name",        L"Administrators") );
+    chk( put_Value(pObj, L"Description", L"Administrators group") );
+    chk( pRoles->SaveChanges(&n) );
+    chk( pObj->get_Key(&key) );
+
+    pObj->Release();
+    pObj = NULL;
+
+    /* Setup users in the role */
+
+    chk( pRoles->GetCollection(_bstr_t(L"UsersInRole"), key,
+                               (IDispatch**)&pUsersInRole) );
+    chk( pUsersInRole->Populate() );
+
+    chk( pUsersInRole->Add((IDispatch**)&pObj) );
+    chk( GetAdminName(name) );
+    chk( put_Value(pObj, L"User", _bstr_t(".\\") + name) );
+
+    pObj->Release();
+    pObj = NULL;
+
+    chk( pUsersInRole->Add((IDispatch**)&pObj) );
+    chk( put_Value(pObj, L"User", L"SYSTEM") );
+    chk( pUsersInRole->SaveChanges(&n) );
+
+out:
+    if (pUnknown) {
+        pUnknown->Release();
+    }
+    if (pCatalog) {
+        pCatalog->Release();
+    }
+    if (pApps) {
+        pApps->Release();
+    }
+    if (pRoles) {
+        pRoles->Release();
+    }
+    if (pUsersInRole) {
+        pUsersInRole->Release();
+    }
+    if (pObj) {
+        pObj->Release();
+    }
+
+    if (FAILED(hr)) {
+        COMUnregister();
+    }
+    CoUninitialize();
+
+    return hr;
+}
+
+/* Unregister this module from COM+ Applications Catalog */
+STDAPI COMUnregister(void)
+{
+    HRESULT hr;
+    IUnknown *pUnknown = NULL;
+    ICOMAdminCatalog *pCatalog = NULL;
+    ICatalogCollection *pColl = NULL;
+    ICatalogObject *pObj = NULL;
+    _variant_t var;
+    long i, n;
+
+    if (VSSCheckOSVersion() == S_FALSE) {
+        printf("VSS provider is not supported in this OS version.\n");
+        return S_FALSE; /* VSS feature is disabled */
+    }
+
+    chk( DllUnregisterServer() );
+
+    chk( CoInitialize(NULL) );
+    chk( CoCreateInstance(CLSID_COMAdminCatalog, NULL, CLSCTX_INPROC_SERVER,
+                          IID_IUnknown, (void**)&pUnknown) );
+    chk( pUnknown->QueryInterface(IID_ICOMAdminCatalog, (void**)&pCatalog) );
+
+    chk( pCatalog->GetCollection(_bstr_t(L"Applications"),
+                                 (IDispatch**)&pColl) );
+    chk( pColl->Populate() );
+
+    chk( pColl->get_Count(&n) );
+    for (i = n - 1; i >= 0; i--) {
+        chk( pColl->get_Item(i, (IDispatch**)&pObj) );
+        chk( pObj->get_Value(_bstr_t(L"Name"), &var) );
+        if (var == _variant_t(QGA_PROVIDER_LNAME)) {
+            printf("Removing COM+ Application: %S\n", (wchar_t*)_bstr_t(var));
+            chk( pColl->Remove(i) );
+        }
+    }
+    chk( pColl->SaveChanges(&n) );
+
+out:
+    if (pUnknown) {
+        pUnknown->Release();
+    }
+    if (pCatalog) {
+        pCatalog->Release();
+    }
+    if (pColl) {
+        pColl->Release();
+    }
+    if (pObj) {
+        pObj->Release();
+    }
+    CoUninitialize();
+
+    return hr;
+}
+
+
+static BOOL CreateRegistryKey(LPCTSTR key, LPCTSTR value, LPCTSTR data)
+{
+    HKEY  hKey;
+    LONG  ret;
+    DWORD size;
+
+    ret = RegCreateKeyEx(HKEY_CLASSES_ROOT, key, 0, NULL,
+        REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL);
+    if (ret != ERROR_SUCCESS) {
+        goto out;
+    }
+
+    if (data != NULL) {
+        size = (lstrlen(data) + 1) * sizeof(TCHAR);
+    } else {
+        size = 0;
+    }
+
+    ret = RegSetValueEx(hKey, value, 0, REG_SZ, (LPBYTE)data, size);
+    RegCloseKey(hKey);
+
+out:
+    if (ret != ERROR_SUCCESS) {
+        /* We cannot printf here, and need MessageBox to report an error. */
+        errmsg_dialog(ret, "Cannot add registry ", key);
+        return FALSE;
+    }
+    return TRUE;
+}
+
+/* Register this dll as a VSS provider */
+STDAPI DllRegisterServer(void)
+{
+    IVssAdmin *pVssAdmin = NULL;
+    HRESULT hr = E_FAIL;
+    char dllPath[MAX_PATH];
+    char key[256];
+
+    CoInitialize(NULL);
+
+    if (!g_hinstDll) {
+        errmsg_dialog(hr, "Module instance is not available");
+        goto out;
+    }
+
+    /* Add this module to registery */
+
+    sprintf(key, "CLSID\\%s", g_szClsid);
+    if (!CreateRegistryKey(key, NULL, g_szClsid)) {
+        goto out;
+    }
+
+    if (!GetModuleFileName(g_hinstDll, dllPath, sizeof(dllPath))) {
+        errmsg_dialog(GetLastError(), "GetModuleFileName failed");
+        goto out;
+    }
+    sprintf(key, "CLSID\\%s\\InprocServer32", g_szClsid);
+    if (!CreateRegistryKey(key, NULL, dllPath)) {
+        goto out;
+    }
+
+    sprintf(key, "CLSID\\%s\\InprocServer32", g_szClsid);
+    if (!CreateRegistryKey(key, "ThreadingModel", "Apartment")) {
+        goto out;
+    }
+
+    sprintf(key, "CLSID\\%s\\ProgID", g_szClsid);
+    if (!CreateRegistryKey(key, NULL, g_szProgid)) {
+        goto out;
+    }
+
+    if (!CreateRegistryKey(g_szProgid, NULL, QGA_PROVIDER_NAME)) {
+        goto out;
+    }
+
+    sprintf(key, "%s\\CLSID", g_szProgid);
+    if (!CreateRegistryKey(key, NULL, g_szClsid)) {
+        goto out;
+    }
+
+    hr = CoCreateInstance(CLSID_VSSCoordinator,
+        NULL, CLSCTX_ALL, IID_IVssAdmin, (void **)&pVssAdmin);
+    if (FAILED(hr)) {
+        errmsg_dialog(hr, "CoCreateInstance(VSSCoordinator) failed");
+        goto out;
+    }
+
+    hr = pVssAdmin->RegisterProvider(
+        g_gProviderId, CLSID_QGAVSSProvider,
+        const_cast<WCHAR*>(QGA_PROVIDER_LNAME), VSS_PROV_SOFTWARE,
+        const_cast<WCHAR*>(QGA_PROVIDER_VERSION), g_gProviderVersion);
+    if (FAILED(hr)) {
+        errmsg_dialog(hr, "RegisterProvider failed");
+        goto out;
+    }
+
+out:
+    if (pVssAdmin) {
+        pVssAdmin->Release();
+    }
+    CoUninitialize();
+
+    if (FAILED(hr)) {
+        DllUnregisterServer();
+    }
+
+    return hr;
+}
+
+/* Unregister this VSS hardware provider from the system */
+STDAPI DllUnregisterServer(void)
+{
+    TCHAR key[256];
+    IVssAdmin *pVssAdmin = NULL;
+
+    CoInitialize(NULL);
+
+    HRESULT hr = CoCreateInstance(CLSID_VSSCoordinator,
+         NULL, CLSCTX_ALL, IID_IVssAdmin, (void **)&pVssAdmin);
+    if (SUCCEEDED(hr)) {
+        hr = pVssAdmin->UnregisterProvider(g_gProviderId);
+        pVssAdmin->Release();
+    } else {
+        errmsg_dialog(hr, "CoCreateInstance(VSSCoordinator) failed");
+    }
+
+    sprintf(key, "CLSID\\%s", g_szClsid);
+    SHDeleteKey(HKEY_CLASSES_ROOT, key);
+    SHDeleteKey(HKEY_CLASSES_ROOT, g_szProgid);
+
+    CoUninitialize();
+
+    return S_OK; /* Uninstall should never fail */
+}
+
+
+/* Support functions for _bstr_t in MinGW: Originally written by: Diaa Sami */
+
+void __stdcall _com_issue_error(HRESULT hr)
+{
+    printf("_com_issue_error() called with parameter HRESULT = %lu", hr);
+}
+
+namespace _com_util
+{
+    char * __stdcall ConvertBSTRToString(BSTR bstr)
+    {
+        const unsigned int stringLength = lstrlenW(bstr);
+        char *const ascii = new char [stringLength + 1];
+
+        wcstombs(ascii, bstr, stringLength + 1);
+
+        return ascii;
+    }
+
+    BSTR __stdcall ConvertStringToBSTR(const char *const ascii)
+    {
+        const unsigned int stringLength = lstrlenA(ascii);
+        BSTR bstr = SysAllocStringLen(NULL, stringLength);
+
+        mbstowcs(bstr, ascii, stringLength + 1);
+
+        return bstr;
+    }
+}
diff --git a/qga/vss-win32-provider/provider.cpp b/qga/vss-win32-provider/provider.cpp
new file mode 100644
index 0000000..afce5f9
--- /dev/null
+++ b/qga/vss-win32-provider/provider.cpp
@@ -0,0 +1,474 @@
+/*
+ * QEMU Guest Agent win32 VSS Provider implementations
+ *
+ * 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.
+ */
+
+#include <stdio.h>
+#include "../vss-win32.h"
+#include "inc/win2003/vscoordint.h"
+#include "inc/win2003/vsprov.h"
+
+static long g_nComObjsInUse = 0;
+HINSTANCE g_hinstDll = NULL;
+
+/* VSS common GUID's */
+
+const CLSID CLSID_VSSCoordinator =
+{0xE579AB5F, 0x1CC4, 0x44b4, {0xBE, 0xD9, 0xDE, 0x09, 0x91, 0xFF, 0x06, 0x23}};
+const IID IID_IVssAdmin =
+{0x77ED5996, 0x2F63, 0x11d3, {0x8A, 0x39, 0x00, 0xC0, 0x4F, 0x72, 0xD8, 0xE3}};
+
+const IID IID_IVssHardwareSnapshotProvider =
+{0x9593A157, 0x44E9, 0x4344, {0xBB, 0xEB, 0x44, 0xFB, 0xF9, 0xB0, 0x6B, 0x10}};
+const IID IID_IVssSoftwareSnapshotProvider =
+{0x609e123e, 0x2c5a, 0x44d3, {0x8f, 0x01, 0x0b, 0x1d, 0x9a, 0x47, 0xd1, 0xff}};
+const IID IID_IVssProviderCreateSnapshotSet =
+{0x5F894E5B, 0x1E39, 0x4778, {0x8E, 0x23, 0x9A, 0xBA, 0xD9, 0xF0, 0xE0, 0x8C}};
+const IID IID_IVssProviderNotifications =
+{0xE561901F, 0x03A5, 0x4afe, {0x86, 0xD0, 0x72, 0xBA, 0xEE, 0xCE, 0x70, 0x04}};
+
+const IID IID_IVssEnumObject =
+{0xAE1C7110, 0x2F60, 0x11d3, {0x8A, 0x39, 0x00, 0xC0, 0x4F, 0x72, 0xD8, 0xE3}};
+
+
+void LockModule(BOOL block)
+{
+    if (block)
+        InterlockedIncrement(&g_nComObjsInUse);
+    else
+        InterlockedDecrement(&g_nComObjsInUse);
+}
+
+/* Empty enumerator for VssObject */
+
+class CQGAVSSEnumObject : public IVssEnumObject
+{
+public:
+    STDMETHODIMP QueryInterface(REFIID riid, void **ppObj);
+    STDMETHODIMP_(ULONG) AddRef();
+    STDMETHODIMP_(ULONG) Release();
+
+    /* IVssEnumObject Methods */
+    STDMETHODIMP Next(
+        ULONG celt, VSS_OBJECT_PROP *rgelt, ULONG *pceltFetched);
+    STDMETHODIMP Skip(ULONG celt);
+    STDMETHODIMP Reset(void);
+    STDMETHODIMP Clone(IVssEnumObject **ppenum);
+
+    /* CQGAVSSEnumObject Methods */
+    CQGAVSSEnumObject();
+    ~CQGAVSSEnumObject();
+
+private:
+    long m_nRefCount;
+};
+
+CQGAVSSEnumObject::CQGAVSSEnumObject()
+{
+    m_nRefCount = 0;
+    LockModule(TRUE);
+}
+
+CQGAVSSEnumObject::~CQGAVSSEnumObject()
+{
+    LockModule(FALSE);
+}
+
+STDMETHODIMP CQGAVSSEnumObject::QueryInterface(REFIID riid, void **ppObj)
+{
+    if (riid == IID_IUnknown || riid == IID_IVssEnumObject) {
+        *ppObj = static_cast<void*>(static_cast<IVssEnumObject*>(this));
+        AddRef();
+        return S_OK;
+    }
+    ppObj = NULL;
+    return E_NOINTERFACE;
+}
+
+STDMETHODIMP_(ULONG) CQGAVSSEnumObject::AddRef()
+{
+    return InterlockedIncrement(&m_nRefCount);
+}
+
+STDMETHODIMP_(ULONG) CQGAVSSEnumObject::Release()
+{
+    long nRefCount = InterlockedDecrement(&m_nRefCount);
+    if (m_nRefCount == 0)
+        delete this;
+    return nRefCount;
+}
+
+STDMETHODIMP CQGAVSSEnumObject::Next(
+    ULONG celt, VSS_OBJECT_PROP *rgelt, ULONG *pceltFetched)
+{
+    *pceltFetched = 0;
+    return S_FALSE;
+}
+
+STDMETHODIMP CQGAVSSEnumObject::Skip(ULONG celt)
+{
+    return S_FALSE;
+}
+
+STDMETHODIMP CQGAVSSEnumObject::Reset(void)
+{
+    return S_OK;
+}
+
+STDMETHODIMP CQGAVSSEnumObject::Clone(IVssEnumObject **ppenum)
+{
+    return E_NOTIMPL;
+}
+
+
+/* QGAVssProvider */
+
+class CQGAVssProvider :
+    public IVssSoftwareSnapshotProvider,
+    public IVssProviderCreateSnapshotSet,
+    public IVssProviderNotifications
+{
+public:
+    STDMETHODIMP QueryInterface(REFIID riid, void **ppObj);
+    STDMETHODIMP_(ULONG) AddRef();
+    STDMETHODIMP_(ULONG) Release();
+
+    /* IVssSoftwareSnapshotProvider Methods */
+    STDMETHODIMP SetContext(LONG lContext);
+    STDMETHODIMP GetSnapshotProperties(
+        VSS_ID SnapshotId, VSS_SNAPSHOT_PROP *pProp);
+    STDMETHODIMP Query(
+        VSS_ID QueriedObjectId, VSS_OBJECT_TYPE eQueriedObjectType,
+        VSS_OBJECT_TYPE eReturnedObjectsType, IVssEnumObject **ppEnum);
+    STDMETHODIMP DeleteSnapshots(
+        VSS_ID SourceObjectId, VSS_OBJECT_TYPE eSourceObjectType,
+        BOOL bForceDelete, LONG *plDeletedSnapshots,
+        VSS_ID *pNondeletedSnapshotID);
+    STDMETHODIMP BeginPrepareSnapshot(
+        VSS_ID SnapshotSetId, VSS_ID SnapshotId,
+        VSS_PWSZ pwszVolumeName, LONG lNewContext);
+    STDMETHODIMP IsVolumeSupported(
+        VSS_PWSZ pwszVolumeName, BOOL *pbSupportedByThisProvider);
+    STDMETHODIMP IsVolumeSnapshotted(
+        VSS_PWSZ pwszVolumeName, BOOL *pbSnapshotsPresent,
+        LONG *plSnapshotCompatibility);
+    STDMETHODIMP SetSnapshotProperty(
+        VSS_ID SnapshotId, VSS_SNAPSHOT_PROPERTY_ID eSnapshotPropertyId,
+        VARIANT vProperty);
+    STDMETHODIMP RevertToSnapshot(VSS_ID SnapshotId);
+    STDMETHODIMP QueryRevertStatus(VSS_PWSZ pwszVolume, IVssAsync **ppAsync);
+
+    /* IVssProviderCreateSnapshotSet Methods */
+    STDMETHODIMP EndPrepareSnapshots(VSS_ID SnapshotSetId);
+    STDMETHODIMP PreCommitSnapshots(VSS_ID SnapshotSetId);
+    STDMETHODIMP CommitSnapshots (VSS_ID SnapshotSetId);
+    STDMETHODIMP PostCommitSnapshots(
+        VSS_ID SnapshotSetId, LONG lSnapshotsCount);
+    STDMETHODIMP PreFinalCommitSnapshots(VSS_ID SnapshotSetId);
+    STDMETHODIMP PostFinalCommitSnapshots(VSS_ID SnapshotSetId);
+    STDMETHODIMP AbortSnapshots(VSS_ID SnapshotSetId);
+
+    /* IVssProviderNotifications Methods */
+    STDMETHODIMP OnLoad(IUnknown *pCallback);
+    STDMETHODIMP OnUnload(BOOL bForceUnload);
+
+    /* CQGAVssProvider Methods */
+    CQGAVssProvider();
+    ~CQGAVssProvider();
+
+private:
+    long m_nRefCount;
+};
+
+CQGAVssProvider::CQGAVssProvider()
+{
+    m_nRefCount = 0;
+    LockModule(TRUE);
+}
+
+CQGAVssProvider::~CQGAVssProvider()
+{
+    LockModule(FALSE);
+}
+
+STDMETHODIMP CQGAVssProvider::QueryInterface(REFIID riid, void **ppObj)
+{
+    if (riid == IID_IUnknown) {
+        *ppObj = static_cast<void*>(this);
+        AddRef();
+        return S_OK;
+    }
+    else if (riid == IID_IVssSoftwareSnapshotProvider) {
+        *ppObj = static_cast<void*>(static_cast<IVssSoftwareSnapshotProvider*>(this));
+        AddRef();
+        return S_OK;
+    }
+    else if (riid == IID_IVssProviderCreateSnapshotSet) {
+        *ppObj = static_cast<void*>(static_cast<IVssProviderCreateSnapshotSet*>(this));
+        AddRef();
+        return S_OK;
+    }
+    else if (riid == IID_IVssProviderNotifications) {
+        *ppObj = static_cast<void*>(static_cast<IVssProviderNotifications*>(this));
+        AddRef();
+        return S_OK;
+    }
+    *ppObj = NULL;
+    return E_NOINTERFACE;
+}
+
+STDMETHODIMP_(ULONG) CQGAVssProvider::AddRef()
+{
+    return InterlockedIncrement(&m_nRefCount);
+}
+
+STDMETHODIMP_(ULONG) CQGAVssProvider::Release()
+{
+    long nRefCount = InterlockedDecrement(&m_nRefCount);
+    if (m_nRefCount == 0)
+        delete this;
+    return nRefCount;
+}
+
+
+/*
+ * IVssSoftwareSnapshotProvider methods
+ */
+
+STDMETHODIMP CQGAVssProvider::SetContext(LONG lContext)
+{
+    return S_OK;
+}
+
+STDMETHODIMP CQGAVssProvider::GetSnapshotProperties(
+    VSS_ID SnapshotId, VSS_SNAPSHOT_PROP *pProp)
+{
+    return VSS_E_OBJECT_NOT_FOUND;
+}
+
+STDMETHODIMP CQGAVssProvider::Query(
+    VSS_ID QueriedObjectId, VSS_OBJECT_TYPE eQueriedObjectType,
+    VSS_OBJECT_TYPE eReturnedObjectsType, IVssEnumObject **ppEnum)
+{
+    *ppEnum = new CQGAVSSEnumObject;
+    (*ppEnum)->AddRef();
+    return S_OK;
+}
+
+STDMETHODIMP CQGAVssProvider::DeleteSnapshots(
+    VSS_ID SourceObjectId, VSS_OBJECT_TYPE eSourceObjectType,
+    BOOL bForceDelete, LONG *plDeletedSnapshots, VSS_ID *pNondeletedSnapshotID)
+{
+    return E_NOTIMPL;
+}
+
+STDMETHODIMP CQGAVssProvider::BeginPrepareSnapshot(
+    VSS_ID SnapshotSetId, VSS_ID SnapshotId,
+    VSS_PWSZ pwszVolumeName, LONG lNewContext)
+{
+    return S_OK;
+}
+
+STDMETHODIMP CQGAVssProvider::IsVolumeSupported(
+    VSS_PWSZ pwszVolumeName, BOOL *pbSupportedByThisProvider)
+{
+    *pbSupportedByThisProvider = TRUE;
+
+    return S_OK;
+}
+
+STDMETHODIMP CQGAVssProvider::IsVolumeSnapshotted(VSS_PWSZ pwszVolumeName,
+    BOOL *pbSnapshotsPresent, LONG *plSnapshotCompatibility)
+{
+    return S_OK;
+}
+
+STDMETHODIMP CQGAVssProvider::SetSnapshotProperty(VSS_ID SnapshotId,
+    VSS_SNAPSHOT_PROPERTY_ID eSnapshotPropertyId, VARIANT vProperty)
+{
+    return E_NOTIMPL;
+}
+
+STDMETHODIMP CQGAVssProvider::RevertToSnapshot(VSS_ID SnapshotId)
+{
+    return E_NOTIMPL;
+}
+
+STDMETHODIMP CQGAVssProvider::QueryRevertStatus(
+    VSS_PWSZ pwszVolume, IVssAsync **ppAsync)
+{
+    return S_OK;
+}
+
+
+/*
+ * IVssProviderCreateSnapshotSet methods
+ */
+
+STDMETHODIMP CQGAVssProvider::EndPrepareSnapshots(VSS_ID SnapshotSetId)
+{
+    return S_OK;
+}
+
+STDMETHODIMP CQGAVssProvider::PreCommitSnapshots(VSS_ID SnapshotSetId)
+{
+    return S_OK;
+}
+
+STDMETHODIMP CQGAVssProvider::CommitSnapshots(VSS_ID SnapshotSetId)
+{
+    HRESULT hr = S_OK;
+    HANDLE hEvent, hEvent2;
+
+    hEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, EVENT_NAME_FROZEN);
+    if (hEvent == INVALID_HANDLE_VALUE) {
+        hr = E_FAIL;
+        goto out;
+    }
+
+    hEvent2 = OpenEvent(EVENT_ALL_ACCESS, FALSE, EVENT_NAME_THAW);
+    if (hEvent == INVALID_HANDLE_VALUE) {
+        CloseHandle(hEvent);
+        hr = E_FAIL;
+        goto out;
+    }
+
+    SetEvent(hEvent);
+    if (WaitForSingleObject(hEvent2, 60*1000) != WAIT_OBJECT_0) {
+        hr = E_ABORT;
+    }
+
+    CloseHandle(hEvent2);
+    CloseHandle(hEvent);
+out:
+    return hr;
+}
+
+STDMETHODIMP CQGAVssProvider::PostCommitSnapshots(
+    VSS_ID SnapshotSetId, LONG lSnapshotsCount)
+{
+    return S_OK;
+}
+
+STDMETHODIMP CQGAVssProvider::PreFinalCommitSnapshots(VSS_ID SnapshotSetId)
+{
+    return S_OK;
+}
+
+STDMETHODIMP CQGAVssProvider::PostFinalCommitSnapshots(VSS_ID SnapshotSetId)
+{
+    return S_OK;
+}
+
+STDMETHODIMP CQGAVssProvider::AbortSnapshots(VSS_ID SnapshotSetId)
+{
+    return S_OK;
+}
+
+/*
+ * IVssProviderNotifications methods
+ */
+
+STDMETHODIMP CQGAVssProvider::OnLoad(IUnknown *pCallback)
+{
+    return S_OK;
+}
+
+STDMETHODIMP CQGAVssProvider::OnUnload(BOOL bForceUnload)
+{
+    return S_OK;
+}
+
+
+/*
+ * CQGAVssProviderFactory class
+ */
+
+class CQGAVssProviderFactory : public IClassFactory
+{
+public:
+    STDMETHODIMP QueryInterface(REFIID riid, void **ppv);
+    STDMETHODIMP_(ULONG) AddRef();
+    STDMETHODIMP_(ULONG) Release();
+    STDMETHODIMP CreateInstance(
+        IUnknown *pUnknownOuter, REFIID iid, void **ppv);
+    STDMETHODIMP LockServer(BOOL bLock) { return E_NOTIMPL; }
+private:
+    long m_nRefCount;
+};
+
+STDMETHODIMP CQGAVssProviderFactory::QueryInterface(REFIID riid, void **ppv)
+{
+    if (riid == IID_IUnknown || riid == IID_IClassFactory) {
+        *ppv = static_cast<void*>(this);
+        AddRef();
+        return S_OK;
+    }
+    *ppv = NULL;
+    return E_NOINTERFACE;
+}
+
+STDMETHODIMP_(ULONG) CQGAVssProviderFactory::AddRef()
+{
+    LockModule(TRUE);
+    return 2;
+}
+
+STDMETHODIMP_(ULONG) CQGAVssProviderFactory::Release()
+{
+    LockModule(FALSE);
+    return 1;
+}
+
+STDMETHODIMP CQGAVssProviderFactory::CreateInstance(
+    IUnknown *pUnknownOuter, REFIID iid, void **ppv)
+{
+    if (pUnknownOuter)
+        return CLASS_E_NOAGGREGATION;
+    CQGAVssProvider *pObj = new CQGAVssProvider;
+    if (!pObj)
+        return E_OUTOFMEMORY;
+    return pObj->QueryInterface(iid, ppv);
+}
+
+
+/*
+ * DLL functions
+ */
+
+STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
+{
+    static CQGAVssProviderFactory factory;
+
+    *ppv = NULL;
+    if (IsEqualCLSID(rclsid, CLSID_QGAVSSProvider)) {
+        return factory.QueryInterface(riid, ppv);
+    }
+    return CLASS_E_CLASSNOTAVAILABLE;
+}
+
+STDAPI DllCanUnloadNow()
+{
+    return g_nComObjsInUse == 0 ? S_OK : S_FALSE;
+}
+
+EXTERN_C
+BOOL WINAPI DllMain(HINSTANCE hinstDll, DWORD dwReason, LPVOID lpReserved)
+{
+    switch (dwReason) {
+
+    case DLL_PROCESS_ATTACH:
+        g_hinstDll = hinstDll;
+        DisableThreadLibraryCalls(hinstDll);
+        break;
+    }
+
+    return TRUE;
+}
diff --git a/qga/vss-win32-provider/qga-provider.def b/qga/vss-win32-provider/qga-provider.def
new file mode 100644
index 0000000..9f3afc8
--- /dev/null
+++ b/qga/vss-win32-provider/qga-provider.def
@@ -0,0 +1,10 @@
+LIBRARY      "QGA-PROVIDER.DLL"
+
+EXPORTS
+	VSSCheckOSVersion	PRIVATE
+	COMRegister		PRIVATE
+	COMUnregister		PRIVATE
+	DllCanUnloadNow		PRIVATE
+	DllGetClassObject	PRIVATE
+	DllRegisterServer	PRIVATE
+	DllUnregisterServer	PRIVATE
diff --git a/qga/vss-win32-provider/qga-provider.idl b/qga/vss-win32-provider/qga-provider.idl
new file mode 100644
index 0000000..17abca0
--- /dev/null
+++ b/qga/vss-win32-provider/qga-provider.idl
@@ -0,0 +1,20 @@
+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;
+    };
+};
diff --git a/qga/vss-win32.h b/qga/vss-win32.h
new file mode 100644
index 0000000..7600087
--- /dev/null
+++ b/qga/vss-win32.h
@@ -0,0 +1,85 @@
+/*
+ * 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 */
+#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 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"
+
+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
+};
+
+#endif

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [RFC PATCH v2 06/11] qemu-ga: Add Windows VSS requester to quisce applications and filesystems
  2013-04-12 20:01 [Qemu-devel] [RFC PATCH v2 00/11] qemu-ga: fsfreeze on Windows using VSS Tomoki Sekiyama
                   ` (4 preceding siblings ...)
  2013-04-12 20:01 ` [Qemu-devel] [RFC PATCH v2 05/11] qemu-ga: Add Windows VSS provider to quiesce applications on fsfreeze Tomoki Sekiyama
@ 2013-04-12 20:01 ` Tomoki Sekiyama
  2013-04-12 20:02 ` [Qemu-devel] [RFC PATCH v2 07/11] qemu-ga: call Windows VSS requester in fsfreeze command handler Tomoki Sekiyama
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Tomoki Sekiyama @ 2013-04-12 20:01 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, lcapitulino, vrozenfe, Tomoki Sekiyama, mdroth

This adds VSS requester functions for to qemu-ga.
This provides facility to request VSS service in Windows guest to quisce
applications and filesystems.
This function is only supported in Windows 2003 or later. In older guests,
this function does nothing.

Signed-off-by: Tomoki Sekiyama <tomoki.sekiyama@hds.com>
---
 qga/Makefile.objs           |    3 
 qga/vss-win32-requester.cpp |  393 +++++++++++++++++++++++++++++++++++++++++++
 qga/vss-win32-requester.h   |   31 +++
 3 files changed, 426 insertions(+), 1 deletion(-)
 create mode 100644 qga/vss-win32-requester.cpp
 create mode 100644 qga/vss-win32-requester.h

diff --git a/qga/Makefile.objs b/qga/Makefile.objs
index 8d93866..f17a380 100644
--- a/qga/Makefile.objs
+++ b/qga/Makefile.objs
@@ -6,6 +6,7 @@ qga-obj-y += qapi-generated/qga-qmp-marshal.o
 
 ifeq ($(CONFIG_QGA_VSS),y)
 QEMU_CFLAGS += -DHAS_VSS_SDK
-qga-obj-y += vss-win32-provider/
+qga-obj-y += vss-win32-provider/ vss-win32-requester.o
 qga-prv-obj-y += vss-win32-provider/
+$(obj)/vss-win32-requester.o: QEMU_CXXFLAGS += -Wno-unknown-pragmas
 endif
diff --git a/qga/vss-win32-requester.cpp b/qga/vss-win32-requester.cpp
new file mode 100644
index 0000000..90ff026
--- /dev/null
+++ b/qga/vss-win32-requester.cpp
@@ -0,0 +1,393 @@
+/*
+ * QEMU Guest Agent win32 VSS Requester implementations
+ *
+ * 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.
+ */
+
+#include <stdio.h>
+#include <assert.h>
+extern "C" {
+#include "guest-agent-core.h"
+}
+#include "vss-win32-requester.h"
+#include "vss-win32-provider.h"
+#include "vss-win32.h"
+#include "inc/win2003/vswriter.h"
+#include "inc/win2003/vsbackup.h"
+
+/* Functions in VSSAPI.DLL */
+typedef HRESULT (STDAPICALLTYPE* t_CreateVssBackupComponents)(OUT IVssBackupComponents **);
+typedef void (APIENTRY* t_VssFreeSnapshotProperties)(IN VSS_SNAPSHOT_PROP*);
+
+static t_CreateVssBackupComponents _CreateVssBackupComponents = NULL;
+static t_VssFreeSnapshotProperties _VssFreeSnapshotProperties = NULL;
+static IVssBackupComponents *pVssbc = NULL;
+static IVssAsync *pAsyncSnapshot = NULL;
+static HMODULE hLib = NULL;
+static HANDLE hEvent = INVALID_HANDLE_VALUE, hEvent2 = INVALID_HANDLE_VALUE;
+static int cFrozenVols = 0;
+
+GCC_FMT_ATTR(1, 2)
+static void errmsg(const char *fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+    char *msg = g_strdup_vprintf(fmt, ap);
+    va_end(ap);
+    MessageBox(NULL, msg, "Error in QEMU guest agent", MB_OK | MB_ICONWARNING);
+    g_free(msg);
+}
+
+static void error_set_win32(Error **errp, DWORD err,
+                            ErrorClass eclass, const char *text)
+{
+    char *msg = NULL, *nul = strchr(text, '(');
+    int len = nul ? nul - text : -1;
+
+    /* print error message in native encoding */
+    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+                  FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+                  NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+                  (char *)&msg, 0, NULL);
+    printf("%.*s. (Error: %lx) %s\n", len, text, err, msg);
+    LocalFree(msg);
+
+    /* set error message in UTF-8 encoding */
+    msg = g_win32_error_message(err);
+    error_set(errp, eclass, "%.*s. (Error: %lx) %s", len, text, err, msg);
+    g_free(msg);
+}
+#define error_setg_win32(errp, err, text) \
+    error_set_win32(errp, err, ERROR_CLASS_GENERIC_ERROR, text)
+
+#define _chk(status, text, errp, err_label)	\
+    do {                                        \
+        HRESULT __hr = (status);                \
+        if (FAILED(__hr)) {                     \
+            error_setg_win32(errp, __hr, text); \
+            goto err_label;                     \
+        }                                       \
+    } while(0)
+
+#define chk(status) _chk(status, "Failed to " #status, err, out)
+
+
+HRESULT WaitForAsync(IVssAsync *pAsync)
+{
+    HRESULT ret, hr;
+
+    do {
+        hr = pAsync->Wait();
+        if (FAILED(hr)) {
+            ret = hr;
+            break;
+        }
+        hr = pAsync->QueryStatus(&ret, NULL);
+        if (FAILED(hr)) {
+            ret = hr;
+            break;
+        }
+    } while (ret == VSS_S_ASYNC_PENDING);
+
+    return ret;
+}
+
+HRESULT vss_init(void)
+{
+    HRESULT hr;
+
+    hr = VSSCheckOSVersion();
+    if (hr == S_FALSE) {
+        return hr;
+    }
+
+    hr = CoInitialize(NULL);
+    if (FAILED(hr)) {
+        errmsg("CoInitialize failed [%lx]", hr);
+        goto out;
+    };
+    hr = CoInitializeSecurity(
+        NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
+        RPC_C_IMP_LEVEL_IDENTIFY, NULL, EOAC_NONE, NULL);
+    if (FAILED(hr)) {
+        errmsg("CoInitializeSecurity failed [%lx]", hr);
+        goto out;
+    }
+
+    hLib = LoadLibraryA("VSSAPI.DLL");
+    if (!hLib) {
+        errmsg("LoadLibrary VSSAPI.DLL failed");
+        hr = E_FAIL;
+        goto out;
+    }
+
+    _CreateVssBackupComponents = (t_CreateVssBackupComponents)
+        GetProcAddress(hLib,
+#ifdef _WIN64 /* 64bit environment */
+        "?CreateVssBackupComponents@@YAJPEAPEAVIVssBackupComponents@@@Z"
+#else /* 32bit environment */
+        "?CreateVssBackupComponents@@YGJPAPAVIVssBackupComponents@@@Z"
+#endif
+        );
+    _VssFreeSnapshotProperties = (t_VssFreeSnapshotProperties)
+        GetProcAddress(hLib, "VssFreeSnapshotProperties");
+    if (!_CreateVssBackupComponents || !_VssFreeSnapshotProperties) {
+        errmsg("GetProcAddress failed");
+        hr = E_FAIL;
+        goto out;
+    }
+
+    return S_OK;
+out:
+    vss_deinit();
+    return hr;
+}
+
+static void vss_cleanup(void)
+{
+    if (hEvent != INVALID_HANDLE_VALUE) {
+        CloseHandle(hEvent);
+        hEvent = INVALID_HANDLE_VALUE;
+    }
+    if (hEvent2 != INVALID_HANDLE_VALUE) {
+        CloseHandle(hEvent2);
+        hEvent2 = INVALID_HANDLE_VALUE;
+    }
+    if (pVssbc) {
+        pVssbc->Release();
+        pVssbc = NULL;
+    }
+}
+
+void vss_deinit(void)
+{
+    if (VSSCheckOSVersion() == S_FALSE) {
+        return;
+    }
+
+    vss_cleanup();
+
+    CoUninitialize();
+
+    _CreateVssBackupComponents = NULL;
+    _VssFreeSnapshotProperties = NULL;
+    if (hLib) {
+        FreeLibrary(hLib);
+        hLib = NULL;
+    }
+}
+
+int vss_initialized(void)
+{
+    return hLib != NULL;
+}
+
+static void vss_add_components(Error **err)
+{
+    unsigned int cWriters, i;
+    VSS_ID id, idInstance, idWriter;
+    BSTR bstrWriterName;
+    VSS_USAGE_TYPE usage;
+    VSS_SOURCE_TYPE source;
+    unsigned int cComponents, c1, c2, j;
+    IVssExamineWriterMetadata *pMetadata;
+    IVssWMComponent *pComponent;
+    PVSSCOMPONENTINFO pInfo = NULL;
+
+    chk( pVssbc->GetWriterMetadataCount(&cWriters) );
+
+    for (i = 0; i < cWriters; i++) {
+        chk( pVssbc->GetWriterMetadata(i, &id, &pMetadata) );
+        chk( pMetadata->GetIdentity(&idInstance, &idWriter,
+                                    &bstrWriterName, &usage, &source) );
+        chk( pMetadata->GetFileCounts(&c1, &c2, &cComponents) );
+
+        for (j = 0; j < cComponents; j++) {
+            chk( pMetadata->GetComponent(j, &pComponent) );
+            chk( pComponent->GetComponentInfo(&pInfo) );
+            if (pInfo->bSelectable) {
+                chk( pVssbc->AddComponent(idInstance, idWriter, pInfo->type,
+                                          pInfo->bstrLogicalPath,
+                                          pInfo->bstrComponentName) );
+            }
+            pComponent->FreeComponentInfo(pInfo);
+            pInfo = NULL;
+            pComponent->Release();
+            pComponent = NULL;
+        }
+
+        pMetadata->Release();
+        pMetadata = NULL;
+    }
+out:
+    if (pComponent) {
+        if (pInfo) {
+            pComponent->FreeComponentInfo(pInfo);
+        }
+        pComponent->Release();
+    }
+    if (pMetadata) {
+        pMetadata->Release();
+    }
+}
+
+void qga_vss_fsfreeze_freeze(int *num_vols, Error **err)
+{
+    IVssAsync *pAsync;
+    HANDLE h;
+    GUID guidSnapshotSet = GUID_NULL;
+    SECURITY_DESCRIPTOR sd;
+    SECURITY_ATTRIBUTES sa;
+    WCHAR buf[64], *b = buf;
+    int n = 0;
+
+    if (pVssbc) { /* already frozen */
+        *num_vols = 0;
+        return;
+    }
+
+    assert(_CreateVssBackupComponents != NULL);
+    chk( _CreateVssBackupComponents(&pVssbc) );
+    chk( pVssbc->InitializeForBackup() );
+    chk( pVssbc->SetBackupState(true, true, VSS_BT_FULL, false) );
+    /*
+     * Currently writable snapshots are not supported.
+     * To prevent the final commit (which requires to write to snapshots),
+     * VSS_VOLSNAP_ATTR_NO_AUTORECOVERY (for Win2008 SP2 or later) and
+     * VSS_VOLSNAP_ATTR_TRANSPORTABLE (for ealier versions) are specified here.
+     */
+    chk( pVssbc->SetContext(VSS_CTX_APP_ROLLBACK |
+                            VSS_VOLSNAP_ATTR_NO_AUTORECOVERY |
+                            VSS_VOLSNAP_ATTR_TRANSPORTABLE |
+                            VSS_VOLSNAP_ATTR_TXF_RECOVERY) );
+
+    chk( pVssbc->GatherWriterMetadata(&pAsync) );
+    _chk( WaitForAsync(pAsync), "GatherWriterMetadata", err, out );
+    pAsync->Release();
+
+    vss_add_components(err);
+    if (error_is_set(err)) {
+        goto out;
+    }
+
+    chk( pVssbc->StartSnapshotSet(&guidSnapshotSet) );
+
+    h = FindFirstVolumeW(buf, sizeof(buf));
+    while (h != INVALID_HANDLE_VALUE) {
+        if (GetDriveTypeW(buf) == DRIVE_FIXED) {
+            VSS_ID pid;
+            HRESULT hr = pVssbc->AddToSnapshotSet(buf, g_gProviderId, &pid);
+            if (FAILED(hr)) {
+                WCHAR name[PATH_MAX];
+                char msg[PATH_MAX+32];
+                if (GetVolumePathNamesForVolumeNameW(
+                        buf, name, sizeof(name), NULL) && *name) {
+                    b = name;
+                }
+                snprintf(msg, sizeof(msg), "add %S to snapshot set", b);
+                error_setg_win32(err, hr, msg);
+                goto out;
+            }
+	    n++;
+        }
+        if (!FindNextVolumeW(h, buf, sizeof(buf))) {
+            FindVolumeClose(h);
+            break;
+        }
+    }
+
+    chk( pVssbc->PrepareForBackup(&pAsync) );
+    _chk( WaitForAsync(pAsync), "PrepareForBackup", err, out );
+    pAsync->Release();
+
+    chk( pVssbc->GatherWriterStatus(&pAsync) );
+    _chk( WaitForAsync(pAsync), "GatherWriterStatus", err, out );
+    pAsync->Release();
+
+    /* Allow unrestricted access to events */
+    InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
+    SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);
+    sa.nLength = sizeof(sa);
+    sa.lpSecurityDescriptor = &sd;
+    sa.bInheritHandle = FALSE;
+
+    hEvent = CreateEvent(&sa, TRUE, FALSE, EVENT_NAME_FROZEN);
+    if (hEvent == INVALID_HANDLE_VALUE) {
+        error_setg_win32(err, GetLastError(), "CreateEvenet");
+        goto out;
+    }
+    hEvent2 = CreateEvent(&sa, TRUE, FALSE, EVENT_NAME_THAW);
+    if (hEvent2 == INVALID_HANDLE_VALUE) {
+        error_setg_win32(err, GetLastError(), "CreateEvenet");
+        goto out;
+    }
+
+    chk( pVssbc->DoSnapshotSet(&pAsyncSnapshot) );
+
+    /* Need to call QueryStatus several times to make VSS provider progress */
+    for (int i = 0; i < 1000; i++) {
+        HRESULT hr = S_OK;
+        chk( pAsyncSnapshot->QueryStatus(&hr, NULL) );
+        if (hr != VSS_S_ASYNC_PENDING) {
+            error_setg(err, "DoSnapshotSet exited without freeze event");
+            goto out;
+        }
+        DWORD ret = WaitForSingleObject(hEvent, 10);
+        if (ret == WAIT_OBJECT_0) {
+            break;
+        }
+    }
+
+    *num_vols = cFrozenVols = n;
+    return;
+
+out:
+    if (pVssbc) {
+        pVssbc->AbortBackup();
+    }
+    vss_cleanup();
+}
+
+
+void qga_vss_fsfreeze_thaw(int *num_vols, Error **err)
+{
+    IVssAsync *pAsync;
+
+    if (hEvent2 == INVALID_HANDLE_VALUE) {
+        /*
+         * In this case, DoSnapshotSet is aborted or not started,
+         * and no volumes must be frozen. We return without an error.
+         */
+        *num_vols = 0;
+        return;
+    }
+    SetEvent(hEvent2);
+
+    assert(pVssbc);
+    assert(pAsyncSnapshot);
+
+    _chk( WaitForAsync(pAsyncSnapshot), "DoSnapshotSet", err, out );
+    pAsyncSnapshot->Release();
+    pAsyncSnapshot = NULL;
+
+    chk( pVssbc->BackupComplete(&pAsync) );
+    _chk( WaitForAsync(pAsync), "BackupComplete", err, out );
+    pAsync->Release();
+
+    *num_vols = cFrozenVols;
+    cFrozenVols = 0;
+    goto done;
+
+out:
+    if (pVssbc) {
+        pVssbc->AbortBackup();
+    }
+done:
+    vss_cleanup();
+}
diff --git a/qga/vss-win32-requester.h b/qga/vss-win32-requester.h
new file mode 100644
index 0000000..f180f56
--- /dev/null
+++ b/qga/vss-win32-requester.h
@@ -0,0 +1,31 @@
+/*
+ * 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
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+HRESULT vss_init(void);
+void vss_deinit(void);
+int vss_initialized(void);
+
+void qga_vss_fsfreeze_freeze(int *nr_volume, struct Error **err);
+void qga_vss_fsfreeze_thaw(int *nr_volume, struct Error **err);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [RFC PATCH v2 07/11] qemu-ga: call Windows VSS requester in fsfreeze command handler
  2013-04-12 20:01 [Qemu-devel] [RFC PATCH v2 00/11] qemu-ga: fsfreeze on Windows using VSS Tomoki Sekiyama
                   ` (5 preceding siblings ...)
  2013-04-12 20:01 ` [Qemu-devel] [RFC PATCH v2 06/11] qemu-ga: Add Windows VSS requester to quisce applications and filesystems Tomoki Sekiyama
@ 2013-04-12 20:02 ` Tomoki Sekiyama
  2013-04-12 20:02 ` [Qemu-devel] [RFC PATCH v2 08/11] qemu-ga: install Windows VSS provider on `qemu-ga -s install' Tomoki Sekiyama
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Tomoki Sekiyama @ 2013-04-12 20:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, lcapitulino, vrozenfe, Tomoki Sekiyama, mdroth

Support guest-fsfreeze-freeze and guest-fsfreeze-thaw commands for Windows
guests. When fsfreeze command is issued, it calls the VSS requester to
freeze filesystems and applications. On thaw command, it again tells the VSS
requester to thaw them.

This also adds calling of initialize functions for the VSS requester.

Signed-off-by: Tomoki Sekiyama <tomoki.sekiyama@hds.com>
---
 qga/commands-win32.c |   74 ++++++++++++++++++++++++++++++++++++++++++++++----
 qga/main.c           |   33 ++++++++++++++++++++++
 2 files changed, 100 insertions(+), 7 deletions(-)

diff --git a/qga/commands-win32.c b/qga/commands-win32.c
index 24e4ad0..67dca60 100644
--- a/qga/commands-win32.c
+++ b/qga/commands-win32.c
@@ -15,6 +15,7 @@
 #include <wtypes.h>
 #include <powrprof.h>
 #include "qga/guest-agent-core.h"
+#include "qga/vss-win32-requester.h"
 #include "qga-qmp-commands.h"
 #include "qapi/qmp/qerror.h"
 
@@ -151,34 +152,95 @@ void qmp_guest_file_flush(int64_t handle, Error **err)
     error_set(err, QERR_UNSUPPORTED);
 }
 
+#ifdef HAS_VSS_SDK
+
 /*
  * Return status of freeze/thaw
  */
 GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **err)
 {
-    error_set(err, QERR_UNSUPPORTED);
-    return 0;
+    if (!vss_initialized()) {
+        error_set(err, QERR_UNSUPPORTED);
+        return 0;
+    }
+
+    if (ga_is_frozen(ga_state)) {
+        return GUEST_FSFREEZE_STATUS_FROZEN;
+    }
+
+    return GUEST_FSFREEZE_STATUS_THAWED;
 }
 
 /*
- * Walk list of mounted file systems in the guest, and freeze the ones which
- * are real local file systems.
+ * Freeze local file systems using Volume Shadow-copy Service.
+ * The frozen state is limited for up to 10 seconds by VSS.
  */
 int64_t qmp_guest_fsfreeze_freeze(Error **err)
 {
-    error_set(err, QERR_UNSUPPORTED);
+    int i;
+
+    slog("guest-fsfreeze called");
+
+    if (!vss_initialized()) {
+        error_set(err, QERR_UNSUPPORTED);
+        return 0;
+    }
+
+    /* cannot risk guest agent blocking itself on a write in this state */
+    ga_set_frozen(ga_state);
+
+    qga_vss_fsfreeze_freeze(&i, err);
+    if (error_is_set(err)) {
+        goto error;
+    }
+
+    return i;
+
+error:
+    qmp_guest_fsfreeze_thaw(NULL);
     return 0;
 }
 
 /*
- * Walk list of frozen file systems in the guest, and thaw them.
+ * Thaw local file systems using Volume Shadow-copy Service.
  */
 int64_t qmp_guest_fsfreeze_thaw(Error **err)
 {
+    int i;
+
+    if (!vss_initialized()) {
+        error_set(err, QERR_UNSUPPORTED);
+        return 0;
+    }
+
+    qga_vss_fsfreeze_thaw(&i, err);
+
+    ga_unset_frozen(ga_state);
+    return i;
+}
+
+#else
+
+GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **err)
+{
+    error_set(err, QERR_UNSUPPORTED);
+    return 0;
+}
+
+int64_t qmp_guest_fsfreeze_freeze(Error **err)
+{
+    error_set(err, QERR_UNSUPPORTED);
+    return 0;
+}
+
+int64_t qmp_guest_fsfreeze_thaw(Error **err)
+{
     error_set(err, QERR_UNSUPPORTED);
     return 0;
 }
 
+#endif
+
 /*
  * Walk list of mounted file systems in the guest, and discard unused
  * areas.
diff --git a/qga/main.c b/qga/main.c
index 1841759..92230e9 100644
--- a/qga/main.c
+++ b/qga/main.c
@@ -34,6 +34,10 @@
 #include "qemu/bswap.h"
 #ifdef _WIN32
 #include "qga/service-win32.h"
+#ifdef HAS_VSS_SDK
+#include "qga/vss-win32-provider.h"
+#include "qga/vss-win32-requester.h"
+#endif
 #include <windows.h>
 #endif
 #ifdef __linux__
@@ -685,6 +689,25 @@ static gboolean channel_init(GAState *s, const gchar *method, const gchar *path)
 }
 
 #ifdef _WIN32
+
+static gboolean vss_win32_init(void)
+{
+#ifdef HAS_VSS_SDK
+    if (FAILED(vss_init())) {
+        g_critical("failed to initialize VSS");
+        return false;
+    }
+#endif
+    return true;
+}
+
+static void vss_win32_deinit(void)
+{
+#ifdef HAS_VSS_SDK
+    vss_deinit();
+#endif
+}
+
 DWORD WINAPI service_ctrl_handler(DWORD ctrl, DWORD type, LPVOID data,
                                   LPVOID ctx)
 {
@@ -727,8 +750,12 @@ VOID WINAPI service_main(DWORD argc, TCHAR *argv[])
     service->status.dwWaitHint = 0;
     SetServiceStatus(service->status_handle, &service->status);
 
+    if (!vss_win32_init()) {
+        goto out_bad;
+    }
     g_main_loop_run(ga_state->main_loop);
-
+    vss_win32_deinit();
+out_bad:
     service->status.dwCurrentState = SERVICE_STOPPED;
     SetServiceStatus(service->status_handle, &service->status);
 }
@@ -1132,7 +1159,11 @@ int main(int argc, char **argv)
             { (char *)QGA_SERVICE_NAME, service_main }, { NULL, NULL } };
         StartServiceCtrlDispatcher(service_table);
     } else {
+        if (!vss_win32_init()) {
+            goto out_bad;
+        }
         g_main_loop_run(ga_state->main_loop);
+        vss_win32_deinit();
     }
 #endif
 

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [RFC PATCH v2 08/11] qemu-ga: install Windows VSS provider on `qemu-ga -s install'
  2013-04-12 20:01 [Qemu-devel] [RFC PATCH v2 00/11] qemu-ga: fsfreeze on Windows using VSS Tomoki Sekiyama
                   ` (6 preceding siblings ...)
  2013-04-12 20:02 ` [Qemu-devel] [RFC PATCH v2 07/11] qemu-ga: call Windows VSS requester in fsfreeze command handler Tomoki Sekiyama
@ 2013-04-12 20:02 ` Tomoki Sekiyama
  2013-04-12 20:02 ` [Qemu-devel] [RFC PATCH v2 09/11] qemu-ga: Add VSS provider .tlb file in the repository Tomoki Sekiyama
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Tomoki Sekiyama @ 2013-04-12 20:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, lcapitulino, vrozenfe, Tomoki Sekiyama, mdroth

Register QGA VSS provider library into Windows when qemu-ga is installed as
Windows service ('-s install' option). It is deregistered when the service
is uninstalled ('-s uninstall' option).

Signed-off-by: Tomoki Sekiyama <tomoki.sekiyama@hds.com>
---
 qga/main.c |    8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/qga/main.c b/qga/main.c
index 92230e9..09fa291 100644
--- a/qga/main.c
+++ b/qga/main.c
@@ -1029,8 +1029,16 @@ int main(int argc, char **argv)
         case 's':
             service = optarg;
             if (strcmp(service, "install") == 0) {
+#ifdef HAS_VSS_SDK
+                if (FAILED(COMRegister())) {
+                    return EXIT_FAILURE;
+                }
+#endif
                 return ga_install_service(path, log_filepath);
             } else if (strcmp(service, "uninstall") == 0) {
+#ifdef HAS_VSS_SDK
+                COMUnregister();
+#endif
                 return ga_uninstall_service();
             } else {
                 printf("Unknown service command.\n");

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [RFC PATCH v2 09/11] qemu-ga: Add VSS provider .tlb file in the repository
  2013-04-12 20:01 [Qemu-devel] [RFC PATCH v2 00/11] qemu-ga: fsfreeze on Windows using VSS Tomoki Sekiyama
                   ` (7 preceding siblings ...)
  2013-04-12 20:02 ` [Qemu-devel] [RFC PATCH v2 08/11] qemu-ga: install Windows VSS provider on `qemu-ga -s install' Tomoki Sekiyama
@ 2013-04-12 20:02 ` Tomoki Sekiyama
  2013-04-12 20:02 ` [Qemu-devel] [RFC PATCH v2 10/11] QMP/qemu-ga-client: make timeout longer for guest-fsfreeze-freeze command Tomoki Sekiyama
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Tomoki Sekiyama @ 2013-04-12 20:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, lcapitulino, vrozenfe, Tomoki Sekiyama, mdroth

To build type library (.tlb) for qga-provider.dll from COM IDL (.idl),
MIDL in VisualC++ and stdole2.tlb in Windows SDK are required.

This patch adds pre-compiled .tlb file in the repository in order to
enable cross-compile qemu-ga.exe for Windows with VSS support.

Signed-off-by: Tomoki Sekiyama <tomoki.sekiyama@hds.com>
---
 Makefile                                |    2 +-
 qga/vss-win32-provider/Makefile.objs    |    4 ++++
 qga/vss-win32-provider/qga-provider.tlb |  Bin
 3 files changed, 5 insertions(+), 1 deletion(-)
 create mode 100644 qga/vss-win32-provider/qga-provider.tlb

diff --git a/Makefile b/Makefile
index 8d4506f..c938aec 100644
--- a/Makefile
+++ b/Makefile
@@ -224,7 +224,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
diff --git a/qga/vss-win32-provider/Makefile.objs b/qga/vss-win32-provider/Makefile.objs
index 73ef752..698359b 100644
--- a/qga/vss-win32-provider/Makefile.objs
+++ b/qga/vss-win32-provider/Makefile.objs
@@ -18,4 +18,8 @@ MIDL=midl
 WINSDK="C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\Include"
 
 $(obj)/qga-provider.tlb: $(SRC_PATH)/$(obj)/qga-provider.idl
+ifeq ($(wildcard $(SRC_PATH)/$(obj)/qga-provider.tlb),)
 	$(call quiet-command,$(MIDL) -m64 -o $@ -I $(WINSDK) $<,"  MIDL  $(TARGET_DIR)$@")
+else
+	$(call quiet-command,cp $(dir $<)qga-provider.tlb $@, "  COPY  $(TARGET_DIR)$@")
+endif
diff --git a/qga/vss-win32-provider/qga-provider.tlb b/qga/vss-win32-provider/qga-provider.tlb
new file mode 100644
index 0000000000000000000000000000000000000000..226452a1861371ffe0cad1019cf90fdfdcd5ef49
GIT binary patch
literal 1528
zcmeYbb_-!*U}OLRP8Kl5;0UB3A_y8H!@$4<WGF*9|A9aP$W{R21|SCUVfs9Pj1;IC
zKahR`)X0Ox{{ZC6An~sN`2tA%H9-9hNPHcj{0byK4>OPh6a(1_GM|T)fx!kz-UG<D
zK;nbc0l9GX===tt`Vb`fD?q*q5+7YXI$u?Zf#C;G4-9~uhYKVCC4f!`hZ{(Z0*HVD
zkhwswGqAt}ki;hd*$F@lQbP%-z+r|5P#hGW*vvKniaRx03p~wP?y>h_rLW<nKOg@=
z6{hYgzgH7@QE<^MU>KC!yoBjb#vz`9Lwu4+R-SJ!kIOX4xLBUUGN9-NyTyP76j}@n
z2f!qQ8-xepfXD+7rW+{SKz4&@7#qX~^1#sn3O|tFK>%ciE<<riN`6kNkzPqoQh0bc
zNbM*XJ|Un0jALSb15^rEE6h+Y8tCpA798vm9#E8DmYI@T<dc~c4pSpwQKEn@FU<fE
zfvHyrsVqoU0O~4AEUE;iEfI8i=bXgi;_z?|20Ng!&PAz-C8;S2NtFt|o-RHLWvNBQ
znfZAN=6VJOdIqMZrV5EA3T{Q23NES13Py$shQ?OLW>&_Q3PuKoMqI)S5zj9Ngog_=
gXfrXehlhjmFbIJB4$8MKU>*YlD1Z9^F{m5{03Vre%>V!Z

literal 0
HcmV?d00001

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [RFC PATCH v2 10/11] QMP/qemu-ga-client: make timeout longer for guest-fsfreeze-freeze command
  2013-04-12 20:01 [Qemu-devel] [RFC PATCH v2 00/11] qemu-ga: fsfreeze on Windows using VSS Tomoki Sekiyama
                   ` (8 preceding siblings ...)
  2013-04-12 20:02 ` [Qemu-devel] [RFC PATCH v2 09/11] qemu-ga: Add VSS provider .tlb file in the repository Tomoki Sekiyama
@ 2013-04-12 20:02 ` Tomoki Sekiyama
  2013-04-12 20:02 ` [Qemu-devel] [RFC PATCH v2 11/11] QMP/qmp.py: set locale for exceptions to display non-ascii messages correctly Tomoki Sekiyama
  2013-04-23 11:08 ` [Qemu-devel] [RFC PATCH v2 00/11] qemu-ga: fsfreeze on Windows using VSS Libaiqing
  11 siblings, 0 replies; 15+ messages in thread
From: Tomoki Sekiyama @ 2013-04-12 20:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, lcapitulino, vrozenfe, Tomoki Sekiyama, mdroth

guest-fsfreeze-freeze command can take longer than 3 seconds when heavy
disk I/O is running. To avoid unexpected timeout, this changes the timeout
to 30 seconds.

Signed-off-by: Tomoki Sekiyama <tomoki.sekiyama@hds.com>
---
 QMP/qemu-ga-client |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/QMP/qemu-ga-client b/QMP/qemu-ga-client
index 46676c3..1f7011a 100755
--- a/QMP/qemu-ga-client
+++ b/QMP/qemu-ga-client
@@ -267,7 +267,9 @@ def main(address, cmd, args):
             print('Hint: qemu is not running?')
         sys.exit(1)
 
-    if cmd != 'ping':
+    if cmd == 'fsfreeze' and args[0] == 'freeze':
+        client.sync(30)
+    elif cmd != 'ping':
         client.sync()
 
     globals()['_cmd_' + cmd](client, args)

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [RFC PATCH v2 11/11] QMP/qmp.py: set locale for exceptions to display non-ascii messages correctly
  2013-04-12 20:01 [Qemu-devel] [RFC PATCH v2 00/11] qemu-ga: fsfreeze on Windows using VSS Tomoki Sekiyama
                   ` (9 preceding siblings ...)
  2013-04-12 20:02 ` [Qemu-devel] [RFC PATCH v2 10/11] QMP/qemu-ga-client: make timeout longer for guest-fsfreeze-freeze command Tomoki Sekiyama
@ 2013-04-12 20:02 ` Tomoki Sekiyama
  2013-04-23 11:08 ` [Qemu-devel] [RFC PATCH v2 00/11] qemu-ga: fsfreeze on Windows using VSS Libaiqing
  11 siblings, 0 replies; 15+ messages in thread
From: Tomoki Sekiyama @ 2013-04-12 20:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, lcapitulino, vrozenfe, Tomoki Sekiyama, mdroth

qemu-ga in Windows might return error message with multibyte characters
when the guest OS language is set to other than English. To display such
messages correctly, this decodes the message based on locale settings.

Signed-off-by: Tomoki Sekiyama <tomoki.sekiyama@hds.com>
---
 QMP/qmp.py |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/QMP/qmp.py b/QMP/qmp.py
index c551df1..ee21819 100644
--- a/QMP/qmp.py
+++ b/QMP/qmp.py
@@ -11,6 +11,7 @@
 import json
 import errno
 import socket
+import locale
 
 class QMPError(Exception):
     pass
@@ -133,7 +134,8 @@ class QEMUMonitorProtocol:
     def command(self, cmd, **kwds):
         ret = self.cmd(cmd, kwds)
         if ret.has_key('error'):
-            raise Exception(ret['error']['desc'])
+            enc = locale.getpreferredencoding()
+            raise Exception(ret['error']['desc'].encode(enc))
         return ret['return']
 
     def pull_event(self, wait=False):

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v2 00/11] qemu-ga: fsfreeze on Windows using VSS
  2013-04-12 20:01 [Qemu-devel] [RFC PATCH v2 00/11] qemu-ga: fsfreeze on Windows using VSS Tomoki Sekiyama
                   ` (10 preceding siblings ...)
  2013-04-12 20:02 ` [Qemu-devel] [RFC PATCH v2 11/11] QMP/qmp.py: set locale for exceptions to display non-ascii messages correctly Tomoki Sekiyama
@ 2013-04-23 11:08 ` Libaiqing
  2013-04-23 16:44   ` Tomoki Sekiyama
  11 siblings, 1 reply; 15+ messages in thread
From: Libaiqing @ 2013-04-23 11:08 UTC (permalink / raw)
  To: tomoki.sekiyama@hds.com, qemu-devel@nongnu.org
  Cc: mdroth@linux.vnet.ibm.com, pbonzini@redhat.com,
	vrozenfe@redhat.com, Haofeng, lcapitulino@redhat.com

Hi,
  I tried the patch v2,with the following config.
  
  Guest os : win7 32bit professional
  Host os : fedora 17 
  Command: 
     qemu-kvm -enable-kvm -name win7 -M pc-0.15 -m 1024 -smp 2 -boot c  -device virtio-serial  -drive file=/home/libaiqing/vss/win7.img,if=virtio,index=0,format=qcow2 - -monitor stdio -vga qxl  -vnc :1 -chardev
     socket,id=charchannel0,path=/var/lib/libvirt/qemu/wahaha1_requester,server,nowait -device virtserialport,chardev=charchannel0,id=channel0,name=org.qemu.guest_agent.1  


  Issue:
    1 Extcuting the command "net start qemu-ga" failed,but the command "qemu-qa.exe -m virtio-serial -p \\.\Global\org.qemu.guest_agent.1" is ok.
    2 executing the command "{"execute":"guest-fsfreeze-freeze"}" failed,the output is:

 [root@fedora121 ~]# socat stdio,ignoreeof unix-connect:/var/lib/libvirt/qemu/wahaha1_requester
{'execute':'guest-info'}
{"return": {"version": "1.4.50", "supported_commands": [{"enabled": true, "name": "guest-set-vcpus"}, {"enabled": true, "name": "guest-get-vcpus"}, {"enabled": true, "name": "guest-network-get-interfaces"}, {"enabled": true, "name": "guest-suspend-hybrid"}, {"enabled": true, "name": "guest-suspend-ram"}, {"enabled": true, "name": "guest-suspend-disk"}, {"enabled": true, "name": "guest-fstrim"}, {"enabled": true, "name": "guest-fsfreeze-thaw"}, {"enabled": true, "name": "guest-fsfreeze-freeze"}, {"enabled": true, "name": "guest-fsfreeze-status"}, {"enabled": true, "name": "guest-file-flush"}, {"enabled": true, "name": "guest-file-seek"}, {"enabled": true, "name": "guest-file-write"}, {"enabled": true, "name": "guest-file-read"}, {"enabled": true, "name": "guest-file-close"}, {"enabled": true, "name": "guest-file-open"}, {"enabled": true, "name": "guest-shutdown"}, {"enabled": true, "name": "guest-info"}, {"enabled": true, "name": "guest-set-time"}, {"enabled": true, "name": "guest-get-time"}, {"enabled": true, "name": "guest-ping"}, {"enabled": true, "name": "guest-sync"}, {"enabled": true, "name": "guest-sync-delimited"}]}}
{"execute":"guest-fsfreeze-status"}
{"return": "thawed"}
{"execute":"guest-fsfreeze-freeze"}
{"error": {"class": "GenericError", "desc": "Failed to pVssbc->SetContext. (Error: 8004231b) "}}

Could you give me some advise to debug this problem ? I can provide more information if need.

Regards,
baiqing
-----Original Message-----
From: qemu-devel-bounces+libaiqing=huawei.com@nongnu.org [mailto:qemu-devel-bounces+libaiqing=huawei.com@nongnu.org] On Behalf Of Tomoki Sekiyama
Sent: Saturday, April 13, 2013 4:02 AM
To: qemu-devel@nongnu.org
Cc: pbonzini@redhat.com; lcapitulino@redhat.com; vrozenfe@redhat.com; mdroth@linux.vnet.ibm.com
Subject: [Qemu-devel] [RFC PATCH v2 00/11] qemu-ga: fsfreeze on Windows using VSS

Hi,

This patch series is attempts to add fsfreeze support for Windows
qemu-guest-agent.

changes from v1: 
 - Fix out-tree build by stop using recursive Makefile
 - Added script to extract VSS SDK headers on POSIX systems using msitools
   (thanks Paolo)
 - Remove some unnecessary header files

v1: http://lists.gnu.org/archive/html/qemu-devel/2013-02/msg01963.html

* Description
In Windows, VSS (Volume Shadow Copy Service) provides a facility to
quiesce filesystems and applications before disk snapshots are taken.
This patch series implements "fsfreeze" command of qemu-ga using VSS.

* How to build & run qemu-ga with VSS support

 - Download Microsoft VSS SDK from:
   http://www.microsoft.com/en-us/download/details.aspx?id=23490

 - Setup the SDK
   scripts/extract-vsssdk-headers setup.exe (on POSIX-systems)

 - Specify installed SDK directory to configure option as:
   ./configure -with-vss-sdk="path/to/VSS SDK" --cross-prefix=i686-w64-mingw32-

 - Make qemu-ga.exe

 - Install qemu-ga.exe and qga/vss-win32-provider/qga-provider.{dll,tlb} into
   the same directory in guests

 - Run `qemu-ga.exe -s install' and `net start qemu-ga' in the guests

Any feedback are appliciated.

---
Tomoki Sekiyama (11):
      configure: Support configuring c++ compiler
      Fix errors and warnings while compiling with c++ compilier
      Add a script to extract VSS SDK headers on POSIX system
      qemu-ga: Add an configure option to specify path to Windows VSS SDK
      qemu-ga: Add Windows VSS provider to quiesce applications on fsfreeze
      qemu-ga: Add Windows VSS requester to quisce applications and filesystems
      qemu-ga: call Windows VSS requester in fsfreeze command handler
      qemu-ga: install Windows VSS provider on `qemu-ga -s install'
      qemu-ga: Add VSS provider .tlb file in the repository
      QMP/qemu-ga-client: make timeout longer for guest-fsfreeze-freeze command
      QMP/qmp.py: set locale for exceptions to display non-ascii messages correctly


 .gitignore                              |    1 
 Makefile                                |    3 
 Makefile.objs                           |    2 
 QMP/qemu-ga-client                      |    4 
 QMP/qmp.py                              |    4 
 configure                               |   59 ++++
 hmp.c                                   |    2 
 hw/pci/pci.c                            |    2 
 qga/Makefile.objs                       |    7 
 qga/commands-win32.c                    |   74 ++++-
 qga/main.c                              |   41 +++
 qga/vss-win32-provider.h                |   26 ++
 qga/vss-win32-provider/Makefile.objs    |   25 ++
 qga/vss-win32-provider/install.cpp      |  494 +++++++++++++++++++++++++++++++
 qga/vss-win32-provider/provider.cpp     |  474 ++++++++++++++++++++++++++++++
 qga/vss-win32-provider/qga-provider.def |   10 +
 qga/vss-win32-provider/qga-provider.idl |   20 +
 qga/vss-win32-provider/qga-provider.tlb |  Bin
 qga/vss-win32-requester.cpp             |  393 +++++++++++++++++++++++++
 qga/vss-win32-requester.h               |   31 ++
 qga/vss-win32.h                         |   85 +++++
 rules.mak                               |    9 +
 scripts/extract-vsssdk-headers          |   25 ++
 scripts/qapi.py                         |    9 +
 24 files changed, 1785 insertions(+), 15 deletions(-)
 create mode 100644 qga/vss-win32-provider.h
 create mode 100644 qga/vss-win32-provider/Makefile.objs
 create mode 100644 qga/vss-win32-provider/install.cpp
 create mode 100644 qga/vss-win32-provider/provider.cpp
 create mode 100644 qga/vss-win32-provider/qga-provider.def
 create mode 100644 qga/vss-win32-provider/qga-provider.idl
 create mode 100644 qga/vss-win32-provider/qga-provider.tlb
 create mode 100644 qga/vss-win32-requester.cpp
 create mode 100644 qga/vss-win32-requester.h
 create mode 100644 qga/vss-win32.h
 create mode 100755 scripts/extract-vsssdk-headers



^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v2 00/11] qemu-ga: fsfreeze on Windows using VSS
  2013-04-23 11:08 ` [Qemu-devel] [RFC PATCH v2 00/11] qemu-ga: fsfreeze on Windows using VSS Libaiqing
@ 2013-04-23 16:44   ` Tomoki Sekiyama
  2013-04-29 17:13     ` Tomoki Sekiyama
  0 siblings, 1 reply; 15+ messages in thread
From: Tomoki Sekiyama @ 2013-04-23 16:44 UTC (permalink / raw)
  To: Libaiqing, qemu-devel@nongnu.org
  Cc: mdroth@linux.vnet.ibm.com, pbonzini@redhat.com,
	vrozenfe@redhat.com, Haofeng, lcapitulino@redhat.com

Hi Baiqing,


Thank you for your testing.

>    1 Extcuting the command "net start qemu-ga" failed,but the command
>"qemu-qa.exe -m virtio-serial -p \\.\Global\org.qemu.guest_agent.1" is ok.

`qemu-ga.exe -s install -p \\.\Global\org.qemu.guest_agent.1' may help to
use virtio-serial ".1" in qemu-ga service. Otherwise ".0" is used by
default.


>    2 executing the command "{"execute":"guest-fsfreeze-freeze"}"
>failed,the output is:
<snip>
> {"execute":"guest-fsfreeze-freeze"}
> {"error": {"class": "GenericError", "desc": "Failed to
>pVssbc->SetContext. (Error: 8004231b) "}}
> 
> Could you give me some advise to debug this problem ? I can provide more
>information if need.

Is there any logs corresponding to the error in Event Viewer?

And this might be caused by unsupported VSS_VOLSNAP_ATTR_* flags in
SetContext()
called from qga_vss_fsfreeze_freeze() at qga/vss-win32-requester.cpp,
but I couldn't find out flags not supported on Windows 7 from VSS
references.


Could you try whether removing some of these flags is effective to avoid
the error in your environment?


Thanks,
Tomoki Sekiyama

On 4/23/13 7:08 , "Libaiqing" <libaiqing@huawei.com> wrote:

>Hi,
>  I tried the patch v2,with the following config.
>  
>  Guest os : win7 32bit professional
>  Host os : fedora 17
>  Command: 
>     qemu-kvm -enable-kvm -name win7 -M pc-0.15 -m 1024 -smp 2 -boot c
>-device virtio-serial  -drive
>file=/home/libaiqing/vss/win7.img,if=virtio,index=0,format=qcow2 -
>-monitor stdio -vga qxl  -vnc :1 -chardev
>     
>socket,id=charchannel0,path=/var/lib/libvirt/qemu/wahaha1_requester,server
>,nowait -device 
>virtserialport,chardev=charchannel0,id=channel0,name=org.qemu.guest_agent.
>1  
>
>
>  Issue:
>    1 Extcuting the command "net start qemu-ga" failed,but the command
>"qemu-qa.exe -m virtio-serial -p \\.\Global\org.qemu.guest_agent.1" is ok.
>    2 executing the command "{"execute":"guest-fsfreeze-freeze"}"
>failed,the output is:
>
> [root@fedora121 ~]# socat stdio,ignoreeof
>unix-connect:/var/lib/libvirt/qemu/wahaha1_requester
>{'execute':'guest-info'}
>{"return": {"version": "1.4.50", "supported_commands": [{"enabled": true,
>"name": "guest-set-vcpus"}, {"enabled": true, "name": "guest-get-vcpus"},
>{"enabled": true, "name": "guest-network-get-interfaces"}, {"enabled":
>true, "name": "guest-suspend-hybrid"}, {"enabled": true, "name":
>"guest-suspend-ram"}, {"enabled": true, "name": "guest-suspend-disk"},
>{"enabled": true, "name": "guest-fstrim"}, {"enabled": true, "name":
>"guest-fsfreeze-thaw"}, {"enabled": true, "name":
>"guest-fsfreeze-freeze"}, {"enabled": true, "name":
>"guest-fsfreeze-status"}, {"enabled": true, "name": "guest-file-flush"},
>{"enabled": true, "name": "guest-file-seek"}, {"enabled": true, "name":
>"guest-file-write"}, {"enabled": true, "name": "guest-file-read"},
>{"enabled": true, "name": "guest-file-close"}, {"enabled": true, "name":
>"guest-file-open"}, {"enabled": true, "name": "guest-shutdown"},
>{"enabled": true, "name": "guest-info"}, {"enabled": true, "name":
>"guest-set-time"}, {"enabled": true, "name": "guest-get-time"},
>{"enabled": true, "name": "guest-ping"}, {"enabled": true, "name":
>"guest-sync"}, {"enabled": true, "name": "guest-sync-delimited"}]}}
>{"execute":"guest-fsfreeze-status"}
>{"return": "thawed"}
>{"execute":"guest-fsfreeze-freeze"}
>{"error": {"class": "GenericError", "desc": "Failed to
>pVssbc->SetContext. (Error: 8004231b) "}}
>
>Could you give me some advise to debug this problem ? I can provide more
>information if need.
>
>Regards,
>baiqing
>-----Original Message-----
>From: qemu-devel-bounces+libaiqing=huawei.com@nongnu.org
>[mailto:qemu-devel-bounces+libaiqing=huawei.com@nongnu.org] On Behalf Of
>Tomoki Sekiyama
>Sent: Saturday, April 13, 2013 4:02 AM
>To: qemu-devel@nongnu.org
>Cc: pbonzini@redhat.com; lcapitulino@redhat.com; vrozenfe@redhat.com;
>mdroth@linux.vnet.ibm.com
>Subject: [Qemu-devel] [RFC PATCH v2 00/11] qemu-ga: fsfreeze on Windows
>using VSS
>
>Hi,
>
>This patch series is attempts to add fsfreeze support for Windows
>qemu-guest-agent.
>
>changes from v1: 
> - Fix out-tree build by stop using recursive Makefile
> - Added script to extract VSS SDK headers on POSIX systems using msitools
>   (thanks Paolo)
> - Remove some unnecessary header files
>
>v1: http://lists.gnu.org/archive/html/qemu-devel/2013-02/msg01963.html
>
>* Description
>In Windows, VSS (Volume Shadow Copy Service) provides a facility to
>quiesce filesystems and applications before disk snapshots are taken.
>This patch series implements "fsfreeze" command of qemu-ga using VSS.
>
>* How to build & run qemu-ga with VSS support
>
> - Download Microsoft VSS SDK from:
>   http://www.microsoft.com/en-us/download/details.aspx?id=23490
>
> - Setup the SDK
>   scripts/extract-vsssdk-headers setup.exe (on POSIX-systems)
>
> - Specify installed SDK directory to configure option as:
>   ./configure -with-vss-sdk="path/to/VSS SDK"
>--cross-prefix=i686-w64-mingw32-
>
> - Make qemu-ga.exe
>
> - Install qemu-ga.exe and qga/vss-win32-provider/qga-provider.{dll,tlb}
>into
>   the same directory in guests
>
> - Run `qemu-ga.exe -s install' and `net start qemu-ga' in the guests
>
>Any feedback are appliciated.
>
>---
>Tomoki Sekiyama (11):
>      configure: Support configuring c++ compiler
>      Fix errors and warnings while compiling with c++ compilier
>      Add a script to extract VSS SDK headers on POSIX system
>      qemu-ga: Add an configure option to specify path to Windows VSS SDK
>      qemu-ga: Add Windows VSS provider to quiesce applications on
>fsfreeze
>      qemu-ga: Add Windows VSS requester to quisce applications and
>filesystems
>      qemu-ga: call Windows VSS requester in fsfreeze command handler
>      qemu-ga: install Windows VSS provider on `qemu-ga -s install'
>      qemu-ga: Add VSS provider .tlb file in the repository
>      QMP/qemu-ga-client: make timeout longer for guest-fsfreeze-freeze
>command
>      QMP/qmp.py: set locale for exceptions to display non-ascii messages
>correctly
>
>
> .gitignore                              |    1
> Makefile                                |    3
> Makefile.objs                           |    2
> QMP/qemu-ga-client                      |    4
> QMP/qmp.py                              |    4
> configure                               |   59 ++++
> hmp.c                                   |    2
> hw/pci/pci.c                            |    2
> qga/Makefile.objs                       |    7
> qga/commands-win32.c                    |   74 ++++-
> qga/main.c                              |   41 +++
> qga/vss-win32-provider.h                |   26 ++
> qga/vss-win32-provider/Makefile.objs    |   25 ++
> qga/vss-win32-provider/install.cpp      |  494
>+++++++++++++++++++++++++++++++
> qga/vss-win32-provider/provider.cpp     |  474
>++++++++++++++++++++++++++++++
> qga/vss-win32-provider/qga-provider.def |   10 +
> qga/vss-win32-provider/qga-provider.idl |   20 +
> qga/vss-win32-provider/qga-provider.tlb |  Bin
> qga/vss-win32-requester.cpp             |  393 +++++++++++++++++++++++++
> qga/vss-win32-requester.h               |   31 ++
> qga/vss-win32.h                         |   85 +++++
> rules.mak                               |    9 +
> scripts/extract-vsssdk-headers          |   25 ++
> scripts/qapi.py                         |    9 +
> 24 files changed, 1785 insertions(+), 15 deletions(-)
> create mode 100644 qga/vss-win32-provider.h
> create mode 100644 qga/vss-win32-provider/Makefile.objs
> create mode 100644 qga/vss-win32-provider/install.cpp
> create mode 100644 qga/vss-win32-provider/provider.cpp
> create mode 100644 qga/vss-win32-provider/qga-provider.def
> create mode 100644 qga/vss-win32-provider/qga-provider.idl
> create mode 100644 qga/vss-win32-provider/qga-provider.tlb
> create mode 100644 qga/vss-win32-requester.cpp
> create mode 100644 qga/vss-win32-requester.h
> create mode 100644 qga/vss-win32.h
> create mode 100755 scripts/extract-vsssdk-headers
>
>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v2 00/11] qemu-ga: fsfreeze on Windows using VSS
  2013-04-23 16:44   ` Tomoki Sekiyama
@ 2013-04-29 17:13     ` Tomoki Sekiyama
  0 siblings, 0 replies; 15+ messages in thread
From: Tomoki Sekiyama @ 2013-04-29 17:13 UTC (permalink / raw)
  To: Libaiqing, qemu-devel@nongnu.org
  Cc: mdroth@linux.vnet.ibm.com, pbonzini@redhat.com,
	vrozenfe@redhat.com, Haofeng, lcapitulino@redhat.com

[-- Attachment #1: Type: text/plain, Size: 1518 bytes --]

Hi,

On 4/23/13 12:44 , "Tomoki Sekiyama" <tomoki.sekiyama@hds.com> wrote:
>>    2 executing the command "{"execute":"guest-fsfreeze-freeze"}"
>>failed,the output is:
><snip>
>> {"execute":"guest-fsfreeze-freeze"}
>> {"error": {"class": "GenericError", "desc": "Failed to
>>pVssbc->SetContext. (Error: 8004231b) "}}
>> 
>> Could you give me some advise to debug this problem ? I can provide more
>>information if need.
>
>Is there any logs corresponding to the error in Event Viewer?
>
>And this might be caused by unsupported VSS_VOLSNAP_ATTR_* flags in
>SetContext()
>called from qga_vss_fsfreeze_freeze() at qga/vss-win32-requester.cpp,
>but I couldn't find out flags not supported on Windows 7 from VSS
>references.

I'm investigating this issue. Some versions of Windows seem to
ignore VSS_VOLSNAP_ATTR_NO_AUTORECOVERY, and to cause an error with
VSS_VOLSNAP_ATTR_TRANSPORTABLE. In such cases, we cannot disable
Auto-recovery that requires writable snapshots we don't yet support.
Because of this, even if we remove TRANSPORTABLE flag, auto-recovery
would be enabled and cause another error (VSS_E_OBJECT_NOT_FOUND) on thaw.

The patch attached (to be applied after v2 patch) removes TRANSPORTABLE
flag, and ignores the VSS_E_OBJECT_NOT_FOUND error on thaw.
I think this should resolve the issue in Windows 7, and also works in
the other versions of Windows. Could you try this?

If it works, I will merge this into my path set and resend it as v3.

Thanks,
Tomoki Sekiyama


[-- Attachment #2: ignore-notfound.patch --]
[-- Type: application/octet-stream, Size: 1987 bytes --]

diff --git a/qga/vss-win32-requester.cpp b/qga/vss-win32-requester.cpp
index 90ff026..0e02818 100644
--- a/qga/vss-win32-requester.cpp
+++ b/qga/vss-win32-requester.cpp
@@ -259,12 +259,11 @@ void qga_vss_fsfreeze_freeze(int *num_vols, Error **err)
     /*
      * Currently writable snapshots are not supported.
      * To prevent the final commit (which requires to write to snapshots),
-     * VSS_VOLSNAP_ATTR_NO_AUTORECOVERY (for Win2008 SP2 or later) and
-     * VSS_VOLSNAP_ATTR_TRANSPORTABLE (for ealier versions) are specified here.
+     * VSS_VOLSNAP_ATTR_NO_AUTORECOVERY (for Win2008 SP2 or later) 
+     * are specified here.
      */
     chk( pVssbc->SetContext(VSS_CTX_APP_ROLLBACK |
                             VSS_VOLSNAP_ATTR_NO_AUTORECOVERY |
-                            VSS_VOLSNAP_ATTR_TRANSPORTABLE |
                             VSS_VOLSNAP_ATTR_TXF_RECOVERY) );
 
     chk( pVssbc->GatherWriterMetadata(&pAsync) );
@@ -372,7 +371,19 @@ void qga_vss_fsfreeze_thaw(int *num_vols, Error **err)
     assert(pVssbc);
     assert(pAsyncSnapshot);
 
-    _chk( WaitForAsync(pAsyncSnapshot), "DoSnapshotSet", err, out );
+    HRESULT hr = WaitForAsync(pAsyncSnapshot);
+    if (hr == VSS_E_OBJECT_NOT_FOUND) {
+        /*
+         * On Windows earlier than 2008 SP2 which does not support
+         * VSS_VOLSNAP_ATTR_NO_AUTORECOVERY context, final commit is not
+         * skipped and VSS is aborted. In this case, we get here. Still the
+         * snapshot is taken successfully, so we just ignore the error.
+         */
+        pAsyncSnapshot->Release();
+        pAsyncSnapshot = NULL;
+        goto final;
+    }
+    _chk( hr, "DoSnapshotSet", err, out );
     pAsyncSnapshot->Release();
     pAsyncSnapshot = NULL;
 
@@ -380,6 +391,7 @@ void qga_vss_fsfreeze_thaw(int *num_vols, Error **err)
     _chk( WaitForAsync(pAsync), "BackupComplete", err, out );
     pAsync->Release();
 
+final:
     *num_vols = cFrozenVols;
     cFrozenVols = 0;
     goto done;

^ permalink raw reply related	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2013-04-29 17:13 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-04-12 20:01 [Qemu-devel] [RFC PATCH v2 00/11] qemu-ga: fsfreeze on Windows using VSS Tomoki Sekiyama
2013-04-12 20:01 ` [Qemu-devel] [RFC PATCH v2 01/11] configure: Support configuring c++ compiler Tomoki Sekiyama
2013-04-12 20:01 ` [Qemu-devel] [RFC PATCH v2 02/11] Fix errors and warnings while compiling with c++ compilier Tomoki Sekiyama
2013-04-12 20:01 ` [Qemu-devel] [RFC PATCH v2 03/11] Add a script to extract VSS SDK headers on POSIX system Tomoki Sekiyama
2013-04-12 20:01 ` [Qemu-devel] [RFC PATCH v2 04/11] qemu-ga: Add an configure option to specify path to Windows VSS SDK Tomoki Sekiyama
2013-04-12 20:01 ` [Qemu-devel] [RFC PATCH v2 05/11] qemu-ga: Add Windows VSS provider to quiesce applications on fsfreeze Tomoki Sekiyama
2013-04-12 20:01 ` [Qemu-devel] [RFC PATCH v2 06/11] qemu-ga: Add Windows VSS requester to quisce applications and filesystems Tomoki Sekiyama
2013-04-12 20:02 ` [Qemu-devel] [RFC PATCH v2 07/11] qemu-ga: call Windows VSS requester in fsfreeze command handler Tomoki Sekiyama
2013-04-12 20:02 ` [Qemu-devel] [RFC PATCH v2 08/11] qemu-ga: install Windows VSS provider on `qemu-ga -s install' Tomoki Sekiyama
2013-04-12 20:02 ` [Qemu-devel] [RFC PATCH v2 09/11] qemu-ga: Add VSS provider .tlb file in the repository Tomoki Sekiyama
2013-04-12 20:02 ` [Qemu-devel] [RFC PATCH v2 10/11] QMP/qemu-ga-client: make timeout longer for guest-fsfreeze-freeze command Tomoki Sekiyama
2013-04-12 20:02 ` [Qemu-devel] [RFC PATCH v2 11/11] QMP/qmp.py: set locale for exceptions to display non-ascii messages correctly Tomoki Sekiyama
2013-04-23 11:08 ` [Qemu-devel] [RFC PATCH v2 00/11] qemu-ga: fsfreeze on Windows using VSS Libaiqing
2013-04-23 16:44   ` Tomoki Sekiyama
2013-04-29 17:13     ` Tomoki Sekiyama

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).