/*
 * Implementation of the Microsoft Installer (msi.dll)
 *
 * Copyright 2002-2004 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
 */

#define COBJMACROS

#include <stdarg.h>

#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#include "shlwapi.h"
#include "wine/debug.h"
#include "msi.h"
#include "msiquery.h"
#include "msipriv.h"

WINE_DEFAULT_DEBUG_CHANNEL(msi);

static CRITICAL_SECTION MSI_handle_cs;
static CRITICAL_SECTION_DEBUG MSI_handle_cs_debug =
{
    0, 0, &MSI_handle_cs,
    { &MSI_handle_cs_debug.ProcessLocksList, 
      &MSI_handle_cs_debug.ProcessLocksList },
      0, 0, { (DWORD_PTR)(__FILE__ ": MSI_handle_cs") }
};
static CRITICAL_SECTION MSI_handle_cs = { &MSI_handle_cs_debug, -1, 0, 0, 0, 0 };

static CRITICAL_SECTION MSI_object_cs;
static CRITICAL_SECTION_DEBUG MSI_object_cs_debug =
{
    0, 0, &MSI_object_cs,
    { &MSI_object_cs_debug.ProcessLocksList, 
      &MSI_object_cs_debug.ProcessLocksList },
      0, 0, { (DWORD_PTR)(__FILE__ ": MSI_object_cs") }
};
static CRITICAL_SECTION MSI_object_cs = { &MSI_object_cs_debug, -1, 0, 0, 0, 0 };

typedef struct msi_handle_info_t
{
    BOOL remote;
    union {
        MSIOBJECTHDR *obj;
        IUnknown *unk;
    } u;
    DWORD dwThreadId;
} msi_handle_info;

static msi_handle_info *msihandletable = NULL;
static unsigned int msihandletable_size = 0;

void msi_free_handle_table(void)
{
    msi_free( msihandletable );
    msihandletable = NULL;
    msihandletable_size = 0;
    DeleteCriticalSection(&MSI_handle_cs);
    DeleteCriticalSection(&MSI_object_cs);
}

static MSIHANDLE alloc_handle_table_entry(void)
{
    UINT i;

    /* find a slot */
    for(i=0; i<msihandletable_size; i++)
        if( !msihandletable[i].u.obj && !msihandletable[i].u.unk )
            break;
    if( i==msihandletable_size )
    {
        msi_handle_info *p;
        int newsize;
        if (msihandletable_size == 0)
        {
            newsize = 256;
            p = msi_alloc_zero(newsize*sizeof(msi_handle_info));
        }
        else
        {
            newsize = msihandletable_size * 2;
            p = msi_realloc_zero(msihandletable,
                            newsize*sizeof(msi_handle_info));
        }
        if (!p)
            return 0;
        msihandletable = p;
        msihandletable_size = newsize;
    }
    return i + 1;
}

MSIHANDLE alloc_msihandle( MSIOBJECTHDR *obj )
{
    msi_handle_info *entry;
    MSIHANDLE ret;

    EnterCriticalSection( &MSI_handle_cs );

    ret = alloc_handle_table_entry();
    if (ret)
    {
        entry = &msihandletable[ ret - 1 ];
        msiobj_addref( obj );
        entry->u.obj = obj;
        entry->dwThreadId = GetCurrentThreadId();
        entry->remote = FALSE;
    }

    LeaveCriticalSection( &MSI_handle_cs );

    TRACE("%p -> %d\n", obj, ret );

    return ret;
}

MSIHANDLE alloc_msi_remote_handle( IUnknown *unk )
{
    msi_handle_info *entry;
    MSIHANDLE ret;

    EnterCriticalSection( &MSI_handle_cs );

    ret = alloc_handle_table_entry();
    if (ret)
    {
        entry = &msihandletable[ ret - 1 ];
        IUnknown_AddRef( unk );
        entry->u.unk = unk;
        entry->dwThreadId = GetCurrentThreadId();
        entry->remote = TRUE;
    }

    LeaveCriticalSection( &MSI_handle_cs );

    TRACE("%p -> %d\n", unk, ret);

    return ret;
}

