1*c2c66affSColin Finck /*
2*c2c66affSColin Finck * Copyright 2008-2009 Jacek Caban for CodeWeavers
3*c2c66affSColin Finck *
4*c2c66affSColin Finck * This library is free software; you can redistribute it and/or
5*c2c66affSColin Finck * modify it under the terms of the GNU Lesser General Public
6*c2c66affSColin Finck * License as published by the Free Software Foundation; either
7*c2c66affSColin Finck * version 2.1 of the License, or (at your option) any later version.
8*c2c66affSColin Finck *
9*c2c66affSColin Finck * This library is distributed in the hope that it will be useful,
10*c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of
11*c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12*c2c66affSColin Finck * Lesser General Public License for more details.
13*c2c66affSColin Finck *
14*c2c66affSColin Finck * You should have received a copy of the GNU Lesser General Public
15*c2c66affSColin Finck * License along with this library; if not, write to the Free Software
16*c2c66affSColin Finck * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17*c2c66affSColin Finck */
18*c2c66affSColin Finck
19*c2c66affSColin Finck #include "mshtml_private.h"
20*c2c66affSColin Finck
21*c2c66affSColin Finck #define MAX_ARGS 16
22*c2c66affSColin Finck
23*c2c66affSColin Finck static CRITICAL_SECTION cs_dispex_static_data;
24*c2c66affSColin Finck static CRITICAL_SECTION_DEBUG cs_dispex_static_data_dbg =
25*c2c66affSColin Finck {
26*c2c66affSColin Finck 0, 0, &cs_dispex_static_data,
27*c2c66affSColin Finck { &cs_dispex_static_data_dbg.ProcessLocksList, &cs_dispex_static_data_dbg.ProcessLocksList },
28*c2c66affSColin Finck 0, 0, { (DWORD_PTR)(__FILE__ ": dispex_static_data") }
29*c2c66affSColin Finck };
30*c2c66affSColin Finck static CRITICAL_SECTION cs_dispex_static_data = { &cs_dispex_static_data_dbg, -1, 0, 0, 0, 0 };
31*c2c66affSColin Finck
32*c2c66affSColin Finck
33*c2c66affSColin Finck static const WCHAR objectW[] = {'[','o','b','j','e','c','t',']',0};
34*c2c66affSColin Finck
35*c2c66affSColin Finck typedef struct {
36*c2c66affSColin Finck DISPID id;
37*c2c66affSColin Finck BSTR name;
38*c2c66affSColin Finck tid_t tid;
39*c2c66affSColin Finck SHORT call_vtbl_off;
40*c2c66affSColin Finck SHORT put_vtbl_off;
41*c2c66affSColin Finck SHORT get_vtbl_off;
42*c2c66affSColin Finck SHORT func_disp_idx;
43*c2c66affSColin Finck USHORT argc;
44*c2c66affSColin Finck VARTYPE prop_vt;
45*c2c66affSColin Finck VARTYPE *arg_types;
46*c2c66affSColin Finck } func_info_t;
47*c2c66affSColin Finck
48*c2c66affSColin Finck struct dispex_data_t {
49*c2c66affSColin Finck DWORD func_cnt;
50*c2c66affSColin Finck func_info_t *funcs;
51*c2c66affSColin Finck func_info_t **name_table;
52*c2c66affSColin Finck DWORD func_disp_cnt;
53*c2c66affSColin Finck
54*c2c66affSColin Finck struct list entry;
55*c2c66affSColin Finck };
56*c2c66affSColin Finck
57*c2c66affSColin Finck typedef struct {
58*c2c66affSColin Finck VARIANT var;
59*c2c66affSColin Finck LPWSTR name;
60*c2c66affSColin Finck DWORD flags;
61*c2c66affSColin Finck } dynamic_prop_t;
62*c2c66affSColin Finck
63*c2c66affSColin Finck #define DYNPROP_DELETED 0x01
64*c2c66affSColin Finck
65*c2c66affSColin Finck typedef struct {
66*c2c66affSColin Finck DispatchEx dispex;
67*c2c66affSColin Finck IUnknown IUnknown_iface;
68*c2c66affSColin Finck LONG ref;
69*c2c66affSColin Finck DispatchEx *obj;
70*c2c66affSColin Finck func_info_t *info;
71*c2c66affSColin Finck } func_disp_t;
72*c2c66affSColin Finck
73*c2c66affSColin Finck typedef struct {
74*c2c66affSColin Finck func_disp_t *func_obj;
75*c2c66affSColin Finck VARIANT val;
76*c2c66affSColin Finck } func_obj_entry_t;
77*c2c66affSColin Finck
78*c2c66affSColin Finck struct dispex_dynamic_data_t {
79*c2c66affSColin Finck DWORD buf_size;
80*c2c66affSColin Finck DWORD prop_cnt;
81*c2c66affSColin Finck dynamic_prop_t *props;
82*c2c66affSColin Finck func_obj_entry_t *func_disps;
83*c2c66affSColin Finck };
84*c2c66affSColin Finck
85*c2c66affSColin Finck #define DISPID_DYNPROP_0 0x50000000
86*c2c66affSColin Finck #define DISPID_DYNPROP_MAX 0x5fffffff
87*c2c66affSColin Finck
88*c2c66affSColin Finck #define FDEX_VERSION_MASK 0xf0000000
89*c2c66affSColin Finck
90*c2c66affSColin Finck static ITypeLib *typelib;
91*c2c66affSColin Finck static ITypeInfo *typeinfos[LAST_tid];
92*c2c66affSColin Finck static struct list dispex_data_list = LIST_INIT(dispex_data_list);
93*c2c66affSColin Finck
94*c2c66affSColin Finck static REFIID tid_ids[] = {
95*c2c66affSColin Finck #define XIID(iface) &IID_ ## iface,
96*c2c66affSColin Finck #define XDIID(iface) &DIID_ ## iface,
97*c2c66affSColin Finck TID_LIST
98*c2c66affSColin Finck #undef XIID
99*c2c66affSColin Finck #undef XDIID
100*c2c66affSColin Finck };
101*c2c66affSColin Finck
load_typelib(void)102*c2c66affSColin Finck static HRESULT load_typelib(void)
103*c2c66affSColin Finck {
104*c2c66affSColin Finck HRESULT hres;
105*c2c66affSColin Finck ITypeLib *tl;
106*c2c66affSColin Finck
107*c2c66affSColin Finck hres = LoadRegTypeLib(&LIBID_MSHTML, 4, 0, LOCALE_SYSTEM_DEFAULT, &tl);
108*c2c66affSColin Finck if(FAILED(hres)) {
109*c2c66affSColin Finck ERR("LoadRegTypeLib failed: %08x\n", hres);
110*c2c66affSColin Finck return hres;
111*c2c66affSColin Finck }
112*c2c66affSColin Finck
113*c2c66affSColin Finck if(InterlockedCompareExchangePointer((void**)&typelib, tl, NULL))
114*c2c66affSColin Finck ITypeLib_Release(tl);
115*c2c66affSColin Finck return hres;
116*c2c66affSColin Finck }
117*c2c66affSColin Finck
get_typeinfo(tid_t tid,ITypeInfo ** typeinfo)118*c2c66affSColin Finck static HRESULT get_typeinfo(tid_t tid, ITypeInfo **typeinfo)
119*c2c66affSColin Finck {
120*c2c66affSColin Finck HRESULT hres;
121*c2c66affSColin Finck
122*c2c66affSColin Finck if (!typelib)
123*c2c66affSColin Finck hres = load_typelib();
124*c2c66affSColin Finck if (!typelib)
125*c2c66affSColin Finck return hres;
126*c2c66affSColin Finck
127*c2c66affSColin Finck if(!typeinfos[tid]) {
128*c2c66affSColin Finck ITypeInfo *ti;
129*c2c66affSColin Finck
130*c2c66affSColin Finck hres = ITypeLib_GetTypeInfoOfGuid(typelib, tid_ids[tid], &ti);
131*c2c66affSColin Finck if(FAILED(hres)) {
132*c2c66affSColin Finck ERR("GetTypeInfoOfGuid(%s) failed: %08x\n", debugstr_mshtml_guid(tid_ids[tid]), hres);
133*c2c66affSColin Finck return hres;
134*c2c66affSColin Finck }
135*c2c66affSColin Finck
136*c2c66affSColin Finck if(InterlockedCompareExchangePointer((void**)(typeinfos+tid), ti, NULL))
137*c2c66affSColin Finck ITypeInfo_Release(ti);
138*c2c66affSColin Finck }
139*c2c66affSColin Finck
140*c2c66affSColin Finck *typeinfo = typeinfos[tid];
141*c2c66affSColin Finck return S_OK;
142*c2c66affSColin Finck }
143*c2c66affSColin Finck
release_typelib(void)144*c2c66affSColin Finck void release_typelib(void)
145*c2c66affSColin Finck {
146*c2c66affSColin Finck dispex_data_t *iter;
147*c2c66affSColin Finck unsigned i;
148*c2c66affSColin Finck
149*c2c66affSColin Finck while(!list_empty(&dispex_data_list)) {
150*c2c66affSColin Finck iter = LIST_ENTRY(list_head(&dispex_data_list), dispex_data_t, entry);
151*c2c66affSColin Finck list_remove(&iter->entry);
152*c2c66affSColin Finck
153*c2c66affSColin Finck for(i=0; i < iter->func_cnt; i++)
154*c2c66affSColin Finck SysFreeString(iter->funcs[i].name);
155*c2c66affSColin Finck
156*c2c66affSColin Finck heap_free(iter->funcs);
157*c2c66affSColin Finck heap_free(iter->name_table);
158*c2c66affSColin Finck heap_free(iter);
159*c2c66affSColin Finck }
160*c2c66affSColin Finck
161*c2c66affSColin Finck if(!typelib)
162*c2c66affSColin Finck return;
163*c2c66affSColin Finck
164*c2c66affSColin Finck for(i=0; i < sizeof(typeinfos)/sizeof(*typeinfos); i++)
165*c2c66affSColin Finck if(typeinfos[i])
166*c2c66affSColin Finck ITypeInfo_Release(typeinfos[i]);
167*c2c66affSColin Finck
168*c2c66affSColin Finck ITypeLib_Release(typelib);
169*c2c66affSColin Finck DeleteCriticalSection(&cs_dispex_static_data);
170*c2c66affSColin Finck }
171*c2c66affSColin Finck
get_htmldoc_classinfo(ITypeInfo ** typeinfo)172*c2c66affSColin Finck HRESULT get_htmldoc_classinfo(ITypeInfo **typeinfo)
173*c2c66affSColin Finck {
174*c2c66affSColin Finck HRESULT hres;
175*c2c66affSColin Finck
176*c2c66affSColin Finck if (!typelib)
177*c2c66affSColin Finck hres = load_typelib();
178*c2c66affSColin Finck if (!typelib)
179*c2c66affSColin Finck return hres;
180*c2c66affSColin Finck
181*c2c66affSColin Finck hres = ITypeLib_GetTypeInfoOfGuid(typelib, &CLSID_HTMLDocument, typeinfo);
182*c2c66affSColin Finck if(FAILED(hres))
183*c2c66affSColin Finck ERR("GetTypeInfoOfGuid failed: %08x\n", hres);
184*c2c66affSColin Finck return hres;
185*c2c66affSColin Finck }
186*c2c66affSColin Finck
187*c2c66affSColin Finck /* Not all argument types are supported yet */
188*c2c66affSColin Finck #define BUILTIN_ARG_TYPES_SWITCH \
189*c2c66affSColin Finck CASE_VT(VT_I2, INT16, V_I2); \
190*c2c66affSColin Finck CASE_VT(VT_I4, INT32, V_I4); \
191*c2c66affSColin Finck CASE_VT(VT_R4, float, V_R4); \
192*c2c66affSColin Finck CASE_VT(VT_BSTR, BSTR, V_BSTR); \
193*c2c66affSColin Finck CASE_VT(VT_BOOL, VARIANT_BOOL, V_BOOL)
194*c2c66affSColin Finck
195*c2c66affSColin Finck /* List all types used by IDispatchEx-based properties */
196*c2c66affSColin Finck #define BUILTIN_TYPES_SWITCH \
197*c2c66affSColin Finck BUILTIN_ARG_TYPES_SWITCH; \
198*c2c66affSColin Finck CASE_VT(VT_VARIANT, VARIANT, *); \
199*c2c66affSColin Finck CASE_VT(VT_PTR, void*, V_BYREF); \
200*c2c66affSColin Finck CASE_VT(VT_UNKNOWN, IUnknown*, V_UNKNOWN); \
201*c2c66affSColin Finck CASE_VT(VT_DISPATCH, IDispatch*, V_DISPATCH)
202*c2c66affSColin Finck
is_arg_type_supported(VARTYPE vt)203*c2c66affSColin Finck static BOOL is_arg_type_supported(VARTYPE vt)
204*c2c66affSColin Finck {
205*c2c66affSColin Finck switch(vt) {
206*c2c66affSColin Finck #define CASE_VT(x,a,b) case x: return TRUE
207*c2c66affSColin Finck BUILTIN_ARG_TYPES_SWITCH;
208*c2c66affSColin Finck #undef CASE_VT
209*c2c66affSColin Finck }
210*c2c66affSColin Finck return FALSE;
211*c2c66affSColin Finck }
212*c2c66affSColin Finck
add_func_info(dispex_data_t * data,DWORD * size,tid_t tid,const FUNCDESC * desc,ITypeInfo * dti)213*c2c66affSColin Finck static void add_func_info(dispex_data_t *data, DWORD *size, tid_t tid, const FUNCDESC *desc, ITypeInfo *dti)
214*c2c66affSColin Finck {
215*c2c66affSColin Finck func_info_t *info;
216*c2c66affSColin Finck HRESULT hres;
217*c2c66affSColin Finck
218*c2c66affSColin Finck for(info = data->funcs; info < data->funcs+data->func_cnt; info++) {
219*c2c66affSColin Finck if(info->id == desc->memid) {
220*c2c66affSColin Finck if(info->tid != tid)
221*c2c66affSColin Finck return; /* Duplicated in other interface */
222*c2c66affSColin Finck break;
223*c2c66affSColin Finck }
224*c2c66affSColin Finck }
225*c2c66affSColin Finck
226*c2c66affSColin Finck if(info == data->funcs+data->func_cnt) {
227*c2c66affSColin Finck if(data->func_cnt == *size)
228*c2c66affSColin Finck data->funcs = heap_realloc_zero(data->funcs, (*size <<= 1)*sizeof(func_info_t));
229*c2c66affSColin Finck
230*c2c66affSColin Finck info = data->funcs+data->func_cnt;
231*c2c66affSColin Finck hres = ITypeInfo_GetDocumentation(dti, desc->memid, &info->name, NULL, NULL, NULL);
232*c2c66affSColin Finck if(FAILED(hres))
233*c2c66affSColin Finck return;
234*c2c66affSColin Finck
235*c2c66affSColin Finck data->func_cnt++;
236*c2c66affSColin Finck
237*c2c66affSColin Finck info->id = desc->memid;
238*c2c66affSColin Finck info->tid = tid;
239*c2c66affSColin Finck info->func_disp_idx = -1;
240*c2c66affSColin Finck info->prop_vt = VT_EMPTY;
241*c2c66affSColin Finck }
242*c2c66affSColin Finck
243*c2c66affSColin Finck if(desc->invkind & DISPATCH_METHOD) {
244*c2c66affSColin Finck unsigned i;
245*c2c66affSColin Finck
246*c2c66affSColin Finck info->func_disp_idx = data->func_disp_cnt++;
247*c2c66affSColin Finck info->argc = desc->cParams;
248*c2c66affSColin Finck
249*c2c66affSColin Finck assert(info->argc < MAX_ARGS);
250*c2c66affSColin Finck assert(desc->funckind == FUNC_DISPATCH);
251*c2c66affSColin Finck
252*c2c66affSColin Finck info->arg_types = heap_alloc(sizeof(*info->arg_types) * info->argc);
253*c2c66affSColin Finck if(!info->arg_types)
254*c2c66affSColin Finck return; /* FIXME: real error instead of fallback */
255*c2c66affSColin Finck
256*c2c66affSColin Finck for(i=0; i < info->argc; i++)
257*c2c66affSColin Finck info->arg_types[i] = desc->lprgelemdescParam[i].tdesc.vt;
258*c2c66affSColin Finck
259*c2c66affSColin Finck info->prop_vt = desc->elemdescFunc.tdesc.vt;
260*c2c66affSColin Finck if(info->prop_vt != VT_VOID && !is_arg_type_supported(info->prop_vt)) {
261*c2c66affSColin Finck TRACE("%s: return type %d\n", debugstr_w(info->name), info->prop_vt);
262*c2c66affSColin Finck return; /* Fallback to ITypeInfo::Invoke */
263*c2c66affSColin Finck }
264*c2c66affSColin Finck
265*c2c66affSColin Finck if(desc->cParamsOpt) {
266*c2c66affSColin Finck TRACE("%s: optional params\n", debugstr_w(info->name));
267*c2c66affSColin Finck return; /* Fallback to ITypeInfo::Invoke */
268*c2c66affSColin Finck }
269*c2c66affSColin Finck
270*c2c66affSColin Finck for(i=0; i < info->argc; i++) {
271*c2c66affSColin Finck if(!is_arg_type_supported(info->arg_types[i])) {
272*c2c66affSColin Finck return; /* Fallback to ITypeInfo for unsupported arg types */
273*c2c66affSColin Finck }
274*c2c66affSColin Finck
275*c2c66affSColin Finck if(desc->lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) {
276*c2c66affSColin Finck TRACE("%s param %d: default value\n", debugstr_w(info->name), i);
277*c2c66affSColin Finck return; /* Fallback to ITypeInfo::Invoke */
278*c2c66affSColin Finck }
279*c2c66affSColin Finck }
280*c2c66affSColin Finck
281*c2c66affSColin Finck assert(info->argc <= MAX_ARGS);
282*c2c66affSColin Finck assert(desc->callconv == CC_STDCALL);
283*c2c66affSColin Finck
284*c2c66affSColin Finck info->call_vtbl_off = desc->oVft/sizeof(void*);
285*c2c66affSColin Finck }else if(desc->invkind & (DISPATCH_PROPERTYPUT|DISPATCH_PROPERTYGET)) {
286*c2c66affSColin Finck VARTYPE vt = VT_EMPTY;
287*c2c66affSColin Finck
288*c2c66affSColin Finck if(desc->invkind & DISPATCH_PROPERTYGET) {
289*c2c66affSColin Finck vt = desc->elemdescFunc.tdesc.vt;
290*c2c66affSColin Finck info->get_vtbl_off = desc->oVft/sizeof(void*);
291*c2c66affSColin Finck }
292*c2c66affSColin Finck if(desc->invkind & DISPATCH_PROPERTYPUT) {
293*c2c66affSColin Finck assert(desc->cParams == 1);
294*c2c66affSColin Finck vt = desc->lprgelemdescParam->tdesc.vt;
295*c2c66affSColin Finck info->put_vtbl_off = desc->oVft/sizeof(void*);
296*c2c66affSColin Finck }
297*c2c66affSColin Finck
298*c2c66affSColin Finck assert(info->prop_vt == VT_EMPTY || vt == info->prop_vt);
299*c2c66affSColin Finck info->prop_vt = vt;
300*c2c66affSColin Finck }
301*c2c66affSColin Finck }
302*c2c66affSColin Finck
dispid_cmp(const void * p1,const void * p2)303*c2c66affSColin Finck static int dispid_cmp(const void *p1, const void *p2)
304*c2c66affSColin Finck {
305*c2c66affSColin Finck return ((const func_info_t*)p1)->id - ((const func_info_t*)p2)->id;
306*c2c66affSColin Finck }
307*c2c66affSColin Finck
func_name_cmp(const void * p1,const void * p2)308*c2c66affSColin Finck static int func_name_cmp(const void *p1, const void *p2)
309*c2c66affSColin Finck {
310*c2c66affSColin Finck return strcmpiW((*(func_info_t* const*)p1)->name, (*(func_info_t* const*)p2)->name);
311*c2c66affSColin Finck }
312*c2c66affSColin Finck
preprocess_dispex_data(DispatchEx * This)313*c2c66affSColin Finck static dispex_data_t *preprocess_dispex_data(DispatchEx *This)
314*c2c66affSColin Finck {
315*c2c66affSColin Finck const tid_t *tid = This->data->iface_tids;
316*c2c66affSColin Finck FUNCDESC *funcdesc;
317*c2c66affSColin Finck dispex_data_t *data;
318*c2c66affSColin Finck DWORD size = 16, i;
319*c2c66affSColin Finck ITypeInfo *ti, *dti;
320*c2c66affSColin Finck HRESULT hres;
321*c2c66affSColin Finck
322*c2c66affSColin Finck TRACE("(%p)\n", This);
323*c2c66affSColin Finck
324*c2c66affSColin Finck if(This->data->disp_tid) {
325*c2c66affSColin Finck hres = get_typeinfo(This->data->disp_tid, &dti);
326*c2c66affSColin Finck if(FAILED(hres)) {
327*c2c66affSColin Finck ERR("Could not get disp type info: %08x\n", hres);
328*c2c66affSColin Finck return NULL;
329*c2c66affSColin Finck }
330*c2c66affSColin Finck }
331*c2c66affSColin Finck
332*c2c66affSColin Finck data = heap_alloc(sizeof(dispex_data_t));
333*c2c66affSColin Finck if (!data) {
334*c2c66affSColin Finck ERR("Out of memory\n");
335*c2c66affSColin Finck return NULL;
336*c2c66affSColin Finck }
337*c2c66affSColin Finck data->func_cnt = 0;
338*c2c66affSColin Finck data->func_disp_cnt = 0;
339*c2c66affSColin Finck data->funcs = heap_alloc_zero(size*sizeof(func_info_t));
340*c2c66affSColin Finck if (!data->funcs) {
341*c2c66affSColin Finck heap_free (data);
342*c2c66affSColin Finck ERR("Out of memory\n");
343*c2c66affSColin Finck return NULL;
344*c2c66affSColin Finck }
345*c2c66affSColin Finck list_add_tail(&dispex_data_list, &data->entry);
346*c2c66affSColin Finck
347*c2c66affSColin Finck while(*tid) {
348*c2c66affSColin Finck hres = get_typeinfo(*tid, &ti);
349*c2c66affSColin Finck if(FAILED(hres))
350*c2c66affSColin Finck break;
351*c2c66affSColin Finck
352*c2c66affSColin Finck i=7;
353*c2c66affSColin Finck while(1) {
354*c2c66affSColin Finck hres = ITypeInfo_GetFuncDesc(ti, i++, &funcdesc);
355*c2c66affSColin Finck if(FAILED(hres))
356*c2c66affSColin Finck break;
357*c2c66affSColin Finck
358*c2c66affSColin Finck add_func_info(data, &size, *tid, funcdesc, dti);
359*c2c66affSColin Finck ITypeInfo_ReleaseFuncDesc(ti, funcdesc);
360*c2c66affSColin Finck }
361*c2c66affSColin Finck
362*c2c66affSColin Finck tid++;
363*c2c66affSColin Finck }
364*c2c66affSColin Finck
365*c2c66affSColin Finck if(!data->func_cnt) {
366*c2c66affSColin Finck heap_free(data->funcs);
367*c2c66affSColin Finck data->name_table = NULL;
368*c2c66affSColin Finck data->funcs = NULL;
369*c2c66affSColin Finck return data;
370*c2c66affSColin Finck }
371*c2c66affSColin Finck
372*c2c66affSColin Finck
373*c2c66affSColin Finck data->funcs = heap_realloc(data->funcs, data->func_cnt * sizeof(func_info_t));
374*c2c66affSColin Finck qsort(data->funcs, data->func_cnt, sizeof(func_info_t), dispid_cmp);
375*c2c66affSColin Finck
376*c2c66affSColin Finck data->name_table = heap_alloc(data->func_cnt * sizeof(func_info_t*));
377*c2c66affSColin Finck for(i=0; i < data->func_cnt; i++)
378*c2c66affSColin Finck data->name_table[i] = data->funcs+i;
379*c2c66affSColin Finck qsort(data->name_table, data->func_cnt, sizeof(func_info_t*), func_name_cmp);
380*c2c66affSColin Finck
381*c2c66affSColin Finck return data;
382*c2c66affSColin Finck }
383*c2c66affSColin Finck
id_cmp(const void * p1,const void * p2)384*c2c66affSColin Finck static int id_cmp(const void *p1, const void *p2)
385*c2c66affSColin Finck {
386*c2c66affSColin Finck return *(const DISPID*)p1 - *(const DISPID*)p2;
387*c2c66affSColin Finck }
388*c2c66affSColin Finck
get_dispids(tid_t tid,DWORD * ret_size,DISPID ** ret)389*c2c66affSColin Finck HRESULT get_dispids(tid_t tid, DWORD *ret_size, DISPID **ret)
390*c2c66affSColin Finck {
391*c2c66affSColin Finck unsigned i, func_cnt;
392*c2c66affSColin Finck FUNCDESC *funcdesc;
393*c2c66affSColin Finck ITypeInfo *ti;
394*c2c66affSColin Finck TYPEATTR *attr;
395*c2c66affSColin Finck DISPID *ids;
396*c2c66affSColin Finck HRESULT hres;
397*c2c66affSColin Finck
398*c2c66affSColin Finck hres = get_typeinfo(tid, &ti);
399*c2c66affSColin Finck if(FAILED(hres))
400*c2c66affSColin Finck return hres;
401*c2c66affSColin Finck
402*c2c66affSColin Finck hres = ITypeInfo_GetTypeAttr(ti, &attr);
403*c2c66affSColin Finck if(FAILED(hres)) {
404*c2c66affSColin Finck ITypeInfo_Release(ti);
405*c2c66affSColin Finck return hres;
406*c2c66affSColin Finck }
407*c2c66affSColin Finck
408*c2c66affSColin Finck func_cnt = attr->cFuncs;
409*c2c66affSColin Finck ITypeInfo_ReleaseTypeAttr(ti, attr);
410*c2c66affSColin Finck
411*c2c66affSColin Finck ids = heap_alloc(func_cnt*sizeof(DISPID));
412*c2c66affSColin Finck if(!ids) {
413*c2c66affSColin Finck ITypeInfo_Release(ti);
414*c2c66affSColin Finck return E_OUTOFMEMORY;
415*c2c66affSColin Finck }
416*c2c66affSColin Finck
417*c2c66affSColin Finck for(i=0; i < func_cnt; i++) {
418*c2c66affSColin Finck hres = ITypeInfo_GetFuncDesc(ti, i, &funcdesc);
419*c2c66affSColin Finck if(FAILED(hres))
420*c2c66affSColin Finck break;
421*c2c66affSColin Finck
422*c2c66affSColin Finck ids[i] = funcdesc->memid;
423*c2c66affSColin Finck ITypeInfo_ReleaseFuncDesc(ti, funcdesc);
424*c2c66affSColin Finck }
425*c2c66affSColin Finck
426*c2c66affSColin Finck ITypeInfo_Release(ti);
427*c2c66affSColin Finck if(FAILED(hres)) {
428*c2c66affSColin Finck heap_free(ids);
429*c2c66affSColin Finck return hres;
430*c2c66affSColin Finck }
431*c2c66affSColin Finck
432*c2c66affSColin Finck qsort(ids, func_cnt, sizeof(DISPID), id_cmp);
433*c2c66affSColin Finck
434*c2c66affSColin Finck *ret_size = func_cnt;
435*c2c66affSColin Finck *ret = ids;
436*c2c66affSColin Finck return S_OK;
437*c2c66affSColin Finck }
438*c2c66affSColin Finck
get_dispex_data(DispatchEx * This)439*c2c66affSColin Finck static dispex_data_t *get_dispex_data(DispatchEx *This)
440*c2c66affSColin Finck {
441*c2c66affSColin Finck if(This->data->data)
442*c2c66affSColin Finck return This->data->data;
443*c2c66affSColin Finck
444*c2c66affSColin Finck EnterCriticalSection(&cs_dispex_static_data);
445*c2c66affSColin Finck
446*c2c66affSColin Finck if(!This->data->data)
447*c2c66affSColin Finck This->data->data = preprocess_dispex_data(This);
448*c2c66affSColin Finck
449*c2c66affSColin Finck LeaveCriticalSection(&cs_dispex_static_data);
450*c2c66affSColin Finck
451*c2c66affSColin Finck return This->data->data;
452*c2c66affSColin Finck }
453*c2c66affSColin Finck
is_custom_dispid(DISPID id)454*c2c66affSColin Finck static inline BOOL is_custom_dispid(DISPID id)
455*c2c66affSColin Finck {
456*c2c66affSColin Finck return MSHTML_DISPID_CUSTOM_MIN <= id && id <= MSHTML_DISPID_CUSTOM_MAX;
457*c2c66affSColin Finck }
458*c2c66affSColin Finck
is_dynamic_dispid(DISPID id)459*c2c66affSColin Finck static inline BOOL is_dynamic_dispid(DISPID id)
460*c2c66affSColin Finck {
461*c2c66affSColin Finck return DISPID_DYNPROP_0 <= id && id <= DISPID_DYNPROP_MAX;
462*c2c66affSColin Finck }
463*c2c66affSColin Finck
get_dispid_type(DISPID id)464*c2c66affSColin Finck dispex_prop_type_t get_dispid_type(DISPID id)
465*c2c66affSColin Finck {
466*c2c66affSColin Finck if(is_dynamic_dispid(id))
467*c2c66affSColin Finck return DISPEXPROP_DYNAMIC;
468*c2c66affSColin Finck if(is_custom_dispid(id))
469*c2c66affSColin Finck return DISPEXPROP_CUSTOM;
470*c2c66affSColin Finck return DISPEXPROP_BUILTIN;
471*c2c66affSColin Finck }
472*c2c66affSColin Finck
variant_copy(VARIANT * dest,VARIANT * src)473*c2c66affSColin Finck static HRESULT variant_copy(VARIANT *dest, VARIANT *src)
474*c2c66affSColin Finck {
475*c2c66affSColin Finck if(V_VT(src) == VT_BSTR && !V_BSTR(src)) {
476*c2c66affSColin Finck V_VT(dest) = VT_BSTR;
477*c2c66affSColin Finck V_BSTR(dest) = NULL;
478*c2c66affSColin Finck return S_OK;
479*c2c66affSColin Finck }
480*c2c66affSColin Finck
481*c2c66affSColin Finck return VariantCopy(dest, src);
482*c2c66affSColin Finck }
483*c2c66affSColin Finck
get_dynamic_data(DispatchEx * This)484*c2c66affSColin Finck static inline dispex_dynamic_data_t *get_dynamic_data(DispatchEx *This)
485*c2c66affSColin Finck {
486*c2c66affSColin Finck if(This->dynamic_data)
487*c2c66affSColin Finck return This->dynamic_data;
488*c2c66affSColin Finck
489*c2c66affSColin Finck This->dynamic_data = heap_alloc_zero(sizeof(dispex_dynamic_data_t));
490*c2c66affSColin Finck if(!This->dynamic_data)
491*c2c66affSColin Finck return NULL;
492*c2c66affSColin Finck
493*c2c66affSColin Finck if(This->data->vtbl && This->data->vtbl->populate_props)
494*c2c66affSColin Finck This->data->vtbl->populate_props(This);
495*c2c66affSColin Finck
496*c2c66affSColin Finck return This->dynamic_data;
497*c2c66affSColin Finck }
498*c2c66affSColin Finck
get_dynamic_prop(DispatchEx * This,const WCHAR * name,DWORD flags,dynamic_prop_t ** ret)499*c2c66affSColin Finck static HRESULT get_dynamic_prop(DispatchEx *This, const WCHAR *name, DWORD flags, dynamic_prop_t **ret)
500*c2c66affSColin Finck {
501*c2c66affSColin Finck const BOOL alloc = flags & fdexNameEnsure;
502*c2c66affSColin Finck dispex_dynamic_data_t *data;
503*c2c66affSColin Finck dynamic_prop_t *prop;
504*c2c66affSColin Finck
505*c2c66affSColin Finck data = get_dynamic_data(This);
506*c2c66affSColin Finck if(!data)
507*c2c66affSColin Finck return E_OUTOFMEMORY;
508*c2c66affSColin Finck
509*c2c66affSColin Finck for(prop = data->props; prop < data->props+data->prop_cnt; prop++) {
510*c2c66affSColin Finck if(flags & fdexNameCaseInsensitive ? !strcmpiW(prop->name, name) : !strcmpW(prop->name, name)) {
511*c2c66affSColin Finck if(prop->flags & DYNPROP_DELETED) {
512*c2c66affSColin Finck if(!alloc)
513*c2c66affSColin Finck return DISP_E_UNKNOWNNAME;
514*c2c66affSColin Finck prop->flags &= ~DYNPROP_DELETED;
515*c2c66affSColin Finck }
516*c2c66affSColin Finck *ret = prop;
517*c2c66affSColin Finck return S_OK;
518*c2c66affSColin Finck }
519*c2c66affSColin Finck }
520*c2c66affSColin Finck
521*c2c66affSColin Finck if(!alloc)
522*c2c66affSColin Finck return DISP_E_UNKNOWNNAME;
523*c2c66affSColin Finck
524*c2c66affSColin Finck TRACE("creating dynamic prop %s\n", debugstr_w(name));
525*c2c66affSColin Finck
526*c2c66affSColin Finck if(!data->buf_size) {
527*c2c66affSColin Finck data->props = heap_alloc(sizeof(dynamic_prop_t)*4);
528*c2c66affSColin Finck if(!data->props)
529*c2c66affSColin Finck return E_OUTOFMEMORY;
530*c2c66affSColin Finck data->buf_size = 4;
531*c2c66affSColin Finck }else if(data->buf_size == data->prop_cnt) {
532*c2c66affSColin Finck dynamic_prop_t *new_props;
533*c2c66affSColin Finck
534*c2c66affSColin Finck new_props = heap_realloc(data->props, sizeof(dynamic_prop_t)*(data->buf_size<<1));
535*c2c66affSColin Finck if(!new_props)
536*c2c66affSColin Finck return E_OUTOFMEMORY;
537*c2c66affSColin Finck
538*c2c66affSColin Finck data->props = new_props;
539*c2c66affSColin Finck data->buf_size <<= 1;
540*c2c66affSColin Finck }
541*c2c66affSColin Finck
542*c2c66affSColin Finck prop = data->props + data->prop_cnt;
543*c2c66affSColin Finck
544*c2c66affSColin Finck prop->name = heap_strdupW(name);
545*c2c66affSColin Finck if(!prop->name)
546*c2c66affSColin Finck return E_OUTOFMEMORY;
547*c2c66affSColin Finck
548*c2c66affSColin Finck VariantInit(&prop->var);
549*c2c66affSColin Finck prop->flags = 0;
550*c2c66affSColin Finck data->prop_cnt++;
551*c2c66affSColin Finck *ret = prop;
552*c2c66affSColin Finck return S_OK;
553*c2c66affSColin Finck }
554*c2c66affSColin Finck
dispex_get_dprop_ref(DispatchEx * This,const WCHAR * name,BOOL alloc,VARIANT ** ret)555*c2c66affSColin Finck HRESULT dispex_get_dprop_ref(DispatchEx *This, const WCHAR *name, BOOL alloc, VARIANT **ret)
556*c2c66affSColin Finck {
557*c2c66affSColin Finck dynamic_prop_t *prop;
558*c2c66affSColin Finck HRESULT hres;
559*c2c66affSColin Finck
560*c2c66affSColin Finck hres = get_dynamic_prop(This, name, alloc ? fdexNameEnsure : 0, &prop);
561*c2c66affSColin Finck if(FAILED(hres))
562*c2c66affSColin Finck return hres;
563*c2c66affSColin Finck
564*c2c66affSColin Finck *ret = &prop->var;
565*c2c66affSColin Finck return S_OK;
566*c2c66affSColin Finck }
567*c2c66affSColin Finck
dispex_get_dynid(DispatchEx * This,const WCHAR * name,DISPID * id)568*c2c66affSColin Finck HRESULT dispex_get_dynid(DispatchEx *This, const WCHAR *name, DISPID *id)
569*c2c66affSColin Finck {
570*c2c66affSColin Finck dynamic_prop_t *prop;
571*c2c66affSColin Finck HRESULT hres;
572*c2c66affSColin Finck
573*c2c66affSColin Finck hres = get_dynamic_prop(This, name, fdexNameEnsure, &prop);
574*c2c66affSColin Finck if(FAILED(hres))
575*c2c66affSColin Finck return hres;
576*c2c66affSColin Finck
577*c2c66affSColin Finck *id = DISPID_DYNPROP_0 + (prop - This->dynamic_data->props);
578*c2c66affSColin Finck return S_OK;
579*c2c66affSColin Finck }
580*c2c66affSColin Finck
dispex_value(DispatchEx * This,LCID lcid,WORD flags,DISPPARAMS * params,VARIANT * res,EXCEPINFO * ei,IServiceProvider * caller)581*c2c66affSColin Finck static HRESULT dispex_value(DispatchEx *This, LCID lcid, WORD flags, DISPPARAMS *params,
582*c2c66affSColin Finck VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
583*c2c66affSColin Finck {
584*c2c66affSColin Finck if(This->data->vtbl && This->data->vtbl->value)
585*c2c66affSColin Finck return This->data->vtbl->value(This, lcid, flags, params, res, ei, caller);
586*c2c66affSColin Finck
587*c2c66affSColin Finck switch(flags) {
588*c2c66affSColin Finck case DISPATCH_PROPERTYGET:
589*c2c66affSColin Finck V_VT(res) = VT_BSTR;
590*c2c66affSColin Finck V_BSTR(res) = SysAllocString(objectW);
591*c2c66affSColin Finck if(!V_BSTR(res))
592*c2c66affSColin Finck return E_OUTOFMEMORY;
593*c2c66affSColin Finck break;
594*c2c66affSColin Finck default:
595*c2c66affSColin Finck FIXME("Unimplemented flags %x\n", flags);
596*c2c66affSColin Finck return E_NOTIMPL;
597*c2c66affSColin Finck }
598*c2c66affSColin Finck
599*c2c66affSColin Finck return S_OK;
600*c2c66affSColin Finck }
601*c2c66affSColin Finck
typeinfo_invoke(DispatchEx * This,func_info_t * func,WORD flags,DISPPARAMS * dp,VARIANT * res,EXCEPINFO * ei)602*c2c66affSColin Finck static HRESULT typeinfo_invoke(DispatchEx *This, func_info_t *func, WORD flags, DISPPARAMS *dp, VARIANT *res,
603*c2c66affSColin Finck EXCEPINFO *ei)
604*c2c66affSColin Finck {
605*c2c66affSColin Finck ITypeInfo *ti;
606*c2c66affSColin Finck IUnknown *unk;
607*c2c66affSColin Finck UINT argerr=0;
608*c2c66affSColin Finck HRESULT hres;
609*c2c66affSColin Finck
610*c2c66affSColin Finck hres = get_typeinfo(func->tid, &ti);
611*c2c66affSColin Finck if(FAILED(hres)) {
612*c2c66affSColin Finck ERR("Could not get type info: %08x\n", hres);
613*c2c66affSColin Finck return hres;
614*c2c66affSColin Finck }
615*c2c66affSColin Finck
616*c2c66affSColin Finck hres = IUnknown_QueryInterface(This->outer, tid_ids[func->tid], (void**)&unk);
617*c2c66affSColin Finck if(FAILED(hres)) {
618*c2c66affSColin Finck ERR("Could not get iface %s: %08x\n", debugstr_mshtml_guid(tid_ids[func->tid]), hres);
619*c2c66affSColin Finck return E_FAIL;
620*c2c66affSColin Finck }
621*c2c66affSColin Finck
622*c2c66affSColin Finck hres = ITypeInfo_Invoke(ti, unk, func->id, flags, dp, res, ei, &argerr);
623*c2c66affSColin Finck
624*c2c66affSColin Finck IUnknown_Release(unk);
625*c2c66affSColin Finck return hres;
626*c2c66affSColin Finck }
627*c2c66affSColin Finck
impl_from_IUnknown(IUnknown * iface)628*c2c66affSColin Finck static inline func_disp_t *impl_from_IUnknown(IUnknown *iface)
629*c2c66affSColin Finck {
630*c2c66affSColin Finck return CONTAINING_RECORD(iface, func_disp_t, IUnknown_iface);
631*c2c66affSColin Finck }
632*c2c66affSColin Finck
Function_QueryInterface(IUnknown * iface,REFIID riid,void ** ppv)633*c2c66affSColin Finck static HRESULT WINAPI Function_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
634*c2c66affSColin Finck {
635*c2c66affSColin Finck func_disp_t *This = impl_from_IUnknown(iface);
636*c2c66affSColin Finck
637*c2c66affSColin Finck TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
638*c2c66affSColin Finck
639*c2c66affSColin Finck if(IsEqualGUID(&IID_IUnknown, riid)) {
640*c2c66affSColin Finck *ppv = &This->IUnknown_iface;
641*c2c66affSColin Finck }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
642*c2c66affSColin Finck return *ppv ? S_OK : E_NOINTERFACE;
643*c2c66affSColin Finck }else {
644*c2c66affSColin Finck *ppv = NULL;
645*c2c66affSColin Finck return E_NOINTERFACE;
646*c2c66affSColin Finck }
647*c2c66affSColin Finck
648*c2c66affSColin Finck IUnknown_AddRef((IUnknown*)*ppv);
649*c2c66affSColin Finck return S_OK;
650*c2c66affSColin Finck }
651*c2c66affSColin Finck
Function_AddRef(IUnknown * iface)652*c2c66affSColin Finck static ULONG WINAPI Function_AddRef(IUnknown *iface)
653*c2c66affSColin Finck {
654*c2c66affSColin Finck func_disp_t *This = impl_from_IUnknown(iface);
655*c2c66affSColin Finck LONG ref = InterlockedIncrement(&This->ref);
656*c2c66affSColin Finck
657*c2c66affSColin Finck TRACE("(%p) ref=%d\n", This, ref);
658*c2c66affSColin Finck
659*c2c66affSColin Finck return ref;
660*c2c66affSColin Finck }
661*c2c66affSColin Finck
Function_Release(IUnknown * iface)662*c2c66affSColin Finck static ULONG WINAPI Function_Release(IUnknown *iface)
663*c2c66affSColin Finck {
664*c2c66affSColin Finck func_disp_t *This = impl_from_IUnknown(iface);
665*c2c66affSColin Finck LONG ref = InterlockedDecrement(&This->ref);
666*c2c66affSColin Finck
667*c2c66affSColin Finck TRACE("(%p) ref=%d\n", This, ref);
668*c2c66affSColin Finck
669*c2c66affSColin Finck if(!ref) {
670*c2c66affSColin Finck assert(!This->obj);
671*c2c66affSColin Finck release_dispex(&This->dispex);
672*c2c66affSColin Finck heap_free(This);
673*c2c66affSColin Finck }
674*c2c66affSColin Finck
675*c2c66affSColin Finck return ref;
676*c2c66affSColin Finck }
677*c2c66affSColin Finck
678*c2c66affSColin Finck static const IUnknownVtbl FunctionUnkVtbl = {
679*c2c66affSColin Finck Function_QueryInterface,
680*c2c66affSColin Finck Function_AddRef,
681*c2c66affSColin Finck Function_Release
682*c2c66affSColin Finck };
683*c2c66affSColin Finck
impl_from_DispatchEx(DispatchEx * iface)684*c2c66affSColin Finck static inline func_disp_t *impl_from_DispatchEx(DispatchEx *iface)
685*c2c66affSColin Finck {
686*c2c66affSColin Finck return CONTAINING_RECORD(iface, func_disp_t, dispex);
687*c2c66affSColin Finck }
688*c2c66affSColin Finck
function_value(DispatchEx * dispex,LCID lcid,WORD flags,DISPPARAMS * params,VARIANT * res,EXCEPINFO * ei,IServiceProvider * caller)689*c2c66affSColin Finck static HRESULT function_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *params,
690*c2c66affSColin Finck VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
691*c2c66affSColin Finck {
692*c2c66affSColin Finck func_disp_t *This = impl_from_DispatchEx(dispex);
693*c2c66affSColin Finck HRESULT hres;
694*c2c66affSColin Finck
695*c2c66affSColin Finck switch(flags) {
696*c2c66affSColin Finck case DISPATCH_METHOD|DISPATCH_PROPERTYGET:
697*c2c66affSColin Finck if(!res)
698*c2c66affSColin Finck return E_INVALIDARG;
699*c2c66affSColin Finck /* fall through */
700*c2c66affSColin Finck case DISPATCH_METHOD:
701*c2c66affSColin Finck if(!This->obj)
702*c2c66affSColin Finck return E_UNEXPECTED;
703*c2c66affSColin Finck hres = typeinfo_invoke(This->obj, This->info, flags, params, res, ei);
704*c2c66affSColin Finck break;
705*c2c66affSColin Finck case DISPATCH_PROPERTYGET: {
706*c2c66affSColin Finck unsigned name_len;
707*c2c66affSColin Finck WCHAR *ptr;
708*c2c66affSColin Finck BSTR str;
709*c2c66affSColin Finck
710*c2c66affSColin Finck static const WCHAR func_prefixW[] =
711*c2c66affSColin Finck {'\n','f','u','n','c','t','i','o','n',' '};
712*c2c66affSColin Finck static const WCHAR func_suffixW[] =
713*c2c66affSColin Finck {'(',')',' ','{','\n',' ',' ',' ',' ','[','n','a','t','i','v','e',' ','c','o','d','e',']','\n','}','\n'};
714*c2c66affSColin Finck
715*c2c66affSColin Finck /* FIXME: This probably should be more generic. Also we should try to get IID_IActiveScriptSite and SID_GetCaller. */
716*c2c66affSColin Finck if(!caller)
717*c2c66affSColin Finck return E_ACCESSDENIED;
718*c2c66affSColin Finck
719*c2c66affSColin Finck name_len = SysStringLen(This->info->name);
720*c2c66affSColin Finck ptr = str = SysAllocStringLen(NULL, name_len + (sizeof(func_prefixW)+sizeof(func_suffixW))/sizeof(WCHAR));
721*c2c66affSColin Finck if(!str)
722*c2c66affSColin Finck return E_OUTOFMEMORY;
723*c2c66affSColin Finck
724*c2c66affSColin Finck memcpy(ptr, func_prefixW, sizeof(func_prefixW));
725*c2c66affSColin Finck ptr += sizeof(func_prefixW)/sizeof(WCHAR);
726*c2c66affSColin Finck
727*c2c66affSColin Finck memcpy(ptr, This->info->name, name_len*sizeof(WCHAR));
728*c2c66affSColin Finck ptr += name_len;
729*c2c66affSColin Finck
730*c2c66affSColin Finck memcpy(ptr, func_suffixW, sizeof(func_suffixW));
731*c2c66affSColin Finck
732*c2c66affSColin Finck V_VT(res) = VT_BSTR;
733*c2c66affSColin Finck V_BSTR(res) = str;
734*c2c66affSColin Finck return S_OK;
735*c2c66affSColin Finck }
736*c2c66affSColin Finck default:
737*c2c66affSColin Finck FIXME("Unimplemented flags %x\n", flags);
738*c2c66affSColin Finck hres = E_NOTIMPL;
739*c2c66affSColin Finck }
740*c2c66affSColin Finck
741*c2c66affSColin Finck return hres;
742*c2c66affSColin Finck }
743*c2c66affSColin Finck
744*c2c66affSColin Finck static const dispex_static_data_vtbl_t function_dispex_vtbl = {
745*c2c66affSColin Finck function_value,
746*c2c66affSColin Finck NULL,
747*c2c66affSColin Finck NULL,
748*c2c66affSColin Finck NULL
749*c2c66affSColin Finck };
750*c2c66affSColin Finck
751*c2c66affSColin Finck static const tid_t function_iface_tids[] = {0};
752*c2c66affSColin Finck
753*c2c66affSColin Finck static dispex_static_data_t function_dispex = {
754*c2c66affSColin Finck &function_dispex_vtbl,
755*c2c66affSColin Finck NULL_tid,
756*c2c66affSColin Finck NULL,
757*c2c66affSColin Finck function_iface_tids
758*c2c66affSColin Finck };
759*c2c66affSColin Finck
create_func_disp(DispatchEx * obj,func_info_t * info)760*c2c66affSColin Finck static func_disp_t *create_func_disp(DispatchEx *obj, func_info_t *info)
761*c2c66affSColin Finck {
762*c2c66affSColin Finck func_disp_t *ret;
763*c2c66affSColin Finck
764*c2c66affSColin Finck ret = heap_alloc_zero(sizeof(func_disp_t));
765*c2c66affSColin Finck if(!ret)
766*c2c66affSColin Finck return NULL;
767*c2c66affSColin Finck
768*c2c66affSColin Finck ret->IUnknown_iface.lpVtbl = &FunctionUnkVtbl;
769*c2c66affSColin Finck init_dispex(&ret->dispex, &ret->IUnknown_iface, &function_dispex);
770*c2c66affSColin Finck ret->ref = 1;
771*c2c66affSColin Finck ret->obj = obj;
772*c2c66affSColin Finck ret->info = info;
773*c2c66affSColin Finck
774*c2c66affSColin Finck return ret;
775*c2c66affSColin Finck }
776*c2c66affSColin Finck
invoke_disp_value(DispatchEx * This,IDispatch * func_disp,LCID lcid,WORD flags,DISPPARAMS * dp,VARIANT * res,EXCEPINFO * ei,IServiceProvider * caller)777*c2c66affSColin Finck static HRESULT invoke_disp_value(DispatchEx *This, IDispatch *func_disp, LCID lcid, WORD flags, DISPPARAMS *dp,
778*c2c66affSColin Finck VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
779*c2c66affSColin Finck {
780*c2c66affSColin Finck DISPID named_arg = DISPID_THIS;
781*c2c66affSColin Finck DISPPARAMS new_dp = {NULL, &named_arg, 0, 1};
782*c2c66affSColin Finck IDispatchEx *dispex;
783*c2c66affSColin Finck HRESULT hres;
784*c2c66affSColin Finck
785*c2c66affSColin Finck if(dp->cNamedArgs) {
786*c2c66affSColin Finck FIXME("named args not supported\n");
787*c2c66affSColin Finck return E_NOTIMPL;
788*c2c66affSColin Finck }
789*c2c66affSColin Finck
790*c2c66affSColin Finck new_dp.rgvarg = heap_alloc((dp->cArgs+1)*sizeof(VARIANTARG));
791*c2c66affSColin Finck if(!new_dp.rgvarg)
792*c2c66affSColin Finck return E_OUTOFMEMORY;
793*c2c66affSColin Finck
794*c2c66affSColin Finck new_dp.cArgs = dp->cArgs+1;
795*c2c66affSColin Finck memcpy(new_dp.rgvarg+1, dp->rgvarg, dp->cArgs*sizeof(VARIANTARG));
796*c2c66affSColin Finck
797*c2c66affSColin Finck V_VT(new_dp.rgvarg) = VT_DISPATCH;
798*c2c66affSColin Finck V_DISPATCH(new_dp.rgvarg) = (IDispatch*)&This->IDispatchEx_iface;
799*c2c66affSColin Finck
800*c2c66affSColin Finck hres = IDispatch_QueryInterface(func_disp, &IID_IDispatchEx, (void**)&dispex);
801*c2c66affSColin Finck TRACE(">>>\n");
802*c2c66affSColin Finck if(SUCCEEDED(hres)) {
803*c2c66affSColin Finck hres = IDispatchEx_InvokeEx(dispex, DISPID_VALUE, lcid, flags, &new_dp, res, ei, caller);
804*c2c66affSColin Finck IDispatchEx_Release(dispex);
805*c2c66affSColin Finck }else {
806*c2c66affSColin Finck ULONG err = 0;
807*c2c66affSColin Finck hres = IDispatch_Invoke(func_disp, DISPID_VALUE, &IID_NULL, lcid, flags, &new_dp, res, ei, &err);
808*c2c66affSColin Finck }
809*c2c66affSColin Finck if(SUCCEEDED(hres))
810*c2c66affSColin Finck TRACE("<<< %s\n", debugstr_variant(res));
811*c2c66affSColin Finck else
812*c2c66affSColin Finck WARN("<<< %08x\n", hres);
813*c2c66affSColin Finck
814*c2c66affSColin Finck heap_free(new_dp.rgvarg);
815*c2c66affSColin Finck return hres;
816*c2c66affSColin Finck }
817*c2c66affSColin Finck
get_func_obj_entry(DispatchEx * This,func_info_t * func,func_obj_entry_t ** ret)818*c2c66affSColin Finck static HRESULT get_func_obj_entry(DispatchEx *This, func_info_t *func, func_obj_entry_t **ret)
819*c2c66affSColin Finck {
820*c2c66affSColin Finck dispex_dynamic_data_t *dynamic_data;
821*c2c66affSColin Finck func_obj_entry_t *entry;
822*c2c66affSColin Finck
823*c2c66affSColin Finck dynamic_data = get_dynamic_data(This);
824*c2c66affSColin Finck if(!dynamic_data)
825*c2c66affSColin Finck return E_OUTOFMEMORY;
826*c2c66affSColin Finck
827*c2c66affSColin Finck if(!dynamic_data->func_disps) {
828*c2c66affSColin Finck dynamic_data->func_disps = heap_alloc_zero(This->data->data->func_disp_cnt * sizeof(*dynamic_data->func_disps));
829*c2c66affSColin Finck if(!dynamic_data->func_disps)
830*c2c66affSColin Finck return E_OUTOFMEMORY;
831*c2c66affSColin Finck }
832*c2c66affSColin Finck
833*c2c66affSColin Finck entry = dynamic_data->func_disps + func->func_disp_idx;
834*c2c66affSColin Finck if(!entry->func_obj) {
835*c2c66affSColin Finck entry->func_obj = create_func_disp(This, func);
836*c2c66affSColin Finck if(!entry->func_obj)
837*c2c66affSColin Finck return E_OUTOFMEMORY;
838*c2c66affSColin Finck
839*c2c66affSColin Finck IDispatchEx_AddRef(&entry->func_obj->dispex.IDispatchEx_iface);
840*c2c66affSColin Finck V_VT(&entry->val) = VT_DISPATCH;
841*c2c66affSColin Finck V_DISPATCH(&entry->val) = (IDispatch*)&entry->func_obj->dispex.IDispatchEx_iface;
842*c2c66affSColin Finck }
843*c2c66affSColin Finck
844*c2c66affSColin Finck *ret = entry;
845*c2c66affSColin Finck return S_OK;
846*c2c66affSColin Finck }
847*c2c66affSColin Finck
get_builtin_func(dispex_data_t * data,DISPID id,func_info_t ** ret)848*c2c66affSColin Finck static HRESULT get_builtin_func(dispex_data_t *data, DISPID id, func_info_t **ret)
849*c2c66affSColin Finck {
850*c2c66affSColin Finck int min, max, n;
851*c2c66affSColin Finck
852*c2c66affSColin Finck min = 0;
853*c2c66affSColin Finck max = data->func_cnt-1;
854*c2c66affSColin Finck
855*c2c66affSColin Finck while(min <= max) {
856*c2c66affSColin Finck n = (min+max)/2;
857*c2c66affSColin Finck
858*c2c66affSColin Finck if(data->funcs[n].id == id) {
859*c2c66affSColin Finck *ret = data->funcs+n;
860*c2c66affSColin Finck return S_OK;
861*c2c66affSColin Finck }
862*c2c66affSColin Finck
863*c2c66affSColin Finck if(data->funcs[n].id < id)
864*c2c66affSColin Finck min = n+1;
865*c2c66affSColin Finck else
866*c2c66affSColin Finck max = n-1;
867*c2c66affSColin Finck }
868*c2c66affSColin Finck
869*c2c66affSColin Finck WARN("invalid id %x\n", id);
870*c2c66affSColin Finck return DISP_E_UNKNOWNNAME;
871*c2c66affSColin Finck }
872*c2c66affSColin Finck
get_builtin_id(DispatchEx * This,BSTR name,DWORD grfdex,DISPID * ret)873*c2c66affSColin Finck static HRESULT get_builtin_id(DispatchEx *This, BSTR name, DWORD grfdex, DISPID *ret)
874*c2c66affSColin Finck {
875*c2c66affSColin Finck dispex_data_t *data;
876*c2c66affSColin Finck int min, max, n, c;
877*c2c66affSColin Finck
878*c2c66affSColin Finck data = get_dispex_data(This);
879*c2c66affSColin Finck if(!data)
880*c2c66affSColin Finck return E_FAIL;
881*c2c66affSColin Finck
882*c2c66affSColin Finck min = 0;
883*c2c66affSColin Finck max = data->func_cnt-1;
884*c2c66affSColin Finck
885*c2c66affSColin Finck while(min <= max) {
886*c2c66affSColin Finck n = (min+max)/2;
887*c2c66affSColin Finck
888*c2c66affSColin Finck c = strcmpiW(data->name_table[n]->name, name);
889*c2c66affSColin Finck if(!c) {
890*c2c66affSColin Finck if((grfdex & fdexNameCaseSensitive) && strcmpW(data->name_table[n]->name, name))
891*c2c66affSColin Finck break;
892*c2c66affSColin Finck
893*c2c66affSColin Finck *ret = data->name_table[n]->id;
894*c2c66affSColin Finck return S_OK;
895*c2c66affSColin Finck }
896*c2c66affSColin Finck
897*c2c66affSColin Finck if(c > 0)
898*c2c66affSColin Finck max = n-1;
899*c2c66affSColin Finck else
900*c2c66affSColin Finck min = n+1;
901*c2c66affSColin Finck }
902*c2c66affSColin Finck
903*c2c66affSColin Finck if(This->data->vtbl && This->data->vtbl->get_dispid) {
904*c2c66affSColin Finck HRESULT hres;
905*c2c66affSColin Finck
906*c2c66affSColin Finck hres = This->data->vtbl->get_dispid(This, name, grfdex, ret);
907*c2c66affSColin Finck if(hres != DISP_E_UNKNOWNNAME)
908*c2c66affSColin Finck return hres;
909*c2c66affSColin Finck }
910*c2c66affSColin Finck
911*c2c66affSColin Finck return DISP_E_UNKNOWNNAME;
912*c2c66affSColin Finck }
913*c2c66affSColin Finck
change_type(VARIANT * dst,VARIANT * src,VARTYPE vt,IServiceProvider * caller)914*c2c66affSColin Finck static HRESULT change_type(VARIANT *dst, VARIANT *src, VARTYPE vt, IServiceProvider *caller)
915*c2c66affSColin Finck {
916*c2c66affSColin Finck V_VT(dst) = VT_EMPTY;
917*c2c66affSColin Finck
918*c2c66affSColin Finck if(caller) {
919*c2c66affSColin Finck IVariantChangeType *change_type = NULL;
920*c2c66affSColin Finck HRESULT hres;
921*c2c66affSColin Finck
922*c2c66affSColin Finck hres = IServiceProvider_QueryService(caller, &SID_VariantConversion, &IID_IVariantChangeType, (void**)&change_type);
923*c2c66affSColin Finck if(SUCCEEDED(hres)) {
924*c2c66affSColin Finck hres = IVariantChangeType_ChangeType(change_type, dst, src, LOCALE_NEUTRAL, vt);
925*c2c66affSColin Finck IVariantChangeType_Release(change_type);
926*c2c66affSColin Finck return hres;
927*c2c66affSColin Finck }
928*c2c66affSColin Finck }
929*c2c66affSColin Finck
930*c2c66affSColin Finck switch(vt) {
931*c2c66affSColin Finck case VT_BOOL:
932*c2c66affSColin Finck if(V_VT(src) == VT_BSTR) {
933*c2c66affSColin Finck V_VT(dst) = VT_BOOL;
934*c2c66affSColin Finck V_BOOL(dst) = V_BSTR(src) && *V_BSTR(src) ? VARIANT_TRUE : VARIANT_FALSE;
935*c2c66affSColin Finck return S_OK;
936*c2c66affSColin Finck }
937*c2c66affSColin Finck break;
938*c2c66affSColin Finck }
939*c2c66affSColin Finck
940*c2c66affSColin Finck return VariantChangeType(dst, src, 0, vt);
941*c2c66affSColin Finck }
942*c2c66affSColin Finck
builtin_propget(DispatchEx * This,func_info_t * func,DISPPARAMS * dp,VARIANT * res)943*c2c66affSColin Finck static HRESULT builtin_propget(DispatchEx *This, func_info_t *func, DISPPARAMS *dp, VARIANT *res)
944*c2c66affSColin Finck {
945*c2c66affSColin Finck IUnknown *iface;
946*c2c66affSColin Finck HRESULT hres;
947*c2c66affSColin Finck
948*c2c66affSColin Finck if(dp && dp->cArgs) {
949*c2c66affSColin Finck FIXME("cArgs %d\n", dp->cArgs);
950*c2c66affSColin Finck return E_NOTIMPL;
951*c2c66affSColin Finck }
952*c2c66affSColin Finck
953*c2c66affSColin Finck assert(func->get_vtbl_off);
954*c2c66affSColin Finck
955*c2c66affSColin Finck hres = IUnknown_QueryInterface(This->outer, tid_ids[func->tid], (void**)&iface);
956*c2c66affSColin Finck if(SUCCEEDED(hres)) {
957*c2c66affSColin Finck switch(func->prop_vt) {
958*c2c66affSColin Finck #define CASE_VT(vt,type,access) \
959*c2c66affSColin Finck case vt: { \
960*c2c66affSColin Finck type val; \
961*c2c66affSColin Finck hres = ((HRESULT (WINAPI*)(IUnknown*,type*))((void**)iface->lpVtbl)[func->get_vtbl_off])(iface,&val); \
962*c2c66affSColin Finck if(SUCCEEDED(hres)) \
963*c2c66affSColin Finck access(res) = val; \
964*c2c66affSColin Finck } \
965*c2c66affSColin Finck break
966*c2c66affSColin Finck BUILTIN_TYPES_SWITCH;
967*c2c66affSColin Finck #undef CASE_VT
968*c2c66affSColin Finck default:
969*c2c66affSColin Finck FIXME("Unhandled vt %d\n", func->prop_vt);
970*c2c66affSColin Finck hres = E_NOTIMPL;
971*c2c66affSColin Finck }
972*c2c66affSColin Finck IUnknown_Release(iface);
973*c2c66affSColin Finck }
974*c2c66affSColin Finck
975*c2c66affSColin Finck if(FAILED(hres))
976*c2c66affSColin Finck return hres;
977*c2c66affSColin Finck
978*c2c66affSColin Finck if(func->prop_vt != VT_VARIANT)
979*c2c66affSColin Finck V_VT(res) = func->prop_vt == VT_PTR ? VT_DISPATCH : func->prop_vt;
980*c2c66affSColin Finck return S_OK;
981*c2c66affSColin Finck }
982*c2c66affSColin Finck
builtin_propput(DispatchEx * This,func_info_t * func,DISPPARAMS * dp,IServiceProvider * caller)983*c2c66affSColin Finck static HRESULT builtin_propput(DispatchEx *This, func_info_t *func, DISPPARAMS *dp, IServiceProvider *caller)
984*c2c66affSColin Finck {
985*c2c66affSColin Finck VARIANT *v, tmpv;
986*c2c66affSColin Finck IUnknown *iface;
987*c2c66affSColin Finck HRESULT hres;
988*c2c66affSColin Finck
989*c2c66affSColin Finck if(dp->cArgs != 1 || (dp->cNamedArgs == 1 && *dp->rgdispidNamedArgs != DISPID_PROPERTYPUT)
990*c2c66affSColin Finck || dp->cNamedArgs > 1) {
991*c2c66affSColin Finck FIXME("invalid args\n");
992*c2c66affSColin Finck return E_INVALIDARG;
993*c2c66affSColin Finck }
994*c2c66affSColin Finck
995*c2c66affSColin Finck if(!func->put_vtbl_off) {
996*c2c66affSColin Finck FIXME("No setter\n");
997*c2c66affSColin Finck return E_FAIL;
998*c2c66affSColin Finck }
999*c2c66affSColin Finck
1000*c2c66affSColin Finck v = dp->rgvarg;
1001*c2c66affSColin Finck if(func->prop_vt != VT_VARIANT && V_VT(v) != func->prop_vt) {
1002*c2c66affSColin Finck hres = change_type(&tmpv, v, func->prop_vt, caller);
1003*c2c66affSColin Finck if(FAILED(hres))
1004*c2c66affSColin Finck return hres;
1005*c2c66affSColin Finck v = &tmpv;
1006*c2c66affSColin Finck }
1007*c2c66affSColin Finck
1008*c2c66affSColin Finck hres = IUnknown_QueryInterface(This->outer, tid_ids[func->tid], (void**)&iface);
1009*c2c66affSColin Finck if(SUCCEEDED(hres)) {
1010*c2c66affSColin Finck switch(func->prop_vt) {
1011*c2c66affSColin Finck #define CASE_VT(vt,type,access) \
1012*c2c66affSColin Finck case vt: \
1013*c2c66affSColin Finck hres = ((HRESULT (WINAPI*)(IUnknown*,type))((void**)iface->lpVtbl)[func->put_vtbl_off])(iface,access(v)); \
1014*c2c66affSColin Finck break
1015*c2c66affSColin Finck BUILTIN_TYPES_SWITCH;
1016*c2c66affSColin Finck #undef CASE_VT
1017*c2c66affSColin Finck default:
1018*c2c66affSColin Finck FIXME("Unimplemented vt %d\n", func->prop_vt);
1019*c2c66affSColin Finck hres = E_NOTIMPL;
1020*c2c66affSColin Finck }
1021*c2c66affSColin Finck
1022*c2c66affSColin Finck IUnknown_Release(iface);
1023*c2c66affSColin Finck }
1024*c2c66affSColin Finck
1025*c2c66affSColin Finck if(v == &tmpv)
1026*c2c66affSColin Finck VariantClear(v);
1027*c2c66affSColin Finck return hres;
1028*c2c66affSColin Finck }
1029*c2c66affSColin Finck
invoke_builtin_function(DispatchEx * This,func_info_t * func,DISPPARAMS * dp,VARIANT * res,IServiceProvider * caller)1030*c2c66affSColin Finck static HRESULT invoke_builtin_function(DispatchEx *This, func_info_t *func, DISPPARAMS *dp, VARIANT *res, IServiceProvider *caller)
1031*c2c66affSColin Finck {
1032*c2c66affSColin Finck VARIANT arg_buf[MAX_ARGS], *arg_ptrs[MAX_ARGS], *arg, retv, ret_ref, vhres;
1033*c2c66affSColin Finck unsigned i, nconv = 0;
1034*c2c66affSColin Finck IUnknown *iface;
1035*c2c66affSColin Finck HRESULT hres;
1036*c2c66affSColin Finck
1037*c2c66affSColin Finck if(dp->cNamedArgs) {
1038*c2c66affSColin Finck FIXME("Named arguments not supported\n");
1039*c2c66affSColin Finck return E_NOTIMPL;
1040*c2c66affSColin Finck }
1041*c2c66affSColin Finck
1042*c2c66affSColin Finck if(dp->cArgs != func->argc) {
1043*c2c66affSColin Finck FIXME("Invalid argument count (expected %u, got %u)\n", func->argc, dp->cArgs);
1044*c2c66affSColin Finck return E_INVALIDARG;
1045*c2c66affSColin Finck }
1046*c2c66affSColin Finck
1047*c2c66affSColin Finck hres = IUnknown_QueryInterface(This->outer, tid_ids[func->tid], (void**)&iface);
1048*c2c66affSColin Finck if(FAILED(hres))
1049*c2c66affSColin Finck return hres;
1050*c2c66affSColin Finck
1051*c2c66affSColin Finck for(i=0; i < func->argc; i++) {
1052*c2c66affSColin Finck arg = dp->rgvarg+dp->cArgs-i-1;
1053*c2c66affSColin Finck if(func->arg_types[i] == V_VT(arg)) {
1054*c2c66affSColin Finck arg_ptrs[i] = arg;
1055*c2c66affSColin Finck }else {
1056*c2c66affSColin Finck hres = change_type(arg_buf+nconv, arg, func->arg_types[i], caller);
1057*c2c66affSColin Finck if(FAILED(hres))
1058*c2c66affSColin Finck break;
1059*c2c66affSColin Finck arg_ptrs[i] = arg_buf + nconv++;
1060*c2c66affSColin Finck }
1061*c2c66affSColin Finck }
1062*c2c66affSColin Finck
1063*c2c66affSColin Finck if(SUCCEEDED(hres)) {
1064*c2c66affSColin Finck if(func->prop_vt == VT_VOID) {
1065*c2c66affSColin Finck V_VT(&retv) = VT_EMPTY;
1066*c2c66affSColin Finck }else {
1067*c2c66affSColin Finck V_VT(&retv) = func->prop_vt;
1068*c2c66affSColin Finck arg_ptrs[func->argc] = &ret_ref;
1069*c2c66affSColin Finck V_VT(&ret_ref) = VT_BYREF|func->prop_vt;
1070*c2c66affSColin Finck
1071*c2c66affSColin Finck switch(func->prop_vt) {
1072*c2c66affSColin Finck #define CASE_VT(vt,type,access) \
1073*c2c66affSColin Finck case vt: \
1074*c2c66affSColin Finck V_BYREF(&ret_ref) = &access(&retv); \
1075*c2c66affSColin Finck break
1076*c2c66affSColin Finck BUILTIN_TYPES_SWITCH;
1077*c2c66affSColin Finck #undef CASE_VT
1078*c2c66affSColin Finck default:
1079*c2c66affSColin Finck assert(0);
1080*c2c66affSColin Finck }
1081*c2c66affSColin Finck }
1082*c2c66affSColin Finck
1083*c2c66affSColin Finck V_VT(&vhres) = VT_ERROR;
1084*c2c66affSColin Finck hres = DispCallFunc(iface, func->call_vtbl_off*sizeof(void*), CC_STDCALL, VT_ERROR,
1085*c2c66affSColin Finck func->argc + (func->prop_vt == VT_VOID ? 0 : 1), func->arg_types, arg_ptrs, &vhres);
1086*c2c66affSColin Finck }
1087*c2c66affSColin Finck
1088*c2c66affSColin Finck while(nconv--)
1089*c2c66affSColin Finck VariantClear(arg_buf+nconv);
1090*c2c66affSColin Finck IUnknown_Release(iface);
1091*c2c66affSColin Finck if(FAILED(hres))
1092*c2c66affSColin Finck return hres;
1093*c2c66affSColin Finck if(FAILED(V_ERROR(&vhres)))
1094*c2c66affSColin Finck return V_ERROR(&vhres);
1095*c2c66affSColin Finck
1096*c2c66affSColin Finck if(res)
1097*c2c66affSColin Finck *res = retv;
1098*c2c66affSColin Finck else
1099*c2c66affSColin Finck VariantClear(&retv);
1100*c2c66affSColin Finck return V_ERROR(&vhres);
1101*c2c66affSColin Finck }
1102*c2c66affSColin Finck
function_invoke(DispatchEx * This,func_info_t * func,WORD flags,DISPPARAMS * dp,VARIANT * res,EXCEPINFO * ei,IServiceProvider * caller)1103*c2c66affSColin Finck static HRESULT function_invoke(DispatchEx *This, func_info_t *func, WORD flags, DISPPARAMS *dp, VARIANT *res,
1104*c2c66affSColin Finck EXCEPINFO *ei, IServiceProvider *caller)
1105*c2c66affSColin Finck {
1106*c2c66affSColin Finck HRESULT hres;
1107*c2c66affSColin Finck
1108*c2c66affSColin Finck switch(flags) {
1109*c2c66affSColin Finck case DISPATCH_METHOD|DISPATCH_PROPERTYGET:
1110*c2c66affSColin Finck if(!res)
1111*c2c66affSColin Finck return E_INVALIDARG;
1112*c2c66affSColin Finck /* fall through */
1113*c2c66affSColin Finck case DISPATCH_METHOD:
1114*c2c66affSColin Finck if(This->dynamic_data && This->dynamic_data->func_disps
1115*c2c66affSColin Finck && This->dynamic_data->func_disps[func->func_disp_idx].func_obj) {
1116*c2c66affSColin Finck func_obj_entry_t *entry = This->dynamic_data->func_disps + func->func_disp_idx;
1117*c2c66affSColin Finck
1118*c2c66affSColin Finck if(V_VT(&entry->val) != VT_DISPATCH) {
1119*c2c66affSColin Finck FIXME("calling %s not supported\n", debugstr_variant(&entry->val));
1120*c2c66affSColin Finck return E_NOTIMPL;
1121*c2c66affSColin Finck }
1122*c2c66affSColin Finck
1123*c2c66affSColin Finck if((IDispatch*)&entry->func_obj->dispex.IDispatchEx_iface != V_DISPATCH(&entry->val)) {
1124*c2c66affSColin Finck if(!V_DISPATCH(&entry->val)) {
1125*c2c66affSColin Finck FIXME("Calling null\n");
1126*c2c66affSColin Finck return E_FAIL;
1127*c2c66affSColin Finck }
1128*c2c66affSColin Finck
1129*c2c66affSColin Finck hres = invoke_disp_value(This, V_DISPATCH(&entry->val), 0, flags, dp, res, ei, NULL);
1130*c2c66affSColin Finck break;
1131*c2c66affSColin Finck }
1132*c2c66affSColin Finck }
1133*c2c66affSColin Finck
1134*c2c66affSColin Finck if(func->call_vtbl_off)
1135*c2c66affSColin Finck hres = invoke_builtin_function(This, func, dp, res, caller);
1136*c2c66affSColin Finck else
1137*c2c66affSColin Finck hres = typeinfo_invoke(This, func, flags, dp, res, ei);
1138*c2c66affSColin Finck break;
1139*c2c66affSColin Finck case DISPATCH_PROPERTYGET: {
1140*c2c66affSColin Finck func_obj_entry_t *entry;
1141*c2c66affSColin Finck
1142*c2c66affSColin Finck if(func->id == DISPID_VALUE) {
1143*c2c66affSColin Finck BSTR ret;
1144*c2c66affSColin Finck
1145*c2c66affSColin Finck ret = SysAllocString(objectW);
1146*c2c66affSColin Finck if(!ret)
1147*c2c66affSColin Finck return E_OUTOFMEMORY;
1148*c2c66affSColin Finck
1149*c2c66affSColin Finck V_VT(res) = VT_BSTR;
1150*c2c66affSColin Finck V_BSTR(res) = ret;
1151*c2c66affSColin Finck return S_OK;
1152*c2c66affSColin Finck }
1153*c2c66affSColin Finck
1154*c2c66affSColin Finck hres = get_func_obj_entry(This, func, &entry);
1155*c2c66affSColin Finck if(FAILED(hres))
1156*c2c66affSColin Finck return hres;
1157*c2c66affSColin Finck
1158*c2c66affSColin Finck V_VT(res) = VT_EMPTY;
1159*c2c66affSColin Finck return VariantCopy(res, &entry->val);
1160*c2c66affSColin Finck }
1161*c2c66affSColin Finck case DISPATCH_PROPERTYPUT: {
1162*c2c66affSColin Finck func_obj_entry_t *entry;
1163*c2c66affSColin Finck
1164*c2c66affSColin Finck if(dp->cArgs != 1 || (dp->cNamedArgs == 1 && *dp->rgdispidNamedArgs != DISPID_PROPERTYPUT)
1165*c2c66affSColin Finck || dp->cNamedArgs > 1) {
1166*c2c66affSColin Finck FIXME("invalid args\n");
1167*c2c66affSColin Finck return E_INVALIDARG;
1168*c2c66affSColin Finck }
1169*c2c66affSColin Finck
1170*c2c66affSColin Finck /*
1171*c2c66affSColin Finck * NOTE: Although we have IDispatchEx tests showing, that it's not allowed to set
1172*c2c66affSColin Finck * function property using InvokeEx, it's possible to do that from jscript.
1173*c2c66affSColin Finck * Native probably uses some undocumented interface in this case, but it should
1174*c2c66affSColin Finck * be fine for us to allow IDispatchEx handle that.
1175*c2c66affSColin Finck */
1176*c2c66affSColin Finck hres = get_func_obj_entry(This, func, &entry);
1177*c2c66affSColin Finck if(FAILED(hres))
1178*c2c66affSColin Finck return hres;
1179*c2c66affSColin Finck
1180*c2c66affSColin Finck return VariantCopy(&entry->val, dp->rgvarg);
1181*c2c66affSColin Finck }
1182*c2c66affSColin Finck default:
1183*c2c66affSColin Finck FIXME("Unimplemented flags %x\n", flags);
1184*c2c66affSColin Finck hres = E_NOTIMPL;
1185*c2c66affSColin Finck }
1186*c2c66affSColin Finck
1187*c2c66affSColin Finck return hres;
1188*c2c66affSColin Finck }
1189*c2c66affSColin Finck
invoke_builtin_prop(DispatchEx * This,DISPID id,LCID lcid,WORD flags,DISPPARAMS * dp,VARIANT * res,EXCEPINFO * ei,IServiceProvider * caller)1190*c2c66affSColin Finck static HRESULT invoke_builtin_prop(DispatchEx *This, DISPID id, LCID lcid, WORD flags, DISPPARAMS *dp,
1191*c2c66affSColin Finck VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
1192*c2c66affSColin Finck {
1193*c2c66affSColin Finck dispex_data_t *data;
1194*c2c66affSColin Finck func_info_t *func;
1195*c2c66affSColin Finck HRESULT hres;
1196*c2c66affSColin Finck
1197*c2c66affSColin Finck data = get_dispex_data(This);
1198*c2c66affSColin Finck if(!data)
1199*c2c66affSColin Finck return E_FAIL;
1200*c2c66affSColin Finck
1201*c2c66affSColin Finck hres = get_builtin_func(data, id, &func);
1202*c2c66affSColin Finck if(id == DISPID_VALUE && hres == DISP_E_UNKNOWNNAME)
1203*c2c66affSColin Finck return dispex_value(This, lcid, flags, dp, res, ei, caller);
1204*c2c66affSColin Finck if(FAILED(hres))
1205*c2c66affSColin Finck return hres;
1206*c2c66affSColin Finck
1207*c2c66affSColin Finck if(func->func_disp_idx != -1)
1208*c2c66affSColin Finck return function_invoke(This, func, flags, dp, res, ei, caller);
1209*c2c66affSColin Finck
1210*c2c66affSColin Finck switch(flags) {
1211*c2c66affSColin Finck case DISPATCH_PROPERTYPUT:
1212*c2c66affSColin Finck if(res)
1213*c2c66affSColin Finck V_VT(res) = VT_EMPTY;
1214*c2c66affSColin Finck hres = builtin_propput(This, func, dp, caller);
1215*c2c66affSColin Finck break;
1216*c2c66affSColin Finck case DISPATCH_PROPERTYGET:
1217*c2c66affSColin Finck hres = builtin_propget(This, func, dp, res);
1218*c2c66affSColin Finck break;
1219*c2c66affSColin Finck default:
1220*c2c66affSColin Finck if(!func->get_vtbl_off) {
1221*c2c66affSColin Finck hres = typeinfo_invoke(This, func, flags, dp, res, ei);
1222*c2c66affSColin Finck }else {
1223*c2c66affSColin Finck VARIANT v;
1224*c2c66affSColin Finck
1225*c2c66affSColin Finck hres = builtin_propget(This, func, NULL, &v);
1226*c2c66affSColin Finck if(FAILED(hres))
1227*c2c66affSColin Finck return hres;
1228*c2c66affSColin Finck
1229*c2c66affSColin Finck if(flags != (DISPATCH_PROPERTYGET|DISPATCH_METHOD) || dp->cArgs) {
1230*c2c66affSColin Finck if(V_VT(&v) != VT_DISPATCH) {
1231*c2c66affSColin Finck FIXME("Not a function %s flags %08x\n", debugstr_variant(&v), flags);
1232*c2c66affSColin Finck VariantClear(&v);
1233*c2c66affSColin Finck return E_FAIL;
1234*c2c66affSColin Finck }
1235*c2c66affSColin Finck
1236*c2c66affSColin Finck hres = invoke_disp_value(This, V_DISPATCH(&v), lcid, flags, dp, res, ei, caller);
1237*c2c66affSColin Finck IDispatch_Release(V_DISPATCH(&v));
1238*c2c66affSColin Finck }else if(res) {
1239*c2c66affSColin Finck *res = v;
1240*c2c66affSColin Finck }else {
1241*c2c66affSColin Finck VariantClear(&v);
1242*c2c66affSColin Finck }
1243*c2c66affSColin Finck }
1244*c2c66affSColin Finck }
1245*c2c66affSColin Finck
1246*c2c66affSColin Finck return hres;
1247*c2c66affSColin Finck }
1248*c2c66affSColin Finck
remove_attribute(DispatchEx * This,DISPID id,VARIANT_BOOL * success)1249*c2c66affSColin Finck HRESULT remove_attribute(DispatchEx *This, DISPID id, VARIANT_BOOL *success)
1250*c2c66affSColin Finck {
1251*c2c66affSColin Finck switch(get_dispid_type(id)) {
1252*c2c66affSColin Finck case DISPEXPROP_CUSTOM:
1253*c2c66affSColin Finck FIXME("DISPEXPROP_CUSTOM not supported\n");
1254*c2c66affSColin Finck return E_NOTIMPL;
1255*c2c66affSColin Finck
1256*c2c66affSColin Finck case DISPEXPROP_DYNAMIC: {
1257*c2c66affSColin Finck DWORD idx = id - DISPID_DYNPROP_0;
1258*c2c66affSColin Finck dynamic_prop_t *prop;
1259*c2c66affSColin Finck
1260*c2c66affSColin Finck prop = This->dynamic_data->props+idx;
1261*c2c66affSColin Finck VariantClear(&prop->var);
1262*c2c66affSColin Finck prop->flags |= DYNPROP_DELETED;
1263*c2c66affSColin Finck *success = VARIANT_TRUE;
1264*c2c66affSColin Finck return S_OK;
1265*c2c66affSColin Finck }
1266*c2c66affSColin Finck case DISPEXPROP_BUILTIN: {
1267*c2c66affSColin Finck VARIANT var;
1268*c2c66affSColin Finck DISPPARAMS dp = {&var,NULL,1,0};
1269*c2c66affSColin Finck dispex_data_t *data;
1270*c2c66affSColin Finck func_info_t *func;
1271*c2c66affSColin Finck HRESULT hres;
1272*c2c66affSColin Finck
1273*c2c66affSColin Finck data = get_dispex_data(This);
1274*c2c66affSColin Finck if(!data)
1275*c2c66affSColin Finck return E_FAIL;
1276*c2c66affSColin Finck
1277*c2c66affSColin Finck hres = get_builtin_func(data, id, &func);
1278*c2c66affSColin Finck if(FAILED(hres))
1279*c2c66affSColin Finck return hres;
1280*c2c66affSColin Finck
1281*c2c66affSColin Finck /* For builtin functions, we set their value to the original function. */
1282*c2c66affSColin Finck if(func->func_disp_idx != -1) {
1283*c2c66affSColin Finck func_obj_entry_t *entry;
1284*c2c66affSColin Finck
1285*c2c66affSColin Finck if(!This->dynamic_data || !This->dynamic_data->func_disps
1286*c2c66affSColin Finck || !This->dynamic_data->func_disps[func->func_disp_idx].func_obj) {
1287*c2c66affSColin Finck *success = VARIANT_FALSE;
1288*c2c66affSColin Finck return S_OK;
1289*c2c66affSColin Finck }
1290*c2c66affSColin Finck
1291*c2c66affSColin Finck entry = This->dynamic_data->func_disps + func->func_disp_idx;
1292*c2c66affSColin Finck if(V_VT(&entry->val) == VT_DISPATCH
1293*c2c66affSColin Finck && V_DISPATCH(&entry->val) == (IDispatch*)&entry->func_obj->dispex.IDispatchEx_iface) {
1294*c2c66affSColin Finck *success = VARIANT_FALSE;
1295*c2c66affSColin Finck return S_OK;
1296*c2c66affSColin Finck }
1297*c2c66affSColin Finck
1298*c2c66affSColin Finck VariantClear(&entry->val);
1299*c2c66affSColin Finck V_VT(&entry->val) = VT_DISPATCH;
1300*c2c66affSColin Finck V_DISPATCH(&entry->val) = (IDispatch*)&entry->func_obj->dispex.IDispatchEx_iface;
1301*c2c66affSColin Finck IDispatch_AddRef(V_DISPATCH(&entry->val));
1302*c2c66affSColin Finck *success = VARIANT_TRUE;
1303*c2c66affSColin Finck return S_OK;
1304*c2c66affSColin Finck }
1305*c2c66affSColin Finck
1306*c2c66affSColin Finck V_VT(&var) = VT_EMPTY;
1307*c2c66affSColin Finck hres = builtin_propput(This, func, &dp, NULL);
1308*c2c66affSColin Finck if(FAILED(hres))
1309*c2c66affSColin Finck return hres;
1310*c2c66affSColin Finck
1311*c2c66affSColin Finck *success = VARIANT_TRUE;
1312*c2c66affSColin Finck return S_OK;
1313*c2c66affSColin Finck }
1314*c2c66affSColin Finck default:
1315*c2c66affSColin Finck assert(0);
1316*c2c66affSColin Finck return E_FAIL;
1317*c2c66affSColin Finck }
1318*c2c66affSColin Finck }
1319*c2c66affSColin Finck
impl_from_IDispatchEx(IDispatchEx * iface)1320*c2c66affSColin Finck static inline DispatchEx *impl_from_IDispatchEx(IDispatchEx *iface)
1321*c2c66affSColin Finck {
1322*c2c66affSColin Finck return CONTAINING_RECORD(iface, DispatchEx, IDispatchEx_iface);
1323*c2c66affSColin Finck }
1324*c2c66affSColin Finck
DispatchEx_QueryInterface(IDispatchEx * iface,REFIID riid,void ** ppv)1325*c2c66affSColin Finck static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv)
1326*c2c66affSColin Finck {
1327*c2c66affSColin Finck DispatchEx *This = impl_from_IDispatchEx(iface);
1328*c2c66affSColin Finck
1329*c2c66affSColin Finck return IUnknown_QueryInterface(This->outer, riid, ppv);
1330*c2c66affSColin Finck }
1331*c2c66affSColin Finck
DispatchEx_AddRef(IDispatchEx * iface)1332*c2c66affSColin Finck static ULONG WINAPI DispatchEx_AddRef(IDispatchEx *iface)
1333*c2c66affSColin Finck {
1334*c2c66affSColin Finck DispatchEx *This = impl_from_IDispatchEx(iface);
1335*c2c66affSColin Finck
1336*c2c66affSColin Finck return IUnknown_AddRef(This->outer);
1337*c2c66affSColin Finck }
1338*c2c66affSColin Finck
DispatchEx_Release(IDispatchEx * iface)1339*c2c66affSColin Finck static ULONG WINAPI DispatchEx_Release(IDispatchEx *iface)
1340*c2c66affSColin Finck {
1341*c2c66affSColin Finck DispatchEx *This = impl_from_IDispatchEx(iface);
1342*c2c66affSColin Finck
1343*c2c66affSColin Finck return IUnknown_Release(This->outer);
1344*c2c66affSColin Finck }
1345*c2c66affSColin Finck
DispatchEx_GetTypeInfoCount(IDispatchEx * iface,UINT * pctinfo)1346*c2c66affSColin Finck static HRESULT WINAPI DispatchEx_GetTypeInfoCount(IDispatchEx *iface, UINT *pctinfo)
1347*c2c66affSColin Finck {
1348*c2c66affSColin Finck DispatchEx *This = impl_from_IDispatchEx(iface);
1349*c2c66affSColin Finck
1350*c2c66affSColin Finck TRACE("(%p)->(%p)\n", This, pctinfo);
1351*c2c66affSColin Finck
1352*c2c66affSColin Finck *pctinfo = 1;
1353*c2c66affSColin Finck return S_OK;
1354*c2c66affSColin Finck }
1355*c2c66affSColin Finck
DispatchEx_GetTypeInfo(IDispatchEx * iface,UINT iTInfo,LCID lcid,ITypeInfo ** ppTInfo)1356*c2c66affSColin Finck static HRESULT WINAPI DispatchEx_GetTypeInfo(IDispatchEx *iface, UINT iTInfo,
1357*c2c66affSColin Finck LCID lcid, ITypeInfo **ppTInfo)
1358*c2c66affSColin Finck {
1359*c2c66affSColin Finck DispatchEx *This = impl_from_IDispatchEx(iface);
1360*c2c66affSColin Finck HRESULT hres;
1361*c2c66affSColin Finck
1362*c2c66affSColin Finck TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
1363*c2c66affSColin Finck
1364*c2c66affSColin Finck hres = get_typeinfo(This->data->disp_tid, ppTInfo);
1365*c2c66affSColin Finck if(FAILED(hres))
1366*c2c66affSColin Finck return hres;
1367*c2c66affSColin Finck
1368*c2c66affSColin Finck ITypeInfo_AddRef(*ppTInfo);
1369*c2c66affSColin Finck return S_OK;
1370*c2c66affSColin Finck }
1371*c2c66affSColin Finck
DispatchEx_GetIDsOfNames(IDispatchEx * iface,REFIID riid,LPOLESTR * rgszNames,UINT cNames,LCID lcid,DISPID * rgDispId)1372*c2c66affSColin Finck static HRESULT WINAPI DispatchEx_GetIDsOfNames(IDispatchEx *iface, REFIID riid,
1373*c2c66affSColin Finck LPOLESTR *rgszNames, UINT cNames,
1374*c2c66affSColin Finck LCID lcid, DISPID *rgDispId)
1375*c2c66affSColin Finck {
1376*c2c66affSColin Finck DispatchEx *This = impl_from_IDispatchEx(iface);
1377*c2c66affSColin Finck UINT i;
1378*c2c66affSColin Finck HRESULT hres;
1379*c2c66affSColin Finck
1380*c2c66affSColin Finck TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1381*c2c66affSColin Finck lcid, rgDispId);
1382*c2c66affSColin Finck
1383*c2c66affSColin Finck for(i=0; i < cNames; i++) {
1384*c2c66affSColin Finck hres = IDispatchEx_GetDispID(&This->IDispatchEx_iface, rgszNames[i], 0, rgDispId+i);
1385*c2c66affSColin Finck if(FAILED(hres))
1386*c2c66affSColin Finck return hres;
1387*c2c66affSColin Finck }
1388*c2c66affSColin Finck
1389*c2c66affSColin Finck return S_OK;
1390*c2c66affSColin Finck }
1391*c2c66affSColin Finck
DispatchEx_Invoke(IDispatchEx * iface,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)1392*c2c66affSColin Finck static HRESULT WINAPI DispatchEx_Invoke(IDispatchEx *iface, DISPID dispIdMember,
1393*c2c66affSColin Finck REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
1394*c2c66affSColin Finck VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1395*c2c66affSColin Finck {
1396*c2c66affSColin Finck DispatchEx *This = impl_from_IDispatchEx(iface);
1397*c2c66affSColin Finck
1398*c2c66affSColin Finck TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1399*c2c66affSColin Finck lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1400*c2c66affSColin Finck
1401*c2c66affSColin Finck return IDispatchEx_InvokeEx(&This->IDispatchEx_iface, dispIdMember, lcid, wFlags, pDispParams,
1402*c2c66affSColin Finck pVarResult, pExcepInfo, NULL);
1403*c2c66affSColin Finck }
1404*c2c66affSColin Finck
DispatchEx_GetDispID(IDispatchEx * iface,BSTR bstrName,DWORD grfdex,DISPID * pid)1405*c2c66affSColin Finck static HRESULT WINAPI DispatchEx_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid)
1406*c2c66affSColin Finck {
1407*c2c66affSColin Finck DispatchEx *This = impl_from_IDispatchEx(iface);
1408*c2c66affSColin Finck dynamic_prop_t *dprop;
1409*c2c66affSColin Finck HRESULT hres;
1410*c2c66affSColin Finck
1411*c2c66affSColin Finck TRACE("(%p)->(%s %x %p)\n", This, debugstr_w(bstrName), grfdex, pid);
1412*c2c66affSColin Finck
1413*c2c66affSColin Finck if(grfdex & ~(fdexNameCaseSensitive|fdexNameCaseInsensitive|fdexNameEnsure|fdexNameImplicit|FDEX_VERSION_MASK))
1414*c2c66affSColin Finck FIXME("Unsupported grfdex %x\n", grfdex);
1415*c2c66affSColin Finck
1416*c2c66affSColin Finck hres = get_builtin_id(This, bstrName, grfdex, pid);
1417*c2c66affSColin Finck if(hres != DISP_E_UNKNOWNNAME)
1418*c2c66affSColin Finck return hres;
1419*c2c66affSColin Finck
1420*c2c66affSColin Finck hres = get_dynamic_prop(This, bstrName, grfdex, &dprop);
1421*c2c66affSColin Finck if(FAILED(hres))
1422*c2c66affSColin Finck return hres;
1423*c2c66affSColin Finck
1424*c2c66affSColin Finck *pid = DISPID_DYNPROP_0 + (dprop - This->dynamic_data->props);
1425*c2c66affSColin Finck return S_OK;
1426*c2c66affSColin Finck }
1427*c2c66affSColin Finck
DispatchEx_InvokeEx(IDispatchEx * iface,DISPID id,LCID lcid,WORD wFlags,DISPPARAMS * pdp,VARIANT * pvarRes,EXCEPINFO * pei,IServiceProvider * pspCaller)1428*c2c66affSColin Finck static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
1429*c2c66affSColin Finck VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
1430*c2c66affSColin Finck {
1431*c2c66affSColin Finck DispatchEx *This = impl_from_IDispatchEx(iface);
1432*c2c66affSColin Finck HRESULT hres;
1433*c2c66affSColin Finck
1434*c2c66affSColin Finck TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller);
1435*c2c66affSColin Finck
1436*c2c66affSColin Finck if(wFlags == (DISPATCH_PROPERTYPUT|DISPATCH_PROPERTYPUTREF))
1437*c2c66affSColin Finck wFlags = DISPATCH_PROPERTYPUT;
1438*c2c66affSColin Finck
1439*c2c66affSColin Finck switch(get_dispid_type(id)) {
1440*c2c66affSColin Finck case DISPEXPROP_CUSTOM:
1441*c2c66affSColin Finck if(!This->data->vtbl || !This->data->vtbl->invoke)
1442*c2c66affSColin Finck return DISP_E_UNKNOWNNAME;
1443*c2c66affSColin Finck return This->data->vtbl->invoke(This, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller);
1444*c2c66affSColin Finck
1445*c2c66affSColin Finck case DISPEXPROP_DYNAMIC: {
1446*c2c66affSColin Finck DWORD idx = id - DISPID_DYNPROP_0;
1447*c2c66affSColin Finck dynamic_prop_t *prop;
1448*c2c66affSColin Finck
1449*c2c66affSColin Finck if(!get_dynamic_data(This) || This->dynamic_data->prop_cnt <= idx)
1450*c2c66affSColin Finck return DISP_E_UNKNOWNNAME;
1451*c2c66affSColin Finck
1452*c2c66affSColin Finck prop = This->dynamic_data->props+idx;
1453*c2c66affSColin Finck
1454*c2c66affSColin Finck switch(wFlags) {
1455*c2c66affSColin Finck case DISPATCH_METHOD|DISPATCH_PROPERTYGET:
1456*c2c66affSColin Finck if(!pvarRes)
1457*c2c66affSColin Finck return E_INVALIDARG;
1458*c2c66affSColin Finck /* fall through */
1459*c2c66affSColin Finck case DISPATCH_METHOD:
1460*c2c66affSColin Finck if(V_VT(&prop->var) != VT_DISPATCH) {
1461*c2c66affSColin Finck FIXME("invoke %s\n", debugstr_variant(&prop->var));
1462*c2c66affSColin Finck return E_NOTIMPL;
1463*c2c66affSColin Finck }
1464*c2c66affSColin Finck
1465*c2c66affSColin Finck return invoke_disp_value(This, V_DISPATCH(&prop->var), lcid, wFlags, pdp, pvarRes, pei, pspCaller);
1466*c2c66affSColin Finck case DISPATCH_PROPERTYGET:
1467*c2c66affSColin Finck if(prop->flags & DYNPROP_DELETED)
1468*c2c66affSColin Finck return DISP_E_UNKNOWNNAME;
1469*c2c66affSColin Finck V_VT(pvarRes) = VT_EMPTY;
1470*c2c66affSColin Finck return variant_copy(pvarRes, &prop->var);
1471*c2c66affSColin Finck case DISPATCH_PROPERTYPUT:
1472*c2c66affSColin Finck if(pdp->cArgs != 1 || (pdp->cNamedArgs == 1 && *pdp->rgdispidNamedArgs != DISPID_PROPERTYPUT)
1473*c2c66affSColin Finck || pdp->cNamedArgs > 1) {
1474*c2c66affSColin Finck FIXME("invalid args\n");
1475*c2c66affSColin Finck return E_INVALIDARG;
1476*c2c66affSColin Finck }
1477*c2c66affSColin Finck
1478*c2c66affSColin Finck TRACE("put %s\n", debugstr_variant(pdp->rgvarg));
1479*c2c66affSColin Finck VariantClear(&prop->var);
1480*c2c66affSColin Finck hres = variant_copy(&prop->var, pdp->rgvarg);
1481*c2c66affSColin Finck if(FAILED(hres))
1482*c2c66affSColin Finck return hres;
1483*c2c66affSColin Finck
1484*c2c66affSColin Finck prop->flags &= ~DYNPROP_DELETED;
1485*c2c66affSColin Finck return S_OK;
1486*c2c66affSColin Finck default:
1487*c2c66affSColin Finck FIXME("unhandled wFlags %x\n", wFlags);
1488*c2c66affSColin Finck return E_NOTIMPL;
1489*c2c66affSColin Finck }
1490*c2c66affSColin Finck }
1491*c2c66affSColin Finck case DISPEXPROP_BUILTIN:
1492*c2c66affSColin Finck if(wFlags == DISPATCH_CONSTRUCT) {
1493*c2c66affSColin Finck if(id == DISPID_VALUE) {
1494*c2c66affSColin Finck if(This->data->vtbl && This->data->vtbl->value) {
1495*c2c66affSColin Finck return This->data->vtbl->value(This, lcid, wFlags, pdp, pvarRes, pei, pspCaller);
1496*c2c66affSColin Finck }
1497*c2c66affSColin Finck FIXME("DISPATCH_CONSTRUCT flag but missing value function\n");
1498*c2c66affSColin Finck return E_FAIL;
1499*c2c66affSColin Finck }
1500*c2c66affSColin Finck FIXME("DISPATCH_CONSTRUCT flag without DISPID_VALUE\n");
1501*c2c66affSColin Finck return E_FAIL;
1502*c2c66affSColin Finck }
1503*c2c66affSColin Finck
1504*c2c66affSColin Finck return invoke_builtin_prop(This, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller);
1505*c2c66affSColin Finck default:
1506*c2c66affSColin Finck assert(0);
1507*c2c66affSColin Finck return E_FAIL;
1508*c2c66affSColin Finck }
1509*c2c66affSColin Finck }
1510*c2c66affSColin Finck
DispatchEx_DeleteMemberByName(IDispatchEx * iface,BSTR bstrName,DWORD grfdex)1511*c2c66affSColin Finck static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex)
1512*c2c66affSColin Finck {
1513*c2c66affSColin Finck DispatchEx *This = impl_from_IDispatchEx(iface);
1514*c2c66affSColin Finck
1515*c2c66affSColin Finck TRACE("(%p)->(%s %x)\n", This, debugstr_w(bstrName), grfdex);
1516*c2c66affSColin Finck
1517*c2c66affSColin Finck /* Not implemented by IE */
1518*c2c66affSColin Finck return E_NOTIMPL;
1519*c2c66affSColin Finck }
1520*c2c66affSColin Finck
DispatchEx_DeleteMemberByDispID(IDispatchEx * iface,DISPID id)1521*c2c66affSColin Finck static HRESULT WINAPI DispatchEx_DeleteMemberByDispID(IDispatchEx *iface, DISPID id)
1522*c2c66affSColin Finck {
1523*c2c66affSColin Finck DispatchEx *This = impl_from_IDispatchEx(iface);
1524*c2c66affSColin Finck
1525*c2c66affSColin Finck TRACE("(%p)->(%x)\n", This, id);
1526*c2c66affSColin Finck
1527*c2c66affSColin Finck /* Not implemented by IE */
1528*c2c66affSColin Finck return E_NOTIMPL;
1529*c2c66affSColin Finck }
1530*c2c66affSColin Finck
DispatchEx_GetMemberProperties(IDispatchEx * iface,DISPID id,DWORD grfdexFetch,DWORD * pgrfdex)1531*c2c66affSColin Finck static HRESULT WINAPI DispatchEx_GetMemberProperties(IDispatchEx *iface, DISPID id, DWORD grfdexFetch, DWORD *pgrfdex)
1532*c2c66affSColin Finck {
1533*c2c66affSColin Finck DispatchEx *This = impl_from_IDispatchEx(iface);
1534*c2c66affSColin Finck FIXME("(%p)->(%x %x %p)\n", This, id, grfdexFetch, pgrfdex);
1535*c2c66affSColin Finck return E_NOTIMPL;
1536*c2c66affSColin Finck }
1537*c2c66affSColin Finck
DispatchEx_GetMemberName(IDispatchEx * iface,DISPID id,BSTR * pbstrName)1538*c2c66affSColin Finck static HRESULT WINAPI DispatchEx_GetMemberName(IDispatchEx *iface, DISPID id, BSTR *pbstrName)
1539*c2c66affSColin Finck {
1540*c2c66affSColin Finck DispatchEx *This = impl_from_IDispatchEx(iface);
1541*c2c66affSColin Finck dispex_data_t *data;
1542*c2c66affSColin Finck func_info_t *func;
1543*c2c66affSColin Finck HRESULT hres;
1544*c2c66affSColin Finck
1545*c2c66affSColin Finck TRACE("(%p)->(%x %p)\n", This, id, pbstrName);
1546*c2c66affSColin Finck
1547*c2c66affSColin Finck if(is_dynamic_dispid(id)) {
1548*c2c66affSColin Finck DWORD idx = id - DISPID_DYNPROP_0;
1549*c2c66affSColin Finck
1550*c2c66affSColin Finck if(!get_dynamic_data(This) || This->dynamic_data->prop_cnt <= idx)
1551*c2c66affSColin Finck return DISP_E_UNKNOWNNAME;
1552*c2c66affSColin Finck
1553*c2c66affSColin Finck *pbstrName = SysAllocString(This->dynamic_data->props[idx].name);
1554*c2c66affSColin Finck if(!*pbstrName)
1555*c2c66affSColin Finck return E_OUTOFMEMORY;
1556*c2c66affSColin Finck
1557*c2c66affSColin Finck return S_OK;
1558*c2c66affSColin Finck }
1559*c2c66affSColin Finck
1560*c2c66affSColin Finck data = get_dispex_data(This);
1561*c2c66affSColin Finck if(!data)
1562*c2c66affSColin Finck return E_FAIL;
1563*c2c66affSColin Finck
1564*c2c66affSColin Finck hres = get_builtin_func(data, id, &func);
1565*c2c66affSColin Finck if(FAILED(hres))
1566*c2c66affSColin Finck return hres;
1567*c2c66affSColin Finck
1568*c2c66affSColin Finck *pbstrName = SysAllocString(func->name);
1569*c2c66affSColin Finck if(!*pbstrName)
1570*c2c66affSColin Finck return E_OUTOFMEMORY;
1571*c2c66affSColin Finck return S_OK;
1572*c2c66affSColin Finck }
1573*c2c66affSColin Finck
DispatchEx_GetNextDispID(IDispatchEx * iface,DWORD grfdex,DISPID id,DISPID * pid)1574*c2c66affSColin Finck static HRESULT WINAPI DispatchEx_GetNextDispID(IDispatchEx *iface, DWORD grfdex, DISPID id, DISPID *pid)
1575*c2c66affSColin Finck {
1576*c2c66affSColin Finck DispatchEx *This = impl_from_IDispatchEx(iface);
1577*c2c66affSColin Finck dispex_data_t *data;
1578*c2c66affSColin Finck func_info_t *func;
1579*c2c66affSColin Finck HRESULT hres;
1580*c2c66affSColin Finck
1581*c2c66affSColin Finck TRACE("(%p)->(%x %x %p)\n", This, grfdex, id, pid);
1582*c2c66affSColin Finck
1583*c2c66affSColin Finck if(is_dynamic_dispid(id)) {
1584*c2c66affSColin Finck DWORD idx = id - DISPID_DYNPROP_0;
1585*c2c66affSColin Finck
1586*c2c66affSColin Finck if(!get_dynamic_data(This) || This->dynamic_data->prop_cnt <= idx)
1587*c2c66affSColin Finck return DISP_E_UNKNOWNNAME;
1588*c2c66affSColin Finck
1589*c2c66affSColin Finck while(++idx < This->dynamic_data->prop_cnt && This->dynamic_data->props[idx].flags & DYNPROP_DELETED);
1590*c2c66affSColin Finck
1591*c2c66affSColin Finck if(idx == This->dynamic_data->prop_cnt) {
1592*c2c66affSColin Finck *pid = DISPID_STARTENUM;
1593*c2c66affSColin Finck return S_FALSE;
1594*c2c66affSColin Finck }
1595*c2c66affSColin Finck
1596*c2c66affSColin Finck *pid = DISPID_DYNPROP_0+idx;
1597*c2c66affSColin Finck return S_OK;
1598*c2c66affSColin Finck }
1599*c2c66affSColin Finck
1600*c2c66affSColin Finck data = get_dispex_data(This);
1601*c2c66affSColin Finck if(!data)
1602*c2c66affSColin Finck return E_FAIL;
1603*c2c66affSColin Finck
1604*c2c66affSColin Finck if(id == DISPID_STARTENUM) {
1605*c2c66affSColin Finck func = data->funcs;
1606*c2c66affSColin Finck }else {
1607*c2c66affSColin Finck hres = get_builtin_func(data, id, &func);
1608*c2c66affSColin Finck if(FAILED(hres))
1609*c2c66affSColin Finck return hres;
1610*c2c66affSColin Finck func++;
1611*c2c66affSColin Finck }
1612*c2c66affSColin Finck
1613*c2c66affSColin Finck while(func < data->funcs+data->func_cnt) {
1614*c2c66affSColin Finck /* FIXME: Skip hidden properties */
1615*c2c66affSColin Finck if(func->func_disp_idx == -1) {
1616*c2c66affSColin Finck *pid = func->id;
1617*c2c66affSColin Finck return S_OK;
1618*c2c66affSColin Finck }
1619*c2c66affSColin Finck func++;
1620*c2c66affSColin Finck }
1621*c2c66affSColin Finck
1622*c2c66affSColin Finck if(get_dynamic_data(This) && This->dynamic_data->prop_cnt) {
1623*c2c66affSColin Finck *pid = DISPID_DYNPROP_0;
1624*c2c66affSColin Finck return S_OK;
1625*c2c66affSColin Finck }
1626*c2c66affSColin Finck
1627*c2c66affSColin Finck *pid = DISPID_STARTENUM;
1628*c2c66affSColin Finck return S_FALSE;
1629*c2c66affSColin Finck }
1630*c2c66affSColin Finck
DispatchEx_GetNameSpaceParent(IDispatchEx * iface,IUnknown ** ppunk)1631*c2c66affSColin Finck static HRESULT WINAPI DispatchEx_GetNameSpaceParent(IDispatchEx *iface, IUnknown **ppunk)
1632*c2c66affSColin Finck {
1633*c2c66affSColin Finck DispatchEx *This = impl_from_IDispatchEx(iface);
1634*c2c66affSColin Finck FIXME("(%p)->(%p)\n", This, ppunk);
1635*c2c66affSColin Finck return E_NOTIMPL;
1636*c2c66affSColin Finck }
1637*c2c66affSColin Finck
1638*c2c66affSColin Finck static IDispatchExVtbl DispatchExVtbl = {
1639*c2c66affSColin Finck DispatchEx_QueryInterface,
1640*c2c66affSColin Finck DispatchEx_AddRef,
1641*c2c66affSColin Finck DispatchEx_Release,
1642*c2c66affSColin Finck DispatchEx_GetTypeInfoCount,
1643*c2c66affSColin Finck DispatchEx_GetTypeInfo,
1644*c2c66affSColin Finck DispatchEx_GetIDsOfNames,
1645*c2c66affSColin Finck DispatchEx_Invoke,
1646*c2c66affSColin Finck DispatchEx_GetDispID,
1647*c2c66affSColin Finck DispatchEx_InvokeEx,
1648*c2c66affSColin Finck DispatchEx_DeleteMemberByName,
1649*c2c66affSColin Finck DispatchEx_DeleteMemberByDispID,
1650*c2c66affSColin Finck DispatchEx_GetMemberProperties,
1651*c2c66affSColin Finck DispatchEx_GetMemberName,
1652*c2c66affSColin Finck DispatchEx_GetNextDispID,
1653*c2c66affSColin Finck DispatchEx_GetNameSpaceParent
1654*c2c66affSColin Finck };
1655*c2c66affSColin Finck
dispex_query_interface(DispatchEx * This,REFIID riid,void ** ppv)1656*c2c66affSColin Finck BOOL dispex_query_interface(DispatchEx *This, REFIID riid, void **ppv)
1657*c2c66affSColin Finck {
1658*c2c66affSColin Finck if(IsEqualGUID(&IID_IDispatch, riid))
1659*c2c66affSColin Finck *ppv = &This->IDispatchEx_iface;
1660*c2c66affSColin Finck else if(IsEqualGUID(&IID_IDispatchEx, riid))
1661*c2c66affSColin Finck *ppv = &This->IDispatchEx_iface;
1662*c2c66affSColin Finck else if(IsEqualGUID(&IID_IDispatchJS, riid))
1663*c2c66affSColin Finck *ppv = NULL;
1664*c2c66affSColin Finck else if(IsEqualGUID(&IID_UndocumentedScriptIface, riid))
1665*c2c66affSColin Finck *ppv = NULL;
1666*c2c66affSColin Finck else
1667*c2c66affSColin Finck return FALSE;
1668*c2c66affSColin Finck
1669*c2c66affSColin Finck if(*ppv)
1670*c2c66affSColin Finck IUnknown_AddRef((IUnknown*)*ppv);
1671*c2c66affSColin Finck return TRUE;
1672*c2c66affSColin Finck }
1673*c2c66affSColin Finck
dispex_traverse(DispatchEx * This,nsCycleCollectionTraversalCallback * cb)1674*c2c66affSColin Finck void dispex_traverse(DispatchEx *This, nsCycleCollectionTraversalCallback *cb)
1675*c2c66affSColin Finck {
1676*c2c66affSColin Finck dynamic_prop_t *prop;
1677*c2c66affSColin Finck
1678*c2c66affSColin Finck if(!This->dynamic_data)
1679*c2c66affSColin Finck return;
1680*c2c66affSColin Finck
1681*c2c66affSColin Finck for(prop = This->dynamic_data->props; prop < This->dynamic_data->props + This->dynamic_data->prop_cnt; prop++) {
1682*c2c66affSColin Finck if(V_VT(&prop->var) == VT_DISPATCH)
1683*c2c66affSColin Finck note_cc_edge((nsISupports*)V_DISPATCH(&prop->var), "dispex_data", cb);
1684*c2c66affSColin Finck }
1685*c2c66affSColin Finck
1686*c2c66affSColin Finck /* FIXME: Traverse func_disps */
1687*c2c66affSColin Finck }
1688*c2c66affSColin Finck
dispex_unlink(DispatchEx * This)1689*c2c66affSColin Finck void dispex_unlink(DispatchEx *This)
1690*c2c66affSColin Finck {
1691*c2c66affSColin Finck dynamic_prop_t *prop;
1692*c2c66affSColin Finck
1693*c2c66affSColin Finck if(!This->dynamic_data)
1694*c2c66affSColin Finck return;
1695*c2c66affSColin Finck
1696*c2c66affSColin Finck for(prop = This->dynamic_data->props; prop < This->dynamic_data->props + This->dynamic_data->prop_cnt; prop++) {
1697*c2c66affSColin Finck if(V_VT(&prop->var) == VT_DISPATCH) {
1698*c2c66affSColin Finck V_VT(&prop->var) = VT_EMPTY;
1699*c2c66affSColin Finck IDispatch_Release(V_DISPATCH(&prop->var));
1700*c2c66affSColin Finck }else {
1701*c2c66affSColin Finck VariantClear(&prop->var);
1702*c2c66affSColin Finck }
1703*c2c66affSColin Finck }
1704*c2c66affSColin Finck }
1705*c2c66affSColin Finck
release_dispex(DispatchEx * This)1706*c2c66affSColin Finck void release_dispex(DispatchEx *This)
1707*c2c66affSColin Finck {
1708*c2c66affSColin Finck dynamic_prop_t *prop;
1709*c2c66affSColin Finck
1710*c2c66affSColin Finck if(!This->dynamic_data)
1711*c2c66affSColin Finck return;
1712*c2c66affSColin Finck
1713*c2c66affSColin Finck for(prop = This->dynamic_data->props; prop < This->dynamic_data->props + This->dynamic_data->prop_cnt; prop++) {
1714*c2c66affSColin Finck VariantClear(&prop->var);
1715*c2c66affSColin Finck heap_free(prop->name);
1716*c2c66affSColin Finck }
1717*c2c66affSColin Finck
1718*c2c66affSColin Finck heap_free(This->dynamic_data->props);
1719*c2c66affSColin Finck
1720*c2c66affSColin Finck if(This->dynamic_data->func_disps) {
1721*c2c66affSColin Finck func_obj_entry_t *iter;
1722*c2c66affSColin Finck
1723*c2c66affSColin Finck for(iter = This->dynamic_data->func_disps; iter < This->dynamic_data->func_disps+This->data->data->func_disp_cnt; iter++) {
1724*c2c66affSColin Finck if(iter->func_obj) {
1725*c2c66affSColin Finck iter->func_obj->obj = NULL;
1726*c2c66affSColin Finck IDispatchEx_Release(&iter->func_obj->dispex.IDispatchEx_iface);
1727*c2c66affSColin Finck }
1728*c2c66affSColin Finck VariantClear(&iter->val);
1729*c2c66affSColin Finck }
1730*c2c66affSColin Finck
1731*c2c66affSColin Finck heap_free(This->dynamic_data->func_disps);
1732*c2c66affSColin Finck }
1733*c2c66affSColin Finck
1734*c2c66affSColin Finck heap_free(This->dynamic_data);
1735*c2c66affSColin Finck }
1736*c2c66affSColin Finck
init_dispex(DispatchEx * dispex,IUnknown * outer,dispex_static_data_t * data)1737*c2c66affSColin Finck void init_dispex(DispatchEx *dispex, IUnknown *outer, dispex_static_data_t *data)
1738*c2c66affSColin Finck {
1739*c2c66affSColin Finck dispex->IDispatchEx_iface.lpVtbl = &DispatchExVtbl;
1740*c2c66affSColin Finck dispex->outer = outer;
1741*c2c66affSColin Finck dispex->data = data;
1742*c2c66affSColin Finck dispex->dynamic_data = NULL;
1743*c2c66affSColin Finck }
1744