2 * Copyright 2011 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
23 #include "wine/debug.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(vbscript
);
27 #define FDEX_VERSION_MASK 0xf0000000
29 static inline BOOL
is_func_id(vbdisp_t
*This
, DISPID id
)
31 return id
< This
->desc
->func_cnt
;
34 static BOOL
get_func_id(vbdisp_t
*This
, const WCHAR
*name
, vbdisp_invoke_type_t invoke_type
, BOOL search_private
, DISPID
*id
)
38 for(i
= invoke_type
== VBDISP_ANY
? 0 : 1; i
< This
->desc
->func_cnt
; i
++) {
39 if(invoke_type
== VBDISP_ANY
) {
40 if(!search_private
&& !This
->desc
->funcs
[i
].is_public
)
42 if(!i
&& !This
->desc
->funcs
[0].name
) /* default value may not exist */
45 if(!This
->desc
->funcs
[i
].entries
[invoke_type
]
46 || (!search_private
&& !This
->desc
->funcs
[i
].entries
[invoke_type
]->is_public
))
50 if(!strcmpiW(This
->desc
->funcs
[i
].name
, name
)) {
59 HRESULT
vbdisp_get_id(vbdisp_t
*This
, BSTR name
, vbdisp_invoke_type_t invoke_type
, BOOL search_private
, DISPID
*id
)
63 if(get_func_id(This
, name
, invoke_type
, search_private
, id
))
66 for(i
=0; i
< This
->desc
->prop_cnt
; i
++) {
67 if(!search_private
&& !This
->desc
->props
[i
].is_public
)
70 if(!strcmpiW(This
->desc
->props
[i
].name
, name
)) {
71 *id
= i
+ This
->desc
->func_cnt
;
76 if(This
->desc
->typeinfo
) {
79 hres
= ITypeInfo_GetIDsOfNames(This
->desc
->typeinfo
, &name
, 1, id
);
85 return DISP_E_UNKNOWNNAME
;
88 static VARIANT
*get_propput_arg(const DISPPARAMS
*dp
)
92 for(i
=0; i
< dp
->cNamedArgs
; i
++) {
93 if(dp
->rgdispidNamedArgs
[i
] == DISPID_PROPERTYPUT
)
100 static HRESULT
invoke_variant_prop(VARIANT
*v
, WORD flags
, DISPPARAMS
*dp
, VARIANT
*res
)
105 case DISPATCH_PROPERTYGET
|DISPATCH_METHOD
:
106 case DISPATCH_PROPERTYGET
:
108 WARN("called with arguments\n");
109 return DISP_E_MEMBERNOTFOUND
; /* That's what tests show */
112 hres
= VariantCopy(res
, v
);
115 case DISPATCH_PROPERTYPUT
: {
118 put_val
= get_propput_arg(dp
);
120 WARN("no value to set\n");
121 return DISP_E_PARAMNOTOPTIONAL
;
125 V_VT(res
) = VT_EMPTY
;
127 hres
= VariantCopy(v
, put_val
);
132 FIXME("unimplemented flags %x\n", flags
);
139 static HRESULT
invoke_builtin(vbdisp_t
*This
, const builtin_prop_t
*prop
, WORD flags
, DISPPARAMS
*dp
, VARIANT
*res
)
145 case DISPATCH_PROPERTYGET
:
146 if(!(prop
->flags
& (BP_GET
|BP_GETPUT
))) {
147 FIXME("property does not support DISPATCH_PROPERTYGET\n");
151 case DISPATCH_PROPERTYGET
|DISPATCH_METHOD
:
152 if(!prop
->proc
&& prop
->flags
== BP_GET
) {
153 const int vt
= prop
->min_args
, val
= prop
->max_args
;
164 const string_constant_t
*str
= (const string_constant_t
*)prop
->max_args
;
167 ret
= SysAllocStringLen(str
->buf
, str
->len
);
169 return E_OUTOFMEMORY
;
180 case DISPATCH_METHOD
:
181 if(prop
->flags
& (BP_GET
|BP_GETPUT
)) {
182 FIXME("Call on property\n");
186 case DISPATCH_PROPERTYPUT
:
187 if(!(prop
->flags
& BP_GETPUT
)) {
188 FIXME("property does not support DISPATCH_PROPERTYPUT\n");
195 FIXME("unsupported flags %x\n", flags
);
201 if(argn
< prop
->min_args
|| argn
> (prop
->max_args
? prop
->max_args
: prop
->min_args
)) {
202 FIXME("invalid number of arguments\n");
206 assert(argn
< sizeof(args
)/sizeof(*args
));
208 for(i
=0; i
< argn
; i
++) {
209 if(V_VT(dp
->rgvarg
+dp
->cArgs
-i
-1) == (VT_BYREF
|VT_VARIANT
))
210 args
[i
] = *V_VARIANTREF(dp
->rgvarg
+dp
->cArgs
-i
-1);
212 args
[i
] = dp
->rgvarg
[dp
->cArgs
-i
-1];
215 return prop
->proc(This
, args
, dp
->cArgs
, res
);
218 static BOOL
run_terminator(vbdisp_t
*This
)
222 if(This
->terminator_ran
)
224 This
->terminator_ran
= TRUE
;
226 if(!This
->desc
->class_terminate_id
)
230 exec_script(This
->desc
->ctx
, This
->desc
->funcs
[This
->desc
->class_terminate_id
].entries
[VBDISP_CALLGET
],
231 (IDispatch
*)&This
->IDispatchEx_iface
, &dp
, NULL
);
235 static void clean_props(vbdisp_t
*This
)
242 for(i
=0; i
< This
->desc
->prop_cnt
; i
++)
243 VariantClear(This
->props
+i
);
246 static inline vbdisp_t
*impl_from_IDispatchEx(IDispatchEx
*iface
)
248 return CONTAINING_RECORD(iface
, vbdisp_t
, IDispatchEx_iface
);
251 static HRESULT WINAPI
DispatchEx_QueryInterface(IDispatchEx
*iface
, REFIID riid
, void **ppv
)
253 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
255 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
256 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
257 *ppv
= &This
->IDispatchEx_iface
;
258 }else if(IsEqualGUID(&IID_IDispatch
, riid
)) {
259 TRACE("(%p)->(IID_IDispatch %p)\n", This
, ppv
);
260 *ppv
= &This
->IDispatchEx_iface
;
261 }else if(IsEqualGUID(&IID_IDispatchEx
, riid
)) {
262 TRACE("(%p)->(IID_IDispatchEx %p)\n", This
, ppv
);
263 *ppv
= &This
->IDispatchEx_iface
;
265 WARN("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
267 return E_NOINTERFACE
;
270 IUnknown_AddRef((IUnknown
*)*ppv
);
274 static ULONG WINAPI
DispatchEx_AddRef(IDispatchEx
*iface
)
276 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
277 LONG ref
= InterlockedIncrement(&This
->ref
);
279 TRACE("(%p) ref=%d\n", This
, ref
);
284 static ULONG WINAPI
DispatchEx_Release(IDispatchEx
*iface
)
286 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
287 LONG ref
= InterlockedDecrement(&This
->ref
);
289 TRACE("(%p) ref=%d\n", This
, ref
);
291 if(!ref
&& run_terminator(This
)) {
293 list_remove(&This
->entry
);
300 static HRESULT WINAPI
DispatchEx_GetTypeInfoCount(IDispatchEx
*iface
, UINT
*pctinfo
)
302 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
304 TRACE("(%p)->(%p)\n", This
, pctinfo
);
310 static HRESULT WINAPI
DispatchEx_GetTypeInfo(IDispatchEx
*iface
, UINT iTInfo
, LCID lcid
,
313 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
314 FIXME("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
318 static HRESULT WINAPI
DispatchEx_GetIDsOfNames(IDispatchEx
*iface
, REFIID riid
,
319 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
,
322 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
323 FIXME("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
,
328 static HRESULT WINAPI
DispatchEx_Invoke(IDispatchEx
*iface
, DISPID dispIdMember
,
329 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
,
330 VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
332 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
333 FIXME("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
334 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
338 static HRESULT WINAPI
DispatchEx_GetDispID(IDispatchEx
*iface
, BSTR bstrName
, DWORD grfdex
, DISPID
*pid
)
340 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
342 TRACE("(%p)->(%s %x %p)\n", This
, debugstr_w(bstrName
), grfdex
, pid
);
344 grfdex
&= ~FDEX_VERSION_MASK
;
349 /* Tests show that fdexNameCaseSensitive is ignored */
351 if(grfdex
& ~(fdexNameEnsure
|fdexNameCaseInsensitive
|fdexNameCaseSensitive
)) {
352 FIXME("unsupported flags %x\n", grfdex
);
356 return vbdisp_get_id(This
, bstrName
, VBDISP_ANY
, FALSE
, pid
);
359 static HRESULT WINAPI
DispatchEx_InvokeEx(IDispatchEx
*iface
, DISPID id
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pdp
,
360 VARIANT
*pvarRes
, EXCEPINFO
*pei
, IServiceProvider
*pspCaller
)
362 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
364 TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This
, id
, lcid
, wFlags
, pdp
, pvarRes
, pei
, pspCaller
);
370 V_VT(pvarRes
) = VT_EMPTY
;
373 return DISP_E_MEMBERNOTFOUND
;
375 if(is_func_id(This
, id
)) {
379 case DISPATCH_METHOD
:
380 case DISPATCH_METHOD
|DISPATCH_PROPERTYGET
:
381 func
= This
->desc
->funcs
[id
].entries
[VBDISP_CALLGET
];
383 FIXME("no invoke/getter\n");
384 return DISP_E_MEMBERNOTFOUND
;
387 return exec_script(This
->desc
->ctx
, func
, (IDispatch
*)&This
->IDispatchEx_iface
, pdp
, pvarRes
);
388 case DISPATCH_PROPERTYPUT
: {
390 DISPPARAMS dp
= {NULL
, NULL
, 1, 0};
393 FIXME("arguments not implemented\n");
397 put_val
= get_propput_arg(pdp
);
399 WARN("no value to set\n");
400 return DISP_E_PARAMNOTOPTIONAL
;
404 func
= This
->desc
->funcs
[id
].entries
[V_VT(put_val
) == VT_DISPATCH
? VBDISP_SET
: VBDISP_LET
];
406 FIXME("no letter/setter\n");
407 return DISP_E_MEMBERNOTFOUND
;
410 return exec_script(This
->desc
->ctx
, func
, (IDispatch
*)&This
->IDispatchEx_iface
, &dp
, NULL
);
413 FIXME("flags %x\n", wFlags
);
414 return DISP_E_MEMBERNOTFOUND
;
418 if(id
< This
->desc
->prop_cnt
+ This
->desc
->func_cnt
)
419 return invoke_variant_prop(This
->props
+(id
-This
->desc
->func_cnt
), wFlags
, pdp
, pvarRes
);
421 if(This
->desc
->builtin_prop_cnt
) {
422 unsigned min
= 0, max
= This
->desc
->builtin_prop_cnt
-1, i
;
426 if(This
->desc
->builtin_props
[i
].id
== id
)
427 return invoke_builtin(This
, This
->desc
->builtin_props
+i
, wFlags
, pdp
, pvarRes
);
428 if(This
->desc
->builtin_props
[i
].id
< id
)
435 return DISP_E_MEMBERNOTFOUND
;
438 static HRESULT WINAPI
DispatchEx_DeleteMemberByName(IDispatchEx
*iface
, BSTR bstrName
, DWORD grfdex
)
440 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
441 FIXME("(%p)->(%s %x)\n", This
, debugstr_w(bstrName
), grfdex
);
445 static HRESULT WINAPI
DispatchEx_DeleteMemberByDispID(IDispatchEx
*iface
, DISPID id
)
447 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
448 FIXME("(%p)->(%x)\n", This
, id
);
452 static HRESULT WINAPI
DispatchEx_GetMemberProperties(IDispatchEx
*iface
, DISPID id
, DWORD grfdexFetch
, DWORD
*pgrfdex
)
454 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
455 FIXME("(%p)->(%x %x %p)\n", This
, id
, grfdexFetch
, pgrfdex
);
459 static HRESULT WINAPI
DispatchEx_GetMemberName(IDispatchEx
*iface
, DISPID id
, BSTR
*pbstrName
)
461 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
462 FIXME("(%p)->(%x %p)\n", This
, id
, pbstrName
);
466 static HRESULT WINAPI
DispatchEx_GetNextDispID(IDispatchEx
*iface
, DWORD grfdex
, DISPID id
, DISPID
*pid
)
468 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
469 FIXME("(%p)->(%x %x %p)\n", This
, grfdex
, id
, pid
);
473 static HRESULT WINAPI
DispatchEx_GetNameSpaceParent(IDispatchEx
*iface
, IUnknown
**ppunk
)
475 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
476 FIXME("(%p)->(%p)\n", This
, ppunk
);
480 static IDispatchExVtbl DispatchExVtbl
= {
481 DispatchEx_QueryInterface
,
484 DispatchEx_GetTypeInfoCount
,
485 DispatchEx_GetTypeInfo
,
486 DispatchEx_GetIDsOfNames
,
488 DispatchEx_GetDispID
,
490 DispatchEx_DeleteMemberByName
,
491 DispatchEx_DeleteMemberByDispID
,
492 DispatchEx_GetMemberProperties
,
493 DispatchEx_GetMemberName
,
494 DispatchEx_GetNextDispID
,
495 DispatchEx_GetNameSpaceParent
498 static inline vbdisp_t
*unsafe_impl_from_IDispatch(IDispatch
*iface
)
500 return iface
->lpVtbl
== (IDispatchVtbl
*)&DispatchExVtbl
501 ? CONTAINING_RECORD(iface
, vbdisp_t
, IDispatchEx_iface
)
505 HRESULT
create_vbdisp(const class_desc_t
*desc
, vbdisp_t
**ret
)
509 vbdisp
= heap_alloc_zero( FIELD_OFFSET( vbdisp_t
, props
[desc
->prop_cnt
] ));
511 return E_OUTOFMEMORY
;
513 vbdisp
->IDispatchEx_iface
.lpVtbl
= &DispatchExVtbl
;
517 list_add_tail(&desc
->ctx
->objects
, &vbdisp
->entry
);
519 if(desc
->class_initialize_id
) {
523 hres
= exec_script(desc
->ctx
, desc
->funcs
[desc
->class_initialize_id
].entries
[VBDISP_CALLGET
],
524 (IDispatch
*)&vbdisp
->IDispatchEx_iface
, &dp
, NULL
);
526 IDispatchEx_Release(&vbdisp
->IDispatchEx_iface
);
535 static HRESULT
Procedure_invoke(vbdisp_t
*This
, VARIANT
*args
, unsigned args_cnt
, VARIANT
*res
)
537 script_ctx_t
*ctx
= This
->desc
->ctx
;
542 IActiveScriptSite_OnEnterScript(ctx
->site
);
543 hres
= exec_script(ctx
, This
->desc
->value_func
, NULL
, NULL
, NULL
);
544 IActiveScriptSite_OnLeaveScript(ctx
->site
);
549 static const builtin_prop_t procedure_props
[] = {
550 {DISPID_VALUE
, Procedure_invoke
, 0}
553 HRESULT
create_procedure_disp(script_ctx_t
*ctx
, vbscode_t
*code
, IDispatch
**ret
)
559 desc
= heap_alloc_zero(sizeof(*desc
));
561 return E_OUTOFMEMORY
;
564 desc
->builtin_prop_cnt
= sizeof(procedure_props
)/sizeof(*procedure_props
);
565 desc
->builtin_props
= procedure_props
;
566 desc
->value_func
= &code
->main_code
;
568 hres
= create_vbdisp(desc
, &vbdisp
);
574 desc
->next
= ctx
->procs
;
577 *ret
= (IDispatch
*)&vbdisp
->IDispatchEx_iface
;
581 struct _ident_map_t
{
590 static inline DISPID
ident_to_id(ScriptDisp
*This
, ident_map_t
*ident
)
592 return (ident
-This
->ident_map
)+1;
595 static inline ident_map_t
*id_to_ident(ScriptDisp
*This
, DISPID id
)
597 return 0 < id
&& id
<= This
->ident_map_cnt
? This
->ident_map
+id
-1 : NULL
;
600 static ident_map_t
*add_ident(ScriptDisp
*This
, const WCHAR
*name
)
604 if(!This
->ident_map_size
) {
605 This
->ident_map
= heap_alloc(4 * sizeof(*This
->ident_map
));
608 This
->ident_map_size
= 4;
609 }else if(This
->ident_map_cnt
== This
->ident_map_size
) {
610 ident_map_t
*new_map
;
612 new_map
= heap_realloc(This
->ident_map
, 2*This
->ident_map_size
*sizeof(*new_map
));
615 This
->ident_map
= new_map
;
616 This
->ident_map_size
*= 2;
619 ret
= This
->ident_map
+ This
->ident_map_cnt
++;
624 static inline ScriptDisp
*ScriptDisp_from_IDispatchEx(IDispatchEx
*iface
)
626 return CONTAINING_RECORD(iface
, ScriptDisp
, IDispatchEx_iface
);
629 static HRESULT WINAPI
ScriptDisp_QueryInterface(IDispatchEx
*iface
, REFIID riid
, void **ppv
)
631 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
633 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
634 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
635 *ppv
= &This
->IDispatchEx_iface
;
636 }else if(IsEqualGUID(&IID_IDispatch
, riid
)) {
637 TRACE("(%p)->(IID_IDispatch %p)\n", This
, ppv
);
638 *ppv
= &This
->IDispatchEx_iface
;
639 }else if(IsEqualGUID(&IID_IDispatchEx
, riid
)) {
640 TRACE("(%p)->(IID_IDispatchEx %p)\n", This
, ppv
);
641 *ppv
= &This
->IDispatchEx_iface
;
643 WARN("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
645 return E_NOINTERFACE
;
648 IUnknown_AddRef((IUnknown
*)*ppv
);
652 static ULONG WINAPI
ScriptDisp_AddRef(IDispatchEx
*iface
)
654 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
655 LONG ref
= InterlockedIncrement(&This
->ref
);
657 TRACE("(%p) ref=%d\n", This
, ref
);
662 static ULONG WINAPI
ScriptDisp_Release(IDispatchEx
*iface
)
664 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
665 LONG ref
= InterlockedDecrement(&This
->ref
);
667 TRACE("(%p) ref=%d\n", This
, ref
);
671 heap_free(This
->ident_map
);
678 static HRESULT WINAPI
ScriptDisp_GetTypeInfoCount(IDispatchEx
*iface
, UINT
*pctinfo
)
680 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
682 TRACE("(%p)->(%p)\n", This
, pctinfo
);
688 static HRESULT WINAPI
ScriptDisp_GetTypeInfo(IDispatchEx
*iface
, UINT iTInfo
, LCID lcid
,
691 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
692 FIXME("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
696 static HRESULT WINAPI
ScriptDisp_GetIDsOfNames(IDispatchEx
*iface
, REFIID riid
,
697 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
699 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
703 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
,
706 for(i
=0; i
< cNames
; i
++) {
707 hres
= IDispatchEx_GetDispID(&This
->IDispatchEx_iface
, rgszNames
[i
], 0, rgDispId
+i
);
715 static HRESULT WINAPI
ScriptDisp_Invoke(IDispatchEx
*iface
, DISPID dispIdMember
, REFIID riid
, LCID lcid
,
716 WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
718 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
720 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
721 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
723 return IDispatchEx_InvokeEx(&This
->IDispatchEx_iface
, dispIdMember
, lcid
, wFlags
,
724 pDispParams
, pVarResult
, pExcepInfo
, NULL
);
727 static HRESULT WINAPI
ScriptDisp_GetDispID(IDispatchEx
*iface
, BSTR bstrName
, DWORD grfdex
, DISPID
*pid
)
729 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
734 TRACE("(%p)->(%s %x %p)\n", This
, debugstr_w(bstrName
), grfdex
, pid
);
739 for(ident
= This
->ident_map
; ident
< This
->ident_map
+This
->ident_map_cnt
; ident
++) {
740 if(!strcmpiW(ident
->name
, bstrName
)) {
741 *pid
= ident_to_id(This
, ident
);
746 for(var
= This
->ctx
->global_vars
; var
; var
= var
->next
) {
747 if(!strcmpiW(var
->name
, bstrName
)) {
748 ident
= add_ident(This
, var
->name
);
750 return E_OUTOFMEMORY
;
752 ident
->is_var
= TRUE
;
754 *pid
= ident_to_id(This
, ident
);
759 for(func
= This
->ctx
->global_funcs
; func
; func
= func
->next
) {
760 if(!strcmpiW(func
->name
, bstrName
)) {
761 ident
= add_ident(This
, func
->name
);
763 return E_OUTOFMEMORY
;
765 ident
->is_var
= FALSE
;
766 ident
->u
.func
= func
;
767 *pid
= ident_to_id(This
, ident
);
773 return DISP_E_UNKNOWNNAME
;
776 static HRESULT WINAPI
ScriptDisp_InvokeEx(IDispatchEx
*iface
, DISPID id
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pdp
,
777 VARIANT
*pvarRes
, EXCEPINFO
*pei
, IServiceProvider
*pspCaller
)
779 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
783 TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This
, id
, lcid
, wFlags
, pdp
, pvarRes
, pei
, pspCaller
);
785 ident
= id_to_ident(This
, id
);
787 return DISP_E_MEMBERNOTFOUND
;
790 if(ident
->u
.var
->is_const
) {
791 FIXME("const not supported\n");
795 return invoke_variant_prop(&ident
->u
.var
->v
, wFlags
, pdp
, pvarRes
);
799 case DISPATCH_METHOD
:
800 case DISPATCH_METHOD
|DISPATCH_PROPERTYGET
:
801 IActiveScriptSite_OnEnterScript(This
->ctx
->site
);
802 hres
= exec_script(This
->ctx
, ident
->u
.func
, NULL
, pdp
, pvarRes
);
803 IActiveScriptSite_OnLeaveScript(This
->ctx
->site
);
806 FIXME("Unsupported flags %x\n", wFlags
);
813 static HRESULT WINAPI
ScriptDisp_DeleteMemberByName(IDispatchEx
*iface
, BSTR bstrName
, DWORD grfdex
)
815 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
816 FIXME("(%p)->(%s %x)\n", This
, debugstr_w(bstrName
), grfdex
);
820 static HRESULT WINAPI
ScriptDisp_DeleteMemberByDispID(IDispatchEx
*iface
, DISPID id
)
822 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
823 FIXME("(%p)->(%x)\n", This
, id
);
827 static HRESULT WINAPI
ScriptDisp_GetMemberProperties(IDispatchEx
*iface
, DISPID id
, DWORD grfdexFetch
, DWORD
*pgrfdex
)
829 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
830 FIXME("(%p)->(%x %x %p)\n", This
, id
, grfdexFetch
, pgrfdex
);
834 static HRESULT WINAPI
ScriptDisp_GetMemberName(IDispatchEx
*iface
, DISPID id
, BSTR
*pbstrName
)
836 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
837 FIXME("(%p)->(%x %p)\n", This
, id
, pbstrName
);
841 static HRESULT WINAPI
ScriptDisp_GetNextDispID(IDispatchEx
*iface
, DWORD grfdex
, DISPID id
, DISPID
*pid
)
843 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
844 FIXME("(%p)->(%x %x %p)\n", This
, grfdex
, id
, pid
);
848 static HRESULT WINAPI
ScriptDisp_GetNameSpaceParent(IDispatchEx
*iface
, IUnknown
**ppunk
)
850 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
851 FIXME("(%p)->(%p)\n", This
, ppunk
);
855 static IDispatchExVtbl ScriptDispVtbl
= {
856 ScriptDisp_QueryInterface
,
859 ScriptDisp_GetTypeInfoCount
,
860 ScriptDisp_GetTypeInfo
,
861 ScriptDisp_GetIDsOfNames
,
863 ScriptDisp_GetDispID
,
865 ScriptDisp_DeleteMemberByName
,
866 ScriptDisp_DeleteMemberByDispID
,
867 ScriptDisp_GetMemberProperties
,
868 ScriptDisp_GetMemberName
,
869 ScriptDisp_GetNextDispID
,
870 ScriptDisp_GetNameSpaceParent
873 HRESULT
create_script_disp(script_ctx_t
*ctx
, ScriptDisp
**ret
)
875 ScriptDisp
*script_disp
;
877 script_disp
= heap_alloc_zero(sizeof(*script_disp
));
879 return E_OUTOFMEMORY
;
881 script_disp
->IDispatchEx_iface
.lpVtbl
= &ScriptDispVtbl
;
882 script_disp
->ref
= 1;
883 script_disp
->ctx
= ctx
;
889 void collect_objects(script_ctx_t
*ctx
)
891 vbdisp_t
*iter
, *iter2
;
893 LIST_FOR_EACH_ENTRY_SAFE(iter
, iter2
, &ctx
->objects
, vbdisp_t
, entry
)
894 run_terminator(iter
);
896 while(!list_empty(&ctx
->objects
)) {
897 iter
= LIST_ENTRY(list_head(&ctx
->objects
), vbdisp_t
, entry
);
899 IDispatchEx_AddRef(&iter
->IDispatchEx_iface
);
902 list_remove(&iter
->entry
);
903 list_init(&iter
->entry
);
904 IDispatchEx_Release(&iter
->IDispatchEx_iface
);
908 HRESULT
disp_get_id(IDispatch
*disp
, BSTR name
, vbdisp_invoke_type_t invoke_type
, BOOL search_private
, DISPID
*id
)
914 vbdisp
= unsafe_impl_from_IDispatch(disp
);
916 return vbdisp_get_id(vbdisp
, name
, invoke_type
, search_private
, id
);
918 hres
= IDispatch_QueryInterface(disp
, &IID_IDispatchEx
, (void**)&dispex
);
920 TRACE("using IDispatch\n");
921 return IDispatch_GetIDsOfNames(disp
, &IID_NULL
, &name
, 1, 0, id
);
924 hres
= IDispatchEx_GetDispID(dispex
, name
, fdexNameCaseInsensitive
, id
);
925 IDispatchEx_Release(dispex
);
929 HRESULT
disp_call(script_ctx_t
*ctx
, IDispatch
*disp
, DISPID id
, DISPPARAMS
*dp
, VARIANT
*retv
)
931 const WORD flags
= DISPATCH_METHOD
|(retv
? DISPATCH_PROPERTYGET
: 0);
936 memset(&ei
, 0, sizeof(ei
));
938 V_VT(retv
) = VT_EMPTY
;
940 hres
= IDispatch_QueryInterface(disp
, &IID_IDispatchEx
, (void**)&dispex
);
944 TRACE("using IDispatch\n");
945 return IDispatch_Invoke(disp
, id
, &IID_NULL
, ctx
->lcid
, flags
, dp
, retv
, &ei
, &err
);
948 hres
= IDispatchEx_InvokeEx(dispex
, id
, ctx
->lcid
, flags
, dp
, retv
, &ei
, NULL
/* CALLER_FIXME */);
949 IDispatchEx_Release(dispex
);
953 HRESULT
disp_propput(script_ctx_t
*ctx
, IDispatch
*disp
, DISPID id
, DISPPARAMS
*dp
)
959 hres
= IDispatch_QueryInterface(disp
, &IID_IDispatchEx
, (void**)&dispex
);
960 if(SUCCEEDED(hres
)) {
961 hres
= IDispatchEx_InvokeEx(dispex
, id
, ctx
->lcid
, DISPATCH_PROPERTYPUT
, dp
, NULL
, &ei
, NULL
/* FIXME! */);
962 IDispatchEx_Release(dispex
);
966 TRACE("using IDispatch\n");
967 hres
= IDispatch_Invoke(disp
, id
, &IID_NULL
, ctx
->lcid
, DISPATCH_PROPERTYPUT
, dp
, NULL
, &ei
, &err
);