2 * Misc marshaling routinues
4 * Copyright 2010 Huw Davies
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #define NONAMELESSUNION
25 #define NONAMELESSSTRUCT
36 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(ole);
40 HRESULT CALLBACK IDispatchEx_InvokeEx_Proxy(IDispatchEx* This, DISPID id, LCID lcid, WORD wFlags,
41 DISPPARAMS *pdp, VARIANT *pvarRes, EXCEPINFO *pei,
42 IServiceProvider *pspCaller)
48 VARIANT dummy_arg, *ref_arg = &dummy_arg, *copy_arg, *orig_arg = NULL;
51 TRACE("(%p)->(%08x, %04x, %04x, %p, %p, %p, %p)\n", This, id, lcid, wFlags,
52 pdp, pvarRes, pei, pspCaller);
54 if(!pvarRes) pvarRes = &result;
55 if(!pei) pei = &excep_info;
57 for(arg = 0, byref_args = 0; arg < pdp->cArgs; arg++)
58 if(V_ISBYREF(pdp->rgvarg + arg)) byref_args++;
62 DWORD size = pdp->cArgs * sizeof(VARIANT) +
63 byref_args * (sizeof(VARIANT) + sizeof(UINT));
65 copy_arg = CoTaskMemAlloc(size);
66 if(!copy_arg) return E_OUTOFMEMORY;
68 ref_arg = copy_arg + pdp->cArgs;
69 ref_idx = (UINT*)(ref_arg + byref_args);
71 /* copy the byref args to ref_arg[], the others go to copy_arg[] */
72 for(arg = 0, byref_args = 0; arg < pdp->cArgs; arg++)
74 if(V_ISBYREF(pdp->rgvarg + arg))
76 ref_arg[byref_args] = pdp->rgvarg[arg];
77 ref_idx[byref_args] = arg;
78 VariantInit(copy_arg + arg);
82 copy_arg[arg] = pdp->rgvarg[arg];
85 orig_arg = pdp->rgvarg;
86 pdp->rgvarg = copy_arg;
89 hr = IDispatchEx_RemoteInvokeEx_Proxy(This, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller,
90 byref_args, ref_idx, ref_arg);
94 CoTaskMemFree(pdp->rgvarg);
95 pdp->rgvarg = orig_arg;
98 if(pvarRes == &result) VariantClear(pvarRes);
99 if(pei == &excep_info)
101 SysFreeString(pei->bstrSource);
102 SysFreeString(pei->bstrDescription);
103 SysFreeString(pei->bstrHelpFile);
109 HRESULT __RPC_STUB IDispatchEx_InvokeEx_Stub(IDispatchEx* This, DISPID id, LCID lcid, DWORD dwFlags,
110 DISPPARAMS *pdp, VARIANT *result, EXCEPINFO *pei,
111 IServiceProvider *pspCaller, UINT byref_args,
112 UINT *ref_idx, VARIANT *ref_arg)
117 TRACE("(%p)->(%08x, %04x, %08x, %p, %p, %p, %p, %d, %p, %p)\n", This, id, lcid, dwFlags,
118 pdp, result, pei, pspCaller, byref_args, ref_idx, ref_arg);
121 memset(pei, 0, sizeof(*pei));
123 for(arg = 0; arg < byref_args; arg++)
124 pdp->rgvarg[ref_idx[arg]] = ref_arg[arg];
126 hr = IDispatchEx_InvokeEx(This, id, lcid, dwFlags, pdp, result, pei, pspCaller);
128 for(arg = 0; arg < byref_args; arg++)
129 VariantInit(pdp->rgvarg + ref_idx[arg]);