2 * Misc marshaling routines
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
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
38 #define NULL_RESULT 0x20000
39 #define NULL_EXCEPINFO 0x40000
41 HRESULT CALLBACK
IDispatchEx_InvokeEx_Proxy(IDispatchEx
* This
, DISPID id
, LCID lcid
, WORD wFlags
,
42 DISPPARAMS
*pdp
, VARIANT
*pvarRes
, EXCEPINFO
*pei
,
43 IServiceProvider
*pspCaller
)
48 UINT byref_args
, arg
, dummy_idx
;
49 VARIANT dummy_arg
, *ref_arg
= &dummy_arg
, *copy_arg
, *orig_arg
= NULL
;
50 UINT
*ref_idx
= &dummy_idx
;
51 DWORD dword_flags
= wFlags
& 0xf;
53 TRACE("(%p)->(%08x, %04x, %04x, %p, %p, %p, %p)\n", This
, id
, lcid
, wFlags
,
54 pdp
, pvarRes
, pei
, pspCaller
);
59 dword_flags
|= NULL_RESULT
;
65 dword_flags
|= NULL_EXCEPINFO
;
68 for(arg
= 0, byref_args
= 0; arg
< pdp
->cArgs
; arg
++)
69 if(V_ISBYREF(pdp
->rgvarg
+ arg
)) byref_args
++;
73 DWORD size
= pdp
->cArgs
* sizeof(VARIANT
) +
74 byref_args
* (sizeof(VARIANT
) + sizeof(UINT
));
76 copy_arg
= CoTaskMemAlloc(size
);
77 if(!copy_arg
) return E_OUTOFMEMORY
;
79 ref_arg
= copy_arg
+ pdp
->cArgs
;
80 ref_idx
= (UINT
*)(ref_arg
+ byref_args
);
82 /* copy the byref args to ref_arg[], the others go to copy_arg[] */
83 for(arg
= 0, byref_args
= 0; arg
< pdp
->cArgs
; arg
++)
85 if(V_ISBYREF(pdp
->rgvarg
+ arg
))
87 ref_arg
[byref_args
] = pdp
->rgvarg
[arg
];
88 ref_idx
[byref_args
] = arg
;
89 VariantInit(copy_arg
+ arg
);
93 copy_arg
[arg
] = pdp
->rgvarg
[arg
];
96 orig_arg
= pdp
->rgvarg
;
97 pdp
->rgvarg
= copy_arg
;
100 hr
= IDispatchEx_RemoteInvokeEx_Proxy(This
, id
, lcid
, dword_flags
, pdp
, pvarRes
, pei
, pspCaller
,
101 byref_args
, ref_idx
, ref_arg
);
105 CoTaskMemFree(pdp
->rgvarg
);
106 pdp
->rgvarg
= orig_arg
;
112 HRESULT __RPC_STUB
IDispatchEx_InvokeEx_Stub(IDispatchEx
* This
, DISPID id
, LCID lcid
, DWORD dwFlags
,
113 DISPPARAMS
*pdp
, VARIANT
*result
, EXCEPINFO
*pei
,
114 IServiceProvider
*pspCaller
, UINT byref_args
,
115 UINT
*ref_idx
, VARIANT
*ref_arg
)
119 VARTYPE
*vt_list
= NULL
;
121 TRACE("(%p)->(%08x, %04x, %08x, %p, %p, %p, %p, %d, %p, %p)\n", This
, id
, lcid
, dwFlags
,
122 pdp
, result
, pei
, pspCaller
, byref_args
, ref_idx
, ref_arg
);
125 memset(pei
, 0, sizeof(*pei
));
127 for(arg
= 0; arg
< byref_args
; arg
++)
128 pdp
->rgvarg
[ref_idx
[arg
]] = ref_arg
[arg
];
130 if(dwFlags
& NULL_RESULT
) result
= NULL
;
131 if(dwFlags
& NULL_EXCEPINFO
) pei
= NULL
;
133 /* Create an array of the original VTs to check that the function doesn't change
137 vt_list
= HeapAlloc(GetProcessHeap(), 0, pdp
->cArgs
* sizeof(vt_list
[0]));
138 if(!vt_list
) return E_OUTOFMEMORY
;
139 for(arg
= 0; arg
< pdp
->cArgs
; arg
++)
140 vt_list
[arg
] = V_VT(pdp
->rgvarg
+ arg
);
143 hr
= IDispatchEx_InvokeEx(This
, id
, lcid
, dwFlags
& 0xffff, pdp
, result
, pei
, pspCaller
);
145 if(SUCCEEDED(hr
) && byref_args
)
147 for(arg
= 0; arg
< pdp
->cArgs
; arg
++)
149 if(vt_list
[arg
] != V_VT(pdp
->rgvarg
+ arg
))
151 hr
= DISP_E_BADCALLEE
;
157 if(hr
== DISP_E_EXCEPTION
)
159 if(pei
&& pei
->pfnDeferredFillIn
)
161 pei
->pfnDeferredFillIn(pei
);
162 pei
->pfnDeferredFillIn
= NULL
;
166 for(arg
= 0; arg
< byref_args
; arg
++)
167 VariantInit(pdp
->rgvarg
+ ref_idx
[arg
]);
169 HeapFree(GetProcessHeap(), 0, vt_list
);