All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v7 00/10] qemu-ga: fsfreeze on Windows using VSS
@ 2013-07-15 16:20 Tomoki Sekiyama
  2013-07-15 16:20 ` [Qemu-devel] [PATCH v7 01/10] configure: Support configuring C++ compiler Tomoki Sekiyama
                   ` (10 more replies)
  0 siblings, 11 replies; 24+ messages in thread
From: Tomoki Sekiyama @ 2013-07-15 16:20 UTC (permalink / raw)
  To: qemu-devel
  Cc: libaiqing, ghammer, stefanha, mdroth, lcapitulino, vrozenfe,
	pbonzini, seiji.aguchi, lersek, areis

Hi,

This is v7 of patch series to add fsfreeze for Windows qemu-guest-agent.

changes from v7:
 - Fix COM initialization issue for Windows service thread (patch 07/10)

v6: http://lists.nongnu.org/archive/html/qemu-devel/2013-07/msg01788.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 qga/vss-win32/qga-vss.{dll,tlb}

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

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

Any feedback are appreciated.

---
Tomoki Sekiyama (10):
      configure: Support configuring C++ compiler
      Add c++ keywords to QAPI helper script
      checkpatch.pl: Check .cpp files
      Add a script to extract VSS SDK headers on POSIX system
      qemu-ga: Add configure options to specify path to Windows/VSS SDK
      error: Add error_set_win32 and error_setg_win32
      qemu-ga: Add Windows VSS provider and requester as DLL
      qemu-ga: Call Windows VSS requester in fsfreeze command handler
      qemu-ga: Install Windows VSS provider on `qemu-ga -s install'
      QMP/qemu-ga-client: Make timeout longer for guest-fsfreeze-freeze command


 .gitignore                     |    1 
 Makefile                       |    3 
 Makefile.objs                  |    2 
 QMP/qemu-ga-client             |    4 
 configure                      |   87 +++++++
 hmp.c                          |    2 
 hw/pci/pci.c                   |    2 
 include/qapi/error.h           |   13 +
 qga/Makefile.objs              |    5 
 qga/commands-win32.c           |   82 ++++++
 qga/main.c                     |   10 +
 qga/vss-win32.c                |  154 ++++++++++++
 qga/vss-win32.h                |   27 ++
 qga/vss-win32/Makefile.objs    |   23 ++
 qga/vss-win32/install.cpp      |  424 +++++++++++++++++++++++++++++++++
 qga/vss-win32/provider.cpp     |  513 ++++++++++++++++++++++++++++++++++++++++
 qga/vss-win32/qga-vss.def      |   13 +
 qga/vss-win32/qga-vss.idl      |   20 ++
 qga/vss-win32/qga-vss.tlb      |  Bin
 qga/vss-win32/requester.cpp    |  487 ++++++++++++++++++++++++++++++++++++++
 qga/vss-win32/requester.h      |   42 +++
 qga/vss-win32/vss-common.h     |  128 ++++++++++
 rules.mak                      |    9 +
 scripts/checkpatch.pl          |   37 ++-
 scripts/extract-vsssdk-headers |   35 +++
 scripts/qapi.py                |   12 +
 util/error.c                   |   35 +++
 27 files changed, 2146 insertions(+), 24 deletions(-)
 create mode 100644 qga/vss-win32.c
 create mode 100644 qga/vss-win32.h
 create mode 100644 qga/vss-win32/Makefile.objs
 create mode 100644 qga/vss-win32/install.cpp
 create mode 100644 qga/vss-win32/provider.cpp
 create mode 100644 qga/vss-win32/qga-vss.def
 create mode 100644 qga/vss-win32/qga-vss.idl
 create mode 100644 qga/vss-win32/qga-vss.tlb
 create mode 100644 qga/vss-win32/requester.cpp
 create mode 100644 qga/vss-win32/requester.h
 create mode 100644 qga/vss-win32/vss-common.h
 create mode 100755 scripts/extract-vsssdk-headers

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

* [Qemu-devel] [PATCH v7 01/10] configure: Support configuring C++ compiler
  2013-07-15 16:20 [Qemu-devel] [PATCH v7 00/10] qemu-ga: fsfreeze on Windows using VSS Tomoki Sekiyama
@ 2013-07-15 16:20 ` Tomoki Sekiyama
  2013-07-22 20:53   ` Michael Roth
  2013-07-15 16:20 ` [Qemu-devel] [PATCH v7 02/10] Add c++ keywords to QAPI helper script Tomoki Sekiyama
                   ` (9 subsequent siblings)
  10 siblings, 1 reply; 24+ messages in thread
From: Tomoki Sekiyama @ 2013-07-15 16:20 UTC (permalink / raw)
  To: qemu-devel
  Cc: libaiqing, ghammer, stefanha, mdroth, lcapitulino, vrozenfe,
	pbonzini, seiji.aguchi, Laszlo Ersek, areis

Add configuration for C++ compiler in configure and Makefiles.
The C++ compiler is choosed as following:
 - ${CXX}, if it is specified.
 - ${cross_prefix}g++, if ${cross_prefix} is specified.
 - Otherwise, c++ is used.

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>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
---
 configure |   13 +++++++++++++
 rules.mak |    9 ++++++++-
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/configure b/configure
index cb0f870..6923b65 100755
--- a/configure
+++ b/configure
@@ -251,6 +251,8 @@ for opt do
   ;;
   --cc=*) CC="$optarg"
   ;;
+  --cxx=*) CXX="$optarg"
+  ;;
   --source-path=*) source_path="$optarg"
   ;;
   --cpu=*) cpu="$optarg"
@@ -281,6 +283,12 @@ else
   cc="${CC-${cross_prefix}gcc}"
 fi
 
+if test -z "${CXX}${cross_prefix}"; then
+  cxx="c++"
+else
+  cxx="${CXX-${cross_prefix}g++}"
+fi
+
 ar="${AR-${cross_prefix}ar}"
 as="${AS-${cross_prefix}as}"
 cpp="${CPP-$cc -E}"
@@ -621,6 +629,8 @@ for opt do
   ;;
   --host-cc=*) host_cc="$optarg"
   ;;
+  --cxx=*) cxx="$optarg"
+  ;;
   --objcc=*) objcc="$optarg"
   ;;
   --make=*) make="$optarg"
@@ -1022,6 +1032,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"
@@ -3496,6 +3507,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"
@@ -4069,6 +4081,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 4499745..abc2e84 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
 
@@ -50,6 +54,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)$@")
 
@@ -70,7 +77,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 %.rc
+VPATH_SUFFIXES = %.c %.h %.S %.cpp %.m %.mak %.texi %.sh %.rc
 set-vpath = $(if $1,$(foreach PATTERN,$(VPATH_SUFFIXES),$(eval vpath $(PATTERN) $1)))
 
 # find-in-path

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

* [Qemu-devel] [PATCH v7 02/10] Add c++ keywords to QAPI helper script
  2013-07-15 16:20 [Qemu-devel] [PATCH v7 00/10] qemu-ga: fsfreeze on Windows using VSS Tomoki Sekiyama
  2013-07-15 16:20 ` [Qemu-devel] [PATCH v7 01/10] configure: Support configuring C++ compiler Tomoki Sekiyama
@ 2013-07-15 16:20 ` Tomoki Sekiyama
  2013-07-22 20:55   ` Michael Roth
  2013-07-15 16:20 ` [Qemu-devel] [PATCH v7 03/10] checkpatch.pl: Check .cpp files Tomoki Sekiyama
                   ` (8 subsequent siblings)
  10 siblings, 1 reply; 24+ messages in thread
From: Tomoki Sekiyama @ 2013-07-15 16:20 UTC (permalink / raw)
  To: qemu-devel
  Cc: libaiqing, ghammer, stefanha, mdroth, lcapitulino, vrozenfe,
	pbonzini, seiji.aguchi, Laszlo Ersek, areis

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>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
---
 hmp.c           |    2 +-
 hw/pci/pci.c    |    2 +-
 scripts/qapi.py |   12 +++++++++++-
 3 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/hmp.c b/hmp.c
index 2daed43..69b1506 100644
--- a/hmp.c
+++ b/hmp.c
@@ -524,7 +524,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 dcc85ef..5369996 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -1461,7 +1461,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 baf1321..942bcc2 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -169,9 +169,19 @@ 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',
+                     # alternative representations
+                     'and', 'and_eq', 'bitand', 'bitor', 'compl', 'not',
+                     'not_eq', 'or', 'or_eq', 'xor', 'xor_eq'])
     # 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] 24+ messages in thread

* [Qemu-devel] [PATCH v7 03/10] checkpatch.pl: Check .cpp files
  2013-07-15 16:20 [Qemu-devel] [PATCH v7 00/10] qemu-ga: fsfreeze on Windows using VSS Tomoki Sekiyama
  2013-07-15 16:20 ` [Qemu-devel] [PATCH v7 01/10] configure: Support configuring C++ compiler Tomoki Sekiyama
  2013-07-15 16:20 ` [Qemu-devel] [PATCH v7 02/10] Add c++ keywords to QAPI helper script Tomoki Sekiyama
@ 2013-07-15 16:20 ` Tomoki Sekiyama
  2013-07-22 21:21   ` Michael Roth
  2013-07-15 16:20 ` [Qemu-devel] [PATCH v7 04/10] Add a script to extract VSS SDK headers on POSIX system Tomoki Sekiyama
                   ` (7 subsequent siblings)
  10 siblings, 1 reply; 24+ messages in thread
From: Tomoki Sekiyama @ 2013-07-15 16:20 UTC (permalink / raw)
  To: qemu-devel
  Cc: libaiqing, ghammer, stefanha, mdroth, lcapitulino, vrozenfe,
	pbonzini, seiji.aguchi, lersek, areis

Enable checkpatch.pl to apply the same checks as C source files for
C++ files with .cpp extensions. It also adds some exceptions for C++
sources to suppress errors for:
  - <> used in C++ template arguments (e.g. template <class T>)
  - :: used to represent namespaces   (e.g. SomeClass::method())
  - : used in class declaration       (e.g. class T : public Super)
  - ~ used in destructor method name  (e.g. T::~T())
  - spacing around 'catch'            (e.g. catch (...))

Signed-off-by: Tomoki Sekiyama <tomoki.sekiyama@hds.com>
---
 scripts/checkpatch.pl |   37 +++++++++++++++++++++++++++++--------
 1 file changed, 29 insertions(+), 8 deletions(-)

diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index ec0aa4c..0ef72b5 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -1363,7 +1363,7 @@ sub process {
 # Check for incorrect file permissions
 		if ($line =~ /^new (file )?mode.*[7531]\d{0,2}$/) {
 			my $permhere = $here . "FILE: $realfile\n";
-			if ($realfile =~ /(Makefile|Kconfig|\.c|\.h|\.S|\.tmpl)$/) {
+			if ($realfile =~ /(Makefile|Kconfig|\.c|\.cpp|\.h|\.S|\.tmpl)$/) {
 				ERROR("do not set execute permissions for source files\n" . $permhere);
 			}
 		}
@@ -1460,7 +1460,7 @@ sub process {
 		}
 
 # check we are in a valid source file if not then ignore this hunk
-		next if ($realfile !~ /\.(h|c|s|S|pl|sh)$/);
+		next if ($realfile !~ /\.(h|c|cpp|s|S|pl|sh)$/);
 
 #80 column limit
 		if ($line =~ /^\+/ && $prevrawline !~ /\/\*\*/ &&
@@ -1495,7 +1495,7 @@ sub process {
 		}
 
 # check we are in a valid source file C or perl if not then ignore this hunk
-		next if ($realfile !~ /\.(h|c|pl)$/);
+		next if ($realfile !~ /\.(h|c|cpp|pl)$/);
 
 # in QEMU, no tabs are allowed
 		if ($rawline =~ /^\+.*\t/) {
@@ -1505,7 +1505,7 @@ sub process {
 		}
 
 # check we are in a valid C source file if not then ignore this hunk
-		next if ($realfile !~ /\.(h|c)$/);
+		next if ($realfile !~ /\.(h|c|cpp)$/);
 
 # check for RCS/CVS revision markers
 		if ($rawline =~ /^\+.*\$(Revision|Log|Id)(?:\$|)/) {
@@ -1969,6 +1969,9 @@ sub process {
 				asm|__asm__)$/x)
 			{
 
+			# Ignore 'catch (...)' in C++
+			} elsif ($name =~ /^catch$/ && $realfile =~ /(\.cpp|\.h)$/) {
+
 			# cpp #define statements have non-optional spaces, ie
 			# if there is a space between the name and the open
 			# parenthesis it is simply not a parameter group.
@@ -1992,7 +1995,7 @@ sub process {
 				\+=|-=|\*=|\/=|%=|\^=|\|=|&=|
 				=>|->|<<|>>|<|>|=|!|~|
 				&&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/|%|
-				\?|:
+				\?|::|:
 			}x;
 			my @elements = split(/($ops|;)/, $opline);
 			my $off = 0;
@@ -2066,7 +2069,8 @@ sub process {
 				#   ->
 				#   :   when part of a bitfield
 				} elsif ($op eq '->' || $opv eq ':B') {
-					if ($ctx =~ /Wx.|.xW/) {
+					if ($ctx =~ /Wx.|.xW/ &&
+						!($opv eq ':B' && $line =~ /class/)) {
 						ERROR("spaces prohibited around that '$op' $at\n" . $hereptr);
 					}
 
@@ -2088,7 +2092,11 @@ sub process {
 				} elsif ($op eq '!' || $op eq '~' ||
 					 $opv eq '*U' || $opv eq '-U' ||
 					 $opv eq '&U' || $opv eq '&&U') {
-					if ($ctx !~ /[WEBC]x./ && $ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/) {
+					if ($op eq '~' && $ca =~ /::$/ && $realfile =~ /(\.cpp|\.h)$/) {
+						# '~' used as a name of Destructor
+
+					}
+					elsif ($ctx !~ /[WEBC]x./ && $ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/) {
 						ERROR("space required before that '$op' $at\n" . $hereptr);
 					}
 					if ($op eq '*' && $cc =~/\s*$Modifier\b/) {
@@ -2126,8 +2134,9 @@ sub process {
 
 				# A colon needs no spaces before when it is
 				# terminating a case value or a label.
+				# Ignored if it is used in class declaration in C++.
 				} elsif ($opv eq ':C' || $opv eq ':L') {
-					if ($ctx =~ /Wx./) {
+					if ($ctx =~ /Wx./ && $line !~ /class/) {
 						ERROR("space prohibited before that '$op' $at\n" . $hereptr);
 					}
 
@@ -2135,6 +2144,18 @@ sub process {
 				} elsif ($ctx !~ /[EWC]x[CWE]/) {
 					my $ok = 0;
 
+					if ($realfile =~ /\.cpp|\.h$/) {
+						# Ignore template arguments <...> in C++
+						if (($op eq '<' || $op eq '>') && $line =~ /<.*>/) {
+							$ok = 1;
+						}
+
+						# Ignore :: in C++
+						if ($op eq '::') {
+							$ok = 1;
+						}
+					}
+
 					# Ignore email addresses <foo@bar>
 					if (($op eq '<' &&
 					     $cc =~ /^\S+\@\S+>/) ||

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

* [Qemu-devel] [PATCH v7 04/10] Add a script to extract VSS SDK headers on POSIX system
  2013-07-15 16:20 [Qemu-devel] [PATCH v7 00/10] qemu-ga: fsfreeze on Windows using VSS Tomoki Sekiyama
                   ` (2 preceding siblings ...)
  2013-07-15 16:20 ` [Qemu-devel] [PATCH v7 03/10] checkpatch.pl: Check .cpp files Tomoki Sekiyama
@ 2013-07-15 16:20 ` Tomoki Sekiyama
  2013-07-22 21:27   ` Michael Roth
  2013-07-15 16:20 ` [Qemu-devel] [PATCH v7 05/10] qemu-ga: Add configure options to specify path to Windows/VSS SDK Tomoki Sekiyama
                   ` (6 subsequent siblings)
  10 siblings, 1 reply; 24+ messages in thread
From: Tomoki Sekiyama @ 2013-07-15 16:20 UTC (permalink / raw)
  To: qemu-devel
  Cc: libaiqing, ghammer, stefanha, mdroth, lcapitulino, vrozenfe,
	Paolo Bonzini, seiji.aguchi, Laszlo Ersek, areis

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: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Tomoki Sekiyama <tomoki.sekiyama@hds.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
---
 scripts/extract-vsssdk-headers |   35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 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..9e38510
--- /dev/null
+++ b/scripts/extract-vsssdk-headers
@@ -0,0 +1,35 @@
+#! /bin/bash
+
+# extract-vsssdk-headers
+# Author: Paolo Bonzini <pbonzini@redhat.com>
+
+set -e
+if test $# != 1 || ! test -f "$1"; then
+  echo 'Usage: extract-vsssdk-headers /path/to/setup.exe' >&2
+  exit 1
+fi
+
+if ! command -v msiextract > /dev/null; then
+  echo 'msiextract not found. Please install msitools.' >&2
+  exit 1
+fi
+
+if test -e inc; then
+  echo '"inc" already exists.' >&2
+  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')
+tmpdir=$(mktemp -d)
+trap 'rm -fr -- "$tmpdir" vsssdk.msi' EXIT HUP INT QUIT ALRM TERM
+tail -c +$(($offset+1)) -- "$1" > vsssdk.msi
+
+# Now extract the files.
+msiextract -C $tmpdir vsssdk.msi
+mv "$tmpdir/Program Files/Microsoft/VSSSDK72/inc" inc
+echo 'Extracted SDK headers into "inc" directory.'
+exit 0

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

* [Qemu-devel] [PATCH v7 05/10] qemu-ga: Add configure options to specify path to Windows/VSS SDK
  2013-07-15 16:20 [Qemu-devel] [PATCH v7 00/10] qemu-ga: fsfreeze on Windows using VSS Tomoki Sekiyama
                   ` (3 preceding siblings ...)
  2013-07-15 16:20 ` [Qemu-devel] [PATCH v7 04/10] Add a script to extract VSS SDK headers on POSIX system Tomoki Sekiyama
@ 2013-07-15 16:20 ` Tomoki Sekiyama
  2013-07-22 21:42   ` Michael Roth
  2013-07-15 16:20 ` [Qemu-devel] [PATCH v7 06/10] error: Add error_set_win32 and error_setg_win32 Tomoki Sekiyama
                   ` (5 subsequent siblings)
  10 siblings, 1 reply; 24+ messages in thread
From: Tomoki Sekiyama @ 2013-07-15 16:20 UTC (permalink / raw)
  To: qemu-devel
  Cc: libaiqing, ghammer, stefanha, mdroth, lcapitulino, vrozenfe,
	pbonzini, seiji.aguchi, Laszlo Ersek, areis

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

If the path is omitted, it tries to search the headers from default paths
and VSS support is enabled only if the SDK is found.
VSS support is disabled if --without-vss-sdk or --with-vss-sdk=no is
specified.

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

To cross-compile using mingw, you need to setup the SDK on Windows
environments to extract headers. You can also extract the SDK headers on
POSIX environments using scripts/extract-vss-headers and msitools.

In addition, --with-win-sdk="/path/to/Windows SDK" option is also added to
specify path to Windows SDK, which may be used for native-compile of .tlb
file of qemu-ga VSS provider. However, this is usually unnecessary because
pre-compiled .tlb file is included.

Signed-off-by: Tomoki Sekiyama <tomoki.sekiyama@hds.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
---
 .gitignore |    1 +
 Makefile   |    1 +
 configure  |   69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 71 insertions(+)

diff --git a/.gitignore b/.gitignore
index 0fe114d..02d15f0 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 c06bfab..ec35a15 100644
--- a/Makefile
+++ b/Makefile
@@ -273,6 +273,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
 	if test -f dtc/version_gen.h; then make $(DTC_MAKE_ARGS) clean; fi
 
diff --git a/configure b/configure
index 6923b65..8e1147f 100755
--- a/configure
+++ b/configure
@@ -232,6 +232,8 @@ usb_redir=""
 glx=""
 zlib="yes"
 guest_agent="yes"
+guest_agent_with_vss="no"
+vss_win32_sdk=""
 want_tools="yes"
 libiscsi=""
 coroutine=""
@@ -926,6 +928,14 @@ 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"
+  ;;
+  --with-win-sdk=*) win_sdk="$optarg"
+  ;;
   --enable-tools) want_tools="yes"
   ;;
   --disable-tools) want_tools="no"
@@ -1158,6 +1168,8 @@ 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 "  --with-win-sdk=SDK-path  path to Windows Platform SDK (to build VSS .tlb)"
 echo "  --disable-seccomp        disable seccomp support"
 echo "  --enable-seccomp         enables seccomp support"
 echo "  --with-coroutine=BACKEND coroutine backend. Supported options:"
@@ -3072,6 +3084,57 @@ 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
+
+##########################################
+# lookup Windows platform SDK (if not specified)
+# The SDK is needed only to build .tlb (type library) file of guest agent
+# VSS provider from the source. It is usually unnecessary because the
+# pre-compiled .tlb file is included.
+
+if test "$mingw32" = "yes" -a "$guest_agent" = "yes" -a "$guest_agent_with_vss" = "yes" ; then
+  if test -z "$win_sdk"; then
+    programfiles="$PROGRAMFILES"
+    test -n "$PROGRAMW6432" && programfiles="$PROGRAMW6432"
+    if test -n "$programfiles"; then
+      win_sdk=$(ls -d "$programfiles/Microsoft SDKs/Windows/v"* | tail -1) 2>/dev/null
+    fi
+  fi
+fi
+
+##########################################
 
 ##########################################
 # check if we have fdatasync
@@ -3503,6 +3566,7 @@ echo "Manual directory  `eval echo $mandir`"
 echo "ELF interp prefix $interp_prefix"
 else
 echo "local state directory   queried at runtime"
+echo "Windows SDK       $win_sdk"
 fi
 echo "Source path       $source_path"
 echo "C compiler        $cc"
@@ -3589,6 +3653,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"
@@ -3663,6 +3728,10 @@ 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
+    echo "WIN_SDK=\"$win_sdk\"" >> $config_host_mak
+  fi
 else
   echo "CONFIG_POSIX=y" >> $config_host_mak
 fi

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

* [Qemu-devel] [PATCH v7 06/10] error: Add error_set_win32 and error_setg_win32
  2013-07-15 16:20 [Qemu-devel] [PATCH v7 00/10] qemu-ga: fsfreeze on Windows using VSS Tomoki Sekiyama
                   ` (4 preceding siblings ...)
  2013-07-15 16:20 ` [Qemu-devel] [PATCH v7 05/10] qemu-ga: Add configure options to specify path to Windows/VSS SDK Tomoki Sekiyama
@ 2013-07-15 16:20 ` Tomoki Sekiyama
  2013-07-22 21:50   ` Michael Roth
  2013-07-15 16:20 ` [Qemu-devel] [PATCH v7 07/10] qemu-ga: Add Windows VSS provider and requester as DLL Tomoki Sekiyama
                   ` (4 subsequent siblings)
  10 siblings, 1 reply; 24+ messages in thread
From: Tomoki Sekiyama @ 2013-07-15 16:20 UTC (permalink / raw)
  To: qemu-devel
  Cc: libaiqing, ghammer, stefanha, mdroth, lcapitulino, vrozenfe,
	pbonzini, seiji.aguchi, lersek, areis

These functions help maintaining homogeneous formatting of error messages
with Windows error code and description (generated by
g_win32_error_message()).

Signed-off-by: Tomoki Sekiyama <tomoki.sekiyama@hds.com>
---
 include/qapi/error.h |   13 +++++++++++++
 util/error.c         |   35 +++++++++++++++++++++++++++++++++++
 2 files changed, 48 insertions(+)

diff --git a/include/qapi/error.h b/include/qapi/error.h
index ffd1cea..7d4c696 100644
--- a/include/qapi/error.h
+++ b/include/qapi/error.h
@@ -36,6 +36,15 @@ void error_set(Error **err, ErrorClass err_class, const char *fmt, ...) GCC_FMT_
  */
 void error_set_errno(Error **err, int os_error, ErrorClass err_class, const char *fmt, ...) GCC_FMT_ATTR(4, 5);
 
+#ifdef _WIN32
+/**
+ * Set an indirect pointer to an error given a ErrorClass value and a
+ * printf-style human message, followed by a g_win32_error_message() string if
+ * @win32_err is not zero.
+ */
+void error_set_win32(Error **err, int win32_err, ErrorClass err_class, const char *fmt, ...) GCC_FMT_ATTR(4, 5);
+#endif
+
 /**
  * Same as error_set(), but sets a generic error
  */
@@ -43,6 +52,10 @@ void error_set_errno(Error **err, int os_error, ErrorClass err_class, const char
     error_set(err, ERROR_CLASS_GENERIC_ERROR, fmt, ## __VA_ARGS__)
 #define error_setg_errno(err, os_error, fmt, ...) \
     error_set_errno(err, os_error, ERROR_CLASS_GENERIC_ERROR, fmt, ## __VA_ARGS__)
+#ifdef _WIN32
+#define error_setg_win32(err, win32_err, fmt, ...) \
+    error_set_win32(err, win32_err, ERROR_CLASS_GENERIC_ERROR, fmt, ## __VA_ARGS__)
+#endif
 
 /**
  * Helper for open() errors
diff --git a/util/error.c b/util/error.c
index 53b0435..ec0faa6 100644
--- a/util/error.c
+++ b/util/error.c
@@ -76,6 +76,41 @@ void error_setg_file_open(Error **errp, int os_errno, const char *filename)
     error_setg_errno(errp, os_errno, "Could not open '%s'", filename);
 }
 
+#ifdef _WIN32
+
+void error_set_win32(Error **errp, int win32_err, ErrorClass err_class,
+                     const char *fmt, ...)
+{
+    Error *err;
+    char *msg1;
+    va_list ap;
+
+    if (errp == NULL) {
+        return;
+    }
+    assert(*errp == NULL);
+
+    err = g_malloc0(sizeof(*err));
+
+    va_start(ap, fmt);
+    msg1 = g_strdup_vprintf(fmt, ap);
+    if (win32_err != 0) {
+        char *msg2 = g_win32_error_message(win32_err);
+        err->msg = g_strdup_printf("%s: %s (error: %x)", msg1, msg2,
+                                   (unsigned)win32_err);
+        g_free(msg2);
+        g_free(msg1);
+    } else {
+        err->msg = msg1;
+    }
+    va_end(ap);
+    err->err_class = err_class;
+
+    *errp = err;
+}
+
+#endif
+
 Error *error_copy(const Error *err)
 {
     Error *err_new;

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

* [Qemu-devel] [PATCH v7 07/10] qemu-ga: Add Windows VSS provider and requester as DLL
  2013-07-15 16:20 [Qemu-devel] [PATCH v7 00/10] qemu-ga: fsfreeze on Windows using VSS Tomoki Sekiyama
                   ` (5 preceding siblings ...)
  2013-07-15 16:20 ` [Qemu-devel] [PATCH v7 06/10] error: Add error_set_win32 and error_setg_win32 Tomoki Sekiyama
@ 2013-07-15 16:20 ` Tomoki Sekiyama
  2013-07-15 16:20 ` [Qemu-devel] [PATCH v7 08/10] qemu-ga: Call Windows VSS requester in fsfreeze command handler Tomoki Sekiyama
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 24+ messages in thread
From: Tomoki Sekiyama @ 2013-07-15 16:20 UTC (permalink / raw)
  To: qemu-devel
  Cc: libaiqing, ghammer, stefanha, mdroth, lcapitulino, vrozenfe,
	pbonzini, seiji.aguchi, lersek, areis

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

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

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

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

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

In several versions of Windows which don't support attribute
VSS_VOLSNAP_ATTR_NO_AUTORECOVERY, DoSnapshotSet fails with error
VSS_E_OBJECT_NOT_FOUND. In this patch, we just ignore this error.
To solve this fundamentally, we need a framework to handle mount writable
snapshot on guests, which is required by VSS auto-recovery feature
(cleanup phase after a snapshot is taken).

Signed-off-by: Tomoki Sekiyama <tomoki.sekiyama@hds.com>
---
 Makefile                    |    2 
 Makefile.objs               |    2 
 configure                   |    5 
 qga/Makefile.objs           |    4 
 qga/vss-win32/Makefile.objs |   23 ++
 qga/vss-win32/install.cpp   |  424 ++++++++++++++++++++++++++++++++++++
 qga/vss-win32/provider.cpp  |  513 +++++++++++++++++++++++++++++++++++++++++++
 qga/vss-win32/qga-vss.def   |   13 +
 qga/vss-win32/qga-vss.idl   |   20 ++
 qga/vss-win32/qga-vss.tlb   |  Bin
 qga/vss-win32/requester.cpp |  487 +++++++++++++++++++++++++++++++++++++++++
 qga/vss-win32/requester.h   |   42 ++++
 qga/vss-win32/vss-common.h  |  128 +++++++++++
 13 files changed, 1661 insertions(+), 2 deletions(-)
 create mode 100644 qga/vss-win32/Makefile.objs
 create mode 100644 qga/vss-win32/install.cpp
 create mode 100644 qga/vss-win32/provider.cpp
 create mode 100644 qga/vss-win32/qga-vss.def
 create mode 100644 qga/vss-win32/qga-vss.idl
 create mode 100644 qga/vss-win32/qga-vss.tlb
 create mode 100644 qga/vss-win32/requester.cpp
 create mode 100644 qga/vss-win32/requester.h
 create mode 100644 qga/vss-win32/vss-common.h

diff --git a/Makefile b/Makefile
index ec35a15..6b64cfb 100644
--- a/Makefile
+++ b/Makefile
@@ -236,7 +236,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/Makefile.objs b/Makefile.objs
index 5b288ba..ae541d1 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -103,6 +103,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-vss-dll-obj-y = qga/
 
 vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
 
@@ -114,6 +115,7 @@ nested-vars += \
 	stub-obj-y \
 	util-obj-y \
 	qga-obj-y \
+	qga-vss-dll-obj-y \
 	block-obj-y \
 	common-obj-y
 dummy := $(call unnest-vars)
diff --git a/configure b/configure
index 8e1147f..797c6d5 100755
--- a/configure
+++ b/configure
@@ -3497,9 +3497,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..4891732 100644
--- a/qga/Makefile.objs
+++ b/qga/Makefile.objs
@@ -3,3 +3,7 @@ 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)
+qga-vss-dll-obj-y += vss-win32/
+endif
diff --git a/qga/vss-win32/Makefile.objs b/qga/vss-win32/Makefile.objs
new file mode 100644
index 0000000..4dad964
--- /dev/null
+++ b/qga/vss-win32/Makefile.objs
@@ -0,0 +1,23 @@
+# rules to build qga-vss.dll
+
+qga-vss-dll-obj-y += requester.o provider.o install.o
+
+obj-qga-vss-dll-obj-y = $(addprefix $(obj)/, $(qga-vss-dll-obj-y))
+$(obj-qga-vss-dll-obj-y): QEMU_CXXFLAGS = $(filter-out -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Wold-style-declaration -Wold-style-definition -Wredundant-decls -fstack-protector-all, $(QEMU_CFLAGS)) -Wno-unknown-pragmas -Wno-delete-non-virtual-dtor
+
+$(obj)/qga-vss.dll: LDFLAGS = -shared -Wl,--add-stdcall-alias,--enable-stdcall-fixup -lole32 -loleaut32 -lshlwapi -luuid -static
+$(obj)/qga-vss.dll: $(obj-qga-vss-dll-obj-y) $(SRC_PATH)/$(obj)/qga-vss.def
+	$(call quiet-command,$(CXX) -o $@ $(qga-vss-dll-obj-y) $(SRC_PATH)/qga/vss-win32/qga-vss.def $(CXXFLAGS) $(LDFLAGS),"  LINK  $(TARGET_DIR)$@")
+
+
+# rules to build qga-provider.tlb
+# Currently, only native build is supported because building .tlb
+# (TypeLibrary) from .idl requires WindowsSDK and MIDL (and cl.exe in VC++).
+MIDL=$(WIN_SDK)/Bin/midl
+
+$(obj)/qga-vss.tlb: $(SRC_PATH)/$(obj)/qga-vss.idl
+ifeq ($(wildcard $(SRC_PATH)/$(obj)/qga-vss.tlb),)
+	$(call quiet-command,$(MIDL) -tlb $@ -I $(WIN_SDK)/Include $<,"  MIDL  $(TARGET_DIR)$@")
+else
+	$(call quiet-command,cp $(dir $<)qga-vss.tlb $@, "  COPY  $(TARGET_DIR)$@")
+endif
diff --git a/qga/vss-win32/install.cpp b/qga/vss-win32/install.cpp
new file mode 100644
index 0000000..4882f9f
--- /dev/null
+++ b/qga/vss-win32/install.cpp
@@ -0,0 +1,424 @@
+/*
+ * 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-common.h"
+#include "inc/win2003/vscoordint.h"
+
+#include <comadmin.h>
+#include <wbemidl.h>
+#include <comdef.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} };
+
+void errmsg(DWORD err, const char *text)
+{
+    /*
+     * `text' contains function call statement when errmsg is called via chk().
+     * To make error message more readable, we cut off the text after '('.
+     * If text doesn't contains '(', negative precision is given, which is
+     * treated as though it were missing.
+     */
+    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);
+    fprintf(stderr, "%.*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", 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)
+
+void __stdcall _com_issue_error(HRESULT hr)
+{
+    errmsg(hr, "Unexpected error in COM");
+}
+
+template<class T>
+HRESULT put_Value(ICatalogObject *pObj, LPCWSTR name, T val)
+{
+    return pObj->put_Value(_bstr_t(name), _variant_t(val));
+}
+
+/* Lookup Administrators group name from winmgmt */
+static HRESULT GetAdminName(_bstr_t *name)
+{
+    HRESULT hr;
+    COMPointer<IWbemLocator> pLoc;
+    COMPointer<IWbemServices> pSvc;
+    COMPointer<IEnumWbemClassObject> pEnum;
+    COMPointer<IWbemClassObject> pWobj;
+    ULONG returned;
+    _variant_t var;
+
+    chk(CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER,
+                         IID_IWbemLocator, (LPVOID *)pLoc.replace()));
+    chk(pLoc->ConnectServer(_bstr_t(L"ROOT\\CIMV2"), NULL, NULL, NULL,
+                            0, 0, 0, pSvc.replace()));
+    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.replace()));
+    if (!pEnum) {
+        hr = E_FAIL;
+        errmsg(hr, "Failed to query for Administrators");
+        goto out;
+    }
+    chk(pEnum->Next(WBEM_INFINITE, 1, pWobj.replace(), &returned));
+    if (returned == 0) {
+        hr = E_FAIL;
+        errmsg(hr, "No Administrators found");
+        goto out;
+    }
+
+    chk(pWobj->Get(_bstr_t(L"Name"), 0, &var, 0, 0));
+    try {
+        *name = var;
+    } catch(...) {
+        hr = E_FAIL;
+        errmsg(hr, "Failed to get name of Administrators");
+        goto out;
+    }
+
+out:
+    return hr;
+}
+
+
+/* Unregister this module from COM+ Applications Catalog */
+STDAPI COMUnregister(void)
+{
+    HRESULT hr;
+    COMInitializer initializer;
+    COMPointer<IUnknown> pUnknown;
+    COMPointer<ICOMAdminCatalog> pCatalog;
+    COMPointer<ICatalogCollection> pColl;
+    COMPointer<ICatalogObject> pObj;
+    _variant_t var;
+    long i, n;
+
+    DllUnregisterServer();
+
+    chk(CoCreateInstance(CLSID_COMAdminCatalog, NULL, CLSCTX_INPROC_SERVER,
+                         IID_IUnknown, (void **)pUnknown.replace()));
+    chk(pUnknown->QueryInterface(IID_ICOMAdminCatalog,
+                                 (void **)pCatalog.replace()));
+    chk(pCatalog->GetCollection(_bstr_t(L"Applications"),
+                                (IDispatch **)pColl.replace()));
+    chk(pColl->Populate());
+
+    chk(pColl->get_Count(&n));
+    for (i = n - 1; i >= 0; i--) {
+        chk(pColl->get_Item(i, (IDispatch **)pObj.replace()));
+        chk(pObj->get_Value(_bstr_t(L"Name"), &var));
+        if (var == _variant_t(QGA_PROVIDER_LNAME)) {
+            fprintf(stderr, "Removing COM+ Application: %S\n",
+                    (wchar_t *)_bstr_t(var));
+            chk(pColl->Remove(i));
+        }
+    }
+    chk(pColl->SaveChanges(&n));
+
+out:
+    return hr;
+}
+
+/* Register this module to COM+ Applications Catalog */
+STDAPI COMRegister(void)
+{
+    HRESULT hr = E_FAIL;
+    COMInitializer initializer;
+    COMPointer<IUnknown> pUnknown;
+    COMPointer<ICOMAdminCatalog> pCatalog;
+    COMPointer<ICatalogCollection> pApps, pRoles, pUsersInRole;
+    COMPointer<ICatalogObject> pObj;
+    long n;
+    _bstr_t name;
+    _variant_t key;
+    CHAR dllPath[MAX_PATH], tlbPath[MAX_PATH];
+    bool unregisterOnFailure = false;
+
+    if (!g_hinstDll) {
+        errmsg(E_FAIL, "Failed to initialize DLL");
+        return E_FAIL;
+    }
+
+    chk(CoCreateInstance(CLSID_COMAdminCatalog, NULL, CLSCTX_INPROC_SERVER,
+                         IID_IUnknown, (void **)pUnknown.replace()));
+    chk(pUnknown->QueryInterface(IID_ICOMAdminCatalog,
+                                 (void **)pCatalog.replace()));
+
+    /* Install COM+ Component */
+
+    chk(pCatalog->GetCollection(_bstr_t(L"Applications"),
+                                (IDispatch **)pApps.replace()));
+    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));
+
+    /* The app should be deleted if something fails after SaveChanges */
+    unregisterOnFailure = true;
+
+    chk(pObj->get_Key(&key));
+
+    if (!GetModuleFileName(g_hinstDll, dllPath, sizeof(dllPath))) {
+        hr = HRESULT_FROM_WIN32(GetLastError());
+        errmsg(hr, "GetModuleFileName failed");
+        goto out;
+    }
+    n = strlen(dllPath);
+    if (n < 3) {
+        hr = E_FAIL;
+        errmsg(hr, "Failed to lookup dll");
+        goto out;
+    }
+    strcpy(tlbPath, dllPath);
+    strcpy(tlbPath+n-3, "tlb");
+    fprintf(stderr, "Registering " QGA_PROVIDER_NAME ":\n");
+    fprintf(stderr, "  %s\n", dllPath);
+    fprintf(stderr, "  %s\n", tlbPath);
+    if (!PathFileExists(tlbPath)) {
+        hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
+        errmsg(hr, "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.replace()));
+    chk(pRoles->Populate());
+    chk(pRoles->Add((IDispatch **)pObj.replace()));
+    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));
+
+    /* Setup users in the role */
+
+    chk(pRoles->GetCollection(_bstr_t(L"UsersInRole"), key,
+                              (IDispatch **)pUsersInRole.replace()));
+    chk(pUsersInRole->Populate());
+
+    chk(pUsersInRole->Add((IDispatch **)pObj.replace()));
+    chk(GetAdminName(&name));
+    chk(put_Value(pObj, L"User", _bstr_t(".\\") + name));
+
+    chk(pUsersInRole->Add((IDispatch **)pObj.replace()));
+    chk(put_Value(pObj, L"User", L"SYSTEM"));
+    chk(pUsersInRole->SaveChanges(&n));
+
+out:
+    if (unregisterOnFailure && FAILED(hr)) {
+        COMUnregister();
+    }
+
+    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 = strlen(data) + 1;
+    } else {
+        size = 0;
+    }
+
+    ret = RegSetValueEx(hKey, value, 0, REG_SZ, (LPBYTE)data, size);
+    RegCloseKey(hKey);
+
+out:
+    if (ret != ERROR_SUCCESS) {
+        /* As we cannot printf within DllRegisterServer(), show a dialog. */
+        errmsg_dialog(ret, "Cannot add registry", key);
+        return FALSE;
+    }
+    return TRUE;
+}
+
+/* Register this dll as a VSS provider */
+STDAPI DllRegisterServer(void)
+{
+    COMInitializer initializer;
+    COMPointer<IVssAdmin> pVssAdmin;
+    HRESULT hr = E_FAIL;
+    char dllPath[MAX_PATH];
+    char key[256];
+
+    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;
+    }
+
+    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.replace());
+    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");
+    }
+
+out:
+    if (FAILED(hr)) {
+        DllUnregisterServer();
+    }
+
+    return hr;
+}
+
+/* Unregister this VSS hardware provider from the system */
+STDAPI DllUnregisterServer(void)
+{
+    TCHAR key[256];
+    COMInitializer initializer;
+    COMPointer<IVssAdmin> pVssAdmin;
+
+    HRESULT hr = CoCreateInstance(CLSID_VSSCoordinator,
+                                  NULL, CLSCTX_ALL, IID_IVssAdmin,
+                                  (void **)pVssAdmin.replace());
+    if (SUCCEEDED(hr)) {
+        hr = pVssAdmin->UnregisterProvider(g_gProviderId);
+    } else {
+        errmsg(hr, "CoCreateInstance(VSSCoordinator) failed");
+    }
+
+    sprintf(key, "CLSID\\%s", g_szClsid);
+    SHDeleteKey(HKEY_CLASSES_ROOT, key);
+    SHDeleteKey(HKEY_CLASSES_ROOT, g_szProgid);
+
+    return S_OK; /* Uninstall should never fail */
+}
+
+
+/* Support function to convert ASCII string into BSTR (used in _bstr_t) */
+namespace _com_util
+{
+    BSTR WINAPI ConvertStringToBSTR(const char *ascii) {
+        int len = strlen(ascii);
+        BSTR bstr = SysAllocStringLen(NULL, len);
+
+        if (!bstr) {
+            return NULL;
+        }
+
+        if (mbstowcs(bstr, ascii, len) == (size_t)-1) {
+            fprintf(stderr, "Failed to convert string '%s' into BSTR", ascii);
+            bstr[0] = 0;
+        }
+        return bstr;
+    }
+}
diff --git a/qga/vss-win32/provider.cpp b/qga/vss-win32/provider.cpp
new file mode 100644
index 0000000..e39526a
--- /dev/null
+++ b/qga/vss-win32/provider.cpp
@@ -0,0 +1,513 @@
+/*
+ * 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-common.h"
+#include "inc/win2003/vscoordint.h"
+#include "inc/win2003/vsprov.h"
+
+#define VSS_TIMEOUT_MSEC (60*1000)
+
+static long g_nComObjsInUse;
+HINSTANCE g_hinstDll;
+
+/* 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 lock)
+{
+    if (lock) {
+        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;
+    }
+    if (riid == IID_IVssSoftwareSnapshotProvider) {
+        *ppObj = static_cast<void*>(
+            static_cast<IVssSoftwareSnapshotProvider*>(this));
+        AddRef();
+        return S_OK;
+    }
+    if (riid == IID_IVssProviderCreateSnapshotSet) {
+        *ppObj = static_cast<void*>(
+            static_cast<IVssProviderCreateSnapshotSet*>(this));
+        AddRef();
+        return S_OK;
+    }
+    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)
+{
+    try {
+        *ppEnum = new CQGAVSSEnumObject;
+    } catch (...) {
+        return E_OUTOFMEMORY;
+    }
+    (*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)
+{
+    *pbSnapshotsPresent = FALSE;
+    *plSnapshotCompatibility = 0;
+    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 E_NOTIMPL;
+}
+
+
+/*
+ * 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 hEventFrozen, hEventThaw;
+
+    hEventFrozen = OpenEvent(EVENT_ALL_ACCESS, FALSE, EVENT_NAME_FROZEN);
+    if (hEventFrozen == INVALID_HANDLE_VALUE) {
+        return E_FAIL;
+    }
+
+    hEventThaw = OpenEvent(EVENT_ALL_ACCESS, FALSE, EVENT_NAME_THAW);
+    if (hEventThaw == INVALID_HANDLE_VALUE) {
+        CloseHandle(hEventFrozen);
+        return E_FAIL;
+    }
+
+    /* Send event to qemu-ga to notify filesystem is frozen */
+    SetEvent(hEventFrozen);
+
+    /* Wait until the snapshot is taken by the host. */
+    if (WaitForSingleObject(hEventThaw, VSS_TIMEOUT_MSEC) != WAIT_OBJECT_0) {
+        hr = E_ABORT;
+    }
+
+    CloseHandle(hEventThaw);
+    CloseHandle(hEventFrozen);
+    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 lock) { return E_NOTIMPL; }
+
+    CQGAVssProviderFactory();
+    ~CQGAVssProviderFactory();
+
+private:
+    long m_nRefCount;
+};
+
+CQGAVssProviderFactory::CQGAVssProviderFactory()
+{
+    m_nRefCount = 0;
+    LockModule(TRUE);
+}
+
+CQGAVssProviderFactory::~CQGAVssProviderFactory()
+{
+    LockModule(FALSE);
+}
+
+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()
+{
+    return InterlockedIncrement(&m_nRefCount);
+}
+
+STDMETHODIMP_(ULONG) CQGAVssProviderFactory::Release()
+{
+    long nRefCount = InterlockedDecrement(&m_nRefCount);
+    if (m_nRefCount == 0) {
+        delete this;
+    }
+    return nRefCount;
+}
+
+STDMETHODIMP CQGAVssProviderFactory::CreateInstance(
+    IUnknown *pUnknownOuter, REFIID iid, void **ppv)
+{
+    CQGAVssProvider *pObj;
+
+    if (pUnknownOuter) {
+        return CLASS_E_NOAGGREGATION;
+    }
+    try {
+        pObj = new CQGAVssProvider;
+    } catch (...) {
+        return E_OUTOFMEMORY;
+    }
+    HRESULT hr = pObj->QueryInterface(iid, ppv);
+    if (FAILED(hr)) {
+        delete pObj;
+    }
+    return hr;
+}
+
+
+/*
+ * DLL functions
+ */
+
+STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
+{
+    CQGAVssProviderFactory *factory;
+    try {
+        factory = new CQGAVssProviderFactory;
+    } catch (...) {
+        return E_OUTOFMEMORY;
+    }
+    factory->AddRef();
+    HRESULT hr = factory->QueryInterface(riid, ppv);
+    factory->Release();
+    return hr;
+}
+
+STDAPI DllCanUnloadNow()
+{
+    return g_nComObjsInUse == 0 ? S_OK : S_FALSE;
+}
+
+EXTERN_C
+BOOL WINAPI DllMain(HINSTANCE hinstDll, DWORD dwReason, LPVOID lpReserved)
+{
+    if (dwReason == DLL_PROCESS_ATTACH) {
+        g_hinstDll = hinstDll;
+        DisableThreadLibraryCalls(hinstDll);
+    }
+    return TRUE;
+}
diff --git a/qga/vss-win32/qga-vss.def b/qga/vss-win32/qga-vss.def
new file mode 100644
index 0000000..927782c
--- /dev/null
+++ b/qga/vss-win32/qga-vss.def
@@ -0,0 +1,13 @@
+LIBRARY      "QGA-PROVIDER.DLL"
+
+EXPORTS
+	COMRegister		PRIVATE
+	COMUnregister		PRIVATE
+	DllCanUnloadNow		PRIVATE
+	DllGetClassObject	PRIVATE
+	DllRegisterServer	PRIVATE
+	DllUnregisterServer	PRIVATE
+	requester_init		PRIVATE
+	requester_deinit	PRIVATE
+	requester_freeze	PRIVATE
+	requester_thaw		PRIVATE
diff --git a/qga/vss-win32/qga-vss.idl b/qga/vss-win32/qga-vss.idl
new file mode 100644
index 0000000..17abca0
--- /dev/null
+++ b/qga/vss-win32/qga-vss.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/qga-vss.tlb b/qga/vss-win32/qga-vss.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

diff --git a/qga/vss-win32/requester.cpp b/qga/vss-win32/requester.cpp
new file mode 100644
index 0000000..1b91ca5
--- /dev/null
+++ b/qga/vss-win32/requester.cpp
@@ -0,0 +1,487 @@
+/*
+ * 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 "vss-common.h"
+#include "requester.h"
+#include "assert.h"
+#include "inc/win2003/vswriter.h"
+#include "inc/win2003/vsbackup.h"
+
+/* Max wait time for frozen event (VSS can only hold writes for 10 seconds) */
+#define VSS_TIMEOUT_FREEZE_MSEC 10000
+
+/* Call QueryStatus every 10 ms while waiting for frozen event */
+#define VSS_TIMEOUT_EVENT_MSEC 10
+
+#define err_set(e, err, fmt, ...) \
+    ((e)->error_set((e)->errp, err, (e)->err_class, fmt, ## __VA_ARGS__))
+#define err_is_set(e) ((e)->errp && *(e)->errp)
+
+
+/* Handle to VSSAPI.DLL */
+static HMODULE hLib;
+
+/* Functions in VSSAPI.DLL */
+typedef HRESULT(STDAPICALLTYPE * t_CreateVssBackupComponents)(
+    OUT IVssBackupComponents**);
+typedef void(APIENTRY * t_VssFreeSnapshotProperties)(IN VSS_SNAPSHOT_PROP*);
+static t_CreateVssBackupComponents pCreateVssBackupComponents;
+static t_VssFreeSnapshotProperties pVssFreeSnapshotProperties;
+
+/* Variables used while applications and filesystes are frozen by VSS */
+static struct QGAVSSContext {
+    IVssBackupComponents *pVssbc;  /* VSS requester interface */
+    IVssAsync *pAsyncSnapshot;     /* async info of VSS snapshot operation */
+    HANDLE hEventFrozen;           /* frozen event from qga-provider.dll */
+    HANDLE hEventThaw;             /* thaw event to qga-provider.dll */
+    int cFrozenVols;               /* number of frozen volumes */
+} vss_ctx;
+
+STDAPI requester_init(void)
+{
+    vss_ctx.hEventFrozen = vss_ctx.hEventThaw = INVALID_HANDLE_VALUE;
+
+    COMInitializer initializer; /* to call CoInitializeSecurity */
+    HRESULT hr = CoInitializeSecurity(
+        NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
+        RPC_C_IMP_LEVEL_IDENTIFY, NULL, EOAC_NONE, NULL);
+    if (FAILED(hr)) {
+        fprintf(stderr, "failed to CoInitializeSecurity (error %lx)\n", hr);
+        return hr;
+    }
+
+    hLib = LoadLibraryA("VSSAPI.DLL");
+    if (!hLib) {
+        fprintf(stderr, "failed to load VSSAPI.DLL\n");
+        return HRESULT_FROM_WIN32(GetLastError());
+    }
+
+    pCreateVssBackupComponents = (t_CreateVssBackupComponents)
+        GetProcAddress(hLib,
+#ifdef _WIN64 /* 64bit environment */
+        "?CreateVssBackupComponents@@YAJPEAPEAVIVssBackupComponents@@@Z"
+#else /* 32bit environment */
+        "?CreateVssBackupComponents@@YGJPAPAVIVssBackupComponents@@@Z"
+#endif
+        );
+    if (!pCreateVssBackupComponents) {
+        fprintf(stderr, "failed to get proc address from VSSAPI.DLL\n");
+        return HRESULT_FROM_WIN32(GetLastError());
+    }
+
+    pVssFreeSnapshotProperties = (t_VssFreeSnapshotProperties)
+        GetProcAddress(hLib, "VssFreeSnapshotProperties");
+    if (!pVssFreeSnapshotProperties) {
+        fprintf(stderr, "failed to get proc address from VSSAPI.DLL\n");
+        return HRESULT_FROM_WIN32(GetLastError());
+    }
+
+    return S_OK;
+}
+
+static void requester_cleanup(void)
+{
+    if (vss_ctx.hEventFrozen != INVALID_HANDLE_VALUE) {
+        CloseHandle(vss_ctx.hEventFrozen);
+        vss_ctx.hEventFrozen = INVALID_HANDLE_VALUE;
+    }
+    if (vss_ctx.hEventThaw != INVALID_HANDLE_VALUE) {
+        CloseHandle(vss_ctx.hEventThaw);
+        vss_ctx.hEventThaw = INVALID_HANDLE_VALUE;
+    }
+    if (vss_ctx.pAsyncSnapshot) {
+        vss_ctx.pAsyncSnapshot->Release();
+        vss_ctx.pAsyncSnapshot = NULL;
+    }
+    if (vss_ctx.pVssbc) {
+        vss_ctx.pVssbc->Release();
+        vss_ctx.pVssbc = NULL;
+    }
+    vss_ctx.cFrozenVols = 0;
+}
+
+STDAPI requester_deinit(void)
+{
+    requester_cleanup();
+
+    pCreateVssBackupComponents = NULL;
+    pVssFreeSnapshotProperties = NULL;
+    if (hLib) {
+        FreeLibrary(hLib);
+        hLib = NULL;
+    }
+
+    return S_OK;
+}
+
+static 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;
+}
+
+static void AddComponents(ErrorSet *errset)
+{
+    unsigned int cWriters, i;
+    VSS_ID id, idInstance, idWriter;
+    BSTR bstrWriterName = NULL;
+    VSS_USAGE_TYPE usage;
+    VSS_SOURCE_TYPE source;
+    unsigned int cComponents, c1, c2, j;
+    COMPointer<IVssExamineWriterMetadata> pMetadata;
+    COMPointer<IVssWMComponent> pComponent;
+    PVSSCOMPONENTINFO info;
+    HRESULT hr;
+
+    hr = vss_ctx.pVssbc->GetWriterMetadataCount(&cWriters);
+    if (FAILED(hr)) {
+        err_set(errset, hr, "failed to get writer metadata count");
+        goto out;
+    }
+
+    for (i = 0; i < cWriters; i++) {
+        hr = vss_ctx.pVssbc->GetWriterMetadata(i, &id, pMetadata.replace());
+        if (FAILED(hr)) {
+            err_set(errset, hr, "failed to get writer metadata of %d/%d",
+                             i, cWriters);
+            goto out;
+        }
+
+        hr = pMetadata->GetIdentity(&idInstance, &idWriter,
+                                    &bstrWriterName, &usage, &source);
+        if (FAILED(hr)) {
+            err_set(errset, hr, "failed to get identity of writer %d/%d",
+                             i, cWriters);
+            goto out;
+        }
+
+        hr = pMetadata->GetFileCounts(&c1, &c2, &cComponents);
+        if (FAILED(hr)) {
+            err_set(errset, hr, "failed to get file counts of %S",
+                             bstrWriterName);
+            goto out;
+        }
+
+        for (j = 0; j < cComponents; j++) {
+            hr = pMetadata->GetComponent(j, pComponent.replace());
+            if (FAILED(hr)) {
+                err_set(errset, hr,
+                                 "failed to get component %d/%d of %S",
+                                 j, cComponents, bstrWriterName);
+                goto out;
+            }
+
+            hr = pComponent->GetComponentInfo(&info);
+            if (FAILED(hr)) {
+                err_set(errset, hr,
+                                 "failed to get component info %d/%d of %S",
+                                 j, cComponents, bstrWriterName);
+                goto out;
+            }
+
+            if (info->bSelectable) {
+                hr = vss_ctx.pVssbc->AddComponent(idInstance, idWriter,
+                                                  info->type,
+                                                  info->bstrLogicalPath,
+                                                  info->bstrComponentName);
+                if (FAILED(hr)) {
+                    err_set(errset, hr, "failed to add component %S(%S)",
+                                     info->bstrComponentName, bstrWriterName);
+                    goto out;
+                }
+            }
+            SysFreeString(bstrWriterName);
+            bstrWriterName = NULL;
+            pComponent->FreeComponentInfo(info);
+            info = NULL;
+        }
+    }
+out:
+    if (bstrWriterName) {
+        SysFreeString(bstrWriterName);
+    }
+    if (pComponent && info) {
+        pComponent->FreeComponentInfo(info);
+    }
+}
+
+void requester_freeze(int *num_vols, ErrorSet *errset)
+{
+    COMPointer<IVssAsync> pAsync;
+    HANDLE volume;
+    HRESULT hr;
+    LONG ctx;
+    GUID guidSnapshotSet = GUID_NULL;
+    SECURITY_DESCRIPTOR sd;
+    SECURITY_ATTRIBUTES sa;
+    WCHAR short_volume_name[64], *display_name = short_volume_name;
+    DWORD wait_status;
+    int num_fixed_drives = 0, i;
+
+    if (vss_ctx.pVssbc) { /* already frozen */
+        *num_vols = 0;
+        return;
+    }
+
+    CoInitialize(NULL);
+
+    assert(pCreateVssBackupComponents != NULL);
+    hr = pCreateVssBackupComponents(&vss_ctx.pVssbc);
+    if (FAILED(hr)) {
+        err_set(errset, hr, "failed to create VSS backup components");
+        goto out;
+    }
+
+    hr = vss_ctx.pVssbc->InitializeForBackup();
+    if (FAILED(hr)) {
+        err_set(errset, hr, "failed to initialize for backup");
+        goto out;
+    }
+
+    hr = vss_ctx.pVssbc->SetBackupState(true, true, VSS_BT_FULL, false);
+    if (FAILED(hr)) {
+        err_set(errset, hr, "failed to set backup state");
+        goto out;
+    }
+
+    /*
+     * Currently writable snapshots are not supported.
+     * To prevent the final commit (which requires to write to snapshots),
+     * ATTR_NO_AUTORECOVERY and ATTR_TRANSPORTABLE are specified here.
+     */
+    ctx = VSS_CTX_APP_ROLLBACK | VSS_VOLSNAP_ATTR_TRANSPORTABLE |
+        VSS_VOLSNAP_ATTR_NO_AUTORECOVERY | VSS_VOLSNAP_ATTR_TXF_RECOVERY;
+    hr = vss_ctx.pVssbc->SetContext(ctx);
+    if (hr == (HRESULT)VSS_E_UNSUPPORTED_CONTEXT) {
+        /* Non-server version of Windows doesn't support ATTR_TRANSPORTABLE */
+        ctx &= ~VSS_VOLSNAP_ATTR_TRANSPORTABLE;
+        hr = vss_ctx.pVssbc->SetContext(ctx);
+    }
+    if (FAILED(hr)) {
+        err_set(errset, hr, "failed to set backup context");
+        goto out;
+    }
+
+    hr = vss_ctx.pVssbc->GatherWriterMetadata(pAsync.replace());
+    if (SUCCEEDED(hr)) {
+        hr = WaitForAsync(pAsync);
+    }
+    if (FAILED(hr)) {
+        err_set(errset, hr, "failed to gather writer metadata");
+        goto out;
+    }
+
+    AddComponents(errset);
+    if (err_is_set(errset)) {
+        goto out;
+    }
+
+    hr = vss_ctx.pVssbc->StartSnapshotSet(&guidSnapshotSet);
+    if (FAILED(hr)) {
+        err_set(errset, hr, "failed to start snapshot set");
+        goto out;
+    }
+
+    volume = FindFirstVolumeW(short_volume_name, sizeof(short_volume_name));
+    if (volume == INVALID_HANDLE_VALUE) {
+        err_set(errset, hr, "failed to find first volume");
+        goto out;
+    }
+    for (;;) {
+        if (GetDriveTypeW(short_volume_name) == DRIVE_FIXED) {
+            VSS_ID pid;
+            hr = vss_ctx.pVssbc->AddToSnapshotSet(short_volume_name,
+                                                  g_gProviderId, &pid);
+            if (FAILED(hr)) {
+                WCHAR volume_path_name[PATH_MAX];
+                if (GetVolumePathNamesForVolumeNameW(
+                        short_volume_name, volume_path_name,
+                        sizeof(volume_path_name), NULL) && *volume_path_name) {
+                    display_name = volume_path_name;
+                }
+                err_set(errset, hr, "failed to add %S to snapshot set",
+                                 display_name);
+                FindVolumeClose(volume);
+                goto out;
+            }
+            num_fixed_drives++;
+        }
+        if (!FindNextVolumeW(volume, short_volume_name,
+                             sizeof(short_volume_name))) {
+            FindVolumeClose(volume);
+            break;
+        }
+    }
+
+    if (num_fixed_drives == 0) {
+        goto out; /* If there is no fixed drive, just exit. */
+    }
+
+    hr = vss_ctx.pVssbc->PrepareForBackup(pAsync.replace());
+    if (SUCCEEDED(hr)) {
+        hr = WaitForAsync(pAsync);
+    }
+    if (FAILED(hr)) {
+        err_set(errset, hr, "failed to prepare for backup");
+        goto out;
+    }
+
+    hr = vss_ctx.pVssbc->GatherWriterStatus(pAsync.replace());
+    if (SUCCEEDED(hr)) {
+        hr = WaitForAsync(pAsync);
+    }
+    if (FAILED(hr)) {
+        err_set(errset, hr, "failed to gather writer status");
+        goto out;
+    }
+
+    /* 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;
+
+    vss_ctx.hEventFrozen = CreateEvent(&sa, TRUE, FALSE, EVENT_NAME_FROZEN);
+    if (vss_ctx.hEventFrozen == INVALID_HANDLE_VALUE) {
+        err_set(errset, GetLastError(), "failed to create event %s",
+                         EVENT_NAME_FROZEN);
+        goto out;
+    }
+    vss_ctx.hEventThaw = CreateEvent(&sa, TRUE, FALSE, EVENT_NAME_THAW);
+    if (vss_ctx.hEventThaw == INVALID_HANDLE_VALUE) {
+        err_set(errset, GetLastError(), "failed to create event %s",
+                         EVENT_NAME_THAW);
+        goto out;
+    }
+
+    /*
+     * Start VSS quiescing operations.
+     * CQGAVssProvider::CommitSnapshots will kick vss_ctx.hEventFrozen
+     * after the applications and filesystems are frozen.
+     */
+    hr = vss_ctx.pVssbc->DoSnapshotSet(&vss_ctx.pAsyncSnapshot);
+    if (FAILED(hr)) {
+        err_set(errset, hr, "failed to do snapshot set");
+        goto out;
+    }
+
+    /* Need to call QueryStatus several times to make VSS provider progress */
+    for (i = 0; i < VSS_TIMEOUT_FREEZE_MSEC/VSS_TIMEOUT_EVENT_MSEC; i++) {
+        HRESULT hr2 = vss_ctx.pAsyncSnapshot->QueryStatus(&hr, NULL);
+        if (FAILED(hr2)) {
+            err_set(errset, hr, "failed to do snapshot set");
+            goto out;
+        }
+        if (hr != VSS_S_ASYNC_PENDING) {
+            err_set(errset, E_FAIL,
+                    "DoSnapshotSet exited without Frozen event");
+            goto out;
+        }
+        wait_status = WaitForSingleObject(vss_ctx.hEventFrozen,
+                                          VSS_TIMEOUT_EVENT_MSEC);
+        if (wait_status != WAIT_TIMEOUT) {
+            break;
+        }
+    }
+    if (wait_status != WAIT_OBJECT_0) {
+        err_set(errset, E_FAIL,
+                "Couldn't receive Frozen event from VSS provider");
+        goto out;
+    }
+
+    *num_vols = vss_ctx.cFrozenVols = num_fixed_drives;
+    return;
+
+out:
+    if (vss_ctx.pVssbc) {
+        vss_ctx.pVssbc->AbortBackup();
+    }
+    requester_cleanup();
+    CoUninitialize();
+}
+
+
+void requester_thaw(int *num_vols, ErrorSet *errset)
+{
+    COMPointer<IVssAsync> pAsync;
+
+    if (vss_ctx.hEventThaw == 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;
+    }
+
+    /* Tell the provider that the snapshot is finished. */
+    SetEvent(vss_ctx.hEventThaw);
+
+    assert(vss_ctx.pVssbc);
+    assert(vss_ctx.pAsyncSnapshot);
+
+    HRESULT hr = WaitForAsync(vss_ctx.pAsyncSnapshot);
+    switch (hr) {
+    case VSS_S_ASYNC_FINISHED:
+        hr = vss_ctx.pVssbc->BackupComplete(pAsync.replace());
+        if (SUCCEEDED(hr)) {
+            hr = WaitForAsync(pAsync);
+        }
+        if (FAILED(hr)) {
+            err_set(errset, hr, "failed to complete backup");
+        }
+        break;
+
+    case (HRESULT)VSS_E_OBJECT_NOT_FOUND:
+        /*
+         * On Windows earlier than 2008 SP2 which does not support
+         * VSS_VOLSNAP_ATTR_NO_AUTORECOVERY context, the final commit is not
+         * skipped and VSS is aborted by VSS_E_OBJECT_NOT_FOUND. However, as
+         * the system had been frozen until fsfreeze-thaw command was issued,
+         * we ignore this error.
+         */
+        vss_ctx.pVssbc->AbortBackup();
+        break;
+
+    case (HRESULT)VSS_E_HOLD_WRITES_TIMEOUT:
+        err_set(errset, hr, "couldn't hold writes: "
+                         "fsfreeze is limited up to 10 seconds");
+        break;
+
+    default:
+        err_set(errset, hr, "failed to do snapshot set");
+    }
+
+    if (err_is_set(errset)) {
+        vss_ctx.pVssbc->AbortBackup();
+    }
+    *num_vols = vss_ctx.cFrozenVols;
+    requester_cleanup();
+
+    CoUninitialize();
+}
diff --git a/qga/vss-win32/requester.h b/qga/vss-win32/requester.h
new file mode 100644
index 0000000..ccd197c
--- /dev/null
+++ b/qga/vss-win32/requester.h
@@ -0,0 +1,42 @@
+/*
+ * QEMU Guest Agent VSS requester declarations
+ *
+ * Copyright Hitachi Data Systems Corp. 2013
+ *
+ * Authors:
+ *  Tomoki Sekiyama   <tomoki.sekiyama@hds.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef VSS_WIN32_REQUESTER_H
+#define VSS_WIN32_REQUESTER_H
+
+#include "qemu/compiler.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Callback to set Error; used to avoid linking glib to the DLL */
+typedef void (*ErrorSetFunc)(void **errp, int win32_err, int err_class,
+                             const char *fmt, ...) GCC_FMT_ATTR(4, 5);
+typedef struct ErrorSet {
+    ErrorSetFunc error_set;
+    void **errp;
+    int err_class;
+} ErrorSet;
+
+STDAPI requester_init(void);
+STDAPI requester_deinit(void);
+
+typedef void (*QGAVSSReuqesterFunc)(int *, ErrorSet *);
+void requester_freeze(int *num_vols, ErrorSet *errset);
+void requester_thaw(int *num_vols, ErrorSet *errset);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/qga/vss-win32/vss-common.h b/qga/vss-win32/vss-common.h
new file mode 100644
index 0000000..3637e8d
--- /dev/null
+++ b/qga/vss-win32/vss-common.h
@@ -0,0 +1,128 @@
+/*
+ * QEMU Guest Agent win32 VSS common declarations
+ *
+ * Copyright Hitachi Data Systems Corp. 2013
+ *
+ * Authors:
+ *  Tomoki Sekiyama   <tomoki.sekiyama@hds.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef VSS_WIN32_H
+#define VSS_WIN32_H
+
+#define __MIDL_user_allocate_free_DEFINED__
+#include "config-host.h"
+#include <windows.h>
+#include <shlwapi.h>
+
+/* Reduce warnings to include vss.h */
+
+/* Ignore annotations for MS IDE */
+#define __in  IN
+#define __out OUT
+#define __RPC_unique_pointer
+#define __RPC_string
+#define __RPC__deref_inout_opt
+#define __RPC__out
+#ifndef __RPC__out_ecount_part
+#define __RPC__out_ecount_part(x, y)
+#endif
+#define _declspec(x)
+#undef uuid
+#define uuid(x)
+
+/* Undef some duplicated error codes redefined in vss.h */
+#undef VSS_E_BAD_STATE
+#undef VSS_E_PROVIDER_NOT_REGISTERED
+#undef VSS_E_PROVIDER_VETO
+#undef VSS_E_OBJECT_NOT_FOUND
+#undef VSS_E_VOLUME_NOT_SUPPORTED
+#undef VSS_E_VOLUME_NOT_SUPPORTED_BY_PROVIDER
+#undef VSS_E_OBJECT_ALREADY_EXISTS
+#undef VSS_E_UNEXPECTED_PROVIDER_ERROR
+#undef VSS_E_INVALID_XML_DOCUMENT
+#undef VSS_E_MAXIMUM_NUMBER_OF_VOLUMES_REACHED
+#undef VSS_E_MAXIMUM_NUMBER_OF_SNAPSHOTS_REACHED
+
+/*
+ * VSS headers must be installed from Microsoft VSS SDK 7.2 available at:
+ * http://www.microsoft.com/en-us/download/details.aspx?id=23490
+ */
+#include "inc/win2003/vss.h"
+
+/* Macros to convert char definitions to wchar */
+#define _L(a) L##a
+#define L(a) _L(a)
+
+/* Constants for QGA VSS Provider */
+
+#define QGA_PROVIDER_NAME "QEMU Guest Agent VSS Provider"
+#define QGA_PROVIDER_LNAME L(QGA_PROVIDER_NAME)
+#define QGA_PROVIDER_VERSION L(QEMU_VERSION)
+
+#define EVENT_NAME_FROZEN "Global\\QGAVSSEvent-frozen"
+#define EVENT_NAME_THAW   "Global\\QGAVSSEvent-thaw"
+
+const GUID g_gProviderId = { 0x3629d4ed, 0xee09, 0x4e0e,
+    {0x9a, 0x5c, 0x6d, 0x8b, 0xa2, 0x87, 0x2a, 0xef} };
+const GUID g_gProviderVersion = { 0x11ef8b15, 0xcac6, 0x40d6,
+    {0x8d, 0x5c, 0x8f, 0xfc, 0x16, 0x3f, 0x24, 0xca} };
+
+const CLSID CLSID_QGAVSSProvider = { 0x6e6a3492, 0x8d4d, 0x440c,
+    {0x96, 0x19, 0x5e, 0x5d, 0x0c, 0xc3, 0x1c, 0xa8} };
+
+const TCHAR g_szClsid[] = TEXT("{6E6A3492-8D4D-440C-9619-5E5D0CC31CA8}");
+const TCHAR g_szProgid[] = TEXT("QGAVSSProvider");
+
+/* Enums undefined in VSS SDK 7.2 but defined in newer Windows SDK */
+enum __VSS_VOLUME_SNAPSHOT_ATTRIBUTES {
+    VSS_VOLSNAP_ATTR_NO_AUTORECOVERY       = 0x00000002,
+    VSS_VOLSNAP_ATTR_TXF_RECOVERY          = 0x02000000
+};
+
+
+/* COM pointer utility; call ->Release() when it goes out of scope */
+template <class T>
+class COMPointer {
+    COMPointer(const COMPointer<T> &p) { } /* no copy */
+    T *p;
+public:
+    COMPointer &operator=(T *new_p)
+    {
+        /* Assignment of a new T* (or NULL) causes release of previous p */
+        if (p && p != new_p) {
+            p->Release();
+        }
+        p = new_p;
+        return *this;
+    }
+    /* Replace by assignment to the pointer of p  */
+    T **replace(void)
+    {
+        *this = NULL;
+        return &p;
+    }
+    /* Make COMPointer be used like T* */
+    operator T*() { return p; }
+    T *operator->(void) { return p; }
+    T &operator*(void) { return *p; }
+    operator bool() { return !!p; }
+
+    COMPointer(T *p = NULL) : p(p) { }
+    ~COMPointer() { *this = NULL; }  /* Automatic release */
+};
+
+/*
+ * COM initializer; this should declared before COMPointer to uninitialize COM
+ * after releasing COM objects.
+ */
+class COMInitializer {
+public:
+    COMInitializer() { CoInitialize(NULL); }
+    ~COMInitializer() { CoUninitialize(); }
+};
+
+#endif

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

* [Qemu-devel] [PATCH v7 08/10] qemu-ga: Call Windows VSS requester in fsfreeze command handler
  2013-07-15 16:20 [Qemu-devel] [PATCH v7 00/10] qemu-ga: fsfreeze on Windows using VSS Tomoki Sekiyama
                   ` (6 preceding siblings ...)
  2013-07-15 16:20 ` [Qemu-devel] [PATCH v7 07/10] qemu-ga: Add Windows VSS provider and requester as DLL Tomoki Sekiyama
@ 2013-07-15 16:20 ` Tomoki Sekiyama
  2013-07-15 16:21 ` [Qemu-devel] [PATCH v7 09/10] qemu-ga: Install Windows VSS provider on `qemu-ga -s install' Tomoki Sekiyama
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 24+ messages in thread
From: Tomoki Sekiyama @ 2013-07-15 16:20 UTC (permalink / raw)
  To: qemu-devel
  Cc: libaiqing, ghammer, stefanha, mdroth, lcapitulino, vrozenfe,
	pbonzini, seiji.aguchi, lersek, areis

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/Makefile.objs    |    1 
 qga/commands-win32.c |   82 +++++++++++++++++++++++++++++---
 qga/vss-win32.c      |  129 ++++++++++++++++++++++++++++++++++++++++++++++++++
 qga/vss-win32.h      |   24 +++++++++
 4 files changed, 228 insertions(+), 8 deletions(-)
 create mode 100644 qga/vss-win32.c
 create mode 100644 qga/vss-win32.h

diff --git a/qga/Makefile.objs b/qga/Makefile.objs
index 4891732..ae1c28b 100644
--- a/qga/Makefile.objs
+++ b/qga/Makefile.objs
@@ -1,6 +1,7 @@
 qga-obj-y = commands.o guest-agent-command-state.o main.o
 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-$(CONFIG_WIN32) += vss-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
 
diff --git a/qga/commands-win32.c b/qga/commands-win32.c
index 24e4ad0..7a37f5c 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.h"
 #include "qga-qmp-commands.h"
 #include "qapi/qmp/qerror.h"
 
@@ -156,27 +157,89 @@ void qmp_guest_file_flush(int64_t handle, Error **err)
  */
 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;
+    Error *local_err = NULL;
+
+    if (!vss_initialized()) {
+        error_set(err, QERR_UNSUPPORTED);
+        return 0;
+    }
+
+    slog("guest-fsfreeze called");
+
+    /* cannot risk guest agent blocking itself on a write in this state */
+    ga_set_frozen(ga_state);
+
+    qga_vss_fsfreeze(&i, err, true);
+    if (error_is_set(err)) {
+        goto error;
+    }
+
+    return i;
+
+error:
+    qmp_guest_fsfreeze_thaw(&local_err);
+    if (error_is_set(&local_err)) {
+        g_debug("cleanup thaw: %s", error_get_pretty(local_err));
+        error_free(local_err);
+    }
     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)
 {
-    error_set(err, QERR_UNSUPPORTED);
-    return 0;
+    int i;
+
+    if (!vss_initialized()) {
+        error_set(err, QERR_UNSUPPORTED);
+        return 0;
+    }
+
+    qga_vss_fsfreeze(&i, err, false);
+
+    ga_unset_frozen(ga_state);
+    return i;
+}
+
+static void guest_fsfreeze_cleanup(void)
+{
+    Error *err = NULL;
+
+    if (!vss_initialized()) {
+        return;
+    }
+
+    if (ga_is_frozen(ga_state) == GUEST_FSFREEZE_STATUS_FROZEN) {
+        qmp_guest_fsfreeze_thaw(&err);
+        if (err) {
+            slog("failed to clean up frozen filesystems: %s",
+                 error_get_pretty(err));
+            error_free(err);
+        }
+    }
+
+    vss_deinit(true);
 }
 
 /*
@@ -354,4 +417,7 @@ int64_t qmp_guest_set_vcpus(GuestLogicalProcessorList *vcpus, Error **errp)
 /* register init/cleanup routines for stateful command groups */
 void ga_command_state_init(GAState *s, GACommandState *cs)
 {
+    if (vss_init(true)) {
+        ga_command_state_add(cs, NULL, guest_fsfreeze_cleanup);
+    }
 }
diff --git a/qga/vss-win32.c b/qga/vss-win32.c
new file mode 100644
index 0000000..27d5b14
--- /dev/null
+++ b/qga/vss-win32.c
@@ -0,0 +1,129 @@
+/*
+ * QEMU Guest Agent VSS utility functions
+ *
+ * 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 <windows.h>
+#include "qga/guest-agent-core.h"
+#include "qga/vss-win32.h"
+#include "qga/vss-win32/requester.h"
+
+#define QGA_VSS_DLL "qga-vss.dll"
+
+static HMODULE provider_lib;
+
+/* Call a function in qga-vss.dll with the specified name */
+static HRESULT call_vss_provider_func(const char *func_name)
+{
+    FARPROC WINAPI func;
+
+    g_assert(provider_lib);
+
+    func = GetProcAddress(provider_lib, func_name);
+    if (!func) {
+        char *msg;
+        FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+                      FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
+                      MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+                      (char *)&msg, 0, NULL);
+        fprintf(stderr, "failed to load %s from %s: %s",
+                func_name, QGA_VSS_DLL, msg);
+        LocalFree(msg);
+        return E_FAIL;
+    }
+
+    return func();
+}
+
+/* Check whether this OS version supports VSS providers */
+static bool vss_check_os_version(void)
+{
+    OSVERSIONINFO OSver;
+
+    OSver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+    GetVersionEx(&OSver);
+    if ((OSver.dwMajorVersion == 5 && OSver.dwMinorVersion >= 2) ||
+       OSver.dwMajorVersion > 5) {
+        return true;
+    }
+    return false;
+}
+
+/* Load qga-vss.dll */
+bool vss_init(bool init_requester)
+{
+    if (!vss_check_os_version()) {
+        /* Do nothing if OS doesn't support providers. */
+        fprintf(stderr, "VSS provider is not supported in this OS version: "
+                "fsfreeze is disabled.\n");
+        return false;
+    }
+
+    provider_lib = LoadLibraryA(QGA_VSS_DLL);
+    if (!provider_lib) {
+        char *msg;
+        FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+                      FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
+                      MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+                      (char *)&msg, 0, NULL);
+        fprintf(stderr, "failed to load %s: %sfsfreeze is disabled\n",
+                QGA_VSS_DLL, msg);
+        LocalFree(msg);
+        return false;
+    }
+
+    if (init_requester) {
+        HRESULT hr = call_vss_provider_func("requester_init");
+        if (FAILED(hr)) {
+            fprintf(stderr, "fsfreeze is disabled.\n");
+            vss_deinit(false);
+            return false;
+        }
+    }
+
+    return true;
+}
+
+/* Unload qga-provider.dll */
+void vss_deinit(bool deinit_requester)
+{
+    if (deinit_requester) {
+        call_vss_provider_func("requester_deinit");
+    }
+    FreeLibrary(provider_lib);
+    provider_lib = NULL;
+}
+
+bool vss_initialized(void)
+{
+    return !!provider_lib;
+}
+
+/* Call VSS requester and freeze/thaw filesystems and applications */
+void qga_vss_fsfreeze(int *nr_volume, Error **err, bool freeze)
+{
+    const char *func_name = freeze ? "requester_freeze" : "requester_thaw";
+    QGAVSSReuqesterFunc func;
+    ErrorSet errset = {
+        .error_set = (ErrorSetFunc)error_set_win32,
+        .errp = (void **)err,
+        .err_class = ERROR_CLASS_GENERIC_ERROR
+    };
+
+    func = (QGAVSSReuqesterFunc)GetProcAddress(provider_lib, func_name);
+    if (!func) {
+        error_setg_win32(err, GetLastError(), "failed to load %s from %s",
+                         func_name, QGA_VSS_DLL);
+        return;
+    }
+
+    func(nr_volume, &errset);
+}
diff --git a/qga/vss-win32.h b/qga/vss-win32.h
new file mode 100644
index 0000000..eac669c
--- /dev/null
+++ b/qga/vss-win32.h
@@ -0,0 +1,24 @@
+/*
+ * QEMU Guest Agent VSS utility 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
+
+#include "qapi/error.h"
+
+bool vss_init(bool init_requester);
+void vss_deinit(bool deinit_requester);
+bool vss_initialized(void);
+
+void qga_vss_fsfreeze(int *nr_volume, Error **err, bool freeze);
+
+#endif

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

* [Qemu-devel] [PATCH v7 09/10] qemu-ga: Install Windows VSS provider on `qemu-ga -s install'
  2013-07-15 16:20 [Qemu-devel] [PATCH v7 00/10] qemu-ga: fsfreeze on Windows using VSS Tomoki Sekiyama
                   ` (7 preceding siblings ...)
  2013-07-15 16:20 ` [Qemu-devel] [PATCH v7 08/10] qemu-ga: Call Windows VSS requester in fsfreeze command handler Tomoki Sekiyama
@ 2013-07-15 16:21 ` Tomoki Sekiyama
  2013-07-15 16:21 ` [Qemu-devel] [PATCH v7 10/10] QMP/qemu-ga-client: Make timeout longer for guest-fsfreeze-freeze command Tomoki Sekiyama
  2013-07-18 22:19 ` [Qemu-devel] [PATCH v7 00/10] qemu-ga: fsfreeze on Windows using VSS Michael Roth
  10 siblings, 0 replies; 24+ messages in thread
From: Tomoki Sekiyama @ 2013-07-15 16:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: libaiqing, ghammer, stefanha, mdroth, lcapitulino, vrozenfe,
	pbonzini, seiji.aguchi, lersek, areis

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      |   10 +++++++++-
 qga/vss-win32.c |   25 +++++++++++++++++++++++++
 qga/vss-win32.h |    3 +++
 3 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/qga/main.c b/qga/main.c
index 0e04e73..6c746c8 100644
--- a/qga/main.c
+++ b/qga/main.c
@@ -34,6 +34,7 @@
 #include "qemu/bswap.h"
 #ifdef _WIN32
 #include "qga/service-win32.h"
+#include "qga/vss-win32.h"
 #include <windows.h>
 #endif
 #ifdef __linux__
@@ -1031,8 +1032,15 @@ int main(int argc, char **argv)
                 fixed_state_dir = (state_dir == dfl_pathnames.state_dir) ?
                                   NULL :
                                   state_dir;
-                return ga_install_service(path, log_filepath, fixed_state_dir);
+                if (ga_install_vss_provider()) {
+                    return EXIT_FAILURE;
+                }
+                if (ga_install_service(path, log_filepath, fixed_state_dir)) {
+                    return EXIT_FAILURE;
+                }
+                return 0;
             } else if (strcmp(service, "uninstall") == 0) {
+                ga_uninstall_vss_provider();
                 return ga_uninstall_service();
             } else {
                 printf("Unknown service command.\n");
diff --git a/qga/vss-win32.c b/qga/vss-win32.c
index 27d5b14..d65b520 100644
--- a/qga/vss-win32.c
+++ b/qga/vss-win32.c
@@ -107,6 +107,31 @@ bool vss_initialized(void)
     return !!provider_lib;
 }
 
+int ga_install_vss_provider(void)
+{
+    HRESULT hr;
+
+    if (!vss_init(false)) {
+        fprintf(stderr, "Installation of VSS provider is skipped. "
+                "fsfreeze will be disabled.\n");
+        return 0;
+    }
+    hr = call_vss_provider_func("COMRegister");
+    vss_deinit(false);
+
+    return SUCCEEDED(hr) ? 0 : EXIT_FAILURE;
+}
+
+void ga_uninstall_vss_provider(void)
+{
+    if (!vss_init(false)) {
+        fprintf(stderr, "Removal of VSS provider is skipped.\n");
+        return;
+    }
+    call_vss_provider_func("COMUnregister");
+    vss_deinit(false);
+}
+
 /* Call VSS requester and freeze/thaw filesystems and applications */
 void qga_vss_fsfreeze(int *nr_volume, Error **err, bool freeze)
 {
diff --git a/qga/vss-win32.h b/qga/vss-win32.h
index eac669c..db8fbe5 100644
--- a/qga/vss-win32.h
+++ b/qga/vss-win32.h
@@ -19,6 +19,9 @@ bool vss_init(bool init_requester);
 void vss_deinit(bool deinit_requester);
 bool vss_initialized(void);
 
+int ga_install_vss_provider(void);
+void ga_uninstall_vss_provider(void);
+
 void qga_vss_fsfreeze(int *nr_volume, Error **err, bool freeze);
 
 #endif

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

* [Qemu-devel] [PATCH v7 10/10] QMP/qemu-ga-client: Make timeout longer for guest-fsfreeze-freeze command
  2013-07-15 16:20 [Qemu-devel] [PATCH v7 00/10] qemu-ga: fsfreeze on Windows using VSS Tomoki Sekiyama
                   ` (8 preceding siblings ...)
  2013-07-15 16:21 ` [Qemu-devel] [PATCH v7 09/10] qemu-ga: Install Windows VSS provider on `qemu-ga -s install' Tomoki Sekiyama
@ 2013-07-15 16:21 ` Tomoki Sekiyama
  2013-07-18 22:19 ` [Qemu-devel] [PATCH v7 00/10] qemu-ga: fsfreeze on Windows using VSS Michael Roth
  10 siblings, 0 replies; 24+ messages in thread
From: Tomoki Sekiyama @ 2013-07-15 16:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: libaiqing, ghammer, stefanha, mdroth, lcapitulino, vrozenfe,
	Paolo Bonzini, seiji.aguchi, Laszlo Ersek, areis

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 60 seconds (timeout of pre-commit phase of VSS).

Signed-off-by: Tomoki Sekiyama <tomoki.sekiyama@hds.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.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..b5f7e7c 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(60)
+    elif cmd != 'ping':
         client.sync()
 
     globals()['_cmd_' + cmd](client, args)

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

* Re: [Qemu-devel] [PATCH v7 00/10] qemu-ga: fsfreeze on Windows using VSS
  2013-07-15 16:20 [Qemu-devel] [PATCH v7 00/10] qemu-ga: fsfreeze on Windows using VSS Tomoki Sekiyama
                   ` (9 preceding siblings ...)
  2013-07-15 16:21 ` [Qemu-devel] [PATCH v7 10/10] QMP/qemu-ga-client: Make timeout longer for guest-fsfreeze-freeze command Tomoki Sekiyama
@ 2013-07-18 22:19 ` Michael Roth
  2013-07-19  3:40   ` Tomoki Sekiyama
  10 siblings, 1 reply; 24+ messages in thread
From: Michael Roth @ 2013-07-18 22:19 UTC (permalink / raw)
  To: Tomoki Sekiyama, qemu-devel
  Cc: libaiqing, ghammer, stefanha, lcapitulino, vrozenfe, pbonzini,
	seiji.aguchi, lersek, areis

Quoting Tomoki Sekiyama (2013-07-15 11:20:23)
> Hi,
> 
> This is v7 of patch series to add fsfreeze for Windows qemu-guest-agent.
> 
> changes from v7:
>  - Fix COM initialization issue for Windows service thread (patch 07/10)
> 
> v6: http://lists.nongnu.org/archive/html/qemu-devel/2013-07/msg01788.html

Hi Tomoki,

I'm also having some issues testing this, though I think my problem is a little
different than the issue in v6:

When I initially ran qemu-ga -s install, I got some output indicating the VSS
service was registered, but then it hung. I noticed afterward that I'd already
had the service running, so figured that that might've been the problem. So I
stopped the service and unregistered it (using a qemu-ga install that was in
a separate directory).

Then I went back to install via qemu-ga.exe -s install, and it just hangs with
no output. I wasn't sure how to reset the state, so I took the Windows approach
and rebooted.

After reboot, running qemu-ga -s install gives me:

C:\Users\mdroth\Documents\qga>qemu-ga.exe -s install
Registering QEMU Guest Agent VSS Provider:
  C:\Users\mdroth\Documents\qga\qga-vss.dll
  C:\Users\mdroth\Documents\qga\qga-vss.tlb
Failed to pCatalog->InstallComponent. (Error: 8011045c) The application name is
not unique and cannot be resolved to an application id

CoCreateInstance. (Error: 80040154) Class not registered

Removing COM+ Application: QEMU Guest Agent VSS Provider
Removing COM+ Application: QEMU Guest Agent VSS Provider

[mdroth@vm5 ~]$

I'm not sure if I'm still in a bad state from earlier, but I can't seem to
recover from here.

If I try running qemu-ga -s uninstall, then qemu-ga -s install again, I get a
pop-up error saying:

"CoCreateInstance(VSSCoordinator) failed. (Error: 80040154) Class not registered

Any ideas what's going on here? I'm on a Windows 7 vm and built using a Fedora
18 mingw environment. Let me know if you need any additional information to
debug.

Thanks!

> 
> 
> * 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 qga/vss-win32/qga-vss.{dll,tlb}
> 
>  - Install qemu-ga.exe, qga/vss-win32/qga-vss.{dll,tlb}, and
>    the other required mingw libraries into the same directory in guests
> 
>  - Run `qemu-ga.exe -s install' and `net start qemu-ga' in the guests
> 
> Any feedback are appreciated.
> 
> ---
> Tomoki Sekiyama (10):
>       configure: Support configuring C++ compiler
>       Add c++ keywords to QAPI helper script
>       checkpatch.pl: Check .cpp files
>       Add a script to extract VSS SDK headers on POSIX system
>       qemu-ga: Add configure options to specify path to Windows/VSS SDK
>       error: Add error_set_win32 and error_setg_win32
>       qemu-ga: Add Windows VSS provider and requester as DLL
>       qemu-ga: Call Windows VSS requester in fsfreeze command handler
>       qemu-ga: Install Windows VSS provider on `qemu-ga -s install'
>       QMP/qemu-ga-client: Make timeout longer for guest-fsfreeze-freeze command
> 
> 
>  .gitignore                     |    1 
>  Makefile                       |    3 
>  Makefile.objs                  |    2 
>  QMP/qemu-ga-client             |    4 
>  configure                      |   87 +++++++
>  hmp.c                          |    2 
>  hw/pci/pci.c                   |    2 
>  include/qapi/error.h           |   13 +
>  qga/Makefile.objs              |    5 
>  qga/commands-win32.c           |   82 ++++++
>  qga/main.c                     |   10 +
>  qga/vss-win32.c                |  154 ++++++++++++
>  qga/vss-win32.h                |   27 ++
>  qga/vss-win32/Makefile.objs    |   23 ++
>  qga/vss-win32/install.cpp      |  424 +++++++++++++++++++++++++++++++++
>  qga/vss-win32/provider.cpp     |  513 ++++++++++++++++++++++++++++++++++++++++
>  qga/vss-win32/qga-vss.def      |   13 +
>  qga/vss-win32/qga-vss.idl      |   20 ++
>  qga/vss-win32/qga-vss.tlb      |  Bin
>  qga/vss-win32/requester.cpp    |  487 ++++++++++++++++++++++++++++++++++++++
>  qga/vss-win32/requester.h      |   42 +++
>  qga/vss-win32/vss-common.h     |  128 ++++++++++
>  rules.mak                      |    9 +
>  scripts/checkpatch.pl          |   37 ++-
>  scripts/extract-vsssdk-headers |   35 +++
>  scripts/qapi.py                |   12 +
>  util/error.c                   |   35 +++
>  27 files changed, 2146 insertions(+), 24 deletions(-)
>  create mode 100644 qga/vss-win32.c
>  create mode 100644 qga/vss-win32.h
>  create mode 100644 qga/vss-win32/Makefile.objs
>  create mode 100644 qga/vss-win32/install.cpp
>  create mode 100644 qga/vss-win32/provider.cpp
>  create mode 100644 qga/vss-win32/qga-vss.def
>  create mode 100644 qga/vss-win32/qga-vss.idl
>  create mode 100644 qga/vss-win32/qga-vss.tlb
>  create mode 100644 qga/vss-win32/requester.cpp
>  create mode 100644 qga/vss-win32/requester.h
>  create mode 100644 qga/vss-win32/vss-common.h
>  create mode 100755 scripts/extract-vsssdk-headers

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

* Re: [Qemu-devel] [PATCH v7 00/10] qemu-ga: fsfreeze on Windows using VSS
  2013-07-18 22:19 ` [Qemu-devel] [PATCH v7 00/10] qemu-ga: fsfreeze on Windows using VSS Michael Roth
@ 2013-07-19  3:40   ` Tomoki Sekiyama
  2013-07-22 20:02     ` Tomoki Sekiyama
  0 siblings, 1 reply; 24+ messages in thread
From: Tomoki Sekiyama @ 2013-07-19  3:40 UTC (permalink / raw)
  To: Michael Roth, qemu-devel
  Cc: libaiqing, ghammer, stefanha, lcapitulino, vrozenfe, pbonzini,
	Seiji Aguchi, lersek, areis

Hi Michael,

> "CoCreateInstance(VSSCoordinator) failed. (Error: 80040154) Class not registered

I have seen this error when I ran 32bit qemu-ga on 64bit Windows (2008 server R2).
Just in case, could you confirm qemu-ga.exe and qga-vss.dll are built for the
correct architecture?

Stopping VSS service by "net stop vss" might be helpful to fix hung.
Otherwise, possibly COM+ related registry are messed up...?
("qemu-ga -s uninstall" deletes whole qemu-ga VSS related registry entries,
 that should solve the problem in usual...)

And If you have any VSS/COM related log in Event Viewer (maybe in
System or Application log) , please let me know.

Thanks,
Tomoki Sekiyama

________________________________________
From: fluxion [flukshun@gmail.com] on behalf of Michael Roth [mdroth@linux.vnet.ibm.com]
Sent: Thursday, July 18, 2013 6:19 PM
To: Tomoki Sekiyama; qemu-devel@nongnu.org
Cc: libaiqing@huawei.com; lersek@redhat.com; ghammer@redhat.com; stefanha@gmail.com; lcapitulino@redhat.com; vrozenfe@redhat.com; pbonzini@redhat.com; Seiji Aguchi; eblake@redhat.com; areis@redhat.com
Subject: Re: [PATCH v7 00/10] qemu-ga: fsfreeze on Windows using VSS

Quoting Tomoki Sekiyama (2013-07-15 11:20:23)
> Hi,
>
> This is v7 of patch series to add fsfreeze for Windows qemu-guest-agent.
>
> changes from v7:
>  - Fix COM initialization issue for Windows service thread (patch 07/10)
>
> v6: http://lists.nongnu.org/archive/html/qemu-devel/2013-07/msg01788.html

Hi Tomoki,

I'm also having some issues testing this, though I think my problem is a little
different than the issue in v6:

When I initially ran qemu-ga -s install, I got some output indicating the VSS
service was registered, but then it hung. I noticed afterward that I'd already
had the service running, so figured that that might've been the problem. So I
stopped the service and unregistered it (using a qemu-ga install that was in
a separate directory).

Then I went back to install via qemu-ga.exe -s install, and it just hangs with
no output. I wasn't sure how to reset the state, so I took the Windows approach
and rebooted.

After reboot, running qemu-ga -s install gives me:

C:\Users\mdroth\Documents\qga>qemu-ga.exe -s install
Registering QEMU Guest Agent VSS Provider:
  C:\Users\mdroth\Documents\qga\qga-vss.dll
  C:\Users\mdroth\Documents\qga\qga-vss.tlb
Failed to pCatalog->InstallComponent. (Error: 8011045c) The application name is
not unique and cannot be resolved to an application id

CoCreateInstance. (Error: 80040154) Class not registered

Removing COM+ Application: QEMU Guest Agent VSS Provider
Removing COM+ Application: QEMU Guest Agent VSS Provider

[mdroth@vm5 ~]$

I'm not sure if I'm still in a bad state from earlier, but I can't seem to
recover from here.

If I try running qemu-ga -s uninstall, then qemu-ga -s install again, I get a
pop-up error saying:

"CoCreateInstance(VSSCoordinator) failed. (Error: 80040154) Class not registered

Any ideas what's going on here? I'm on a Windows 7 vm and built using a Fedora
18 mingw environment. Let me know if you need any additional information to
debug.

Thanks!

>
>
> * 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 qga/vss-win32/qga-vss.{dll,tlb}
>
>  - Install qemu-ga.exe, qga/vss-win32/qga-vss.{dll,tlb}, and
>    the other required mingw libraries into the same directory in guests
>
>  - Run `qemu-ga.exe -s install' and `net start qemu-ga' in the guests
>
> Any feedback are appreciated.
>
> ---
> Tomoki Sekiyama (10):
>       configure: Support configuring C++ compiler
>       Add c++ keywords to QAPI helper script
>       checkpatch.pl: Check .cpp files
>       Add a script to extract VSS SDK headers on POSIX system
>       qemu-ga: Add configure options to specify path to Windows/VSS SDK
>       error: Add error_set_win32 and error_setg_win32
>       qemu-ga: Add Windows VSS provider and requester as DLL
>       qemu-ga: Call Windows VSS requester in fsfreeze command handler
>       qemu-ga: Install Windows VSS provider on `qemu-ga -s install'
>       QMP/qemu-ga-client: Make timeout longer for guest-fsfreeze-freeze command
>
>
>  .gitignore                     |    1
>  Makefile                       |    3
>  Makefile.objs                  |    2
>  QMP/qemu-ga-client             |    4
>  configure                      |   87 +++++++
>  hmp.c                          |    2
>  hw/pci/pci.c                   |    2
>  include/qapi/error.h           |   13 +
>  qga/Makefile.objs              |    5
>  qga/commands-win32.c           |   82 ++++++
>  qga/main.c                     |   10 +
>  qga/vss-win32.c                |  154 ++++++++++++
>  qga/vss-win32.h                |   27 ++
>  qga/vss-win32/Makefile.objs    |   23 ++
>  qga/vss-win32/install.cpp      |  424 +++++++++++++++++++++++++++++++++
>  qga/vss-win32/provider.cpp     |  513 ++++++++++++++++++++++++++++++++++++++++
>  qga/vss-win32/qga-vss.def      |   13 +
>  qga/vss-win32/qga-vss.idl      |   20 ++
>  qga/vss-win32/qga-vss.tlb      |  Bin
>  qga/vss-win32/requester.cpp    |  487 ++++++++++++++++++++++++++++++++++++++
>  qga/vss-win32/requester.h      |   42 +++
>  qga/vss-win32/vss-common.h     |  128 ++++++++++
>  rules.mak                      |    9 +
>  scripts/checkpatch.pl          |   37 ++-
>  scripts/extract-vsssdk-headers |   35 +++
>  scripts/qapi.py                |   12 +
>  util/error.c                   |   35 +++
>  27 files changed, 2146 insertions(+), 24 deletions(-)
>  create mode 100644 qga/vss-win32.c
>  create mode 100644 qga/vss-win32.h
>  create mode 100644 qga/vss-win32/Makefile.objs
>  create mode 100644 qga/vss-win32/install.cpp
>  create mode 100644 qga/vss-win32/provider.cpp
>  create mode 100644 qga/vss-win32/qga-vss.def
>  create mode 100644 qga/vss-win32/qga-vss.idl
>  create mode 100644 qga/vss-win32/qga-vss.tlb
>  create mode 100644 qga/vss-win32/requester.cpp
>  create mode 100644 qga/vss-win32/requester.h
>  create mode 100644 qga/vss-win32/vss-common.h
>  create mode 100755 scripts/extract-vsssdk-headers

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

* Re: [Qemu-devel] [PATCH v7 00/10] qemu-ga: fsfreeze on Windows using VSS
  2013-07-19  3:40   ` Tomoki Sekiyama
@ 2013-07-22 20:02     ` Tomoki Sekiyama
  2013-07-22 20:33       ` Michael Roth
  0 siblings, 1 reply; 24+ messages in thread
From: Tomoki Sekiyama @ 2013-07-22 20:02 UTC (permalink / raw)
  To: Michael Roth, qemu-devel
  Cc: libaiqing, ghammer, stefanha, lcapitulino, vrozenfe, pbonzini,
	Seiji Aguchi, lersek, areis

Hi Michael,

>> "CoCreateInstance(VSSCoordinator) failed. (Error: 80040154) Class not registered
>I have seen this error when I ran 32bit qemu-ga on 64bit Windows (2008 server R2).
>Just in case, could you confirm qemu-ga.exe and qga-vss.dll are built for the
>correct architecture?

I have confirmed that using 32bit qemu-ga.exe on 64bit Windows causes exactly
what you explained at the previous e-mail. (And maybe the hung is caused by a
dialog box popped up *behind* the terminal.... I think this is because the box
belongs to a Windows service, but I don't know how to avoid it...)

Could you tell me which arch (32bit/64bit) of Windows and mingw
(mingw32-* or mingw64-* in Fedora package) are you using?

Thanks,
Tomoki Sekiyama

________________________________________
From: fluxion [flukshun@gmail.com] on behalf of Michael Roth [mdroth@linux.vnet.ibm.com]
Sent: Thursday, July 18, 2013 6:19 PM
To: Tomoki Sekiyama; qemu-devel@nongnu.org
Cc: libaiqing@huawei.com; lersek@redhat.com; ghammer@redhat.com; stefanha@gmail.com; lcapitulino@redhat.com; vrozenfe@redhat.com; pbonzini@redhat.com; Seiji Aguchi; eblake@redhat.com; areis@redhat.com
Subject: Re: [PATCH v7 00/10] qemu-ga: fsfreeze on Windows using VSS

Quoting Tomoki Sekiyama (2013-07-15 11:20:23)
> Hi,
>
> This is v7 of patch series to add fsfreeze for Windows qemu-guest-agent.
>
> changes from v7:
>  - Fix COM initialization issue for Windows service thread (patch 07/10)
>
> v6: http://lists.nongnu.org/archive/html/qemu-devel/2013-07/msg01788.html

Hi Tomoki,

I'm also having some issues testing this, though I think my problem is a little
different than the issue in v6:

When I initially ran qemu-ga -s install, I got some output indicating the VSS
service was registered, but then it hung. I noticed afterward that I'd already
had the service running, so figured that that might've been the problem. So I
stopped the service and unregistered it (using a qemu-ga install that was in
a separate directory).

Then I went back to install via qemu-ga.exe -s install, and it just hangs with
no output. I wasn't sure how to reset the state, so I took the Windows approach
and rebooted.

After reboot, running qemu-ga -s install gives me:

C:\Users\mdroth\Documents\qga>qemu-ga.exe -s install
Registering QEMU Guest Agent VSS Provider:
  C:\Users\mdroth\Documents\qga\qga-vss.dll
  C:\Users\mdroth\Documents\qga\qga-vss.tlb
Failed to pCatalog->InstallComponent. (Error: 8011045c) The application name is
not unique and cannot be resolved to an application id

CoCreateInstance. (Error: 80040154) Class not registered

Removing COM+ Application: QEMU Guest Agent VSS Provider
Removing COM+ Application: QEMU Guest Agent VSS Provider

[mdroth@vm5 ~]$

I'm not sure if I'm still in a bad state from earlier, but I can't seem to
recover from here.

If I try running qemu-ga -s uninstall, then qemu-ga -s install again, I get a
pop-up error saying:

"CoCreateInstance(VSSCoordinator) failed. (Error: 80040154) Class not registered

Any ideas what's going on here? I'm on a Windows 7 vm and built using a Fedora
18 mingw environment. Let me know if you need any additional information to
debug.

Thanks!

>
>
> * 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 qga/vss-win32/qga-vss.{dll,tlb}
>
>  - Install qemu-ga.exe, qga/vss-win32/qga-vss.{dll,tlb}, and
>    the other required mingw libraries into the same directory in guests
>
>  - Run `qemu-ga.exe -s install' and `net start qemu-ga' in the guests
>
> Any feedback are appreciated.
>
> ---
> Tomoki Sekiyama (10):
>       configure: Support configuring C++ compiler
>       Add c++ keywords to QAPI helper script
>       checkpatch.pl: Check .cpp files
>       Add a script to extract VSS SDK headers on POSIX system
>       qemu-ga: Add configure options to specify path to Windows/VSS SDK
>       error: Add error_set_win32 and error_setg_win32
>       qemu-ga: Add Windows VSS provider and requester as DLL
>       qemu-ga: Call Windows VSS requester in fsfreeze command handler
>       qemu-ga: Install Windows VSS provider on `qemu-ga -s install'
>       QMP/qemu-ga-client: Make timeout longer for guest-fsfreeze-freeze command
>
>
>  .gitignore                     |    1
>  Makefile                       |    3
>  Makefile.objs                  |    2
>  QMP/qemu-ga-client             |    4
>  configure                      |   87 +++++++
>  hmp.c                          |    2
>  hw/pci/pci.c                   |    2
>  include/qapi/error.h           |   13 +
>  qga/Makefile.objs              |    5
>  qga/commands-win32.c           |   82 ++++++
>  qga/main.c                     |   10 +
>  qga/vss-win32.c                |  154 ++++++++++++
>  qga/vss-win32.h                |   27 ++
>  qga/vss-win32/Makefile.objs    |   23 ++
>  qga/vss-win32/install.cpp      |  424 +++++++++++++++++++++++++++++++++
>  qga/vss-win32/provider.cpp     |  513 ++++++++++++++++++++++++++++++++++++++++
>  qga/vss-win32/qga-vss.def      |   13 +
>  qga/vss-win32/qga-vss.idl      |   20 ++
>  qga/vss-win32/qga-vss.tlb      |  Bin
>  qga/vss-win32/requester.cpp    |  487 ++++++++++++++++++++++++++++++++++++++
>  qga/vss-win32/requester.h      |   42 +++
>  qga/vss-win32/vss-common.h     |  128 ++++++++++
>  rules.mak                      |    9 +
>  scripts/checkpatch.pl          |   37 ++-
>  scripts/extract-vsssdk-headers |   35 +++
>  scripts/qapi.py                |   12 +
>  util/error.c                   |   35 +++
>  27 files changed, 2146 insertions(+), 24 deletions(-)
>  create mode 100644 qga/vss-win32.c
>  create mode 100644 qga/vss-win32.h
>  create mode 100644 qga/vss-win32/Makefile.objs
>  create mode 100644 qga/vss-win32/install.cpp
>  create mode 100644 qga/vss-win32/provider.cpp
>  create mode 100644 qga/vss-win32/qga-vss.def
>  create mode 100644 qga/vss-win32/qga-vss.idl
>  create mode 100644 qga/vss-win32/qga-vss.tlb
>  create mode 100644 qga/vss-win32/requester.cpp
>  create mode 100644 qga/vss-win32/requester.h
>  create mode 100644 qga/vss-win32/vss-common.h
>  create mode 100755 scripts/extract-vsssdk-headers

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

* Re: [Qemu-devel] [PATCH v7 00/10] qemu-ga: fsfreeze on Windows using VSS
  2013-07-22 20:02     ` Tomoki Sekiyama
@ 2013-07-22 20:33       ` Michael Roth
  2013-07-22 21:33         ` Tomoki Sekiyama
  0 siblings, 1 reply; 24+ messages in thread
From: Michael Roth @ 2013-07-22 20:33 UTC (permalink / raw)
  To: Tomoki Sekiyama, qemu-devel
  Cc: libaiqing, ghammer, stefanha, lcapitulino, vrozenfe, pbonzini,
	Seiji Aguchi, lersek, areis

Quoting Tomoki Sekiyama (2013-07-22 15:02:23)
> Hi Michael,
> 
> >> "CoCreateInstance(VSSCoordinator) failed. (Error: 80040154) Class not registered
> >I have seen this error when I ran 32bit qemu-ga on 64bit Windows (2008 server R2).
> >Just in case, could you confirm qemu-ga.exe and qga-vss.dll are built for the
> >correct architecture?
> 
> I have confirmed that using 32bit qemu-ga.exe on 64bit Windows causes exactly
> what you explained at the previous e-mail. (And maybe the hung is caused by a
> dialog box popped up *behind* the terminal.... I think this is because the box
> belongs to a Windows service, but I don't know how to avoid it...)

Thanks, I was just about to confirm as well :) Problem doesn't seem to be
present if I switch to a 64-bit version.

And you're right, in the instances where the -s install freezes a dialog box
*does* pop up behind the terminal with the above error.

> 
> Could you tell me which arch (32bit/64bit) of Windows and mingw
> (mingw32-* or mingw64-* in Fedora package) are you using?

This was a 32-bit binary (--cross-prefix=i686-w64-mingw32-) on a 64-bit
Windows 7 vm.

I've since built a 64-bit binary (--cross-prefix=x86_64-w64-mingw32-) and have
gotten past service install and successfully issued the freeze/thaw commands.

So I think that solves the 'hang'/CoCreateInstance issue, although it would
be nice if 32-bit could run on 64-bit, since that's supported currently. Is
this a known issue/limitation? If so, perhaps we can avoid registering the
VSS provider if the arch doesn't match?

Also, with 64-bit qemu-ga I do find that if I don't issue `net stop vss` prior
to service install I still get the following error:

 C:\Users\mdroth\Documents\qga>qemu-ga.exe -s install
 Registering QEMU Guest Agent VSS Provider:
   C:\Users\mdroth\Documents\qga\qga-vss.dll
   C:\Users\mdroth\Documents\qga\qga-vss.tlb
 Failed to pCatalog->InstallComponent. (Error: 8011045c) The application name is
 not unique and cannot be resolved to an application id
 
 CoCreateInstance. (Error: 80040154) Class not registered
 
 Removing COM+ Application: QEMU Guest Agent VSS Provider
 Removing COM+ Application: QEMU Guest Agent VSS Provider

Is this expected? And if there's no way around it, would it be possible to
notify users that they need to stop the VSS service prior to install the
service?

Thanks for looking into this!

> 
> Thanks,
> Tomoki Sekiyama
> 
> ________________________________________
> From: fluxion [flukshun@gmail.com] on behalf of Michael Roth [mdroth@linux.vnet.ibm.com]
> Sent: Thursday, July 18, 2013 6:19 PM
> To: Tomoki Sekiyama; qemu-devel@nongnu.org
> Cc: libaiqing@huawei.com; lersek@redhat.com; ghammer@redhat.com; stefanha@gmail.com; lcapitulino@redhat.com; vrozenfe@redhat.com; pbonzini@redhat.com; Seiji Aguchi; eblake@redhat.com; areis@redhat.com
> Subject: Re: [PATCH v7 00/10] qemu-ga: fsfreeze on Windows using VSS
> 
> Quoting Tomoki Sekiyama (2013-07-15 11:20:23)
> > Hi,
> >
> > This is v7 of patch series to add fsfreeze for Windows qemu-guest-agent.
> >
> > changes from v7:
> >  - Fix COM initialization issue for Windows service thread (patch 07/10)
> >
> > v6: http://lists.nongnu.org/archive/html/qemu-devel/2013-07/msg01788.html
> 
> Hi Tomoki,
> 
> I'm also having some issues testing this, though I think my problem is a little
> different than the issue in v6:
> 
> When I initially ran qemu-ga -s install, I got some output indicating the VSS
> service was registered, but then it hung. I noticed afterward that I'd already
> had the service running, so figured that that might've been the problem. So I
> stopped the service and unregistered it (using a qemu-ga install that was in
> a separate directory).
> 
> Then I went back to install via qemu-ga.exe -s install, and it just hangs with
> no output. I wasn't sure how to reset the state, so I took the Windows approach
> and rebooted.
> 
> After reboot, running qemu-ga -s install gives me:
> 
> C:\Users\mdroth\Documents\qga>qemu-ga.exe -s install
> Registering QEMU Guest Agent VSS Provider:
>   C:\Users\mdroth\Documents\qga\qga-vss.dll
>   C:\Users\mdroth\Documents\qga\qga-vss.tlb
> Failed to pCatalog->InstallComponent. (Error: 8011045c) The application name is
> not unique and cannot be resolved to an application id
> 
> CoCreateInstance. (Error: 80040154) Class not registered
> 
> Removing COM+ Application: QEMU Guest Agent VSS Provider
> Removing COM+ Application: QEMU Guest Agent VSS Provider
> 
> [mdroth@vm5 ~]$
> 
> I'm not sure if I'm still in a bad state from earlier, but I can't seem to
> recover from here.
> 
> If I try running qemu-ga -s uninstall, then qemu-ga -s install again, I get a
> pop-up error saying:
> 
> "CoCreateInstance(VSSCoordinator) failed. (Error: 80040154) Class not registered
> 
> Any ideas what's going on here? I'm on a Windows 7 vm and built using a Fedora
> 18 mingw environment. Let me know if you need any additional information to
> debug.
> 
> Thanks!
> 
> >
> >
> > * 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 qga/vss-win32/qga-vss.{dll,tlb}
> >
> >  - Install qemu-ga.exe, qga/vss-win32/qga-vss.{dll,tlb}, and
> >    the other required mingw libraries into the same directory in guests
> >
> >  - Run `qemu-ga.exe -s install' and `net start qemu-ga' in the guests
> >
> > Any feedback are appreciated.
> >
> > ---
> > Tomoki Sekiyama (10):
> >       configure: Support configuring C++ compiler
> >       Add c++ keywords to QAPI helper script
> >       checkpatch.pl: Check .cpp files
> >       Add a script to extract VSS SDK headers on POSIX system
> >       qemu-ga: Add configure options to specify path to Windows/VSS SDK
> >       error: Add error_set_win32 and error_setg_win32
> >       qemu-ga: Add Windows VSS provider and requester as DLL
> >       qemu-ga: Call Windows VSS requester in fsfreeze command handler
> >       qemu-ga: Install Windows VSS provider on `qemu-ga -s install'
> >       QMP/qemu-ga-client: Make timeout longer for guest-fsfreeze-freeze command
> >
> >
> >  .gitignore                     |    1
> >  Makefile                       |    3
> >  Makefile.objs                  |    2
> >  QMP/qemu-ga-client             |    4
> >  configure                      |   87 +++++++
> >  hmp.c                          |    2
> >  hw/pci/pci.c                   |    2
> >  include/qapi/error.h           |   13 +
> >  qga/Makefile.objs              |    5
> >  qga/commands-win32.c           |   82 ++++++
> >  qga/main.c                     |   10 +
> >  qga/vss-win32.c                |  154 ++++++++++++
> >  qga/vss-win32.h                |   27 ++
> >  qga/vss-win32/Makefile.objs    |   23 ++
> >  qga/vss-win32/install.cpp      |  424 +++++++++++++++++++++++++++++++++
> >  qga/vss-win32/provider.cpp     |  513 ++++++++++++++++++++++++++++++++++++++++
> >  qga/vss-win32/qga-vss.def      |   13 +
> >  qga/vss-win32/qga-vss.idl      |   20 ++
> >  qga/vss-win32/qga-vss.tlb      |  Bin
> >  qga/vss-win32/requester.cpp    |  487 ++++++++++++++++++++++++++++++++++++++
> >  qga/vss-win32/requester.h      |   42 +++
> >  qga/vss-win32/vss-common.h     |  128 ++++++++++
> >  rules.mak                      |    9 +
> >  scripts/checkpatch.pl          |   37 ++-
> >  scripts/extract-vsssdk-headers |   35 +++
> >  scripts/qapi.py                |   12 +
> >  util/error.c                   |   35 +++
> >  27 files changed, 2146 insertions(+), 24 deletions(-)
> >  create mode 100644 qga/vss-win32.c
> >  create mode 100644 qga/vss-win32.h
> >  create mode 100644 qga/vss-win32/Makefile.objs
> >  create mode 100644 qga/vss-win32/install.cpp
> >  create mode 100644 qga/vss-win32/provider.cpp
> >  create mode 100644 qga/vss-win32/qga-vss.def
> >  create mode 100644 qga/vss-win32/qga-vss.idl
> >  create mode 100644 qga/vss-win32/qga-vss.tlb
> >  create mode 100644 qga/vss-win32/requester.cpp
> >  create mode 100644 qga/vss-win32/requester.h
> >  create mode 100644 qga/vss-win32/vss-common.h
> >  create mode 100755 scripts/extract-vsssdk-headers

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

* Re: [Qemu-devel] [PATCH v7 01/10] configure: Support configuring C++ compiler
  2013-07-15 16:20 ` [Qemu-devel] [PATCH v7 01/10] configure: Support configuring C++ compiler Tomoki Sekiyama
@ 2013-07-22 20:53   ` Michael Roth
  2013-07-23 21:49     ` Tomoki Sekiyama
  0 siblings, 1 reply; 24+ messages in thread
From: Michael Roth @ 2013-07-22 20:53 UTC (permalink / raw)
  To: Tomoki Sekiyama, qemu-devel
  Cc: libaiqing, ghammer, stefanha, lcapitulino, vrozenfe, pbonzini,
	seiji.aguchi, Laszlo Ersek, areis

Quoting Tomoki Sekiyama (2013-07-15 11:20:29)
> Add configuration for C++ compiler in configure and Makefiles.
> The C++ compiler is choosed as following:
>  - ${CXX}, if it is specified.
>  - ${cross_prefix}g++, if ${cross_prefix} is specified.
>  - Otherwise, c++ is used.
> 
> 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>
> Reviewed-by: Laszlo Ersek <lersek@redhat.com>
> ---
>  configure |   13 +++++++++++++
>  rules.mak |    9 ++++++++-
>  2 files changed, 21 insertions(+), 1 deletion(-)
> 
> diff --git a/configure b/configure
> index cb0f870..6923b65 100755
> --- a/configure
> +++ b/configure
> @@ -251,6 +251,8 @@ for opt do
>    ;;
>    --cc=*) CC="$optarg"
>    ;;
> +  --cxx=*) CXX="$optarg"
> +  ;;
>    --source-path=*) source_path="$optarg"
>    ;;
>    --cpu=*) cpu="$optarg"
> @@ -281,6 +283,12 @@ else
>    cc="${CC-${cross_prefix}gcc}"
>  fi
> 
> +if test -z "${CXX}${cross_prefix}"; then
> +  cxx="c++"
> +else
> +  cxx="${CXX-${cross_prefix}g++}"
> +fi
> +
>  ar="${AR-${cross_prefix}ar}"
>  as="${AS-${cross_prefix}as}"
>  cpp="${CPP-$cc -E}"
> @@ -621,6 +629,8 @@ for opt do
>    ;;
>    --host-cc=*) host_cc="$optarg"
>    ;;
> +  --cxx=*) cxx="$optarg"
> +  ;;

