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
);
27 * This IID is used to get DispatchEx objecto from interface.
28 * We might consider using private insteface instead.
30 static const IID IID_IDispatchJS
=
31 {0x719c3050,0xf9d3,0x11cf,{0xa4,0x93,0x00,0x40,0x05,0x23,0xa8,0xa6}};
40 struct _dispex_prop_t
{
47 const builtin_prop_t
*p
;
52 static inline DISPID
prop_to_id(DispatchEx
*This
, dispex_prop_t
*prop
)
54 return prop
- This
->props
;
57 static inline dispex_prop_t
*get_prop(DispatchEx
*This
, DISPID id
)
59 if(id
< 0 || id
>= This
->prop_cnt
|| This
->props
[id
].type
== PROP_DELETED
)
62 return This
->props
+id
;
65 static DWORD
get_flags(DispatchEx
*This
, dispex_prop_t
*prop
)
67 if(prop
->type
== PROP_PROTREF
) {
68 dispex_prop_t
*parent
= get_prop(This
->prototype
, prop
->u
.ref
);
70 prop
->type
= PROP_DELETED
;
74 return get_flags(This
->prototype
, parent
);
80 static const builtin_prop_t
*find_builtin_prop(DispatchEx
*This
, const WCHAR
*name
)
82 int min
= 0, max
, i
, r
;
84 max
= This
->builtin_info
->props_cnt
-1;
88 r
= strcmpW(name
, This
->builtin_info
->props
[i
].name
);
90 return This
->builtin_info
->props
+ i
;
101 static dispex_prop_t
*alloc_prop(DispatchEx
*This
, const WCHAR
*name
, prop_type_t type
, DWORD flags
)
105 if(This
->buf_size
== This
->prop_cnt
) {
106 dispex_prop_t
*tmp
= heap_realloc(This
->props
, (This
->buf_size
<<=1)*sizeof(*This
->props
));
112 ret
= This
->props
+ This
->prop_cnt
++;
115 ret
->name
= heap_strdupW(name
);
122 static dispex_prop_t
*alloc_protref(DispatchEx
*This
, const WCHAR
*name
, DWORD ref
)
126 ret
= alloc_prop(This
, name
, PROP_PROTREF
, 0);
134 static HRESULT
find_prop_name(DispatchEx
*This
, const WCHAR
*name
, dispex_prop_t
**ret
)
136 const builtin_prop_t
*builtin
;
139 for(prop
= This
->props
; prop
< This
->props
+This
->prop_cnt
; prop
++) {
140 if(prop
->name
&& !strcmpW(prop
->name
, name
)) {
146 builtin
= find_builtin_prop(This
, name
);
148 prop
= alloc_prop(This
, name
, PROP_BUILTIN
, builtin
->flags
);
150 return E_OUTOFMEMORY
;
161 static HRESULT
find_prop_name_prot(DispatchEx
*This
, const WCHAR
*name
, BOOL alloc
, dispex_prop_t
**ret
)
166 hres
= find_prop_name(This
, name
, &prop
);
174 if(This
->prototype
) {
175 hres
= find_prop_name_prot(This
->prototype
, name
, FALSE
, &prop
);
179 prop
= alloc_protref(This
, prop
->name
, prop
- This
->prototype
->props
);
181 return E_OUTOFMEMORY
;
188 TRACE("creating prop %s\n", debugstr_w(name
));
190 prop
= alloc_prop(This
, name
, PROP_VARIANT
, PROPF_ENUM
);
192 return E_OUTOFMEMORY
;
193 VariantInit(&prop
->u
.var
);
200 static HRESULT
set_this(DISPPARAMS
*dp
, DISPPARAMS
*olddp
, IDispatch
*jsthis
)
205 static DISPID this_id
= DISPID_THIS
;
209 for(i
= 0; i
< dp
->cNamedArgs
; i
++) {
210 if(dp
->rgdispidNamedArgs
[i
] == DISPID_THIS
)
214 oldargs
= dp
->rgvarg
;
215 dp
->rgvarg
= heap_alloc((dp
->cArgs
+1) * sizeof(VARIANTARG
));
217 return E_OUTOFMEMORY
;
218 memcpy(dp
->rgvarg
+1, oldargs
, dp
->cArgs
*sizeof(VARIANTARG
));
219 V_VT(dp
->rgvarg
) = VT_DISPATCH
;
220 V_DISPATCH(dp
->rgvarg
) = jsthis
;
224 DISPID
*old
= dp
->rgdispidNamedArgs
;
225 dp
->rgdispidNamedArgs
= heap_alloc((dp
->cNamedArgs
+1)*sizeof(DISPID
));
226 if(!dp
->rgdispidNamedArgs
) {
227 heap_free(dp
->rgvarg
);
228 return E_OUTOFMEMORY
;
231 memcpy(dp
->rgdispidNamedArgs
+1, old
, dp
->cNamedArgs
*sizeof(DISPID
));
232 dp
->rgdispidNamedArgs
[0] = DISPID_THIS
;
235 dp
->rgdispidNamedArgs
= &this_id
;
242 static HRESULT
invoke_prop_func(DispatchEx
*This
, DispatchEx
*jsthis
, dispex_prop_t
*prop
, LCID lcid
, WORD flags
,
243 DISPPARAMS
*dp
, VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
249 if(flags
== DISPATCH_CONSTRUCT
&& (prop
->flags
& DISPATCH_METHOD
)) {
250 WARN("%s is not a constructor\n", debugstr_w(prop
->name
));
253 return prop
->u
.p
->invoke(jsthis
, lcid
, flags
, dp
, retv
, ei
, caller
);
255 return invoke_prop_func(This
->prototype
, jsthis
, This
->prototype
->props
+prop
->u
.ref
, lcid
, flags
, dp
, retv
, ei
, caller
);
259 if(V_VT(&prop
->u
.var
) != VT_DISPATCH
) {
260 FIXME("invoke vt %d\n", V_VT(&prop
->u
.var
));
264 TRACE("call %s %p\n", debugstr_w(prop
->name
), V_DISPATCH(&prop
->u
.var
));
266 hres
= set_this(&new_dp
, dp
, (IDispatch
*)_IDispatchEx_(jsthis
));
270 hres
= disp_call(V_DISPATCH(&prop
->u
.var
), DISPID_VALUE
, lcid
, flags
, &new_dp
, retv
, ei
, caller
);
272 if(new_dp
.rgvarg
!= dp
->rgvarg
) {
273 heap_free(new_dp
.rgvarg
);
274 if(new_dp
.cNamedArgs
> 1)
275 heap_free(new_dp
.rgdispidNamedArgs
);
281 ERR("type %d\n", prop
->type
);
287 static HRESULT
prop_get(DispatchEx
*This
, dispex_prop_t
*prop
, LCID lcid
, DISPPARAMS
*dp
,
288 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
294 if(prop
->u
.p
->flags
& PROPF_METHOD
) {
295 FIXME("function objects not supported\n");
298 hres
= prop
->u
.p
->invoke(This
, lcid
, DISPATCH_PROPERTYGET
, dp
, retv
, ei
, caller
);
302 hres
= prop_get(This
->prototype
, This
->prototype
->props
+prop
->u
.ref
, lcid
, dp
, retv
, ei
, caller
);
305 hres
= VariantCopy(retv
, &prop
->u
.var
);
308 ERR("type %d\n", prop
->type
);
313 TRACE("fail %08x\n", hres
);
317 TRACE("%s ret %s\n", debugstr_w(prop
->name
), debugstr_variant(retv
));
321 static HRESULT
prop_put(DispatchEx
*This
, dispex_prop_t
*prop
, LCID lcid
, DISPPARAMS
*dp
,
322 jsexcept_t
*ei
, IServiceProvider
*caller
)
329 if(!(prop
->flags
& PROPF_METHOD
))
330 return prop
->u
.p
->invoke(This
, lcid
, DISPATCH_PROPERTYPUT
, dp
, NULL
, ei
, caller
);
332 prop
->type
= PROP_VARIANT
;
333 prop
->flags
= PROPF_ENUM
;
334 V_VT(&prop
->u
.var
) = VT_EMPTY
;
337 VariantClear(&prop
->u
.var
);
340 ERR("type %d\n", prop
->type
);
344 for(i
=0; i
< dp
->cNamedArgs
; i
++) {
345 if(dp
->rgdispidNamedArgs
[i
] == DISPID_PROPERTYPUT
)
349 if(i
== dp
->cNamedArgs
) {
350 TRACE("no value to set\n");
351 return DISP_E_PARAMNOTOPTIONAL
;
354 hres
= VariantCopy(&prop
->u
.var
, dp
->rgvarg
+i
);
358 if(This
->builtin_info
->on_put
)
359 This
->builtin_info
->on_put(This
, prop
->name
);
361 TRACE("%s = %s\n", debugstr_w(prop
->name
), debugstr_variant(dp
->rgvarg
+i
));
365 static HRESULT
fill_protrefs(DispatchEx
*This
)
367 dispex_prop_t
*iter
, *prop
;
373 fill_protrefs(This
->prototype
);
375 for(iter
= This
->prototype
->props
; iter
< This
->prototype
->props
+This
->prototype
->prop_cnt
; iter
++) {
376 hres
= find_prop_name(This
, iter
->name
, &prop
);
380 prop
= alloc_protref(This
, iter
->name
, iter
- This
->prototype
->props
);
382 return E_OUTOFMEMORY
;
389 #define DISPATCHEX_THIS(iface) DEFINE_THIS(DispatchEx, IDispatchEx, iface)
391 static HRESULT WINAPI
DispatchEx_QueryInterface(IDispatchEx
*iface
, REFIID riid
, void **ppv
)
393 DispatchEx
*This
= DISPATCHEX_THIS(iface
);
395 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
396 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
397 *ppv
= _IDispatchEx_(This
);
398 }else if(IsEqualGUID(&IID_IDispatch
, riid
)) {
399 TRACE("(%p)->(IID_IDispatch %p)\n", This
, ppv
);
400 *ppv
= _IDispatchEx_(This
);
401 }else if(IsEqualGUID(&IID_IDispatchEx
, riid
)) {
402 TRACE("(%p)->(IID_IDispatchEx %p)\n", This
, ppv
);
403 *ppv
= _IDispatchEx_(This
);
404 }else if(IsEqualGUID(&IID_IDispatchJS
, riid
)) {
405 TRACE("(%p)->(IID_IDispatchJS %p)\n", This
, ppv
);
406 IUnknown_AddRef(_IDispatchEx_(This
));
410 WARN("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
412 return E_NOINTERFACE
;
415 IUnknown_AddRef((IUnknown
*)*ppv
);
419 static ULONG WINAPI
DispatchEx_AddRef(IDispatchEx
*iface
)
421 DispatchEx
*This
= DISPATCHEX_THIS(iface
);
422 LONG ref
= InterlockedIncrement(&This
->ref
);
424 TRACE("(%p) ref=%d\n", This
, ref
);
429 static ULONG WINAPI
DispatchEx_Release(IDispatchEx
*iface
)
431 DispatchEx
*This
= DISPATCHEX_THIS(iface
);
432 LONG ref
= InterlockedDecrement(&This
->ref
);
434 TRACE("(%p) ref=%d\n", This
, ref
);
439 for(prop
= This
->props
; prop
< This
->props
+This
->prop_cnt
; prop
++) {
440 if(prop
->type
== PROP_VARIANT
)
441 VariantClear(&prop
->u
.var
);
442 heap_free(prop
->name
);
444 heap_free(This
->props
);
445 script_release(This
->ctx
);
447 if(This
->builtin_info
->destructor
)
448 This
->builtin_info
->destructor(This
);
456 static HRESULT WINAPI
DispatchEx_GetTypeInfoCount(IDispatchEx
*iface
, UINT
*pctinfo
)
458 DispatchEx
*This
= DISPATCHEX_THIS(iface
);
460 TRACE("(%p)->(%p)\n", This
, pctinfo
);
466 static HRESULT WINAPI
DispatchEx_GetTypeInfo(IDispatchEx
*iface
, UINT iTInfo
,
467 LCID lcid
, ITypeInfo
**ppTInfo
)
469 DispatchEx
*This
= DISPATCHEX_THIS(iface
);
470 FIXME("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
474 static HRESULT WINAPI
DispatchEx_GetIDsOfNames(IDispatchEx
*iface
, REFIID riid
,
475 LPOLESTR
*rgszNames
, UINT cNames
,
476 LCID lcid
, DISPID
*rgDispId
)
478 DispatchEx
*This
= DISPATCHEX_THIS(iface
);
482 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
,
485 for(i
=0; i
< cNames
; i
++) {
486 hres
= IDispatchEx_GetDispID(_IDispatchEx_(This
), rgszNames
[i
], 0, rgDispId
+i
);
494 static HRESULT WINAPI
DispatchEx_Invoke(IDispatchEx
*iface
, DISPID dispIdMember
,
495 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
,
496 VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
498 DispatchEx
*This
= DISPATCHEX_THIS(iface
);
500 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
501 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
503 return IDispatchEx_InvokeEx(_IDispatchEx_(This
), dispIdMember
, lcid
, wFlags
,
504 pDispParams
, pVarResult
, pExcepInfo
, NULL
);
507 static HRESULT WINAPI
DispatchEx_GetDispID(IDispatchEx
*iface
, BSTR bstrName
, DWORD grfdex
, DISPID
*pid
)
509 DispatchEx
*This
= DISPATCHEX_THIS(iface
);
513 TRACE("(%p)->(%s %x %p)\n", This
, debugstr_w(bstrName
), grfdex
, pid
);
515 if(grfdex
& ~(fdexNameCaseSensitive
|fdexNameEnsure
|fdexNameImplicit
)) {
516 FIXME("Unsupported grfdex %x\n", grfdex
);
520 hres
= find_prop_name_prot(This
, bstrName
, (grfdex
&fdexNameEnsure
) != 0, &prop
);
524 *pid
= prop_to_id(This
, prop
);
528 TRACE("not found %s\n", debugstr_w(bstrName
));
529 return DISP_E_UNKNOWNNAME
;
532 static HRESULT WINAPI
DispatchEx_InvokeEx(IDispatchEx
*iface
, DISPID id
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pdp
,
533 VARIANT
*pvarRes
, EXCEPINFO
*pei
, IServiceProvider
*pspCaller
)
535 DispatchEx
*This
= DISPATCHEX_THIS(iface
);
540 TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This
, id
, lcid
, wFlags
, pdp
, pvarRes
, pei
, pspCaller
);
543 V_VT(pvarRes
) = VT_EMPTY
;
545 prop
= get_prop(This
, id
);
546 if(!prop
|| prop
->type
== PROP_DELETED
) {
547 TRACE("invalid id\n");
548 return DISP_E_MEMBERNOTFOUND
;
551 memset(&jsexcept
, 0, sizeof(jsexcept
));
554 case DISPATCH_METHOD
:
555 case DISPATCH_CONSTRUCT
:
556 hres
= invoke_prop_func(This
, This
, prop
, lcid
, wFlags
, pdp
, pvarRes
, &jsexcept
, pspCaller
);
558 case DISPATCH_PROPERTYGET
:
559 hres
= prop_get(This
, prop
, lcid
, pdp
, pvarRes
, &jsexcept
, pspCaller
);
561 case DISPATCH_PROPERTYPUT
:
562 hres
= prop_put(This
, prop
, lcid
, pdp
, &jsexcept
, pspCaller
);
565 FIXME("Unimplemented flags %x\n", wFlags
);
575 static HRESULT WINAPI
DispatchEx_DeleteMemberByName(IDispatchEx
*iface
, BSTR bstrName
, DWORD grfdex
)
577 DispatchEx
*This
= DISPATCHEX_THIS(iface
);
581 TRACE("(%p)->(%s %x)\n", This
, debugstr_w(bstrName
), grfdex
);
583 if(grfdex
& ~(fdexNameCaseSensitive
|fdexNameEnsure
|fdexNameImplicit
))
584 FIXME("Unsupported grfdex %x\n", grfdex
);
586 hres
= find_prop_name(This
, bstrName
, &prop
);
590 TRACE("not found\n");
594 heap_free(prop
->name
);
596 prop
->type
= PROP_DELETED
;
600 static HRESULT WINAPI
DispatchEx_DeleteMemberByDispID(IDispatchEx
*iface
, DISPID id
)
602 DispatchEx
*This
= DISPATCHEX_THIS(iface
);
603 FIXME("(%p)->(%x)\n", This
, id
);
607 static HRESULT WINAPI
DispatchEx_GetMemberProperties(IDispatchEx
*iface
, DISPID id
, DWORD grfdexFetch
, DWORD
*pgrfdex
)
609 DispatchEx
*This
= DISPATCHEX_THIS(iface
);
610 FIXME("(%p)->(%x %x %p)\n", This
, id
, grfdexFetch
, pgrfdex
);
614 static HRESULT WINAPI
DispatchEx_GetMemberName(IDispatchEx
*iface
, DISPID id
, BSTR
*pbstrName
)
616 DispatchEx
*This
= DISPATCHEX_THIS(iface
);
619 TRACE("(%p)->(%x %p)\n", This
, id
, pbstrName
);
621 prop
= get_prop(This
, id
);
622 if(!prop
|| !prop
->name
|| prop
->type
== PROP_DELETED
)
623 return DISP_E_MEMBERNOTFOUND
;
625 *pbstrName
= SysAllocString(prop
->name
);
627 return E_OUTOFMEMORY
;
632 static HRESULT WINAPI
DispatchEx_GetNextDispID(IDispatchEx
*iface
, DWORD grfdex
, DISPID id
, DISPID
*pid
)
634 DispatchEx
*This
= DISPATCHEX_THIS(iface
);
638 TRACE("(%p)->(%x %x %p)\n", This
, grfdex
, id
, pid
);
640 if(id
== DISPID_STARTENUM
) {
641 hres
= fill_protrefs(This
);
646 iter
= get_prop(This
, id
+1);
648 *pid
= DISPID_STARTENUM
;
652 while(iter
< This
->props
+ This
->prop_cnt
) {
653 if(iter
->name
&& (get_flags(This
, iter
) & PROPF_ENUM
)) {
654 *pid
= prop_to_id(This
, iter
);
660 *pid
= DISPID_STARTENUM
;
664 static HRESULT WINAPI
DispatchEx_GetNameSpaceParent(IDispatchEx
*iface
, IUnknown
**ppunk
)
666 DispatchEx
*This
= DISPATCHEX_THIS(iface
);
667 FIXME("(%p)->(%p)\n", This
, ppunk
);
671 #undef DISPATCHEX_THIS
673 static IDispatchExVtbl DispatchExVtbl
= {
674 DispatchEx_QueryInterface
,
677 DispatchEx_GetTypeInfoCount
,
678 DispatchEx_GetTypeInfo
,
679 DispatchEx_GetIDsOfNames
,
681 DispatchEx_GetDispID
,
683 DispatchEx_DeleteMemberByName
,
684 DispatchEx_DeleteMemberByDispID
,
685 DispatchEx_GetMemberProperties
,
686 DispatchEx_GetMemberName
,
687 DispatchEx_GetNextDispID
,
688 DispatchEx_GetNameSpaceParent
691 static HRESULT
jsdisp_set_prot_prop(DispatchEx
*dispex
, DispatchEx
*prototype
)
695 if(!dispex
->props
[1].name
)
696 return E_OUTOFMEMORY
;
698 dispex
->props
[1].type
= PROP_VARIANT
;
699 dispex
->props
[1].flags
= 0;
701 var
= &dispex
->props
[1].u
.var
;
702 V_VT(var
) = VT_DISPATCH
;
703 V_DISPATCH(var
) = (IDispatch
*)_IDispatchEx_(prototype
);
708 static HRESULT
init_dispex(DispatchEx
*dispex
, script_ctx_t
*ctx
, const builtin_info_t
*builtin_info
, DispatchEx
*prototype
)
710 static const WCHAR prototypeW
[] = {'p','r','o','t','o','t','y','p','e',0};
712 TRACE("%p (%p)\n", dispex
, prototype
);
714 dispex
->lpIDispatchExVtbl
= &DispatchExVtbl
;
716 dispex
->builtin_info
= builtin_info
;
718 dispex
->props
= heap_alloc((dispex
->buf_size
=4) * sizeof(dispex_prop_t
));
720 return E_OUTOFMEMORY
;
722 dispex
->prototype
= prototype
;
724 IDispatchEx_AddRef(_IDispatchEx_(prototype
));
726 dispex
->prop_cnt
= 2;
727 dispex
->props
[0].name
= NULL
;
728 dispex
->props
[0].flags
= 0;
729 if(builtin_info
->value_prop
.invoke
) {
730 dispex
->props
[0].type
= PROP_BUILTIN
;
731 dispex
->props
[0].u
.p
= &builtin_info
->value_prop
;
733 dispex
->props
[0].type
= PROP_DELETED
;
736 dispex
->props
[1].type
= PROP_DELETED
;
737 dispex
->props
[1].name
= SysAllocString(prototypeW
);
738 dispex
->props
[1].flags
= 0;
743 hres
= jsdisp_set_prot_prop(dispex
, prototype
);
745 IDispatchEx_Release(_IDispatchEx_(dispex
));
756 static const builtin_info_t dispex_info
= {
764 HRESULT
create_dispex(script_ctx_t
*ctx
, const builtin_info_t
*builtin_info
, DispatchEx
*prototype
, DispatchEx
**dispex
)
769 ret
= heap_alloc_zero(sizeof(DispatchEx
));
771 return E_OUTOFMEMORY
;
773 hres
= init_dispex(ret
, ctx
, builtin_info
? builtin_info
: &dispex_info
, prototype
);
781 DispatchEx
*iface_to_jsdisp(IUnknown
*iface
)
786 hres
= IUnknown_QueryInterface(iface
, &IID_IDispatchJS
, (void**)&ret
);
793 HRESULT
jsdisp_call(DispatchEx
*disp
, DISPID id
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
, VARIANT
*retv
,
794 jsexcept_t
*ei
, IServiceProvider
*caller
)
798 memset(ei
, 0, sizeof(*ei
));
800 V_VT(retv
) = VT_EMPTY
;
802 prop
= get_prop(disp
, id
);
804 return DISP_E_MEMBERNOTFOUND
;
806 return invoke_prop_func(disp
, disp
, prop
, lcid
, flags
, dp
, retv
, ei
, caller
);
809 HRESULT
disp_call(IDispatch
*disp
, DISPID id
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
, VARIANT
*retv
,
810 jsexcept_t
*ei
, IServiceProvider
*caller
)
816 jsdisp
= iface_to_jsdisp((IUnknown
*)disp
);
818 hres
= jsdisp_call(jsdisp
, id
, lcid
, flags
, dp
, retv
, ei
, caller
);
819 IDispatchEx_Release(_IDispatchEx_(jsdisp
));
823 memset(ei
, 0, sizeof(*ei
));
826 V_VT(retv
) = VT_EMPTY
;
827 hres
= IDispatch_QueryInterface(disp
, &IID_IDispatchEx
, (void**)&dispex
);
831 TRACE("using IDispatch\n");
832 return IDispatch_Invoke(disp
, id
, &IID_NULL
, lcid
, flags
, dp
, retv
, &ei
->ei
, &err
);
835 hres
= IDispatchEx_InvokeEx(dispex
, id
, lcid
, flags
, dp
, retv
, &ei
->ei
, caller
);
836 IDispatchEx_Release(dispex
);
841 HRESULT
jsdisp_propput_name(DispatchEx
*obj
, const WCHAR
*name
, LCID lcid
, VARIANT
*val
, jsexcept_t
*ei
, IServiceProvider
*caller
)
843 DISPID named_arg
= DISPID_PROPERTYPUT
;
844 DISPPARAMS dp
= {val
, &named_arg
, 1, 1};
848 hres
= find_prop_name_prot(obj
, name
, TRUE
, &prop
);
852 return prop_put(obj
, prop
, lcid
, &dp
, ei
, caller
);
855 HRESULT
disp_propput(IDispatch
*disp
, DISPID id
, LCID lcid
, VARIANT
*val
, jsexcept_t
*ei
, IServiceProvider
*caller
)
857 DISPID dispid
= DISPID_PROPERTYPUT
;
858 DISPPARAMS dp
= {val
, &dispid
, 1, 1};
863 jsdisp
= iface_to_jsdisp((IUnknown
*)disp
);
867 prop
= get_prop(jsdisp
, id
);
869 hres
= prop_put(jsdisp
, prop
, lcid
, &dp
, ei
, caller
);
871 hres
= DISP_E_MEMBERNOTFOUND
;
873 IDispatchEx_Release(_IDispatchEx_(jsdisp
));
877 hres
= IDispatch_QueryInterface(disp
, &IID_IDispatchEx
, (void**)&dispex
);
881 TRACE("using IDispatch\n");
882 return IDispatch_Invoke(disp
, id
, &IID_NULL
, DISPATCH_PROPERTYPUT
, lcid
, &dp
, NULL
, &ei
->ei
, &err
);
885 hres
= IDispatchEx_InvokeEx(dispex
, id
, lcid
, DISPATCH_PROPERTYPUT
, &dp
, NULL
, &ei
->ei
, caller
);
887 IDispatchEx_Release(dispex
);
891 HRESULT
disp_propget(IDispatch
*disp
, DISPID id
, LCID lcid
, VARIANT
*val
, jsexcept_t
*ei
, IServiceProvider
*caller
)
893 DISPPARAMS dp
= {NULL
,NULL
,0,0};
898 jsdisp
= iface_to_jsdisp((IUnknown
*)disp
);
902 prop
= get_prop(jsdisp
, id
);
904 hres
= prop_get(jsdisp
, prop
, lcid
, &dp
, val
, ei
, caller
);
906 hres
= DISP_E_MEMBERNOTFOUND
;
908 IDispatchEx_Release(_IDispatchEx_(jsdisp
));
912 hres
= IDispatch_QueryInterface(disp
, &IID_IDispatchEx
, (void**)&dispex
);
916 TRACE("uding IDispatch\n");
917 return IDispatchEx_Invoke(dispex
, id
, &IID_NULL
, lcid
, INVOKE_PROPERTYGET
, &dp
, val
, &ei
->ei
, &err
);
920 hres
= IDispatchEx_InvokeEx(dispex
, id
, lcid
, INVOKE_PROPERTYGET
, &dp
, val
, &ei
->ei
, caller
);
921 IDispatchEx_Release(dispex
);