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};
203 if(arg_cnt(params
)) {
204 FIXME("arguments not implemented\n");
208 hres
= get_propput_arg(This
->desc
->ctx
, params
, flags
, &put_val
, &needs_release
);
212 dp
.rgvarg
= &put_val
;
213 func
= This
->desc
->funcs
[id
].entries
[V_VT(&put_val
) == VT_DISPATCH
? VBDISP_SET
: VBDISP_LET
];
215 FIXME("no letter/setter\n");
216 return DISP_E_MEMBERNOTFOUND
;
219 hres
= exec_script(This
->desc
->ctx
, extern_caller
, func
, This
, &dp
, NULL
);
221 VariantClear(&put_val
);
225 FIXME("flags %x\n", flags
);
226 return DISP_E_MEMBERNOTFOUND
;
230 if(id
>= This
->desc
->prop_cnt
+ This
->desc
->func_cnt
)
231 return DISP_E_MEMBERNOTFOUND
;
233 TRACE("%p->%s\n", This
, debugstr_w(This
->desc
->props
[id
- This
->desc
->func_cnt
].name
));
234 return invoke_variant_prop(This
->desc
->ctx
, This
->props
+(id
-This
->desc
->func_cnt
), flags
, params
, res
);
237 static BOOL
run_terminator(vbdisp_t
*This
)
241 if(This
->terminator_ran
)
243 This
->terminator_ran
= TRUE
;
245 if(!This
->desc
->class_terminate_id
)
249 exec_script(This
->desc
->ctx
, FALSE
, This
->desc
->funcs
[This
->desc
->class_terminate_id
].entries
[VBDISP_CALLGET
],
254 static void clean_props(vbdisp_t
*This
)
261 for(i
=0; i
< This
->desc
->array_cnt
; i
++) {
262 if(This
->arrays
[i
]) {
263 SafeArrayDestroy(This
->arrays
[i
]);
264 This
->arrays
[i
] = NULL
;
268 for(i
=0; i
< This
->desc
->prop_cnt
; i
++)
269 VariantClear(This
->props
+i
);
272 static inline vbdisp_t
*impl_from_IDispatchEx(IDispatchEx
*iface
)
274 return CONTAINING_RECORD(iface
, vbdisp_t
, IDispatchEx_iface
);
277 static HRESULT WINAPI
DispatchEx_QueryInterface(IDispatchEx
*iface
, REFIID riid
, void **ppv
)
279 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
281 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
282 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
283 *ppv
= &This
->IDispatchEx_iface
;
284 }else if(IsEqualGUID(&IID_IDispatch
, riid
)) {
285 TRACE("(%p)->(IID_IDispatch %p)\n", This
, ppv
);
286 *ppv
= &This
->IDispatchEx_iface
;
287 }else if(IsEqualGUID(&IID_IDispatchEx
, riid
)) {
288 TRACE("(%p)->(IID_IDispatchEx %p)\n", This
, ppv
);
289 *ppv
= &This
->IDispatchEx_iface
;
291 WARN("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
293 return E_NOINTERFACE
;
296 IUnknown_AddRef((IUnknown
*)*ppv
);
300 static ULONG WINAPI
DispatchEx_AddRef(IDispatchEx
*iface
)
302 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
303 LONG ref
= InterlockedIncrement(&This
->ref
);
305 TRACE("(%p) ref=%d\n", This
, ref
);
310 static ULONG WINAPI
DispatchEx_Release(IDispatchEx
*iface
)
312 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
313 LONG ref
= InterlockedDecrement(&This
->ref
);
315 TRACE("(%p) ref=%d\n", This
, ref
);
317 if(!ref
&& run_terminator(This
)) {
319 list_remove(&This
->entry
);
320 heap_free(This
->arrays
);
327 static HRESULT WINAPI
DispatchEx_GetTypeInfoCount(IDispatchEx
*iface
, UINT
*pctinfo
)
329 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
331 TRACE("(%p)->(%p)\n", This
, pctinfo
);
337 static HRESULT WINAPI
DispatchEx_GetTypeInfo(IDispatchEx
*iface
, UINT iTInfo
, LCID lcid
,
340 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
341 FIXME("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
345 static HRESULT WINAPI
DispatchEx_GetIDsOfNames(IDispatchEx
*iface
, REFIID riid
,
346 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
,
349 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
350 FIXME("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
,
355 static HRESULT WINAPI
DispatchEx_Invoke(IDispatchEx
*iface
, DISPID dispIdMember
,
356 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
,
357 VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
359 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
361 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
362 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
364 return IDispatchEx_InvokeEx(&This
->IDispatchEx_iface
, dispIdMember
, lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, NULL
);
367 static HRESULT WINAPI
DispatchEx_GetDispID(IDispatchEx
*iface
, BSTR bstrName
, DWORD grfdex
, DISPID
*pid
)
369 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
371 TRACE("(%p)->(%s %x %p)\n", This
, debugstr_w(bstrName
), grfdex
, pid
);
373 grfdex
&= ~FDEX_VERSION_MASK
;
378 /* Tests show that fdexNameCaseSensitive is ignored */
380 if(grfdex
& ~(fdexNameEnsure
|fdexNameCaseInsensitive
|fdexNameCaseSensitive
)) {
381 FIXME("unsupported flags %x\n", grfdex
);
385 return vbdisp_get_id(This
, bstrName
, VBDISP_ANY
, FALSE
, pid
);
388 static HRESULT WINAPI
DispatchEx_InvokeEx(IDispatchEx
*iface
, DISPID id
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pdp
,
389 VARIANT
*pvarRes
, EXCEPINFO
*pei
, IServiceProvider
*pspCaller
)
391 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
393 TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This
, id
, lcid
, wFlags
, pdp
, pvarRes
, pei
, pspCaller
);
399 V_VT(pvarRes
) = VT_EMPTY
;
401 return invoke_vbdisp(This
, id
, wFlags
, TRUE
, pdp
, pvarRes
);
404 static HRESULT WINAPI
DispatchEx_DeleteMemberByName(IDispatchEx
*iface
, BSTR bstrName
, DWORD grfdex
)
406 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
407 FIXME("(%p)->(%s %x)\n", This
, debugstr_w(bstrName
), grfdex
);
411 static HRESULT WINAPI
DispatchEx_DeleteMemberByDispID(IDispatchEx
*iface
, DISPID id
)
413 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
414 FIXME("(%p)->(%x)\n", This
, id
);
418 static HRESULT WINAPI
DispatchEx_GetMemberProperties(IDispatchEx
*iface
, DISPID id
, DWORD grfdexFetch
, DWORD
*pgrfdex
)
420 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
421 FIXME("(%p)->(%x %x %p)\n", This
, id
, grfdexFetch
, pgrfdex
);
425 static HRESULT WINAPI
DispatchEx_GetMemberName(IDispatchEx
*iface
, DISPID id
, BSTR
*pbstrName
)
427 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
428 FIXME("(%p)->(%x %p)\n", This
, id
, pbstrName
);
432 static HRESULT WINAPI
DispatchEx_GetNextDispID(IDispatchEx
*iface
, DWORD grfdex
, DISPID id
, DISPID
*pid
)
434 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
435 FIXME("(%p)->(%x %x %p)\n", This
, grfdex
, id
, pid
);
439 static HRESULT WINAPI
DispatchEx_GetNameSpaceParent(IDispatchEx
*iface
, IUnknown
**ppunk
)
441 vbdisp_t
*This
= impl_from_IDispatchEx(iface
);
442 FIXME("(%p)->(%p)\n", This
, ppunk
);
446 static IDispatchExVtbl DispatchExVtbl
= {
447 DispatchEx_QueryInterface
,
450 DispatchEx_GetTypeInfoCount
,
451 DispatchEx_GetTypeInfo
,
452 DispatchEx_GetIDsOfNames
,
454 DispatchEx_GetDispID
,
456 DispatchEx_DeleteMemberByName
,
457 DispatchEx_DeleteMemberByDispID
,
458 DispatchEx_GetMemberProperties
,
459 DispatchEx_GetMemberName
,
460 DispatchEx_GetNextDispID
,
461 DispatchEx_GetNameSpaceParent
464 static inline vbdisp_t
*unsafe_impl_from_IDispatch(IDispatch
*iface
)
466 return iface
->lpVtbl
== (IDispatchVtbl
*)&DispatchExVtbl
467 ? CONTAINING_RECORD(iface
, vbdisp_t
, IDispatchEx_iface
)
471 HRESULT
create_vbdisp(const class_desc_t
*desc
, vbdisp_t
**ret
)
476 vbdisp
= heap_alloc_zero( FIELD_OFFSET( vbdisp_t
, props
[desc
->prop_cnt
] ));
478 return E_OUTOFMEMORY
;
480 vbdisp
->IDispatchEx_iface
.lpVtbl
= &DispatchExVtbl
;
484 list_add_tail(&desc
->ctx
->objects
, &vbdisp
->entry
);
486 if(desc
->array_cnt
) {
487 vbdisp
->arrays
= heap_alloc_zero(desc
->array_cnt
* sizeof(*vbdisp
->arrays
));
491 for(i
=0; i
< desc
->array_cnt
; i
++) {
492 if(!desc
->array_descs
[i
].dim_cnt
)
495 vbdisp
->arrays
[i
] = SafeArrayCreate(VT_VARIANT
, desc
->array_descs
[i
].dim_cnt
, desc
->array_descs
[i
].bounds
);
496 if(!vbdisp
->arrays
[i
]) {
497 hres
= E_OUTOFMEMORY
;
502 if(SUCCEEDED(hres
)) {
503 for(i
=0, j
=0; i
< desc
->prop_cnt
; i
++) {
504 if(desc
->props
[i
].is_array
) {
505 V_VT(vbdisp
->props
+i
) = VT_ARRAY
|VT_BYREF
|VT_VARIANT
;
506 V_ARRAYREF(vbdisp
->props
+i
) = vbdisp
->arrays
+ j
++;
511 hres
= E_OUTOFMEMORY
;
515 if(SUCCEEDED(hres
) && desc
->class_initialize_id
) {
517 hres
= exec_script(desc
->ctx
, FALSE
, desc
->funcs
[desc
->class_initialize_id
].entries
[VBDISP_CALLGET
],
522 IDispatchEx_Release(&vbdisp
->IDispatchEx_iface
);
530 struct typeinfo_func
{
536 ITypeInfo ITypeInfo_iface
;
537 ITypeComp ITypeComp_iface
;
542 struct typeinfo_func
*funcs
;
547 static function_t
*get_func_from_memid(const ScriptTypeInfo
*typeinfo
, MEMBERID memid
)
549 UINT a
= 0, b
= typeinfo
->num_funcs
;
551 if (!(memid
& DISPID_FUNCTION_MASK
)) return NULL
;
555 UINT i
= (a
+ b
- 1) / 2;
557 if (memid
== typeinfo
->funcs
[i
].memid
)
558 return typeinfo
->funcs
[i
].func
;
559 else if (memid
< typeinfo
->funcs
[i
].memid
)
567 static inline ScriptTypeInfo
*ScriptTypeInfo_from_ITypeInfo(ITypeInfo
*iface
)
569 return CONTAINING_RECORD(iface
, ScriptTypeInfo
, ITypeInfo_iface
);
572 static inline ScriptTypeInfo
*ScriptTypeInfo_from_ITypeComp(ITypeComp
*iface
)
574 return CONTAINING_RECORD(iface
, ScriptTypeInfo
, ITypeComp_iface
);
577 static HRESULT WINAPI
ScriptTypeInfo_QueryInterface(ITypeInfo
*iface
, REFIID riid
, void **ppv
)
579 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
581 if (IsEqualGUID(&IID_IUnknown
, riid
) || IsEqualGUID(&IID_ITypeInfo
, riid
))
582 *ppv
= &This
->ITypeInfo_iface
;
583 else if (IsEqualGUID(&IID_ITypeComp
, riid
))
584 *ppv
= &This
->ITypeComp_iface
;
587 WARN("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
589 return E_NOINTERFACE
;
592 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
593 IUnknown_AddRef((IUnknown
*)*ppv
);
597 static ULONG WINAPI
ScriptTypeInfo_AddRef(ITypeInfo
*iface
)
599 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
600 LONG ref
= InterlockedIncrement(&This
->ref
);
602 TRACE("(%p) ref=%d\n", This
, ref
);
607 static ULONG WINAPI
ScriptTypeInfo_Release(ITypeInfo
*iface
)
609 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
610 LONG ref
= InterlockedDecrement(&This
->ref
);
613 TRACE("(%p) ref=%d\n", This
, ref
);
617 for (i
= 0; i
< This
->num_funcs
; i
++)
618 release_vbscode(This
->funcs
[i
].func
->code_ctx
);
620 IDispatchEx_Release(&This
->disp
->IDispatchEx_iface
);
621 heap_free(This
->funcs
);
627 static HRESULT WINAPI
ScriptTypeInfo_GetTypeAttr(ITypeInfo
*iface
, TYPEATTR
**ppTypeAttr
)
629 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
632 TRACE("(%p)->(%p)\n", This
, ppTypeAttr
);
634 if (!ppTypeAttr
) return E_INVALIDARG
;
636 attr
= heap_alloc_zero(sizeof(*attr
));
637 if (!attr
) return E_OUTOFMEMORY
;
639 attr
->guid
= GUID_VBScriptTypeInfo
;
640 attr
->lcid
= LOCALE_USER_DEFAULT
;
641 attr
->memidConstructor
= MEMBERID_NIL
;
642 attr
->memidDestructor
= MEMBERID_NIL
;
643 attr
->cbSizeInstance
= 4;
644 attr
->typekind
= TKIND_DISPATCH
;
645 attr
->cFuncs
= This
->num_funcs
;
646 attr
->cVars
= This
->num_vars
;
647 attr
->cImplTypes
= 1;
648 attr
->cbSizeVft
= sizeof(IDispatchVtbl
);
649 attr
->cbAlignment
= 4;
650 attr
->wTypeFlags
= TYPEFLAG_FDISPATCHABLE
;
651 attr
->wMajorVerNum
= VBSCRIPT_MAJOR_VERSION
;
652 attr
->wMinorVerNum
= VBSCRIPT_MINOR_VERSION
;
658 static HRESULT WINAPI
ScriptTypeInfo_GetTypeComp(ITypeInfo
*iface
, ITypeComp
**ppTComp
)
660 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
662 TRACE("(%p)->(%p)\n", This
, ppTComp
);
664 if (!ppTComp
) return E_INVALIDARG
;
666 *ppTComp
= &This
->ITypeComp_iface
;
667 ITypeInfo_AddRef(iface
);
671 static HRESULT WINAPI
ScriptTypeInfo_GetFuncDesc(ITypeInfo
*iface
, UINT index
, FUNCDESC
**ppFuncDesc
)
673 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
678 TRACE("(%p)->(%u %p)\n", This
, index
, ppFuncDesc
);
680 if (!ppFuncDesc
) return E_INVALIDARG
;
681 if (index
>= This
->num_funcs
) return TYPE_E_ELEMENTNOTFOUND
;
682 func
= This
->funcs
[index
].func
;
684 /* Store the parameter array after the FUNCDESC structure */
685 desc
= heap_alloc_zero(sizeof(*desc
) + sizeof(ELEMDESC
) * func
->arg_cnt
);
686 if (!desc
) return E_OUTOFMEMORY
;
688 desc
->memid
= This
->funcs
[index
].memid
;
689 desc
->funckind
= FUNC_DISPATCH
;
690 desc
->invkind
= INVOKE_FUNC
;
691 desc
->callconv
= CC_STDCALL
;
692 desc
->cParams
= func
->arg_cnt
;
693 desc
->elemdescFunc
.tdesc
.vt
= (func
->type
== FUNC_SUB
) ? VT_VOID
: VT_VARIANT
;
695 if (func
->arg_cnt
) desc
->lprgelemdescParam
= (ELEMDESC
*)(desc
+ 1);
696 for (i
= 0; i
< func
->arg_cnt
; i
++)
697 desc
->lprgelemdescParam
[i
].tdesc
.vt
= VT_VARIANT
;
703 static HRESULT WINAPI
ScriptTypeInfo_GetVarDesc(ITypeInfo
*iface
, UINT index
, VARDESC
**ppVarDesc
)
705 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
708 TRACE("(%p)->(%u %p)\n", This
, index
, ppVarDesc
);
710 if (!ppVarDesc
) return E_INVALIDARG
;
711 if (index
>= This
->num_vars
) return TYPE_E_ELEMENTNOTFOUND
;
713 desc
= heap_alloc_zero(sizeof(*desc
));
714 if (!desc
) return E_OUTOFMEMORY
;
716 desc
->memid
= index
+ 1;
717 desc
->varkind
= VAR_DISPATCH
;
718 desc
->elemdescVar
.tdesc
.vt
= VT_VARIANT
;
724 static HRESULT WINAPI
ScriptTypeInfo_GetNames(ITypeInfo
*iface
, MEMBERID memid
, BSTR
*rgBstrNames
,
725 UINT cMaxNames
, UINT
*pcNames
)
727 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
728 ITypeInfo
*disp_typeinfo
;
733 TRACE("(%p)->(%d %p %u %p)\n", This
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
735 if (!rgBstrNames
|| !pcNames
) return E_INVALIDARG
;
736 if (memid
<= 0) return TYPE_E_ELEMENTNOTFOUND
;
738 func
= get_func_from_memid(This
, memid
);
739 if (!func
&& memid
> This
->num_vars
)
741 hr
= get_dispatch_typeinfo(&disp_typeinfo
);
742 if (FAILED(hr
)) return hr
;
744 return ITypeInfo_GetNames(disp_typeinfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
748 if (!cMaxNames
) return S_OK
;
752 UINT num
= min(cMaxNames
, func
->arg_cnt
+ 1);
754 rgBstrNames
[0] = SysAllocString(func
->name
);
755 if (!rgBstrNames
[0]) return E_OUTOFMEMORY
;
757 for (i
= 1; i
< num
; i
++)
759 if (!(rgBstrNames
[i
] = SysAllocString(func
->args
[i
- 1].name
)))
761 do SysFreeString(rgBstrNames
[--i
]); while (i
);
762 return E_OUTOFMEMORY
;
768 rgBstrNames
[0] = SysAllocString(This
->disp
->global_vars
[memid
- 1]->name
);
769 if (!rgBstrNames
[0]) return E_OUTOFMEMORY
;
777 static HRESULT WINAPI
ScriptTypeInfo_GetRefTypeOfImplType(ITypeInfo
*iface
, UINT index
, HREFTYPE
*pRefType
)
779 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
781 TRACE("(%p)->(%u %p)\n", This
, index
, pRefType
);
783 /* We only inherit from IDispatch */
784 if (!pRefType
) return E_INVALIDARG
;
785 if (index
!= 0) return TYPE_E_ELEMENTNOTFOUND
;
791 static HRESULT WINAPI
ScriptTypeInfo_GetImplTypeFlags(ITypeInfo
*iface
, UINT index
, INT
*pImplTypeFlags
)
793 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
795 TRACE("(%p)->(%u %p)\n", This
, index
, pImplTypeFlags
);
797 if (!pImplTypeFlags
) return E_INVALIDARG
;
798 if (index
!= 0) return TYPE_E_ELEMENTNOTFOUND
;
804 static HRESULT WINAPI
ScriptTypeInfo_GetIDsOfNames(ITypeInfo
*iface
, LPOLESTR
*rgszNames
, UINT cNames
,
807 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
808 ITypeInfo
*disp_typeinfo
;
813 TRACE("(%p)->(%p %u %p)\n", This
, rgszNames
, cNames
, pMemId
);
815 if (!rgszNames
|| !cNames
|| !pMemId
) return E_INVALIDARG
;
817 for (i
= 0; i
< cNames
; i
++) pMemId
[i
] = MEMBERID_NIL
;
820 for (i
= 0; i
< This
->num_funcs
; i
++)
822 function_t
*func
= This
->funcs
[i
].func
;
824 if (wcsicmp(name
, func
->name
)) continue;
825 pMemId
[0] = This
->funcs
[i
].memid
;
827 for (j
= 1; j
< cNames
; j
++)
830 for (arg
= func
->arg_cnt
; --arg
>= 0;)
831 if (!wcsicmp(name
, func
->args
[arg
].name
))
836 hr
= DISP_E_UNKNOWNNAME
;
841 for (i
= 0; i
< This
->num_vars
; i
++)
843 if (wcsicmp(name
, This
->disp
->global_vars
[i
]->name
)) continue;
848 /* Look into the inherited IDispatch */
849 hr
= get_dispatch_typeinfo(&disp_typeinfo
);
850 if (FAILED(hr
)) return hr
;
852 return ITypeInfo_GetIDsOfNames(disp_typeinfo
, rgszNames
, cNames
, pMemId
);
855 static HRESULT WINAPI
ScriptTypeInfo_Invoke(ITypeInfo
*iface
, PVOID pvInstance
, MEMBERID memid
, WORD wFlags
,
856 DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
858 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
859 ITypeInfo
*disp_typeinfo
;
863 TRACE("(%p)->(%p %d %d %p %p %p %p)\n", This
, pvInstance
, memid
, wFlags
,
864 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
866 if (!pvInstance
) return E_INVALIDARG
;
867 if (memid
<= 0) return TYPE_E_ELEMENTNOTFOUND
;
869 if (!get_func_from_memid(This
, memid
) && memid
> This
->num_vars
)
871 hr
= get_dispatch_typeinfo(&disp_typeinfo
);
872 if (FAILED(hr
)) return hr
;
874 return ITypeInfo_Invoke(disp_typeinfo
, pvInstance
, memid
, wFlags
, pDispParams
,
875 pVarResult
, pExcepInfo
, puArgErr
);
878 hr
= IUnknown_QueryInterface((IUnknown
*)pvInstance
, &IID_IDispatch
, (void**)&disp
);
879 if (FAILED(hr
)) return hr
;
881 hr
= IDispatch_Invoke(disp
, memid
, &IID_NULL
, LOCALE_USER_DEFAULT
, wFlags
,
882 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
883 IDispatch_Release(disp
);
888 static HRESULT WINAPI
ScriptTypeInfo_GetDocumentation(ITypeInfo
*iface
, MEMBERID memid
, BSTR
*pBstrName
,
889 BSTR
*pBstrDocString
, DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
891 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
892 ITypeInfo
*disp_typeinfo
;
896 TRACE("(%p)->(%d %p %p %p %p)\n", This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
898 if (pBstrDocString
) *pBstrDocString
= NULL
;
899 if (pdwHelpContext
) *pdwHelpContext
= 0;
900 if (pBstrHelpFile
) *pBstrHelpFile
= NULL
;
902 if (memid
== MEMBERID_NIL
)
904 if (pBstrName
&& !(*pBstrName
= SysAllocString(L
"VBScriptTypeInfo")))
905 return E_OUTOFMEMORY
;
906 if (pBstrDocString
&&
907 !(*pBstrDocString
= SysAllocString(L
"Visual Basic Scripting Type Info")))
909 if (pBstrName
) SysFreeString(*pBstrName
);
910 return E_OUTOFMEMORY
;
914 if (memid
<= 0) return TYPE_E_ELEMENTNOTFOUND
;
916 func
= get_func_from_memid(This
, memid
);
917 if (!func
&& memid
> This
->num_vars
)
919 hr
= get_dispatch_typeinfo(&disp_typeinfo
);
920 if (FAILED(hr
)) return hr
;
922 return ITypeInfo_GetDocumentation(disp_typeinfo
, memid
, pBstrName
, pBstrDocString
,
923 pdwHelpContext
, pBstrHelpFile
);
928 *pBstrName
= SysAllocString(func
? func
->name
: This
->disp
->global_vars
[memid
- 1]->name
);
929 if (!*pBstrName
) return E_OUTOFMEMORY
;
934 static HRESULT WINAPI
ScriptTypeInfo_GetDllEntry(ITypeInfo
*iface
, MEMBERID memid
, INVOKEKIND invKind
,
935 BSTR
*pBstrDllName
, BSTR
*pBstrName
, WORD
*pwOrdinal
)
937 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
938 ITypeInfo
*disp_typeinfo
;
941 TRACE("(%p)->(%d %d %p %p %p)\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
943 if (pBstrDllName
) *pBstrDllName
= NULL
;
944 if (pBstrName
) *pBstrName
= NULL
;
945 if (pwOrdinal
) *pwOrdinal
= 0;
947 if (!get_func_from_memid(This
, memid
) && memid
> This
->num_vars
)
949 hr
= get_dispatch_typeinfo(&disp_typeinfo
);
950 if (FAILED(hr
)) return hr
;
952 return ITypeInfo_GetDllEntry(disp_typeinfo
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
954 return TYPE_E_BADMODULEKIND
;
957 static HRESULT WINAPI
ScriptTypeInfo_GetRefTypeInfo(ITypeInfo
*iface
, HREFTYPE hRefType
, ITypeInfo
**ppTInfo
)
959 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
962 TRACE("(%p)->(%x %p)\n", This
, hRefType
, ppTInfo
);
964 if (!ppTInfo
|| (INT
)hRefType
< 0) return E_INVALIDARG
;
966 if (hRefType
& ~3) return E_FAIL
;
969 hr
= get_dispatch_typeinfo(ppTInfo
);
970 if (FAILED(hr
)) return hr
;
975 ITypeInfo_AddRef(*ppTInfo
);
979 static HRESULT WINAPI
ScriptTypeInfo_AddressOfMember(ITypeInfo
*iface
, MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
981 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
982 ITypeInfo
*disp_typeinfo
;
985 TRACE("(%p)->(%d %d %p)\n", This
, memid
, invKind
, ppv
);
987 if (!ppv
) return E_INVALIDARG
;
990 if (!get_func_from_memid(This
, memid
) && memid
> This
->num_vars
)
992 hr
= get_dispatch_typeinfo(&disp_typeinfo
);
993 if (FAILED(hr
)) return hr
;
995 return ITypeInfo_AddressOfMember(disp_typeinfo
, memid
, invKind
, ppv
);
997 return TYPE_E_BADMODULEKIND
;
1000 static HRESULT WINAPI
ScriptTypeInfo_CreateInstance(ITypeInfo
*iface
, IUnknown
*pUnkOuter
, REFIID riid
, PVOID
*ppvObj
)
1002 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
1004 TRACE("(%p)->(%p %s %p)\n", This
, pUnkOuter
, debugstr_guid(riid
), ppvObj
);
1006 if (!ppvObj
) return E_INVALIDARG
;
1009 return TYPE_E_BADMODULEKIND
;
1012 static HRESULT WINAPI
ScriptTypeInfo_GetMops(ITypeInfo
*iface
, MEMBERID memid
, BSTR
*pBstrMops
)
1014 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
1015 ITypeInfo
*disp_typeinfo
;
1018 TRACE("(%p)->(%d %p)\n", This
, memid
, pBstrMops
);
1020 if (!pBstrMops
) return E_INVALIDARG
;
1022 if (!get_func_from_memid(This
, memid
) && memid
> This
->num_vars
)
1024 hr
= get_dispatch_typeinfo(&disp_typeinfo
);
1025 if (FAILED(hr
)) return hr
;
1027 return ITypeInfo_GetMops(disp_typeinfo
, memid
, pBstrMops
);
1034 static HRESULT WINAPI
ScriptTypeInfo_GetContainingTypeLib(ITypeInfo
*iface
, ITypeLib
**ppTLib
, UINT
*pIndex
)
1036 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
1038 FIXME("(%p)->(%p %p)\n", This
, ppTLib
, pIndex
);
1043 static void WINAPI
ScriptTypeInfo_ReleaseTypeAttr(ITypeInfo
*iface
, TYPEATTR
*pTypeAttr
)
1045 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
1047 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
1049 heap_free(pTypeAttr
);
1052 static void WINAPI
ScriptTypeInfo_ReleaseFuncDesc(ITypeInfo
*iface
, FUNCDESC
*pFuncDesc
)
1054 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
1056 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
1058 heap_free(pFuncDesc
);
1061 static void WINAPI
ScriptTypeInfo_ReleaseVarDesc(ITypeInfo
*iface
, VARDESC
*pVarDesc
)
1063 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeInfo(iface
);
1065 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
1067 heap_free(pVarDesc
);
1070 static const ITypeInfoVtbl ScriptTypeInfoVtbl
= {
1071 ScriptTypeInfo_QueryInterface
,
1072 ScriptTypeInfo_AddRef
,
1073 ScriptTypeInfo_Release
,
1074 ScriptTypeInfo_GetTypeAttr
,
1075 ScriptTypeInfo_GetTypeComp
,
1076 ScriptTypeInfo_GetFuncDesc
,
1077 ScriptTypeInfo_GetVarDesc
,
1078 ScriptTypeInfo_GetNames
,
1079 ScriptTypeInfo_GetRefTypeOfImplType
,
1080 ScriptTypeInfo_GetImplTypeFlags
,
1081 ScriptTypeInfo_GetIDsOfNames
,
1082 ScriptTypeInfo_Invoke
,
1083 ScriptTypeInfo_GetDocumentation
,
1084 ScriptTypeInfo_GetDllEntry
,
1085 ScriptTypeInfo_GetRefTypeInfo
,
1086 ScriptTypeInfo_AddressOfMember
,
1087 ScriptTypeInfo_CreateInstance
,
1088 ScriptTypeInfo_GetMops
,
1089 ScriptTypeInfo_GetContainingTypeLib
,
1090 ScriptTypeInfo_ReleaseTypeAttr
,
1091 ScriptTypeInfo_ReleaseFuncDesc
,
1092 ScriptTypeInfo_ReleaseVarDesc
1095 static HRESULT WINAPI
ScriptTypeComp_QueryInterface(ITypeComp
*iface
, REFIID riid
, void **ppv
)
1097 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeComp(iface
);
1098 return ITypeInfo_QueryInterface(&This
->ITypeInfo_iface
, riid
, ppv
);
1101 static ULONG WINAPI
ScriptTypeComp_AddRef(ITypeComp
*iface
)
1103 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeComp(iface
);
1104 return ITypeInfo_AddRef(&This
->ITypeInfo_iface
);
1107 static ULONG WINAPI
ScriptTypeComp_Release(ITypeComp
*iface
)
1109 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeComp(iface
);
1110 return ITypeInfo_Release(&This
->ITypeInfo_iface
);
1113 static HRESULT WINAPI
ScriptTypeComp_Bind(ITypeComp
*iface
, LPOLESTR szName
, ULONG lHashVal
, WORD wFlags
,
1114 ITypeInfo
**ppTInfo
, DESCKIND
*pDescKind
, BINDPTR
*pBindPtr
)
1116 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeComp(iface
);
1117 UINT flags
= wFlags
? wFlags
: ~0;
1118 ITypeInfo
*disp_typeinfo
;
1119 ITypeComp
*disp_typecomp
;
1123 TRACE("(%p)->(%s %08x %d %p %p %p)\n", This
, debugstr_w(szName
), lHashVal
,
1124 wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
1126 if (!szName
|| !ppTInfo
|| !pDescKind
|| !pBindPtr
)
1127 return E_INVALIDARG
;
1129 for (i
= 0; i
< This
->num_funcs
; i
++)
1131 if (wcsicmp(szName
, This
->funcs
[i
].func
->name
)) continue;
1132 if (!(flags
& INVOKE_FUNC
)) return TYPE_E_TYPEMISMATCH
;
1134 hr
= ITypeInfo_GetFuncDesc(&This
->ITypeInfo_iface
, i
, &pBindPtr
->lpfuncdesc
);
1135 if (FAILED(hr
)) return hr
;
1137 *pDescKind
= DESCKIND_FUNCDESC
;
1138 *ppTInfo
= &This
->ITypeInfo_iface
;
1139 ITypeInfo_AddRef(*ppTInfo
);
1143 for (i
= 0; i
< This
->num_vars
; i
++)
1145 if (wcsicmp(szName
, This
->disp
->global_vars
[i
]->name
)) continue;
1146 if (!(flags
& INVOKE_PROPERTYGET
)) return TYPE_E_TYPEMISMATCH
;
1148 hr
= ITypeInfo_GetVarDesc(&This
->ITypeInfo_iface
, i
, &pBindPtr
->lpvardesc
);
1149 if (FAILED(hr
)) return hr
;
1151 *pDescKind
= DESCKIND_VARDESC
;
1152 *ppTInfo
= &This
->ITypeInfo_iface
;
1153 ITypeInfo_AddRef(*ppTInfo
);
1157 /* Look into the inherited IDispatch */
1158 hr
= get_dispatch_typeinfo(&disp_typeinfo
);
1159 if (FAILED(hr
)) return hr
;
1161 hr
= ITypeInfo_GetTypeComp(disp_typeinfo
, &disp_typecomp
);
1162 if (FAILED(hr
)) return hr
;
1164 hr
= ITypeComp_Bind(disp_typecomp
, szName
, lHashVal
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
1165 ITypeComp_Release(disp_typecomp
);
1169 static HRESULT WINAPI
ScriptTypeComp_BindType(ITypeComp
*iface
, LPOLESTR szName
, ULONG lHashVal
,
1170 ITypeInfo
**ppTInfo
, ITypeComp
**ppTComp
)
1172 ScriptTypeInfo
*This
= ScriptTypeInfo_from_ITypeComp(iface
);
1173 ITypeInfo
*disp_typeinfo
;
1174 ITypeComp
*disp_typecomp
;
1177 TRACE("(%p)->(%s %08x %p %p)\n", This
, debugstr_w(szName
), lHashVal
, ppTInfo
, ppTComp
);
1179 if (!szName
|| !ppTInfo
|| !ppTComp
)
1180 return E_INVALIDARG
;
1182 /* Look into the inherited IDispatch */
1183 hr
= get_dispatch_typeinfo(&disp_typeinfo
);
1184 if (FAILED(hr
)) return hr
;
1186 hr
= ITypeInfo_GetTypeComp(disp_typeinfo
, &disp_typecomp
);
1187 if (FAILED(hr
)) return hr
;
1189 hr
= ITypeComp_BindType(disp_typecomp
, szName
, lHashVal
, ppTInfo
, ppTComp
);
1190 ITypeComp_Release(disp_typecomp
);
1194 static const ITypeCompVtbl ScriptTypeCompVtbl
= {
1195 ScriptTypeComp_QueryInterface
,
1196 ScriptTypeComp_AddRef
,
1197 ScriptTypeComp_Release
,
1198 ScriptTypeComp_Bind
,
1199 ScriptTypeComp_BindType
1202 static inline ScriptDisp
*ScriptDisp_from_IDispatchEx(IDispatchEx
*iface
)
1204 return CONTAINING_RECORD(iface
, ScriptDisp
, IDispatchEx_iface
);
1207 static HRESULT WINAPI
ScriptDisp_QueryInterface(IDispatchEx
*iface
, REFIID riid
, void **ppv
)
1209 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1211 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
1212 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
1213 *ppv
= &This
->IDispatchEx_iface
;
1214 }else if(IsEqualGUID(&IID_IDispatch
, riid
)) {
1215 TRACE("(%p)->(IID_IDispatch %p)\n", This
, ppv
);
1216 *ppv
= &This
->IDispatchEx_iface
;
1217 }else if(IsEqualGUID(&IID_IDispatchEx
, riid
)) {
1218 TRACE("(%p)->(IID_IDispatchEx %p)\n", This
, ppv
);
1219 *ppv
= &This
->IDispatchEx_iface
;
1221 WARN("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
1223 return E_NOINTERFACE
;
1226 IUnknown_AddRef((IUnknown
*)*ppv
);
1230 static ULONG WINAPI
ScriptDisp_AddRef(IDispatchEx
*iface
)
1232 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1233 LONG ref
= InterlockedIncrement(&This
->ref
);
1235 TRACE("(%p) ref=%d\n", This
, ref
);
1240 static ULONG WINAPI
ScriptDisp_Release(IDispatchEx
*iface
)
1242 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1243 LONG ref
= InterlockedDecrement(&This
->ref
);
1246 TRACE("(%p) ref=%d\n", This
, ref
);
1251 for (i
= 0; i
< This
->global_vars_cnt
; i
++)
1252 release_dynamic_var(This
->global_vars
[i
]);
1254 heap_pool_free(&This
->heap
);
1255 heap_free(This
->global_vars
);
1256 heap_free(This
->global_funcs
);
1263 static HRESULT WINAPI
ScriptDisp_GetTypeInfoCount(IDispatchEx
*iface
, UINT
*pctinfo
)
1265 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1267 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1273 static HRESULT WINAPI
ScriptDisp_GetTypeInfo(IDispatchEx
*iface
, UINT iTInfo
, LCID lcid
, ITypeInfo
**ret
)
1275 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1276 ScriptTypeInfo
*type_info
;
1280 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ret
);
1283 return DISP_E_BADINDEX
;
1285 if(!(type_info
= heap_alloc(sizeof(*type_info
))))
1286 return E_OUTOFMEMORY
;
1288 for(i
= 0; i
< This
->global_funcs_cnt
; i
++)
1289 if(This
->global_funcs
[i
]->is_public
)
1292 type_info
->ITypeInfo_iface
.lpVtbl
= &ScriptTypeInfoVtbl
;
1293 type_info
->ITypeComp_iface
.lpVtbl
= &ScriptTypeCompVtbl
;
1295 type_info
->num_funcs
= num_funcs
;
1296 type_info
->num_vars
= This
->global_vars_cnt
;
1297 type_info
->disp
= This
;
1299 type_info
->funcs
= heap_alloc(sizeof(*type_info
->funcs
) * num_funcs
);
1300 if(!type_info
->funcs
)
1302 heap_free(type_info
);
1303 return E_OUTOFMEMORY
;
1306 for(j
= 0, i
= 0; i
< This
->global_funcs_cnt
; i
++)
1308 if(!This
->global_funcs
[i
]->is_public
) continue;
1310 type_info
->funcs
[j
].memid
= i
+ 1 + DISPID_FUNCTION_MASK
;
1311 type_info
->funcs
[j
].func
= This
->global_funcs
[i
];
1312 grab_vbscode(This
->global_funcs
[i
]->code_ctx
);
1316 IDispatchEx_AddRef(&This
->IDispatchEx_iface
);
1318 *ret
= &type_info
->ITypeInfo_iface
;
1322 static HRESULT WINAPI
ScriptDisp_GetIDsOfNames(IDispatchEx
*iface
, REFIID riid
,
1323 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
1325 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1329 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
,
1332 for(i
=0; i
< cNames
; i
++) {
1333 hres
= IDispatchEx_GetDispID(&This
->IDispatchEx_iface
, rgszNames
[i
], 0, rgDispId
+i
);
1341 static HRESULT WINAPI
ScriptDisp_Invoke(IDispatchEx
*iface
, DISPID dispIdMember
, REFIID riid
, LCID lcid
,
1342 WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1344 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1346 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
1347 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1349 return IDispatchEx_InvokeEx(&This
->IDispatchEx_iface
, dispIdMember
, lcid
, wFlags
,
1350 pDispParams
, pVarResult
, pExcepInfo
, NULL
);
1353 static HRESULT WINAPI
ScriptDisp_GetDispID(IDispatchEx
*iface
, BSTR bstrName
, DWORD grfdex
, DISPID
*pid
)
1355 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1358 TRACE("(%p)->(%s %x %p)\n", This
, debugstr_w(bstrName
), grfdex
, pid
);
1361 return E_UNEXPECTED
;
1363 for(i
= 0; i
< This
->global_vars_cnt
; i
++) {
1364 if(!wcsicmp(This
->global_vars
[i
]->name
, bstrName
)) {
1370 for(i
= 0; i
< This
->global_funcs_cnt
; i
++) {
1371 if(!wcsicmp(This
->global_funcs
[i
]->name
, bstrName
)) {
1372 *pid
= i
+ 1 + DISPID_FUNCTION_MASK
;
1378 return DISP_E_UNKNOWNNAME
;
1381 static HRESULT WINAPI
ScriptDisp_InvokeEx(IDispatchEx
*iface
, DISPID id
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pdp
,
1382 VARIANT
*pvarRes
, EXCEPINFO
*pei
, IServiceProvider
*pspCaller
)
1384 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1387 TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This
, id
, lcid
, wFlags
, pdp
, pvarRes
, pei
, pspCaller
);
1390 return E_UNEXPECTED
;
1392 if (id
& DISPID_FUNCTION_MASK
)
1394 id
&= ~DISPID_FUNCTION_MASK
;
1395 if (id
> This
->global_funcs_cnt
)
1396 return DISP_E_MEMBERNOTFOUND
;
1400 case DISPATCH_METHOD
:
1401 case DISPATCH_METHOD
| DISPATCH_PROPERTYGET
:
1402 hres
= exec_script(This
->ctx
, TRUE
, This
->global_funcs
[id
- 1], NULL
, pdp
, pvarRes
);
1405 FIXME("Unsupported flags %x\n", wFlags
);
1412 if (id
> This
->global_vars_cnt
)
1413 return DISP_E_MEMBERNOTFOUND
;
1415 if (This
->global_vars
[id
- 1]->is_const
)
1417 FIXME("const not supported\n");
1421 return invoke_variant_prop(This
->ctx
, &This
->global_vars
[id
- 1]->v
, wFlags
, pdp
, pvarRes
);
1424 static HRESULT WINAPI
ScriptDisp_DeleteMemberByName(IDispatchEx
*iface
, BSTR bstrName
, DWORD grfdex
)
1426 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1427 FIXME("(%p)->(%s %x)\n", This
, debugstr_w(bstrName
), grfdex
);
1431 static HRESULT WINAPI
ScriptDisp_DeleteMemberByDispID(IDispatchEx
*iface
, DISPID id
)
1433 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1434 FIXME("(%p)->(%x)\n", This
, id
);
1438 static HRESULT WINAPI
ScriptDisp_GetMemberProperties(IDispatchEx
*iface
, DISPID id
, DWORD grfdexFetch
, DWORD
*pgrfdex
)
1440 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1441 FIXME("(%p)->(%x %x %p)\n", This
, id
, grfdexFetch
, pgrfdex
);
1445 static HRESULT WINAPI
ScriptDisp_GetMemberName(IDispatchEx
*iface
, DISPID id
, BSTR
*pbstrName
)
1447 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1448 FIXME("(%p)->(%x %p)\n", This
, id
, pbstrName
);
1452 static HRESULT WINAPI
ScriptDisp_GetNextDispID(IDispatchEx
*iface
, DWORD grfdex
, DISPID id
, DISPID
*pid
)
1454 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1455 FIXME("(%p)->(%x %x %p)\n", This
, grfdex
, id
, pid
);
1459 static HRESULT WINAPI
ScriptDisp_GetNameSpaceParent(IDispatchEx
*iface
, IUnknown
**ppunk
)
1461 ScriptDisp
*This
= ScriptDisp_from_IDispatchEx(iface
);
1462 FIXME("(%p)->(%p)\n", This
, ppunk
);
1466 static IDispatchExVtbl ScriptDispVtbl
= {
1467 ScriptDisp_QueryInterface
,
1470 ScriptDisp_GetTypeInfoCount
,
1471 ScriptDisp_GetTypeInfo
,
1472 ScriptDisp_GetIDsOfNames
,
1474 ScriptDisp_GetDispID
,
1475 ScriptDisp_InvokeEx
,
1476 ScriptDisp_DeleteMemberByName
,
1477 ScriptDisp_DeleteMemberByDispID
,
1478 ScriptDisp_GetMemberProperties
,
1479 ScriptDisp_GetMemberName
,
1480 ScriptDisp_GetNextDispID
,
1481 ScriptDisp_GetNameSpaceParent
1484 HRESULT
create_script_disp(script_ctx_t
*ctx
, ScriptDisp
**ret
)
1486 ScriptDisp
*script_disp
;
1488 script_disp
= heap_alloc_zero(sizeof(*script_disp
));
1490 return E_OUTOFMEMORY
;
1492 script_disp
->IDispatchEx_iface
.lpVtbl
= &ScriptDispVtbl
;
1493 script_disp
->ref
= 1;
1494 script_disp
->ctx
= ctx
;
1495 heap_pool_init(&script_disp
->heap
);
1501 void collect_objects(script_ctx_t
*ctx
)
1503 vbdisp_t
*iter
, *iter2
;
1505 LIST_FOR_EACH_ENTRY_SAFE(iter
, iter2
, &ctx
->objects
, vbdisp_t
, entry
)
1506 run_terminator(iter
);
1508 while(!list_empty(&ctx
->objects
)) {
1509 iter
= LIST_ENTRY(list_head(&ctx
->objects
), vbdisp_t
, entry
);
1511 IDispatchEx_AddRef(&iter
->IDispatchEx_iface
);
1514 list_remove(&iter
->entry
);
1515 list_init(&iter
->entry
);
1516 IDispatchEx_Release(&iter
->IDispatchEx_iface
);
1520 HRESULT
disp_get_id(IDispatch
*disp
, BSTR name
, vbdisp_invoke_type_t invoke_type
, BOOL search_private
, DISPID
*id
)
1522 IDispatchEx
*dispex
;
1526 vbdisp
= unsafe_impl_from_IDispatch(disp
);
1528 return vbdisp_get_id(vbdisp
, name
, invoke_type
, search_private
, id
);
1530 hres
= IDispatch_QueryInterface(disp
, &IID_IDispatchEx
, (void**)&dispex
);
1532 TRACE("using IDispatch\n");
1533 return IDispatch_GetIDsOfNames(disp
, &IID_NULL
, &name
, 1, 0, id
);
1536 hres
= IDispatchEx_GetDispID(dispex
, name
, fdexNameCaseInsensitive
, id
);
1537 IDispatchEx_Release(dispex
);
1541 #define RPC_E_SERVER_UNAVAILABLE 0x800706ba
1543 HRESULT
map_hres(HRESULT hres
)
1545 if(SUCCEEDED(hres
) || HRESULT_FACILITY(hres
) == FACILITY_VBS
)
1549 case E_NOTIMPL
: return MAKE_VBSERROR(VBSE_ACTION_NOT_SUPPORTED
);
1550 case E_NOINTERFACE
: return MAKE_VBSERROR(VBSE_OLE_NOT_SUPPORTED
);
1551 case DISP_E_UNKNOWNINTERFACE
: return MAKE_VBSERROR(VBSE_OLE_NO_PROP_OR_METHOD
);
1552 case DISP_E_MEMBERNOTFOUND
: return MAKE_VBSERROR(VBSE_OLE_NO_PROP_OR_METHOD
);
1553 case DISP_E_PARAMNOTFOUND
: return MAKE_VBSERROR(VBSE_NAMED_PARAM_NOT_FOUND
);
1554 case DISP_E_TYPEMISMATCH
: return MAKE_VBSERROR(VBSE_TYPE_MISMATCH
);
1555 case DISP_E_UNKNOWNNAME
: return MAKE_VBSERROR(VBSE_OLE_NO_PROP_OR_METHOD
);
1556 case DISP_E_NONAMEDARGS
: return MAKE_VBSERROR(VBSE_NAMED_ARGS_NOT_SUPPORTED
);
1557 case DISP_E_BADVARTYPE
: return MAKE_VBSERROR(VBSE_INVALID_TYPELIB_VARIABLE
);
1558 case DISP_E_OVERFLOW
: return MAKE_VBSERROR(VBSE_OVERFLOW
);
1559 case DISP_E_BADINDEX
: return MAKE_VBSERROR(VBSE_OUT_OF_BOUNDS
);
1560 case DISP_E_UNKNOWNLCID
: return MAKE_VBSERROR(VBSE_LOCALE_SETTING_NOT_SUPPORTED
);
1561 case DISP_E_ARRAYISLOCKED
: return MAKE_VBSERROR(VBSE_ARRAY_LOCKED
);
1562 case DISP_E_BADPARAMCOUNT
: return MAKE_VBSERROR(VBSE_FUNC_ARITY_MISMATCH
);
1563 case DISP_E_PARAMNOTOPTIONAL
: return MAKE_VBSERROR(VBSE_PARAMETER_NOT_OPTIONAL
);
1564 case DISP_E_NOTACOLLECTION
: return MAKE_VBSERROR(VBSE_NOT_ENUM
);
1565 case TYPE_E_DLLFUNCTIONNOTFOUND
: return MAKE_VBSERROR(VBSE_INVALID_DLL_FUNCTION_NAME
);
1566 case TYPE_E_TYPEMISMATCH
: return MAKE_VBSERROR(VBSE_TYPE_MISMATCH
);
1567 case TYPE_E_OUTOFBOUNDS
: return MAKE_VBSERROR(VBSE_OUT_OF_BOUNDS
);
1568 case TYPE_E_IOERROR
: return MAKE_VBSERROR(VBSE_IO_ERROR
);
1569 case TYPE_E_CANTCREATETMPFILE
: return MAKE_VBSERROR(VBSE_CANT_CREATE_TMP_FILE
);
1570 case STG_E_FILENOTFOUND
: return MAKE_VBSERROR(VBSE_OLE_FILE_NOT_FOUND
);
1571 case STG_E_PATHNOTFOUND
: return MAKE_VBSERROR(VBSE_PATH_NOT_FOUND
);
1572 case STG_E_TOOMANYOPENFILES
: return MAKE_VBSERROR(VBSE_TOO_MANY_FILES
);
1573 case STG_E_ACCESSDENIED
: return MAKE_VBSERROR(VBSE_PERMISSION_DENIED
);
1574 case STG_E_INSUFFICIENTMEMORY
: return MAKE_VBSERROR(VBSE_OUT_OF_MEMORY
);
1575 case STG_E_NOMOREFILES
: return MAKE_VBSERROR(VBSE_TOO_MANY_FILES
);
1576 case STG_E_DISKISWRITEPROTECTED
: return MAKE_VBSERROR(VBSE_PERMISSION_DENIED
);
1577 case STG_E_WRITEFAULT
: return MAKE_VBSERROR(VBSE_IO_ERROR
);
1578 case STG_E_READFAULT
: return MAKE_VBSERROR(VBSE_IO_ERROR
);
1579 case STG_E_SHAREVIOLATION
: return MAKE_VBSERROR(VBSE_PATH_FILE_ACCESS
);
1580 case STG_E_LOCKVIOLATION
: return MAKE_VBSERROR(VBSE_PERMISSION_DENIED
);
1581 case STG_E_FILEALREADYEXISTS
: return MAKE_VBSERROR(VBSE_FILE_ALREADY_EXISTS
);
1582 case STG_E_MEDIUMFULL
: return MAKE_VBSERROR(VBSE_DISK_FULL
);
1583 case STG_E_INVALIDNAME
: return MAKE_VBSERROR(VBSE_FILE_NOT_FOUND
);
1584 case STG_E_INUSE
: return MAKE_VBSERROR(VBSE_PERMISSION_DENIED
);
1585 case STG_E_NOTCURRENT
: return MAKE_VBSERROR(VBSE_PERMISSION_DENIED
);
1586 case STG_E_CANTSAVE
: return MAKE_VBSERROR(VBSE_IO_ERROR
);
1587 case REGDB_E_CLASSNOTREG
: return MAKE_VBSERROR(VBSE_CANT_CREATE_OBJECT
);
1588 case MK_E_UNAVAILABLE
: return MAKE_VBSERROR(VBSE_CANT_CREATE_OBJECT
);
1589 case MK_E_INVALIDEXTENSION
: return MAKE_VBSERROR(VBSE_OLE_FILE_NOT_FOUND
);
1590 case MK_E_CANTOPENFILE
: return MAKE_VBSERROR(VBSE_OLE_FILE_NOT_FOUND
);
1591 case CO_E_CLASSSTRING
: return MAKE_VBSERROR(VBSE_CANT_CREATE_OBJECT
);
1592 case CO_E_APPNOTFOUND
: return MAKE_VBSERROR(VBSE_CANT_CREATE_OBJECT
);
1593 case CO_E_APPDIDNTREG
: return MAKE_VBSERROR(VBSE_CANT_CREATE_OBJECT
);
1594 case E_ACCESSDENIED
: return MAKE_VBSERROR(VBSE_PERMISSION_DENIED
);
1595 case E_OUTOFMEMORY
: return MAKE_VBSERROR(VBSE_OUT_OF_MEMORY
);
1596 case E_INVALIDARG
: return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL
);
1597 case RPC_E_SERVER_UNAVAILABLE
: return MAKE_VBSERROR(VBSE_SERVER_NOT_FOUND
);
1598 case CO_E_SERVER_EXEC_FAILURE
: return MAKE_VBSERROR(VBSE_CANT_CREATE_OBJECT
);
1604 HRESULT
disp_call(script_ctx_t
*ctx
, IDispatch
*disp
, DISPID id
, DISPPARAMS
*dp
, VARIANT
*retv
)
1606 const WORD flags
= DISPATCH_METHOD
|(retv
? DISPATCH_PROPERTYGET
: 0);
1607 IDispatchEx
*dispex
;
1612 memset(&ei
, 0, sizeof(ei
));
1614 V_VT(retv
) = VT_EMPTY
;
1616 vbdisp
= unsafe_impl_from_IDispatch(disp
);
1617 if(vbdisp
&& vbdisp
->desc
&& vbdisp
->desc
->ctx
== ctx
)
1618 return invoke_vbdisp(vbdisp
, id
, flags
, FALSE
, dp
, retv
);
1620 hres
= IDispatch_QueryInterface(disp
, &IID_IDispatchEx
, (void**)&dispex
);
1621 if(SUCCEEDED(hres
)) {
1622 hres
= IDispatchEx_InvokeEx(dispex
, id
, ctx
->lcid
, flags
, dp
, retv
, &ei
, NULL
/* CALLER_FIXME */);
1623 IDispatchEx_Release(dispex
);
1627 TRACE("using IDispatch\n");
1628 hres
= IDispatch_Invoke(disp
, id
, &IID_NULL
, ctx
->lcid
, flags
, dp
, retv
, &ei
, &err
);
1631 if(hres
== DISP_E_EXCEPTION
) {
1634 hres
= SCRIPT_E_RECORDED
;
1639 HRESULT
get_disp_value(script_ctx_t
*ctx
, IDispatch
*disp
, VARIANT
*v
)
1641 DISPPARAMS dp
= {NULL
};
1643 return MAKE_VBSERROR(VBSE_OBJECT_VARIABLE_NOT_SET
);
1644 return disp_call(ctx
, disp
, DISPID_VALUE
, &dp
, v
);
1647 HRESULT
disp_propput(script_ctx_t
*ctx
, IDispatch
*disp
, DISPID id
, WORD flags
, DISPPARAMS
*dp
)
1649 IDispatchEx
*dispex
;
1654 vbdisp
= unsafe_impl_from_IDispatch(disp
);
1655 if(vbdisp
&& vbdisp
->desc
&& vbdisp
->desc
->ctx
== ctx
)
1656 return invoke_vbdisp(vbdisp
, id
, flags
, FALSE
, dp
, NULL
);
1658 hres
= IDispatch_QueryInterface(disp
, &IID_IDispatchEx
, (void**)&dispex
);
1659 if(SUCCEEDED(hres
)) {
1660 hres
= IDispatchEx_InvokeEx(dispex
, id
, ctx
->lcid
, flags
, dp
, NULL
, &ei
, NULL
/* FIXME! */);
1661 IDispatchEx_Release(dispex
);
1665 TRACE("using IDispatch\n");
1666 hres
= IDispatch_Invoke(disp
, id
, &IID_NULL
, ctx
->lcid
, flags
, dp
, NULL
, &ei
, &err
);
1669 if(hres
== DISP_E_EXCEPTION
) {
1672 hres
= SCRIPT_E_RECORDED
;