Since we've already determined cxx in the first pass (overriding other
defaults --cxx argument if it's present), I think re-assigning here
is unecessary.

Otherwise looks good.

>    --objcc=*) objcc="$optarg"
>    ;;
>    --make=*) make="$optarg"
> @@ -1022,6 +1032,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"
> @@ -3496,6 +3507,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"
> @@ -4069,6 +4081,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 4499745..abc2e84 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
> 
> @@ -50,6 +54,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)$@")
> 
> @@ -70,7 +77,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 %.rc
> +VPATH_SUFFIXES = %.c %.h %.S %.cpp %.m %.mak %.texi %.sh %.rc
>  set-vpath = $(if $1,$(foreach PATTERN,$(VPATH_SUFFIXES),$(eval vpath $(PATTERN) $1)))
> 
>  # find-in-path

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

* Re: [Qemu-devel] [PATCH v7 02/10] Add c++ keywords to QAPI helper script
  2013-07-15 16:20 ` [Qemu-devel] [PATCH v7 02/10] Add c++ keywords to QAPI helper script Tomoki Sekiyama
@ 2013-07-22 20:55   ` Michael Roth
  0 siblings, 0 replies; 24+ messages in thread
From: Michael Roth @ 2013-07-22 20:55 UTC (permalink / raw)
  To: Tomoki Sekiyama, qemu-devel
  Cc: libaiqing, ghammer, stefanha, lcapitulino, vrozenfe, pbonzini,
	seiji.aguchi, Laszlo Ersek, areis

