/*
 *  openvpnmsica -- Custom Action DLL to provide OpenVPN-specific support to MSI packages
 *                  https://community.openvpn.net/openvpn/wiki/OpenVPNMSICA
 *
 *  Copyright (C) 2018-2021 Simon Rozman <simon@rozman.si>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License version 2
 *  as published by the Free Software Foundation.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#elif defined(_MSC_VER)
#include <config-msvc.h>
#endif

#include "msiex.h"
#include "../tapctl/error.h"

#include <windows.h>
#include <malloc.h>
#include <memory.h>
#include <msiquery.h>
#ifdef _MSC_VER
#pragma comment(lib, "msi.lib")
#endif


UINT
msi_get_string(
    _In_ MSIHANDLE hInstall,
    _In_z_ LPCTSTR szName,
    _Out_ LPTSTR *pszValue)
{
    if (pszValue == NULL)
    {
        return ERROR_BAD_ARGUMENTS;
    }

    /* Try with stack buffer first. */
    TCHAR szBufStack[128];
    DWORD dwLength = _countof(szBufStack);
    UINT uiResult = MsiGetProperty(hInstall, szName, szBufStack, &dwLength);
    if (uiResult == ERROR_SUCCESS)
    {
        /* Copy from stack. */
        *pszValue = (LPTSTR)malloc(++dwLength * sizeof(TCHAR));
        if (*pszValue == NULL)
        {
            msg(M_FATAL, "%s: malloc(%u) failed", dwLength * sizeof(TCHAR));
            return ERROR_OUTOFMEMORY;
        }

        memcpy(*pszValue, szBufStack, dwLength * sizeof(TCHAR));
        return ERROR_SUCCESS;
    }
    else if (uiResult == ERROR_MORE_DATA)
    {
        /* Allocate on heap and retry. */
        LPTSTR szBufHeap = (LPTSTR)malloc(++dwLength * sizeof(TCHAR));
        if (szBufHeap == NULL)
        {
            msg(M_FATAL, "%s: malloc(%u) failed", __FUNCTION__, dwLength * sizeof(TCHAR));
            return ERROR_OUTOFMEMORY;
        }

        uiResult = MsiGetProperty(hInstall, szName, szBufHeap, &dwLength);
        if (uiResult == ERROR_SUCCESS)
        {
            *pszValue = szBufHeap;
        }
        else
        {
            free(szBufHeap);
        }
        return uiResult;
    }
    else
    {
        SetLastError(uiResult); /* MSDN does not mention MsiGetProperty() to set GetLastError(). But we do have an error code. Set last error manually. */
        msg(M_NONFATAL | M_ERRNO, "%s: MsiGetProperty failed", __FUNCTION__);
        return uiResult;
    }
}


UINT
msi_get_record_string(
    _In_ MSIHANDLE hRecord,
    _In_ unsigned int iField,
    _Out_ LPTSTR *pszValue)
{
    if (pszValue == NULL)
    {
        return ERROR_BAD_ARGUMENTS;
    }

    /* Try with stack buffer first. */
    TCHAR szBufStack[128];
    DWORD dwLength = _countof(szBufStack);
    UINT uiResult = MsiRecordGetString(hRecord, iField, szBufStack, &dwLength);
    if (uiResult == ERROR_SUCCESS)
    {
        /* Copy from stack. */
        *pszValue = (LPTSTR)malloc(++dwLength * sizeof(TCHAR));
        if (*pszValue == NULL)
        {
            msg(M_FATAL, "%s: malloc(%u) failed", __FUNCTION__, dwLength * sizeof(TCHAR));
            return ERROR_OUTOFMEMORY;
        }

        memcpy(*pszValue, szBufStack, dwLength * sizeof(TCHAR));
        return ERROR_SUCCESS;
    }
    else if (uiResult == ERROR_MORE_DATA)
    {
        /* Allocate on heap and retry. */
        LPTSTR szBufHeap = (LPTSTR)malloc(++dwLength * sizeof(TCHAR));
        if (szBufHeap == NULL)
        {
            msg(M_FATAL, "%s: malloc(%u) failed", __FUNCTION__, dwLength * sizeof(TCHAR));
            return ERROR_OUTOFMEMORY;
        }

        uiResult = MsiRecordGetString(hRecord, iField, szBufHeap, &dwLength);
        if (uiResult == ERROR_SUCCESS)
        {
            *pszValue = szBufHeap;
        }
        else
        {
            free(szBufHeap);
        }
        return uiResult;
    }
    else
    {
        SetLastError(uiResult); /* MSDN does not mention MsiRecordGetString() to set GetLastError(). But we do have an error code. Set last error manually. */
        msg(M_NONFATAL | M_ERRNO, "%s: MsiRecordGetString failed", __FUNCTION__);
        return uiResult;
    }
}


