/*
 *    Misc marshaling routines
 *
 * Copyright 2010 Huw Davies
 *
 * 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>
#include <string.h>

#define COBJMACROS
#define NONAMELESSUNION
#define NONAMELESSSTRUCT

#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "winerror.h"
#include "objbase.h"
#include "oleauto.h"
#include "dispex.h"

#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(ole);

#define NULL_RESULT    0x20000
#define NULL_EXCEPINFO 0x40000

HRESULT CALLBACK IDispatchEx_InvokeEx_Proxy(IDispatchEx* This, DISPID id, LCID lcid, WORD wFlags,
                                            DISPPARAMS *pdp, VARIANT *pvarRes, EXCEPINFO *pei,
                                            IServiceProvider *pspCaller)
{
    HRESULT hr;
    VARIANT result;
    EXCEPINFO excep_info;
    UINT byref_args, arg, dummy_idx;
    VARIANT dummy_arg, *ref_arg = &dummy_arg, *copy_arg, *orig_arg = NULL;
    UINT *ref_idx = &dummy_idx;
    DWORD dword_flags = wFlags & 0xf;

    TRACE("(%p)->(%08x, %04x, %04x, %p, %p, %p, %p)\n", This, id, lcid, wFlags,
          pdp, pvarRes, pei, pspCaller);

    if(!pvarRes)
    {
        pvarRes = &result;
        dword_flags |= NULL_RESULT;
    }

    if(!pei)
    {
        pei = &excep_info;
        dword_flags |= NULL_EXCEPINFO;
    }

    for(arg = 0, byref_args = 0; arg < pdp->cArgs; arg++)
        if(V_ISBYREF(pdp->rgvarg + arg)) byref_args++;

    if(byref_args)
    {
        DWORD size = pdp->cArgs * sizeof(VARIANT) +
            byref_args * (sizeof(VARIANT) + sizeof(UINT));

        copy_arg = CoTaskMemAlloc(size);
        if(!copy_arg) return E_OUTOFMEMORY;

        ref_arg = copy_arg + pdp->cArgs;
        ref_idx = (UINT*)(ref_arg + byref_args);

        /* copy the byref args to ref_arg[], the others go to copy_arg[] */
        for(arg = 0, byref_args = 0; arg < pdp->cArgs; arg++)
        {
            if(V_ISBYREF(pdp->rgvarg + arg))
            {
                ref_arg[byref_args] = pdp->rgvarg[arg];
                ref_idx[byref_args] = arg;
                VariantInit(copy_arg + arg);
                byref_args++;
            }
            else
                copy_arg[arg] = pdp->rgvarg[arg];
        }

        orig_arg = pdp->rgvarg;
        pdp->rgvarg = copy_arg;
    }

    hr = IDispatchEx_RemoteInvokeEx_Proxy(This, id, lcid, dword_flags, pdp, pvarRes, pei, pspCaller,
                                          byref_args, ref_idx, ref_arg);

    if(byref_args)
    {
        CoTaskMemFree(pdp->rgvarg);
        pdp->rgvarg = orig_arg;
    }

    return hr;
}

HRESULT __RPC_STUB IDispatchEx_InvokeEx_Stub(IDispatchEx* This, DISPID id, LCID lcid, DWORD dwFlags,
                                             DISPPARAMS *pdp, VARIANT *result, EXCEPINFO *pei,
                                             IServiceProvider *pspCaller, UINT byref_args,
                                             UINT *ref_idx, VARIANT *ref_arg)
{
    HRESULT hr;
    UINT arg;
    VARTYPE *vt_list = NULL;

    TRACE("(%p)->(%08x, %04x, %08x, %p, %p, %p, %p, %d, %p, %p)\n", This, id, lcid, dwFlags,
          pdp, result, pei, pspCaller, byref_args, ref_idx, ref_arg);

    VariantInit(result);
    memset(pei, 0, sizeof(*pei));

    for(arg = 0; arg < byref_args; arg++)
        pdp->rgvarg[ref_idx[arg]] = ref_arg[arg];

    if(dwFlags & NULL_RESULT) result = NULL;
    if(dwFlags & NULL_EXCEPINFO) pei = NULL;

    /* Create an array of the original VTs to check that the function doesn't change
       any on return. */
    if(byref_args)
    {
        vt_list = HeapAlloc(GetProcessHeap(), 0, pdp->cArgs * sizeof(vt_list[0]));
        if(!vt_list) return E_OUTOFMEMORY;
        for(arg = 0; arg < pdp->cArgs; arg++)
            vt_list[arg] = V_VT(pdp->rgvarg + arg);
    }

    hr = IDispatchEx_InvokeEx(This, id, lcid, dwFlags & 0xffff, pdp, result, pei, pspCaller);

    if(SUCCEEDED(hr) && byref_args)
    {
        for(arg = 0; arg < pdp->cArgs; arg++)
        {
            if(vt_list[arg] != V_VT(pdp->rgvarg + arg))
            {
                hr = DISP_E_BADCALLEE;
                break;
            }
        }
    }

    if(hr == DISP_E_EXCEPTION)
    {
        if(pei && pei->pfnDeferredFillIn)
        {
            pei->pfnDeferredFillIn(pei);
            pei->pfnDeferredFillIn = NULL;
        }
    }

    for(arg = 0; arg < byref_args; arg++)
        VariantInit(pdp->rgvarg + ref_idx[arg]);

    HeapFree(GetProcessHeap(), 0, vt_list);
    return hr;
}
