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 HRESULT
get_propput_arg(script_ctx_t
*ctx
, const DISPPARAMS
*dp
, WORD flags
, VARIANT
*v
, BOOL
*is_owned
)
92 for(i
=0; i
< dp
->cNamedArgs
; i
++) {
93 if(dp
->rgdispidNamedArgs
[i
] == DISPID_PROPERTYPUT
)
96 if(i
== dp
->cNamedArgs
) {
97 WARN("no value to set\n");
98 return DISP_E_PARAMNOTOPTIONAL
;
102 if(V_VT(v
) == (VT_VARIANT
|VT_BYREF
))
103 *v
= *V_VARIANTREF(v
);
106 if(V_VT(v
) == VT_DISPATCH
) {
107 if(!(flags
& DISPATCH_PROPERTYPUTREF
)) {
110 hres
= get_disp_value(ctx
, V_DISPATCH(v
), v
);
116 }else if(!(flags
& DISPATCH_PROPERTYPUT
)) {
117 WARN("%s can't be assigned without DISPATCH_PROPERTYPUT flag\n", debugstr_variant(v
));
118 return DISP_E_EXCEPTION
;
124 static HRESULT
invoke_variant_prop(script_ctx_t
*ctx
, VARIANT
*v
, WORD flags
, DISPPARAMS
*dp
, VARIANT
*res
)
129 case DISPATCH_PROPERTYGET
|DISPATCH_METHOD
:
130 case DISPATCH_PROPERTYGET
:
132 WARN("called with arguments\n");
133 return DISP_E_MEMBERNOTFOUND
; /* That's what tests show */
136 hres
= VariantCopyInd(res
, v
);
139 case DISPATCH_PROPERTYPUT
:
140 case DISPATCH_PROPERTYPUTREF
:
141 case DISPATCH_PROPERTYPUT
|DISPATCH_PROPERTYPUTREF
: {
145 hres
= get_propput_arg(ctx
, dp
, flags
, &put_val
, &own_val
);
150 FIXME("Arguments not supported\n");
155 V_VT(res
) = VT_EMPTY
;
160 hres
= VariantCopyInd(v
, &put_val
);
165 FIXME("unimplemented flags %x\n", flags
);
172 static HRESULT
invoke_builtin(vbdisp_t
*This
, const builtin_prop_t
*prop
, WORD flags
, DISPPARAMS
*dp
, VARIANT
*res
)
178 case DISPATCH_PROPERTYGET
:
179 if(!(prop
->flags
& (BP_GET
|BP_GETPUT
))) {
180 FIXME("property does not support DISPATCH_PROPERTYGET\n");
184 case DISPATCH_PROPERTYGET
|DISPATCH_METHOD
:
185 if(!prop
->proc
&& prop
->flags
== BP_GET
) {
186 const int vt
= prop
->min_args
, val
= prop
->max_args
;
197 const string_constant_t
*str
= (const string_constant_t
*)prop
->max_args
;
200 ret
= SysAllocStringLen(str
->buf
, str
->len
);
202 return E_OUTOFMEMORY
;
213 case DISPATCH_METHOD
:
214 if(prop
->flags
& (BP_GET
|BP_GETPUT
)) {
215 FIXME("Call on property\n");
219 case DISPATCH_PROPERTYPUT
:
220 if(!(prop
->flags
& BP_GETPUT
)) {
221 FIXME("property does not support DISPATCH_PROPERTYPUT\n");
228 FIXME("unsupported flags %x\n", flags
);
234 if(argn
< prop
->min_args
|| argn
> (prop
->max_args
? prop
->max_args
: prop
->min_args
)) {
235 FIXME("invalid number of arguments\n");
239 assert(argn
< sizeof(args
)/sizeof(*args
));
241 for(i
=0; i
< argn
; i
++) {
242 if(V_VT(dp
->rgvarg
+dp
->cArgs
-i
-1) == (VT_BYREF
|VT_VARIANT
))
243 args
[i
] = *V_VARIANTREF(dp
->rgvarg
+dp
->cArgs
-i
-1);
245 args
[i
] = dp
->rgvarg
[dp
->cArgs
-i
-1];
248 return prop
->proc(This
, args
, dp
->cArgs
, res
);
251 static BOOL
run_terminator(vbdisp_t
*This
)
255 if(This
->terminator_ran
)
257 This
->terminator_ran
= TRUE
;
259 if(!This
->desc
->class_terminate_id
)
263 exec_script(This
->desc
->ctx
, This
->desc
->funcs
[This
->desc
->class_terminate_id
].entries
[VBDISP_CALLGET
],
268 static void clean_props(vbdisp_t
*This
)
275 for(i
=0; i
< This
->desc
->array_cnt
; i
++) {
276 if(This
->arrays
[i
]) {
277 SafeArrayDestroy(This
->arrays
[i
]);
278 This
->arrays
[i
] = NULL
;
282 for(i
=0; i
< This
->desc
->prop_cnt
; i
++)
283 VariantClear(This
->props
+i
);
286 static inline vbdisp_t
*impl_from_IDispatchEx(IDispatchEx
*iface
)
288 return CONTAINING_RECORD(iface
, vbdisp_t
, IDispatchEx_iface
);
291 static HRESULT WINAPI
DispatchEx_QueryInterface(IDispatchEx
*iface
, REFIID riid
, void **ppv
)
293 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
295 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
296 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
297 *ppv
= &This
->IDispatchEx_iface
;
298 }else if(IsEqualGUID(&IID_IDispatch
, riid
)) {
299 TRACE("(%p)->(IID_IDispatch %p)\n", This
, ppv
);
300 *ppv
= &This
->IDispatchEx_iface
;
301 }else if(IsEqualGUID(&IID_IDispatchEx
, riid
)) {
302 TRACE("(%p)->(IID_IDispatchEx %p)\n", This
, ppv
);
303 *ppv
= &This
->IDispatchEx_iface
;
305 WARN("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
307 return E_NOINTERFACE
;
310 IUnknown_AddRef((IUnknown
*)*ppv
);
314 static ULONG WINAPI
DispatchEx_AddRef(IDispatchEx
*iface
)
316 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
317 LONG ref
= InterlockedIncrement(&This
->ref
);
319 TRACE("(%p) ref=%d\n", This
, ref
);
324 static ULONG WINAPI
DispatchEx_Release(IDispatchEx
*iface
)
326 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
327 LONG ref
= InterlockedDecrement(&This
->ref
);
329 TRACE("(%p) ref=%d\n", This
, ref
);
331 if(!ref
&& run_terminator(This
)) {
333 list_remove(&This
->entry
);
334 heap_free(This
->arrays
);
341 static HRESULT WINAPI
DispatchEx_GetTypeInfoCount(IDispatchEx
*iface
, UINT
*pctinfo
)
343 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
345 TRACE("(%p)->(%p)\n", This
, pctinfo
);
351 static HRESULT WINAPI
DispatchEx_GetTypeInfo(IDispatchEx
*iface
, UINT iTInfo
, LCID lcid
,
354 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
355 FIXME("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
359 static HRESULT WINAPI
DispatchEx_GetIDsOfNames(IDispatchEx
*iface
, REFIID riid
,
360 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
,
363 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
364 FIXME("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
,
369 static HRESULT WINAPI
DispatchEx_Invoke(IDispatchEx
*iface
, DISPID dispIdMember
,
370 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
,
371 VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
373 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
375 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
376 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
378 return IDispatchEx_InvokeEx(&This
->IDispatchEx_iface
, dispIdMember
, lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, NULL
);
381 static HRESULT WINAPI
DispatchEx_GetDispID(IDispatchEx
*iface
, BSTR bstrName
, DWORD grfdex
, DISPID
*pid
)
383 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
385 TRACE("(%p)->(%s %x %p)\n", This
, debugstr_w(bstrName
), grfdex
, pid
);
387 grfdex
&= ~FDEX_VERSION_MASK
;
392 /* Tests show that fdexNameCaseSensitive is ignored */
394 if(grfdex
& ~(fdexNameEnsure
|fdexNameCaseInsensitive
|fdexNameCaseSensitive
)) {
395 FIXME("unsupported flags %x\n", grfdex
);
399 return vbdisp_get_id(This
, bstrName
, VBDISP_ANY
, FALSE
, pid
);
402 static HRESULT WINAPI
DispatchEx_InvokeEx(IDispatchEx
*iface
, DISPID id
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pdp
,
403 VARIANT
*pvarRes
, EXCEPINFO
*pei
, IServiceProvider
*pspCaller
)
405 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
407 TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This
, id
, lcid
, wFlags
, pdp
, pvarRes
, pei
, pspCaller
);
413 V_VT(pvarRes
) = VT_EMPTY
;
416 return DISP_E_MEMBERNOTFOUND
;
418 if(is_func_id(This
, id
)) {
422 case DISPATCH_PROPERTYGET
:
423 func
= This
->desc
->funcs
[id
].entries
[VBDISP_CALLGET
];
424 if(!func
|| (func
->type
!= FUNC_PROPGET
&& func
->type
!= FUNC_DEFGET
)) {
426 return DISP_E_MEMBERNOTFOUND
;
429 return exec_script(This
->desc
->ctx
, func
, This
, pdp
, pvarRes
);
431 case DISPATCH_METHOD
:
432 case DISPATCH_METHOD
|DISPATCH_PROPERTYGET
:
433 func
= This
->desc
->funcs
[id
].entries
[VBDISP_CALLGET
];
435 FIXME("no invoke/getter\n");
436 return DISP_E_MEMBERNOTFOUND
;
439 return exec_script(This
->desc
->ctx
, func
, This
, pdp
, pvarRes
);
440 case DISPATCH_PROPERTYPUT
:
441 case DISPATCH_PROPERTYPUTREF
:
442 case DISPATCH_PROPERTYPUT
|DISPATCH_PROPERTYPUTREF
: {
443 DISPPARAMS dp
= {NULL
, NULL
, 1, 0};
449 FIXME("arguments not implemented\n");
453 hres
= get_propput_arg(This
->desc
->ctx
, pdp
, wFlags
, &put_val
, &needs_release
);
457 dp
.rgvarg
= &put_val
;
458 func
= This
->desc
->funcs
[id
].entries
[V_VT(&put_val
) == VT_DISPATCH
? VBDISP_SET
: VBDISP_LET
];
460 FIXME("no letter/setter\n");
461 return DISP_E_MEMBERNOTFOUND
;
464 hres
= exec_script(This
->desc
->ctx
, func
, This
, &dp
, NULL
);
466 VariantClear(&put_val
);
470 FIXME("flags %x\n", wFlags
);
471 return DISP_E_MEMBERNOTFOUND
;
475 if(id
< This
->desc
->prop_cnt
+ This
->desc
->func_cnt
)
476 return invoke_variant_prop(This
->desc
->ctx
, This
->props
+(id
-This
->desc
->func_cnt
), wFlags
, pdp
, pvarRes
);
478 if(This
->desc
->builtin_prop_cnt
) {
479 unsigned min
= 0, max
= This
->desc
->builtin_prop_cnt
-1, i
;
483 if(This
->desc
->builtin_props
[i
].id
== id
)
484 return invoke_builtin(This
, This
->desc
->builtin_props
+i
, wFlags
, pdp
, pvarRes
);
485 if(This
->desc
->builtin_props
[i
].id
< id
)
492 return DISP_E_MEMBERNOTFOUND
;
495 static HRESULT WINAPI
DispatchEx_DeleteMemberByName(IDispatchEx
*iface
, BSTR bstrName
, DWORD grfdex
)
497 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
498 FIXME("(%p)->(%s %x)\n", This
, debugstr_w(bstrName
), grfdex
);
502 static HRESULT WINAPI
DispatchEx_DeleteMemberByDispID(IDispatchEx
*iface
, DISPID id
)
504 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
505 FIXME("(%p)->(%x)\n", This
, id
);
509 static HRESULT WINAPI
DispatchEx_GetMemberProperties(IDispatchEx
*iface
, DISPID id
, DWORD grfdexFetch
, DWORD
*pgrfdex
)
511 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
512 FIXME("(%p)->(%x %x %p)\n", This
, id
, grfdexFetch
, pgrfdex
);
516 static HRESULT WINAPI
DispatchEx_GetMemberName(IDispatchEx
*iface
, DISPID id
, BSTR
*pbstrName
)
518 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
519 FIXME("(%p)->(%x %p)\n", This
, id
, pbstrName
);
523 static HRESULT WINAPI
DispatchEx_GetNextDispID(IDispatchEx
*iface
, DWORD grfdex
, DISPID id
, DISPID
*pid
)
525 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
526 FIXME("(%p)->(%x %x %p)\n", This
, grfdex
, id
, pid
);
530 static HRESULT WINAPI
DispatchEx_GetNameSpaceParent(IDispatchEx
*iface
, IUnknown
**ppunk
)
532 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
533 FIXME("(%p)->(%p)\n", This
, ppunk
);
537 static IDispatchExVtbl DispatchExVtbl
= {
538 DispatchEx_QueryInterface
,
541 DispatchEx_GetTypeInfoCount
,
542 DispatchEx_GetTypeInfo
,
543 DispatchEx_GetIDsOfNames
,
545 DispatchEx_GetDispID
,
547 DispatchEx_DeleteMemberByName
,
548 DispatchEx_DeleteMemberByDispID
,
549 DispatchEx_GetMemberProperties
,
550 DispatchEx_GetMemberName
,
551 DispatchEx_GetNextDispID
,
552 DispatchEx_GetNameSpaceParent
555 static inline vbdisp_t
*unsafe_impl_from_IDispatch(IDispatch
*iface
)
557 return iface
->lpVtbl
== (IDispatchVtbl
*)&DispatchExVtbl
558 ? CONTAINING_RECORD(iface
, vbdisp_t
, IDispatchEx_iface
)
562 HRESULT
create_vbdisp(const class_desc_t
*desc
, vbdisp_t
**ret
)
567 vbdisp
= heap_alloc_zero( FIELD_OFFSET( vbdisp_t
, props
[desc
->prop_cnt
] ));
569 return E_OUTOFMEMORY
;
571 vbdisp
->IDispatchEx_iface
.lpVtbl
= &DispatchExVtbl
;
575 list_add_tail(&desc
->ctx
->objects
, &vbdisp
->entry
);
577 if(desc
->array_cnt
) {
578 vbdisp
->arrays
= heap_alloc_zero(desc
->array_cnt
* sizeof(*vbdisp
->arrays
));
582 for(i
=0; i
< desc
->array_cnt
; i
++) {
583 if(!desc
->array_descs
[i
].dim_cnt
)
586 vbdisp
->arrays
[i
] = SafeArrayCreate(VT_VARIANT
, desc
->array_descs
[i
].dim_cnt
, desc
->array_descs
[i
].bounds
);
587 if(!vbdisp
->arrays
[i
]) {
588 hres
= E_OUTOFMEMORY
;
593 if(SUCCEEDED(hres
)) {
594 for(i
=0, j
=0; i
< desc
->prop_cnt
; i
++) {
595 if(desc
->props
[i
].is_array
) {
596 V_VT(vbdisp
->props
+i
) = VT_ARRAY
|VT_BYREF
|VT_VARIANT
;
597 V_ARRAYREF(vbdisp
->props
+i
) = vbdisp
->arrays
+ j
++;
602 hres
= E_OUTOFMEMORY
;
606 if(SUCCEEDED(hres
) && desc
->class_initialize_id
) {
608 hres
= exec_script(desc
->ctx
, desc
->funcs
[desc
->class_initialize_id
].entries
[VBDISP_CALLGET
],
613 IDispatchEx_Release(&vbdisp
->IDispatchEx_iface
);
621 static HRESULT
Procedure_invoke(vbdisp_t
*This
, VARIANT
*args
, unsigned args_cnt
, VARIANT
*res
)
623 script_ctx_t
*ctx
= This
->desc
->ctx
;
628 IActiveScriptSite_OnEnterScript(ctx
->site
);
629 hres
= exec_script(ctx
, This
->desc
->value_func
, NULL
, NULL
, NULL
);
630 IActiveScriptSite_OnLeaveScript(ctx
->site
);
635 static const builtin_prop_t procedure_props
[] = {
636 {DISPID_VALUE
, Procedure_invoke
, 0}
639 HRESULT
create_procedure_disp(script_ctx_t
*ctx
, vbscode_t
*code
, IDispatch
**ret
)
645 desc
= heap_alloc_zero(sizeof(*desc
));
647 return E_OUTOFMEMORY
;
650 desc
->builtin_prop_cnt
= sizeof(procedure_props
)/sizeof(*procedure_props
);
651 desc
->builtin_props
= procedure_props
;
652 desc
->value_func
= &code
->main_code
;
654 hres
= create_vbdisp(desc
, &vbdisp
);
660 desc
->next
= ctx
->procs
;
663 *ret
= (IDispatch
*)&vbdisp
->IDispatchEx_iface
;
667 struct _ident_map_t
{
676 static inline DISPID
ident_to_id(ScriptDisp
*This
, ident_map_t
*ident
)
678 return (ident
-This
->ident_map
)+1;
681 static inline ident_map_t
*id_to_ident(ScriptDisp
*This
, DISPID id
)
683 return 0 < id
&& id
<= This
->ident_map_cnt
? This
->ident_map
+id
-1 : NULL
;
686 static ident_map_t
*add_ident(ScriptDisp
*This
, const WCHAR
*name
)
690 if(!This
->ident_map_size
) {
691 This
->ident_map
= heap_alloc(4 * sizeof(*This
->ident_map
));
694 This
->ident_map_size
= 4;
695 }else if(This
->ident_map_cnt
== This
->ident_map_size
) {
696 ident_map_t
*new_map
;
698 new_map
= heap_realloc(This
->ident_map
, 2*This
->ident_map_size
*sizeof(*new_map
));
701 This
->ident_map
= new_map
;
702 This
->ident_map_size
*= 2;
705 ret
= This
->ident_map
+ This
->ident_map_cnt
++;
710 static inline ScriptDisp
*ScriptDisp_from_IDispatchEx(IDispatchEx
*iface
)
712 return CONTAINING_RECORD(iface
, ScriptDisp
, IDispatchEx_iface
);
715 static HRESULT WINAPI
ScriptDisp_QueryInterface(IDispatchEx
*iface
, REFIID riid
, void **ppv
)
717 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
719 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
720 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
721 *ppv
= &This
->IDispatchEx_iface
;
722 }else if(IsEqualGUID(&IID_IDispatch
, riid
)) {
723 TRACE("(%p)->(IID_IDispatch %p)\n", This
, ppv
);
724 *ppv
= &This
->IDispatchEx_iface
;
725 }else if(IsEqualGUID(&IID_IDispatchEx
, riid
)) {
726 TRACE("(%p)->(IID_IDispatchEx %p)\n", This
, ppv
);
727 *ppv
= &This
->IDispatchEx_iface
;
729 WARN("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
731 return E_NOINTERFACE
;
734 IUnknown_AddRef((IUnknown
*)*ppv
);
738 static ULONG WINAPI
ScriptDisp_AddRef(IDispatchEx
*iface
)
740 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
741 LONG ref
= InterlockedIncrement(&This
->ref
);
743 TRACE("(%p) ref=%d\n", This
, ref
);
748 static ULONG WINAPI
ScriptDisp_Release(IDispatchEx
*iface
)
750 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
751 LONG ref
= InterlockedDecrement(&This
->ref
);
753 TRACE("(%p) ref=%d\n", This
, ref
);
757 heap_free(This
->ident_map
);
764 static HRESULT WINAPI
ScriptDisp_GetTypeInfoCount(IDispatchEx
*iface
, UINT
*pctinfo
)
766 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
768 TRACE("(%p)->(%p)\n", This
, pctinfo
);
774 static HRESULT WINAPI
ScriptDisp_GetTypeInfo(IDispatchEx
*iface
, UINT iTInfo
, LCID lcid
,
777 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
778 FIXME("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
782 static HRESULT WINAPI
ScriptDisp_GetIDsOfNames(IDispatchEx
*iface
, REFIID riid
,
783 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
785 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
789 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
,
792 for(i
=0; i
< cNames
; i
++) {
793 hres
= IDispatchEx_GetDispID(&This
->IDispatchEx_iface
, rgszNames
[i
], 0, rgDispId
+i
);
801 static HRESULT WINAPI
ScriptDisp_Invoke(IDispatchEx
*iface
, DISPID dispIdMember
, REFIID riid
, LCID lcid
,
802 WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
804 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
806 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
807 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
809 return IDispatchEx_InvokeEx(&This
->IDispatchEx_iface
, dispIdMember
, lcid
, wFlags
,
810 pDispParams
, pVarResult
, pExcepInfo
, NULL
);
813 static HRESULT WINAPI
ScriptDisp_GetDispID(IDispatchEx
*iface
, BSTR bstrName
, DWORD grfdex
, DISPID
*pid
)
815 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
820 TRACE("(%p)->(%s %x %p)\n", This
, debugstr_w(bstrName
), grfdex
, pid
);
825 for(ident
= This
->ident_map
; ident
< This
->ident_map
+This
->ident_map_cnt
; ident
++) {
826 if(!strcmpiW(ident
->name
, bstrName
)) {
827 *pid
= ident_to_id(This
, ident
);
832 for(var
= This
->ctx
->global_vars
; var
; var
= var
->next
) {
833 if(!strcmpiW(var
->name
, bstrName
)) {
834 ident
= add_ident(This
, var
->name
);
836 return E_OUTOFMEMORY
;
838 ident
->is_var
= TRUE
;
840 *pid
= ident_to_id(This
, ident
);
845 for(func
= This
->ctx
->global_funcs
; func
; func
= func
->next
) {
846 if(!strcmpiW(func
->name
, bstrName
)) {
847 ident
= add_ident(This
, func
->name
);
849 return E_OUTOFMEMORY
;
851 ident
->is_var
= FALSE
;
852 ident
->u
.func
= func
;
853 *pid
= ident_to_id(This
, ident
);
859 return DISP_E_UNKNOWNNAME
;
862 static HRESULT WINAPI
ScriptDisp_InvokeEx(IDispatchEx
*iface
, DISPID id
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pdp
,
863 VARIANT
*pvarRes
, EXCEPINFO
*pei
, IServiceProvider
*pspCaller
)
865 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
869 TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This
, id
, lcid
, wFlags
, pdp
, pvarRes
, pei
, pspCaller
);
871 ident
= id_to_ident(This
, id
);
873 return DISP_E_MEMBERNOTFOUND
;
876 if(ident
->u
.var
->is_const
) {
877 FIXME("const not supported\n");
881 return invoke_variant_prop(This
->ctx
, &ident
->u
.var
->v
, wFlags
, pdp
, pvarRes
);
885 case DISPATCH_METHOD
:
886 case DISPATCH_METHOD
|DISPATCH_PROPERTYGET
:
887 IActiveScriptSite_OnEnterScript(This
->ctx
->site
);
888 hres
= exec_script(This
->ctx
, ident
->u
.func
, NULL
, pdp
, pvarRes
);
889 IActiveScriptSite_OnLeaveScript(This
->ctx
->site
);
892 FIXME("Unsupported flags %x\n", wFlags
);
899 static HRESULT WINAPI
ScriptDisp_DeleteMemberByName(IDispatchEx
*iface
, BSTR bstrName
, DWORD grfdex
)
901 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
902 FIXME("(%p)->(%s %x)\n", This
, debugstr_w(bstrName
), grfdex
);
906 static HRESULT WINAPI
ScriptDisp_DeleteMemberByDispID(IDispatchEx
*iface
, DISPID id
)
908 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
909 FIXME("(%p)->(%x)\n", This
, id
);
913 static HRESULT WINAPI
ScriptDisp_GetMemberProperties(IDispatchEx
*iface
, DISPID id
, DWORD grfdexFetch
, DWORD
*pgrfdex
)
915 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
916 FIXME("(%p)->(%x %x %p)\n", This
, id
, grfdexFetch
, pgrfdex
);
920 static HRESULT WINAPI
ScriptDisp_GetMemberName(IDispatchEx
*iface
, DISPID id
, BSTR
*pbstrName
)
922 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
923 FIXME("(%p)->(%x %p)\n", This
, id
, pbstrName
);
927 static HRESULT WINAPI
ScriptDisp_GetNextDispID(IDispatchEx
*iface
, DWORD grfdex
, DISPID id
, DISPID
*pid
)
929 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
930 FIXME("(%p)->(%x %x %p)\n", This
, grfdex
, id
, pid
);
934 static HRESULT WINAPI
ScriptDisp_GetNameSpaceParent(IDispatchEx
*iface
, IUnknown
**ppunk
)
936 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
937 FIXME("(%p)->(%p)\n", This
, ppunk
);
941 static IDispatchExVtbl ScriptDispVtbl
= {
942 ScriptDisp_QueryInterface
,
945 ScriptDisp_GetTypeInfoCount
,
946 ScriptDisp_GetTypeInfo
,
947 ScriptDisp_GetIDsOfNames
,
949 ScriptDisp_GetDispID
,
951 ScriptDisp_DeleteMemberByName
,
952 ScriptDisp_DeleteMemberByDispID
,
953 ScriptDisp_GetMemberProperties
,
954 ScriptDisp_GetMemberName
,
955 ScriptDisp_GetNextDispID
,
956 ScriptDisp_GetNameSpaceParent
959 HRESULT
create_script_disp(script_ctx_t
*ctx
, ScriptDisp
**ret
)
961 ScriptDisp
*script_disp
;
963 script_disp
= heap_alloc_zero(sizeof(*script_disp
));
965 return E_OUTOFMEMORY
;
967 script_disp
->IDispatchEx_iface
.lpVtbl
= &ScriptDispVtbl
;
968 script_disp
->ref
= 1;
969 script_disp
->ctx
= ctx
;
975 void collect_objects(script_ctx_t
*ctx
)
977 vbdisp_t
*iter
, *iter2
;
979 LIST_FOR_EACH_ENTRY_SAFE(iter
, iter2
, &ctx
->objects
, vbdisp_t
, entry
)
980 run_terminator(iter
);
982 while(!list_empty(&ctx
->objects
)) {
983 iter
= LIST_ENTRY(list_head(&ctx
->objects
), vbdisp_t
, entry
);
985 IDispatchEx_AddRef(&iter
->IDispatchEx_iface
);
988 list_remove(&iter
->entry
);
989 list_init(&iter
->entry
);
990 IDispatchEx_Release(&iter
->IDispatchEx_iface
);
994 HRESULT
disp_get_id(IDispatch
*disp
, BSTR name
, vbdisp_invoke_type_t invoke_type
, BOOL search_private
, DISPID
*id
)
1000 vbdisp
= unsafe_impl_from_IDispatch(disp
);
1002 return vbdisp_get_id(vbdisp
, name
, invoke_type
, search_private
, id
);
1004 hres
= IDispatch_QueryInterface(disp
, &IID_IDispatchEx
, (void**)&dispex
);
1006 TRACE("using IDispatch\n");
1007 return IDispatch_GetIDsOfNames(disp
, &IID_NULL
, &name
, 1, 0, id
);
1010 hres
= IDispatchEx_GetDispID(dispex
, name
, fdexNameCaseInsensitive
, id
);
1011 IDispatchEx_Release(dispex
);
1015 #define RPC_E_SERVER_UNAVAILABLE 0x800706ba
1017 HRESULT
map_hres(HRESULT hres
)
1019 if(SUCCEEDED(hres
) || HRESULT_FACILITY(hres
) == FACILITY_VBS
)
1023 case E_NOTIMPL
: return MAKE_VBSERROR(VBSE_ACTION_NOT_SUPPORTED
);
1024 case E_NOINTERFACE
: return MAKE_VBSERROR(VBSE_OLE_NOT_SUPPORTED
);
1025 case DISP_E_UNKNOWNINTERFACE
: return MAKE_VBSERROR(VBSE_OLE_NO_PROP_OR_METHOD
);
1026 case DISP_E_MEMBERNOTFOUND
: return MAKE_VBSERROR(VBSE_OLE_NO_PROP_OR_METHOD
);
1027 case DISP_E_PARAMNOTFOUND
: return MAKE_VBSERROR(VBSE_NAMED_PARAM_NOT_FOUND
);
1028 case DISP_E_TYPEMISMATCH
: return MAKE_VBSERROR(VBSE_TYPE_MISMATCH
);
1029 case DISP_E_UNKNOWNNAME
: return MAKE_VBSERROR(VBSE_OLE_NO_PROP_OR_METHOD
);
1030 case DISP_E_NONAMEDARGS
: return MAKE_VBSERROR(VBSE_NAMED_ARGS_NOT_SUPPORTED
);
1031 case DISP_E_BADVARTYPE
: return MAKE_VBSERROR(VBSE_INVALID_TYPELIB_VARIABLE
);
1032 case DISP_E_OVERFLOW
: return MAKE_VBSERROR(VBSE_OVERFLOW
);
1033 case DISP_E_BADINDEX
: return MAKE_VBSERROR(VBSE_OUT_OF_BOUNDS
);
1034 case DISP_E_UNKNOWNLCID
: return MAKE_VBSERROR(VBSE_LOCALE_SETTING_NOT_SUPPORTED
);
1035 case DISP_E_ARRAYISLOCKED
: return MAKE_VBSERROR(VBSE_ARRAY_LOCKED
);
1036 case DISP_E_BADPARAMCOUNT
: return MAKE_VBSERROR(VBSE_FUNC_ARITY_MISMATCH
);
1037 case DISP_E_PARAMNOTOPTIONAL
: return MAKE_VBSERROR(VBSE_PARAMETER_NOT_OPTIONAL
);
1038 case DISP_E_NOTACOLLECTION
: return MAKE_VBSERROR(VBSE_NOT_ENUM
);
1039 case TYPE_E_DLLFUNCTIONNOTFOUND
: return MAKE_VBSERROR(VBSE_INVALID_DLL_FUNCTION_NAME
);
1040 case TYPE_E_TYPEMISMATCH
: return MAKE_VBSERROR(VBSE_TYPE_MISMATCH
);
1041 case TYPE_E_OUTOFBOUNDS
: return MAKE_VBSERROR(VBSE_OUT_OF_BOUNDS
);
1042 case TYPE_E_IOERROR
: return MAKE_VBSERROR(VBSE_IO_ERROR
);
1043 case TYPE_E_CANTCREATETMPFILE
: return MAKE_VBSERROR(VBSE_CANT_CREATE_TMP_FILE
);
1044 case STG_E_FILENOTFOUND
: return MAKE_VBSERROR(VBSE_OLE_FILE_NOT_FOUND
);
1045 case STG_E_PATHNOTFOUND
: return MAKE_VBSERROR(VBSE_PATH_NOT_FOUND
);
1046 case STG_E_TOOMANYOPENFILES
: return MAKE_VBSERROR(VBSE_TOO_MANY_FILES
);
1047 case STG_E_ACCESSDENIED
: return MAKE_VBSERROR(VBSE_PERMISSION_DENIED
);
1048 case STG_E_INSUFFICIENTMEMORY
: return MAKE_VBSERROR(VBSE_OUT_OF_MEMORY
);
1049 case STG_E_NOMOREFILES
: return MAKE_VBSERROR(VBSE_TOO_MANY_FILES
);
1050 case STG_E_DISKISWRITEPROTECTED
: return MAKE_VBSERROR(VBSE_PERMISSION_DENIED
);
1051 case STG_E_WRITEFAULT
: return MAKE_VBSERROR(VBSE_IO_ERROR
);
1052 case STG_E_READFAULT
: return MAKE_VBSERROR(VBSE_IO_ERROR
);
1053 case STG_E_SHAREVIOLATION
: return MAKE_VBSERROR(VBSE_PATH_FILE_ACCESS
);
1054 case STG_E_LOCKVIOLATION
: return MAKE_VBSERROR(VBSE_PERMISSION_DENIED
);
1055 case STG_E_FILEALREADYEXISTS
: return MAKE_VBSERROR(VBSE_FILE_ALREADY_EXISTS
);
1056 case STG_E_MEDIUMFULL
: return MAKE_VBSERROR(VBSE_DISK_FULL
);
1057 case STG_E_INVALIDNAME
: return MAKE_VBSERROR(VBSE_FILE_NOT_FOUND
);
1058 case STG_E_INUSE
: return MAKE_VBSERROR(VBSE_PERMISSION_DENIED
);
1059 case STG_E_NOTCURRENT
: return MAKE_VBSERROR(VBSE_PERMISSION_DENIED
);
1060 case STG_E_CANTSAVE
: return MAKE_VBSERROR(VBSE_IO_ERROR
);
1061 case REGDB_E_CLASSNOTREG
: return MAKE_VBSERROR(VBSE_CANT_CREATE_OBJECT
);
1062 case MK_E_UNAVAILABLE
: return MAKE_VBSERROR(VBSE_CANT_CREATE_OBJECT
);
1063 case MK_E_INVALIDEXTENSION
: return MAKE_VBSERROR(VBSE_OLE_FILE_NOT_FOUND
);
1064 case MK_E_CANTOPENFILE
: return MAKE_VBSERROR(VBSE_OLE_FILE_NOT_FOUND
);
1065 case CO_E_CLASSSTRING
: return MAKE_VBSERROR(VBSE_CANT_CREATE_OBJECT
);
1066 case CO_E_APPNOTFOUND
: return MAKE_VBSERROR(VBSE_CANT_CREATE_OBJECT
);
1067 case CO_E_APPDIDNTREG
: return MAKE_VBSERROR(VBSE_CANT_CREATE_OBJECT
);
1068 case E_ACCESSDENIED
: return MAKE_VBSERROR(VBSE_PERMISSION_DENIED
);
1069 case E_OUTOFMEMORY
: return MAKE_VBSERROR(VBSE_OUT_OF_MEMORY
);
1070 case E_INVALIDARG
: return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL
);
1071 case RPC_E_SERVER_UNAVAILABLE
: return MAKE_VBSERROR(VBSE_SERVER_NOT_FOUND
);
1072 case CO_E_SERVER_EXEC_FAILURE
: return MAKE_VBSERROR(VBSE_CANT_CREATE_OBJECT
);
1078 HRESULT
disp_call(script_ctx_t
*ctx
, IDispatch
*disp
, DISPID id
, DISPPARAMS
*dp
, VARIANT
*retv
)
1080 const WORD flags
= DISPATCH_METHOD
|(retv
? DISPATCH_PROPERTYGET
: 0);
1081 IDispatchEx
*dispex
;
1085 memset(&ei
, 0, sizeof(ei
));
1087 V_VT(retv
) = VT_EMPTY
;
1089 hres
= IDispatch_QueryInterface(disp
, &IID_IDispatchEx
, (void**)&dispex
);
1093 TRACE("using IDispatch\n");
1094 return IDispatch_Invoke(disp
, id
, &IID_NULL
, ctx
->lcid
, flags
, dp
, retv
, &ei
, &err
);
1097 hres
= IDispatchEx_InvokeEx(dispex
, id
, ctx
->lcid
, flags
, dp
, retv
, &ei
, NULL
/* CALLER_FIXME */);
1098 IDispatchEx_Release(dispex
);
1102 HRESULT
get_disp_value(script_ctx_t
*ctx
, IDispatch
*disp
, VARIANT
*v
)
1104 DISPPARAMS dp
= {NULL
};
1105 return disp_call(ctx
, disp
, DISPID_VALUE
, &dp
, v
);
1108 HRESULT
disp_propput(script_ctx_t
*ctx
, IDispatch
*disp
, DISPID id
, WORD flags
, DISPPARAMS
*dp
)
1110 IDispatchEx
*dispex
;
1114 hres
= IDispatch_QueryInterface(disp
, &IID_IDispatchEx
, (void**)&dispex
);
1115 if(SUCCEEDED(hres
)) {
1116 hres
= IDispatchEx_InvokeEx(dispex
, id
, ctx
->lcid
, flags
, dp
, NULL
, &ei
, NULL
/* FIXME! */);
1117 IDispatchEx_Release(dispex
);
1121 TRACE("using IDispatch\n");
1122 hres
= IDispatch_Invoke(disp
, id
, &IID_NULL
, ctx
->lcid
, flags
, dp
, NULL
, &ei
, &err
);