/*
 * 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);
}