Quoting Tomoki Sekiyama (2013-07-15 11:20:33)
> 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>
> Reviewed-by: Laszlo Ersek <lersek@redhat.com>

Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>

> ---
>  hmp.c           |    2 +-
>  hw/pci/pci.c    |    2 +-
>  scripts/qapi.py |   12 +++++++++++-
>  3 files changed, 13 insertions(+), 3 deletions(-)
> 
> diff --git a/hmp.c b/hmp.c
> index 2daed43..69b1506 100644
> --- a/hmp.c
> +++ b/hmp.c
> @@ -524,7 +524,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 dcc85ef..5369996 100644
> --- a/hw/pci/pci.c
> +++ b/hw/pci/pci.c
> @@ -1461,7 +1461,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 baf1321..942bcc2 100644
> --- a/scripts/qapi.py
> +++ b/scripts/qapi.py
> @@ -169,9 +169,19 @@ 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',
> +                     # alternative representations
> +                     'and', 'and_eq', 'bitand', 'bitor', 'compl', 'not',
> +                     'not_eq', 'or', 'or_eq', 'xor', 'xor_eq'])
>      # 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	[flat|nested] 24+ messages in thread

* Re: [Qemu-devel] [PATCH v7 03/10] checkpatch.pl: Check .cpp files
  2013-07-15 16:20 ` [Qemu-devel] [PATCH v7 03/10] checkpatch.pl: Check .cpp files Tomoki Sekiyama
@ 2013-07-22 21:21   ` Michael Roth
  2013-07-23 21:49     ` Tomoki Sekiyama
  0 siblings, 1 reply; 24+ messages in thread
From: Michael Roth @ 2013-07-22 21:21 UTC (permalink / raw)
  To: Tomoki Sekiyama, qemu-devel
  Cc: libaiqing, ghammer, stefanha, lcapitulino, vrozenfe, pbonzini,
	seiji.aguchi, lersek, areis

Quoting Tomoki Sekiyama (2013-07-15 11:20:37)
> Enable checkpatch.pl to apply the same checks as C source files for
> C++ files with .cpp extensions. It also adds some exceptions for C++
> sources to suppress errors for:
>   - <> used in C++ template arguments (e.g. template <class T>)
>   - :: used to represent namespaces   (e.g. SomeClass::method())
>   - : used in class declaration       (e.g. class T : public Super)
>   - ~ used in destructor method name  (e.g. T::~T())
>   - spacing around 'catch'            (e.g. catch (...))
> 
> Signed-off-by: Tomoki Sekiyama <tomoki.sekiyama@hds.com>

One small nit below about documentation. Looks good otherwise.

> ---
>  scripts/checkpatch.pl |   37 +++++++++++++++++++++++++++++--------
>  1 file changed, 29 insertions(+), 8 deletions(-)
> 
> diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
> index ec0aa4c..0ef72b5 100755
> --- a/scripts/checkpatch.pl
> +++ b/scripts/checkpatch.pl
> @@ -1363,7 +1363,7 @@ sub process {
>  # Check for incorrect file permissions
>                 if ($line =~ /^new (file )?mode.*[7531]\d{0,2}$/) {
>                         my $permhere = $here . "FILE: $realfile\n";
> -                       if ($realfile =~ /(Makefile|Kconfig|\.c|\.h|\.S|\.tmpl)$/) {
> +                       if ($realfile =~ /(Makefile|Kconfig|\.c|\.cpp|\.h|\.S|\.tmpl)$/) {
>                                 ERROR("do not set execute permissions for source files\n" . $permhere);
>                         }
>                 }
> @@ -1460,7 +1460,7 @@ sub process {
>                 }
> 
>  # check we are in a valid source file if not then ignore this hunk
> -               next if ($realfile !~ /\.(h|c|s|S|pl|sh)$/);
> +               next if ($realfile !~ /\.(h|c|cpp|s|S|pl|sh)$/);
> 
>  #80 column limit
>                 if ($line =~ /^\+/ && $prevrawline !~ /\/\*\*/ &&
> @@ -1495,7 +1495,7 @@ sub process {
>                 }
> 
>  # check we are in a valid source file C or perl if not then ignore this hunk
> -               next if ($realfile !~ /\.(h|c|pl)$/);
> +               next if ($realfile !~ /\.(h|c|cpp|pl)$/);
> 
>  # in QEMU, no tabs are allowed
>                 if ($rawline =~ /^\+.*    /) {
> @@ -1505,7 +1505,7 @@ sub process {
>                 }
> 
>  # check we are in a valid C source file if not then ignore this hunk
> -               next if ($realfile !~ /\.(h|c)$/);
> +               next if ($realfile !~ /\.(h|c|cpp)$/);
> 
>  # check for RCS/CVS revision markers
>                 if ($rawline =~ /^\+.*\$(Revision|Log|Id)(?:\$|)/) {
> @@ -1969,6 +1969,9 @@ sub process {
>                                 asm|__asm__)$/x)
>                         {
> 
> +                       # Ignore 'catch (...)' in C++
> +                       } elsif ($name =~ /^catch$/ && $realfile =~ /(\.cpp|\.h)$/) {
> +
>                         # cpp #define statements have non-optional spaces, ie
>                         # if there is a space between the name and the open
>                         # parenthesis it is simply not a parameter group.
> @@ -1992,7 +1995,7 @@ sub process {
>                                 \+=|-=|\*=|\/=|%=|\^=|\|=|&=|
>                                 =>|->|<<|>>|<|>|=|!|~|
>                                 &&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/|%|
> -                               \?|:
> +                               \?|::|:
>                         }x;
>                         my @elements = split(/($ops|;)/, $opline);
>                         my $off = 0;
> @@ -2066,7 +2069,8 @@ sub process {
>                                 #   ->
>                                 #   :   when part of a bitfield
>                                 } elsif ($op eq '->' || $opv eq ':B') {
> -                                       if ($ctx =~ /Wx.|.xW/) {
> +                                       if ($ctx =~ /Wx.|.xW/ &&
> +                                               !($opv eq ':B' && $line =~ /class/)) {

Everything else seemed fairly obvious or was well commented, but I couldn't
figure out what this change was for. Could you insert a small comment to
explain?

>                                                 ERROR("spaces prohibited around that '$op' $at\n" . $hereptr);
>                                         }
> 
> @@ -2088,7 +2092,11 @@ sub process {
>                                 } elsif ($op eq '!' || $op eq '~' ||
>                                          $opv eq '*U' || $opv eq '-U' ||
>                                          $opv eq '&U' || $opv eq '&&U') {
> -                                       if ($ctx !~ /[WEBC]x./ && $ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/) {
> +                                       if ($op eq '~' && $ca =~ /::$/ && $realfile =~ /(\.cpp|\.h)$/) {
> +                                               # '~' used as a name of Destructor
> +
> +                                       }
> +                                       elsif ($ctx !~ /[WEBC]x./ && $ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/) {
>                                                 ERROR("space required before that '$op' $at\n" . $hereptr);
>                                         }
>                                         if ($op eq '*' && $cc =~/\s*$Modifier\b/) {
> @@ -2126,8 +2134,9 @@ sub process {
> 
>                                 # A colon needs no spaces before when it is
>                                 # terminating a case value or a label.
> +                               # Ignored if it is used in class declaration in C++.
>                                 } elsif ($opv eq ':C' || $opv eq ':L') {
> -                                       if ($ctx =~ /Wx./) {
> +                                       if ($ctx =~ /Wx./ && $line !~ /class/) {
>                                                 ERROR("space prohibited before that '$op' $at\n" . $hereptr);
>                                         }
> 
> @@ -2135,6 +2144,18 @@ sub process {
>                                 } elsif ($ctx !~ /[EWC]x[CWE]/) {
>                                         my $ok = 0;
> 
> +                                       if ($realfile =~ /\.cpp|\.h$/) {
> +                                               # Ignore template arguments <...> in C++
> +                                               if (($op eq '<' || $op eq '>') && $line =~ /<.*>/) {
> +                                                       $ok = 1;
> +                                               }
> +
> +                                               # Ignore :: in C++
> +                                               if ($op eq '::') {
> +                                                       $ok = 1;
> +                                               }
> +                                       }
> +
>                                         # Ignore email addresses <foo@bar>
>                                         if (($op eq '<' &&
>                                              $cc =~ /^\S+\@\S+>/) ||

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

* Re: [Qemu-devel] [PATCH v7 04/10] Add a script to extract VSS SDK headers on POSIX system
  2013-07-15 16:20 ` [Qemu-devel] [PATCH v7 04/10] Add a script to extract VSS SDK headers on POSIX system Tomoki Sekiyama
