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
= 0; i
< This
->desc
->func_cnt
; i
++) {
42 if(invoke_type
== VBDISP_ANY
) {
43 if(!search_private
&& !This
->desc
->funcs
[i
].is_public
)
46 if(!This
->desc
->funcs
[i
].entries
[invoke_type
]
47 || (!search_private
&& !This
->desc
->funcs
[i
].entries
[invoke_type
]->is_public
))
51 if(This
->desc
->funcs
[i
].name
&& !wcsicmp(This
->desc
->funcs
[i
].name
, name
)) {
60 HRESULT
vbdisp_get_id(vbdisp_t
*This
, BSTR name
, vbdisp_invoke_type_t invoke_type
, BOOL search_private
, DISPID
*id
)
64 if(get_func_id(This
, name
, invoke_type
, search_private
, id
))
67 for(i
=0; i
< This
->desc
->prop_cnt
; i
++) {
68 if(!search_private
&& !This
->desc
->props
[i
].is_public
)
71 if(!wcsicmp(This
->desc
->props
[i
].name
, name
)) {
72 *id
= i
+ This
->desc
->func_cnt
;
78 return DISP_E_UNKNOWNNAME
;
81 static HRESULT
get_propput_arg(script_ctx_t
*ctx
, const DISPPARAMS
*dp
, WORD flags
, VARIANT
*v
, BOOL
*is_owned
)
85 for(i
=0; i
< dp
->cNamedArgs
; i
++) {
86 if(dp
->rgdispidNamedArgs
[i
] == DISPID_PROPERTYPUT
)
89 if(i
== dp
->cNamedArgs
) {
90 WARN("no value to set\n");
91 return DISP_E_PARAMNOTOPTIONAL
;
95 if(V_VT(v
) == (VT_VARIANT
|VT_BYREF
))
96 *v
= *V_VARIANTREF(v
);
99 if(V_VT(v
) == VT_DISPATCH
) {
100 if(!(flags
& DISPATCH_PROPERTYPUTREF
)) {
103 hres
= get_disp_value(ctx
, V_DISPATCH(v
), v
);
109 }else if(!(flags
& DISPATCH_PROPERTYPUT
)) {
110 WARN("%s can't be assigned without DISPATCH_PROPERTYPUT flag\n", debugstr_variant(v
));
111 return DISP_E_EXCEPTION
;
117 static HRESULT
invoke_variant_prop(script_ctx_t
*ctx
, VARIANT
*v
, WORD flags
, DISPPARAMS
*dp
, VARIANT
*res
)
122 case DISPATCH_PROPERTYGET
|DISPATCH_METHOD
:
123 case DISPATCH_PROPERTYGET
:
125 WARN("called with arguments\n");
126 return DISP_E_MEMBERNOTFOUND
; /* That's what tests show */
129 hres
= VariantCopyInd(res
, v
);
132 case DISPATCH_PROPERTYPUT
:
133 case DISPATCH_PROPERTYPUTREF
:
134 case DISPATCH_PROPERTYPUT
|DISPATCH_PROPERTYPUTREF
: {
138 hres
= get_propput_arg(ctx
, dp
, flags
, &put_val
, &own_val
);
143 FIXME("Arguments not supported\n");
148 V_VT(res
) = VT_EMPTY
;
153 hres
= VariantCopyInd(v
, &put_val
);
158 FIXME("unimplemented flags %x\n", flags
);
165 static HRESULT
invoke_vbdisp(vbdisp_t
*This
, DISPID id
, DWORD flags
, BOOL extern_caller
, DISPPARAMS
*params
, VARIANT
*res
)
168 return DISP_E_MEMBERNOTFOUND
;
170 if(is_func_id(This
, id
)) {
173 TRACE("%p->%s\n", This
, debugstr_w(This
->desc
->funcs
[id
].name
));
176 case DISPATCH_PROPERTYGET
:
177 func
= This
->desc
->funcs
[id
].entries
[VBDISP_CALLGET
];
178 if(!func
|| func
->type
!= FUNC_PROPGET
) {
180 return DISP_E_MEMBERNOTFOUND
;
183 return exec_script(This
->desc
->ctx
, extern_caller
, func
, This
, params
, res
);
185 case DISPATCH_METHOD
:
186 case DISPATCH_METHOD
|DISPATCH_PROPERTYGET
:
187 func
= This
->desc
->funcs
[id
].entries
[VBDISP_CALLGET
];
189 FIXME("no invoke/getter\n");
190 return DISP_E_MEMBERNOTFOUND
;
193 return exec_script(This
->desc
->ctx
, extern_caller
, func
, This
, params
, res
);
195 case DISPATCH_PROPERTYPUT
:
196 case DISPATCH_PROPERTYPUTREF
:
197 case DISPATCH_PROPERTYPUT
|DISPATCH_PROPERTYPUTREF
: {
198 DISPPARAMS dp
= {NULL
, NULL
, 1, 0};
204 dp
.cArgs
= arg_cnt(params
) + 1;
205 if(dp
.cArgs
> ARRAY_SIZE(buf
)) {
206 dp
.rgvarg
= heap_alloc(dp
.cArgs
*sizeof(VARIANT
));
208 return E_OUTOFMEMORY
;
213 hres
= get_propput_arg(This
->desc
->ctx
, params
, flags
, dp
.rgvarg
, &needs_release
);
216 heap_free(dp
.rgvarg
);
220 func
= This
->desc
->funcs
[id
].entries
[V_VT(dp
.rgvarg
) == VT_DISPATCH
? VBDISP_SET
: VBDISP_LET
];
222 FIXME("no letter/setter\n");
224 heap_free(dp
.rgvarg
);
225 return DISP_E_MEMBERNOTFOUND
;
228 for(i
=1; i
< dp
.cArgs
; i
++) {
229 dp
.rgvarg
[i
]=params
->rgvarg
[params
->cNamedArgs
+i
-1];
232 hres
= exec_script(This
->desc
->ctx
, extern_caller
, func
, This
, &dp
, NULL
);
234 VariantClear(dp
.rgvarg
);
236 heap_free(dp
.rgvarg
);
240 FIXME("flags %lx\n", flags
);
241 return DISP_E_MEMBERNOTFOUND
;
245 if(id
>= This
->desc
->prop_cnt
+ This
->desc
->func_cnt
)
246 return DISP_E_MEMBERNOTFOUND
;
248 TRACE("%p->%s\n", This
, debugstr_w(This
->desc
->props
[id
- This
->desc
->func_cnt
].name
));
249 return invoke_variant_prop(This
->desc
->ctx
, This
->props
+(id
-This
->desc
->func_cnt
), flags
, params
, res
);
252 static BOOL
run_terminator(vbdisp_t
*This
)
256 if(This
->terminator_ran
)
258 This
->terminator_ran
= TRUE
;
260 if(!This
->desc
->class_terminate_id
)
264 exec_script(This
->desc
->ctx
, FALSE
, This
->desc
->funcs
[This
->desc
->class_terminate_id
].entries
[VBDISP_CALLGET
],
269 static void clean_props(vbdisp_t
*This
)
276 for(i
=0; i
< This
->desc
->array_cnt
; i
++) {
277 if(This
->arrays
[i
]) {
278 SafeArrayDestroy(This
->arrays
[i
]);
279 This
->arrays
[i
] = NULL
;
283 for(i
=0; i
< This
->desc
->prop_cnt
; i
++)
284 VariantClear(This
->props
+i
);
287 static inline vbdisp_t
*impl_from_IDispatchEx(IDispatchEx
*iface
)
289 return CONTAINING_RECORD(iface
, vbdisp_t
, IDispatchEx_iface
);
292 static HRESULT WINAPI
DispatchEx_QueryInterface(IDispatchEx
*iface
, REFIID riid
, void **ppv
)
294 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
296 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
297 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
298 *ppv
= &This
->IDispatchEx_iface
;
299 }else if(IsEqualGUID(&IID_IDispatch
, riid
)) {
300 TRACE("(%p)->(IID_IDispatch %p)\n", This
, ppv
);
301 *ppv
= &This
->IDispatchEx_iface
;
302 }else if(IsEqualGUID(&IID_IDispatchEx
, riid
)) {
303 TRACE("(%p)->(IID_IDispatchEx %p)\n", This
, ppv
);
304 *ppv
= &This
->IDispatchEx_iface
;
306 WARN("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
308 return E_NOINTERFACE
;
311 IUnknown_AddRef((IUnknown
*)*ppv
);
315 static ULONG WINAPI
DispatchEx_AddRef(IDispatchEx
*iface
)
317 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
318 LONG ref
= InterlockedIncrement(&This
->ref
);
320 TRACE("(%p) ref=%ld\n", This
, ref
);
325 static ULONG WINAPI
DispatchEx_Release(IDispatchEx
*iface
)
327 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
328 LONG ref
= InterlockedDecrement(&This
->ref
);
330 TRACE("(%p) ref=%ld\n", This
, ref
);
332 if(!ref
&& run_terminator(This
)) {
334 list_remove(&This
->entry
);
335 heap_free(This
->arrays
);
342 static HRESULT WINAPI
DispatchEx_GetTypeInfoCount(IDispatchEx
*iface
, UINT
*pctinfo
)
344 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
346 TRACE("(%p)->(%p)\n", This
, pctinfo
);
352 static HRESULT WINAPI
DispatchEx_GetTypeInfo(IDispatchEx
*iface
, UINT iTInfo
, LCID lcid
,
355 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
356 FIXME("(%p)->(%u %lu %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
360 static HRESULT WINAPI
DispatchEx_GetIDsOfNames(IDispatchEx
*iface
, REFIID riid
,
361 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
,
364 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
365 FIXME("(%p)->(%s %p %u %lu %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
,
370 static HRESULT WINAPI
DispatchEx_Invoke(IDispatchEx
*iface
, DISPID dispIdMember
,
371 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
,
372 VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
374 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
376 TRACE("(%p)->(%ld %s %ld %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
377 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
379 return IDispatchEx_InvokeEx(&This
->IDispatchEx_iface
, dispIdMember
, lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, NULL
);
382 static HRESULT WINAPI
DispatchEx_GetDispID(IDispatchEx
*iface
, BSTR bstrName
, DWORD grfdex
, DISPID
*pid
)
384 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
386 TRACE("(%p)->(%s %lx %p)\n", This
, debugstr_w(bstrName
), grfdex
, pid
);
388 grfdex
&= ~FDEX_VERSION_MASK
;
393 /* Tests show that fdexNameCaseSensitive is ignored */
395 if(grfdex
& ~(fdexNameEnsure
|fdexNameCaseInsensitive
|fdexNameCaseSensitive
)) {
396 FIXME("unsupported flags %lx\n", grfdex
);
400 return vbdisp_get_id(This
, bstrName
, VBDISP_ANY
, FALSE
, pid
);
403 static HRESULT WINAPI
DispatchEx_InvokeEx(IDispatchEx
*iface
, DISPID id
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pdp
,
404 VARIANT
*pvarRes
, EXCEPINFO
*pei
, IServiceProvider
*pspCaller
)
406 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
408 TRACE("(%p)->(%lx %lx %x %p %p %p %p)\n", This
, id
, lcid
, wFlags
, pdp
, pvarRes
, pei
, pspCaller
);
414 V_VT(pvarRes
) = VT_EMPTY
;
416 return invoke_vbdisp(This
, id
, wFlags
, TRUE
, pdp
, pvarRes
);
419 static HRESULT WINAPI
DispatchEx_DeleteMemberByName(IDispatchEx
*iface
, BSTR bstrName
, DWORD grfdex
)
421 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
422 FIXME("(%p)->(%s %lx)\n", This
, debugstr_w(bstrName
), grfdex
);
426 static HRESULT WINAPI
DispatchEx_DeleteMemberByDispID(IDispatchEx
*iface
, DISPID id
)
428 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
429 FIXME("(%p)->(%lx)\n", This
, id
);
433 static HRESULT WINAPI
DispatchEx_GetMemberProperties(IDispatchEx
*iface
, DISPID id
, DWORD grfdexFetch
, DWORD
*pgrfdex
)
435 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
436 FIXME("(%p)->(%lx %lx %p)\n", This
, id
, grfdexFetch
, pgrfdex
);
440 static HRESULT WINAPI
DispatchEx_GetMemberName(IDispatchEx
*iface
, DISPID id
, BSTR
*pbstrName
)
442 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
443 FIXME("(%p)->(%lx %p)\n", This
, id
, pbstrName
);
447 static HRESULT WINAPI
DispatchEx_GetNextDispID(IDispatchEx
*iface
, DWORD grfdex
, DISPID id
, DISPID
*pid
)
449 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
450 FIXME("(%p)->(%lx %lx %p)\n", This
, grfdex
, id
, pid
);
454 static HRESULT WINAPI
DispatchEx_GetNameSpaceParent(IDispatchEx
*iface
, IUnknown
**ppunk
)
456 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
457 FIXME("(%p)->(%p)\n", This
, ppunk
);
461 static IDispatchExVtbl DispatchExVtbl
= {
462 DispatchEx_QueryInterface
,
465 DispatchEx_GetTypeInfoCount
,
466 DispatchEx_GetTypeInfo
,
467 DispatchEx_GetIDsOfNames
,
469 DispatchEx_GetDispID
,
471 DispatchEx_DeleteMemberByName
,
472 DispatchEx_DeleteMemberByDispID
,
473 DispatchEx_GetMemberProperties
,
474 DispatchEx_GetMemberName
,
475 DispatchEx_GetNextDispID
,
476 DispatchEx_GetNameSpaceParent
479 static inline vbdisp_t
*unsafe_impl_from_IDispatch(IDispatch
*iface
)
481 return iface
->lpVtbl
== (IDispatchVtbl
*)&DispatchExVtbl
482 ? CONTAINING_RECORD(iface
, vbdisp_t
, IDispatchEx_iface
)
486 HRESULT
create_vbdisp(const class_desc_t
*desc
, vbdisp_t
**ret
)
491 vbdisp
= heap_alloc_zero( FIELD_OFFSET( vbdisp_t
, props
[desc
->prop_cnt
] ));
493 return E_OUTOFMEMORY
;
495 vbdisp
->IDispatchEx_iface
.lpVtbl
= &DispatchExVtbl
;
499 list_add_tail(&desc
->ctx
->objects
, &vbdisp
->entry
);
501 if(desc
->array_cnt
) {
502 vbdisp
->arrays
= heap_alloc_zero(desc
->array_cnt
* sizeof(*vbdisp
->arrays
));
506 for(i
=0; i
< desc
->array_cnt
; i
++) {
507 if(!desc
->array_descs
[i
].dim_cnt
)
510 vbdisp
->arrays
[i
] = SafeArrayCreate(VT_VARIANT
, desc
->array_descs
[i
].dim_cnt
, desc
->array_descs
[i
].bounds
);
511 if(!vbdisp
->arrays
[i
]) {
512 hres
= E_OUTOFMEMORY
;
517 if(SUCCEEDED(hres
)) {
518 for(i
=0, j
=0; i
< desc
->prop_cnt
; i
++) {
519 if(desc
->props
[i
].is_array
) {
520 V_VT(vbdisp
->props
+i
) = VT_ARRAY
|VT_BYREF
|VT_VARIANT
;
521 V_ARRAYREF(vbdisp
->props
+i
) = vbdisp
->arrays
+ j
++;
526 hres
= E_OUTOFMEMORY
;
530 if(SUCCEEDED(hres
) && desc
->class_initialize_id
) {
532 hres
= exec_script(desc
->ctx
, FALSE
, desc
->funcs
[desc
->class_initialize_id
].entries
[VBDISP_CALLGET
],
537 IDispatchEx_Release(&vbdisp
->IDispatchEx_iface
);
545 struct typeinfo_func
{
551 ITypeInfo ITypeInfo_iface
;
552 ITypeComp ITypeComp_iface
;
557 struct typeinfo_func
*funcs
;
562 static function_t
*get_func_from_memid(const ScriptTypeInfo
*typeinfo
, MEMBERID memid
)
564 UINT a
= 0, b
= typeinfo
->num_funcs
;
566 if (!(memid
& DISPID_FUNCTION_MASK
)) return NULL
;
570 UINT i
= (a
+ b
- 1) / 2;
572 if (memid
== typeinfo
->funcs
[i
].memid
)
573 return typeinfo
->funcs
[i
].func
;
574 else if (memid
< typeinfo
->funcs
[i
].memid
)
582 static inline ScriptTypeInfo
*ScriptTypeInfo_from_ITypeInfo(ITypeInfo
*iface
)
584 return CONTAINING_RECORD(iface
, ScriptTypeInfo
, ITypeInfo_iface
);
587 static inline ScriptTypeInfo
*ScriptTypeInfo_from_ITypeComp(ITypeComp
*iface
)
589 return CONTAINING_RECORD(iface
, ScriptTypeInfo
, ITypeComp_iface
);
592 static HRESULT WINAPI
ScriptTypeInfo_QueryInterface(ITypeInfo
*iface
, REFIID riid
, void **ppv
)
594 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
596 if (IsEqualGUID(&IID_IUnknown
, riid
) || IsEqualGUID(&IID_ITypeInfo
, riid
))
597 *ppv
= &This
->ITypeInfo_iface
;
598 else if (IsEqualGUID(&IID_ITypeComp
, riid
))
599 *ppv
= &This
->ITypeComp_iface
;
602 WARN("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
604 return E_NOINTERFACE
;
607 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
608 IUnknown_AddRef((IUnknown
*)*ppv
);
612 static ULONG WINAPI
ScriptTypeInfo_AddRef(ITypeInfo
*iface
)
614 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
615 LONG ref
= InterlockedIncrement(&This
->ref
);
617 TRACE("(%p) ref=%ld\n", This
, ref
);
622 static ULONG WINAPI
ScriptTypeInfo_Release(ITypeInfo
*iface
)
624 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
625 LONG ref
= InterlockedDecrement(&This
->ref
);
628 TRACE("(%p) ref=%ld\n", This
, ref
);
632 for (i
= 0; i
< This
->num_funcs
; i
++)
633 release_vbscode(This
->funcs
[i
].func
->code_ctx
);
635 IDispatchEx_Release(&This
->disp
->IDispatchEx_iface
);
636 heap_free(This
->funcs
);
642 static HRESULT WINAPI
ScriptTypeInfo_GetTypeAttr(ITypeInfo
*iface
, TYPEATTR
**ppTypeAttr
)
644 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
647 TRACE("(%p)->(%p)\n", This
, ppTypeAttr
);
649 if (!ppTypeAttr
) return E_INVALIDARG
;
651 attr
= heap_alloc_zero(sizeof(*attr
));
652 if (!attr
) return E_OUTOFMEMORY
;
654 attr
->guid
= GUID_VBScriptTypeInfo
;
655 attr
->lcid
= LOCALE_USER_DEFAULT
;
656 attr
->memidConstructor
= MEMBERID_NIL
;
657 attr
->memidDestructor
= MEMBERID_NIL
;
658 attr
->cbSizeInstance
= 4;
659 attr
->typekind
= TKIND_DISPATCH
;
660 attr
->cFuncs
= This
->num_funcs
;
661 attr
->cVars
= This
->num_vars
;
662 attr
->cImplTypes
= 1;
663 attr
->cbSizeVft
= sizeof(IDispatchVtbl
);
664 attr
->cbAlignment
= 4;
665 attr
->wTypeFlags
= TYPEFLAG_FDISPATCHABLE
;
666 attr
->wMajorVerNum
= VBSCRIPT_MAJOR_VERSION
;
667 attr
->wMinorVerNum
= VBSCRIPT_MINOR_VERSION
;
673 static HRESULT WINAPI
ScriptTypeInfo_GetTypeComp(ITypeInfo
*iface
, ITypeComp
**ppTComp
)
675 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
677 TRACE("(%p)->(%p)\n", This
, ppTComp
);
679 if (!ppTComp
) return E_INVALIDARG
;
681 *ppTComp
= &This
->ITypeComp_iface
;
682 ITypeInfo_AddRef(iface
);
686 static HRESULT WINAPI
ScriptTypeInfo_GetFuncDesc(ITypeInfo
*iface
, UINT index
, FUNCDESC
**ppFuncDesc
)
688 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
693 TRACE("(%p)->(%u %p)\n", This
, index
, ppFuncDesc
);
695 if (!ppFuncDesc
) return E_INVALIDARG
;
696 if (index
>= This
->num_funcs
) return TYPE_E_ELEMENTNOTFOUND
;
697 func
= This
->funcs
[index
].func
;
699 /* Store the parameter array after the FUNCDESC structure */
700 desc
= heap_alloc_zero(sizeof(*desc
) + sizeof(ELEMDESC
) * func
->arg_cnt
);
701 if (!desc
) return E_OUTOFMEMORY
;
703 desc
->memid
= This
->funcs
[index
].memid
;
704 desc
->funckind
= FUNC_DISPATCH
;
705 desc
->invkind
= INVOKE_FUNC
;
706 desc
->callconv
= CC_STDCALL
;
707 desc
->cParams
= func
->arg_cnt
;
708 desc
->elemdescFunc
.tdesc
.vt
= (func
->type
== FUNC_SUB
) ? VT_VOID
: VT_VARIANT
;
710 if (func
->arg_cnt
) desc
->lprgelemdescParam
= (ELEMDESC
*)(desc
+ 1);
711 for (i
= 0; i
< func
->arg_cnt
; i
++)
712 desc
->lprgelemdescParam
[i
].tdesc
.vt
= VT_VARIANT
;
718 static HRESULT WINAPI
ScriptTypeInfo_GetVarDesc(ITypeInfo
*iface
, UINT index
, VARDESC
**ppVarDesc
)
720 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
723 TRACE("(%p)->(%u %p)\n", This
, index
, ppVarDesc
);
725 if (!ppVarDesc
) return E_INVALIDARG
;
726 if (index
>= This
->num_vars
) return TYPE_E_ELEMENTNOTFOUND
;
728 desc
= heap_alloc_zero(sizeof(*desc
));
729 if (!desc
) return E_OUTOFMEMORY
;
731 desc
->memid
= index
+ 1;
732 desc
->varkind
= VAR_DISPATCH
;
733 desc
->elemdescVar
.tdesc
.vt
= VT_VARIANT
;
739 static HRESULT WINAPI
ScriptTypeInfo_GetNames(ITypeInfo
*iface
, MEMBERID memid
, BSTR
*rgBstrNames
,
740 UINT cMaxNames
, UINT
*pcNames
)
742 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
743 ITypeInfo
*disp_typeinfo
;
748 TRACE("(%p)->(%ld %p %u %p)\n", This
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
750 if (!rgBstrNames
|| !pcNames
) return E_INVALIDARG
;
751 if (memid
<= 0) return TYPE_E_ELEMENTNOTFOUND
;
753 func
= get_func_from_memid(This
, memid
);
754 if (!func
&& memid
> This
->num_vars
)
756 hr
= get_dispatch_typeinfo(&disp_typeinfo
);
757 if (FAILED(hr
)) return hr
;
759 return ITypeInfo_GetNames(disp_typeinfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
763 if (!cMaxNames
) return S_OK
;
767 UINT num
= min(cMaxNames
, func
->arg_cnt
+ 1);
769 rgBstrNames
[0] = SysAllocString(func
->name
);
770 if (!rgBstrNames
[0]) return E_OUTOFMEMORY
;
772 for (i
= 1; i
< num
; i
++)
774 if (!(rgBstrNames
[i
] = SysAllocString(func
->args
[i
- 1].name
)))
776 do SysFreeString(rgBstrNames
[--i
]); while (i
);
777 return E_OUTOFMEMORY
;
783 rgBstrNames
[0] = SysAllocString(This
->disp
->global_vars
[memid
- 1]->name
);
784 if (!rgBstrNames
[0]) return E_OUTOFMEMORY
;
792 static HRESULT WINAPI
ScriptTypeInfo_GetRefTypeOfImplType(ITypeInfo
*iface
, UINT index
, HREFTYPE
*pRefType
)
794 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
796 TRACE("(%p)->(%u %p)\n", This
, index
, pRefType
);
798 /* We only inherit from IDispatch */
799 if (!pRefType
) return E_INVALIDARG
;
800 if (index
!= 0) return TYPE_E_ELEMENTNOTFOUND
;
806 static HRESULT WINAPI
ScriptTypeInfo_GetImplTypeFlags(ITypeInfo
*iface
, UINT index
, INT
*pImplTypeFlags
)
808 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
810 TRACE("(%p)->(%u %p)\n", This
, index
, pImplTypeFlags
);
812 if (!pImplTypeFlags
) return E_INVALIDARG
;
813 if (index
!= 0) return TYPE_E_ELEMENTNOTFOUND
;
819 static HRESULT WINAPI
ScriptTypeInfo_GetIDsOfNames(ITypeInfo
*iface
, LPOLESTR
*rgszNames
, UINT cNames
,
822 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
823 ITypeInfo
*disp_typeinfo
;
828 TRACE("(%p)->(%p %u %p)\n", This
, rgszNames
, cNames
, pMemId
);
830 if (!rgszNames
|| !cNames
|| !pMemId
) return E_INVALIDARG
;
832 for (i
= 0; i
< cNames
; i
++) pMemId
[i
] = MEMBERID_NIL
;
835 for (i
= 0; i
< This
->num_funcs
; i
++)
837 function_t
*func
= This
->funcs
[i
].func
;
839 if (wcsicmp(name
, func
->name
)) continue;
840 pMemId
[0] = This
->funcs
[i
].memid
;
842 for (j
= 1; j
< cNames
; j
++)
845 for (arg
= func
->arg_cnt
; --arg
>= 0;)
846 if (!wcsicmp(name
, func
->args
[arg
].name
))
851 hr
= DISP_E_UNKNOWNNAME
;
856 for (i
= 0; i
< This
->num_vars
; i
++)
858 if (wcsicmp(name
, This
->disp
->global_vars
[i
]->name
)) continue;
863 /* Look into the inherited IDispatch */
864 hr
= get_dispatch_typeinfo(&disp_typeinfo
);
865 if (FAILED(hr
)) return hr
;
867 return ITypeInfo_GetIDsOfNames(disp_typeinfo
, rgszNames
, cNames
, pMemId
);
870 static HRESULT WINAPI
ScriptTypeInfo_Invoke(ITypeInfo
*iface
, PVOID pvInstance
, MEMBERID memid
, WORD wFlags
,
871 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
873 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
874 ITypeInfo
*disp_typeinfo
;
878 TRACE("(%p)->(%p %ld %d %p %p %p %p)\n", This
, pvInstance
, memid
, wFlags
,
879 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
881 if (!pvInstance
) return E_INVALIDARG
;
882 if (memid
<= 0) return TYPE_E_ELEMENTNOTFOUND
;
884 if (!get_func_from_memid(This
, memid
) && memid
> This
->num_vars
)
886 hr
= get_dispatch_typeinfo(&disp_typeinfo
);
887 if (FAILED(hr
)) return hr
;
889 return ITypeInfo_Invoke(disp_typeinfo
, pvInstance
, memid
, wFlags
, pDispParams
,
890 pVarResult
, pExcepInfo
, puArgErr
);
893 hr
= IUnknown_QueryInterface((IUnknown
*)pvInstance
, &IID_IDispatch
, (void**)&disp
);
894 if (FAILED(hr
)) return hr
;
896 hr
= IDispatch_Invoke(disp
, memid
, &IID_NULL
, LOCALE_USER_DEFAULT
, wFlags
,
897 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
898 IDispatch_Release(disp
);
903 static HRESULT WINAPI
ScriptTypeInfo_GetDocumentation(ITypeInfo
*iface
, MEMBERID memid
, BSTR
*pBstrName
,
904 BSTR
*pBstrDocString
, DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
906 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
907 ITypeInfo
*disp_typeinfo
;
911 TRACE("(%p)->(%ld %p %p %p %p)\n", This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
913 if (pBstrDocString
) *pBstrDocString
= NULL
;
914 if (pdwHelpContext
) *pdwHelpContext
= 0;
915 if (pBstrHelpFile
) *pBstrHelpFile
= NULL
;
917 if (memid
== MEMBERID_NIL
)
919 if (pBstrName
&& !(*pBstrName
= SysAllocString(L
"VBScriptTypeInfo")))
920 return E_OUTOFMEMORY
;
921 if (pBstrDocString
&&
922 !(*pBstrDocString
= SysAllocString(L
"Visual Basic Scripting Type Info")))
924 if (pBstrName
) SysFreeString(*pBstrName
);
925 return E_OUTOFMEMORY
;
929 if (memid
<= 0) return TYPE_E_ELEMENTNOTFOUND
;
931 func
= get_func_from_memid(This
, memid
);
932 if (!func
&& memid
> This
->num_vars
)
934 hr
= get_dispatch_typeinfo(&disp_typeinfo
);
935 if (FAILED(hr
)) return hr
;
937 return ITypeInfo_GetDocumentation(disp_typeinfo
, memid
, pBstrName
, pBstrDocString
,
938 pdwHelpContext
, pBstrHelpFile
);
943 *pBstrName
= SysAllocString(func
? func
->name
: This
->disp
->global_vars
[memid
- 1]->name
);
944 if (!*pBstrName
) return E_OUTOFMEMORY
;
949 static HRESULT WINAPI
ScriptTypeInfo_GetDllEntry(ITypeInfo
*iface
, MEMBERID memid
, INVOKEKIND invKind
,
950 BSTR
*pBstrDllName
, BSTR
*pBstrName
, WORD
*pwOrdinal
)
952 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
953 ITypeInfo
*disp_typeinfo
;
956 TRACE("(%p)->(%ld %d %p %p %p)\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
958 if (pBstrDllName
) *pBstrDllName
= NULL
;
959 if (pBstrName
) *pBstrName
= NULL
;
960 if (pwOrdinal
) *pwOrdinal
= 0;
962 if (!get_func_from_memid(This
, memid
) && memid
> This
->num_vars
)
964 hr
= get_dispatch_typeinfo(&disp_typeinfo
);
965 if (FAILED(hr
)) return hr
;
967 return ITypeInfo_GetDllEntry(disp_typeinfo
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
969 return TYPE_E_BADMODULEKIND
;
972 static HRESULT WINAPI
ScriptTypeInfo_GetRefTypeInfo(ITypeInfo
*iface
, HREFTYPE hRefType
, ITypeInfo
**ppTInfo
)
974 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
977 TRACE("(%p)->(%lx %p)\n", This
, hRefType
, ppTInfo
);
979 if (!ppTInfo
|| (INT
)hRefType
< 0) return E_INVALIDARG
;
981 if (hRefType
& ~3) return E_FAIL
;
984 hr
= get_dispatch_typeinfo(ppTInfo
);
985 if (FAILED(hr
)) return hr
;
990 ITypeInfo_AddRef(*ppTInfo
);
994 static HRESULT WINAPI
ScriptTypeInfo_AddressOfMember(ITypeInfo
*iface
, MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
996 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
997 ITypeInfo
*disp_typeinfo
;
1000 TRACE("(%p)->(%ld %d %p)\n", This
, memid
, invKind
, ppv
);
1002 if (!ppv
) return E_INVALIDARG
;
1005 if (!get_func_from_memid(This
, memid
) && memid
> This
->num_vars
)
1007 hr
= get_dispatch_typeinfo(&disp_typeinfo
);
1008 if (FAILED(hr
)) return hr
;
1010 return ITypeInfo_AddressOfMember(disp_typeinfo
, memid
, invKind
, ppv
);
1012 return TYPE_E_BADMODULEKIND
;
1015 static HRESULT WINAPI
ScriptTypeInfo_CreateInstance(ITypeInfo
*iface
, IUnknown
*pUnkOuter
, REFIID riid
, PVOID
*ppvObj
)
1017 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
1019 TRACE("(%p)->(%p %s %p)\n", This
, pUnkOuter
, debugstr_guid(riid
), ppvObj
);
1021 if (!ppvObj
) return E_INVALIDARG
;
1024 return TYPE_E_BADMODULEKIND
;
1027 static HRESULT WINAPI
ScriptTypeInfo_GetMops(ITypeInfo
*iface
, MEMBERID memid
, BSTR
*pBstrMops
)
1029 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
1030 ITypeInfo
*disp_typeinfo
;
1033 TRACE("(%p)->(%ld %p)\n", This
, memid
, pBstrMops
);
1035 if (!pBstrMops
) return E_INVALIDARG
;
1037 if (!get_func_from_memid(This
, memid
) && memid
> This
->num_vars
)
1039 hr
= get_dispatch_typeinfo(&disp_typeinfo
);
1040 if (FAILED(hr
)) return hr
;
1042 return ITypeInfo_GetMops(disp_typeinfo
, memid
, pBstrMops
);
1049 static HRESULT WINAPI
ScriptTypeInfo_GetContainingTypeLib(ITypeInfo
*iface
, ITypeLib
**ppTLib
, UINT
*pIndex
)
1051 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
1053 FIXME("(%p)->(%p %p)\n", This
, ppTLib
, pIndex
);
1058 static void WINAPI
ScriptTypeInfo_ReleaseTypeAttr(ITypeInfo
*iface
, TYPEATTR
*pTypeAttr
)
1060 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
1062 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
1064 heap_free(pTypeAttr
);
1067 static void WINAPI
ScriptTypeInfo_ReleaseFuncDesc(ITypeInfo
*iface
, FUNCDESC
*pFuncDesc
)
1069 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
1071 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
1073 heap_free(pFuncDesc
);
1076 static void WINAPI
ScriptTypeInfo_ReleaseVarDesc(ITypeInfo
*iface
, VARDESC
*pVarDesc
)
1078 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
1080 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
1082 heap_free(pVarDesc
);
1085 static const ITypeInfoVtbl ScriptTypeInfoVtbl
= {
1086 ScriptTypeInfo_QueryInterface
,
1087 ScriptTypeInfo_AddRef
,
1088 ScriptTypeInfo_Release
,
1089 ScriptTypeInfo_GetTypeAttr
,
1090 ScriptTypeInfo_GetTypeComp
,
1091 ScriptTypeInfo_GetFuncDesc
,
1092 ScriptTypeInfo_GetVarDesc
,
1093 ScriptTypeInfo_GetNames
,
1094 ScriptTypeInfo_GetRefTypeOfImplType
,
1095 ScriptTypeInfo_GetImplTypeFlags
,
1096 ScriptTypeInfo_GetIDsOfNames
,
1097 ScriptTypeInfo_Invoke
,
1098 ScriptTypeInfo_GetDocumentation
,
1099 ScriptTypeInfo_GetDllEntry
,
1100 ScriptTypeInfo_GetRefTypeInfo
,
1101 ScriptTypeInfo_AddressOfMember
,
1102 ScriptTypeInfo_CreateInstance
,
1103 ScriptTypeInfo_GetMops
,
1104 ScriptTypeInfo_GetContainingTypeLib
,
1105 ScriptTypeInfo_ReleaseTypeAttr
,
1106 ScriptTypeInfo_ReleaseFuncDesc
,
1107 ScriptTypeInfo_ReleaseVarDesc
1110 static HRESULT WINAPI
ScriptTypeComp_QueryInterface(ITypeComp
*iface
, REFIID riid
, void **ppv
)
1112 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeComp(iface
);
1113 return ITypeInfo_QueryInterface(&This
->ITypeInfo_iface
, riid
, ppv
);
1116 static ULONG WINAPI
ScriptTypeComp_AddRef(ITypeComp
*iface
)
1118 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeComp(iface
);
1119 return ITypeInfo_AddRef(&This
->ITypeInfo_iface
);
1122 static ULONG WINAPI
ScriptTypeComp_Release(ITypeComp
*iface
)
1124 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeComp(iface
);
1125 return ITypeInfo_Release(&This
->ITypeInfo_iface
);
1128 static HRESULT WINAPI
ScriptTypeComp_Bind(ITypeComp
*iface
, LPOLESTR szName
, ULONG lHashVal
, WORD wFlags
,
1129 ITypeInfo
**ppTInfo
, DESCKIND
*pDescKind
, BINDPTR
*pBindPtr
)
1131 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeComp(iface
);
1132 UINT flags
= wFlags
? wFlags
: ~0;
1133 ITypeInfo
*disp_typeinfo
;
1134 ITypeComp
*disp_typecomp
;
1138 TRACE("(%p)->(%s %08lx %d %p %p %p)\n", This
, debugstr_w(szName
), lHashVal
,
1139 wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
1141 if (!szName
|| !ppTInfo
|| !pDescKind
|| !pBindPtr
)
1142 return E_INVALIDARG
;
1144 for (i
= 0; i
< This
->num_funcs
; i
++)
1146 if (wcsicmp(szName
, This
->funcs
[i
].func
->name
)) continue;
1147 if (!(flags
& INVOKE_FUNC
)) return TYPE_E_TYPEMISMATCH
;
1149 hr
= ITypeInfo_GetFuncDesc(&This
->ITypeInfo_iface
, i
, &pBindPtr
->lpfuncdesc
);
1150 if (FAILED(hr
)) return hr
;
1152 *pDescKind
= DESCKIND_FUNCDESC
;
1153 *ppTInfo
= &This
->ITypeInfo_iface
;
1154 ITypeInfo_AddRef(*ppTInfo
);
1158 for (i
= 0; i
< This
->num_vars
; i
++)
1160 if (wcsicmp(szName
, This
->disp
->global_vars
[i
]->name
)) continue;
1161 if (!(flags
& INVOKE_PROPERTYGET
)) return TYPE_E_TYPEMISMATCH
;
1163 hr
= ITypeInfo_GetVarDesc(&This
->ITypeInfo_iface
, i
, &pBindPtr
->lpvardesc
);
1164 if (FAILED(hr
)) return hr
;
1166 *pDescKind
= DESCKIND_VARDESC
;
1167 *ppTInfo
= &This
->ITypeInfo_iface
;
1168 ITypeInfo_AddRef(*ppTInfo
);
1172 /* Look into the inherited IDispatch */
1173 hr
= get_dispatch_typeinfo(&disp_typeinfo
);
1174 if (FAILED(hr
)) return hr
;
1176 hr
= ITypeInfo_GetTypeComp(disp_typeinfo
, &disp_typecomp
);
1177 if (FAILED(hr
)) return hr
;
1179 hr
= ITypeComp_Bind(disp_typecomp
, szName
, lHashVal
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
1180 ITypeComp_Release(disp_typecomp
);
1184 static HRESULT WINAPI
ScriptTypeComp_BindType(ITypeComp
*iface
, LPOLESTR szName
, ULONG lHashVal
,
1185 ITypeInfo
**ppTInfo
, ITypeComp
**ppTComp
)
1187 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeComp(iface
);
1188 ITypeInfo
*disp_typeinfo
;
1189 ITypeComp
*disp_typecomp
;
1192 TRACE("(%p)->(%s %08lx %p %p)\n", This
, debugstr_w(szName
), lHashVal
, ppTInfo
, ppTComp
);
1194 if (!szName
|| !ppTInfo
|| !ppTComp
)
1195 return E_INVALIDARG
;
1197 /* Look into the inherited IDispatch */
1198 hr
= get_dispatch_typeinfo(&disp_typeinfo
);
1199 if (FAILED(hr
)) return hr
;
1201 hr
= ITypeInfo_GetTypeComp(disp_typeinfo
, &disp_typecomp
);
1202 if (FAILED(hr
)) return hr
;
1204 hr
= ITypeComp_BindType(disp_typecomp
, szName
, lHashVal
, ppTInfo
, ppTComp
);
1205 ITypeComp_Release(disp_typecomp
);
1209 static const ITypeCompVtbl ScriptTypeCompVtbl
= {
1210 ScriptTypeComp_QueryInterface
,
1211 ScriptTypeComp_AddRef
,
1212 ScriptTypeComp_Release
,
1213 ScriptTypeComp_Bind
,
1214 ScriptTypeComp_BindType
1217 static inline ScriptDisp
*ScriptDisp_from_IDispatchEx(IDispatchEx
*iface
)
1219 return CONTAINING_RECORD(iface
, ScriptDisp
, IDispatchEx_iface
);
1222 static HRESULT WINAPI
ScriptDisp_QueryInterface(IDispatchEx
*iface
, REFIID riid
, void **ppv
)
1224 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1226 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
1227 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
1228 *ppv
= &This
->IDispatchEx_iface
;
1229 }else if(IsEqualGUID(&IID_IDispatch
, riid
)) {
1230 TRACE("(%p)->(IID_IDispatch %p)\n", This
, ppv
);
1231 *ppv
= &This
->IDispatchEx_iface
;
1232 }else if(IsEqualGUID(&IID_IDispatchEx
, riid
)) {
1233 TRACE("(%p)->(IID_IDispatchEx %p)\n", This
, ppv
);
1234 *ppv
= &This
->IDispatchEx_iface
;
1236 WARN("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
1238 return E_NOINTERFACE
;
1241 IUnknown_AddRef((IUnknown
*)*ppv
);
1245 static ULONG WINAPI
ScriptDisp_AddRef(IDispatchEx
*iface
)
1247 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1248 LONG ref
= InterlockedIncrement(&This
->ref
);
1250 TRACE("(%p) ref=%ld\n", This
, ref
);
1255 static ULONG WINAPI
ScriptDisp_Release(IDispatchEx
*iface
)
1257 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1258 LONG ref
= InterlockedDecrement(&This
->ref
);
1261 TRACE("(%p) ref=%ld\n", This
, ref
);
1266 for (i
= 0; i
< This
->global_vars_cnt
; i
++)
1267 release_dynamic_var(This
->global_vars
[i
]);
1269 heap_pool_free(&This
->heap
);
1270 heap_free(This
->global_vars
);
1271 heap_free(This
->global_funcs
);
1278 static HRESULT WINAPI
ScriptDisp_GetTypeInfoCount(IDispatchEx
*iface
, UINT
*pctinfo
)
1280 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1282 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1288 static HRESULT WINAPI
ScriptDisp_GetTypeInfo(IDispatchEx
*iface
, UINT iTInfo
, LCID lcid
, ITypeInfo
**ret
)
1290 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1291 ScriptTypeInfo
*type_info
;
1295 TRACE("(%p)->(%u %lu %p)\n", This
, iTInfo
, lcid
, ret
);
1298 return DISP_E_BADINDEX
;
1300 if(!(type_info
= heap_alloc(sizeof(*type_info
))))
1301 return E_OUTOFMEMORY
;
1303 for(i
= 0; i
< This
->global_funcs_cnt
; i
++)
1304 if(This
->global_funcs
[i
]->is_public
)
1307 type_info
->ITypeInfo_iface
.lpVtbl
= &ScriptTypeInfoVtbl
;
1308 type_info
->ITypeComp_iface
.lpVtbl
= &ScriptTypeCompVtbl
;
1310 type_info
->num_funcs
= num_funcs
;
1311 type_info
->num_vars
= This
->global_vars_cnt
;
1312 type_info
->disp
= This
;
1314 type_info
->funcs
= heap_alloc(sizeof(*type_info
->funcs
) * num_funcs
);
1315 if(!type_info
->funcs
)
1317 heap_free(type_info
);
1318 return E_OUTOFMEMORY
;
1321 for(j
= 0, i
= 0; i
< This
->global_funcs_cnt
; i
++)
1323 if(!This
->global_funcs
[i
]->is_public
) continue;
1325 type_info
->funcs
[j
].memid
= i
+ 1 + DISPID_FUNCTION_MASK
;
1326 type_info
->funcs
[j
].func
= This
->global_funcs
[i
];
1327 grab_vbscode(This
->global_funcs
[i
]->code_ctx
);
1331 IDispatchEx_AddRef(&This
->IDispatchEx_iface
);
1333 *ret
= &type_info
->ITypeInfo_iface
;
1337 static HRESULT WINAPI
ScriptDisp_GetIDsOfNames(IDispatchEx
*iface
, REFIID riid
,
1338 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
1340 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1344 TRACE("(%p)->(%s %p %u %lu %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
,
1350 hres
= IDispatchEx_GetDispID(&This
->IDispatchEx_iface
, rgszNames
[0], 0, rgDispId
);
1354 /* DISPIDs for parameters don't seem to be supported */
1356 for(i
= 1; i
< cNames
; i
++)
1357 rgDispId
[i
] = DISPID_UNKNOWN
;
1358 hres
= DISP_E_UNKNOWNNAME
;
1364 static HRESULT WINAPI
ScriptDisp_Invoke(IDispatchEx
*iface
, DISPID dispIdMember
, REFIID riid
, LCID lcid
,
1365 WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1367 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1369 TRACE("(%p)->(%ld %s %ld %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
1370 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1372 return IDispatchEx_InvokeEx(&This
->IDispatchEx_iface
, dispIdMember
, lcid
, wFlags
,
1373 pDispParams
, pVarResult
, pExcepInfo
, NULL
);
1376 static HRESULT WINAPI
ScriptDisp_GetDispID(IDispatchEx
*iface
, BSTR bstrName
, DWORD grfdex
, DISPID
*pid
)
1378 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1381 TRACE("(%p)->(%s %lx %p)\n", This
, debugstr_w(bstrName
), grfdex
, pid
);
1384 return E_UNEXPECTED
;
1386 for(i
= 0; i
< This
->global_vars_cnt
; i
++) {
1387 if(!wcsicmp(This
->global_vars
[i
]->name
, bstrName
)) {
1393 for(i
= 0; i
< This
->global_funcs_cnt
; i
++) {
1394 if(!wcsicmp(This
->global_funcs
[i
]->name
, bstrName
)) {
1395 *pid
= i
+ 1 + DISPID_FUNCTION_MASK
;
1401 return DISP_E_UNKNOWNNAME
;
1404 static HRESULT WINAPI
ScriptDisp_InvokeEx(IDispatchEx
*iface
, DISPID id
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pdp
,
1405 VARIANT
*pvarRes
, EXCEPINFO
*pei
, IServiceProvider
*pspCaller
)
1407 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1410 TRACE("(%p)->(%lx %lx %x %p %p %p %p)\n", This
, id
, lcid
, wFlags
, pdp
, pvarRes
, pei
, pspCaller
);
1413 return E_UNEXPECTED
;
1415 if (id
& DISPID_FUNCTION_MASK
)
1417 id
&= ~DISPID_FUNCTION_MASK
;
1418 if (id
> This
->global_funcs_cnt
)
1419 return DISP_E_MEMBERNOTFOUND
;
1423 case DISPATCH_METHOD
:
1424 case DISPATCH_METHOD
| DISPATCH_PROPERTYGET
:
1425 hres
= exec_script(This
->ctx
, TRUE
, This
->global_funcs
[id
- 1], NULL
, pdp
, pvarRes
);
1428 FIXME("Unsupported flags %x\n", wFlags
);
1435 if (id
> This
->global_vars_cnt
)
1436 return DISP_E_MEMBERNOTFOUND
;
1438 if (This
->global_vars
[id
- 1]->is_const
)
1440 FIXME("const not supported\n");
1444 return invoke_variant_prop(This
->ctx
, &This
->global_vars
[id
- 1]->v
, wFlags
, pdp
, pvarRes
);
1447 static HRESULT WINAPI
ScriptDisp_DeleteMemberByName(IDispatchEx
*iface
, BSTR bstrName
, DWORD grfdex
)
1449 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1450 FIXME("(%p)->(%s %lx)\n", This
, debugstr_w(bstrName
), grfdex
);
1454 static HRESULT WINAPI
ScriptDisp_DeleteMemberByDispID(IDispatchEx
*iface
, DISPID id
)
1456 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1457 FIXME("(%p)->(%lx)\n", This
, id
);
1461 static HRESULT WINAPI
ScriptDisp_GetMemberProperties(IDispatchEx
*iface
, DISPID id
, DWORD grfdexFetch
, DWORD
*pgrfdex
)
1463 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1464 FIXME("(%p)->(%lx %lx %p)\n", This
, id
, grfdexFetch
, pgrfdex
);
1468 static HRESULT WINAPI
ScriptDisp_GetMemberName(IDispatchEx
*iface
, DISPID id
, BSTR
*pbstrName
)
1470 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1471 FIXME("(%p)->(%lx %p)\n", This
, id
, pbstrName
);
1475 static HRESULT WINAPI
ScriptDisp_GetNextDispID(IDispatchEx
*iface
, DWORD grfdex
, DISPID id
, DISPID
*pid
)
1477 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1478 FIXME("(%p)->(%lx %lx %p)\n", This
, grfdex
, id
, pid
);
1482 static HRESULT WINAPI
ScriptDisp_GetNameSpaceParent(IDispatchEx
*iface
, IUnknown
**ppunk
)
1484 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1485 FIXME("(%p)->(%p)\n", This
, ppunk
);
1489 static IDispatchExVtbl ScriptDispVtbl
= {
1490 ScriptDisp_QueryInterface
,
1493 ScriptDisp_GetTypeInfoCount
,
1494 ScriptDisp_GetTypeInfo
,
1495 ScriptDisp_GetIDsOfNames
,
1497 ScriptDisp_GetDispID
,
1498 ScriptDisp_InvokeEx
,
1499 ScriptDisp_DeleteMemberByName
,
1500 ScriptDisp_DeleteMemberByDispID
,
1501 ScriptDisp_GetMemberProperties
,
1502 ScriptDisp_GetMemberName
,
1503 ScriptDisp_GetNextDispID
,
1504 ScriptDisp_GetNameSpaceParent
1507 HRESULT
create_script_disp(script_ctx_t
*ctx
, ScriptDisp
**ret
)
1509 ScriptDisp
*script_disp
;
1511 script_disp
= heap_alloc_zero(sizeof(*script_disp
));
1513 return E_OUTOFMEMORY
;
1515 script_disp
->IDispatchEx_iface
.lpVtbl
= &ScriptDispVtbl
;
1516 script_disp
->ref
= 1;
1517 script_disp
->ctx
= ctx
;
1518 heap_pool_init(&script_disp
->heap
);
1524 void collect_objects(script_ctx_t
*ctx
)
1526 vbdisp_t
*iter
, *iter2
;
1528 LIST_FOR_EACH_ENTRY_SAFE(iter
, iter2
, &ctx
->objects
, vbdisp_t
, entry
)
1529 run_terminator(iter
);
1531 while(!list_empty(&ctx
->objects
)) {
1532 iter
= LIST_ENTRY(list_head(&ctx
->objects
), vbdisp_t
, entry
);
1534 IDispatchEx_AddRef(&iter
->IDispatchEx_iface
);
1537 list_remove(&iter
->entry
);
1538 list_init(&iter
->entry
);
1539 IDispatchEx_Release(&iter
->IDispatchEx_iface
);
1543 HRESULT
disp_get_id(IDispatch
*disp
, BSTR name
, vbdisp_invoke_type_t invoke_type
, BOOL search_private
, DISPID
*id
)
1545 IDispatchEx
*dispex
;
1549 vbdisp
= unsafe_impl_from_IDispatch(disp
);
1551 return vbdisp_get_id(vbdisp
, name
, invoke_type
, search_private
, id
);
1553 hres
= IDispatch_QueryInterface(disp
, &IID_IDispatchEx
, (void**)&dispex
);
1555 TRACE("using IDispatch\n");
1556 return IDispatch_GetIDsOfNames(disp
, &IID_NULL
, &name
, 1, 0, id
);
1559 hres
= IDispatchEx_GetDispID(dispex
, name
, fdexNameCaseInsensitive
, id
);
1560 IDispatchEx_Release(dispex
);
1564 #define RPC_E_SERVER_UNAVAILABLE 0x800706ba
1566 void map_vbs_exception(EXCEPINFO
*ei
)
1570 if(HRESULT_FACILITY(ei
->scode
) == FACILITY_VBS
)
1571 vbse_number
= HRESULT_CODE(ei
->scode
);
1575 case E_NOTIMPL
: vbse_number
= VBSE_ACTION_NOT_SUPPORTED
; break;
1576 case E_NOINTERFACE
: vbse_number
= VBSE_OLE_NOT_SUPPORTED
; break;
1577 case DISP_E_UNKNOWNINTERFACE
: vbse_number
= VBSE_OLE_NO_PROP_OR_METHOD
; break;
1578 case DISP_E_MEMBERNOTFOUND
: vbse_number
= VBSE_OLE_NO_PROP_OR_METHOD
; break;
1579 case DISP_E_PARAMNOTFOUND
: vbse_number
= VBSE_NAMED_PARAM_NOT_FOUND
; break;
1580 case DISP_E_TYPEMISMATCH
: vbse_number
= VBSE_TYPE_MISMATCH
; break;
1581 case DISP_E_UNKNOWNNAME
: vbse_number
= VBSE_OLE_NO_PROP_OR_METHOD
; break;
1582 case DISP_E_NONAMEDARGS
: vbse_number
= VBSE_NAMED_ARGS_NOT_SUPPORTED
; break;
1583 case DISP_E_BADVARTYPE
: vbse_number
= VBSE_INVALID_TYPELIB_VARIABLE
; break;
1584 case DISP_E_OVERFLOW
: vbse_number
= VBSE_OVERFLOW
; break;
1585 case DISP_E_BADINDEX
: vbse_number
= VBSE_OUT_OF_BOUNDS
; break;
1586 case DISP_E_UNKNOWNLCID
: vbse_number
= VBSE_LOCALE_SETTING_NOT_SUPPORTED
; break;
1587 case DISP_E_ARRAYISLOCKED
: vbse_number
= VBSE_ARRAY_LOCKED
; break;
1588 case DISP_E_BADPARAMCOUNT
: vbse_number
= VBSE_FUNC_ARITY_MISMATCH
; break;
1589 case DISP_E_PARAMNOTOPTIONAL
: vbse_number
= VBSE_PARAMETER_NOT_OPTIONAL
; break;
1590 case DISP_E_NOTACOLLECTION
: vbse_number
= VBSE_NOT_ENUM
; break;
1591 case TYPE_E_DLLFUNCTIONNOTFOUND
: vbse_number
= VBSE_INVALID_DLL_FUNCTION_NAME
; break;
1592 case TYPE_E_TYPEMISMATCH
: vbse_number
= VBSE_TYPE_MISMATCH
; break;
1593 case TYPE_E_OUTOFBOUNDS
: vbse_number
= VBSE_OUT_OF_BOUNDS
; break;
1594 case TYPE_E_IOERROR
: vbse_number
= VBSE_IO_ERROR
; break;
1595 case TYPE_E_CANTCREATETMPFILE
: vbse_number
= VBSE_CANT_CREATE_TMP_FILE
; break;
1596 case STG_E_FILENOTFOUND
: vbse_number
= VBSE_OLE_FILE_NOT_FOUND
; break;
1597 case STG_E_PATHNOTFOUND
: vbse_number
= VBSE_PATH_NOT_FOUND
; break;
1598 case STG_E_TOOMANYOPENFILES
: vbse_number
= VBSE_TOO_MANY_FILES
; break;
1599 case STG_E_ACCESSDENIED
: vbse_number
= VBSE_PERMISSION_DENIED
; break;
1600 case STG_E_INSUFFICIENTMEMORY
: vbse_number
= VBSE_OUT_OF_MEMORY
; break;
1601 case STG_E_NOMOREFILES
: vbse_number
= VBSE_TOO_MANY_FILES
; break;
1602 case STG_E_DISKISWRITEPROTECTED
: vbse_number
= VBSE_PERMISSION_DENIED
; break;
1603 case STG_E_WRITEFAULT
: vbse_number
= VBSE_IO_ERROR
; break;
1604 case STG_E_READFAULT
: vbse_number
= VBSE_IO_ERROR
; break;
1605 case STG_E_SHAREVIOLATION
: vbse_number
= VBSE_PATH_FILE_ACCESS
; break;
1606 case STG_E_LOCKVIOLATION
: vbse_number
= VBSE_PERMISSION_DENIED
; break;
1607 case STG_E_FILEALREADYEXISTS
: vbse_number
= VBSE_FILE_ALREADY_EXISTS
; break;
1608 case STG_E_MEDIUMFULL
: vbse_number
= VBSE_DISK_FULL
; break;
1609 case STG_E_INVALIDNAME
: vbse_number
= VBSE_FILE_NOT_FOUND
; break;
1610 case STG_E_INUSE
: vbse_number
= VBSE_PERMISSION_DENIED
; break;
1611 case STG_E_NOTCURRENT
: vbse_number
= VBSE_PERMISSION_DENIED
; break;
1612 case STG_E_CANTSAVE
: vbse_number
= VBSE_IO_ERROR
; break;
1613 case REGDB_E_CLASSNOTREG
: vbse_number
= VBSE_CANT_CREATE_OBJECT
; break;
1614 case MK_E_UNAVAILABLE
: vbse_number
= VBSE_CANT_CREATE_OBJECT
; break;
1615 case MK_E_INVALIDEXTENSION
: vbse_number
= VBSE_OLE_FILE_NOT_FOUND
; break;
1616 case MK_E_CANTOPENFILE
: vbse_number
= VBSE_OLE_FILE_NOT_FOUND
; break;
1617 case CO_E_CLASSSTRING
: vbse_number
= VBSE_CANT_CREATE_OBJECT
; break;
1618 case CO_E_APPNOTFOUND
: vbse_number
= VBSE_CANT_CREATE_OBJECT
; break;
1619 case CO_E_APPDIDNTREG
: vbse_number
= VBSE_CANT_CREATE_OBJECT
; break;
1620 case E_ACCESSDENIED
: vbse_number
= VBSE_PERMISSION_DENIED
; break;
1621 case E_OUTOFMEMORY
: vbse_number
= VBSE_OUT_OF_MEMORY
; break;
1622 case E_INVALIDARG
: vbse_number
= VBSE_ILLEGAL_FUNC_CALL
; break;
1623 case RPC_E_SERVER_UNAVAILABLE
: vbse_number
= VBSE_SERVER_NOT_FOUND
; break;
1624 case CO_E_SERVER_EXEC_FAILURE
: vbse_number
= VBSE_CANT_CREATE_OBJECT
; break;
1625 default: return; /* early return, all other HRESULT left as-is */
1627 ei
->scode
= MAKE_VBSERROR(vbse_number
);
1630 ei
->bstrSource
= get_vbscript_string(VBS_RUNTIME_ERROR
);
1631 if(!ei
->bstrDescription
)
1632 if(!(ei
->bstrDescription
= get_vbscript_string(vbse_number
)))
1633 ei
->bstrDescription
= get_vbscript_string(VBS_UNKNOWN_RUNTIME_ERROR
);
1636 HRESULT
disp_call(script_ctx_t
*ctx
, IDispatch
*disp
, DISPID id
, DISPPARAMS
*dp
, VARIANT
*retv
)
1638 const WORD flags
= DISPATCH_METHOD
|(retv
? DISPATCH_PROPERTYGET
: 0);
1639 IDispatchEx
*dispex
;
1644 memset(&ei
, 0, sizeof(ei
));
1646 V_VT(retv
) = VT_EMPTY
;
1648 vbdisp
= unsafe_impl_from_IDispatch(disp
);
1649 if(vbdisp
&& vbdisp
->desc
&& vbdisp
->desc
->ctx
== ctx
)
1650 return invoke_vbdisp(vbdisp
, id
, flags
, FALSE
, dp
, retv
);
1652 hres
= IDispatch_QueryInterface(disp
, &IID_IDispatchEx
, (void**)&dispex
);
1653 if(SUCCEEDED(hres
)) {
1654 hres
= IDispatchEx_InvokeEx(dispex
, id
, ctx
->lcid
, flags
, dp
, retv
, &ei
, NULL
/* CALLER_FIXME */);
1655 IDispatchEx_Release(dispex
);
1659 TRACE("using IDispatch\n");
1660 hres
= IDispatch_Invoke(disp
, id
, &IID_NULL
, ctx
->lcid
, flags
, dp
, retv
, &ei
, &err
);
1663 if(hres
== DISP_E_EXCEPTION
) {
1666 hres
= SCRIPT_E_RECORDED
;
1671 HRESULT
get_disp_value(script_ctx_t
*ctx
, IDispatch
*disp
, VARIANT
*v
)
1673 DISPPARAMS dp
= {NULL
};
1675 return MAKE_VBSERROR(VBSE_OBJECT_VARIABLE_NOT_SET
);
1676 return disp_call(ctx
, disp
, DISPID_VALUE
, &dp
, v
);
1679 HRESULT
disp_propput(script_ctx_t
*ctx
, IDispatch
*disp
, DISPID id
, WORD flags
, DISPPARAMS
*dp
)
1681 IDispatchEx
*dispex
;
1686 vbdisp
= unsafe_impl_from_IDispatch(disp
);
1687 if(vbdisp
&& vbdisp
->desc
&& vbdisp
->desc
->ctx
== ctx
)
1688 return invoke_vbdisp(vbdisp
, id
, flags
, FALSE
, dp
, NULL
);
1690 hres
= IDispatch_QueryInterface(disp
, &IID_IDispatchEx
, (void**)&dispex
);
1691 if(SUCCEEDED(hres
)) {
1692 hres
= IDispatchEx_InvokeEx(dispex
, id
, ctx
->lcid
, flags
, dp
, NULL
, &ei
, NULL
/* FIXME! */);
1693 IDispatchEx_Release(dispex
);
1697 TRACE("using IDispatch\n");
1698 hres
= IDispatch_Invoke(disp
, id
, &IID_NULL
, ctx
->lcid
, flags
, dp
, NULL
, &ei
, &err
);
1701 if(hres
== DISP_E_EXCEPTION
) {
1704 hres
= SCRIPT_E_RECORDED
;