123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- /*
- * 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 "qemu/osdep.h"
- #include <windows.h>
- #include "qapi/error.h"
- #include "qemu/error-report.h"
- #include "guest-agent-core.h"
- #include "vss-win32.h"
- #include "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) {
- warn_report("Running under WOW64");
- }
- #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)
- {
- 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, bool freeze,
- strList *mountpoints, Error **errp)
- {
- const char *func_name = freeze ? "requester_freeze" : "requester_thaw";
- QGAVSSRequesterFunc func;
- ErrorSet errset = {
- .error_setg_win32_wrapper = error_setg_win32_internal,
- .errp = errp,
- };
- g_assert(errp); /* requester.cpp requires it */
- func = (QGAVSSRequesterFunc)GetProcAddress(provider_lib, func_name);
- if (!func) {
- error_setg_win32(errp, GetLastError(), "failed to load %s from %s",
- func_name, QGA_VSS_DLL);
- return;
- }
- func(nr_volume, mountpoints, &errset);
- }
|