@ 2013-07-22 21:27   ` Michael Roth
  0 siblings, 0 replies; 24+ messages in thread
From: Michael Roth @ 2013-07-22 21:27 UTC (permalink / raw)
  To: Tomoki Sekiyama, qemu-devel
  Cc: libaiqing, ghammer, stefanha, lcapitulino, vrozenfe,
	Paolo Bonzini, seiji.aguchi, Laszlo Ersek, areis

Quoting Tomoki Sekiyama (2013-07-15 11:20:41)
> 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: Paolo Bonzini <pbonzini@redhat.com>
> Signed-off-by: Tomoki Sekiyama <tomoki.sekiyama@hds.com>
> Reviewed-by: Laszlo Ersek <lersek@redhat.com>

Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>

> ---
>  scripts/extract-vsssdk-headers |   35 +++++++++++++++++++++++++++++++++++
>  1 file changed, 35 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..9e38510
> --- /dev/null
> +++ b/scripts/extract-vsssdk-headers
> @@ -0,0 +1,35 @@
> +#! /bin/bash
> +
> +# extract-vsssdk-headers
> +# Author: Paolo Bonzini <pbonzini@redhat.com>
> +
> +set -e
> +if test $# != 1 || ! test -f "$1"; then
> +  echo 'Usage: extract-vsssdk-headers /path/to/setup.exe' >&2
> +  exit 1
> +fi
> +
> +if ! command -v msiextract > /dev/null; then
> +  echo 'msiextract not found. Please install msitools.' >&2
> +  exit 1
> +fi
> +
> +if test -e inc; then
> +  echo '"inc" already exists.' >&2
> +  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')
> +tmpdir=$(mktemp -d)
> +trap 'rm -fr -- "$tmpdir" vsssdk.msi' EXIT HUP INT QUIT ALRM TERM
> +tail -c +$(($offset+1)) -- "$1" > vsssdk.msi
> +
> +# Now extract the files.
> +msiextract -C $tmpdir vsssdk.msi
> +mv "$tmpdir/Program Files/Microsoft/VSSSDK72/inc" inc
> +echo 'Extracted SDK headers into "inc" directory.'
> +exit 0

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

* Re: [Qemu-devel] [PATCH v7 00/10] qemu-ga: fsfreeze on Windows using VSS
  2013-07-22 20:33       ` Michael Roth
