2 * Copyright 2008 Jacek Caban for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "wine/unicode.h"
22 #include "wine/debug.h"
24 WINE_DEFAULT_DEBUG_CHANNEL(jscript
);
33 struct _dispex_prop_t
{
40 const builtin_prop_t
*p
;
45 static inline DISPID
prop_to_id(DispatchEx
*This
, dispex_prop_t
*prop
)
47 return prop
- This
->props
;
50 static const builtin_prop_t
*find_builtin_prop(DispatchEx
*This
, const WCHAR
*name
)
52 int min
= 0, max
, i
, r
;
54 max
= This
->builtin_info
->props_cnt
-1;
58 r
= strcmpW(name
, This
->builtin_info
->props
[i
].name
);
60 return This
->builtin_info
->props
+ i
;
71 static dispex_prop_t
*alloc_prop(DispatchEx
*This
, const WCHAR
*name
, prop_type_t type
, DWORD flags
)
75 if(This
->buf_size
== This
->prop_cnt
) {
76 dispex_prop_t
*tmp
= heap_realloc(This
->props
, (This
->buf_size
<<=1)*sizeof(*This
->props
));
82 ret
= This
->props
+ This
->prop_cnt
++;
85 ret
->name
= heap_strdupW(name
);
92 static dispex_prop_t
*alloc_protref(DispatchEx
*This
, const WCHAR
*name
, DWORD ref
)
96 ret
= alloc_prop(This
, name
, PROP_PROTREF
, 0);
104 static HRESULT
find_prop_name(DispatchEx
*This
, const WCHAR
*name
, dispex_prop_t
**ret
)
106 const builtin_prop_t
*builtin
;
109 for(prop
= This
->props
; prop
< This
->props
+This
->prop_cnt
; prop
++) {
110 if(prop
->name
&& !strcmpW(prop
->name
, name
)) {
116 builtin
= find_builtin_prop(This
, name
);
118 prop
= alloc_prop(This
, name
, PROP_BUILTIN
, builtin
->flags
);
120 return E_OUTOFMEMORY
;
131 static HRESULT
find_prop_name_prot(DispatchEx
*This
, const WCHAR
*name
, BOOL alloc
, dispex_prop_t
**ret
)
136 hres
= find_prop_name(This
, name
, &prop
);
144 if(This
->prototype
) {
145 hres
= find_prop_name_prot(This
->prototype
, name
, FALSE
, &prop
);
149 prop
= alloc_protref(This
, prop
->name
, prop
- This
->prototype
->props
);
151 return E_OUTOFMEMORY
;
158 TRACE("creating prop %s\n", debugstr_w(name
));
160 prop
= alloc_prop(This
, name
, PROP_VARIANT
, PROPF_ENUM
);
162 return E_OUTOFMEMORY
;
163 VariantInit(&prop
->u
.var
);
170 #define DISPATCHEX_THIS(iface) DEFINE_THIS(DispatchEx, IDispatchEx, iface)
172 static HRESULT WINAPI
DispatchEx_QueryInterface(IDispatchEx
*iface
, REFIID riid
, void **ppv
)
174 DispatchEx
*This
= DISPATCHEX_THIS(iface
);
176 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
177 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
178 *ppv
= _IDispatchEx_(This
);
179 }else if(IsEqualGUID(&IID_IDispatch
, riid
)) {
180 TRACE("(%p)->(IID_IDispatch %p)\n", This
, ppv
);
181 *ppv
= _IDispatchEx_(This
);
182 }else if(IsEqualGUID(&IID_IDispatchEx
, riid
)) {
183 TRACE("(%p)->(IID_IDispatchEx %p)\n", This
, ppv
);
184 *ppv
= _IDispatchEx_(This
);
186 WARN("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
188 return E_NOINTERFACE
;
191 IUnknown_AddRef((IUnknown
*)*ppv
);
195 static ULONG WINAPI
DispatchEx_AddRef(IDispatchEx
*iface
)
197 DispatchEx
*This
= DISPATCHEX_THIS(iface
);
198 LONG ref
= InterlockedIncrement(&This
->ref
);
200 TRACE("(%p) ref=%d\n", This
, ref
);
205 static ULONG WINAPI
DispatchEx_Release(IDispatchEx
*iface
)
207 DispatchEx
*This
= DISPATCHEX_THIS(iface
);
208 LONG ref
= InterlockedDecrement(&This
->ref
);
210 TRACE("(%p) ref=%d\n", This
, ref
);
215 for(prop
= This
->props
; prop
< This
->props
+This
->prop_cnt
; prop
++) {
216 if(prop
->type
== PROP_VARIANT
)
217 VariantClear(&prop
->u
.var
);
218 heap_free(prop
->name
);
220 heap_free(This
->props
);
221 script_release(This
->ctx
);
223 if(This
->builtin_info
->destructor
)
224 This
->builtin_info
->destructor(This
);
232 static HRESULT WINAPI
DispatchEx_GetTypeInfoCount(IDispatchEx
*iface
, UINT
*pctinfo
)
234 DispatchEx
*This
= DISPATCHEX_THIS(iface
);
236 TRACE("(%p)->(%p)\n", This
, pctinfo
);
242 static HRESULT WINAPI
DispatchEx_GetTypeInfo(IDispatchEx
*iface
, UINT iTInfo
,
243 LCID lcid
, ITypeInfo
**ppTInfo
)
245 DispatchEx
*This
= DISPATCHEX_THIS(iface
);
246 FIXME("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
250 static HRESULT WINAPI
DispatchEx_GetIDsOfNames(IDispatchEx
*iface
, REFIID riid
,
251 LPOLESTR
*rgszNames
, UINT cNames
,
252 LCID lcid
, DISPID
*rgDispId
)
254 DispatchEx
*This
= DISPATCHEX_THIS(iface
);
258 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
,
261 for(i
=0; i
< cNames
; i
++) {
262 hres
= IDispatchEx_GetDispID(_IDispatchEx_(This
), rgszNames
[i
], 0, rgDispId
+i
);
270 static HRESULT WINAPI
DispatchEx_Invoke(IDispatchEx
*iface
, DISPID dispIdMember
,
271 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
,
272 VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
274 DispatchEx
*This
= DISPATCHEX_THIS(iface
);
276 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
277 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
279 return IDispatchEx_InvokeEx(_IDispatchEx_(This
), dispIdMember
, lcid
, wFlags
,
280 pDispParams
, pVarResult
, pExcepInfo
, NULL
);
283 static HRESULT WINAPI
DispatchEx_GetDispID(IDispatchEx
*iface
, BSTR bstrName
, DWORD grfdex
, DISPID
*pid
)
285 DispatchEx
*This
= DISPATCHEX_THIS(iface
);
289 TRACE("(%p)->(%s %x %p)\n", This
, debugstr_w(bstrName
), grfdex
, pid
);
291 if(grfdex
& ~(fdexNameCaseSensitive
|fdexNameEnsure
|fdexNameImplicit
)) {
292 FIXME("Unsupported grfdex %x\n", grfdex
);
296 hres
= find_prop_name_prot(This
, bstrName
, (grfdex
&fdexNameEnsure
) != 0, &prop
);
300 *pid
= prop_to_id(This
, prop
);
304 TRACE("not found %s\n", debugstr_w(bstrName
));
305 return DISP_E_UNKNOWNNAME
;
308 static HRESULT WINAPI
DispatchEx_InvokeEx(IDispatchEx
*iface
, DISPID id
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pdp
,
309 VARIANT
*pvarRes
, EXCEPINFO
*pei
, IServiceProvider
*pspCaller
)
311 DispatchEx
*This
= DISPATCHEX_THIS(iface
);
312 FIXME("(%p)->(%x %x %x %p %p %p %p)\n", This
, id
, lcid
, wFlags
, pdp
, pvarRes
, pei
, pspCaller
);
316 static HRESULT WINAPI
DispatchEx_DeleteMemberByName(IDispatchEx
*iface
, BSTR bstrName
, DWORD grfdex
)
318 DispatchEx
*This
= DISPATCHEX_THIS(iface
);
319 FIXME("(%p)->(%s %x)\n", This
, debugstr_w(bstrName
), grfdex
);
323 static HRESULT WINAPI
DispatchEx_DeleteMemberByDispID(IDispatchEx
*iface
, DISPID id
)
325 DispatchEx
*This
= DISPATCHEX_THIS(iface
);
326 FIXME("(%p)->(%x)\n", This
, id
);
330 static HRESULT WINAPI
DispatchEx_GetMemberProperties(IDispatchEx
*iface
, DISPID id
, DWORD grfdexFetch
, DWORD
*pgrfdex
)
332 DispatchEx
*This
= DISPATCHEX_THIS(iface
);
333 FIXME("(%p)->(%x %x %p)\n", This
, id
, grfdexFetch
, pgrfdex
);
337 static HRESULT WINAPI
DispatchEx_GetMemberName(IDispatchEx
*iface
, DISPID id
, BSTR
*pbstrName
)
339 DispatchEx
*This
= DISPATCHEX_THIS(iface
);
340 FIXME("(%p)->(%x %p)\n", This
, id
, pbstrName
);
344 static HRESULT WINAPI
DispatchEx_GetNextDispID(IDispatchEx
*iface
, DWORD grfdex
, DISPID id
, DISPID
*pid
)
346 DispatchEx
*This
= DISPATCHEX_THIS(iface
);
347 FIXME("(%p)->(%x %x %p)\n", This
, grfdex
, id
, pid
);
351 static HRESULT WINAPI
DispatchEx_GetNameSpaceParent(IDispatchEx
*iface
, IUnknown
**ppunk
)
353 DispatchEx
*This
= DISPATCHEX_THIS(iface
);
354 FIXME("(%p)->(%p)\n", This
, ppunk
);
358 #undef DISPATCHEX_THIS
360 static IDispatchExVtbl DispatchExVtbl
= {
361 DispatchEx_QueryInterface
,
364 DispatchEx_GetTypeInfoCount
,
365 DispatchEx_GetTypeInfo
,
366 DispatchEx_GetIDsOfNames
,
368 DispatchEx_GetDispID
,
370 DispatchEx_DeleteMemberByName
,
371 DispatchEx_DeleteMemberByDispID
,
372 DispatchEx_GetMemberProperties
,
373 DispatchEx_GetMemberName
,
374 DispatchEx_GetNextDispID
,
375 DispatchEx_GetNameSpaceParent
378 static HRESULT
jsdisp_set_prot_prop(DispatchEx
*dispex
, DispatchEx
*prototype
)
382 if(!dispex
->props
[1].name
)
383 return E_OUTOFMEMORY
;
385 dispex
->props
[1].type
= PROP_VARIANT
;
386 dispex
->props
[1].flags
= 0;
388 var
= &dispex
->props
[1].u
.var
;
389 V_VT(var
) = VT_DISPATCH
;
390 V_DISPATCH(var
) = (IDispatch
*)_IDispatchEx_(prototype
);
395 static HRESULT
init_dispex(DispatchEx
*dispex
, script_ctx_t
*ctx
, const builtin_info_t
*builtin_info
, DispatchEx
*prototype
)
397 static const WCHAR prototypeW
[] = {'p','r','o','t','o','t','y','p','e',0};
399 TRACE("%p (%p)\n", dispex
, prototype
);
401 dispex
->lpIDispatchExVtbl
= &DispatchExVtbl
;
403 dispex
->builtin_info
= builtin_info
;
405 dispex
->props
= heap_alloc((dispex
->buf_size
=4) * sizeof(dispex_prop_t
));
407 return E_OUTOFMEMORY
;
409 dispex
->prototype
= prototype
;
411 IDispatchEx_AddRef(_IDispatchEx_(prototype
));
413 dispex
->prop_cnt
= 2;
414 dispex
->props
[0].name
= NULL
;
415 dispex
->props
[0].flags
= 0;
416 if(builtin_info
->value_prop
.invoke
) {
417 dispex
->props
[0].type
= PROP_BUILTIN
;
418 dispex
->props
[0].u
.p
= &builtin_info
->value_prop
;
420 dispex
->props
[0].type
= PROP_DELETED
;
423 dispex
->props
[1].type
= PROP_DELETED
;
424 dispex
->props
[1].name
= SysAllocString(prototypeW
);
425 dispex
->props
[1].flags
= 0;
430 hres
= jsdisp_set_prot_prop(dispex
, prototype
);
432 IDispatchEx_Release(_IDispatchEx_(dispex
));
443 static const builtin_info_t dispex_info
= {
451 HRESULT
create_dispex(script_ctx_t
*ctx
, const builtin_info_t
*builtin_info
, DispatchEx
*prototype
, DispatchEx
**dispex
)
456 ret
= heap_alloc_zero(sizeof(DispatchEx
));
458 return E_OUTOFMEMORY
;
460 hres
= init_dispex(ret
, ctx
, builtin_info
? builtin_info
: &dispex_info
, prototype
);