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
:
127 WARN("called with arguments for non-array property\n");
128 return DISP_E_MEMBERNOTFOUND
; /* That's what tests show */
131 if (FAILED(hres
= array_access(V_ARRAY(v
), dp
, &v
)))
133 WARN("failed to access array element\n");
138 hres
= VariantCopyInd(res
, v
);
141 case DISPATCH_PROPERTYPUT
:
142 case DISPATCH_PROPERTYPUTREF
:
143 case DISPATCH_PROPERTYPUT
|DISPATCH_PROPERTYPUTREF
: {
147 hres
= get_propput_arg(ctx
, dp
, flags
, &put_val
, &own_val
);
152 FIXME("Arguments not supported\n");
157 V_VT(res
) = VT_EMPTY
;
162 hres
= VariantCopyInd(v
, &put_val
);
167 FIXME("unimplemented flags %x\n", flags
);
174 static HRESULT
invoke_vbdisp(vbdisp_t
*This
, DISPID id
, DWORD flags
, BOOL extern_caller
, DISPPARAMS
*params
, VARIANT
*res
)
177 return DISP_E_MEMBERNOTFOUND
;
179 if(is_func_id(This
, id
)) {
182 TRACE("%p->%s\n", This
, debugstr_w(This
->desc
->funcs
[id
].name
));
185 case DISPATCH_PROPERTYGET
:
186 func
= This
->desc
->funcs
[id
].entries
[VBDISP_CALLGET
];
187 if(!func
|| func
->type
!= FUNC_PROPGET
) {
189 return DISP_E_MEMBERNOTFOUND
;
192 return exec_script(This
->desc
->ctx
, extern_caller
, func
, This
, params
, res
);
194 case DISPATCH_METHOD
:
195 case DISPATCH_METHOD
|DISPATCH_PROPERTYGET
:
196 func
= This
->desc
->funcs
[id
].entries
[VBDISP_CALLGET
];
198 FIXME("no invoke/getter\n");
199 return DISP_E_MEMBERNOTFOUND
;
202 return exec_script(This
->desc
->ctx
, extern_caller
, func
, This
, params
, res
);
204 case DISPATCH_PROPERTYPUT
:
205 case DISPATCH_PROPERTYPUTREF
:
206 case DISPATCH_PROPERTYPUT
|DISPATCH_PROPERTYPUTREF
: {
207 DISPPARAMS dp
= {NULL
, NULL
, 1, 0};
213 dp
.cArgs
= arg_cnt(params
) + 1;
214 if(dp
.cArgs
> ARRAY_SIZE(buf
)) {
215 dp
.rgvarg
= malloc(dp
.cArgs
*sizeof(VARIANT
));
217 return E_OUTOFMEMORY
;
222 hres
= get_propput_arg(This
->desc
->ctx
, params
, flags
, dp
.rgvarg
, &needs_release
);
229 func
= This
->desc
->funcs
[id
].entries
[V_VT(dp
.rgvarg
) == VT_DISPATCH
? VBDISP_SET
: VBDISP_LET
];
231 FIXME("no letter/setter\n");
234 return DISP_E_MEMBERNOTFOUND
;
237 for(i
=1; i
< dp
.cArgs
; i
++) {
238 dp
.rgvarg
[i
]=params
->rgvarg
[params
->cNamedArgs
+i
-1];
241 hres
= exec_script(This
->desc
->ctx
, extern_caller
, func
, This
, &dp
, NULL
);
243 VariantClear(dp
.rgvarg
);
249 FIXME("flags %lx\n", flags
);
250 return DISP_E_MEMBERNOTFOUND
;
254 if(id
>= This
->desc
->prop_cnt
+ This
->desc
->func_cnt
)
255 return DISP_E_MEMBERNOTFOUND
;
257 TRACE("%p->%s\n", This
, debugstr_w(This
->desc
->props
[id
- This
->desc
->func_cnt
].name
));
258 return invoke_variant_prop(This
->desc
->ctx
, This
->props
+(id
-This
->desc
->func_cnt
), flags
, params
, res
);
261 static BOOL
run_terminator(vbdisp_t
*This
)
265 if(This
->terminator_ran
)
267 This
->terminator_ran
= TRUE
;
269 if(!This
->desc
->class_terminate_id
)
273 exec_script(This
->desc
->ctx
, FALSE
, This
->desc
->funcs
[This
->desc
->class_terminate_id
].entries
[VBDISP_CALLGET
],
278 static void clean_props(vbdisp_t
*This
)
285 for(i
=0; i
< This
->desc
->array_cnt
; i
++) {
286 if(This
->arrays
[i
]) {
287 SafeArrayDestroy(This
->arrays
[i
]);
288 This
->arrays
[i
] = NULL
;
292 for(i
=0; i
< This
->desc
->prop_cnt
; i
++)
293 VariantClear(This
->props
+i
);
296 static inline vbdisp_t
*impl_from_IDispatchEx(IDispatchEx
*iface
)
298 return CONTAINING_RECORD(iface
, vbdisp_t
, IDispatchEx_iface
);
301 static HRESULT WINAPI
DispatchEx_QueryInterface(IDispatchEx
*iface
, REFIID riid
, void **ppv
)
303 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
305 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
306 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
307 *ppv
= &This
->IDispatchEx_iface
;
308 }else if(IsEqualGUID(&IID_IDispatch
, riid
)) {
309 TRACE("(%p)->(IID_IDispatch %p)\n", This
, ppv
);
310 *ppv
= &This
->IDispatchEx_iface
;
311 }else if(IsEqualGUID(&IID_IDispatchEx
, riid
)) {
312 TRACE("(%p)->(IID_IDispatchEx %p)\n", This
, ppv
);
313 *ppv
= &This
->IDispatchEx_iface
;
315 WARN("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
317 return E_NOINTERFACE
;
320 IUnknown_AddRef((IUnknown
*)*ppv
);
324 static ULONG WINAPI
DispatchEx_AddRef(IDispatchEx
*iface
)
326 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
327 LONG ref
= InterlockedIncrement(&This
->ref
);
329 TRACE("(%p) ref=%ld\n", This
, ref
);
334 static ULONG WINAPI
DispatchEx_Release(IDispatchEx
*iface
)
336 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
337 LONG ref
= InterlockedDecrement(&This
->ref
);
339 TRACE("(%p) ref=%ld\n", This
, ref
);
341 if(!ref
&& run_terminator(This
)) {
343 list_remove(&This
->entry
);
351 static HRESULT WINAPI
DispatchEx_GetTypeInfoCount(IDispatchEx
*iface
, UINT
*pctinfo
)
353 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
355 TRACE("(%p)->(%p)\n", This
, pctinfo
);
361 static HRESULT WINAPI
DispatchEx_GetTypeInfo(IDispatchEx
*iface
, UINT iTInfo
, LCID lcid
,
364 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
365 FIXME("(%p)->(%u %lu %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
369 static HRESULT WINAPI
DispatchEx_GetIDsOfNames(IDispatchEx
*iface
, REFIID riid
,
370 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
,
373 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
374 FIXME("(%p)->(%s %p %u %lu %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
,
379 static HRESULT WINAPI
DispatchEx_Invoke(IDispatchEx
*iface
, DISPID dispIdMember
,
380 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
,
381 VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
383 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
385 TRACE("(%p)->(%ld %s %ld %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
386 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
388 return IDispatchEx_InvokeEx(&This
->IDispatchEx_iface
, dispIdMember
, lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, NULL
);
391 static HRESULT WINAPI
DispatchEx_GetDispID(IDispatchEx
*iface
, BSTR bstrName
, DWORD grfdex
, DISPID
*pid
)
393 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
395 TRACE("(%p)->(%s %lx %p)\n", This
, debugstr_w(bstrName
), grfdex
, pid
);
397 grfdex
&= ~FDEX_VERSION_MASK
;
402 /* Tests show that fdexNameCaseSensitive is ignored */
404 if(grfdex
& ~(fdexNameEnsure
|fdexNameCaseInsensitive
|fdexNameCaseSensitive
)) {
405 FIXME("unsupported flags %lx\n", grfdex
);
409 return vbdisp_get_id(This
, bstrName
, VBDISP_ANY
, FALSE
, pid
);
412 static HRESULT WINAPI
DispatchEx_InvokeEx(IDispatchEx
*iface
, DISPID id
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pdp
,
413 VARIANT
*pvarRes
, EXCEPINFO
*pei
, IServiceProvider
*pspCaller
)
415 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
416 IServiceProvider
*prev_caller
;
419 TRACE("(%p)->(%lx %lx %x %p %p %p %p)\n", This
, id
, lcid
, wFlags
, pdp
, pvarRes
, pei
, pspCaller
);
425 V_VT(pvarRes
) = VT_EMPTY
;
427 prev_caller
= This
->desc
->ctx
->vbcaller
->caller
;
428 This
->desc
->ctx
->vbcaller
->caller
= pspCaller
;
430 IServiceProvider_AddRef(pspCaller
);
432 hres
= invoke_vbdisp(This
, id
, wFlags
, TRUE
, pdp
, pvarRes
);
434 This
->desc
->ctx
->vbcaller
->caller
= prev_caller
;
436 IServiceProvider_Release(pspCaller
);
440 static HRESULT WINAPI
DispatchEx_DeleteMemberByName(IDispatchEx
*iface
, BSTR bstrName
, DWORD grfdex
)
442 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
443 FIXME("(%p)->(%s %lx)\n", This
, debugstr_w(bstrName
), grfdex
);
447 static HRESULT WINAPI
DispatchEx_DeleteMemberByDispID(IDispatchEx
*iface
, DISPID id
)
449 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
450 FIXME("(%p)->(%lx)\n", This
, id
);
454 static HRESULT WINAPI
DispatchEx_GetMemberProperties(IDispatchEx
*iface
, DISPID id
, DWORD grfdexFetch
, DWORD
*pgrfdex
)
456 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
457 FIXME("(%p)->(%lx %lx %p)\n", This
, id
, grfdexFetch
, pgrfdex
);
461 static HRESULT WINAPI
DispatchEx_GetMemberName(IDispatchEx
*iface
, DISPID id
, BSTR
*pbstrName
)
463 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
464 FIXME("(%p)->(%lx %p)\n", This
, id
, pbstrName
);
468 static HRESULT WINAPI
DispatchEx_GetNextDispID(IDispatchEx
*iface
, DWORD grfdex
, DISPID id
, DISPID
*pid
)
470 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
471 FIXME("(%p)->(%lx %lx %p)\n", This
, grfdex
, id
, pid
);
475 static HRESULT WINAPI
DispatchEx_GetNameSpaceParent(IDispatchEx
*iface
, IUnknown
**ppunk
)
477 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
478 FIXME("(%p)->(%p)\n", This
, ppunk
);
482 static IDispatchExVtbl DispatchExVtbl
= {
483 DispatchEx_QueryInterface
,
486 DispatchEx_GetTypeInfoCount
,
487 DispatchEx_GetTypeInfo
,
488 DispatchEx_GetIDsOfNames
,
490 DispatchEx_GetDispID
,
492 DispatchEx_DeleteMemberByName
,
493 DispatchEx_DeleteMemberByDispID
,
494 DispatchEx_GetMemberProperties
,
495 DispatchEx_GetMemberName
,
496 DispatchEx_GetNextDispID
,
497 DispatchEx_GetNameSpaceParent
500 static inline vbdisp_t
*unsafe_impl_from_IDispatch(IDispatch
*iface
)
502 return iface
->lpVtbl
== (IDispatchVtbl
*)&DispatchExVtbl
503 ? CONTAINING_RECORD(iface
, vbdisp_t
, IDispatchEx_iface
)
507 HRESULT
create_vbdisp(const class_desc_t
*desc
, vbdisp_t
**ret
)
512 vbdisp
= calloc( 1, FIELD_OFFSET( vbdisp_t
, props
[desc
->prop_cnt
] ));
514 return E_OUTOFMEMORY
;
516 vbdisp
->IDispatchEx_iface
.lpVtbl
= &DispatchExVtbl
;
520 list_add_tail(&desc
->ctx
->objects
, &vbdisp
->entry
);
522 if(desc
->array_cnt
) {
523 vbdisp
->arrays
= calloc(desc
->array_cnt
, sizeof(*vbdisp
->arrays
));
527 for(i
=0; i
< desc
->array_cnt
; i
++) {
528 if(!desc
->array_descs
[i
].dim_cnt
)
531 vbdisp
->arrays
[i
] = SafeArrayCreate(VT_VARIANT
, desc
->array_descs
[i
].dim_cnt
, desc
->array_descs
[i
].bounds
);
532 if(!vbdisp
->arrays
[i
]) {
533 hres
= E_OUTOFMEMORY
;
538 if(SUCCEEDED(hres
)) {
539 for(i
=0, j
=0; i
< desc
->prop_cnt
; i
++) {
540 if(desc
->props
[i
].is_array
) {
541 V_VT(vbdisp
->props
+i
) = VT_ARRAY
|VT_BYREF
|VT_VARIANT
;
542 V_ARRAYREF(vbdisp
->props
+i
) = vbdisp
->arrays
+ j
++;
547 hres
= E_OUTOFMEMORY
;
551 if(SUCCEEDED(hres
) && desc
->class_initialize_id
) {
553 hres
= exec_script(desc
->ctx
, FALSE
, desc
->funcs
[desc
->class_initialize_id
].entries
[VBDISP_CALLGET
],
558 IDispatchEx_Release(&vbdisp
->IDispatchEx_iface
);
566 struct typeinfo_func
{
572 ITypeInfo ITypeInfo_iface
;
573 ITypeComp ITypeComp_iface
;
578 struct typeinfo_func
*funcs
;
583 static function_t
*get_func_from_memid(const ScriptTypeInfo
*typeinfo
, MEMBERID memid
)
585 UINT a
= 0, b
= typeinfo
->num_funcs
;
587 if (!(memid
& DISPID_FUNCTION_MASK
)) return NULL
;
591 UINT i
= (a
+ b
- 1) / 2;
593 if (memid
== typeinfo
->funcs
[i
].memid
)
594 return typeinfo
->funcs
[i
].func
;
595 else if (memid
< typeinfo
->funcs
[i
].memid
)
603 static inline ScriptTypeInfo
*ScriptTypeInfo_from_ITypeInfo(ITypeInfo
*iface
)
605 return CONTAINING_RECORD(iface
, ScriptTypeInfo
, ITypeInfo_iface
);
608 static inline ScriptTypeInfo
*ScriptTypeInfo_from_ITypeComp(ITypeComp
*iface
)
610 return CONTAINING_RECORD(iface
, ScriptTypeInfo
, ITypeComp_iface
);
613 static HRESULT WINAPI
ScriptTypeInfo_QueryInterface(ITypeInfo
*iface
, REFIID riid
, void **ppv
)
615 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
617 if (IsEqualGUID(&IID_IUnknown
, riid
) || IsEqualGUID(&IID_ITypeInfo
, riid
))
618 *ppv
= &This
->ITypeInfo_iface
;
619 else if (IsEqualGUID(&IID_ITypeComp
, riid
))
620 *ppv
= &This
->ITypeComp_iface
;
623 WARN("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
625 return E_NOINTERFACE
;
628 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
629 IUnknown_AddRef((IUnknown
*)*ppv
);
633 static ULONG WINAPI
ScriptTypeInfo_AddRef(ITypeInfo
*iface
)
635 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
636 LONG ref
= InterlockedIncrement(&This
->ref
);
638 TRACE("(%p) ref=%ld\n", This
, ref
);
643 static ULONG WINAPI
ScriptTypeInfo_Release(ITypeInfo
*iface
)
645 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
646 LONG ref
= InterlockedDecrement(&This
->ref
);
649 TRACE("(%p) ref=%ld\n", This
, ref
);
653 for (i
= 0; i
< This
->num_funcs
; i
++)
654 release_vbscode(This
->funcs
[i
].func
->code_ctx
);
656 IDispatchEx_Release(&This
->disp
->IDispatchEx_iface
);
663 static HRESULT WINAPI
ScriptTypeInfo_GetTypeAttr(ITypeInfo
*iface
, TYPEATTR
**ppTypeAttr
)
665 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
668 TRACE("(%p)->(%p)\n", This
, ppTypeAttr
);
670 if (!ppTypeAttr
) return E_INVALIDARG
;
672 attr
= calloc(1, sizeof(*attr
));
673 if (!attr
) return E_OUTOFMEMORY
;
675 attr
->guid
= GUID_VBScriptTypeInfo
;
676 attr
->lcid
= LOCALE_USER_DEFAULT
;
677 attr
->memidConstructor
= MEMBERID_NIL
;
678 attr
->memidDestructor
= MEMBERID_NIL
;
679 attr
->cbSizeInstance
= 4;
680 attr
->typekind
= TKIND_DISPATCH
;
681 attr
->cFuncs
= This
->num_funcs
;
682 attr
->cVars
= This
->num_vars
;
683 attr
->cImplTypes
= 1;
684 attr
->cbSizeVft
= sizeof(IDispatchVtbl
);
685 attr
->cbAlignment
= 4;
686 attr
->wTypeFlags
= TYPEFLAG_FDISPATCHABLE
;
687 attr
->wMajorVerNum
= VBSCRIPT_MAJOR_VERSION
;
688 attr
->wMinorVerNum
= VBSCRIPT_MINOR_VERSION
;
694 static HRESULT WINAPI
ScriptTypeInfo_GetTypeComp(ITypeInfo
*iface
, ITypeComp
**ppTComp
)
696 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
698 TRACE("(%p)->(%p)\n", This
, ppTComp
);
700 if (!ppTComp
) return E_INVALIDARG
;
702 *ppTComp
= &This
->ITypeComp_iface
;
703 ITypeInfo_AddRef(iface
);
707 static HRESULT WINAPI
ScriptTypeInfo_GetFuncDesc(ITypeInfo
*iface
, UINT index
, FUNCDESC
**ppFuncDesc
)
709 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
714 TRACE("(%p)->(%u %p)\n", This
, index
, ppFuncDesc
);
716 if (!ppFuncDesc
) return E_INVALIDARG
;
717 if (index
>= This
->num_funcs
) return TYPE_E_ELEMENTNOTFOUND
;
718 func
= This
->funcs
[index
].func
;
720 /* Store the parameter array after the FUNCDESC structure */
721 desc
= calloc(1, sizeof(*desc
) + sizeof(ELEMDESC
) * func
->arg_cnt
);
722 if (!desc
) return E_OUTOFMEMORY
;
724 desc
->memid
= This
->funcs
[index
].memid
;
725 desc
->funckind
= FUNC_DISPATCH
;
726 desc
->invkind
= INVOKE_FUNC
;
727 desc
->callconv
= CC_STDCALL
;
728 desc
->cParams
= func
->arg_cnt
;
729 desc
->elemdescFunc
.tdesc
.vt
= (func
->type
== FUNC_SUB
) ? VT_VOID
: VT_VARIANT
;
731 if (func
->arg_cnt
) desc
->lprgelemdescParam
= (ELEMDESC
*)(desc
+ 1);
732 for (i
= 0; i
< func
->arg_cnt
; i
++)
733 desc
->lprgelemdescParam
[i
].tdesc
.vt
= VT_VARIANT
;
739 static HRESULT WINAPI
ScriptTypeInfo_GetVarDesc(ITypeInfo
*iface
, UINT index
, VARDESC
**ppVarDesc
)
741 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
744 TRACE("(%p)->(%u %p)\n", This
, index
, ppVarDesc
);
746 if (!ppVarDesc
) return E_INVALIDARG
;
747 if (index
>= This
->num_vars
) return TYPE_E_ELEMENTNOTFOUND
;
749 desc
= calloc(1, sizeof(*desc
));
750 if (!desc
) return E_OUTOFMEMORY
;
752 desc
->memid
= index
+ 1;
753 desc
->varkind
= VAR_DISPATCH
;
754 desc
->elemdescVar
.tdesc
.vt
= VT_VARIANT
;
760 static HRESULT WINAPI
ScriptTypeInfo_GetNames(ITypeInfo
*iface
, MEMBERID memid
, BSTR
*rgBstrNames
,
761 UINT cMaxNames
, UINT
*pcNames
)
763 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
764 ITypeInfo
*disp_typeinfo
;
769 TRACE("(%p)->(%ld %p %u %p)\n", This
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
771 if (!rgBstrNames
|| !pcNames
) return E_INVALIDARG
;
772 if (memid
<= 0) return TYPE_E_ELEMENTNOTFOUND
;
774 func
= get_func_from_memid(This
, memid
);
775 if (!func
&& memid
> This
->num_vars
)
777 hr
= get_dispatch_typeinfo(&disp_typeinfo
);
778 if (FAILED(hr
)) return hr
;
780 return ITypeInfo_GetNames(disp_typeinfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
784 if (!cMaxNames
) return S_OK
;
788 UINT num
= min(cMaxNames
, func
->arg_cnt
+ 1);
790 rgBstrNames
[0] = SysAllocString(func
->name
);
791 if (!rgBstrNames
[0]) return E_OUTOFMEMORY
;
793 for (i
= 1; i
< num
; i
++)
795 if (!(rgBstrNames
[i
] = SysAllocString(func
->args
[i
- 1].name
)))
797 do SysFreeString(rgBstrNames
[--i
]); while (i
);
798 return E_OUTOFMEMORY
;
804 rgBstrNames
[0] = SysAllocString(This
->disp
->global_vars
[memid
- 1]->name
);
805 if (!rgBstrNames
[0]) return E_OUTOFMEMORY
;
813 static HRESULT WINAPI
ScriptTypeInfo_GetRefTypeOfImplType(ITypeInfo
*iface
, UINT index
, HREFTYPE
*pRefType
)
815 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
817 TRACE("(%p)->(%u %p)\n", This
, index
, pRefType
);
819 /* We only inherit from IDispatch */
820 if (!pRefType
) return E_INVALIDARG
;
821 if (index
!= 0) return TYPE_E_ELEMENTNOTFOUND
;
827 static HRESULT WINAPI
ScriptTypeInfo_GetImplTypeFlags(ITypeInfo
*iface
, UINT index
, INT
*pImplTypeFlags
)
829 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
831 TRACE("(%p)->(%u %p)\n", This
, index
, pImplTypeFlags
);
833 if (!pImplTypeFlags
) return E_INVALIDARG
;
834 if (index
!= 0) return TYPE_E_ELEMENTNOTFOUND
;
840 static HRESULT WINAPI
ScriptTypeInfo_GetIDsOfNames(ITypeInfo
*iface
, LPOLESTR
*rgszNames
, UINT cNames
,
843 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
844 ITypeInfo
*disp_typeinfo
;
849 TRACE("(%p)->(%p %u %p)\n", This
, rgszNames
, cNames
, pMemId
);
851 if (!rgszNames
|| !cNames
|| !pMemId
) return E_INVALIDARG
;
853 for (i
= 0; i
< cNames
; i
++) pMemId
[i
] = MEMBERID_NIL
;
856 for (i
= 0; i
< This
->num_funcs
; i
++)
858 function_t
*func
= This
->funcs
[i
].func
;
860 if (wcsicmp(name
, func
->name
)) continue;
861 pMemId
[0] = This
->funcs
[i
].memid
;
863 for (j
= 1; j
< cNames
; j
++)
866 for (arg
= func
->arg_cnt
; --arg
>= 0;)
867 if (!wcsicmp(name
, func
->args
[arg
].name
))
872 hr
= DISP_E_UNKNOWNNAME
;
877 for (i
= 0; i
< This
->num_vars
; i
++)
879 if (wcsicmp(name
, This
->disp
->global_vars
[i
]->name
)) continue;
884 /* Look into the inherited IDispatch */
885 hr
= get_dispatch_typeinfo(&disp_typeinfo
);
886 if (FAILED(hr
)) return hr
;
888 return ITypeInfo_GetIDsOfNames(disp_typeinfo
, rgszNames
, cNames
, pMemId
);
891 static HRESULT WINAPI
ScriptTypeInfo_Invoke(ITypeInfo
*iface
, PVOID pvInstance
, MEMBERID memid
, WORD wFlags
,
892 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
894 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
895 ITypeInfo
*disp_typeinfo
;
899 TRACE("(%p)->(%p %ld %d %p %p %p %p)\n", This
, pvInstance
, memid
, wFlags
,
900 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
902 if (!pvInstance
) return E_INVALIDARG
;
903 if (memid
<= 0) return TYPE_E_ELEMENTNOTFOUND
;
905 if (!get_func_from_memid(This
, memid
) && memid
> This
->num_vars
)
907 hr
= get_dispatch_typeinfo(&disp_typeinfo
);
908 if (FAILED(hr
)) return hr
;
910 return ITypeInfo_Invoke(disp_typeinfo
, pvInstance
, memid
, wFlags
, pDispParams
,
911 pVarResult
, pExcepInfo
, puArgErr
);
914 hr
= IUnknown_QueryInterface((IUnknown
*)pvInstance
, &IID_IDispatch
, (void**)&disp
);
915 if (FAILED(hr
)) return hr
;
917 hr
= IDispatch_Invoke(disp
, memid
, &IID_NULL
, LOCALE_USER_DEFAULT
, wFlags
,
918 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
919 IDispatch_Release(disp
);
924 static HRESULT WINAPI
ScriptTypeInfo_GetDocumentation(ITypeInfo
*iface
, MEMBERID memid
, BSTR
*pBstrName
,
925 BSTR
*pBstrDocString
, DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
927 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
928 ITypeInfo
*disp_typeinfo
;
932 TRACE("(%p)->(%ld %p %p %p %p)\n", This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
934 if (pBstrDocString
) *pBstrDocString
= NULL
;
935 if (pdwHelpContext
) *pdwHelpContext
= 0;
936 if (pBstrHelpFile
) *pBstrHelpFile
= NULL
;
938 if (memid
== MEMBERID_NIL
)
940 if (pBstrName
&& !(*pBstrName
= SysAllocString(L
"VBScriptTypeInfo")))
941 return E_OUTOFMEMORY
;
942 if (pBstrDocString
&&
943 !(*pBstrDocString
= SysAllocString(L
"Visual Basic Scripting Type Info")))
945 if (pBstrName
) SysFreeString(*pBstrName
);
946 return E_OUTOFMEMORY
;
950 if (memid
<= 0) return TYPE_E_ELEMENTNOTFOUND
;
952 func
= get_func_from_memid(This
, memid
);
953 if (!func
&& memid
> This
->num_vars
)
955 hr
= get_dispatch_typeinfo(&disp_typeinfo
);
956 if (FAILED(hr
)) return hr
;
958 return ITypeInfo_GetDocumentation(disp_typeinfo
, memid
, pBstrName
, pBstrDocString
,
959 pdwHelpContext
, pBstrHelpFile
);
964 *pBstrName
= SysAllocString(func
? func
->name
: This
->disp
->global_vars
[memid
- 1]->name
);
965 if (!*pBstrName
) return E_OUTOFMEMORY
;
970 static HRESULT WINAPI
ScriptTypeInfo_GetDllEntry(ITypeInfo
*iface
, MEMBERID memid
, INVOKEKIND invKind
,
971 BSTR
*pBstrDllName
, BSTR
*pBstrName
, WORD
*pwOrdinal
)
973 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
974 ITypeInfo
*disp_typeinfo
;
977 TRACE("(%p)->(%ld %d %p %p %p)\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
979 if (pBstrDllName
) *pBstrDllName
= NULL
;
980 if (pBstrName
) *pBstrName
= NULL
;
981 if (pwOrdinal
) *pwOrdinal
= 0;
983 if (!get_func_from_memid(This
, memid
) && memid
> This
->num_vars
)
985 hr
= get_dispatch_typeinfo(&disp_typeinfo
);
986 if (FAILED(hr
)) return hr
;
988 return ITypeInfo_GetDllEntry(disp_typeinfo
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
990 return TYPE_E_BADMODULEKIND
;
993 static HRESULT WINAPI
ScriptTypeInfo_GetRefTypeInfo(ITypeInfo
*iface
, HREFTYPE hRefType
, ITypeInfo
**ppTInfo
)
995 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
998 TRACE("(%p)->(%lx %p)\n", This
, hRefType
, ppTInfo
);
1000 if (!ppTInfo
|| (INT
)hRefType
< 0) return E_INVALIDARG
;
1002 if (hRefType
& ~3) return E_FAIL
;
1005 hr
= get_dispatch_typeinfo(ppTInfo
);
1006 if (FAILED(hr
)) return hr
;
1011 ITypeInfo_AddRef(*ppTInfo
);
1015 static HRESULT WINAPI
ScriptTypeInfo_AddressOfMember(ITypeInfo
*iface
, MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
1017 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
1018 ITypeInfo
*disp_typeinfo
;
1021 TRACE("(%p)->(%ld %d %p)\n", This
, memid
, invKind
, ppv
);
1023 if (!ppv
) return E_INVALIDARG
;
1026 if (!get_func_from_memid(This
, memid
) && memid
> This
->num_vars
)
1028 hr
= get_dispatch_typeinfo(&disp_typeinfo
);
1029 if (FAILED(hr
)) return hr
;
1031 return ITypeInfo_AddressOfMember(disp_typeinfo
, memid
, invKind
, ppv
);
1033 return TYPE_E_BADMODULEKIND
;
1036 static HRESULT WINAPI
ScriptTypeInfo_CreateInstance(ITypeInfo
*iface
, IUnknown
*pUnkOuter
, REFIID riid
, PVOID
*ppvObj
)
1038 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
1040 TRACE("(%p)->(%p %s %p)\n", This
, pUnkOuter
, debugstr_guid(riid
), ppvObj
);
1042 if (!ppvObj
) return E_INVALIDARG
;
1045 return TYPE_E_BADMODULEKIND
;
1048 static HRESULT WINAPI
ScriptTypeInfo_GetMops(ITypeInfo
*iface
, MEMBERID memid
, BSTR
*pBstrMops
)
1050 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
1051 ITypeInfo
*disp_typeinfo
;
1054 TRACE("(%p)->(%ld %p)\n", This
, memid
, pBstrMops
);
1056 if (!pBstrMops
) return E_INVALIDARG
;
1058 if (!get_func_from_memid(This
, memid
) && memid
> This
->num_vars
)
1060 hr
= get_dispatch_typeinfo(&disp_typeinfo
);
1061 if (FAILED(hr
)) return hr
;
1063 return ITypeInfo_GetMops(disp_typeinfo
, memid
, pBstrMops
);
1070 static HRESULT WINAPI
ScriptTypeInfo_GetContainingTypeLib(ITypeInfo
*iface
, ITypeLib
**ppTLib
, UINT
*pIndex
)
1072 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
1074 FIXME("(%p)->(%p %p)\n", This
, ppTLib
, pIndex
);
1079 static void WINAPI
ScriptTypeInfo_ReleaseTypeAttr(ITypeInfo
*iface
, TYPEATTR
*pTypeAttr
)
1081 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
1083 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
1088 static void WINAPI
ScriptTypeInfo_ReleaseFuncDesc(ITypeInfo
*iface
, FUNCDESC
*pFuncDesc
)
1090 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
1092 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
1097 static void WINAPI
ScriptTypeInfo_ReleaseVarDesc(ITypeInfo
*iface
, VARDESC
*pVarDesc
)
1099 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
1101 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
1106 static const ITypeInfoVtbl ScriptTypeInfoVtbl
= {
1107 ScriptTypeInfo_QueryInterface
,
1108 ScriptTypeInfo_AddRef
,
1109 ScriptTypeInfo_Release
,
1110 ScriptTypeInfo_GetTypeAttr
,
1111 ScriptTypeInfo_GetTypeComp
,
1112 ScriptTypeInfo_GetFuncDesc
,
1113 ScriptTypeInfo_GetVarDesc
,
1114 ScriptTypeInfo_GetNames
,
1115 ScriptTypeInfo_GetRefTypeOfImplType
,
1116 ScriptTypeInfo_GetImplTypeFlags
,
1117 ScriptTypeInfo_GetIDsOfNames
,
1118 ScriptTypeInfo_Invoke
,
1119 ScriptTypeInfo_GetDocumentation
,
1120 ScriptTypeInfo_GetDllEntry
,
1121 ScriptTypeInfo_GetRefTypeInfo
,
1122 ScriptTypeInfo_AddressOfMember
,
1123 ScriptTypeInfo_CreateInstance
,
1124 ScriptTypeInfo_GetMops
,
1125 ScriptTypeInfo_GetContainingTypeLib
,
1126 ScriptTypeInfo_ReleaseTypeAttr
,
1127 ScriptTypeInfo_ReleaseFuncDesc
,
1128 ScriptTypeInfo_ReleaseVarDesc
1131 static HRESULT WINAPI
ScriptTypeComp_QueryInterface(ITypeComp
*iface
, REFIID riid
, void **ppv
)
1133 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeComp(iface
);
1134 return ITypeInfo_QueryInterface(&This
->ITypeInfo_iface
, riid
, ppv
);
1137 static ULONG WINAPI
ScriptTypeComp_AddRef(ITypeComp
*iface
)
1139 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeComp(iface
);
1140 return ITypeInfo_AddRef(&This
->ITypeInfo_iface
);
1143 static ULONG WINAPI
ScriptTypeComp_Release(ITypeComp
*iface
)
1145 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeComp(iface
);
1146 return ITypeInfo_Release(&This
->ITypeInfo_iface
);
1149 static HRESULT WINAPI
ScriptTypeComp_Bind(ITypeComp
*iface
, LPOLESTR szName
, ULONG lHashVal
, WORD wFlags
,
1150 ITypeInfo
**ppTInfo
, DESCKIND
*pDescKind
, BINDPTR
*pBindPtr
)
1152 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeComp(iface
);
1153 UINT flags
= wFlags
? wFlags
: ~0;
1154 ITypeInfo
*disp_typeinfo
;
1155 ITypeComp
*disp_typecomp
;
1159 TRACE("(%p)->(%s %08lx %d %p %p %p)\n", This
, debugstr_w(szName
), lHashVal
,
1160 wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
1162 if (!szName
|| !ppTInfo
|| !pDescKind
|| !pBindPtr
)
1163 return E_INVALIDARG
;
1165 for (i
= 0; i
< This
->num_funcs
; i
++)
1167 if (wcsicmp(szName
, This
->funcs
[i
].func
->name
)) continue;
1168 if (!(flags
& INVOKE_FUNC
)) return TYPE_E_TYPEMISMATCH
;
1170 hr
= ITypeInfo_GetFuncDesc(&This
->ITypeInfo_iface
, i
, &pBindPtr
->lpfuncdesc
);
1171 if (FAILED(hr
)) return hr
;
1173 *pDescKind
= DESCKIND_FUNCDESC
;
1174 *ppTInfo
= &This
->ITypeInfo_iface
;
1175 ITypeInfo_AddRef(*ppTInfo
);
1179 for (i
= 0; i
< This
->num_vars
; i
++)
1181 if (wcsicmp(szName
, This
->disp
->global_vars
[i
]->name
)) continue;
1182 if (!(flags
& INVOKE_PROPERTYGET
)) return TYPE_E_TYPEMISMATCH
;
1184 hr
= ITypeInfo_GetVarDesc(&This
->ITypeInfo_iface
, i
, &pBindPtr
->lpvardesc
);
1185 if (FAILED(hr
)) return hr
;
1187 *pDescKind
= DESCKIND_VARDESC
;
1188 *ppTInfo
= &This
->ITypeInfo_iface
;
1189 ITypeInfo_AddRef(*ppTInfo
);
1193 /* Look into the inherited IDispatch */
1194 hr
= get_dispatch_typeinfo(&disp_typeinfo
);
1195 if (FAILED(hr
)) return hr
;
1197 hr
= ITypeInfo_GetTypeComp(disp_typeinfo
, &disp_typecomp
);
1198 if (FAILED(hr
)) return hr
;
1200 hr
= ITypeComp_Bind(disp_typecomp
, szName
, lHashVal
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
1201 ITypeComp_Release(disp_typecomp
);
1205 static HRESULT WINAPI
ScriptTypeComp_BindType(ITypeComp
*iface
, LPOLESTR szName
, ULONG lHashVal
,
1206 ITypeInfo
**ppTInfo
, ITypeComp
**ppTComp
)
1208 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeComp(iface
);
1209 ITypeInfo
*disp_typeinfo
;
1210 ITypeComp
*disp_typecomp
;
1213 TRACE("(%p)->(%s %08lx %p %p)\n", This
, debugstr_w(szName
), lHashVal
, ppTInfo
, ppTComp
);
1215 if (!szName
|| !ppTInfo
|| !ppTComp
)
1216 return E_INVALIDARG
;
1218 /* Look into the inherited IDispatch */
1219 hr
= get_dispatch_typeinfo(&disp_typeinfo
);
1220 if (FAILED(hr
)) return hr
;
1222 hr
= ITypeInfo_GetTypeComp(disp_typeinfo
, &disp_typecomp
);
1223 if (FAILED(hr
)) return hr
;
1225 hr
= ITypeComp_BindType(disp_typecomp
, szName
, lHashVal
, ppTInfo
, ppTComp
);
1226 ITypeComp_Release(disp_typecomp
);
1230 static const ITypeCompVtbl ScriptTypeCompVtbl
= {
1231 ScriptTypeComp_QueryInterface
,
1232 ScriptTypeComp_AddRef
,
1233 ScriptTypeComp_Release
,
1234 ScriptTypeComp_Bind
,
1235 ScriptTypeComp_BindType
1238 static inline ScriptDisp
*ScriptDisp_from_IDispatchEx(IDispatchEx
*iface
)
1240 return CONTAINING_RECORD(iface
, ScriptDisp
, IDispatchEx_iface
);
1243 static HRESULT WINAPI
ScriptDisp_QueryInterface(IDispatchEx
*iface
, REFIID riid
, void **ppv
)
1245 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1247 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
1248 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
1249 *ppv
= &This
->IDispatchEx_iface
;
1250 }else if(IsEqualGUID(&IID_IDispatch
, riid
)) {
1251 TRACE("(%p)->(IID_IDispatch %p)\n", This
, ppv
);
1252 *ppv
= &This
->IDispatchEx_iface
;
1253 }else if(IsEqualGUID(&IID_IDispatchEx
, riid
)) {
1254 TRACE("(%p)->(IID_IDispatchEx %p)\n", This
, ppv
);
1255 *ppv
= &This
->IDispatchEx_iface
;
1257 WARN("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
1259 return E_NOINTERFACE
;
1262 IUnknown_AddRef((IUnknown
*)*ppv
);
1266 static ULONG WINAPI
ScriptDisp_AddRef(IDispatchEx
*iface
)
1268 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1269 LONG ref
= InterlockedIncrement(&This
->ref
);
1271 TRACE("(%p) ref=%ld\n", This
, ref
);
1276 static ULONG WINAPI
ScriptDisp_Release(IDispatchEx
*iface
)
1278 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1279 LONG ref
= InterlockedDecrement(&This
->ref
);
1282 TRACE("(%p) ref=%ld\n", This
, ref
);
1287 for (i
= 0; i
< This
->global_vars_cnt
; i
++)
1288 release_dynamic_var(This
->global_vars
[i
]);
1290 heap_pool_free(&This
->heap
);
1291 free(This
->global_vars
);
1292 free(This
->global_funcs
);
1299 static HRESULT WINAPI
ScriptDisp_GetTypeInfoCount(IDispatchEx
*iface
, UINT
*pctinfo
)
1301 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1303 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1309 static HRESULT WINAPI
ScriptDisp_GetTypeInfo(IDispatchEx
*iface
, UINT iTInfo
, LCID lcid
, ITypeInfo
**ret
)
1311 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1312 ScriptTypeInfo
*type_info
;
1316 TRACE("(%p)->(%u %lu %p)\n", This
, iTInfo
, lcid
, ret
);
1319 return DISP_E_BADINDEX
;
1321 if(!(type_info
= calloc(1, sizeof(*type_info
))))
1322 return E_OUTOFMEMORY
;
1324 for(i
= 0; i
< This
->global_funcs_cnt
; i
++)
1325 if(This
->global_funcs
[i
]->is_public
)
1328 type_info
->ITypeInfo_iface
.lpVtbl
= &ScriptTypeInfoVtbl
;
1329 type_info
->ITypeComp_iface
.lpVtbl
= &ScriptTypeCompVtbl
;
1331 type_info
->num_funcs
= num_funcs
;
1332 type_info
->num_vars
= This
->global_vars_cnt
;
1333 type_info
->disp
= This
;
1335 type_info
->funcs
= calloc(num_funcs
, sizeof(*type_info
->funcs
));
1336 if(!type_info
->funcs
)
1339 return E_OUTOFMEMORY
;
1342 for(j
= 0, i
= 0; i
< This
->global_funcs_cnt
; i
++)
1344 if(!This
->global_funcs
[i
]->is_public
) continue;
1346 type_info
->funcs
[j
].memid
= i
+ 1 + DISPID_FUNCTION_MASK
;
1347 type_info
->funcs
[j
].func
= This
->global_funcs
[i
];
1348 grab_vbscode(This
->global_funcs
[i
]->code_ctx
);
1352 IDispatchEx_AddRef(&This
->IDispatchEx_iface
);
1354 *ret
= &type_info
->ITypeInfo_iface
;
1358 static HRESULT WINAPI
ScriptDisp_GetIDsOfNames(IDispatchEx
*iface
, REFIID riid
,
1359 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
1361 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1365 TRACE("(%p)->(%s %p %u %lu %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
,
1371 hres
= IDispatchEx_GetDispID(&This
->IDispatchEx_iface
, rgszNames
[0], 0, rgDispId
);
1375 /* DISPIDs for parameters don't seem to be supported */
1377 for(i
= 1; i
< cNames
; i
++)
1378 rgDispId
[i
] = DISPID_UNKNOWN
;
1379 hres
= DISP_E_UNKNOWNNAME
;
1385 static HRESULT WINAPI
ScriptDisp_Invoke(IDispatchEx
*iface
, DISPID dispIdMember
, REFIID riid
, LCID lcid
,
1386 WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1388 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1390 TRACE("(%p)->(%ld %s %ld %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
1391 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1393 return IDispatchEx_InvokeEx(&This
->IDispatchEx_iface
, dispIdMember
, lcid
, wFlags
,
1394 pDispParams
, pVarResult
, pExcepInfo
, NULL
);
1397 static HRESULT WINAPI
ScriptDisp_GetDispID(IDispatchEx
*iface
, BSTR bstrName
, DWORD grfdex
, DISPID
*pid
)
1399 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1402 TRACE("(%p)->(%s %lx %p)\n", This
, debugstr_w(bstrName
), grfdex
, pid
);
1405 return E_UNEXPECTED
;
1407 for(i
= 0; i
< This
->global_vars_cnt
; i
++) {
1408 if(!wcsicmp(This
->global_vars
[i
]->name
, bstrName
)) {
1414 for(i
= 0; i
< This
->global_funcs_cnt
; i
++) {
1415 if(!wcsicmp(This
->global_funcs
[i
]->name
, bstrName
)) {
1416 *pid
= i
+ 1 + DISPID_FUNCTION_MASK
;
1422 return DISP_E_UNKNOWNNAME
;
1425 static HRESULT WINAPI
ScriptDisp_InvokeEx(IDispatchEx
*iface
, DISPID id
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pdp
,
1426 VARIANT
*pvarRes
, EXCEPINFO
*pei
, IServiceProvider
*pspCaller
)
1428 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1429 IServiceProvider
*prev_caller
;
1432 TRACE("(%p)->(%lx %lx %x %p %p %p %p)\n", This
, id
, lcid
, wFlags
, pdp
, pvarRes
, pei
, pspCaller
);
1435 return E_UNEXPECTED
;
1437 prev_caller
= This
->ctx
->vbcaller
->caller
;
1438 This
->ctx
->vbcaller
->caller
= pspCaller
;
1440 IServiceProvider_AddRef(pspCaller
);
1442 if (id
& DISPID_FUNCTION_MASK
)
1444 id
&= ~DISPID_FUNCTION_MASK
;
1445 if (id
> This
->global_funcs_cnt
) {
1446 hres
= DISP_E_MEMBERNOTFOUND
;
1452 case DISPATCH_METHOD
:
1453 case DISPATCH_METHOD
| DISPATCH_PROPERTYGET
:
1454 hres
= exec_script(This
->ctx
, TRUE
, This
->global_funcs
[id
- 1], NULL
, pdp
, pvarRes
);
1457 FIXME("Unsupported flags %x\n", wFlags
);
1464 if (id
> This
->global_vars_cnt
) {
1465 hres
= DISP_E_MEMBERNOTFOUND
;
1469 if (This
->global_vars
[id
- 1]->is_const
)
1471 FIXME("const not supported\n");
1476 hres
= invoke_variant_prop(This
->ctx
, &This
->global_vars
[id
- 1]->v
, wFlags
, pdp
, pvarRes
);
1479 This
->ctx
->vbcaller
->caller
= prev_caller
;
1481 IServiceProvider_Release(pspCaller
);
1485 static HRESULT WINAPI
ScriptDisp_DeleteMemberByName(IDispatchEx
*iface
, BSTR bstrName
, DWORD grfdex
)
1487 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1488 FIXME("(%p)->(%s %lx)\n", This
, debugstr_w(bstrName
), grfdex
);
1492 static HRESULT WINAPI
ScriptDisp_DeleteMemberByDispID(IDispatchEx
*iface
, DISPID id
)
1494 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1495 FIXME("(%p)->(%lx)\n", This
, id
);
1499 static HRESULT WINAPI
ScriptDisp_GetMemberProperties(IDispatchEx
*iface
, DISPID id
, DWORD grfdexFetch
, DWORD
*pgrfdex
)
1501 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1502 FIXME("(%p)->(%lx %lx %p)\n", This
, id
, grfdexFetch
, pgrfdex
);
1506 static HRESULT WINAPI
ScriptDisp_GetMemberName(IDispatchEx
*iface
, DISPID id
, BSTR
*pbstrName
)
1508 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1509 FIXME("(%p)->(%lx %p)\n", This
, id
, pbstrName
);
1513 static HRESULT WINAPI
ScriptDisp_GetNextDispID(IDispatchEx
*iface
, DWORD grfdex
, DISPID id
, DISPID
*pid
)
1515 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1516 FIXME("(%p)->(%lx %lx %p)\n", This
, grfdex
, id
, pid
);
1520 static HRESULT WINAPI
ScriptDisp_GetNameSpaceParent(IDispatchEx
*iface
, IUnknown
**ppunk
)
1522 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1523 FIXME("(%p)->(%p)\n", This
, ppunk
);
1527 static IDispatchExVtbl ScriptDispVtbl
= {
1528 ScriptDisp_QueryInterface
,
1531 ScriptDisp_GetTypeInfoCount
,
1532 ScriptDisp_GetTypeInfo
,
1533 ScriptDisp_GetIDsOfNames
,
1535 ScriptDisp_GetDispID
,
1536 ScriptDisp_InvokeEx
,
1537 ScriptDisp_DeleteMemberByName
,
1538 ScriptDisp_DeleteMemberByDispID
,
1539 ScriptDisp_GetMemberProperties
,
1540 ScriptDisp_GetMemberName
,
1541 ScriptDisp_GetNextDispID
,
1542 ScriptDisp_GetNameSpaceParent
1545 HRESULT
create_script_disp(script_ctx_t
*ctx
, ScriptDisp
**ret
)
1547 ScriptDisp
*script_disp
;
1549 script_disp
= calloc(1, sizeof(*script_disp
));
1551 return E_OUTOFMEMORY
;
1553 script_disp
->IDispatchEx_iface
.lpVtbl
= &ScriptDispVtbl
;
1554 script_disp
->ref
= 1;
1555 script_disp
->ctx
= ctx
;
1556 heap_pool_init(&script_disp
->heap
);
1557 script_disp
->rnd
= 0x50000;
1563 void collect_objects(script_ctx_t
*ctx
)
1565 vbdisp_t
*iter
, *iter2
;
1567 LIST_FOR_EACH_ENTRY_SAFE(iter
, iter2
, &ctx
->objects
, vbdisp_t
, entry
)
1568 run_terminator(iter
);
1570 while(!list_empty(&ctx
->objects
)) {
1571 iter
= LIST_ENTRY(list_head(&ctx
->objects
), vbdisp_t
, entry
);
1573 IDispatchEx_AddRef(&iter
->IDispatchEx_iface
);
1576 list_remove(&iter
->entry
);
1577 list_init(&iter
->entry
);
1578 IDispatchEx_Release(&iter
->IDispatchEx_iface
);
1582 HRESULT
disp_get_id(IDispatch
*disp
, BSTR name
, vbdisp_invoke_type_t invoke_type
, BOOL search_private
, DISPID
*id
)
1584 IDispatchEx
*dispex
;
1588 vbdisp
= unsafe_impl_from_IDispatch(disp
);
1590 return vbdisp_get_id(vbdisp
, name
, invoke_type
, search_private
, id
);
1592 hres
= IDispatch_QueryInterface(disp
, &IID_IDispatchEx
, (void**)&dispex
);
1594 TRACE("using IDispatch\n");
1595 return IDispatch_GetIDsOfNames(disp
, &IID_NULL
, &name
, 1, 0, id
);
1598 hres
= IDispatchEx_GetDispID(dispex
, name
, fdexNameCaseInsensitive
, id
);
1599 IDispatchEx_Release(dispex
);
1603 #define RPC_E_SERVER_UNAVAILABLE 0x800706ba
1605 void map_vbs_exception(EXCEPINFO
*ei
)
1609 if(HRESULT_FACILITY(ei
->scode
) == FACILITY_VBS
)
1610 vbse_number
= HRESULT_CODE(ei
->scode
);
1614 case E_NOTIMPL
: vbse_number
= VBSE_ACTION_NOT_SUPPORTED
; break;
1615 case E_NOINTERFACE
: vbse_number
= VBSE_OLE_NOT_SUPPORTED
; break;
1616 case DISP_E_UNKNOWNINTERFACE
: vbse_number
= VBSE_OLE_NO_PROP_OR_METHOD
; break;
1617 case DISP_E_MEMBERNOTFOUND
: vbse_number
= VBSE_OLE_NO_PROP_OR_METHOD
; break;
1618 case DISP_E_PARAMNOTFOUND
: vbse_number
= VBSE_NAMED_PARAM_NOT_FOUND
; break;
1619 case DISP_E_TYPEMISMATCH
: vbse_number
= VBSE_TYPE_MISMATCH
; break;
1620 case DISP_E_UNKNOWNNAME
: vbse_number
= VBSE_OLE_NO_PROP_OR_METHOD
; break;
1621 case DISP_E_NONAMEDARGS
: vbse_number
= VBSE_NAMED_ARGS_NOT_SUPPORTED
; break;
1622 case DISP_E_BADVARTYPE
: vbse_number
= VBSE_INVALID_TYPELIB_VARIABLE
; break;
1623 case DISP_E_OVERFLOW
: vbse_number
= VBSE_OVERFLOW
; break;
1624 case DISP_E_BADINDEX
: vbse_number
= VBSE_OUT_OF_BOUNDS
; break;
1625 case DISP_E_UNKNOWNLCID
: vbse_number
= VBSE_LOCALE_SETTING_NOT_SUPPORTED
; break;
1626 case DISP_E_ARRAYISLOCKED
: vbse_number
= VBSE_ARRAY_LOCKED
; break;
1627 case DISP_E_BADPARAMCOUNT
: vbse_number
= VBSE_FUNC_ARITY_MISMATCH
; break;
1628 case DISP_E_PARAMNOTOPTIONAL
: vbse_number
= VBSE_PARAMETER_NOT_OPTIONAL
; break;
1629 case DISP_E_NOTACOLLECTION
: vbse_number
= VBSE_NOT_ENUM
; break;
1630 case TYPE_E_DLLFUNCTIONNOTFOUND
: vbse_number
= VBSE_INVALID_DLL_FUNCTION_NAME
; break;
1631 case TYPE_E_TYPEMISMATCH
: vbse_number
= VBSE_TYPE_MISMATCH
; break;
1632 case TYPE_E_OUTOFBOUNDS
: vbse_number
= VBSE_OUT_OF_BOUNDS
; break;
1633 case TYPE_E_IOERROR
: vbse_number
= VBSE_IO_ERROR
; break;
1634 case TYPE_E_CANTCREATETMPFILE
: vbse_number
= VBSE_CANT_CREATE_TMP_FILE
; break;
1635 case STG_E_FILENOTFOUND
: vbse_number
= VBSE_OLE_FILE_NOT_FOUND
; break;
1636 case STG_E_PATHNOTFOUND
: vbse_number
= VBSE_PATH_NOT_FOUND
; break;
1637 case STG_E_TOOMANYOPENFILES
: vbse_number
= VBSE_TOO_MANY_FILES
; break;
1638 case STG_E_ACCESSDENIED
: vbse_number
= VBSE_PERMISSION_DENIED
; break;
1639 case STG_E_INSUFFICIENTMEMORY
: vbse_number
= VBSE_OUT_OF_MEMORY
; break;
1640 case STG_E_NOMOREFILES
: vbse_number
= VBSE_TOO_MANY_FILES
; break;
1641 case STG_E_DISKISWRITEPROTECTED
: vbse_number
= VBSE_PERMISSION_DENIED
; break;
1642 case STG_E_WRITEFAULT
: vbse_number
= VBSE_IO_ERROR
; break;
1643 case STG_E_READFAULT
: vbse_number
= VBSE_IO_ERROR
; break;
1644 case STG_E_SHAREVIOLATION
: vbse_number
= VBSE_PATH_FILE_ACCESS
; break;
1645 case STG_E_LOCKVIOLATION
: vbse_number
= VBSE_PERMISSION_DENIED
; break;
1646 case STG_E_FILEALREADYEXISTS
: vbse_number
= VBSE_FILE_ALREADY_EXISTS
; break;
1647 case STG_E_MEDIUMFULL
: vbse_number
= VBSE_DISK_FULL
; break;
1648 case STG_E_INVALIDNAME
: vbse_number
= VBSE_FILE_NOT_FOUND
; break;
1649 case STG_E_INUSE
: vbse_number
= VBSE_PERMISSION_DENIED
; break;
1650 case STG_E_NOTCURRENT
: vbse_number
= VBSE_PERMISSION_DENIED
; break;
1651 case STG_E_CANTSAVE
: vbse_number
= VBSE_IO_ERROR
; break;
1652 case REGDB_E_CLASSNOTREG
: vbse_number
= VBSE_CANT_CREATE_OBJECT
; break;
1653 case MK_E_UNAVAILABLE
: vbse_number
= VBSE_CANT_CREATE_OBJECT
; break;
1654 case MK_E_INVALIDEXTENSION
: vbse_number
= VBSE_OLE_FILE_NOT_FOUND
; break;
1655 case MK_E_CANTOPENFILE
: vbse_number
= VBSE_OLE_FILE_NOT_FOUND
; break;
1656 case CO_E_CLASSSTRING
: vbse_number
= VBSE_CANT_CREATE_OBJECT
; break;
1657 case CO_E_APPNOTFOUND
: vbse_number
= VBSE_CANT_CREATE_OBJECT
; break;
1658 case CO_E_APPDIDNTREG
: vbse_number
= VBSE_CANT_CREATE_OBJECT
; break;
1659 case E_ACCESSDENIED
: vbse_number
= VBSE_PERMISSION_DENIED
; break;
1660 case E_OUTOFMEMORY
: vbse_number
= VBSE_OUT_OF_MEMORY
; break;
1661 case E_INVALIDARG
: vbse_number
= VBSE_ILLEGAL_FUNC_CALL
; break;
1662 case RPC_E_SERVER_UNAVAILABLE
: vbse_number
= VBSE_SERVER_NOT_FOUND
; break;
1663 case CO_E_SERVER_EXEC_FAILURE
: vbse_number
= VBSE_CANT_CREATE_OBJECT
; break;
1664 default: return; /* early return, all other HRESULT left as-is */
1666 ei
->scode
= MAKE_VBSERROR(vbse_number
);
1669 ei
->bstrSource
= get_vbscript_string(VBS_RUNTIME_ERROR
);
1670 if(!ei
->bstrDescription
)
1671 if(!(ei
->bstrDescription
= get_vbscript_string(vbse_number
)))
1672 ei
->bstrDescription
= get_vbscript_string(VBS_UNKNOWN_RUNTIME_ERROR
);
1675 HRESULT
disp_call(script_ctx_t
*ctx
, IDispatch
*disp
, DISPID id
, DISPPARAMS
*dp
, VARIANT
*retv
)
1677 const WORD flags
= DISPATCH_METHOD
|(retv
? DISPATCH_PROPERTYGET
: 0);
1678 IDispatchEx
*dispex
;
1683 memset(&ei
, 0, sizeof(ei
));
1685 V_VT(retv
) = VT_EMPTY
;
1687 vbdisp
= unsafe_impl_from_IDispatch(disp
);
1688 if(vbdisp
&& vbdisp
->desc
&& vbdisp
->desc
->ctx
== ctx
)
1689 return invoke_vbdisp(vbdisp
, id
, flags
, FALSE
, dp
, retv
);
1691 hres
= IDispatch_QueryInterface(disp
, &IID_IDispatchEx
, (void**)&dispex
);
1692 if(SUCCEEDED(hres
)) {
1693 hres
= IDispatchEx_InvokeEx(dispex
, id
, ctx
->lcid
, flags
, dp
, retv
, &ei
, &ctx
->vbcaller
->IServiceProvider_iface
);
1694 IDispatchEx_Release(dispex
);
1698 TRACE("using IDispatch\n");
1699 hres
= IDispatch_Invoke(disp
, id
, &IID_NULL
, ctx
->lcid
, flags
, dp
, retv
, &ei
, &err
);
1702 if(hres
== DISP_E_EXCEPTION
) {
1705 hres
= SCRIPT_E_RECORDED
;
1710 HRESULT
get_disp_value(script_ctx_t
*ctx
, IDispatch
*disp
, VARIANT
*v
)
1712 DISPPARAMS dp
= {NULL
};
1714 return MAKE_VBSERROR(VBSE_OBJECT_VARIABLE_NOT_SET
);
1715 return disp_call(ctx
, disp
, DISPID_VALUE
, &dp
, v
);
1718 HRESULT
disp_propput(script_ctx_t
*ctx
, IDispatch
*disp
, DISPID id
, WORD flags
, DISPPARAMS
*dp
)
1720 IDispatchEx
*dispex
;
1725 vbdisp
= unsafe_impl_from_IDispatch(disp
);
1726 if(vbdisp
&& vbdisp
->desc
&& vbdisp
->desc
->ctx
== ctx
)
1727 return invoke_vbdisp(vbdisp
, id
, flags
, FALSE
, dp
, NULL
);
1729 hres
= IDispatch_QueryInterface(disp
, &IID_IDispatchEx
, (void**)&dispex
);
1730 if(SUCCEEDED(hres
)) {
1731 hres
= IDispatchEx_InvokeEx(dispex
, id
, ctx
->lcid
, flags
, dp
, NULL
, &ei
, &ctx
->vbcaller
->IServiceProvider_iface
);
1732 IDispatchEx_Release(dispex
);
1736 TRACE("using IDispatch\n");
1737 hres
= IDispatch_Invoke(disp
, id
, &IID_NULL
, ctx
->lcid
, flags
, dp
, NULL
, &ei
, &err
);
1740 if(hres
== DISP_E_EXCEPTION
) {
1743 hres
= SCRIPT_E_RECORDED
;