@ 2013-07-22 21:33         ` Tomoki Sekiyama
  0 siblings, 0 replies; 24+ messages in thread
From: Tomoki Sekiyama @ 2013-07-22 21:33 UTC (permalink / raw)
  To: Michael Roth, qemu-devel
  Cc: libaiqing, ghammer, stefanha, lcapitulino, vrozenfe, pbonzini,
	Seiji Aguchi, lersek, areis

Hi Michael,
Thank you for testing.

> So I think that solves the 'hang'/CoCreateInstance issue, although it would
> be nice if 32-bit could run on 64-bit, since that's supported currently. Is
> this a known issue/limitation? If so, perhaps we can avoid registering the
> VSS provider if the arch doesn't match?

Agreed.
It's a known limitation. VSS provider is required to be matched with the OS arch.
I will add some code to skip installation of VSS provider if the arch doesn't match.

> Also, with 64-bit qemu-ga I do find that if I don't issue `net stop vss` prior
> to service install I still get the following error:
> 
> C:\Users\mdroth\Documents\qga>qemu-ga.exe -s install
>  Registering QEMU Guest Agent VSS Provider:
>    C:\Users\mdroth\Documents\qga\qga-vss.dll
>    C:\Users\mdroth\Documents\qga\qga-vss.tlb
>  Failed to pCatalog->InstallComponent. (Error: 8011045c) The application name is
>  not unique and cannot be resolved to an application id

This is caused because VSS provider is already registered.
(And at the second time, it succeeds because doubled providers are removed...
> Removing COM+ Application: QEMU Guest Agent VSS Provider
> Removing COM+ Application: QEMU Guest Agent VSS Provider
).
This seems a side effect of removal of "unregistration before registration" code in v5.
I will fix this by checking if the provider with the same name is already registered
and then making the installation fail by error.

Thanks,
Tomoki Sekiyama

________________________________________
From: fluxion [flukshun@gmail.com] on behalf of Michael Roth [mdroth@linux.vnet.ibm.com]
Sent: Monday, July 22, 2013 4:33 PM
To: Tomoki Sekiyama; qemu-devel@nongnu.org
Cc: libaiqing@huawei.com; lersek@redhat.com; ghammer@redhat.com; stefanha@gmail.com; lcapitulino@redhat.com; vrozenfe@redhat.com; pbonzini@redhat.com; Seiji Aguchi; eblake@redhat.com; areis@redhat.com
Subject: Re: RE: [PATCH v7 00/10] qemu-ga: fsfreeze on Windows using VSS

Quoting Tomoki Sekiyama (2013-07-22 15:02:23)
> Hi Michael,
>
> >> "CoCreateInstance(VSSCoordinator) failed. (Error: 80040154) Class not registered
> >I have seen this error when I ran 32bit qemu-ga on 64bit Windows (2008 server R2).
> >Just in case, could you confirm qemu-ga.exe and qga-vss.dll are built for the
> >correct architecture?
>
> I have confirmed that using 32bit qemu-ga.exe on 64bit Windows causes exactly
> what you explained at the previous e-mail. (And maybe the hung is caused by a
> dialog box popped up *behind* the terminal.... I think this is because the box
> belongs to a Windows service, but I don't know how to avoid it...)

Thanks, I was just about to confirm as well :) Problem doesn't seem to be
present if I switch to a 64-bit version.

And you're right, in the instances where the -s install freezes a dialog box
*does* pop up behind the terminal with the above error.

>
> Could you tell me which arch (32bit/64bit) of Windows and mingw
> (mingw32-* or mingw64-* in Fedora package) are you using?

This was a 32-bit binary (--cross-prefix=i686-w64-mingw32-) on a 64-bit
Windows 7 vm.

I've since built a 64-bit binary (--cross-prefix=x86_64-w64-mingw32-) and have
gotten past service install and successfully issued the freeze/thaw commands.

So I think that solves the 'hang'/CoCreateInstance issue, although it would
be nice if 32-bit could run on 64-bit, since that's supported currently. Is
this a known issue/limitation? If so, perhaps we can avoid registering the
VSS provider if the arch doesn't match?

Also, with 64-bit qemu-ga I do find that if I don't issue `net stop vss` prior
to service install I still get the following error:

 C:\Users\mdroth\Documents\qga>qemu-ga.exe -s install
 Registering QEMU Guest Agent VSS Provider:
   C:\Users\mdroth\Documents\qga\qga-vss.dll
   C:\Users\mdroth\Documents\qga\qga-vss.tlb
 Failed to pCatalog->InstallComponent. (Error: 8011045c) The application name is
 not unique and cannot be resolved to an application id

 CoCreateInstance. (Error: 80040154) Class not registered

 Removing COM+ Application: QEMU Guest Agent VSS Provider
 Removing COM+ Application: QEMU Guest Agent VSS Provider

Is this expected? And if there's no way around it, would it be possible to
notify users that they need to stop the VSS service prior to install the
service?

Thanks for looking into this!

>
> Thanks,
> Tomoki Sekiyama
>
> ________________________________________
> From: fluxion [flukshun@gmail.com] on behalf of Michael Roth [mdroth@linux.vnet.ibm.com]
> Sent: Thursday, July 18, 2013 6:19 PM
> To: Tomoki Sekiyama; qemu-devel@nongnu.org
> Cc: libaiqing@huawei.com; lersek@redhat.com; ghammer@redhat.com; stefanha@gmail.com; lcapitulino@redhat.com; vrozenfe@redhat.com; pbonzini@redhat.com; Seiji Aguchi; eblake@redhat.com; areis@redhat.com
> Subject: Re: [PATCH v7 00/10] qemu-ga: fsfreeze on Windows using VSS
>
> Quoting Tomoki Sekiyama (2013-07-15 11:20:23)
> > Hi,
> >
> > This is v7 of patch series to add fsfreeze for Windows qemu-guest-agent.
> >
> > changes from v7:
> >  - Fix COM initialization issue for Windows service thread (patch 07/10)
> >
> > v6: http://lists.nongnu.org/archive/html/qemu-devel/2013-07/msg01788.html
>
> Hi Tomoki,
>
> I'm also having some issues testing this, though I think my problem is a little
> different than the issue in v6:
>
> When I initially ran qemu-ga -s install, I got some output indicating the VSS
> service was registered, but then it hung. I noticed afterward that I'd already
> had the service running, so figured that that might've been the problem. So I
> stopped the service and unregistered it (using a qemu-ga install that was in
> a separate directory).
>
> Then I went back to install via qemu-ga.exe -s install, and it just hangs with
> no output. I wasn't sure how to reset the state, so I took the Windows approach
> and rebooted.
>
> After reboot, running qemu-ga -s install gives me:
>
> C:\Users\mdroth\Documents\qga>qemu-ga.exe -s install
> Registering QEMU Guest Agent VSS Provider:
>   C:\Users\mdroth\Documents\qga\qga-vss.dll
>   C:\Users\mdroth\Documents\qga\qga-vss.tlb
> Failed to pCatalog->InstallComponent. (Error: 8011045c) The application name is
> not unique and cannot be resolved to an application id
>
> CoCreateInstance. (Error: 80040154) Class not registered
>
> Removing COM+ Application: QEMU Guest Agent VSS Provider
> Removing COM+ Application: QEMU Guest Agent VSS Provider
>
> [mdroth@vm5 ~]$
>
> I'm not sure if I'm still in a bad state from earlier, but I can't seem to
> recover from here.
>
> If I try running qemu-ga -s uninstall, then qemu-ga -s install again, I get a
> pop-up error saying:
>
> "CoCreateInstance(VSSCoordinator) failed. (Error: 80040154) Class not registered
>
> Any ideas what's going on here? I'm on a Windows 7 vm and built using a Fedora
> 18 mingw environment. Let me know if you need any additional information to
> debug.
>
> Thanks!
>
> >
> >
> > * 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 qga/vss-win32/qga-vss.{dll,tlb}
> >
> >  - Install qemu-ga.exe, qga/vss-win32/qga-vss.{dll,tlb}, and
> >    the other required mingw libraries into the same directory in guests
> >
> >  - Run `qemu-ga.exe -s install' and `net start qemu-ga' in the guests
> >
> > Any feedback are appreciated.
> >
> > ---
> > Tomoki Sekiyama (10):
> >       configure: Support configuring C++ compiler
> >       Add c++ keywords to QAPI helper script
> >       checkpatch.pl: Check .cpp files
> >       Add a script to extract VSS SDK headers on POSIX system
> >       qemu-ga: Add configure options to specify path to Windows/VSS SDK
> >       error: Add error_set_win32 and error_setg_win32
> >       qemu-ga: Add Windows VSS provider and requester as DLL
> >       qemu-ga: Call Windows VSS requester in fsfreeze command handler
> >       qemu-ga: Install Windows VSS provider on `qemu-ga -s install'
> >       QMP/qemu-ga-client: Make timeout longer for guest-fsfreeze-freeze command
> >
> >
> >  .gitignore                     |    1
> >  Makefile                       |    3
> >  Makefile.objs                  |    2
> >  QMP/qemu-ga-client             |    4
> >  configure                      |   87 +++++++
> >  hmp.c                          |    2
> >  hw/pci/pci.c                   |    2
> >  include/qapi/error.h           |   13 +
> >  qga/Makefile.objs              |    5
> >  qga/commands-win32.c           |   82 ++++++
> >  qga/main.c                     |   10 +
> >  qga/vss-win32.c                |  154 ++++++++++++
> >  qga/vss-win32.h                |   27 ++
> >  qga/vss-win32/Makefile.objs    |   23 ++
> >  qga/vss-win32/install.cpp      |  424 +++++++++++++++++++++++++++++++++
> >  qga/vss-win32/provider.cpp     |  513 ++++++++++++++++++++++++++++++++++++++++
> >  qga/vss-win32/qga-vss.def      |   13 +
> >  qga/vss-win32/qga-vss.idl      |   20 ++
> >  qga/vss-win32/qga-vss.tlb      |  Bin
> >  qga/vss-win32/requester.cpp    |  487 ++++++++++++++++++++++++++++++++++++++
> >  qga/vss-win32/requester.h      |   42 +++
> >  qga/vss-win32/vss-common.h     |  128 ++++++++++
> >  rules.mak                      |    9 +
> >  scripts/checkpatch.pl          |   37 ++-
> >  scripts/extract-vsssdk-headers |   35 +++
> >  scripts/qapi.py                |   12 +
> >  util/error.c                   |   35 +++
> >  27 files changed, 2146 insertions(+), 24 deletions(-)
> >  create mode 100644 qga/vss-win32.c
> >  create mode 100644 qga/vss-win32.h
> >  create mode 100644 qga/vss-win32/Makefile.objs
> >  create mode 100644 qga/vss-win32/install.cpp
> >  create mode 100644 qga/vss-win32/provider.cpp
> >  create mode 100644 qga/vss-win32/qga-vss.def
> >  create mode 100644 qga/vss-win32/qga-vss.idl
> >  create mode 100644 qga/vss-win32/qga-vss.tlb
> >  create mode 100644 qga/vss-win32/requester.cpp
> >  create mode 100644 qga/vss-win32/requester.h
> >  create mode 100644 qga/vss-win32/vss-common.h
> >  create mode 100755 scripts/extract-vsssdk-headers

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

* Re: [Qemu-devel] [PATCH v7 05/10] qemu-ga: Add configure options to specify path to Windows/VSS SDK
  2013-07-15 16:20 ` [Qemu-devel] [PATCH v7 05/10] qemu-ga: Add configure options to specify path to Windows/VSS SDK Tomoki Sekiyama
