/*
 * QEMU Guest Agent helpers for win32 service management
 *
 * Copyright IBM Corp. 2012
 *
 * Authors:
 *  Gal Hammer        <ghammer@redhat.com>
 *  Michael Roth      <mdroth@linux.vnet.ibm.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 <stdlib.h>
#include <stdio.h>
#include <glib.h>
#include <windows.h>
#include "qga/service-win32.h"

static int printf_win_error(const char *text)
{
    DWORD err = GetLastError();
    char *message;
    int n;

    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
        FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL,
        err,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (char *)&message, 0,
        NULL);
    n = printf("%s. (Error: %d) %s", text, (int)err, message);
    LocalFree(message);

    return n;
}

int ga_install_service(const char *path, const char *logfile)
{
    SC_HANDLE manager;
    SC_HANDLE service;
    TCHAR cmdline[MAX_PATH];

    if (GetModuleFileName(NULL, cmdline, MAX_PATH) == 0) {
        printf_win_error("No full path to service's executable");
        return EXIT_FAILURE;
    }

    _snprintf(cmdline, MAX_PATH - strlen(cmdline), "%s -d", cmdline);

    if (path) {
        _snprintf(cmdline, MAX_PATH - strlen(cmdline), "%s -p %s", cmdline, path);
    }
    if (logfile) {
        _snprintf(cmdline, MAX_PATH - strlen(cmdline), "%s -l %s -v",
            cmdline, logfile);
    }

    g_debug("service's cmdline: %s", cmdline);

    manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    if (manager == NULL) {
        printf_win_error("No handle to service control manager");
        return EXIT_FAILURE;
    }

    service = CreateService(manager, QGA_SERVICE_NAME, QGA_SERVICE_DISPLAY_NAME,
        SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START,
        SERVICE_ERROR_NORMAL, cmdline, NULL, NULL, NULL, NULL, NULL);

    if (service) {
        SERVICE_DESCRIPTION desc = { (char *)QGA_SERVICE_DESCRIPTION };
        ChangeServiceConfig2(service, SERVICE_CONFIG_DESCRIPTION, &desc);

        printf("Service was installed successfully.\n");
    } else {
        printf_win_error("Failed to install service");
    }

    CloseServiceHandle(service);
    CloseServiceHandle(manager);

    return (service == NULL);
}

int ga_uninstall_service(void)
{
    SC_HANDLE manager;
    SC_HANDLE service;

    manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    if (manager == NULL) {
        printf_win_error("No handle to service control manager");
        return EXIT_FAILURE;
    }

    service = OpenService(manager, QGA_SERVICE_NAME, DELETE);
    if (service == NULL) {
        printf_win_error("No handle to service");
        CloseServiceHandle(manager);
        return EXIT_FAILURE;
    }

    if (DeleteService(service) == FALSE) {
        printf_win_error("Failed to delete service");
    } else {
        printf("Service was deleted successfully.\n");
    }

    CloseServiceHandle(service);
    CloseServiceHandle(manager);

    return EXIT_SUCCESS;
}
