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
24 #define NONAMELESSUNION
25 #define NONAMELESSSTRUCT
36 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
40 #define NULL_RESULT 0x20000
41 #define NULL_EXCEPINFO 0x40000
43 HRESULT CALLBACK
IDispatchEx_InvokeEx_Proxy(IDispatchEx
* This
, DISPID id
, LCID lcid
, WORD wFlags
,
44 DISPPARAMS
*pdp
, VARIANT
*pvarRes
, EXCEPINFO
*pei
,
45 IServiceProvider
*pspCaller
)
50 UINT byref_args
, arg
, dummy_idx
;
51 VARIANT dummy_arg
, *ref_arg
= &dummy_arg
, *copy_arg
, *orig_arg
= NULL
;
52 UINT
*ref_idx
= &dummy_idx
;
53 DWORD dword_flags
= wFlags
& 0xf;
55 TRACE("(%p)->(%08x, %04x, %04x, %p, %p, %p, %p)\n", This
, id
, lcid
, wFlags
,
56 pdp
, pvarRes
, pei
, pspCaller
);
61 dword_flags
|= NULL_RESULT
;
67 dword_flags
|= NULL_EXCEPINFO
;
70 for(arg
= 0, byref_args
= 0; arg
< pdp
->cArgs
; arg
++)
71 if(V_ISBYREF(pdp
->rgvarg
+ arg
)) byref_args
++;
75 DWORD size
= pdp
->cArgs
* sizeof(VARIANT
) +
76 byref_args
* (sizeof(VARIANT
) + sizeof(UINT
));
78 copy_arg
= CoTaskMemAlloc(size
);
79 if(!copy_arg
) return E_OUTOFMEMORY
;
81 ref_arg
= copy_arg
+ pdp
->cArgs
;
82 ref_idx
= (UINT
*)(ref_arg
+ byref_args
);
84 /* copy the byref args to ref_arg[], the others go to copy_arg[] */
85 for(arg
= 0, byref_args
= 0; arg
< pdp
->cArgs
; arg
++)
87 if(V_ISBYREF(pdp
->rgvarg
+ arg
))
89 ref_arg
[byref_args
] = pdp
->rgvarg
[arg
];
90 ref_idx
[byref_args
] = arg
;
91 VariantInit(copy_arg
+ arg
);
95 copy_arg
[arg
] = pdp
->rgvarg
[arg
];
98 orig_arg
= pdp
->rgvarg
;
99 pdp
->rgvarg
= copy_arg
;
102 hr
= IDispatchEx_RemoteInvokeEx_Proxy(This
, id
, lcid
, dword_flags
, pdp
, pvarRes
, pei
, pspCaller
,
103 byref_args
, ref_idx
, ref_arg
);
107 CoTaskMemFree(pdp
->rgvarg
);
108 pdp
->rgvarg
= orig_arg
;
114 HRESULT __RPC_STUB
IDispatchEx_InvokeEx_Stub(IDispatchEx
* This
, DISPID id
, LCID lcid
, DWORD dwFlags
,
115 DISPPARAMS
*pdp
, VARIANT
*result
, EXCEPINFO
*pei
,
116 IServiceProvider
*pspCaller
, UINT byref_args
,
117 UINT
*ref_idx
, VARIANT
*ref_arg
)
121 VARTYPE
*vt_list
= NULL
;
123 TRACE("(%p)->(%08x, %04x, %08x, %p, %p, %p, %p, %d, %p, %p)\n", This
, id
, lcid
, dwFlags
,
124 pdp
, result
, pei
, pspCaller
, byref_args
, ref_idx
, ref_arg
);
127 memset(pei
, 0, sizeof(*pei
));
129 for(arg
= 0; arg
< byref_args
; arg
++)
130 pdp
->rgvarg
[ref_idx
[arg
]] = ref_arg
[arg
];
132 if(dwFlags
& NULL_RESULT
) result
= NULL
;
133 if(dwFlags
& NULL_EXCEPINFO
) pei
= NULL
;
135 /* Create an array of the original VTs to check that the function doesn't change
139 vt_list
= HeapAlloc(GetProcessHeap(), 0, pdp
->cArgs
* sizeof(vt_list
[0]));
140 if(!vt_list
) return E_OUTOFMEMORY
;
141 for(arg
= 0; arg
< pdp
->cArgs
; arg
++)
142 vt_list
[arg
] = V_VT(pdp
->rgvarg
+ arg
);
145 hr
= IDispatchEx_InvokeEx(This
, id
, lcid
, dwFlags
& 0xffff, pdp
, result
, pei
, pspCaller
);
147 if(SUCCEEDED(hr
) && byref_args
)
149 for(arg
= 0; arg
< pdp
->cArgs
; arg
++)
151 if(vt_list
[arg
] != V_VT(pdp
->rgvarg
+ arg
))
153 hr
= DISP_E_BADCALLEE
;
159 if(hr
== DISP_E_EXCEPTION
)
161 if(pei
&& pei
->pfnDeferredFillIn
)
163 pei
->pfnDeferredFillIn(pei
);
164 pei
->pfnDeferredFillIn
= NULL
;
168 for(arg
= 0; arg
< byref_args
; arg
++)
169 VariantInit(pdp
->rgvarg
+ ref_idx
[arg
]);
171 HeapFree(GetProcessHeap(), 0, vt_list
);