@ 2013-07-22 21:42   ` Michael Roth
  0 siblings, 0 replies; 24+ messages in thread
From: Michael Roth @ 2013-07-22 21:42 UTC (permalink / raw)
  To: Tomoki Sekiyama, qemu-devel
  Cc: libaiqing, ghammer, stefanha, lcapitulino, vrozenfe, pbonzini,
	seiji.aguchi, Laszlo Ersek, areis

Quoting Tomoki Sekiyama (2013-07-15 11:20:45)
> To enable VSS support in qemu-ga for Windows, header files included in
> VSS SDK are required.
> The VSS support is enabled by the configure option like below:
>   ./configure --with-vss-sdk="/path/to/VSS SDK"
> 
> If the path is omitted, it tries to search the headers from default paths
> and VSS support is enabled only if the SDK is found.
> VSS support is disabled if --without-vss-sdk or --with-vss-sdk=no is
> specified.
> 
> VSS SDK is available from:
>   http://www.microsoft.com/en-us/download/details.aspx?id=23490
> 
> To cross-compile using mingw, you need to setup the SDK on Windows
> environments to extract headers. You can also extract the SDK headers on
> POSIX environments using scripts/extract-vss-headers and msitools.
> 
> In addition, --with-win-sdk="/path/to/Windows SDK" option is also added to
> specify path to Windows SDK, which may be used for native-compile of .tlb
> file of qemu-ga VSS provider. However, this is usually unnecessary because
> pre-compiled .tlb file is included.
> 
> Signed-off-by: Tomoki Sekiyama <tomoki.sekiyama@hds.com>
> Reviewed-by: Laszlo Ersek <lersek@redhat.com>

Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>

> ---
>  .gitignore |    1 +
>  Makefile   |    1 +
>  configure  |   69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 71 insertions(+)
> 
> diff --git a/.gitignore b/.gitignore
> index 0fe114d..02d15f0 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 c06bfab..ec35a15 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -273,6 +273,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
>         if test -f dtc/version_gen.h; then make $(DTC_MAKE_ARGS) clean; fi
> 
> diff --git a/configure b/configure
> index 6923b65..8e1147f 100755
> --- a/configure
> +++ b/configure
> @@ -232,6 +232,8 @@ usb_redir=""
>  glx=""
>  zlib="yes"
>  guest_agent="yes"
> +guest_agent_with_vss="no"
> +vss_win32_sdk=""
>  want_tools="yes"
>  libiscsi=""
>  coroutine=""
> @@ -926,6 +928,14 @@ 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"
> +  ;;
> +  --with-win-sdk=*) win_sdk="$optarg"
> +  ;;
>    --enable-tools) want_tools="yes"
>    ;;
>    --disable-tools) want_tools="no"
> @@ -1158,6 +1168,8 @@ 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 "  --with-win-sdk=SDK-path  path to Windows Platform SDK (to build VSS .tlb)"
>  echo "  --disable-seccomp        disable seccomp support"
>  echo "  --enable-seccomp         enables seccomp support"
>  echo "  --with-coroutine=BACKEND coroutine backend. Supported options:"
> @@ -3072,6 +3084,57 @@ 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
> +
> +##########################################
> +# lookup Windows platform SDK (if not specified)
> +# The SDK is needed only to build .tlb (type library) file of guest agent
> +# VSS provider from the source. It is usually unnecessary because the
> +# pre-compiled .tlb file is included.
> +
> +if test "$mingw32" = "yes" -a "$guest_agent" = "yes" -a "$guest_agent_with_vss" = "yes" ; then
> +  if test -z "$win_sdk"; then
> +    programfiles="$PROGRAMFILES"
> +    test -n "$PROGRAMW6432" && programfiles="$PROGRAMW6432"
> +    if test -n "$programfiles"; then
> +      win_sdk=$(ls -d "$programfiles/Microsoft SDKs/Windows/v"* | tail -1) 2>/dev/null
> +    fi
> +  fi
> +fi
> +
> +##########################################
> 
>  ##########################################
>  # check if we have fdatasync
> @@ -3503,6 +3566,7 @@ echo "Manual directory  `eval echo $mandir`"
>  echo "ELF interp prefix $interp_prefix"
>  else
>  echo "local state directory   queried at runtime"
> +echo "Windows SDK       $win_sdk"
>  fi
>  echo "Source path       $source_path"
>  echo "C compiler        $cc"
> @@ -3589,6 +3653,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"
> @@ -3663,6 +3728,10 @@ 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
> +    echo "WIN_SDK=\"$win_sdk\"" >> $config_host_mak
> +  fi
>  else
>    echo "CONFIG_POSIX=y" >> $config_host_mak
>  fi

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

* Re: [Qemu-devel] [PATCH v7 06/10] error: Add error_set_win32 and error_setg_win32
  2013-07-15 16:20 ` [Qemu-devel] [PATCH v7 06/10] error: Add error_set_win32 and error_setg_win32 Tomoki Sekiyama
