Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/msscript.ocx/msscript.c | 203 +++++++++++++++++++++++++++++++++-- 1 file changed, 195 insertions(+), 8 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index 3fc4aca..e986014 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -51,6 +51,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(msscript);
struct ScriptControl; typedef struct ConnectionPoint ConnectionPoint; +typedef struct ScriptProcedureCollection ScriptProcedureCollection; typedef struct ScriptHost ScriptHost;
struct ConnectionPoint { @@ -82,8 +83,17 @@ typedef struct { BSTR name; ScriptHost *host; IDispatch *script_dispatch; + + ScriptProcedureCollection *procedures; } ScriptModule;
+struct ScriptProcedureCollection { + IScriptProcedureCollection IScriptProcedureCollection_iface; + LONG ref; + + ScriptModule *module; +}; + struct ScriptHost { IActiveScriptSite IActiveScriptSite_iface; IActiveScriptSiteWindow IActiveScriptSiteWindow_iface; @@ -137,6 +147,7 @@ typedef enum tid_t { IScriptControl_tid, IScriptModuleCollection_tid, IScriptModule_tid, + IScriptProcedureCollection_tid, LAST_tid } tid_t;
@@ -146,7 +157,8 @@ static ITypeInfo *typeinfos[LAST_tid]; static REFIID tid_ids[] = { &IID_IScriptControl, &IID_IScriptModuleCollection, - &IID_IScriptModule + &IID_IScriptModule, + &IID_IScriptProcedureCollection, };
static HRESULT load_typelib(void) @@ -404,6 +416,11 @@ static inline ScriptControl *impl_from_IConnectionPointContainer(IConnectionPoin return CONTAINING_RECORD(iface, ScriptControl, IConnectionPointContainer_iface); }
+static inline ScriptProcedureCollection *impl_from_IScriptProcedureCollection(IScriptProcedureCollection *iface) +{ + return CONTAINING_RECORD(iface, ScriptProcedureCollection, IScriptProcedureCollection_iface); +} + static inline ScriptControl *impl_from_IScriptModuleCollection(IScriptModuleCollection *iface) { return CONTAINING_RECORD(iface, ScriptControl, IScriptModuleCollection_iface); @@ -674,6 +691,154 @@ static const IServiceProviderVtbl ServiceProviderVtbl = { ServiceProvider_QueryService };
+static HRESULT WINAPI ScriptProcedureCollection_QueryInterface(IScriptProcedureCollection *iface, REFIID riid, void **ppv) +{ + ScriptProcedureCollection *This = impl_from_IScriptProcedureCollection(iface); + + if (IsEqualGUID(&IID_IDispatch, riid) || IsEqualGUID(&IID_IUnknown, riid) || + IsEqualGUID(&IID_IScriptProcedureCollection, riid)) + { + *ppv = &This->IScriptProcedureCollection_iface; + } + else + { + WARN("unsupported interface: (%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); + *ppv = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; +} + +static ULONG WINAPI ScriptProcedureCollection_AddRef(IScriptProcedureCollection *iface) +{ + ScriptProcedureCollection *This = impl_from_IScriptProcedureCollection(iface); + LONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) ref=%d\n", This, ref); + + return ref; +} + +static ULONG WINAPI ScriptProcedureCollection_Release(IScriptProcedureCollection *iface) +{ + ScriptProcedureCollection *This = impl_from_IScriptProcedureCollection(iface); + LONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) ref=%d\n", This, ref); + + if (!ref) + { + This->module->procedures = NULL; + IScriptModule_Release(&This->module->IScriptModule_iface); + heap_free(This); + } + return ref; +} + +static HRESULT WINAPI ScriptProcedureCollection_GetTypeInfoCount(IScriptProcedureCollection *iface, UINT *pctinfo) +{ + ScriptProcedureCollection *This = impl_from_IScriptProcedureCollection(iface); + + TRACE("(%p)->(%p)\n", This, pctinfo); + + *pctinfo = 1; + return S_OK; +} + +static HRESULT WINAPI ScriptProcedureCollection_GetTypeInfo(IScriptProcedureCollection *iface, UINT iTInfo, + LCID lcid, ITypeInfo **ppTInfo) +{ + ScriptProcedureCollection *This = impl_from_IScriptProcedureCollection(iface); + + TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo); + + return get_typeinfo(IScriptProcedureCollection_tid, ppTInfo); +} + +static HRESULT WINAPI ScriptProcedureCollection_GetIDsOfNames(IScriptProcedureCollection *iface, REFIID riid, + LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) +{ + ScriptProcedureCollection *This = impl_from_IScriptProcedureCollection(iface); + ITypeInfo *typeinfo; + HRESULT hr; + + TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId); + + hr = get_typeinfo(IScriptProcedureCollection_tid, &typeinfo); + if (SUCCEEDED(hr)) + { + hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId); + ITypeInfo_Release(typeinfo); + } + + return hr; +} + +static HRESULT WINAPI ScriptProcedureCollection_Invoke(IScriptProcedureCollection *iface, DISPID dispIdMember, + REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, + EXCEPINFO *pExcepInfo, UINT *puArgErr) +{ + ScriptProcedureCollection *This = impl_from_IScriptProcedureCollection(iface); + ITypeInfo *typeinfo; + HRESULT hr; + + TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid), + lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); + + hr = get_typeinfo(IScriptProcedureCollection_tid, &typeinfo); + if(SUCCEEDED(hr)) + { + hr = ITypeInfo_Invoke(typeinfo, iface, dispIdMember, wFlags, + pDispParams, pVarResult, pExcepInfo, puArgErr); + ITypeInfo_Release(typeinfo); + } + + return hr; +} + +static HRESULT WINAPI ScriptProcedureCollection_get__NewEnum(IScriptProcedureCollection *iface, IUnknown **ppenumProcedures) +{ + ScriptProcedureCollection *This = impl_from_IScriptProcedureCollection(iface); + + FIXME("(%p)->(%p)\n", This, ppenumProcedures); + + return E_NOTIMPL; +} + +static HRESULT WINAPI ScriptProcedureCollection_get_Item(IScriptProcedureCollection *iface, VARIANT index, + IScriptProcedure **ppdispProcedure) +{ + ScriptProcedureCollection *This = impl_from_IScriptProcedureCollection(iface); + + FIXME("(%p)->(%s %p)\n", This, wine_dbgstr_variant(&index), ppdispProcedure); + + return E_NOTIMPL; +} + +static HRESULT WINAPI ScriptProcedureCollection_get_Count(IScriptProcedureCollection *iface, LONG *plCount) +{ + ScriptProcedureCollection *This = impl_from_IScriptProcedureCollection(iface); + + FIXME("(%p)->(%p)\n", This, plCount); + + return E_NOTIMPL; +} + +static const IScriptProcedureCollectionVtbl ScriptProcedureCollectionVtbl = { + ScriptProcedureCollection_QueryInterface, + ScriptProcedureCollection_AddRef, + ScriptProcedureCollection_Release, + ScriptProcedureCollection_GetTypeInfoCount, + ScriptProcedureCollection_GetTypeInfo, + ScriptProcedureCollection_GetIDsOfNames, + ScriptProcedureCollection_Invoke, + ScriptProcedureCollection_get__NewEnum, + ScriptProcedureCollection_get_Item, + ScriptProcedureCollection_get_Count +}; + static void detach_script_host(ScriptHost *host) { if (--host->module_count) @@ -848,9 +1013,29 @@ static HRESULT WINAPI ScriptModule_get_Procedures(IScriptModule *iface, IScriptP { ScriptModule *This = impl_from_IScriptModule(iface);
- FIXME("(%p)->(%p)\n", This, ppdispProcedures); + TRACE("(%p)->(%p)\n", This, ppdispProcedures);
- return E_NOTIMPL; + if (!This->host) + return E_FAIL; + + if (This->procedures) + IScriptProcedureCollection_AddRef(&This->procedures->IScriptProcedureCollection_iface); + else + { + ScriptProcedureCollection *procs; + + if (!(procs = heap_alloc(sizeof(*procs)))) + return E_OUTOFMEMORY; + + procs->IScriptProcedureCollection_iface.lpVtbl = &ScriptProcedureCollectionVtbl; + procs->ref = 1; + procs->module = This; + This->procedures = procs; + IScriptModule_AddRef(&This->IScriptModule_iface); + } + + *ppdispProcedures = &This->procedures->IScriptProcedureCollection_iface; + return S_OK; }
static HRESULT WINAPI ScriptModule_AddCode(IScriptModule *iface, BSTR code) @@ -1060,18 +1245,16 @@ static ScriptModule *create_module(ScriptHost *host, BSTR name) { ScriptModule *module;
- if (!(module = heap_alloc(sizeof(*module)))) return NULL; + if (!(module = heap_alloc_zero(sizeof(*module)))) return NULL;
module->IScriptModule_iface.lpVtbl = &ScriptModuleVtbl; module->ref = 1; - module->name = NULL; if (name && !(module->name = SysAllocString(name))) { heap_free(module); return NULL; } module->host = host; - module->script_dispatch = NULL; IActiveScriptSite_AddRef(&host->IActiveScriptSite_iface); return module; } @@ -1771,8 +1954,12 @@ static HRESULT WINAPI ScriptControl_get_CodeObject(IScriptControl *iface, IDispa static HRESULT WINAPI ScriptControl_get_Procedures(IScriptControl *iface, IScriptProcedureCollection **p) { ScriptControl *This = impl_from_IScriptControl(iface); - FIXME("(%p)->(%p)\n", This, p); - return E_NOTIMPL; + + TRACE("(%p)->(%p)\n", This, p); + + if (!This->host) return E_FAIL; + + return IScriptModule_get_Procedures(&This->modules[0]->IScriptModule_iface, p); }
static HRESULT WINAPI ScriptControl__AboutBox(IScriptControl *iface)
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/msscript.ocx/tests/msscript.c | 606 ++++++++++++++++++++++++++++- 1 file changed, 604 insertions(+), 2 deletions(-)
diff --git a/dlls/msscript.ocx/tests/msscript.c b/dlls/msscript.ocx/tests/msscript.c index 352bf78..a48a749 100644 --- a/dlls/msscript.ocx/tests/msscript.c +++ b/dlls/msscript.ocx/tests/msscript.c @@ -93,7 +93,16 @@ DEFINE_EXPECT(CreateInstance); DEFINE_EXPECT(SetInterfaceSafetyOptions); DEFINE_EXPECT(InitNew); DEFINE_EXPECT(Close); +DEFINE_EXPECT(Bind); +DEFINE_EXPECT(QI_ITypeComp); +DEFINE_EXPECT(GetTypeAttr); +DEFINE_EXPECT(GetNames); +DEFINE_EXPECT(GetFuncDesc); +DEFINE_EXPECT(ReleaseTypeAttr); +DEFINE_EXPECT(ReleaseFuncDesc); +DEFINE_EXPECT(ReleaseVarDesc); DEFINE_EXPECT(QI_IDispatchEx); +DEFINE_EXPECT(GetTypeInfo); DEFINE_EXPECT(GetIDsOfNames); DEFINE_EXPECT(Invoke); DEFINE_EXPECT(InvokeEx); @@ -118,6 +127,55 @@ static void _expect_ref(IUnknown* obj, ULONG ref, int line)
static IActiveScriptSite *site; static SCRIPTSTATE state; +static ITypeInfo TypeInfo; + +static struct +{ + const WCHAR *name; + SHORT num_args; + SHORT num_opt_args; + VARTYPE ret_type; + FUNCKIND func_kind; + INVOKEKIND invoke_kind; + WORD flags; +} custom_engine_funcs[] = +{ + { L"foobar", 3, 0, VT_I4, FUNC_DISPATCH, INVOKE_FUNC, 0 }, + { L"barfoo", 11, 2, VT_VOID, FUNC_VIRTUAL, INVOKE_FUNC, FUNCFLAG_FRESTRICTED }, + { L"empty", 0, 0, VT_EMPTY, FUNC_PUREVIRTUAL, INVOKE_PROPERTYGET, FUNCFLAG_FBINDABLE | FUNCFLAG_FDISPLAYBIND }, + { L"vararg", 4, -1, VT_BSTR, FUNC_NONVIRTUAL, INVOKE_PROPERTYPUT, FUNCFLAG_FREQUESTEDIT }, + { L"static", 0, 1, VT_PTR, FUNC_STATIC, INVOKE_PROPERTYPUTREF, FUNCFLAG_FHIDDEN }, + { L"deadbeef", 21, -9, VT_ERROR, 0xdeadbeef, 0xdeadbeef, 0xffff } +}; + +static int memid_to_func_index(MEMBERID memid) +{ + UINT idx = memid - 0xdeadbeef; + return idx < ARRAY_SIZE(custom_engine_funcs) ? idx : -1; +} + +static MEMBERID func_index_to_memid(UINT idx) +{ + return idx + 0xdeadbeef; +} + +static FUNCDESC *get_func_desc(UINT i) +{ + FUNCDESC *desc; + + if (!(desc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*desc)))) + return NULL; + + desc->memid = func_index_to_memid(i); + desc->cParams = custom_engine_funcs[i].num_args; + desc->cParamsOpt = custom_engine_funcs[i].num_opt_args; + desc->elemdescFunc.tdesc.vt = custom_engine_funcs[i].ret_type; + desc->elemdescFunc.paramdesc.wParamFlags = PARAMFLAG_FRETVAL; + desc->funckind = custom_engine_funcs[i].func_kind; + desc->invkind = custom_engine_funcs[i].invoke_kind; + desc->wFuncFlags = custom_engine_funcs[i].flags; + return desc; +}
static HRESULT WINAPI ActiveScriptParse_QueryInterface(IActiveScriptParse *iface, REFIID riid, void **ppv) { @@ -236,6 +294,282 @@ static const IObjectSafetyVtbl ObjectSafetyVtbl = {
static IObjectSafety ObjectSafety = { &ObjectSafetyVtbl };
+static HRESULT WINAPI TypeComp_QueryInterface(ITypeComp *iface, REFIID riid, void **ppv) +{ + *ppv = NULL; + ok(0, "unexpected call\n"); + return E_NOINTERFACE; +} + +static ULONG WINAPI TypeComp_AddRef(ITypeComp *iface) +{ + return 2; +} + +static ULONG WINAPI TypeComp_Release(ITypeComp *iface) +{ + return 1; +} + +static HRESULT WINAPI TypeComp_Bind(ITypeComp *iface, LPOLESTR szName, ULONG lHashVal, WORD wFlags, + ITypeInfo **ppTInfo, DESCKIND *pDescKind, BINDPTR *pBindPtr) +{ + ULONG hash = LHashValOfNameSys(sizeof(void*) == 8 ? SYS_WIN64 : SYS_WIN32, LOCALE_USER_DEFAULT, szName); + UINT i; + + CHECK_EXPECT(Bind); + ok(lHashVal == hash, "wrong hash, expected 0x%08x, got 0x%08x.\n", hash, lHashVal); + ok(wFlags == INVOKE_FUNC, "wrong flags, got 0x%x.\n", wFlags); + + *ppTInfo = NULL; + *pDescKind = DESCKIND_NONE; + pBindPtr->lptcomp = NULL; + + if (!lstrcmpW(szName, L"type_mismatch")) + return TYPE_E_TYPEMISMATCH; + + if (!lstrcmpW(szName, L"variable")) + { + if (!(pBindPtr->lpvardesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(VARDESC)))) + return E_OUTOFMEMORY; + *ppTInfo = &TypeInfo; + *pDescKind = DESCKIND_VARDESC; + return S_OK; + } + + for (i = 0; i < ARRAY_SIZE(custom_engine_funcs); i++) + { + if (!lstrcmpW(szName, custom_engine_funcs[i].name)) + { + *ppTInfo = &TypeInfo; + *pDescKind = DESCKIND_FUNCDESC; + pBindPtr->lpfuncdesc = get_func_desc(i); + return S_OK; + } + } + + return S_OK; +} + +static HRESULT WINAPI TypeComp_BindType(ITypeComp *iface, LPOLESTR szName, ULONG lHashVal, + ITypeInfo **ppTInfo, ITypeComp **ppTComp) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static const ITypeCompVtbl TypeCompVtbl = { + TypeComp_QueryInterface, + TypeComp_AddRef, + TypeComp_Release, + TypeComp_Bind, + TypeComp_BindType +}; + +static ITypeComp TypeComp = { &TypeCompVtbl }; + +static BOOL TypeComp_available = FALSE; +static HRESULT WINAPI TypeInfo_QueryInterface(ITypeInfo *iface, REFIID riid, void **ppv) +{ + *ppv = NULL; + + if (IsEqualGUID(&IID_ITypeComp, riid)) + { + CHECK_EXPECT(QI_ITypeComp); + if (TypeComp_available) + { + *ppv = &TypeComp; + return S_OK; + } + return E_NOINTERFACE; + } + + ok(0, "unexpected riid %s\n", wine_dbgstr_guid(riid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI TypeInfo_AddRef(ITypeInfo *iface) +{ + return 2; +} + +static ULONG WINAPI TypeInfo_Release(ITypeInfo *iface) +{ + return 1; +} + +static UINT TypeInfo_GetTypeAttr_cFuncs; +static HRESULT WINAPI TypeInfo_GetTypeAttr(ITypeInfo *iface, TYPEATTR **ppTypeAttr) +{ + CHECK_EXPECT(GetTypeAttr); + + if (!(*ppTypeAttr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(TYPEATTR)))) + return E_OUTOFMEMORY; + + (*ppTypeAttr)->cFuncs = TypeInfo_GetTypeAttr_cFuncs; + return S_OK; +} + +static HRESULT WINAPI TypeInfo_GetTypeComp(ITypeInfo *iface, ITypeComp **ppTComp) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI TypeInfo_GetFuncDesc(ITypeInfo *iface, UINT index, FUNCDESC **ppFuncDesc) +{ + CHECK_EXPECT(GetFuncDesc); + + if (index >= ARRAY_SIZE(custom_engine_funcs)) + return E_INVALIDARG; + + *ppFuncDesc = get_func_desc(index); + return S_OK; +} + +static HRESULT WINAPI TypeInfo_GetVarDesc(ITypeInfo *iface, UINT index, VARDESC **ppVarDesc) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI TypeInfo_GetNames(ITypeInfo *iface, MEMBERID memid, BSTR *rgBstrNames, + UINT cMaxNames, UINT *pcNames) +{ + int idx; + + CHECK_EXPECT(GetNames); + ok(cMaxNames == 1, "unexpected cMaxNames, got %u.\n", cMaxNames); + ok(rgBstrNames != NULL, "rgBstrNames is NULL.\n"); + ok(pcNames != NULL, "pcNames is NULL.\n"); + + idx = memid_to_func_index(memid); + if (idx != -1) + { + *rgBstrNames = SysAllocString(custom_engine_funcs[idx].name); + *pcNames = 1; + return S_OK; + } + + *pcNames = 0; + return TYPE_E_ELEMENTNOTFOUND; +} + +static HRESULT WINAPI TypeInfo_GetRefTypeOfImplType(ITypeInfo *iface, UINT index, HREFTYPE *pRefType) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI TypeInfo_GetImplTypeFlags(ITypeInfo *iface, UINT index, INT *pImplTypeFlags) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI TypeInfo_GetIDsOfNames(ITypeInfo *iface, LPOLESTR *rgszNames, UINT cNames, + MEMBERID *pMemId) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI TypeInfo_Invoke(ITypeInfo *iface, PVOID pvInstance, MEMBERID memid, WORD wFlags, + DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI TypeInfo_GetDocumentation(ITypeInfo *iface, MEMBERID memid, BSTR *pBstrName, + BSTR *pBstrDocString, DWORD *pdwHelpContext, BSTR *pBstrHelpFile) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI TypeInfo_GetDllEntry(ITypeInfo *iface, MEMBERID memid, INVOKEKIND invKind, + BSTR *pBstrDllName, BSTR *pBstrName, WORD *pwOrdinal) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI TypeInfo_GetRefTypeInfo(ITypeInfo *iface, HREFTYPE hRefType, ITypeInfo **ppTInfo) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI TypeInfo_AddressOfMember(ITypeInfo *iface, MEMBERID memid, INVOKEKIND invKind, PVOID *ppv) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI TypeInfo_CreateInstance(ITypeInfo *iface, IUnknown *pUnkOuter, REFIID riid, PVOID *ppvObj) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI TypeInfo_GetMops(ITypeInfo *iface, MEMBERID memid, BSTR *pBstrMops) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI TypeInfo_GetContainingTypeLib(ITypeInfo *iface, ITypeLib **ppTLib, UINT *pIndex) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static void WINAPI TypeInfo_ReleaseTypeAttr(ITypeInfo *iface, TYPEATTR *pTypeAttr) +{ + CHECK_EXPECT(ReleaseTypeAttr); + HeapFree(GetProcessHeap(), 0, pTypeAttr); +} + +static void WINAPI TypeInfo_ReleaseFuncDesc(ITypeInfo *iface, FUNCDESC *pFuncDesc) +{ + CHECK_EXPECT(ReleaseFuncDesc); + HeapFree(GetProcessHeap(), 0, pFuncDesc); +} + +static void WINAPI TypeInfo_ReleaseVarDesc(ITypeInfo *iface, VARDESC *pVarDesc) +{ + CHECK_EXPECT(ReleaseVarDesc); + HeapFree(GetProcessHeap(), 0, pVarDesc); +} + +static const ITypeInfoVtbl TypeInfoVtbl = { + TypeInfo_QueryInterface, + TypeInfo_AddRef, + TypeInfo_Release, + TypeInfo_GetTypeAttr, + TypeInfo_GetTypeComp, + TypeInfo_GetFuncDesc, + TypeInfo_GetVarDesc, + TypeInfo_GetNames, + TypeInfo_GetRefTypeOfImplType, + TypeInfo_GetImplTypeFlags, + TypeInfo_GetIDsOfNames, + TypeInfo_Invoke, + TypeInfo_GetDocumentation, + TypeInfo_GetDllEntry, + TypeInfo_GetRefTypeInfo, + TypeInfo_AddressOfMember, + TypeInfo_CreateInstance, + TypeInfo_GetMops, + TypeInfo_GetContainingTypeLib, + TypeInfo_ReleaseTypeAttr, + TypeInfo_ReleaseFuncDesc, + TypeInfo_ReleaseVarDesc +}; + +static ITypeInfo TypeInfo = { &TypeInfoVtbl }; + static BOOL DispatchEx_available = FALSE; static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv) { @@ -274,8 +608,12 @@ static HRESULT WINAPI DispatchEx_GetTypeInfoCount(IDispatchEx *iface, UINT *pcti
static HRESULT WINAPI DispatchEx_GetTypeInfo(IDispatchEx *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo) { - ok(0, "unexpected call\n"); - return E_NOTIMPL; + CHECK_EXPECT(GetTypeInfo); + ok(iTInfo == 0, "unexpected iTInfo %u.\n", iTInfo); + ok(lcid == LOCALE_USER_DEFAULT, "unexpected lcid %u\n", lcid); + + *ppTInfo = &TypeInfo; + return S_OK; }
static BSTR Dispatch_expected_name; @@ -2316,6 +2654,7 @@ static void test_IScriptControl_get_Modules(void) LONG idx1_0[] = { 0, 1 }; LONG idx1_1[] = { 1, 1 };
+ IScriptProcedureCollection *procs; IEnumVARIANT *enumvar, *enumvar2; IScriptModuleCollection *mods; VARIANT var, vars[3]; @@ -2602,6 +2941,8 @@ static void test_IScriptControl_get_Modules(void) ok(hr == E_FAIL, "IScriptModule_get_Name returned: 0x%08x.\n", hr); hr = IScriptModule_get_CodeObject(mod, &disp); ok(hr == E_FAIL, "IScriptModule_get_CodeObject returned: 0x%08x.\n", hr); + hr = IScriptModule_get_Procedures(mod, &procs); + ok(hr == E_FAIL, "IScriptModule_get_Procedures returned: 0x%08x.\n", hr); str = SysAllocString(L"function closed() { }\n"); hr = IScriptModule_AddCode(mod, str); ok(hr == E_FAIL, "IScriptModule_AddCode failed: 0x%08x.\n", hr); @@ -2949,6 +3290,266 @@ static void test_IScriptControl_get_CodeObject(void) } }
+static void test_IScriptControl_get_Procedures(void) +{ + IScriptProcedureCollection *procs, *procs2; + IScriptProcedure *proc; + IScriptControl *sc; + VARIANT var; + LONG count; + HRESULT hr; + BSTR str; + UINT i; + + hr = CoCreateInstance(&CLSID_ScriptControl, NULL, CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, + &IID_IScriptControl, (void**)&sc); + ok(hr == S_OK, "Failed to create IScriptControl interface: 0x%08x.\n", hr); + + hr = IScriptControl_get_Procedures(sc, &procs); + ok(hr == E_FAIL, "IScriptControl_get_Procedures returned: 0x%08x.\n", hr); + + str = SysAllocString(L"jscript"); + hr = IScriptControl_put_Language(sc, str); + ok(hr == S_OK, "IScriptControl_put_Language failed: 0x%08x.\n", hr); + SysFreeString(str); + + hr = IScriptControl_get_Procedures(sc, &procs); + ok(hr == S_OK, "IScriptControl_get_Procedures failed: 0x%08x.\n", hr); + + hr = IScriptProcedureCollection_get_Count(procs, NULL); + todo_wine ok(hr == E_POINTER, "IScriptProcedureCollection_get_Count returned: 0x%08x.\n", hr); + hr = IScriptProcedureCollection_get_Count(procs, &count); + todo_wine ok(hr == S_OK, "IScriptProcedureCollection_get_Count failed: 0x%08x.\n", hr); + + V_VT(&var) = VT_I4; + V_I4(&var) = -1; + hr = IScriptProcedureCollection_get_Item(procs, var, NULL); + todo_wine ok(hr == E_POINTER, "IScriptProcedureCollection_get_Item returned: 0x%08x.\n", hr); + hr = IScriptProcedureCollection_get_Item(procs, var, &proc); + todo_wine ok(hr == 0x800a0009, "IScriptProcedureCollection_get_Item returned: 0x%08x.\n", hr); + + str = SysAllocString(L"" + "function add(a, b) { return a + b; }\n" + "function nop(a) { }\n" + "function muladd(a, b, c) { return a * b + c; }\n" + ); + hr = IScriptControl_AddCode(sc, str); + ok(hr == S_OK, "IScriptControl_AddCode failed: 0x%08x.\n", hr); + todo_wine CHECK_ERROR(sc, 0); + SysFreeString(str); + + hr = IScriptProcedureCollection_get_Count(procs, &count); + todo_wine ok(hr == S_OK, "IScriptProcedureCollection_get_Count failed: 0x%08x.\n", hr); + + V_VT(&var) = VT_I4; + V_I4(&var) = 1; + IScriptProcedureCollection_AddRef(procs); + i = IScriptProcedureCollection_Release(procs); + hr = IScriptProcedureCollection_get_Item(procs, var, &proc); + todo_wine ok(hr == S_OK, "IScriptProcedureCollection_get_Item failed: 0x%08x.\n", hr); + IScriptProcedureCollection_AddRef(procs); + ok(i == IScriptProcedureCollection_Release(procs), + "IScriptProcedureCollection_get_Item should not have added a ref to the collection.\n"); + if (hr == S_OK) IScriptProcedure_Release(proc); + + V_VT(&var) = VT_BSTR; + V_BSTR(&var) = SysAllocString(L"Nop"); + hr = IScriptProcedureCollection_get_Item(procs, var, &proc); + todo_wine ok(hr == S_OK, "IScriptProcedureCollection_get_Item failed: 0x%08x.\n", hr); + ok(V_VT(&var) == VT_BSTR, "var type not BSTR, got %d.\n", V_VT(&var)); + VariantClear(&var); + if (hr == S_OK) IScriptProcedure_Release(proc); + + V_VT(&var) = VT_R8; + V_R8(&var) = 3.0; + hr = IScriptProcedureCollection_get_Item(procs, var, &proc); + todo_wine ok(hr == S_OK, "IScriptProcedureCollection_get_Item failed: 0x%08x.\n", hr); + if (hr == S_OK) IScriptProcedure_Release(proc); + + IScriptProcedureCollection_Release(procs); + IScriptControl_Release(sc); + + if (have_custom_engine) + { + hr = CoCreateInstance(&CLSID_ScriptControl, NULL, CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, + &IID_IScriptControl, (void**)&sc); + ok(hr == S_OK, "Failed to create IScriptControl interface: 0x%08x.\n", hr); + + SET_EXPECT(CreateInstance); + SET_EXPECT(SetInterfaceSafetyOptions); + SET_EXPECT(SetScriptSite); + SET_EXPECT(QI_IActiveScriptParse); + SET_EXPECT(InitNew); + + str = SysAllocString(L"testscript"); + hr = IScriptControl_put_Language(sc, str); + ok(hr == S_OK, "IScriptControl_put_Language failed: 0x%08x.\n", hr); + SysFreeString(str); + + CHECK_CALLED(CreateInstance); + CHECK_CALLED(SetInterfaceSafetyOptions); + CHECK_CALLED(SetScriptSite); + CHECK_CALLED(QI_IActiveScriptParse); + CHECK_CALLED(InitNew); + + hr = IScriptControl_get_Procedures(sc, &procs); + ok(hr == S_OK, "IScriptControl_get_Procedures failed: 0x%08x.\n", hr); + hr = IScriptControl_get_Procedures(sc, &procs2); + ok(hr == S_OK, "IScriptControl_get_Procedures failed: 0x%08x.\n", hr); + ok(procs == procs2, "Procedure collections are not the same (%p vs %p).\n", procs, procs2); + IScriptProcedureCollection_Release(procs2); + + GetScriptDispatch_expected_name = NULL; + SET_EXPECT(SetScriptState_STARTED); + SET_EXPECT(GetScriptDispatch); + SET_EXPECT(GetTypeInfo); + SET_EXPECT(GetTypeAttr); + SET_EXPECT(ReleaseTypeAttr); + TypeInfo_GetTypeAttr_cFuncs = 1337; + hr = IScriptProcedureCollection_get_Count(procs, &count); + todo_wine ok(hr == S_OK, "IScriptProcedureCollection_get_Count failed: 0x%08x.\n", hr); + todo_wine CHECK_CALLED(SetScriptState_STARTED); + todo_wine CHECK_CALLED(GetScriptDispatch); + todo_wine CHECK_CALLED(GetTypeInfo); + todo_wine CHECK_CALLED(GetTypeAttr); + todo_wine CHECK_CALLED(ReleaseTypeAttr); + TypeInfo_GetTypeAttr_cFuncs = ARRAY_SIZE(custom_engine_funcs); + count = 0; + hr = IScriptProcedureCollection_get_Count(procs, &count); + todo_wine ok(hr == S_OK, "IScriptProcedureCollection_get_Count failed: 0x%08x.\n", hr); + todo_wine ok(count == 1337, "count is not 1337, got %d.\n", count); + + /* Reload the collection to update the cached function count */ + IScriptProcedureCollection_Release(procs); + hr = IScriptControl_get_Procedures(sc, &procs); + ok(hr == S_OK, "IScriptControl_get_Procedures failed: 0x%08x.\n", hr); + count = 0; + SET_EXPECT(GetTypeAttr); + SET_EXPECT(ReleaseTypeAttr); + hr = IScriptProcedureCollection_get_Count(procs, &count); + todo_wine ok(hr == S_OK, "IScriptProcedureCollection_get_Count failed: 0x%08x.\n", hr); + todo_wine ok(count == ARRAY_SIZE(custom_engine_funcs), "count is not %u, got %d.\n", TypeInfo_GetTypeAttr_cFuncs, count); + todo_wine CHECK_CALLED(GetTypeAttr); + todo_wine CHECK_CALLED(ReleaseTypeAttr); + + /* Adding code reloads the typeinfo the next time */ + SET_EXPECT(SetScriptState_STARTED); /* FIXME: remove when Wine is fixed */ + SET_EXPECT(ParseScriptText); + parse_item_name = NULL; + parse_flags = SCRIPTTEXT_ISVISIBLE; + str = SysAllocString(L" "); + hr = IScriptControl_AddCode(sc, str); + ok(hr == S_OK, "IScriptControl_AddCode failed: 0x%08x.\n", hr); + SysFreeString(str); + todo_wine CHECK_ERROR(sc, 0); + CHECK_CALLED(ParseScriptText); + + GetScriptDispatch_expected_name = NULL; + SET_EXPECT(GetScriptDispatch); + SET_EXPECT(GetTypeInfo); + SET_EXPECT(GetTypeAttr); + SET_EXPECT(ReleaseTypeAttr); + hr = IScriptProcedureCollection_get_Count(procs, &count); + todo_wine ok(hr == S_OK, "IScriptProcedureCollection_get_Count failed: 0x%08x.\n", hr); + todo_wine ok(count == ARRAY_SIZE(custom_engine_funcs), "count is not %u, got %d.\n", TypeInfo_GetTypeAttr_cFuncs, count); + todo_wine CHECK_CALLED(GetScriptDispatch); + todo_wine CHECK_CALLED(GetTypeInfo); + todo_wine CHECK_CALLED(GetTypeAttr); + todo_wine CHECK_CALLED(ReleaseTypeAttr); + + /* Try without ITypeComp interface */ + SET_EXPECT(QI_ITypeComp); + V_VT(&var) = VT_BSTR; + V_BSTR(&var) = SysAllocString(L"foobar"); + hr = IScriptProcedureCollection_get_Item(procs, var, &proc); + todo_wine ok(hr == E_NOINTERFACE, "IScriptProcedureCollection_get_Item returned: 0x%08x.\n", hr); + ok(V_VT(&var) == VT_BSTR, "var type not BSTR, got %d.\n", V_VT(&var)); + VariantClear(&var); + todo_wine CHECK_CALLED(QI_ITypeComp); + + /* Make ITypeComp available */ + TypeComp_available = TRUE; + SET_EXPECT(QI_ITypeComp); + SET_EXPECT(Bind); + V_VT(&var) = VT_BSTR; + V_BSTR(&var) = SysAllocString(L"type_mismatch"); + hr = IScriptProcedureCollection_get_Item(procs, var, &proc); + todo_wine ok(hr == TYPE_E_TYPEMISMATCH, "IScriptProcedureCollection_get_Item returned: 0x%08x.\n", hr); + VariantClear(&var); + todo_wine CHECK_CALLED(QI_ITypeComp); + todo_wine CHECK_CALLED(Bind); + TypeComp_available = FALSE; + + SET_EXPECT(Bind); + V_VT(&var) = VT_BSTR; + V_BSTR(&var) = SysAllocString(L"not_found"); + hr = IScriptProcedureCollection_get_Item(procs, var, &proc); + todo_wine ok(hr == CTL_E_ILLEGALFUNCTIONCALL, "IScriptProcedureCollection_get_Item failed: 0x%08x.\n", hr); + VariantClear(&var); + todo_wine CHECK_CALLED(Bind); + + SET_EXPECT(Bind); + SET_EXPECT(ReleaseVarDesc); + V_VT(&var) = VT_BSTR; + V_BSTR(&var) = SysAllocString(L"variable"); + hr = IScriptProcedureCollection_get_Item(procs, var, &proc); + todo_wine ok(hr == CTL_E_ILLEGALFUNCTIONCALL, "IScriptProcedureCollection_get_Item failed: 0x%08x.\n", hr); + VariantClear(&var); + todo_wine CHECK_CALLED(Bind); + todo_wine CHECK_CALLED(ReleaseVarDesc); + + /* Index 0 and below are invalid (doesn't even call GetFuncDesc) */ + V_VT(&var) = VT_I4; + V_I4(&var) = 0; + hr = IScriptProcedureCollection_get_Item(procs, var, &proc); + todo_wine ok(hr == 0x800a0009, "IScriptProcedureCollection_get_Item returned: 0x%08x.\n", hr); + V_I4(&var) = -1; + hr = IScriptProcedureCollection_get_Item(procs, var, &proc); + todo_wine ok(hr == 0x800a0009, "IScriptProcedureCollection_get_Item returned: 0x%08x.\n", hr); + SET_EXPECT(GetFuncDesc); + V_I4(&var) = 1337; + hr = IScriptProcedureCollection_get_Item(procs, var, &proc); + todo_wine ok(hr == E_INVALIDARG, "IScriptProcedureCollection_get_Item returned: 0x%08x.\n", hr); + todo_wine CHECK_CALLED(GetFuncDesc); + + for (i = 0; i < ARRAY_SIZE(custom_engine_funcs); i++) + { + /* Querying by index still goes through the Bind process */ + SET_EXPECT(GetFuncDesc); + SET_EXPECT(GetNames); + SET_EXPECT(ReleaseFuncDesc); + V_VT(&var) = VT_R4; + V_R4(&var) = i + 1; + hr = IScriptProcedureCollection_get_Item(procs, var, &proc); + todo_wine ok(hr == S_OK, "get_Item for index %u failed: 0x%08x.\n", i, hr); + todo_wine CHECK_CALLED(GetFuncDesc); + todo_wine CHECK_CALLED(GetNames); + todo_wine CHECK_CALLED(ReleaseFuncDesc); + if (hr == S_OK) IScriptProcedure_Release(proc); + + V_VT(&var) = VT_BSTR; + V_BSTR(&var) = SysAllocString(custom_engine_funcs[i].name); + SET_EXPECT(Bind); + SET_EXPECT(GetNames); + SET_EXPECT(ReleaseFuncDesc); + hr = IScriptProcedureCollection_get_Item(procs, var, &proc); + todo_wine ok(hr == S_OK, "get_Item for %s failed: 0x%08x.\n", wine_dbgstr_w(custom_engine_funcs[i].name), hr); + VariantClear(&var); + todo_wine CHECK_CALLED(Bind); + todo_wine CHECK_CALLED(GetNames); + todo_wine CHECK_CALLED(ReleaseFuncDesc); + if (hr == S_OK) IScriptProcedure_Release(proc); + } + + IScriptProcedureCollection_Release(procs); + IActiveScriptSite_Release(site); + + SET_EXPECT(Close); + IScriptControl_Release(sc); + CHECK_CALLED(Close); + } +} + START_TEST(msscript) { IUnknown *unk; @@ -2988,6 +3589,7 @@ START_TEST(msscript) test_IScriptControl_Run(); test_IScriptControl_get_Modules(); test_IScriptControl_get_CodeObject(); + test_IScriptControl_get_Procedures();
init_registry(FALSE);
hI Gabriel,
On 10.08.2020 16:57, Gabriel Ivăncescu wrote:
/* Adding code reloads the typeinfo the next time */
SET_EXPECT(SetScriptState_STARTED); /* FIXME: remove when Wine is fixed */
This still needs to be paired CHECK_CALLED, you could even express todo_wine with:
todo_wine CHECK_NOT_CALLED(...);
(and you can remove both SET_EXPECT and CHECK_CALLED once Wine is fixed).
Thanks,
Jacek
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/msscript.ocx/msscript.c | 48 ++++++++++++++++++++++++++++-- dlls/msscript.ocx/tests/msscript.c | 38 ++++++++++++----------- 2 files changed, 66 insertions(+), 20 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index e986014..4c737e2 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -83,6 +83,7 @@ typedef struct { BSTR name; ScriptHost *host; IDispatch *script_dispatch; + ITypeInfo *script_typeinfo;
ScriptProcedureCollection *procedures; } ScriptModule; @@ -91,6 +92,7 @@ struct ScriptProcedureCollection { IScriptProcedureCollection IScriptProcedureCollection_iface; LONG ref;
+ LONG count; ScriptModule *module; };
@@ -258,6 +260,23 @@ static HRESULT get_script_dispatch(ScriptModule *module, IDispatch **disp) return S_OK; }
+static HRESULT get_script_typeinfo(ScriptModule *module, ITypeInfo **typeinfo) +{ + IDispatch *disp; + HRESULT hr; + + if (!module->script_typeinfo) + { + hr = get_script_dispatch(module, &disp); + if (FAILED(hr)) return hr; + + hr = IDispatch_GetTypeInfo(disp, 0, LOCALE_USER_DEFAULT, &module->script_typeinfo); + if (FAILED(hr)) return hr; + } + *typeinfo = module->script_typeinfo; + return S_OK; +} + static HRESULT set_script_state(ScriptHost *host, SCRIPTSTATE state) { HRESULT hr; @@ -820,10 +839,32 @@ static HRESULT WINAPI ScriptProcedureCollection_get_Item(IScriptProcedureCollect static HRESULT WINAPI ScriptProcedureCollection_get_Count(IScriptProcedureCollection *iface, LONG *plCount) { ScriptProcedureCollection *This = impl_from_IScriptProcedureCollection(iface); + TYPEATTR *attr; + ITypeInfo *ti; + HRESULT hr;
- FIXME("(%p)->(%p)\n", This, plCount); + TRACE("(%p)->(%p)\n", This, plCount);
- return E_NOTIMPL; + if (!plCount) return E_POINTER; + if (!This->module->host) return E_FAIL; + + hr = start_script(This->module->host); + if (FAILED(hr)) return hr; + + if (This->count == -1) + { + hr = get_script_typeinfo(This->module, &ti); + if (FAILED(hr)) return hr; + + hr = ITypeInfo_GetTypeAttr(ti, &attr); + if (FAILED(hr)) return hr; + + This->count = attr->cFuncs; + ITypeInfo_ReleaseTypeAttr(ti, attr); + } + + *plCount = This->count; + return S_OK; }
static const IScriptProcedureCollectionVtbl ScriptProcedureCollectionVtbl = { @@ -910,6 +951,8 @@ static ULONG WINAPI ScriptModule_Release(IScriptModule *iface) SysFreeString(This->name); if (This->script_dispatch) IDispatch_Release(This->script_dispatch); + if (This->script_typeinfo) + ITypeInfo_Release(This->script_typeinfo); heap_free(This); }
@@ -1029,6 +1072,7 @@ static HRESULT WINAPI ScriptModule_get_Procedures(IScriptModule *iface, IScriptP
procs->IScriptProcedureCollection_iface.lpVtbl = &ScriptProcedureCollectionVtbl; procs->ref = 1; + procs->count = -1; procs->module = This; This->procedures = procs; IScriptModule_AddRef(&This->IScriptModule_iface); diff --git a/dlls/msscript.ocx/tests/msscript.c b/dlls/msscript.ocx/tests/msscript.c index a48a749..9d2e78d 100644 --- a/dlls/msscript.ocx/tests/msscript.c +++ b/dlls/msscript.ocx/tests/msscript.c @@ -3317,9 +3317,10 @@ static void test_IScriptControl_get_Procedures(void) ok(hr == S_OK, "IScriptControl_get_Procedures failed: 0x%08x.\n", hr);
hr = IScriptProcedureCollection_get_Count(procs, NULL); - todo_wine ok(hr == E_POINTER, "IScriptProcedureCollection_get_Count returned: 0x%08x.\n", hr); + ok(hr == E_POINTER, "IScriptProcedureCollection_get_Count returned: 0x%08x.\n", hr); hr = IScriptProcedureCollection_get_Count(procs, &count); - todo_wine ok(hr == S_OK, "IScriptProcedureCollection_get_Count failed: 0x%08x.\n", hr); + ok(hr == S_OK, "IScriptProcedureCollection_get_Count failed: 0x%08x.\n", hr); + ok(count == 0, "count is not 0, got %d.\n", count);
V_VT(&var) = VT_I4; V_I4(&var) = -1; @@ -3339,7 +3340,8 @@ static void test_IScriptControl_get_Procedures(void) SysFreeString(str);
hr = IScriptProcedureCollection_get_Count(procs, &count); - todo_wine ok(hr == S_OK, "IScriptProcedureCollection_get_Count failed: 0x%08x.\n", hr); + ok(hr == S_OK, "IScriptProcedureCollection_get_Count failed: 0x%08x.\n", hr); + todo_wine ok(count == 3, "count is not 3, got %d.\n", count);
V_VT(&var) = VT_I4; V_I4(&var) = 1; @@ -3407,17 +3409,18 @@ static void test_IScriptControl_get_Procedures(void) SET_EXPECT(ReleaseTypeAttr); TypeInfo_GetTypeAttr_cFuncs = 1337; hr = IScriptProcedureCollection_get_Count(procs, &count); - todo_wine ok(hr == S_OK, "IScriptProcedureCollection_get_Count failed: 0x%08x.\n", hr); - todo_wine CHECK_CALLED(SetScriptState_STARTED); - todo_wine CHECK_CALLED(GetScriptDispatch); - todo_wine CHECK_CALLED(GetTypeInfo); - todo_wine CHECK_CALLED(GetTypeAttr); - todo_wine CHECK_CALLED(ReleaseTypeAttr); + ok(hr == S_OK, "IScriptProcedureCollection_get_Count failed: 0x%08x.\n", hr); + ok(count == 1337, "count is not 1337, got %d.\n", count); + CHECK_CALLED(SetScriptState_STARTED); + CHECK_CALLED(GetScriptDispatch); + CHECK_CALLED(GetTypeInfo); + CHECK_CALLED(GetTypeAttr); + CHECK_CALLED(ReleaseTypeAttr); TypeInfo_GetTypeAttr_cFuncs = ARRAY_SIZE(custom_engine_funcs); count = 0; hr = IScriptProcedureCollection_get_Count(procs, &count); - todo_wine ok(hr == S_OK, "IScriptProcedureCollection_get_Count failed: 0x%08x.\n", hr); - todo_wine ok(count == 1337, "count is not 1337, got %d.\n", count); + ok(hr == S_OK, "IScriptProcedureCollection_get_Count failed: 0x%08x.\n", hr); + ok(count == 1337, "count is not 1337, got %d.\n", count);
/* Reload the collection to update the cached function count */ IScriptProcedureCollection_Release(procs); @@ -3427,13 +3430,12 @@ static void test_IScriptControl_get_Procedures(void) SET_EXPECT(GetTypeAttr); SET_EXPECT(ReleaseTypeAttr); hr = IScriptProcedureCollection_get_Count(procs, &count); - todo_wine ok(hr == S_OK, "IScriptProcedureCollection_get_Count failed: 0x%08x.\n", hr); - todo_wine ok(count == ARRAY_SIZE(custom_engine_funcs), "count is not %u, got %d.\n", TypeInfo_GetTypeAttr_cFuncs, count); - todo_wine CHECK_CALLED(GetTypeAttr); - todo_wine CHECK_CALLED(ReleaseTypeAttr); + ok(hr == S_OK, "IScriptProcedureCollection_get_Count failed: 0x%08x.\n", hr); + ok(count == ARRAY_SIZE(custom_engine_funcs), "count is not %u, got %d.\n", TypeInfo_GetTypeAttr_cFuncs, count); + CHECK_CALLED(GetTypeAttr); + CHECK_CALLED(ReleaseTypeAttr);
/* Adding code reloads the typeinfo the next time */ - SET_EXPECT(SetScriptState_STARTED); /* FIXME: remove when Wine is fixed */ SET_EXPECT(ParseScriptText); parse_item_name = NULL; parse_flags = SCRIPTTEXT_ISVISIBLE; @@ -3450,8 +3452,8 @@ static void test_IScriptControl_get_Procedures(void) SET_EXPECT(GetTypeAttr); SET_EXPECT(ReleaseTypeAttr); hr = IScriptProcedureCollection_get_Count(procs, &count); - todo_wine ok(hr == S_OK, "IScriptProcedureCollection_get_Count failed: 0x%08x.\n", hr); - todo_wine ok(count == ARRAY_SIZE(custom_engine_funcs), "count is not %u, got %d.\n", TypeInfo_GetTypeAttr_cFuncs, count); + ok(hr == S_OK, "IScriptProcedureCollection_get_Count failed: 0x%08x.\n", hr); + ok(count == ARRAY_SIZE(custom_engine_funcs), "count is not %u, got %d.\n", TypeInfo_GetTypeAttr_cFuncs, count); todo_wine CHECK_CALLED(GetScriptDispatch); todo_wine CHECK_CALLED(GetTypeInfo); todo_wine CHECK_CALLED(GetTypeAttr);
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/msscript.ocx/msscript.c | 23 +++++++++++++++++++---- dlls/msscript.ocx/tests/msscript.c | 10 +++++----- 2 files changed, 24 insertions(+), 9 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index 4c737e2..60b641f 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -277,6 +277,22 @@ static HRESULT get_script_typeinfo(ScriptModule *module, ITypeInfo **typeinfo) return S_OK; }
+static void uncache_module_objects(ScriptModule *module) +{ + if (module->script_dispatch) + { + IDispatch_Release(module->script_dispatch); + module->script_dispatch = NULL; + } + if (module->script_typeinfo) + { + ITypeInfo_Release(module->script_typeinfo); + module->script_typeinfo = NULL; + } + if (module->procedures) + module->procedures->count = -1; +} + static HRESULT set_script_state(ScriptHost *host, SCRIPTSTATE state) { HRESULT hr; @@ -339,6 +355,8 @@ static HRESULT parse_script_text(ScriptModule *module, BSTR script_text, DWORD f hr = start_script(module->host); if (FAILED(hr)) return hr;
+ uncache_module_objects(module); + hr = IActiveScriptParse_ParseScriptText(module->host->parse, script_text, module->name, NULL, NULL, 0, 1, flag, res, &excepinfo); /* FIXME: more error handling */ @@ -949,10 +967,7 @@ static ULONG WINAPI ScriptModule_Release(IScriptModule *iface) { detach_module(This); SysFreeString(This->name); - if (This->script_dispatch) - IDispatch_Release(This->script_dispatch); - if (This->script_typeinfo) - ITypeInfo_Release(This->script_typeinfo); + uncache_module_objects(This); heap_free(This); }
diff --git a/dlls/msscript.ocx/tests/msscript.c b/dlls/msscript.ocx/tests/msscript.c index 9d2e78d..dbdb00e 100644 --- a/dlls/msscript.ocx/tests/msscript.c +++ b/dlls/msscript.ocx/tests/msscript.c @@ -3341,7 +3341,7 @@ static void test_IScriptControl_get_Procedures(void)
hr = IScriptProcedureCollection_get_Count(procs, &count); ok(hr == S_OK, "IScriptProcedureCollection_get_Count failed: 0x%08x.\n", hr); - todo_wine ok(count == 3, "count is not 3, got %d.\n", count); + ok(count == 3, "count is not 3, got %d.\n", count);
V_VT(&var) = VT_I4; V_I4(&var) = 1; @@ -3454,10 +3454,10 @@ static void test_IScriptControl_get_Procedures(void) hr = IScriptProcedureCollection_get_Count(procs, &count); ok(hr == S_OK, "IScriptProcedureCollection_get_Count failed: 0x%08x.\n", hr); ok(count == ARRAY_SIZE(custom_engine_funcs), "count is not %u, got %d.\n", TypeInfo_GetTypeAttr_cFuncs, count); - todo_wine CHECK_CALLED(GetScriptDispatch); - todo_wine CHECK_CALLED(GetTypeInfo); - todo_wine CHECK_CALLED(GetTypeAttr); - todo_wine CHECK_CALLED(ReleaseTypeAttr); + CHECK_CALLED(GetScriptDispatch); + CHECK_CALLED(GetTypeInfo); + CHECK_CALLED(GetTypeAttr); + CHECK_CALLED(ReleaseTypeAttr);
/* Try without ITypeComp interface */ SET_EXPECT(QI_ITypeComp);
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/msscript.ocx/msscript.c | 266 ++++++++++++++++++++++++++++- dlls/msscript.ocx/tests/msscript.c | 64 +++---- 2 files changed, 296 insertions(+), 34 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index 60b641f..df173be 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -84,10 +84,18 @@ typedef struct { ScriptHost *host; IDispatch *script_dispatch; ITypeInfo *script_typeinfo; + ITypeComp *script_typecomp;
ScriptProcedureCollection *procedures; } ScriptModule;
+typedef struct { + IScriptProcedure IScriptProcedure_iface; + LONG ref; + + BSTR name; +} ScriptProcedure; + struct ScriptProcedureCollection { IScriptProcedureCollection IScriptProcedureCollection_iface; LONG ref; @@ -150,6 +158,7 @@ typedef enum tid_t { IScriptModuleCollection_tid, IScriptModule_tid, IScriptProcedureCollection_tid, + IScriptProcedure_tid, LAST_tid } tid_t;
@@ -161,6 +170,7 @@ static REFIID tid_ids[] = { &IID_IScriptModuleCollection, &IID_IScriptModule, &IID_IScriptProcedureCollection, + &IID_IScriptProcedure };
static HRESULT load_typelib(void) @@ -277,6 +287,19 @@ static HRESULT get_script_typeinfo(ScriptModule *module, ITypeInfo **typeinfo) return S_OK; }
+static HRESULT get_script_typecomp(ScriptModule *module, ITypeInfo *typeinfo, ITypeComp **typecomp) +{ + HRESULT hr; + + if (!module->script_typecomp) + { + hr = ITypeInfo_QueryInterface(typeinfo, &IID_ITypeComp, (void**)&module->script_typecomp); + if (FAILED(hr)) return hr; + } + *typecomp = module->script_typecomp; + return S_OK; +} + static void uncache_module_objects(ScriptModule *module) { if (module->script_dispatch) @@ -289,6 +312,11 @@ static void uncache_module_objects(ScriptModule *module) ITypeInfo_Release(module->script_typeinfo); module->script_typeinfo = NULL; } + if (module->script_typecomp) + { + ITypeComp_Release(module->script_typecomp); + module->script_typecomp = NULL; + } if (module->procedures) module->procedures->count = -1; } @@ -453,6 +481,11 @@ static inline ScriptControl *impl_from_IConnectionPointContainer(IConnectionPoin return CONTAINING_RECORD(iface, ScriptControl, IConnectionPointContainer_iface); }
+static inline ScriptProcedure *impl_from_IScriptProcedure(IScriptProcedure *iface) +{ + return CONTAINING_RECORD(iface, ScriptProcedure, IScriptProcedure_iface); +} + static inline ScriptProcedureCollection *impl_from_IScriptProcedureCollection(IScriptProcedureCollection *iface) { return CONTAINING_RECORD(iface, ScriptProcedureCollection, IScriptProcedureCollection_iface); @@ -728,6 +761,181 @@ static const IServiceProviderVtbl ServiceProviderVtbl = { ServiceProvider_QueryService };
+static HRESULT WINAPI ScriptProcedure_QueryInterface(IScriptProcedure *iface, REFIID riid, void **ppv) +{ + ScriptProcedure *This = impl_from_IScriptProcedure(iface); + + if (IsEqualGUID(&IID_IDispatch, riid) || IsEqualGUID(&IID_IUnknown, riid) || + IsEqualGUID(&IID_IScriptProcedure, riid)) + { + *ppv = &This->IScriptProcedure_iface; + } + else + { + WARN("unsupported interface: (%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); + *ppv = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; +} + +static ULONG WINAPI ScriptProcedure_AddRef(IScriptProcedure *iface) +{ + ScriptProcedure *This = impl_from_IScriptProcedure(iface); + LONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) ref=%d\n", This, ref); + + return ref; +} + +static ULONG WINAPI ScriptProcedure_Release(IScriptProcedure *iface) +{ + ScriptProcedure *This = impl_from_IScriptProcedure(iface); + LONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) ref=%d\n", This, ref); + + if (!ref) + { + SysFreeString(This->name); + heap_free(This); + } + return ref; +} + +static HRESULT WINAPI ScriptProcedure_GetTypeInfoCount(IScriptProcedure *iface, UINT *pctinfo) +{ + ScriptProcedure *This = impl_from_IScriptProcedure(iface); + + TRACE("(%p)->(%p)\n", This, pctinfo); + + *pctinfo = 1; + return S_OK; +} + +static HRESULT WINAPI ScriptProcedure_GetTypeInfo(IScriptProcedure *iface, UINT iTInfo, + LCID lcid, ITypeInfo **ppTInfo) +{ + ScriptProcedure *This = impl_from_IScriptProcedure(iface); + + TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo); + + return get_typeinfo(IScriptProcedure_tid, ppTInfo); +} + +static HRESULT WINAPI ScriptProcedure_GetIDsOfNames(IScriptProcedure *iface, REFIID riid, + LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) +{ + ScriptProcedure *This = impl_from_IScriptProcedure(iface); + ITypeInfo *typeinfo; + HRESULT hr; + + TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId); + + hr = get_typeinfo(IScriptProcedure_tid, &typeinfo); + if (SUCCEEDED(hr)) + { + hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId); + ITypeInfo_Release(typeinfo); + } + + return hr; +} + +static HRESULT WINAPI ScriptProcedure_Invoke(IScriptProcedure *iface, DISPID dispIdMember, + REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, + EXCEPINFO *pExcepInfo, UINT *puArgErr) +{ + ScriptProcedure *This = impl_from_IScriptProcedure(iface); + ITypeInfo *typeinfo; + HRESULT hr; + + TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid), + lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); + + hr = get_typeinfo(IScriptProcedure_tid, &typeinfo); + if(SUCCEEDED(hr)) + { + hr = ITypeInfo_Invoke(typeinfo, iface, dispIdMember, wFlags, + pDispParams, pVarResult, pExcepInfo, puArgErr); + ITypeInfo_Release(typeinfo); + } + + return hr; +} + +static HRESULT WINAPI ScriptProcedure_get_Name(IScriptProcedure *iface, BSTR *pbstrName) +{ + ScriptProcedure *This = impl_from_IScriptProcedure(iface); + + FIXME("(%p)->(%p)\n", This, pbstrName); + + return E_NOTIMPL; +} + +static HRESULT WINAPI ScriptProcedure_get_NumArgs(IScriptProcedure *iface, LONG *pcArgs) +{ + ScriptProcedure *This = impl_from_IScriptProcedure(iface); + + FIXME("(%p)->(%p)\n", This, pcArgs); + + return E_NOTIMPL; +} + +static HRESULT WINAPI ScriptProcedure_get_HasReturnValue(IScriptProcedure *iface, VARIANT_BOOL *pfHasReturnValue) +{ + ScriptProcedure *This = impl_from_IScriptProcedure(iface); + + FIXME("(%p)->(%p)\n", This, pfHasReturnValue); + + return E_NOTIMPL; +} + +static const IScriptProcedureVtbl ScriptProcedureVtbl = { + ScriptProcedure_QueryInterface, + ScriptProcedure_AddRef, + ScriptProcedure_Release, + ScriptProcedure_GetTypeInfoCount, + ScriptProcedure_GetTypeInfo, + ScriptProcedure_GetIDsOfNames, + ScriptProcedure_Invoke, + ScriptProcedure_get_Name, + ScriptProcedure_get_NumArgs, + ScriptProcedure_get_HasReturnValue +}; + +/* This function always releases the FUNCDESC passed in */ +static HRESULT get_script_procedure(ITypeInfo *typeinfo, FUNCDESC *desc, IScriptProcedure **procedure) +{ + ScriptProcedure *proc; + HRESULT hr; + BSTR str; + UINT len; + + hr = ITypeInfo_GetNames(typeinfo, desc->memid, &str, 1, &len); + if (FAILED(hr)) goto done; + + if (!(proc = heap_alloc(sizeof(*proc)))) + { + hr = E_OUTOFMEMORY; + SysFreeString(str); + goto done; + } + + proc->IScriptProcedure_iface.lpVtbl = &ScriptProcedureVtbl; + proc->ref = 1; + proc->name = str; + + *procedure = &proc->IScriptProcedure_iface; + +done: + ITypeInfo_ReleaseFuncDesc(typeinfo, desc); + return hr; +} + static HRESULT WINAPI ScriptProcedureCollection_QueryInterface(IScriptProcedureCollection *iface, REFIID riid, void **ppv) { ScriptProcedureCollection *This = impl_from_IScriptProcedureCollection(iface); @@ -848,10 +1056,64 @@ static HRESULT WINAPI ScriptProcedureCollection_get_Item(IScriptProcedureCollect IScriptProcedure **ppdispProcedure) { ScriptProcedureCollection *This = impl_from_IScriptProcedureCollection(iface); + ITypeInfo *typeinfo; + FUNCDESC *desc; + HRESULT hr;
- FIXME("(%p)->(%s %p)\n", This, wine_dbgstr_variant(&index), ppdispProcedure); + TRACE("(%p)->(%s %p)\n", This, wine_dbgstr_variant(&index), ppdispProcedure);
- return E_NOTIMPL; + if (!ppdispProcedure) return E_POINTER; + if (!This->module->host) return E_FAIL; + + hr = start_script(This->module->host); + if (FAILED(hr)) return hr; + + hr = get_script_typeinfo(This->module, &typeinfo); + if (FAILED(hr)) return hr; + + if (V_VT(&index) == VT_BSTR) + { + ITypeComp *comp; + BINDPTR bindptr; + DESCKIND kind; + ULONG hash; + + hash = LHashValOfNameSys(sizeof(void*) == 8 ? SYS_WIN64 : SYS_WIN32, LOCALE_USER_DEFAULT, V_BSTR(&index)); + + hr = get_script_typecomp(This->module, typeinfo, &comp); + if (FAILED(hr)) return hr; + + hr = ITypeComp_Bind(comp, V_BSTR(&index), hash, INVOKE_FUNC, &typeinfo, &kind, &bindptr); + if (FAILED(hr)) return hr; + + switch (kind) + { + case DESCKIND_FUNCDESC: + hr = get_script_procedure(typeinfo, bindptr.lpfuncdesc, ppdispProcedure); + ITypeInfo_Release(typeinfo); + return hr; + case DESCKIND_IMPLICITAPPOBJ: + case DESCKIND_VARDESC: + ITypeInfo_ReleaseVarDesc(typeinfo, bindptr.lpvardesc); + ITypeInfo_Release(typeinfo); + break; + case DESCKIND_TYPECOMP: + ITypeComp_Release(bindptr.lptcomp); + break; + default: + break; + } + return CTL_E_ILLEGALFUNCTIONCALL; + } + + hr = VariantChangeType(&index, &index, 0, VT_INT); + if (FAILED(hr)) return hr; + if (V_INT(&index) <= 0) return 0x800a0009; + + hr = ITypeInfo_GetFuncDesc(typeinfo, V_INT(&index) - 1, &desc); + if (FAILED(hr)) return hr; + + return get_script_procedure(typeinfo, desc, ppdispProcedure); }
static HRESULT WINAPI ScriptProcedureCollection_get_Count(IScriptProcedureCollection *iface, LONG *plCount) diff --git a/dlls/msscript.ocx/tests/msscript.c b/dlls/msscript.ocx/tests/msscript.c index dbdb00e..ed4d0f8 100644 --- a/dlls/msscript.ocx/tests/msscript.c +++ b/dlls/msscript.ocx/tests/msscript.c @@ -3325,9 +3325,9 @@ static void test_IScriptControl_get_Procedures(void) V_VT(&var) = VT_I4; V_I4(&var) = -1; hr = IScriptProcedureCollection_get_Item(procs, var, NULL); - todo_wine ok(hr == E_POINTER, "IScriptProcedureCollection_get_Item returned: 0x%08x.\n", hr); + ok(hr == E_POINTER, "IScriptProcedureCollection_get_Item returned: 0x%08x.\n", hr); hr = IScriptProcedureCollection_get_Item(procs, var, &proc); - todo_wine ok(hr == 0x800a0009, "IScriptProcedureCollection_get_Item returned: 0x%08x.\n", hr); + ok(hr == 0x800a0009, "IScriptProcedureCollection_get_Item returned: 0x%08x.\n", hr);
str = SysAllocString(L"" "function add(a, b) { return a + b; }\n" @@ -3348,25 +3348,25 @@ static void test_IScriptControl_get_Procedures(void) IScriptProcedureCollection_AddRef(procs); i = IScriptProcedureCollection_Release(procs); hr = IScriptProcedureCollection_get_Item(procs, var, &proc); - todo_wine ok(hr == S_OK, "IScriptProcedureCollection_get_Item failed: 0x%08x.\n", hr); + ok(hr == S_OK, "IScriptProcedureCollection_get_Item failed: 0x%08x.\n", hr); IScriptProcedureCollection_AddRef(procs); ok(i == IScriptProcedureCollection_Release(procs), "IScriptProcedureCollection_get_Item should not have added a ref to the collection.\n"); - if (hr == S_OK) IScriptProcedure_Release(proc); + IScriptProcedure_Release(proc);
V_VT(&var) = VT_BSTR; V_BSTR(&var) = SysAllocString(L"Nop"); hr = IScriptProcedureCollection_get_Item(procs, var, &proc); - todo_wine ok(hr == S_OK, "IScriptProcedureCollection_get_Item failed: 0x%08x.\n", hr); + ok(hr == S_OK, "IScriptProcedureCollection_get_Item failed: 0x%08x.\n", hr); ok(V_VT(&var) == VT_BSTR, "var type not BSTR, got %d.\n", V_VT(&var)); VariantClear(&var); - if (hr == S_OK) IScriptProcedure_Release(proc); + IScriptProcedure_Release(proc);
V_VT(&var) = VT_R8; V_R8(&var) = 3.0; hr = IScriptProcedureCollection_get_Item(procs, var, &proc); - todo_wine ok(hr == S_OK, "IScriptProcedureCollection_get_Item failed: 0x%08x.\n", hr); - if (hr == S_OK) IScriptProcedure_Release(proc); + ok(hr == S_OK, "IScriptProcedureCollection_get_Item failed: 0x%08x.\n", hr); + IScriptProcedure_Release(proc);
IScriptProcedureCollection_Release(procs); IScriptControl_Release(sc); @@ -3464,10 +3464,10 @@ static void test_IScriptControl_get_Procedures(void) V_VT(&var) = VT_BSTR; V_BSTR(&var) = SysAllocString(L"foobar"); hr = IScriptProcedureCollection_get_Item(procs, var, &proc); - todo_wine ok(hr == E_NOINTERFACE, "IScriptProcedureCollection_get_Item returned: 0x%08x.\n", hr); + ok(hr == E_NOINTERFACE, "IScriptProcedureCollection_get_Item returned: 0x%08x.\n", hr); ok(V_VT(&var) == VT_BSTR, "var type not BSTR, got %d.\n", V_VT(&var)); VariantClear(&var); - todo_wine CHECK_CALLED(QI_ITypeComp); + CHECK_CALLED(QI_ITypeComp);
/* Make ITypeComp available */ TypeComp_available = TRUE; @@ -3476,43 +3476,43 @@ static void test_IScriptControl_get_Procedures(void) V_VT(&var) = VT_BSTR; V_BSTR(&var) = SysAllocString(L"type_mismatch"); hr = IScriptProcedureCollection_get_Item(procs, var, &proc); - todo_wine ok(hr == TYPE_E_TYPEMISMATCH, "IScriptProcedureCollection_get_Item returned: 0x%08x.\n", hr); + ok(hr == TYPE_E_TYPEMISMATCH, "IScriptProcedureCollection_get_Item returned: 0x%08x.\n", hr); VariantClear(&var); - todo_wine CHECK_CALLED(QI_ITypeComp); - todo_wine CHECK_CALLED(Bind); + CHECK_CALLED(QI_ITypeComp); + CHECK_CALLED(Bind); TypeComp_available = FALSE;
SET_EXPECT(Bind); V_VT(&var) = VT_BSTR; V_BSTR(&var) = SysAllocString(L"not_found"); hr = IScriptProcedureCollection_get_Item(procs, var, &proc); - todo_wine ok(hr == CTL_E_ILLEGALFUNCTIONCALL, "IScriptProcedureCollection_get_Item failed: 0x%08x.\n", hr); + ok(hr == CTL_E_ILLEGALFUNCTIONCALL, "IScriptProcedureCollection_get_Item failed: 0x%08x.\n", hr); VariantClear(&var); - todo_wine CHECK_CALLED(Bind); + CHECK_CALLED(Bind);
SET_EXPECT(Bind); SET_EXPECT(ReleaseVarDesc); V_VT(&var) = VT_BSTR; V_BSTR(&var) = SysAllocString(L"variable"); hr = IScriptProcedureCollection_get_Item(procs, var, &proc); - todo_wine ok(hr == CTL_E_ILLEGALFUNCTIONCALL, "IScriptProcedureCollection_get_Item failed: 0x%08x.\n", hr); + ok(hr == CTL_E_ILLEGALFUNCTIONCALL, "IScriptProcedureCollection_get_Item failed: 0x%08x.\n", hr); VariantClear(&var); - todo_wine CHECK_CALLED(Bind); - todo_wine CHECK_CALLED(ReleaseVarDesc); + CHECK_CALLED(Bind); + CHECK_CALLED(ReleaseVarDesc);
/* Index 0 and below are invalid (doesn't even call GetFuncDesc) */ V_VT(&var) = VT_I4; V_I4(&var) = 0; hr = IScriptProcedureCollection_get_Item(procs, var, &proc); - todo_wine ok(hr == 0x800a0009, "IScriptProcedureCollection_get_Item returned: 0x%08x.\n", hr); + ok(hr == 0x800a0009, "IScriptProcedureCollection_get_Item returned: 0x%08x.\n", hr); V_I4(&var) = -1; hr = IScriptProcedureCollection_get_Item(procs, var, &proc); - todo_wine ok(hr == 0x800a0009, "IScriptProcedureCollection_get_Item returned: 0x%08x.\n", hr); + ok(hr == 0x800a0009, "IScriptProcedureCollection_get_Item returned: 0x%08x.\n", hr); SET_EXPECT(GetFuncDesc); V_I4(&var) = 1337; hr = IScriptProcedureCollection_get_Item(procs, var, &proc); - todo_wine ok(hr == E_INVALIDARG, "IScriptProcedureCollection_get_Item returned: 0x%08x.\n", hr); - todo_wine CHECK_CALLED(GetFuncDesc); + ok(hr == E_INVALIDARG, "IScriptProcedureCollection_get_Item returned: 0x%08x.\n", hr); + CHECK_CALLED(GetFuncDesc);
for (i = 0; i < ARRAY_SIZE(custom_engine_funcs); i++) { @@ -3523,11 +3523,11 @@ static void test_IScriptControl_get_Procedures(void) V_VT(&var) = VT_R4; V_R4(&var) = i + 1; hr = IScriptProcedureCollection_get_Item(procs, var, &proc); - todo_wine ok(hr == S_OK, "get_Item for index %u failed: 0x%08x.\n", i, hr); - todo_wine CHECK_CALLED(GetFuncDesc); - todo_wine CHECK_CALLED(GetNames); - todo_wine CHECK_CALLED(ReleaseFuncDesc); - if (hr == S_OK) IScriptProcedure_Release(proc); + ok(hr == S_OK, "get_Item for index %u failed: 0x%08x.\n", i, hr); + CHECK_CALLED(GetFuncDesc); + CHECK_CALLED(GetNames); + CHECK_CALLED(ReleaseFuncDesc); + IScriptProcedure_Release(proc);
V_VT(&var) = VT_BSTR; V_BSTR(&var) = SysAllocString(custom_engine_funcs[i].name); @@ -3535,12 +3535,12 @@ static void test_IScriptControl_get_Procedures(void) SET_EXPECT(GetNames); SET_EXPECT(ReleaseFuncDesc); hr = IScriptProcedureCollection_get_Item(procs, var, &proc); - todo_wine ok(hr == S_OK, "get_Item for %s failed: 0x%08x.\n", wine_dbgstr_w(custom_engine_funcs[i].name), hr); + ok(hr == S_OK, "get_Item for %s failed: 0x%08x.\n", wine_dbgstr_w(custom_engine_funcs[i].name), hr); VariantClear(&var); - todo_wine CHECK_CALLED(Bind); - todo_wine CHECK_CALLED(GetNames); - todo_wine CHECK_CALLED(ReleaseFuncDesc); - if (hr == S_OK) IScriptProcedure_Release(proc); + CHECK_CALLED(Bind); + CHECK_CALLED(GetNames); + CHECK_CALLED(ReleaseFuncDesc); + IScriptProcedure_Release(proc); }
IScriptProcedureCollection_Release(procs);
Hi Gabriel,
On 10.08.2020 16:58, Gabriel Ivăncescu wrote:
case DESCKIND_TYPECOMP:
ITypeComp_Release(bindptr.lptcomp);
break;
default:
break;
}
return CTL_E_ILLEGALFUNCTIONCALL;
You leak typeinfo here.
Thanks,
Jacek
On 11/08/2020 14:51, Jacek Caban wrote:
Hi Gabriel,
On 10.08.2020 16:58, Gabriel Ivăncescu wrote:
case DESCKIND_TYPECOMP:
ITypeComp_Release(bindptr.lptcomp);
break;
default:
break;
}
return CTL_E_ILLEGALFUNCTIONCALL;
You leak typeinfo here.
Thanks,
Jacek
Hi Jacek,
Sorry, I'm not familiar with the exact details. Does a typeinfo always get returned? Because MSDN states:
`If a FUNCDESC or VARDESC was returned, then ppTInfo points to a pointer to the type description that contains the item to which it is bound.`
Additionally also for DESCKIND_IMPLICITAPPOBJ in the Remarks. But not for other returns.
Should I move the release of the typeinfo outside the switch, and check it for NULL instead before releasing, or is that NULL check not needed?
Thanks, Gabriel
On 11.08.2020 17:38, Gabriel Ivăncescu wrote:
On 11/08/2020 14:51, Jacek Caban wrote:
Hi Gabriel,
On 10.08.2020 16:58, Gabriel Ivăncescu wrote:
+ case DESCKIND_TYPECOMP: + ITypeComp_Release(bindptr.lptcomp); + break; + default: + break; + } + return CTL_E_ILLEGALFUNCTIONCALL;
You leak typeinfo here.
Thanks,
Jacek
Hi Jacek,
Sorry, I'm not familiar with the exact details. Does a typeinfo always get returned? Because MSDN states:
`If a FUNCDESC or VARDESC was returned, then ppTInfo points to a pointer to the type description that contains the item to which it is bound.`
Additionally also for DESCKIND_IMPLICITAPPOBJ in the Remarks. But not for other returns.
Should I move the release of the typeinfo outside the switch, and check it for NULL instead before releasing, or is that NULL check not needed?
I misinterpreted it, sorry. This part looks good.
Thanks,
Jacek
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com ---
Since we're computing the hash anyway for ITypeComp::Bind, a simple fixed hash table has been used to cache them much more efficiently than a linear lookup.
dlls/msscript.ocx/msscript.c | 59 ++++++++++++++++++++++++++++-- dlls/msscript.ocx/tests/msscript.c | 12 +++++- 2 files changed, 66 insertions(+), 5 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index df173be..ccdbba4 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -93,6 +93,9 @@ typedef struct { IScriptProcedure IScriptProcedure_iface; LONG ref;
+ ULONG hash; + struct list entry; + BSTR name; } ScriptProcedure;
@@ -102,6 +105,7 @@ struct ScriptProcedureCollection {
LONG count; ScriptModule *module; + struct list hash_table[43]; };
struct ScriptHost { @@ -800,6 +804,7 @@ static ULONG WINAPI ScriptProcedure_Release(IScriptProcedure *iface)
if (!ref) { + list_remove(&This->entry); SysFreeString(This->name); heap_free(This); } @@ -908,9 +913,12 @@ static const IScriptProcedureVtbl ScriptProcedureVtbl = { };
/* This function always releases the FUNCDESC passed in */ -static HRESULT get_script_procedure(ITypeInfo *typeinfo, FUNCDESC *desc, IScriptProcedure **procedure) +static HRESULT get_script_procedure(ScriptProcedureCollection *procedures, ITypeInfo *typeinfo, + FUNCDESC *desc, IScriptProcedure **procedure) { + struct list *proc_list; ScriptProcedure *proc; + ULONG hash; HRESULT hr; BSTR str; UINT len; @@ -918,6 +926,23 @@ static HRESULT get_script_procedure(ITypeInfo *typeinfo, FUNCDESC *desc, IScript hr = ITypeInfo_GetNames(typeinfo, desc->memid, &str, 1, &len); if (FAILED(hr)) goto done;
+ len = SysStringLen(str); + hash = LHashValOfNameSys(sizeof(void*) == 8 ? SYS_WIN64 : SYS_WIN32, LOCALE_USER_DEFAULT, str); + proc_list = &procedures->hash_table[hash % ARRAY_SIZE(procedures->hash_table)]; + + /* Try to find it in the hash table */ + LIST_FOR_EACH_ENTRY(proc, proc_list, ScriptProcedure, entry) + { + if (proc->hash == hash && SysStringLen(proc->name) == len && + !memcmp(proc->name, str, len * sizeof(*str))) + { + SysFreeString(str); + IScriptProcedure_AddRef(&proc->IScriptProcedure_iface); + *procedure = &proc->IScriptProcedure_iface; + goto done; + } + } + if (!(proc = heap_alloc(sizeof(*proc)))) { hr = E_OUTOFMEMORY; @@ -927,7 +952,9 @@ static HRESULT get_script_procedure(ITypeInfo *typeinfo, FUNCDESC *desc, IScript
proc->IScriptProcedure_iface.lpVtbl = &ScriptProcedureVtbl; proc->ref = 1; + proc->hash = hash; proc->name = str; + list_add_tail(proc_list, &proc->entry);
*procedure = &proc->IScriptProcedure_iface;
@@ -970,11 +997,16 @@ static ULONG WINAPI ScriptProcedureCollection_Release(IScriptProcedureCollection { ScriptProcedureCollection *This = impl_from_IScriptProcedureCollection(iface); LONG ref = InterlockedDecrement(&This->ref); + UINT i;
TRACE("(%p) ref=%d\n", This, ref);
if (!ref) { + /* Unlink any dangling items from the hash table */ + for (i = 0; i < ARRAY_SIZE(This->hash_table); i++) + list_remove(&This->hash_table[i]); + This->module->procedures = NULL; IScriptModule_Release(&This->module->IScriptModule_iface); heap_free(This); @@ -1073,12 +1105,29 @@ static HRESULT WINAPI ScriptProcedureCollection_get_Item(IScriptProcedureCollect
if (V_VT(&index) == VT_BSTR) { + struct list *proc_list; + ScriptProcedure *proc; ITypeComp *comp; BINDPTR bindptr; DESCKIND kind; ULONG hash; + UINT len;
+ len = SysStringLen(V_BSTR(&index)); hash = LHashValOfNameSys(sizeof(void*) == 8 ? SYS_WIN64 : SYS_WIN32, LOCALE_USER_DEFAULT, V_BSTR(&index)); + proc_list = &This->hash_table[hash % ARRAY_SIZE(This->hash_table)]; + + /* Try to find it in the hash table */ + LIST_FOR_EACH_ENTRY(proc, proc_list, ScriptProcedure, entry) + { + if (proc->hash == hash && SysStringLen(proc->name) == len && + !memcmp(proc->name, V_BSTR(&index), len * sizeof(WCHAR))) + { + IScriptProcedure_AddRef(&proc->IScriptProcedure_iface); + *ppdispProcedure = &proc->IScriptProcedure_iface; + return S_OK; + } + }
hr = get_script_typecomp(This->module, typeinfo, &comp); if (FAILED(hr)) return hr; @@ -1089,7 +1138,7 @@ static HRESULT WINAPI ScriptProcedureCollection_get_Item(IScriptProcedureCollect switch (kind) { case DESCKIND_FUNCDESC: - hr = get_script_procedure(typeinfo, bindptr.lpfuncdesc, ppdispProcedure); + hr = get_script_procedure(This, typeinfo, bindptr.lpfuncdesc, ppdispProcedure); ITypeInfo_Release(typeinfo); return hr; case DESCKIND_IMPLICITAPPOBJ: @@ -1113,7 +1162,7 @@ static HRESULT WINAPI ScriptProcedureCollection_get_Item(IScriptProcedureCollect hr = ITypeInfo_GetFuncDesc(typeinfo, V_INT(&index) - 1, &desc); if (FAILED(hr)) return hr;
- return get_script_procedure(typeinfo, desc, ppdispProcedure); + return get_script_procedure(This, typeinfo, desc, ppdispProcedure); }
static HRESULT WINAPI ScriptProcedureCollection_get_Count(IScriptProcedureCollection *iface, LONG *plCount) @@ -1343,6 +1392,7 @@ static HRESULT WINAPI ScriptModule_get_Procedures(IScriptModule *iface, IScriptP else { ScriptProcedureCollection *procs; + UINT i;
if (!(procs = heap_alloc(sizeof(*procs)))) return E_OUTOFMEMORY; @@ -1351,6 +1401,9 @@ static HRESULT WINAPI ScriptModule_get_Procedures(IScriptModule *iface, IScriptP procs->ref = 1; procs->count = -1; procs->module = This; + for (i = 0; i < ARRAY_SIZE(procs->hash_table); i++) + list_init(&procs->hash_table[i]); + This->procedures = procs; IScriptModule_AddRef(&This->IScriptModule_iface); } diff --git a/dlls/msscript.ocx/tests/msscript.c b/dlls/msscript.ocx/tests/msscript.c index ed4d0f8..c56e2d5 100644 --- a/dlls/msscript.ocx/tests/msscript.c +++ b/dlls/msscript.ocx/tests/msscript.c @@ -3293,7 +3293,7 @@ static void test_IScriptControl_get_CodeObject(void) static void test_IScriptControl_get_Procedures(void) { IScriptProcedureCollection *procs, *procs2; - IScriptProcedure *proc; + IScriptProcedure *proc, *proc2; IScriptControl *sc; VARIANT var; LONG count; @@ -3527,10 +3527,18 @@ static void test_IScriptControl_get_Procedures(void) CHECK_CALLED(GetFuncDesc); CHECK_CALLED(GetNames); CHECK_CALLED(ReleaseFuncDesc); - IScriptProcedure_Release(proc);
+ /* The name is cached and not looked up with Bind anymore */ V_VT(&var) = VT_BSTR; V_BSTR(&var) = SysAllocString(custom_engine_funcs[i].name); + hr = IScriptProcedureCollection_get_Item(procs, var, &proc2); + ok(hr == S_OK, "get_Item for %s failed: 0x%08x.\n", wine_dbgstr_w(custom_engine_funcs[i].name), hr); + ok(proc == proc2, "proc and proc2 are not the same for %s and index %u.\n", + wine_dbgstr_w(custom_engine_funcs[i].name), i + 1); + IScriptProcedure_Release(proc); + IScriptProcedure_Release(proc2); + + /* Since both were released, the cache entry is destroyed */ SET_EXPECT(Bind); SET_EXPECT(GetNames); SET_EXPECT(ReleaseFuncDesc);
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/msscript.ocx/msscript.c | 7 +++++-- dlls/msscript.ocx/tests/msscript.c | 22 ++++++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index ccdbba4..173e04a 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -876,9 +876,12 @@ static HRESULT WINAPI ScriptProcedure_get_Name(IScriptProcedure *iface, BSTR *pb { ScriptProcedure *This = impl_from_IScriptProcedure(iface);
- FIXME("(%p)->(%p)\n", This, pbstrName); + TRACE("(%p)->(%p)\n", This, pbstrName);
- return E_NOTIMPL; + if (!pbstrName) return E_POINTER; + + *pbstrName = SysAllocString(This->name); + return *pbstrName ? S_OK : E_OUTOFMEMORY; }
static HRESULT WINAPI ScriptProcedure_get_NumArgs(IScriptProcedure *iface, LONG *pcArgs) diff --git a/dlls/msscript.ocx/tests/msscript.c b/dlls/msscript.ocx/tests/msscript.c index c56e2d5..d08f30c 100644 --- a/dlls/msscript.ocx/tests/msscript.c +++ b/dlls/msscript.ocx/tests/msscript.c @@ -3352,6 +3352,12 @@ static void test_IScriptControl_get_Procedures(void) IScriptProcedureCollection_AddRef(procs); ok(i == IScriptProcedureCollection_Release(procs), "IScriptProcedureCollection_get_Item should not have added a ref to the collection.\n"); + hr = IScriptProcedure_get_Name(proc, NULL); + ok(hr == E_POINTER, "IScriptProcedure_get_Name returned: 0x%08x.\n", hr); + hr = IScriptProcedure_get_Name(proc, &str); + ok(hr == S_OK, "IScriptProcedure_get_Name failed: 0x%08x.\n", hr); + ok(!lstrcmpW(str, L"add"), "Wrong name, got %s.\n", wine_dbgstr_w(str)); + SysFreeString(str); IScriptProcedure_Release(proc);
V_VT(&var) = VT_BSTR; @@ -3360,12 +3366,20 @@ static void test_IScriptControl_get_Procedures(void) ok(hr == S_OK, "IScriptProcedureCollection_get_Item failed: 0x%08x.\n", hr); ok(V_VT(&var) == VT_BSTR, "var type not BSTR, got %d.\n", V_VT(&var)); VariantClear(&var); + hr = IScriptProcedure_get_Name(proc, &str); + ok(hr == S_OK, "IScriptProcedure_get_Name failed: 0x%08x.\n", hr); + ok(!lstrcmpW(str, L"nop"), "Wrong name, got %s.\n", wine_dbgstr_w(str)); + SysFreeString(str); IScriptProcedure_Release(proc);
V_VT(&var) = VT_R8; V_R8(&var) = 3.0; hr = IScriptProcedureCollection_get_Item(procs, var, &proc); ok(hr == S_OK, "IScriptProcedureCollection_get_Item failed: 0x%08x.\n", hr); + hr = IScriptProcedure_get_Name(proc, &str); + ok(hr == S_OK, "IScriptProcedure_get_Name failed: 0x%08x.\n", hr); + ok(!lstrcmpW(str, L"muladd"), "Wrong name, got %s.\n", wine_dbgstr_w(str)); + SysFreeString(str); IScriptProcedure_Release(proc);
IScriptProcedureCollection_Release(procs); @@ -3548,6 +3562,14 @@ static void test_IScriptControl_get_Procedures(void) CHECK_CALLED(Bind); CHECK_CALLED(GetNames); CHECK_CALLED(ReleaseFuncDesc); + + /* Verify the properties */ + hr = IScriptProcedure_get_Name(proc, &str); + ok(hr == S_OK, "get_Name for %s failed: 0x%08x.\n", wine_dbgstr_w(custom_engine_funcs[i].name), hr); + ok(!lstrcmpW(str, custom_engine_funcs[i].name), "Name is not %s, got %s.\n", + wine_dbgstr_w(custom_engine_funcs[i].name), wine_dbgstr_w(str)); + SysFreeString(str); + IScriptProcedure_Release(proc); }
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/msscript.ocx/msscript.c | 9 +++++++-- dlls/msscript.ocx/tests/msscript.c | 15 +++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index 173e04a..a510db7 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -97,6 +97,7 @@ typedef struct { struct list entry;
BSTR name; + USHORT num_args; } ScriptProcedure;
struct ScriptProcedureCollection { @@ -888,9 +889,12 @@ static HRESULT WINAPI ScriptProcedure_get_NumArgs(IScriptProcedure *iface, LONG { ScriptProcedure *This = impl_from_IScriptProcedure(iface);
- FIXME("(%p)->(%p)\n", This, pcArgs); + TRACE("(%p)->(%p)\n", This, pcArgs);
- return E_NOTIMPL; + if (!pcArgs) return E_POINTER; + + *pcArgs = This->num_args; + return S_OK; }
static HRESULT WINAPI ScriptProcedure_get_HasReturnValue(IScriptProcedure *iface, VARIANT_BOOL *pfHasReturnValue) @@ -957,6 +961,7 @@ static HRESULT get_script_procedure(ScriptProcedureCollection *procedures, IType proc->ref = 1; proc->hash = hash; proc->name = str; + proc->num_args = desc->cParams + desc->cParamsOpt; list_add_tail(proc_list, &proc->entry);
*procedure = &proc->IScriptProcedure_iface; diff --git a/dlls/msscript.ocx/tests/msscript.c b/dlls/msscript.ocx/tests/msscript.c index d08f30c..ad7e48f 100644 --- a/dlls/msscript.ocx/tests/msscript.c +++ b/dlls/msscript.ocx/tests/msscript.c @@ -3358,6 +3358,11 @@ static void test_IScriptControl_get_Procedures(void) ok(hr == S_OK, "IScriptProcedure_get_Name failed: 0x%08x.\n", hr); ok(!lstrcmpW(str, L"add"), "Wrong name, got %s.\n", wine_dbgstr_w(str)); SysFreeString(str); + hr = IScriptProcedure_get_NumArgs(proc, NULL); + ok(hr == E_POINTER, "IScriptProcedure_get_NumArgs returned: 0x%08x.\n", hr); + hr = IScriptProcedure_get_NumArgs(proc, &count); + ok(hr == S_OK, "IScriptProcedure_get_NumArgs failed: 0x%08x.\n", hr); + ok(count == 2, "Wrong NumArgs, got %d.\n", count); IScriptProcedure_Release(proc);
V_VT(&var) = VT_BSTR; @@ -3370,6 +3375,9 @@ static void test_IScriptControl_get_Procedures(void) ok(hr == S_OK, "IScriptProcedure_get_Name failed: 0x%08x.\n", hr); ok(!lstrcmpW(str, L"nop"), "Wrong name, got %s.\n", wine_dbgstr_w(str)); SysFreeString(str); + hr = IScriptProcedure_get_NumArgs(proc, &count); + ok(hr == S_OK, "IScriptProcedure_get_NumArgs failed: 0x%08x.\n", hr); + ok(count == 1, "Wrong NumArgs, got %d.\n", count); IScriptProcedure_Release(proc);
V_VT(&var) = VT_R8; @@ -3380,6 +3388,9 @@ static void test_IScriptControl_get_Procedures(void) ok(hr == S_OK, "IScriptProcedure_get_Name failed: 0x%08x.\n", hr); ok(!lstrcmpW(str, L"muladd"), "Wrong name, got %s.\n", wine_dbgstr_w(str)); SysFreeString(str); + hr = IScriptProcedure_get_NumArgs(proc, &count); + ok(hr == S_OK, "IScriptProcedure_get_NumArgs failed: 0x%08x.\n", hr); + ok(count == 3, "Wrong NumArgs, got %d.\n", count); IScriptProcedure_Release(proc);
IScriptProcedureCollection_Release(procs); @@ -3569,6 +3580,10 @@ static void test_IScriptControl_get_Procedures(void) ok(!lstrcmpW(str, custom_engine_funcs[i].name), "Name is not %s, got %s.\n", wine_dbgstr_w(custom_engine_funcs[i].name), wine_dbgstr_w(str)); SysFreeString(str); + hr = IScriptProcedure_get_NumArgs(proc, &count); + ok(hr == S_OK, "get_NumArgs for %s failed: 0x%08x.\n", wine_dbgstr_w(custom_engine_funcs[i].name), hr); + ok(count == custom_engine_funcs[i].num_args + custom_engine_funcs[i].num_opt_args, + "NumArgs is not %d, got %d.\n", custom_engine_funcs[i].num_args + custom_engine_funcs[i].num_opt_args, count);
IScriptProcedure_Release(proc); }
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/msscript.ocx/msscript.c | 9 +++++++-- dlls/msscript.ocx/tests/msscript.c | 13 +++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index a510db7..a339e70 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -98,6 +98,7 @@ typedef struct {
BSTR name; USHORT num_args; + VARTYPE ret_type; } ScriptProcedure;
struct ScriptProcedureCollection { @@ -901,9 +902,12 @@ static HRESULT WINAPI ScriptProcedure_get_HasReturnValue(IScriptProcedure *iface { ScriptProcedure *This = impl_from_IScriptProcedure(iface);
- FIXME("(%p)->(%p)\n", This, pfHasReturnValue); + TRACE("(%p)->(%p)\n", This, pfHasReturnValue);
- return E_NOTIMPL; + if (!pfHasReturnValue) return E_POINTER; + + *pfHasReturnValue = (This->ret_type == VT_VOID) ? VARIANT_FALSE : VARIANT_TRUE; + return S_OK; }
static const IScriptProcedureVtbl ScriptProcedureVtbl = { @@ -962,6 +966,7 @@ static HRESULT get_script_procedure(ScriptProcedureCollection *procedures, IType proc->hash = hash; proc->name = str; proc->num_args = desc->cParams + desc->cParamsOpt; + proc->ret_type = desc->elemdescFunc.tdesc.vt; list_add_tail(proc_list, &proc->entry);
*procedure = &proc->IScriptProcedure_iface; diff --git a/dlls/msscript.ocx/tests/msscript.c b/dlls/msscript.ocx/tests/msscript.c index ad7e48f..7233af5 100644 --- a/dlls/msscript.ocx/tests/msscript.c +++ b/dlls/msscript.ocx/tests/msscript.c @@ -3295,6 +3295,7 @@ static void test_IScriptControl_get_Procedures(void) IScriptProcedureCollection *procs, *procs2; IScriptProcedure *proc, *proc2; IScriptControl *sc; + VARIANT_BOOL vbool; VARIANT var; LONG count; HRESULT hr; @@ -3363,6 +3364,11 @@ static void test_IScriptControl_get_Procedures(void) hr = IScriptProcedure_get_NumArgs(proc, &count); ok(hr == S_OK, "IScriptProcedure_get_NumArgs failed: 0x%08x.\n", hr); ok(count == 2, "Wrong NumArgs, got %d.\n", count); + hr = IScriptProcedure_get_HasReturnValue(proc, NULL); + ok(hr == E_POINTER, "IScriptProcedure_get_HasReturnValue returned: 0x%08x.\n", hr); + hr = IScriptProcedure_get_HasReturnValue(proc, &vbool); + ok(hr == S_OK, "IScriptProcedure_get_HasReturnValue failed: 0x%08x.\n", hr); + ok(vbool == VARIANT_TRUE, "HasReturnValue did not return True, got %x.\n", vbool); IScriptProcedure_Release(proc);
V_VT(&var) = VT_BSTR; @@ -3378,6 +3384,9 @@ static void test_IScriptControl_get_Procedures(void) hr = IScriptProcedure_get_NumArgs(proc, &count); ok(hr == S_OK, "IScriptProcedure_get_NumArgs failed: 0x%08x.\n", hr); ok(count == 1, "Wrong NumArgs, got %d.\n", count); + hr = IScriptProcedure_get_HasReturnValue(proc, &vbool); + ok(hr == S_OK, "IScriptProcedure_get_HasReturnValue failed: 0x%08x.\n", hr); + ok(vbool == VARIANT_TRUE, "HasReturnValue did not return True, got %x.\n", vbool); IScriptProcedure_Release(proc);
V_VT(&var) = VT_R8; @@ -3584,6 +3593,10 @@ static void test_IScriptControl_get_Procedures(void) ok(hr == S_OK, "get_NumArgs for %s failed: 0x%08x.\n", wine_dbgstr_w(custom_engine_funcs[i].name), hr); ok(count == custom_engine_funcs[i].num_args + custom_engine_funcs[i].num_opt_args, "NumArgs is not %d, got %d.\n", custom_engine_funcs[i].num_args + custom_engine_funcs[i].num_opt_args, count); + hr = IScriptProcedure_get_HasReturnValue(proc, &vbool); + ok(hr == S_OK, "get_HasReturnValue for %s failed: 0x%08x.\n", wine_dbgstr_w(custom_engine_funcs[i].name), hr); + ok(vbool == ((custom_engine_funcs[i].ret_type == VT_VOID) ? VARIANT_FALSE : VARIANT_TRUE), + "get_HasReturnValue for %s returned %x.\n", wine_dbgstr_w(custom_engine_funcs[i].name), vbool);
IScriptProcedure_Release(proc); }