[PATCH 2/9] msscript.ocx/tests: Add initial tests for Script Procedures.

Gabriel Ivăncescu gabrielopcode at gmail.com
Mon Aug 10 09:57:57 CDT 2020


Signed-off-by: Gabriel Ivăncescu <gabrielopcode at 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);
 
-- 
2.21.0




More information about the wine-devel mailing list