@ 2013-07-22 21:50   ` Michael Roth
  0 siblings, 0 replies; 24+ messages in thread
From: Michael Roth @ 2013-07-22 21:50 UTC (permalink / raw)
  To: Tomoki Sekiyama, qemu-devel
  Cc: libaiqing, ghammer, stefanha, lcapitulino, vrozenfe, pbonzini,
	seiji.aguchi, lersek, areis

Quoting Tomoki Sekiyama (2013-07-15 11:20:49)
> These functions help maintaining homogeneous formatting of error messages
> with Windows error code and description (generated by
> g_win32_error_message()).
> 
> Signed-off-by: Tomoki Sekiyama <tomoki.sekiyama@hds.com>

Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>

> ---
>  include/qapi/error.h |   13 +++++++++++++
>  util/error.c         |   35 +++++++++++++++++++++++++++++++++++
>  2 files changed, 48 insertions(+)
> 
> diff --git a/include/qapi/error.h b/include/qapi/error.h
> index ffd1cea..7d4c696 100644
> --- a/include/qapi/error.h
> +++ b/include/qapi/error.h
> @@ -36,6 +36,15 @@ void error_set(Error **err, ErrorClass err_class, const char *fmt, ...) GCC_FMT_
>   */
>  void error_set_errno(Error **err, int os_error, ErrorClass err_class, const char *fmt, ...) GCC_FMT_ATTR(4, 5);
> 
> +#ifdef _WIN32
> +/**
> + * Set an indirect pointer to an error given a ErrorClass value and a
> + * printf-style human message, followed by a g_win32_error_message() string if
> + * @win32_err is not zero.
> + */
> +void error_set_win32(Error **err, int win32_err, ErrorClass err_class, const char *fmt, ...) GCC_FMT_ATTR(4, 5);
> +#endif
> +
>  /**
>   * Same as error_set(), but sets a generic error
>   */
> @@ -43,6 +52,10 @@ void error_set_errno(Error **err, int os_error, ErrorClass err_class, const char
>      error_set(err, ERROR_CLASS_GENERIC_ERROR, fmt, ## __VA_ARGS__)
>  #define error_setg_errno(err, os_error, fmt, ...) \
>      error_set_errno(err, os_error, ERROR_CLASS_GENERIC_ERROR, fmt, ## __VA_ARGS__)
> +#ifdef _WIN32
> +#define error_setg_win32(err, win32_err, fmt, ...) \
> +    error_set_win32(err, win32_err, ERROR_CLASS_GENERIC_ERROR, fmt, ## __VA_ARGS__)
> +#endif
> 
>  /**
>   * Helper for open() errors
> diff --git a/util/error.c b/util/error.c
> index 53b0435..ec0faa6 100644
> --- a/util/error.c
> +++ b/util/error.c
> @@ -76,6 +76,41 @@ void error_setg_file_open(Error **errp, int os_errno, const char *filename)
>      error_setg_errno(errp, os_errno, "Could not open '%s'", filename);
>  }
> 
> +#ifdef _WIN32
> +
> +void error_set_win32(Error **errp, int win32_err, ErrorClass err_class,
> +                     const char *fmt, ...)
> +{
> +    Error *err;
> +    char *msg1;
> +    va_list ap;
> +
> +    if (errp == NULL) {
> +        return;
> +    }
> +    assert(*errp == NULL);
> +
> +    err = g_malloc0(sizeof(*err));
> +
> +    va_start(ap, fmt);
> +    msg1 = g_strdup_vprintf(fmt, ap);
> +    if (win32_err != 0) {
> +        char *msg2 = g_win32_error_message(win32_err);
> +        err->msg = g_strdup_printf("%s: %s (error: %x)", msg1, msg2,
> +                                   (unsigned)win32_err);
> +        g_free(msg2);
> +        g_free(msg1);
> +    } else {
> +        err->msg = msg1;
> +    }
> +    va_end(ap);
> +    err->err_class = err_class;
> +
> +    *errp = err;
> +}
> +
> +#endif
> +
>  Error *error_copy(const Error *err)
>  {
>      Error *err_new;

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

* Re: [Qemu-devel] [PATCH v7 03/10] checkpatch.pl: Check .cpp files
  2013-07-22 21:21   ` Michael Roth
@ 2013-07-23 21:49     ` Tomoki Sekiyama
  0 siblings, 0 replies; 24+ messages in thread
From: Tomoki Sekiyama @ 2013-07-23 21:49 UTC (permalink / raw)
  To: Michael Roth, qemu-devel
  Cc: libaiqing, ghammer, stefanha, lcapitulino, vrozenfe, pbonzini,
	Seiji Aguchi, lersek, areis

On 7/22/13 17:21 , "Michael Roth" <mdroth@linux.vnet.ibm.com> wrote:

>Quoting Tomoki Sekiyama (2013-07-15 11:20:37)
>> Enable checkpatch.pl to apply the same checks as C source files for
>> C++ files with .cpp extensions. It also adds some exceptions for C++
>> sources to suppress errors for:
>>   - <> used in C++ template arguments (e.g. template <class T>)
>>   - :: used to represent namespaces   (e.g. SomeClass::method())
>>   - : used in class declaration       (e.g. class T : public Super)
>>   - ~ used in destructor method name  (e.g. T::~T())
>>   - spacing around 'catch'            (e.g. catch (...))
>> 
>> Signed-off-by: Tomoki Sekiyama <tomoki.sekiyama@hds.com>
>
>One small nit below about documentation. Looks good otherwise.
<snip>
>>@@ -2066,7 +2069,8 @@ sub process {
>>                                 #   ->
>>                                 #   :   when part of a bitfield
>>                                 } elsif ($op eq '->' || $opv eq ':B') {
>> -                                       if ($ctx =~ /Wx.|.xW/) {
>> +                                       if ($ctx =~ /Wx.|.xW/ &&
>> +                                               !($opv eq ':B' && $line
>>=~ /class/)) {
>
>Everything else seemed fairly obvious or was well commented, but I
>couldn't
>figure out what this change was for. Could you insert a small comment to
>explain?

Sure. This is suppressing errors for : used in class declaration.
I will do some cleanups for this.

Thanks,
Tomoki Sekiyama

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

* Re: [Qemu-devel] [PATCH v7 01/10] configure: Support configuring C++ compiler
  2013-07-22 20:53   ` Michael Roth
@ 2013-07-23 21:49     ` Tomoki Sekiyama
  0 siblings, 0 replies; 24+ messages in thread
From: Tomoki Sekiyama @ 2013-07-23 21:49 UTC (permalink / raw)
  To: Michael Roth, qemu-devel
  Cc: libaiqing, ghammer, stefanha, lcapitulino, vrozenfe, pbonzini,
	Seiji Aguchi, Laszlo Ersek, areis

Hi Michael,
Thanks for your review.

On 7/22/13 16:53 , "Michael Roth" <mdroth@linux.vnet.ibm.com> wrote:

>Quoting Tomoki Sekiyama (2013-07-15 11:20:29)
>> Add configuration for C++ compiler in configure and Makefiles.
>> The C++ compiler is choosed as following:
>>  - ${CXX}, if it is specified.
>>  - ${cross_prefix}g++, if ${cross_prefix} is specified.
>>  - Otherwise, c++ is used.
>> 
>> 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>
>> Reviewed-by: Laszlo Ersek <lersek@redhat.com>
>> ---
>>  configure |   13 +++++++++++++
>>  rules.mak |    9 ++++++++-
>>  2 files changed, 21 insertions(+), 1 deletion(-)
>> 
>> diff --git a/configure b/configure
>> index cb0f870..6923b65 100755
>> --- a/configure
>> +++ b/configure
>> @@ -251,6 +251,8 @@ for opt do
>>    ;;
>>    --cc=*) CC="$optarg"
>>    ;;
>> +  --cxx=*) CXX="$optarg"
>> +  ;;
>>    --source-path=*) source_path="$optarg"
>>    ;;
>>    --cpu=*) cpu="$optarg"
>> @@ -281,6 +283,12 @@ else
>>    cc="${CC-${cross_prefix}gcc}"
>>  fi
>> 
>> +if test -z "${CXX}${cross_prefix}"; then
>> +  cxx="c++"
>> +else
>> +  cxx="${CXX-${cross_prefix}g++}"
>> +fi
>> +
>>  ar="${AR-${cross_prefix}ar}"
>>  as="${AS-${cross_prefix}as}"
>>  cpp="${CPP-$cc -E}"
>> @@ -621,6 +629,8 @@ for opt do
>>    ;;
>>    --host-cc=*) host_cc="$optarg"
>>    ;;
>> +  --cxx=*) cxx="$optarg"
>> +  ;;
>
>Since we've already determined cxx in the first pass (overriding other
>defaults --cxx argument if it's present), I think re-assigning here
>is unecessary.
>
>Otherwise looks good.

OK, I will remove the assignment.

Thanks,
Tomoki Sekiyama

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

end of thread, other threads:[~2013-07-23 21:50 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-07-15 16:20 [Qemu-devel] [PATCH v7 00/10] qemu-ga: fsfreeze on Windows using VSS Tomoki Sekiyama
2013-07-15 16:20 ` [Qemu-devel] [PATCH v7 01/10] configure: Support configuring C++ compiler Tomoki Sekiyama
2013-07-22 20:53   ` Michael Roth
2013-07-23 21:49     ` Tomoki Sekiyama
2013-07-15 16:20 ` [Qemu-devel] [PATCH v7 02/10] Add c++ keywords to QAPI helper script Tomoki Sekiyama
2013-07-22 20:55   ` Michael Roth
2013-07-15 16:20 ` [Qemu-devel] [PATCH v7 03/10] checkpatch.pl: Check .cpp files Tomoki Sekiyama
2013-07-22 21:21   ` Michael Roth
2013-07-23 21:49     ` Tomoki Sekiyama
2013-07-15 16:20 ` [Qemu-devel] [PATCH v7 04/10] Add a script to extract VSS SDK headers on POSIX system Tomoki Sekiyama
2013-07-22 21:27   ` Michael Roth
2013-07-15 16:20 ` [Qemu-devel] [PATCH v7 05/10] qemu-ga: Add configure options to specify path to Windows/VSS SDK Tomoki Sekiyama
2013-07-22 21:42   ` Michael Roth
2013-07-15 16:20 ` [Qemu-devel] [PATCH v7 06/10] error: Add error_set_win32 and error_setg_win32 Tomoki Sekiyama
2013-07-22 21:50   ` Michael Roth
2013-07-15 16:20 ` [Qemu-devel] [PATCH v7 07/10] qemu-ga: Add Windows VSS provider and requester as DLL Tomoki Sekiyama
2013-07-15 16:20 ` [Qemu-devel] [PATCH v7 08/10] qemu-ga: Call Windows VSS requester in fsfreeze command handler Tomoki Sekiyama
2013-07-15 16:21 ` [Qemu-devel] [PATCH v7 09/10] qemu-ga: Install Windows VSS provider on `qemu-ga -s install' Tomoki Sekiyama
2013-07-15 16:21 ` [Qemu-devel] [PATCH v7 10/10] QMP/qemu-ga-client: Make timeout longer for guest-fsfreeze-freeze command Tomoki Sekiyama
2013-07-18 22:19 ` [Qemu-devel] [PATCH v7 00/10] qemu-ga: fsfreeze on Windows using VSS Michael Roth
2013-07-19  3:40   ` Tomoki Sekiyama
2013-07-22 20:02     ` Tomoki Sekiyama
2013-07-22 20:33       ` Michael Roth
2013-07-22 21:33         ` Tomoki Sekiyama

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.