Commit f69f0bca authored by Anthony Liguori's avatar Anthony Liguori
Browse files

Merge remote-tracking branch 'mdroth/qga-pull-2013-9-9' into staging



# By Tomoki Sekiyama (10) and Paul Burton (1)
# Via Michael Roth
* mdroth/qga-pull-2013-9-9:
  QMP/qemu-ga-client: Make timeout longer for guest-fsfreeze-freeze command
  qemu-ga: Install Windows VSS provider on `qemu-ga -s install'
  qemu-ga: Call Windows VSS requester in fsfreeze command handler
  qemu-ga: Add Windows VSS provider and requester as DLL
  error: Add error_set_win32 and error_setg_win32
  qemu-ga: Add configure options to specify path to Windows/VSS SDK
  Add a script to extract VSS SDK headers on POSIX system
  checkpatch.pl: Check .cpp files
  Add c++ keywords to QAPI helper script
  configure: Support configuring C++ compiler
  mips_malta: support up to 2GiB RAM

Message-id: 1378755701-2051-1-git-send-email-mdroth@linux.vnet.ibm.com
Signed-off-by: default avatarAnthony Liguori <anthony@codemonkey.ws>
parents 97fdb941 e2682db0
......@@ -82,6 +82,7 @@ fsdev/virtfs-proxy-helper.pod
*.la
*.pc
.libs
.sdk
*.swp
*.orig
.pc
......
......@@ -235,7 +235,7 @@ clean:
rm -f qemu-options.def
find . -name '*.[oda]' -type f -exec rm -f {} +
find . -name '*.l[oa]' -type f -exec rm -f {} +
rm -f $(TOOLS) $(HELPERS-y) qemu-ga TAGS cscope.* *.pod *~ */*~
rm -f $(filter-out %.tlb,$(TOOLS)) $(HELPERS-y) qemu-ga TAGS cscope.* *.pod *~ */*~
rm -Rf .libs
rm -f qemu-img-cmds.h
@# May not be present in GENERATED_HEADERS
......@@ -272,6 +272,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
......
......@@ -109,6 +109,7 @@ version-lobj-$(CONFIG_WIN32) += $(BUILD_DIR)/version.lo
# FIXME: a few definitions from qapi-types.o/qapi-visit.o are needed
# by libqemuutil.a. These should be moved to a separate .json schema.
qga-obj-y = qga/ qapi-types.o qapi-visit.o
qga-vss-dll-obj-y = qga/
vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
......@@ -120,6 +121,7 @@ nested-vars += \
stub-obj-y \
util-obj-y \
qga-obj-y \
qga-vss-dll-obj-y \
block-obj-y \
common-obj-y
dummy := $(call unnest-vars)
......@@ -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)
......
......@@ -232,6 +232,9 @@ usb_redir=""
glx=""
zlib="yes"
guest_agent=""
guest_agent_with_vss="no"
vss_win32_sdk=""
win_sdk="no"
want_tools="yes"
libiscsi=""
coroutine=""
......@@ -252,6 +255,8 @@ for opt do
;;
--cc=*) CC="$optarg"
;;
--cxx=*) CXX="$optarg"
;;
--source-path=*) source_path="$optarg"
;;
--cpu=*) cpu="$optarg"
......@@ -282,6 +287,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}"
......@@ -626,6 +637,8 @@ for opt do
;;
--host-cc=*) host_cc="$optarg"
;;
--cxx=*)
;;
--objcc=*) objcc="$optarg"
;;
--make=*) make="$optarg"
......@@ -917,6 +930,18 @@ 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=""
;;
--with-win-sdk=*) win_sdk="$optarg"
;;
--without-win-sdk) win_sdk="no"
;;
--enable-tools) want_tools="yes"
;;
--disable-tools) want_tools="no"
......@@ -1032,6 +1057,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"
......@@ -1157,6 +1183,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:"
......@@ -3120,6 +3148,61 @@ if test "$usb_redir" != "no" ; then
fi
fi
##########################################
# check if we have VSS SDK headers for win
if test "$mingw32" = "yes" -a "$guest_agent" != "no" -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" != "no" -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
else
feature_not_found "Windows SDK"
fi
elif test "$win_sdk" = "no"; then
win_sdk=""
fi
fi
##########################################
##########################################
......@@ -3485,8 +3568,11 @@ if test "$softmmu" = yes ; then
fi
fi
if [ "$guest_agent" != "no" ]; then
if [ "$linux" = "yes" -o "$bsd" = "yes" -o "$solaris" = "yes" ] ; then
if [ "$linux" = "yes" -o "$bsd" = "yes" -o "$solaris" = "yes" -o "$mingw32" = "yes" ] ; then
tools="qemu-ga\$(EXESUF) $tools"
if [ "$mingw32" = "yes" -a "$guest_agent_with_vss" = "yes" ]; then
tools="qga/vss-win32/qga-vss.dll qga/vss-win32/qga-vss.tlb $tools"
fi
guest_agent=yes
elif [ "$guest_agent" != yes ]; then
guest_agent=no
......@@ -3557,10 +3643,12 @@ 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"
echo "Host C compiler $host_cc"
echo "C++ compiler $cxx"
echo "Objective-C compiler $objcc"
echo "CFLAGS $CFLAGS"
echo "QEMU_CFLAGS $QEMU_CFLAGS"
......@@ -3642,6 +3730,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"
......@@ -3716,6 +3805,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
......@@ -4148,6 +4241,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
......
......@@ -544,7 +544,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",
......
......@@ -827,7 +827,8 @@ static int64_t load_kernel (void)
}
prom_set(prom_buf, prom_index++, "memsize");
prom_set(prom_buf, prom_index++, "%i", loaderparams.ram_size);
prom_set(prom_buf, prom_index++, "%i",
MIN(loaderparams.ram_size, 256 << 20));
prom_set(prom_buf, prom_index++, "modetty0");
prom_set(prom_buf, prom_index++, "38400n8r");
prom_set(prom_buf, prom_index++, NULL);
......@@ -884,7 +885,9 @@ void mips_malta_init(QEMUMachineInitArgs *args)
char *filename;
pflash_t *fl;
MemoryRegion *system_memory = get_system_memory();
MemoryRegion *ram = g_new(MemoryRegion, 1);
MemoryRegion *ram_high = g_new(MemoryRegion, 1);
MemoryRegion *ram_low_preio = g_new(MemoryRegion, 1);
MemoryRegion *ram_low_postio;
MemoryRegion *bios, *bios_copy = g_new(MemoryRegion, 1);
target_long bios_size = FLASH_SIZE;
const size_t smbus_eeprom_size = 8 * 256;
......@@ -951,15 +954,32 @@ void mips_malta_init(QEMUMachineInitArgs *args)
env = &cpu->env;
/* allocate RAM */
if (ram_size > (256 << 20)) {
if (ram_size > (2048u << 20)) {
fprintf(stderr,
"qemu: Too much memory for this machine: %d MB, maximum 256 MB\n",
"qemu: Too much memory for this machine: %d MB, maximum 2048 MB\n",
((unsigned int)ram_size / (1 << 20)));
exit(1);
}
memory_region_init_ram(ram, NULL, "mips_malta.ram", ram_size);
vmstate_register_ram_global(ram);
memory_region_add_subregion(system_memory, 0, ram);
/* register RAM at high address where it is undisturbed by IO */
memory_region_init_ram(ram_high, NULL, "mips_malta.ram", ram_size);
vmstate_register_ram_global(ram_high);
memory_region_add_subregion(system_memory, 0x80000000, ram_high);
/* alias for pre IO hole access */
memory_region_init_alias(ram_low_preio, NULL, "mips_malta_low_preio.ram",
ram_high, 0, MIN(ram_size, (256 << 20)));
memory_region_add_subregion(system_memory, 0, ram_low_preio);
/* alias for post IO hole access, if there is enough RAM */
if (ram_size > (512 << 20)) {
ram_low_postio = g_new(MemoryRegion, 1);
memory_region_init_alias(ram_low_postio, NULL,
"mips_malta_low_postio.ram",
ram_high, 512 << 20,
ram_size - (512 << 20));
memory_region_add_subregion(system_memory, 512 << 20, ram_low_postio);
}
/* generate SPD EEPROM data */
generate_eeprom_spd(&smbus_eeprom_buf[0 * 256], ram_size);
......@@ -992,7 +1012,7 @@ void mips_malta_init(QEMUMachineInitArgs *args)
fl_idx++;
if (kernel_filename) {
/* Write a small bootloader to the flash location. */
loaderparams.ram_size = ram_size;
loaderparams.ram_size = MIN(ram_size, 256 << 20);
loaderparams.kernel_filename = kernel_filename;
loaderparams.kernel_cmdline = kernel_cmdline;
loaderparams.initrd_filename = initrd_filename;
......
......@@ -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;
......
......@@ -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
......
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
qga-vss-dll-obj-$(CONFIG_QGA_VSS) += vss-win32/
......@@ -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);
}
}
......@@ -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");
......
/*
* 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) {
BOOL wow64 = false;
#ifndef _WIN64
/* Provider doesn't work under WOW64 (32bit agent on 64bit OS) */
if (!IsWow64Process(GetCurrentProcess(), &wow64)) {
fprintf(stderr, "failed to IsWow64Process (Error: %lx\n)\n",
GetLastError());
return false;
}
if (wow64) {
fprintf(stderr, "Warning: Running under WOW64\n");
}
#endif
return !wow64;
}
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;
}
int ga_install_vss_provider(void)
{