/*
 * Implementation of the Microsoft Installer (msi.dll)
 *
 * Copyright 2006 Mike McCormack for CodeWeavers
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include <stdarg.h>

#define COBJMACROS

#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#include "shlwapi.h"
#include "oleauto.h"
#include "rpcproxy.h"
#include "msipriv.h"
#include "msiserver.h"

#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(msi);

static LONG dll_count;

/* the UI level */
INSTALLUILEVEL           gUILevel         = INSTALLUILEVEL_DEFAULT;
HWND                     gUIhwnd          = 0;
INSTALLUI_HANDLERA       gUIHandlerA      = NULL;
INSTALLUI_HANDLERW       gUIHandlerW      = NULL;
INSTALLUI_HANDLER_RECORD gUIHandlerRecord = NULL;
DWORD                    gUIFilter        = 0;
DWORD                    gUIFilterRecord  = 0;
LPVOID                   gUIContext       = NULL;
LPVOID                   gUIContextRecord = NULL;
WCHAR                   *gszLogFile       = NULL;
HINSTANCE msi_hInstance;


/*
 * Dll lifetime tracking declaration
 */
static void LockModule(void)
{
    InterlockedIncrement(&dll_count);
}

static void UnlockModule(void)
{
    InterlockedDecrement(&dll_count);
}

/******************************************************************
 *      DllMain
 */
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    switch (fdwReason)
    {
    case DLL_PROCESS_ATTACH:
        msi_hInstance = hinstDLL;
        DisableThreadLibraryCalls(hinstDLL);
        IsWow64Process( GetCurrentProcess(), &is_wow64 );
        break;
    case DLL_PROCESS_DETACH:
        if (lpvReserved) break;
        msi_dialog_unregister_class();
        msi_free_handle_table();
        msi_free( gszLogFile );
        release_typelib();
        break;
    }
    return TRUE;
}

typedef struct tagIClassFactoryImpl {
    IClassFactory IClassFactory_iface;
    HRESULT (*create_object)( IUnknown*, LPVOID* );
} IClassFactoryImpl;

static inline IClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface)
{
    return CONTAINING_RECORD(iface, IClassFactoryImpl, IClassFactory_iface);
}

static HRESULT WINAPI MsiCF_QueryInterface(LPCLASSFACTORY iface,
                REFIID riid,LPVOID *ppobj)
{
    IClassFactoryImpl *This = impl_from_IClassFactory(iface);

    TRACE("%p %s %p\n",This,debugstr_guid(riid),ppobj);

    if( IsEqualCLSID( riid, &IID_IUnknown ) ||
        IsEqualCLSID( riid, &IID_IClassFactory ) )
    {
        IClassFactory_AddRef( iface );
        *ppobj = iface;
        return S_OK;
    }
    return E_NOINTERFACE;
}

static ULONG WINAPI MsiCF_AddRef(LPCLASSFACTORY iface)
{
    LockModule();
    return 2;
}

static ULONG WINAPI MsiCF_Release(LPCLASSFACTORY iface)
{
    UnlockModule();
    return 1;
}

static HRESULT WINAPI MsiCF_CreateInstance(LPCLASSFACTORY iface,
    LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj)
{
    IClassFactoryImpl *This = impl_from_IClassFactory(iface);
    IUnknown *unk = NULL;
    HRESULT r;

    TRACE("%p %p %s %p\n", This, pOuter, debugstr_guid(riid), ppobj);

    r = This->create_object( pOuter, (LPVOID*) &unk );
    if (SUCCEEDED(r))
    {
        r = IUnknown_QueryInterface( unk, riid, ppobj );
        IUnknown_Release( unk );
    }
    return r;
}

static HRESULT WINAPI MsiCF_LockServer(LPCLASSFACTORY iface, BOOL dolock)
{
    TRACE("%p %d\n", iface, dolock);

    if (dolock)
        LockModule();
    else
        UnlockModule();

    return S_OK;
}

static const IClassFactoryVtbl MsiCF_Vtbl =
{
    MsiCF_QueryInterface,
    MsiCF_AddRef,
    MsiCF_Release,
    MsiCF_CreateInstance,
    MsiCF_LockServer
};

static IClassFactoryImpl MsiServer_CF = { { &MsiCF_Vtbl }, create_msiserver };
static IClassFactoryImpl WineMsiCustomRemote_CF = { { &MsiCF_Vtbl }, create_msi_custom_remote };
static IClassFactoryImpl WineMsiRemotePackage_CF = { { &MsiCF_Vtbl }, create_msi_remote_package };

/******************************************************************
 * DllGetClassObject          [MSI.@]
 */
HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
{
    TRACE("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);

    if ( IsEqualCLSID (rclsid, &CLSID_MsiInstaller) )
    {
        *ppv = &MsiServer_CF;
        return S_OK;
    }

    if ( IsEqualCLSID (rclsid, &CLSID_WineMsiRemoteCustomAction) )
    {
        *ppv = &WineMsiCustomRemote_CF;
        return S_OK;
    }

    if ( IsEqualCLSID (rclsid, &CLSID_WineMsiRemotePackage) )
    {
        *ppv = &WineMsiRemotePackage_CF;
        return S_OK;
    }

    if( IsEqualCLSID (rclsid, &CLSID_MsiServerMessage) ||
        IsEqualCLSID (rclsid, &CLSID_MsiServer) ||
        IsEqualCLSID (rclsid, &CLSID_PSFactoryBuffer) ||
        IsEqualCLSID (rclsid, &CLSID_MsiServerX3) )
    {
        FIXME("create %s object\n", debugstr_guid( rclsid ));
    }

    return CLASS_E_CLASSNOTAVAILABLE;
}

/******************************************************************
 * DllGetVersion              [MSI.@]
 */
HRESULT WINAPI DllGetVersion(DLLVERSIONINFO *pdvi)
{
    TRACE("%p\n",pdvi);

    if (pdvi->cbSize < sizeof(DLLVERSIONINFO))
        return E_INVALIDARG;

    pdvi->dwMajorVersion = MSI_MAJORVERSION;
    pdvi->dwMinorVersion = MSI_MINORVERSION;
    pdvi->dwBuildNumber = MSI_BUILDNUMBER;
    pdvi->dwPlatformID = DLLVER_PLATFORM_WINDOWS;

    return S_OK;
}

/******************************************************************
 * DllCanUnloadNow            [MSI.@]
 */
HRESULT WINAPI DllCanUnloadNow(void)
{
    return dll_count == 0 ? S_OK : S_FALSE;
}

/***********************************************************************
 *  DllRegisterServer (MSI.@)
 */
HRESULT WINAPI DllRegisterServer(void)
{
    return __wine_register_resources( msi_hInstance );
}

/***********************************************************************
 *  DllUnregisterServer (MSI.@)
 */
HRESULT WINAPI DllUnregisterServer(void)
{
    return __wine_unregister_resources( msi_hInstance );
}