UINT
msi_format_record(
    _In_ MSIHANDLE hInstall,
    _In_ MSIHANDLE hRecord,
    _Out_ LPTSTR *pszValue)
{
    if (pszValue == NULL)
    {
        return ERROR_BAD_ARGUMENTS;
    }

    /* Try with stack buffer first. */
    TCHAR szBufStack[128];
    DWORD dwLength = _countof(szBufStack);
    UINT uiResult = MsiFormatRecord(hInstall, hRecord, szBufStack, &dwLength);
    if (uiResult == ERROR_SUCCESS)
    {
        /* Copy from stack. */
        *pszValue = (LPTSTR)malloc(++dwLength * sizeof(TCHAR));
        if (*pszValue == NULL)
        {
            msg(M_FATAL, "%s: malloc(%u) failed", __FUNCTION__, dwLength * sizeof(TCHAR));
            return ERROR_OUTOFMEMORY;
        }

        memcpy(*pszValue, szBufStack, dwLength * sizeof(TCHAR));
        return ERROR_SUCCESS;
    }
    else if (uiResult == ERROR_MORE_DATA)
    {
        /* Allocate on heap and retry. */
        LPTSTR szBufHeap = (LPTSTR)malloc(++dwLength * sizeof(TCHAR));
        if (szBufHeap == NULL)
        {
            msg(M_FATAL, "%s: malloc(%u) failed", __FUNCTION__, dwLength * sizeof(TCHAR));
            return ERROR_OUTOFMEMORY;
        }

        uiResult = MsiFormatRecord(hInstall, hRecord, szBufHeap, &dwLength);
        if (uiResult == ERROR_SUCCESS)
        {
            *pszValue = szBufHeap;
        }
        else
        {
            free(szBufHeap);
        }
        return uiResult;
    }
    else
    {
        SetLastError(uiResult); /* MSDN does not mention MsiFormatRecord() to set GetLastError(). But we do have an error code. Set last error manually. */
        msg(M_NONFATAL | M_ERRNO, "%s: MsiFormatRecord failed", __FUNCTION__);
        return uiResult;
    }
}


UINT
msi_format_field(
    _In_ MSIHANDLE hInstall,
    _In_ MSIHANDLE hRecord,
    _In_ unsigned int iField,
    _Out_ LPTSTR *pszValue)
{
    if (pszValue == NULL)
    {
        return ERROR_BAD_ARGUMENTS;
    }

    /* Read string to format. */
    LPTSTR szValue = NULL;
    UINT uiResult = msi_get_record_string(hRecord, iField, &szValue);
    if (uiResult != ERROR_SUCCESS)
    {
        return uiResult;
    }
    if (szValue[0] == 0)
    {
        /* The string is empty. There's nothing left to do. */
        *pszValue = szValue;
        return ERROR_SUCCESS;
    }

    /* Create a temporary record. */
    MSIHANDLE hRecordEx = MsiCreateRecord(1);
    if (!hRecordEx)
    {
        uiResult = ERROR_INVALID_HANDLE;
        msg(M_NONFATAL, "%s: MsiCreateRecord failed", __FUNCTION__);
        goto cleanup_szValue;
    }

    /* Populate the record with data. */
    uiResult = MsiRecordSetString(hRecordEx, 0, szValue);
    if (uiResult != ERROR_SUCCESS)
    {
        SetLastError(uiResult); /* MSDN does not mention MsiRecordSetString() to set GetLastError(). But we do have an error code. Set last error manually. */
        msg(M_NONFATAL | M_ERRNO, "%s: MsiRecordSetString failed", __FUNCTION__);
        goto cleanup_hRecordEx;
    }

    /* Do the formatting. */
    uiResult = msi_format_record(hInstall, hRecordEx, pszValue);

cleanup_hRecordEx:
    MsiCloseHandle(hRecordEx);
cleanup_szValue:
    free(szValue);
    return uiResult;
}
