/*
 *    Misc marshaling routinues
 *
 * 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;
    VARIANT dummy_arg, *ref_arg = &dummy_arg, *copy_arg, *orig_arg = NULL;
    UINT *ref_idx = NULL;
    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;
}