void *msihandle2msiinfo(MSIHANDLE handle, UINT type)
{
    MSIOBJECTHDR *ret = NULL;

    EnterCriticalSection( &MSI_handle_cs );
    handle--;
    if( handle >= msihandletable_size )
        goto out;
    if( msihandletable[handle].remote)
        goto out;
    if( !msihandletable[handle].u.obj )
        goto out;
    if( msihandletable[handle].u.obj->magic != MSIHANDLE_MAGIC )
        goto out;
    if( type && (msihandletable[handle].u.obj->type != type) )
        goto out;
    ret = msihandletable[handle].u.obj;
    msiobj_addref( ret );

out:
    LeaveCriticalSection( &MSI_handle_cs );

    return ret;
}

IUnknown *msi_get_remote( MSIHANDLE handle )
{
    IUnknown *unk = NULL;

    EnterCriticalSection( &MSI_handle_cs );
    handle--;
    if( handle>=msihandletable_size )
        goto out;
    if( !msihandletable[handle].remote)
        goto out;
    unk = msihandletable[handle].u.unk;
    if( unk )
        IUnknown_AddRef( unk );

out:
    LeaveCriticalSection( &MSI_handle_cs );

    return unk;
}

void *alloc_msiobject(UINT type, UINT size, msihandledestructor destroy )
{
    MSIOBJECTHDR *info;

    info = msi_alloc_zero( size );
    if( info )
    {
        info->magic = MSIHANDLE_MAGIC;
        info->type = type;
        info->refcount = 1;
        info->destructor = destroy;
    }

    return info;
}

void msiobj_addref( MSIOBJECTHDR *info )
{
    if( !info )
        return;

    if( info->magic != MSIHANDLE_MAGIC )
    {
        ERR("Invalid handle!\n");
        return;
    }

    InterlockedIncrement(&info->refcount);
}

void msiobj_lock( MSIOBJECTHDR *info )
{
    EnterCriticalSection( &MSI_object_cs );
}

void msiobj_unlock( MSIOBJECTHDR *info )
{
    LeaveCriticalSection( &MSI_object_cs );
}

int msiobj_release( MSIOBJECTHDR *info )
{
    int ret;

    if( !info )
        return -1;

    if( info->magic != MSIHANDLE_MAGIC )
    {
        ERR("Invalid handle!\n");
        return -1;
    }

    ret = InterlockedDecrement( &info->refcount );
    if( ret==0 )
    {
        if( info->destructor )
            info->destructor( info );
        msi_free( info );
        TRACE("object %p destroyed\n", info);
    }

    return ret;
}

/***********************************************************
 *   MsiCloseHandle   [MSI.@]
 */
UINT WINAPI MsiCloseHandle(MSIHANDLE handle)
{
    MSIOBJECTHDR *info = NULL;
    UINT ret = ERROR_INVALID_HANDLE;

    TRACE("%x\n",handle);

    if (!handle)
        return ERROR_SUCCESS;

    EnterCriticalSection( &MSI_handle_cs );

    handle--;
    if (handle >= msihandletable_size)
        goto out;

    if (msihandletable[handle].remote)
    {
        IUnknown_Release( msihandletable[handle].u.unk );
    }
    else
    {
        info = msihandletable[handle].u.obj;
        if( !info )
            goto out;

        if( info->magic != MSIHANDLE_MAGIC )
        {
            ERR("Invalid handle!\n");
            goto out;
        }
    }

    msihandletable[handle].u.obj = NULL;
    msihandletable[handle].remote = 0;
    msihandletable[handle].dwThreadId = 0;

    ret = ERROR_SUCCESS;

    TRACE("handle %x destroyed\n", handle+1);
out:
    LeaveCriticalSection( &MSI_handle_cs );
    if( info )
        msiobj_release( info );

    return ret;
}

/***********************************************************
 *   MsiCloseAllHandles   [MSI.@]
 *
 *  Closes all handles owned by the current thread
 *
 *  RETURNS:
 *   The number of handles closed
 */
UINT WINAPI MsiCloseAllHandles(void)
{
    UINT i, n=0;

    TRACE("\n");

    EnterCriticalSection( &MSI_handle_cs );
    for(i=0; i<msihandletable_size; i++)
    {
        if(msihandletable[i].dwThreadId == GetCurrentThreadId())
        {
            LeaveCriticalSection( &MSI_handle_cs );
            MsiCloseHandle( i+1 );
            EnterCriticalSection( &MSI_handle_cs );
            n++;
        }
    }
    LeaveCriticalSection( &MSI_handle_cs );

    return n;
}
