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 static const GUID GUID_VBScriptTypeInfo
= {0xc59c6b12,0xf6c1,0x11cf,{0x88,0x35,0x00,0xa0,0xc9,0x11,0xe8,0xb2}};
29 #define DISPID_FUNCTION_MASK 0x20000000
30 #define FDEX_VERSION_MASK 0xf0000000
32 static inline BOOL
is_func_id(vbdisp_t
*This
, DISPID id
)
34 return id
< This
->desc
->func_cnt
;
37 static BOOL
get_func_id(vbdisp_t
*This
, const WCHAR
*name
, vbdisp_invoke_type_t invoke_type
, BOOL search_private
, DISPID
*id
)
41 for(i
= invoke_type
== VBDISP_ANY
? 0 : 1; i
< This
->desc
->func_cnt
; i
++) {
42 if(invoke_type
== VBDISP_ANY
) {
43 if(!search_private
&& !This
->desc
->funcs
[i
].is_public
)
45 if(!i
&& !This
->desc
->funcs
[0].name
) /* default value may not exist */
48 if(!This
->desc
->funcs
[i
].entries
[invoke_type
]
49 || (!search_private
&& !This
->desc
->funcs
[i
].entries
[invoke_type
]->is_public
))
53 if(!wcsicmp(This
->desc
->funcs
[i
].name
, name
)) {
62 HRESULT
vbdisp_get_id(vbdisp_t
*This
, BSTR name
, vbdisp_invoke_type_t invoke_type
, BOOL search_private
, DISPID
*id
)
66 if(get_func_id(This
, name
, invoke_type
, search_private
, id
))
69 for(i
=0; i
< This
->desc
->prop_cnt
; i
++) {
70 if(!search_private
&& !This
->desc
->props
[i
].is_public
)
73 if(!wcsicmp(This
->desc
->props
[i
].name
, name
)) {
74 *id
= i
+ This
->desc
->func_cnt
;
80 return DISP_E_UNKNOWNNAME
;
83 static HRESULT
get_propput_arg(script_ctx_t
*ctx
, const DISPPARAMS
*dp
, WORD flags
, VARIANT
*v
, BOOL
*is_owned
)
87 for(i
=0; i
< dp
->cNamedArgs
; i
++) {
88 if(dp
->rgdispidNamedArgs
[i
] == DISPID_PROPERTYPUT
)
91 if(i
== dp
->cNamedArgs
) {
92 WARN("no value to set\n");
93 return DISP_E_PARAMNOTOPTIONAL
;
97 if(V_VT(v
) == (VT_VARIANT
|VT_BYREF
))
98 *v
= *V_VARIANTREF(v
);
101 if(V_VT(v
) == VT_DISPATCH
) {
102 if(!(flags
& DISPATCH_PROPERTYPUTREF
)) {
105 hres
= get_disp_value(ctx
, V_DISPATCH(v
), v
);
111 }else if(!(flags
& DISPATCH_PROPERTYPUT
)) {
112 WARN("%s can't be assigned without DISPATCH_PROPERTYPUT flag\n", debugstr_variant(v
));
113 return DISP_E_EXCEPTION
;
119 static HRESULT
invoke_variant_prop(script_ctx_t
*ctx
, VARIANT
*v
, WORD flags
, DISPPARAMS
*dp
, VARIANT
*res
)
124 case DISPATCH_PROPERTYGET
|DISPATCH_METHOD
:
125 case DISPATCH_PROPERTYGET
:
127 WARN("called with arguments\n");
128 return DISP_E_MEMBERNOTFOUND
; /* That's what tests show */
131 hres
= VariantCopyInd(res
, v
);
134 case DISPATCH_PROPERTYPUT
:
135 case DISPATCH_PROPERTYPUTREF
:
136 case DISPATCH_PROPERTYPUT
|DISPATCH_PROPERTYPUTREF
: {
140 hres
= get_propput_arg(ctx
, dp
, flags
, &put_val
, &own_val
);
145 FIXME("Arguments not supported\n");
150 V_VT(res
) = VT_EMPTY
;
155 hres
= VariantCopyInd(v
, &put_val
);
160 FIXME("unimplemented flags %x\n", flags
);
167 static HRESULT
invoke_vbdisp(vbdisp_t
*This
, DISPID id
, DWORD flags
, BOOL extern_caller
, DISPPARAMS
*params
, VARIANT
*res
)
170 return DISP_E_MEMBERNOTFOUND
;
172 if(is_func_id(This
, id
)) {
175 TRACE("%p->%s\n", This
, debugstr_w(This
->desc
->funcs
[id
].name
));
178 case DISPATCH_PROPERTYGET
:
179 func
= This
->desc
->funcs
[id
].entries
[VBDISP_CALLGET
];
180 if(!func
|| (func
->type
!= FUNC_PROPGET
&& func
->type
!= FUNC_DEFGET
)) {
182 return DISP_E_MEMBERNOTFOUND
;
185 return exec_script(This
->desc
->ctx
, extern_caller
, func
, This
, params
, res
);
187 case DISPATCH_METHOD
:
188 case DISPATCH_METHOD
|DISPATCH_PROPERTYGET
:
189 func
= This
->desc
->funcs
[id
].entries
[VBDISP_CALLGET
];
191 FIXME("no invoke/getter\n");
192 return DISP_E_MEMBERNOTFOUND
;
195 return exec_script(This
->desc
->ctx
, extern_caller
, func
, This
, params
, res
);
197 case DISPATCH_PROPERTYPUT
:
198 case DISPATCH_PROPERTYPUTREF
:
199 case DISPATCH_PROPERTYPUT
|DISPATCH_PROPERTYPUTREF
: {
200 DISPPARAMS dp
= {NULL
, NULL
, 1, 0};
205 if(arg_cnt(params
)) {
206 FIXME("arguments not implemented\n");
210 hres
= get_propput_arg(This
->desc
->ctx
, params
, flags
, &put_val
, &needs_release
);
214 dp
.rgvarg
= &put_val
;
215 func
= This
->desc
->funcs
[id
].entries
[V_VT(&put_val
) == VT_DISPATCH
? VBDISP_SET
: VBDISP_LET
];
217 FIXME("no letter/setter\n");
218 return DISP_E_MEMBERNOTFOUND
;
221 hres
= exec_script(This
->desc
->ctx
, extern_caller
, func
, This
, &dp
, NULL
);
223 VariantClear(&put_val
);
227 FIXME("flags %x\n", flags
);
228 return DISP_E_MEMBERNOTFOUND
;
232 if(id
>= This
->desc
->prop_cnt
+ This
->desc
->func_cnt
)
233 return DISP_E_MEMBERNOTFOUND
;
235 TRACE("%p->%s\n", This
, debugstr_w(This
->desc
->props
[id
- This
->desc
->func_cnt
].name
));
236 return invoke_variant_prop(This
->desc
->ctx
, This
->props
+(id
-This
->desc
->func_cnt
), flags
, params
, res
);
239 static BOOL
run_terminator(vbdisp_t
*This
)
243 if(This
->terminator_ran
)
245 This
->terminator_ran
= TRUE
;
247 if(!This
->desc
->class_terminate_id
)
251 exec_script(This
->desc
->ctx
, FALSE
, This
->desc
->funcs
[This
->desc
->class_terminate_id
].entries
[VBDISP_CALLGET
],
256 static void clean_props(vbdisp_t
*This
)
263 for(i
=0; i
< This
->desc
->array_cnt
; i
++) {
264 if(This
->arrays
[i
]) {
265 SafeArrayDestroy(This
->arrays
[i
]);
266 This
->arrays
[i
] = NULL
;
270 for(i
=0; i
< This
->desc
->prop_cnt
; i
++)
271 VariantClear(This
->props
+i
);
274 static inline vbdisp_t
*impl_from_IDispatchEx(IDispatchEx
*iface
)
276 return CONTAINING_RECORD(iface
, vbdisp_t
, IDispatchEx_iface
);
279 static HRESULT WINAPI
DispatchEx_QueryInterface(IDispatchEx
*iface
, REFIID riid
, void **ppv
)
281 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
283 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
284 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
285 *ppv
= &This
->IDispatchEx_iface
;
286 }else if(IsEqualGUID(&IID_IDispatch
, riid
)) {
287 TRACE("(%p)->(IID_IDispatch %p)\n", This
, ppv
);
288 *ppv
= &This
->IDispatchEx_iface
;
289 }else if(IsEqualGUID(&IID_IDispatchEx
, riid
)) {
290 TRACE("(%p)->(IID_IDispatchEx %p)\n", This
, ppv
);
291 *ppv
= &This
->IDispatchEx_iface
;
293 WARN("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
295 return E_NOINTERFACE
;
298 IUnknown_AddRef((IUnknown
*)*ppv
);
302 static ULONG WINAPI
DispatchEx_AddRef(IDispatchEx
*iface
)
304 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
305 LONG ref
= InterlockedIncrement(&This
->ref
);
307 TRACE("(%p) ref=%d\n", This
, ref
);
312 static ULONG WINAPI
DispatchEx_Release(IDispatchEx
*iface
)
314 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
315 LONG ref
= InterlockedDecrement(&This
->ref
);
317 TRACE("(%p) ref=%d\n", This
, ref
);
319 if(!ref
&& run_terminator(This
)) {
321 list_remove(&This
->entry
);
322 heap_free(This
->arrays
);
329 static HRESULT WINAPI
DispatchEx_GetTypeInfoCount(IDispatchEx
*iface
, UINT
*pctinfo
)
331 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
333 TRACE("(%p)->(%p)\n", This
, pctinfo
);
339 static HRESULT WINAPI
DispatchEx_GetTypeInfo(IDispatchEx
*iface
, UINT iTInfo
, LCID lcid
,
342 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
343 FIXME("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
347 static HRESULT WINAPI
DispatchEx_GetIDsOfNames(IDispatchEx
*iface
, REFIID riid
,
348 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
,
351 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
352 FIXME("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
,
357 static HRESULT WINAPI
DispatchEx_Invoke(IDispatchEx
*iface
, DISPID dispIdMember
,
358 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
,
359 VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
361 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
363 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
364 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
366 return IDispatchEx_InvokeEx(&This
->IDispatchEx_iface
, dispIdMember
, lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, NULL
);
369 static HRESULT WINAPI
DispatchEx_GetDispID(IDispatchEx
*iface
, BSTR bstrName
, DWORD grfdex
, DISPID
*pid
)
371 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
373 TRACE("(%p)->(%s %x %p)\n", This
, debugstr_w(bstrName
), grfdex
, pid
);
375 grfdex
&= ~FDEX_VERSION_MASK
;
380 /* Tests show that fdexNameCaseSensitive is ignored */
382 if(grfdex
& ~(fdexNameEnsure
|fdexNameCaseInsensitive
|fdexNameCaseSensitive
)) {
383 FIXME("unsupported flags %x\n", grfdex
);
387 return vbdisp_get_id(This
, bstrName
, VBDISP_ANY
, FALSE
, pid
);
390 static HRESULT WINAPI
DispatchEx_InvokeEx(IDispatchEx
*iface
, DISPID id
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pdp
,
391 VARIANT
*pvarRes
, EXCEPINFO
*pei
, IServiceProvider
*pspCaller
)
393 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
395 TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This
, id
, lcid
, wFlags
, pdp
, pvarRes
, pei
, pspCaller
);
401 V_VT(pvarRes
) = VT_EMPTY
;
403 return invoke_vbdisp(This
, id
, wFlags
, TRUE
, pdp
, pvarRes
);
406 static HRESULT WINAPI
DispatchEx_DeleteMemberByName(IDispatchEx
*iface
, BSTR bstrName
, DWORD grfdex
)
408 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
409 FIXME("(%p)->(%s %x)\n", This
, debugstr_w(bstrName
), grfdex
);
413 static HRESULT WINAPI
DispatchEx_DeleteMemberByDispID(IDispatchEx
*iface
, DISPID id
)
415 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
416 FIXME("(%p)->(%x)\n", This
, id
);
420 static HRESULT WINAPI
DispatchEx_GetMemberProperties(IDispatchEx
*iface
, DISPID id
, DWORD grfdexFetch
, DWORD
*pgrfdex
)
422 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
423 FIXME("(%p)->(%x %x %p)\n", This
, id
, grfdexFetch
, pgrfdex
);
427 static HRESULT WINAPI
DispatchEx_GetMemberName(IDispatchEx
*iface
, DISPID id
, BSTR
*pbstrName
)
429 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
430 FIXME("(%p)->(%x %p)\n", This
, id
, pbstrName
);
434 static HRESULT WINAPI
DispatchEx_GetNextDispID(IDispatchEx
*iface
, DWORD grfdex
, DISPID id
, DISPID
*pid
)
436 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
437 FIXME("(%p)->(%x %x %p)\n", This
, grfdex
, id
, pid
);
441 static HRESULT WINAPI
DispatchEx_GetNameSpaceParent(IDispatchEx
*iface
, IUnknown
**ppunk
)
443 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
444 FIXME("(%p)->(%p)\n", This
, ppunk
);
448 static IDispatchExVtbl DispatchExVtbl
= {
449 DispatchEx_QueryInterface
,
452 DispatchEx_GetTypeInfoCount
,
453 DispatchEx_GetTypeInfo
,
454 DispatchEx_GetIDsOfNames
,
456 DispatchEx_GetDispID
,
458 DispatchEx_DeleteMemberByName
,
459 DispatchEx_DeleteMemberByDispID
,
460 DispatchEx_GetMemberProperties
,
461 DispatchEx_GetMemberName
,
462 DispatchEx_GetNextDispID
,
463 DispatchEx_GetNameSpaceParent
466 static inline vbdisp_t
*unsafe_impl_from_IDispatch(IDispatch
*iface
)
468 return iface
->lpVtbl
== (IDispatchVtbl
*)&DispatchExVtbl
469 ? CONTAINING_RECORD(iface
, vbdisp_t
, IDispatchEx_iface
)
473 HRESULT
create_vbdisp(const class_desc_t
*desc
, vbdisp_t
**ret
)
478 vbdisp
= heap_alloc_zero( FIELD_OFFSET( vbdisp_t
, props
[desc
->prop_cnt
] ));
480 return E_OUTOFMEMORY
;
482 vbdisp
->IDispatchEx_iface
.lpVtbl
= &DispatchExVtbl
;
486 list_add_tail(&desc
->ctx
->objects
, &vbdisp
->entry
);
488 if(desc
->array_cnt
) {
489 vbdisp
->arrays
= heap_alloc_zero(desc
->array_cnt
* sizeof(*vbdisp
->arrays
));
493 for(i
=0; i
< desc
->array_cnt
; i
++) {
494 if(!desc
->array_descs
[i
].dim_cnt
)
497 vbdisp
->arrays
[i
] = SafeArrayCreate(VT_VARIANT
, desc
->array_descs
[i
].dim_cnt
, desc
->array_descs
[i
].bounds
);
498 if(!vbdisp
->arrays
[i
]) {
499 hres
= E_OUTOFMEMORY
;
504 if(SUCCEEDED(hres
)) {
505 for(i
=0, j
=0; i
< desc
->prop_cnt
; i
++) {
506 if(desc
->props
[i
].is_array
) {
507 V_VT(vbdisp
->props
+i
) = VT_ARRAY
|VT_BYREF
|VT_VARIANT
;
508 V_ARRAYREF(vbdisp
->props
+i
) = vbdisp
->arrays
+ j
++;
513 hres
= E_OUTOFMEMORY
;
517 if(SUCCEEDED(hres
) && desc
->class_initialize_id
) {
519 hres
= exec_script(desc
->ctx
, FALSE
, desc
->funcs
[desc
->class_initialize_id
].entries
[VBDISP_CALLGET
],
524 IDispatchEx_Release(&vbdisp
->IDispatchEx_iface
);
532 struct typeinfo_func
{
538 ITypeInfo ITypeInfo_iface
;
539 ITypeComp ITypeComp_iface
;
544 struct typeinfo_func
*funcs
;
549 static function_t
*get_func_from_memid(const ScriptTypeInfo
*typeinfo
, MEMBERID memid
)
551 UINT a
= 0, b
= typeinfo
->num_funcs
;
553 if (!(memid
& DISPID_FUNCTION_MASK
)) return NULL
;
557 UINT i
= (a
+ b
- 1) / 2;
559 if (memid
== typeinfo
->funcs
[i
].memid
)
560 return typeinfo
->funcs
[i
].func
;
561 else if (memid
< typeinfo
->funcs
[i
].memid
)
569 static inline ScriptTypeInfo
*ScriptTypeInfo_from_ITypeInfo(ITypeInfo
*iface
)
571 return CONTAINING_RECORD(iface
, ScriptTypeInfo
, ITypeInfo_iface
);
574 static inline ScriptTypeInfo
*ScriptTypeInfo_from_ITypeComp(ITypeComp
*iface
)
576 return CONTAINING_RECORD(iface
, ScriptTypeInfo
, ITypeComp_iface
);
579 static HRESULT WINAPI
ScriptTypeInfo_QueryInterface(ITypeInfo
*iface
, REFIID riid
, void **ppv
)
581 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
583 if (IsEqualGUID(&IID_IUnknown
, riid
) || IsEqualGUID(&IID_ITypeInfo
, riid
))
584 *ppv
= &This
->ITypeInfo_iface
;
585 else if (IsEqualGUID(&IID_ITypeComp
, riid
))
586 *ppv
= &This
->ITypeComp_iface
;
589 WARN("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
591 return E_NOINTERFACE
;
594 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
595 IUnknown_AddRef((IUnknown
*)*ppv
);
599 static ULONG WINAPI
ScriptTypeInfo_AddRef(ITypeInfo
*iface
)
601 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
602 LONG ref
= InterlockedIncrement(&This
->ref
);
604 TRACE("(%p) ref=%d\n", This
, ref
);
609 static ULONG WINAPI
ScriptTypeInfo_Release(ITypeInfo
*iface
)
611 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
612 LONG ref
= InterlockedDecrement(&This
->ref
);
615 TRACE("(%p) ref=%d\n", This
, ref
);
619 for (i
= 0; i
< This
->num_funcs
; i
++)
620 release_vbscode(This
->funcs
[i
].func
->code_ctx
);
622 IDispatchEx_Release(&This
->disp
->IDispatchEx_iface
);
623 heap_free(This
->funcs
);
629 static HRESULT WINAPI
ScriptTypeInfo_GetTypeAttr(ITypeInfo
*iface
, TYPEATTR
**ppTypeAttr
)
631 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
634 TRACE("(%p)->(%p)\n", This
, ppTypeAttr
);
636 if (!ppTypeAttr
) return E_INVALIDARG
;
638 attr
= heap_alloc_zero(sizeof(*attr
));
639 if (!attr
) return E_OUTOFMEMORY
;
641 attr
->guid
= GUID_VBScriptTypeInfo
;
642 attr
->lcid
= LOCALE_USER_DEFAULT
;
643 attr
->memidConstructor
= MEMBERID_NIL
;
644 attr
->memidDestructor
= MEMBERID_NIL
;
645 attr
->cbSizeInstance
= 4;
646 attr
->typekind
= TKIND_DISPATCH
;
647 attr
->cFuncs
= This
->num_funcs
;
648 attr
->cVars
= This
->num_vars
;
649 attr
->cImplTypes
= 1;
650 attr
->cbSizeVft
= sizeof(IDispatchVtbl
);
651 attr
->cbAlignment
= 4;
652 attr
->wTypeFlags
= TYPEFLAG_FDISPATCHABLE
;
653 attr
->wMajorVerNum
= VBSCRIPT_MAJOR_VERSION
;
654 attr
->wMinorVerNum
= VBSCRIPT_MINOR_VERSION
;
660 static HRESULT WINAPI
ScriptTypeInfo_GetTypeComp(ITypeInfo
*iface
, ITypeComp
**ppTComp
)
662 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
664 TRACE("(%p)->(%p)\n", This
, ppTComp
);
666 if (!ppTComp
) return E_INVALIDARG
;
668 *ppTComp
= &This
->ITypeComp_iface
;
669 ITypeInfo_AddRef(iface
);
673 static HRESULT WINAPI
ScriptTypeInfo_GetFuncDesc(ITypeInfo
*iface
, UINT index
, FUNCDESC
**ppFuncDesc
)
675 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
680 TRACE("(%p)->(%u %p)\n", This
, index
, ppFuncDesc
);
682 if (!ppFuncDesc
) return E_INVALIDARG
;
683 if (index
>= This
->num_funcs
) return TYPE_E_ELEMENTNOTFOUND
;
684 func
= This
->funcs
[index
].func
;
686 /* Store the parameter array after the FUNCDESC structure */
687 desc
= heap_alloc_zero(sizeof(*desc
) + sizeof(ELEMDESC
) * func
->arg_cnt
);
688 if (!desc
) return E_OUTOFMEMORY
;
690 desc
->memid
= This
->funcs
[index
].memid
;
691 desc
->funckind
= FUNC_DISPATCH
;
692 desc
->invkind
= INVOKE_FUNC
;
693 desc
->callconv
= CC_STDCALL
;
694 desc
->cParams
= func
->arg_cnt
;
695 desc
->elemdescFunc
.tdesc
.vt
= (func
->type
== FUNC_SUB
) ? VT_VOID
: VT_VARIANT
;
697 if (func
->arg_cnt
) desc
->lprgelemdescParam
= (ELEMDESC
*)(desc
+ 1);
698 for (i
= 0; i
< func
->arg_cnt
; i
++)
699 desc
->lprgelemdescParam
[i
].tdesc
.vt
= VT_VARIANT
;
705 static HRESULT WINAPI
ScriptTypeInfo_GetVarDesc(ITypeInfo
*iface
, UINT index
, VARDESC
**ppVarDesc
)
707 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
710 TRACE("(%p)->(%u %p)\n", This
, index
, ppVarDesc
);
712 if (!ppVarDesc
) return E_INVALIDARG
;
713 if (index
>= This
->num_vars
) return TYPE_E_ELEMENTNOTFOUND
;
715 desc
= heap_alloc_zero(sizeof(*desc
));
716 if (!desc
) return E_OUTOFMEMORY
;
718 desc
->memid
= index
+ 1;
719 desc
->varkind
= VAR_DISPATCH
;
720 desc
->elemdescVar
.tdesc
.vt
= VT_VARIANT
;
726 static HRESULT WINAPI
ScriptTypeInfo_GetNames(ITypeInfo
*iface
, MEMBERID memid
, BSTR
*rgBstrNames
,
727 UINT cMaxNames
, UINT
*pcNames
)
729 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
730 ITypeInfo
*disp_typeinfo
;
735 TRACE("(%p)->(%d %p %u %p)\n", This
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
737 if (!rgBstrNames
|| !pcNames
) return E_INVALIDARG
;
738 if (memid
<= 0) return TYPE_E_ELEMENTNOTFOUND
;
740 func
= get_func_from_memid(This
, memid
);
741 if (!func
&& memid
> This
->num_vars
)
743 hr
= get_dispatch_typeinfo(&disp_typeinfo
);
744 if (FAILED(hr
)) return hr
;
746 return ITypeInfo_GetNames(disp_typeinfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
750 if (!cMaxNames
) return S_OK
;
754 UINT num
= min(cMaxNames
, func
->arg_cnt
+ 1);
756 rgBstrNames
[0] = SysAllocString(func
->name
);
757 if (!rgBstrNames
[0]) return E_OUTOFMEMORY
;
759 for (i
= 1; i
< num
; i
++)
761 if (!(rgBstrNames
[i
] = SysAllocString(func
->args
[i
- 1].name
)))
763 do SysFreeString(rgBstrNames
[--i
]); while (i
);
764 return E_OUTOFMEMORY
;
770 rgBstrNames
[0] = SysAllocString(This
->disp
->global_vars
[memid
- 1]->name
);
771 if (!rgBstrNames
[0]) return E_OUTOFMEMORY
;
779 static HRESULT WINAPI
ScriptTypeInfo_GetRefTypeOfImplType(ITypeInfo
*iface
, UINT index
, HREFTYPE
*pRefType
)
781 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
783 TRACE("(%p)->(%u %p)\n", This
, index
, pRefType
);
785 /* We only inherit from IDispatch */
786 if (!pRefType
) return E_INVALIDARG
;
787 if (index
!= 0) return TYPE_E_ELEMENTNOTFOUND
;
793 static HRESULT WINAPI
ScriptTypeInfo_GetImplTypeFlags(ITypeInfo
*iface
, UINT index
, INT
*pImplTypeFlags
)
795 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
797 TRACE("(%p)->(%u %p)\n", This
, index
, pImplTypeFlags
);
799 if (!pImplTypeFlags
) return E_INVALIDARG
;
800 if (index
!= 0) return TYPE_E_ELEMENTNOTFOUND
;
806 static HRESULT WINAPI
ScriptTypeInfo_GetIDsOfNames(ITypeInfo
*iface
, LPOLESTR
*rgszNames
, UINT cNames
,
809 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
810 ITypeInfo
*disp_typeinfo
;
815 TRACE("(%p)->(%p %u %p)\n", This
, rgszNames
, cNames
, pMemId
);
817 if (!rgszNames
|| !cNames
|| !pMemId
) return E_INVALIDARG
;
819 for (i
= 0; i
< cNames
; i
++) pMemId
[i
] = MEMBERID_NIL
;
822 for (i
= 0; i
< This
->num_funcs
; i
++)
824 function_t
*func
= This
->funcs
[i
].func
;
826 if (wcsicmp(name
, func
->name
)) continue;
827 pMemId
[0] = This
->funcs
[i
].memid
;
829 for (j
= 1; j
< cNames
; j
++)
832 for (arg
= func
->arg_cnt
; --arg
>= 0;)
833 if (!wcsicmp(name
, func
->args
[arg
].name
))
838 hr
= DISP_E_UNKNOWNNAME
;
843 for (i
= 0; i
< This
->num_vars
; i
++)
845 if (wcsicmp(name
, This
->disp
->global_vars
[i
]->name
)) continue;
850 /* Look into the inherited IDispatch */
851 hr
= get_dispatch_typeinfo(&disp_typeinfo
);
852 if (FAILED(hr
)) return hr
;
854 return ITypeInfo_GetIDsOfNames(disp_typeinfo
, rgszNames
, cNames
, pMemId
);
857 static HRESULT WINAPI
ScriptTypeInfo_Invoke(ITypeInfo
*iface
, PVOID pvInstance
, MEMBERID memid
, WORD wFlags
,
858 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
860 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
861 ITypeInfo
*disp_typeinfo
;
865 TRACE("(%p)->(%p %d %d %p %p %p %p)\n", This
, pvInstance
, memid
, wFlags
,
866 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
868 if (!pvInstance
) return E_INVALIDARG
;
869 if (memid
<= 0) return TYPE_E_ELEMENTNOTFOUND
;
871 if (!get_func_from_memid(This
, memid
) && memid
> This
->num_vars
)
873 hr
= get_dispatch_typeinfo(&disp_typeinfo
);
874 if (FAILED(hr
)) return hr
;
876 return ITypeInfo_Invoke(disp_typeinfo
, pvInstance
, memid
, wFlags
, pDispParams
,
877 pVarResult
, pExcepInfo
, puArgErr
);
880 hr
= IUnknown_QueryInterface((IUnknown
*)pvInstance
, &IID_IDispatch
, (void**)&disp
);
881 if (FAILED(hr
)) return hr
;
883 hr
= IDispatch_Invoke(disp
, memid
, &IID_NULL
, LOCALE_USER_DEFAULT
, wFlags
,
884 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
885 IDispatch_Release(disp
);
890 static HRESULT WINAPI
ScriptTypeInfo_GetDocumentation(ITypeInfo
*iface
, MEMBERID memid
, BSTR
*pBstrName
,
891 BSTR
*pBstrDocString
, DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
893 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
894 ITypeInfo
*disp_typeinfo
;
898 TRACE("(%p)->(%d %p %p %p %p)\n", This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
900 if (pBstrDocString
) *pBstrDocString
= NULL
;
901 if (pdwHelpContext
) *pdwHelpContext
= 0;
902 if (pBstrHelpFile
) *pBstrHelpFile
= NULL
;
904 if (memid
== MEMBERID_NIL
)
906 if (pBstrName
&& !(*pBstrName
= SysAllocString(L
"VBScriptTypeInfo")))
907 return E_OUTOFMEMORY
;
908 if (pBstrDocString
&&
909 !(*pBstrDocString
= SysAllocString(L
"Visual Basic Scripting Type Info")))
911 if (pBstrName
) SysFreeString(*pBstrName
);
912 return E_OUTOFMEMORY
;
916 if (memid
<= 0) return TYPE_E_ELEMENTNOTFOUND
;
918 func
= get_func_from_memid(This
, memid
);
919 if (!func
&& memid
> This
->num_vars
)
921 hr
= get_dispatch_typeinfo(&disp_typeinfo
);
922 if (FAILED(hr
)) return hr
;
924 return ITypeInfo_GetDocumentation(disp_typeinfo
, memid
, pBstrName
, pBstrDocString
,
925 pdwHelpContext
, pBstrHelpFile
);
930 *pBstrName
= SysAllocString(func
? func
->name
: This
->disp
->global_vars
[memid
- 1]->name
);
931 if (!*pBstrName
) return E_OUTOFMEMORY
;
936 static HRESULT WINAPI
ScriptTypeInfo_GetDllEntry(ITypeInfo
*iface
, MEMBERID memid
, INVOKEKIND invKind
,
937 BSTR
*pBstrDllName
, BSTR
*pBstrName
, WORD
*pwOrdinal
)
939 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
940 ITypeInfo
*disp_typeinfo
;
943 TRACE("(%p)->(%d %d %p %p %p)\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
945 if (pBstrDllName
) *pBstrDllName
= NULL
;
946 if (pBstrName
) *pBstrName
= NULL
;
947 if (pwOrdinal
) *pwOrdinal
= 0;
949 if (!get_func_from_memid(This
, memid
) && memid
> This
->num_vars
)
951 hr
= get_dispatch_typeinfo(&disp_typeinfo
);
952 if (FAILED(hr
)) return hr
;
954 return ITypeInfo_GetDllEntry(disp_typeinfo
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
956 return TYPE_E_BADMODULEKIND
;
959 static HRESULT WINAPI
ScriptTypeInfo_GetRefTypeInfo(ITypeInfo
*iface
, HREFTYPE hRefType
, ITypeInfo
**ppTInfo
)
961 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
964 TRACE("(%p)->(%x %p)\n", This
, hRefType
, ppTInfo
);
966 if (!ppTInfo
|| (INT
)hRefType
< 0) return E_INVALIDARG
;
968 if (hRefType
& ~3) return E_FAIL
;
971 hr
= get_dispatch_typeinfo(ppTInfo
);
972 if (FAILED(hr
)) return hr
;
977 ITypeInfo_AddRef(*ppTInfo
);
981 static HRESULT WINAPI
ScriptTypeInfo_AddressOfMember(ITypeInfo
*iface
, MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
983 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
984 ITypeInfo
*disp_typeinfo
;
987 TRACE("(%p)->(%d %d %p)\n", This
, memid
, invKind
, ppv
);
989 if (!ppv
) return E_INVALIDARG
;
992 if (!get_func_from_memid(This
, memid
) && memid
> This
->num_vars
)
994 hr
= get_dispatch_typeinfo(&disp_typeinfo
);
995 if (FAILED(hr
)) return hr
;
997 return ITypeInfo_AddressOfMember(disp_typeinfo
, memid
, invKind
, ppv
);
999 return TYPE_E_BADMODULEKIND
;
1002 static HRESULT WINAPI
ScriptTypeInfo_CreateInstance(ITypeInfo
*iface
, IUnknown
*pUnkOuter
, REFIID riid
, PVOID
*ppvObj
)
1004 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
1006 TRACE("(%p)->(%p %s %p)\n", This
, pUnkOuter
, debugstr_guid(riid
), ppvObj
);
1008 if (!ppvObj
) return E_INVALIDARG
;
1011 return TYPE_E_BADMODULEKIND
;
1014 static HRESULT WINAPI
ScriptTypeInfo_GetMops(ITypeInfo
*iface
, MEMBERID memid
, BSTR
*pBstrMops
)
1016 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
1017 ITypeInfo
*disp_typeinfo
;
1020 TRACE("(%p)->(%d %p)\n", This
, memid
, pBstrMops
);
1022 if (!pBstrMops
) return E_INVALIDARG
;
1024 if (!get_func_from_memid(This
, memid
) && memid
> This
->num_vars
)
1026 hr
= get_dispatch_typeinfo(&disp_typeinfo
);
1027 if (FAILED(hr
)) return hr
;
1029 return ITypeInfo_GetMops(disp_typeinfo
, memid
, pBstrMops
);
1036 static HRESULT WINAPI
ScriptTypeInfo_GetContainingTypeLib(ITypeInfo
*iface
, ITypeLib
**ppTLib
, UINT
*pIndex
)
1038 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
1040 FIXME("(%p)->(%p %p)\n", This
, ppTLib
, pIndex
);
1045 static void WINAPI
ScriptTypeInfo_ReleaseTypeAttr(ITypeInfo
*iface
, TYPEATTR
*pTypeAttr
)
1047 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
1049 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
1051 heap_free(pTypeAttr
);
1054 static void WINAPI
ScriptTypeInfo_ReleaseFuncDesc(ITypeInfo
*iface
, FUNCDESC
*pFuncDesc
)
1056 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
1058 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
1060 heap_free(pFuncDesc
);
1063 static void WINAPI
ScriptTypeInfo_ReleaseVarDesc(ITypeInfo
*iface
, VARDESC
*pVarDesc
)
1065 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
1067 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
1069 heap_free(pVarDesc
);
1072 static const ITypeInfoVtbl ScriptTypeInfoVtbl
= {
1073 ScriptTypeInfo_QueryInterface
,
1074 ScriptTypeInfo_AddRef
,
1075 ScriptTypeInfo_Release
,
1076 ScriptTypeInfo_GetTypeAttr
,
1077 ScriptTypeInfo_GetTypeComp
,
1078 ScriptTypeInfo_GetFuncDesc
,
1079 ScriptTypeInfo_GetVarDesc
,
1080 ScriptTypeInfo_GetNames
,
1081 ScriptTypeInfo_GetRefTypeOfImplType
,
1082 ScriptTypeInfo_GetImplTypeFlags
,
1083 ScriptTypeInfo_GetIDsOfNames
,
1084 ScriptTypeInfo_Invoke
,
1085 ScriptTypeInfo_GetDocumentation
,
1086 ScriptTypeInfo_GetDllEntry
,
1087 ScriptTypeInfo_GetRefTypeInfo
,
1088 ScriptTypeInfo_AddressOfMember
,
1089 ScriptTypeInfo_CreateInstance
,
1090 ScriptTypeInfo_GetMops
,
1091 ScriptTypeInfo_GetContainingTypeLib
,
1092 ScriptTypeInfo_ReleaseTypeAttr
,
1093 ScriptTypeInfo_ReleaseFuncDesc
,
1094 ScriptTypeInfo_ReleaseVarDesc
1097 static HRESULT WINAPI
ScriptTypeComp_QueryInterface(ITypeComp
*iface
, REFIID riid
, void **ppv
)
1099 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeComp(iface
);
1100 return ITypeInfo_QueryInterface(&This
->ITypeInfo_iface
, riid
, ppv
);
1103 static ULONG WINAPI
ScriptTypeComp_AddRef(ITypeComp
*iface
)
1105 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeComp(iface
);
1106 return ITypeInfo_AddRef(&This
->ITypeInfo_iface
);
1109 static ULONG WINAPI
ScriptTypeComp_Release(ITypeComp
*iface
)
1111 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeComp(iface
);
1112 return ITypeInfo_Release(&This
->ITypeInfo_iface
);
1115 static HRESULT WINAPI
ScriptTypeComp_Bind(ITypeComp
*iface
, LPOLESTR szName
, ULONG lHashVal
, WORD wFlags
,
1116 ITypeInfo
**ppTInfo
, DESCKIND
*pDescKind
, BINDPTR
*pBindPtr
)
1118 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeComp(iface
);
1119 UINT flags
= wFlags
? wFlags
: ~0;
1120 ITypeInfo
*disp_typeinfo
;
1121 ITypeComp
*disp_typecomp
;
1125 TRACE("(%p)->(%s %08x %d %p %p %p)\n", This
, debugstr_w(szName
), lHashVal
,
1126 wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
1128 if (!szName
|| !ppTInfo
|| !pDescKind
|| !pBindPtr
)
1129 return E_INVALIDARG
;
1131 for (i
= 0; i
< This
->num_funcs
; i
++)
1133 if (wcsicmp(szName
, This
->funcs
[i
].func
->name
)) continue;
1134 if (!(flags
& INVOKE_FUNC
)) return TYPE_E_TYPEMISMATCH
;
1136 hr
= ITypeInfo_GetFuncDesc(&This
->ITypeInfo_iface
, i
, &pBindPtr
->lpfuncdesc
);
1137 if (FAILED(hr
)) return hr
;
1139 *pDescKind
= DESCKIND_FUNCDESC
;
1140 *ppTInfo
= &This
->ITypeInfo_iface
;
1141 ITypeInfo_AddRef(*ppTInfo
);
1145 for (i
= 0; i
< This
->num_vars
; i
++)
1147 if (wcsicmp(szName
, This
->disp
->global_vars
[i
]->name
)) continue;
1148 if (!(flags
& INVOKE_PROPERTYGET
)) return TYPE_E_TYPEMISMATCH
;
1150 hr
= ITypeInfo_GetVarDesc(&This
->ITypeInfo_iface
, i
, &pBindPtr
->lpvardesc
);
1151 if (FAILED(hr
)) return hr
;
1153 *pDescKind
= DESCKIND_VARDESC
;
1154 *ppTInfo
= &This
->ITypeInfo_iface
;
1155 ITypeInfo_AddRef(*ppTInfo
);
1159 /* Look into the inherited IDispatch */
1160 hr
= get_dispatch_typeinfo(&disp_typeinfo
);
1161 if (FAILED(hr
)) return hr
;
1163 hr
= ITypeInfo_GetTypeComp(disp_typeinfo
, &disp_typecomp
);
1164 if (FAILED(hr
)) return hr
;
1166 hr
= ITypeComp_Bind(disp_typecomp
, szName
, lHashVal
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
1167 ITypeComp_Release(disp_typecomp
);
1171 static HRESULT WINAPI
ScriptTypeComp_BindType(ITypeComp
*iface
, LPOLESTR szName
, ULONG lHashVal
,
1172 ITypeInfo
**ppTInfo
, ITypeComp
**ppTComp
)
1174 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeComp(iface
);
1175 ITypeInfo
*disp_typeinfo
;
1176 ITypeComp
*disp_typecomp
;
1179 TRACE("(%p)->(%s %08x %p %p)\n", This
, debugstr_w(szName
), lHashVal
, ppTInfo
, ppTComp
);
1181 if (!szName
|| !ppTInfo
|| !ppTComp
)
1182 return E_INVALIDARG
;
1184 /* Look into the inherited IDispatch */
1185 hr
= get_dispatch_typeinfo(&disp_typeinfo
);
1186 if (FAILED(hr
)) return hr
;
1188 hr
= ITypeInfo_GetTypeComp(disp_typeinfo
, &disp_typecomp
);
1189 if (FAILED(hr
)) return hr
;
1191 hr
= ITypeComp_BindType(disp_typecomp
, szName
, lHashVal
, ppTInfo
, ppTComp
);
1192 ITypeComp_Release(disp_typecomp
);
1196 static const ITypeCompVtbl ScriptTypeCompVtbl
= {
1197 ScriptTypeComp_QueryInterface
,
1198 ScriptTypeComp_AddRef
,
1199 ScriptTypeComp_Release
,
1200 ScriptTypeComp_Bind
,
1201 ScriptTypeComp_BindType
1204 static inline ScriptDisp
*ScriptDisp_from_IDispatchEx(IDispatchEx
*iface
)
1206 return CONTAINING_RECORD(iface
, ScriptDisp
, IDispatchEx_iface
);
1209 static HRESULT WINAPI
ScriptDisp_QueryInterface(IDispatchEx
*iface
, REFIID riid
, void **ppv
)
1211 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1213 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
1214 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
1215 *ppv
= &This
->IDispatchEx_iface
;
1216 }else if(IsEqualGUID(&IID_IDispatch
, riid
)) {
1217 TRACE("(%p)->(IID_IDispatch %p)\n", This
, ppv
);
1218 *ppv
= &This
->IDispatchEx_iface
;
1219 }else if(IsEqualGUID(&IID_IDispatchEx
, riid
)) {
1220 TRACE("(%p)->(IID_IDispatchEx %p)\n", This
, ppv
);
1221 *ppv
= &This
->IDispatchEx_iface
;
1223 WARN("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
1225 return E_NOINTERFACE
;
1228 IUnknown_AddRef((IUnknown
*)*ppv
);
1232 static ULONG WINAPI
ScriptDisp_AddRef(IDispatchEx
*iface
)
1234 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1235 LONG ref
= InterlockedIncrement(&This
->ref
);
1237 TRACE("(%p) ref=%d\n", This
, ref
);
1242 static ULONG WINAPI
ScriptDisp_Release(IDispatchEx
*iface
)
1244 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1245 LONG ref
= InterlockedDecrement(&This
->ref
);
1248 TRACE("(%p) ref=%d\n", This
, ref
);
1253 for (i
= 0; i
< This
->global_vars_cnt
; i
++)
1254 release_dynamic_var(This
->global_vars
[i
]);
1256 heap_pool_free(&This
->heap
);
1257 heap_free(This
->global_vars
);
1258 heap_free(This
->global_funcs
);
1265 static HRESULT WINAPI
ScriptDisp_GetTypeInfoCount(IDispatchEx
*iface
, UINT
*pctinfo
)
1267 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1269 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1275 static HRESULT WINAPI
ScriptDisp_GetTypeInfo(IDispatchEx
*iface
, UINT iTInfo
, LCID lcid
, ITypeInfo
**ret
)
1277 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1278 ScriptTypeInfo
*type_info
;
1282 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ret
);
1285 return DISP_E_BADINDEX
;
1287 if(!(type_info
= heap_alloc(sizeof(*type_info
))))
1288 return E_OUTOFMEMORY
;
1290 for(i
= 0; i
< This
->global_funcs_cnt
; i
++)
1291 if(This
->global_funcs
[i
]->is_public
)
1294 type_info
->ITypeInfo_iface
.lpVtbl
= &ScriptTypeInfoVtbl
;
1295 type_info
->ITypeComp_iface
.lpVtbl
= &ScriptTypeCompVtbl
;
1297 type_info
->num_funcs
= num_funcs
;
1298 type_info
->num_vars
= This
->global_vars_cnt
;
1299 type_info
->disp
= This
;
1301 type_info
->funcs
= heap_alloc(sizeof(*type_info
->funcs
) * num_funcs
);
1302 if(!type_info
->funcs
)
1304 heap_free(type_info
);
1305 return E_OUTOFMEMORY
;
1308 for(j
= 0, i
= 0; i
< This
->global_funcs_cnt
; i
++)
1310 if(!This
->global_funcs
[i
]->is_public
) continue;
1312 type_info
->funcs
[j
].memid
= i
+ 1 + DISPID_FUNCTION_MASK
;
1313 type_info
->funcs
[j
].func
= This
->global_funcs
[i
];
1314 grab_vbscode(This
->global_funcs
[i
]->code_ctx
);
1318 IDispatchEx_AddRef(&This
->IDispatchEx_iface
);
1320 *ret
= &type_info
->ITypeInfo_iface
;
1324 static HRESULT WINAPI
ScriptDisp_GetIDsOfNames(IDispatchEx
*iface
, REFIID riid
,
1325 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
1327 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1331 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
,
1334 for(i
=0; i
< cNames
; i
++) {
1335 hres
= IDispatchEx_GetDispID(&This
->IDispatchEx_iface
, rgszNames
[i
], 0, rgDispId
+i
);
1343 static HRESULT WINAPI
ScriptDisp_Invoke(IDispatchEx
*iface
, DISPID dispIdMember
, REFIID riid
, LCID lcid
,
1344 WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1346 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1348 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
1349 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1351 return IDispatchEx_InvokeEx(&This
->IDispatchEx_iface
, dispIdMember
, lcid
, wFlags
,
1352 pDispParams
, pVarResult
, pExcepInfo
, NULL
);
1355 static HRESULT WINAPI
ScriptDisp_GetDispID(IDispatchEx
*iface
, BSTR bstrName
, DWORD grfdex
, DISPID
*pid
)
1357 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1360 TRACE("(%p)->(%s %x %p)\n", This
, debugstr_w(bstrName
), grfdex
, pid
);
1363 return E_UNEXPECTED
;
1365 for(i
= 0; i
< This
->global_vars_cnt
; i
++) {
1366 if(!wcsicmp(This
->global_vars
[i
]->name
, bstrName
)) {
1372 for(i
= 0; i
< This
->global_funcs_cnt
; i
++) {
1373 if(!wcsicmp(This
->global_funcs
[i
]->name
, bstrName
)) {
1374 *pid
= i
+ 1 + DISPID_FUNCTION_MASK
;
1380 return DISP_E_UNKNOWNNAME
;
1383 static HRESULT WINAPI
ScriptDisp_InvokeEx(IDispatchEx
*iface
, DISPID id
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pdp
,
1384 VARIANT
*pvarRes
, EXCEPINFO
*pei
, IServiceProvider
*pspCaller
)
1386 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1389 TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This
, id
, lcid
, wFlags
, pdp
, pvarRes
, pei
, pspCaller
);
1391 if (id
& DISPID_FUNCTION_MASK
)
1393 id
&= ~DISPID_FUNCTION_MASK
;
1394 if (id
> This
->global_funcs_cnt
)
1395 return DISP_E_MEMBERNOTFOUND
;
1399 case DISPATCH_METHOD
:
1400 case DISPATCH_METHOD
| DISPATCH_PROPERTYGET
:
1401 hres
= exec_script(This
->ctx
, TRUE
, This
->global_funcs
[id
- 1], NULL
, pdp
, pvarRes
);
1404 FIXME("Unsupported flags %x\n", wFlags
);
1411 if (id
> This
->global_vars_cnt
)
1412 return DISP_E_MEMBERNOTFOUND
;
1414 if (This
->global_vars
[id
- 1]->is_const
)
1416 FIXME("const not supported\n");
1420 return invoke_variant_prop(This
->ctx
, &This
->global_vars
[id
- 1]->v
, wFlags
, pdp
, pvarRes
);
1423 static HRESULT WINAPI
ScriptDisp_DeleteMemberByName(IDispatchEx
*iface
, BSTR bstrName
, DWORD grfdex
)
1425 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1426 FIXME("(%p)->(%s %x)\n", This
, debugstr_w(bstrName
), grfdex
);
1430 static HRESULT WINAPI
ScriptDisp_DeleteMemberByDispID(IDispatchEx
*iface
, DISPID id
)
1432 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1433 FIXME("(%p)->(%x)\n", This
, id
);
1437 static HRESULT WINAPI
ScriptDisp_GetMemberProperties(IDispatchEx
*iface
, DISPID id
, DWORD grfdexFetch
, DWORD
*pgrfdex
)
1439 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1440 FIXME("(%p)->(%x %x %p)\n", This
, id
, grfdexFetch
, pgrfdex
);
1444 static HRESULT WINAPI
ScriptDisp_GetMemberName(IDispatchEx
*iface
, DISPID id
, BSTR
*pbstrName
)
1446 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1447 FIXME("(%p)->(%x %p)\n", This
, id
, pbstrName
);
1451 static HRESULT WINAPI
ScriptDisp_GetNextDispID(IDispatchEx
*iface
, DWORD grfdex
, DISPID id
, DISPID
*pid
)
1453 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1454 FIXME("(%p)->(%x %x %p)\n", This
, grfdex
, id
, pid
);
1458 static HRESULT WINAPI
ScriptDisp_GetNameSpaceParent(IDispatchEx
*iface
, IUnknown
**ppunk
)
1460 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1461 FIXME("(%p)->(%p)\n", This
, ppunk
);
1465 static IDispatchExVtbl ScriptDispVtbl
= {
1466 ScriptDisp_QueryInterface
,
1469 ScriptDisp_GetTypeInfoCount
,
1470 ScriptDisp_GetTypeInfo
,
1471 ScriptDisp_GetIDsOfNames
,
1473 ScriptDisp_GetDispID
,
1474 ScriptDisp_InvokeEx
,
1475 ScriptDisp_DeleteMemberByName
,
1476 ScriptDisp_DeleteMemberByDispID
,
1477 ScriptDisp_GetMemberProperties
,
1478 ScriptDisp_GetMemberName
,
1479 ScriptDisp_GetNextDispID
,
1480 ScriptDisp_GetNameSpaceParent
1483 HRESULT
create_script_disp(script_ctx_t
*ctx
, ScriptDisp
**ret
)
1485 ScriptDisp
*script_disp
;
1487 script_disp
= heap_alloc_zero(sizeof(*script_disp
));
1489 return E_OUTOFMEMORY
;
1491 script_disp
->IDispatchEx_iface
.lpVtbl
= &ScriptDispVtbl
;
1492 script_disp
->ref
= 1;
1493 script_disp
->ctx
= ctx
;
1494 heap_pool_init(&script_disp
->heap
);
1500 void collect_objects(script_ctx_t
*ctx
)
1502 vbdisp_t
*iter
, *iter2
;
1504 LIST_FOR_EACH_ENTRY_SAFE(iter
, iter2
, &ctx
->objects
, vbdisp_t
, entry
)
1505 run_terminator(iter
);
1507 while(!list_empty(&ctx
->objects
)) {
1508 iter
= LIST_ENTRY(list_head(&ctx
->objects
), vbdisp_t
, entry
);
1510 IDispatchEx_AddRef(&iter
->IDispatchEx_iface
);
1513 list_remove(&iter
->entry
);
1514 list_init(&iter
->entry
);
1515 IDispatchEx_Release(&iter
->IDispatchEx_iface
);
1519 HRESULT
disp_get_id(IDispatch
*disp
, BSTR name
, vbdisp_invoke_type_t invoke_type
, BOOL search_private
, DISPID
*id
)
1521 IDispatchEx
*dispex
;
1525 vbdisp
= unsafe_impl_from_IDispatch(disp
);
1527 return vbdisp_get_id(vbdisp
, name
, invoke_type
, search_private
, id
);
1529 hres
= IDispatch_QueryInterface(disp
, &IID_IDispatchEx
, (void**)&dispex
);
1531 TRACE("using IDispatch\n");
1532 return IDispatch_GetIDsOfNames(disp
, &IID_NULL
, &name
, 1, 0, id
);
1535 hres
= IDispatchEx_GetDispID(dispex
, name
, fdexNameCaseInsensitive
, id
);
1536 IDispatchEx_Release(dispex
);
1540 #define RPC_E_SERVER_UNAVAILABLE 0x800706ba
1542 HRESULT
map_hres(HRESULT hres
)
1544 if(SUCCEEDED(hres
) || HRESULT_FACILITY(hres
) == FACILITY_VBS
)
1548 case E_NOTIMPL
: return MAKE_VBSERROR(VBSE_ACTION_NOT_SUPPORTED
);
1549 case E_NOINTERFACE
: return MAKE_VBSERROR(VBSE_OLE_NOT_SUPPORTED
);
1550 case DISP_E_UNKNOWNINTERFACE
: return MAKE_VBSERROR(VBSE_OLE_NO_PROP_OR_METHOD
);
1551 case DISP_E_MEMBERNOTFOUND
: return MAKE_VBSERROR(VBSE_OLE_NO_PROP_OR_METHOD
);
1552 case DISP_E_PARAMNOTFOUND
: return MAKE_VBSERROR(VBSE_NAMED_PARAM_NOT_FOUND
);
1553 case DISP_E_TYPEMISMATCH
: return MAKE_VBSERROR(VBSE_TYPE_MISMATCH
);
1554 case DISP_E_UNKNOWNNAME
: return MAKE_VBSERROR(VBSE_OLE_NO_PROP_OR_METHOD
);
1555 case DISP_E_NONAMEDARGS
: return MAKE_VBSERROR(VBSE_NAMED_ARGS_NOT_SUPPORTED
);
1556 case DISP_E_BADVARTYPE
: return MAKE_VBSERROR(VBSE_INVALID_TYPELIB_VARIABLE
);
1557 case DISP_E_OVERFLOW
: return MAKE_VBSERROR(VBSE_OVERFLOW
);
1558 case DISP_E_BADINDEX
: return MAKE_VBSERROR(VBSE_OUT_OF_BOUNDS
);
1559 case DISP_E_UNKNOWNLCID
: return MAKE_VBSERROR(VBSE_LOCALE_SETTING_NOT_SUPPORTED
);
1560 case DISP_E_ARRAYISLOCKED
: return MAKE_VBSERROR(VBSE_ARRAY_LOCKED
);
1561 case DISP_E_BADPARAMCOUNT
: return MAKE_VBSERROR(VBSE_FUNC_ARITY_MISMATCH
);
1562 case DISP_E_PARAMNOTOPTIONAL
: return MAKE_VBSERROR(VBSE_PARAMETER_NOT_OPTIONAL
);
1563 case DISP_E_NOTACOLLECTION
: return MAKE_VBSERROR(VBSE_NOT_ENUM
);
1564 case TYPE_E_DLLFUNCTIONNOTFOUND
: return MAKE_VBSERROR(VBSE_INVALID_DLL_FUNCTION_NAME
);
1565 case TYPE_E_TYPEMISMATCH
: return MAKE_VBSERROR(VBSE_TYPE_MISMATCH
);
1566 case TYPE_E_OUTOFBOUNDS
: return MAKE_VBSERROR(VBSE_OUT_OF_BOUNDS
);
1567 case TYPE_E_IOERROR
: return MAKE_VBSERROR(VBSE_IO_ERROR
);
1568 case TYPE_E_CANTCREATETMPFILE
: return MAKE_VBSERROR(VBSE_CANT_CREATE_TMP_FILE
);
1569 case STG_E_FILENOTFOUND
: return MAKE_VBSERROR(VBSE_OLE_FILE_NOT_FOUND
);
1570 case STG_E_PATHNOTFOUND
: return MAKE_VBSERROR(VBSE_PATH_NOT_FOUND
);
1571 case STG_E_TOOMANYOPENFILES
: return MAKE_VBSERROR(VBSE_TOO_MANY_FILES
);
1572 case STG_E_ACCESSDENIED
: return MAKE_VBSERROR(VBSE_PERMISSION_DENIED
);
1573 case STG_E_INSUFFICIENTMEMORY
: return MAKE_VBSERROR(VBSE_OUT_OF_MEMORY
);
1574 case STG_E_NOMOREFILES
: return MAKE_VBSERROR(VBSE_TOO_MANY_FILES
);
1575 case STG_E_DISKISWRITEPROTECTED
: return MAKE_VBSERROR(VBSE_PERMISSION_DENIED
);
1576 case STG_E_WRITEFAULT
: return MAKE_VBSERROR(VBSE_IO_ERROR
);
1577 case STG_E_READFAULT
: return MAKE_VBSERROR(VBSE_IO_ERROR
);
1578 case STG_E_SHAREVIOLATION
: return MAKE_VBSERROR(VBSE_PATH_FILE_ACCESS
);
1579 case STG_E_LOCKVIOLATION
: return MAKE_VBSERROR(VBSE_PERMISSION_DENIED
);
1580 case STG_E_FILEALREADYEXISTS
: return MAKE_VBSERROR(VBSE_FILE_ALREADY_EXISTS
);
1581 case STG_E_MEDIUMFULL
: return MAKE_VBSERROR(VBSE_DISK_FULL
);
1582 case STG_E_INVALIDNAME
: return MAKE_VBSERROR(VBSE_FILE_NOT_FOUND
);
1583 case STG_E_INUSE
: return MAKE_VBSERROR(VBSE_PERMISSION_DENIED
);
1584 case STG_E_NOTCURRENT
: return MAKE_VBSERROR(VBSE_PERMISSION_DENIED
);
1585 case STG_E_CANTSAVE
: return MAKE_VBSERROR(VBSE_IO_ERROR
);
1586 case REGDB_E_CLASSNOTREG
: return MAKE_VBSERROR(VBSE_CANT_CREATE_OBJECT
);
1587 case MK_E_UNAVAILABLE
: return MAKE_VBSERROR(VBSE_CANT_CREATE_OBJECT
);
1588 case MK_E_INVALIDEXTENSION
: return MAKE_VBSERROR(VBSE_OLE_FILE_NOT_FOUND
);
1589 case MK_E_CANTOPENFILE
: return MAKE_VBSERROR(VBSE_OLE_FILE_NOT_FOUND
);
1590 case CO_E_CLASSSTRING
: return MAKE_VBSERROR(VBSE_CANT_CREATE_OBJECT
);
1591 case CO_E_APPNOTFOUND
: return MAKE_VBSERROR(VBSE_CANT_CREATE_OBJECT
);
1592 case CO_E_APPDIDNTREG
: return MAKE_VBSERROR(VBSE_CANT_CREATE_OBJECT
);
1593 case E_ACCESSDENIED
: return MAKE_VBSERROR(VBSE_PERMISSION_DENIED
);
1594 case E_OUTOFMEMORY
: return MAKE_VBSERROR(VBSE_OUT_OF_MEMORY
);
1595 case E_INVALIDARG
: return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL
);
1596 case RPC_E_SERVER_UNAVAILABLE
: return MAKE_VBSERROR(VBSE_SERVER_NOT_FOUND
);
1597 case CO_E_SERVER_EXEC_FAILURE
: return MAKE_VBSERROR(VBSE_CANT_CREATE_OBJECT
);
1603 HRESULT
disp_call(script_ctx_t
*ctx
, IDispatch
*disp
, DISPID id
, DISPPARAMS
*dp
, VARIANT
*retv
)
1605 const WORD flags
= DISPATCH_METHOD
|(retv
? DISPATCH_PROPERTYGET
: 0);
1606 IDispatchEx
*dispex
;
1611 memset(&ei
, 0, sizeof(ei
));
1613 V_VT(retv
) = VT_EMPTY
;
1615 vbdisp
= unsafe_impl_from_IDispatch(disp
);
1616 if(vbdisp
&& vbdisp
->desc
&& vbdisp
->desc
->ctx
== ctx
)
1617 return invoke_vbdisp(vbdisp
, id
, flags
, FALSE
, dp
, retv
);
1619 hres
= IDispatch_QueryInterface(disp
, &IID_IDispatchEx
, (void**)&dispex
);
1620 if(SUCCEEDED(hres
)) {
1621 hres
= IDispatchEx_InvokeEx(dispex
, id
, ctx
->lcid
, flags
, dp
, retv
, &ei
, NULL
/* CALLER_FIXME */);
1622 IDispatchEx_Release(dispex
);
1626 TRACE("using IDispatch\n");
1627 hres
= IDispatch_Invoke(disp
, id
, &IID_NULL
, ctx
->lcid
, flags
, dp
, retv
, &ei
, &err
);
1630 if(hres
== DISP_E_EXCEPTION
) {
1633 hres
= SCRIPT_E_RECORDED
;
1638 HRESULT
get_disp_value(script_ctx_t
*ctx
, IDispatch
*disp
, VARIANT
*v
)
1640 DISPPARAMS dp
= {NULL
};
1642 return MAKE_VBSERROR(VBSE_OBJECT_VARIABLE_NOT_SET
);
1643 return disp_call(ctx
, disp
, DISPID_VALUE
, &dp
, v
);
1646 HRESULT
disp_propput(script_ctx_t
*ctx
, IDispatch
*disp
, DISPID id
, WORD flags
, DISPPARAMS
*dp
)
1648 IDispatchEx
*dispex
;
1653 vbdisp
= unsafe_impl_from_IDispatch(disp
);
1654 if(vbdisp
&& vbdisp
->desc
&& vbdisp
->desc
->ctx
== ctx
)
1655 return invoke_vbdisp(vbdisp
, id
, flags
, FALSE
, dp
, NULL
);
1657 hres
= IDispatch_QueryInterface(disp
, &IID_IDispatchEx
, (void**)&dispex
);
1658 if(SUCCEEDED(hres
)) {
1659 hres
= IDispatchEx_InvokeEx(dispex
, id
, ctx
->lcid
, flags
, dp
, NULL
, &ei
, NULL
/* FIXME! */);
1660 IDispatchEx_Release(dispex
);
1664 TRACE("using IDispatch\n");
1665 hres
= IDispatch_Invoke(disp
, id
, &IID_NULL
, ctx
->lcid
, flags
, dp
, NULL
, &ei
, &err
);
1668 if(hres
== DISP_E_EXCEPTION
) {
1671 hres
= SCRIPT_E_RECORDED
;