Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/msscript.ocx/msscript.c | 163 ++++++++++++++++++++++++++++- dlls/msscript.ocx/tests/msscript.c | 134 +++++++++++++++++++++++- 2 files changed, 294 insertions(+), 3 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index 7fc7b95..352bcab 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -66,6 +66,15 @@ struct named_item { IDispatch *disp; };
+struct module_enum { + IEnumVARIANT IEnumVARIANT_iface; + LONG ref; + + UINT pos; + ScriptHost *host; + ScriptControl *control; +}; + typedef struct { IScriptModule IScriptModule_iface; LONG ref; @@ -375,6 +384,11 @@ static inline ScriptHost *impl_from_IServiceProvider(IServiceProvider *iface) return CONTAINING_RECORD(iface, ScriptHost, IServiceProvider_iface); }
+static inline struct module_enum *module_enum_from_IEnumVARIANT(IEnumVARIANT *iface) +{ + return CONTAINING_RECORD(iface, struct module_enum, IEnumVARIANT_iface); +} + /* IActiveScriptSite */ static HRESULT WINAPI ActiveScriptSite_QueryInterface(IActiveScriptSite *iface, REFIID riid, void **ppv) { @@ -844,6 +858,135 @@ static const IScriptModuleVtbl ScriptModuleVtbl = { ScriptModule_Run };
+static HRESULT WINAPI module_enum_QueryInterface(IEnumVARIANT *iface, REFIID riid, void **ppv) +{ + struct module_enum *This = module_enum_from_IEnumVARIANT(iface); + + if (IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IEnumVARIANT, riid)) + { + *ppv = &This->IEnumVARIANT_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 module_enum_AddRef(IEnumVARIANT *iface) +{ + struct module_enum *This = module_enum_from_IEnumVARIANT(iface); + LONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) ref=%d\n", This, ref); + + return ref; +} + +static ULONG WINAPI module_enum_Release(IEnumVARIANT *iface) +{ + struct module_enum *This = module_enum_from_IEnumVARIANT(iface); + LONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) ref=%d\n", This, ref); + + if (!ref) + { + IActiveScriptSite_Release(&This->host->IActiveScriptSite_iface); + IScriptControl_Release(&This->control->IScriptControl_iface); + heap_free(This); + } + + return ref; +} + +static HRESULT WINAPI module_enum_Next(IEnumVARIANT *iface, ULONG celt, VARIANT *rgVar, ULONG *pCeltFetched) +{ + struct module_enum *This = module_enum_from_IEnumVARIANT(iface); + unsigned int i, num; + + TRACE("(%p)->(%u %p %p)\n", This, celt, rgVar, pCeltFetched); + + if (!rgVar) return E_POINTER; + if (This->host != This->control->host) return E_FAIL; + + num = min(celt, This->host->module_count - This->pos); + for (i = 0; i < num; i++) + { + V_VT(rgVar + i) = VT_DISPATCH; + V_DISPATCH(rgVar + i) = (IDispatch*)(&This->control->modules[This->pos++]->IScriptModule_iface); + IDispatch_AddRef(V_DISPATCH(rgVar + i)); + } + + if (pCeltFetched) *pCeltFetched = i; + return i == celt ? S_OK : S_FALSE; +} + +static HRESULT WINAPI module_enum_Skip(IEnumVARIANT *iface, ULONG celt) +{ + struct module_enum *This = module_enum_from_IEnumVARIANT(iface); + + TRACE("(%p)->(%u)\n", This, celt); + + if (This->host != This->control->host) return E_FAIL; + + if (This->host->module_count - This->pos < celt) + { + This->pos = This->host->module_count; + return S_FALSE; + } + This->pos += celt; + return S_OK; +} + +static HRESULT WINAPI module_enum_Reset(IEnumVARIANT *iface) +{ + struct module_enum *This = module_enum_from_IEnumVARIANT(iface); + + TRACE("(%p)\n", This); + + if (This->host != This->control->host) return E_FAIL; + + This->pos = 0; + return S_OK; +} + +static HRESULT WINAPI module_enum_Clone(IEnumVARIANT *iface, IEnumVARIANT **ppEnum) +{ + struct module_enum *This = module_enum_from_IEnumVARIANT(iface); + struct module_enum *clone; + + TRACE("(%p)->(%p)\n", This, ppEnum); + + if (!ppEnum) return E_POINTER; + if (This->host != This->control->host) return E_FAIL; + + if (!(clone = heap_alloc(sizeof(*clone)))) + return E_OUTOFMEMORY; + + *clone = *This; + clone->ref = 1; + IActiveScriptSite_AddRef(&This->host->IActiveScriptSite_iface); + IScriptControl_AddRef(&This->control->IScriptControl_iface); + + *ppEnum = &clone->IEnumVARIANT_iface; + return S_OK; +} + +static const IEnumVARIANTVtbl module_enum_vtbl = { + module_enum_QueryInterface, + module_enum_AddRef, + module_enum_Release, + module_enum_Next, + module_enum_Skip, + module_enum_Reset, + module_enum_Clone +}; + static ScriptModule *create_module(ScriptHost *host, BSTR name) { ScriptModule *module; @@ -987,10 +1130,26 @@ static HRESULT WINAPI ScriptModuleCollection_Invoke(IScriptModuleCollection *ifa static HRESULT WINAPI ScriptModuleCollection_get__NewEnum(IScriptModuleCollection *iface, IUnknown **ppenumContexts) { ScriptControl *This = impl_from_IScriptModuleCollection(iface); + struct module_enum *module_enum;
- FIXME("(%p)->(%p)\n", This, ppenumContexts); + TRACE("(%p)->(%p)\n", This, ppenumContexts);
- return E_NOTIMPL; + if (!ppenumContexts) return E_POINTER; + if (!This->host) return E_FAIL; + + if (!(module_enum = heap_alloc(sizeof(*module_enum)))) + return E_OUTOFMEMORY; + + module_enum->IEnumVARIANT_iface.lpVtbl = &module_enum_vtbl; + module_enum->ref = 1; + module_enum->pos = 0; + module_enum->host = This->host; + module_enum->control = This; + IActiveScriptSite_AddRef(&This->host->IActiveScriptSite_iface); + IScriptControl_AddRef(&This->IScriptControl_iface); + + *ppenumContexts = (IUnknown*)&module_enum->IEnumVARIANT_iface; + return S_OK; }
static HRESULT WINAPI ScriptModuleCollection_get_Item(IScriptModuleCollection *iface, VARIANT index, diff --git a/dlls/msscript.ocx/tests/msscript.c b/dlls/msscript.ocx/tests/msscript.c index 807f82e..9986fbf 100644 --- a/dlls/msscript.ocx/tests/msscript.c +++ b/dlls/msscript.ocx/tests/msscript.c @@ -2307,14 +2307,17 @@ static void test_IScriptControl_Run(void)
static void test_IScriptControl_get_Modules(void) { + IEnumVARIANT *enumvar, *enumvar2; IScriptModuleCollection *mods; + VARIANT var, vars[3]; IScriptModule *mod; IScriptControl *sc; IUnknown *unknown; - VARIANT var; + ULONG fetched; LONG count; HRESULT hr; BSTR str; + UINT i;
hr = CoCreateInstance(&CLSID_ScriptControl, NULL, CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, &IID_IScriptControl, (void**)&sc); @@ -2360,6 +2363,16 @@ static void test_IScriptControl_get_Modules(void) IScriptModule_Release(mod); SysFreeString(str);
+ /* Grab an enumerator before we add another module */ + hr = IScriptModuleCollection_get__NewEnum(mods, NULL); + ok(hr == E_POINTER, "IScriptModuleCollection_get__NewEnum returned: 0x%08x.\n", hr); + hr = IScriptModuleCollection_get__NewEnum(mods, &unknown); + ok(hr == S_OK, "IScriptModuleCollection_get__NewEnum failed: 0x%08x.\n", hr); + hr = IUnknown_QueryInterface(unknown, &IID_IEnumVARIANT, (void**)&enumvar); + ok(hr == S_OK, "Failed to query for IEnumVARIANT: 0x%08x.\n", hr); + ok((char*)unknown == (char*)enumvar, "unknown and enumvar are not the same (%p vs %p).\n", unknown, enumvar); + IUnknown_Release(unknown); + str = SysAllocString(L"some other Module"); hr = IScriptModuleCollection_Add(mods, str, &var, &mod); ok(hr == S_OK, "IScriptModuleCollection_Add failed: 0x%08x.\n", hr); @@ -2428,6 +2441,46 @@ static void test_IScriptControl_get_Modules(void) IScriptModule_Release(mod); SysFreeString(str);
+ /* Test the enumerator, should be updated */ + fetched = 0xdeadbeef; + hr = IEnumVARIANT_Next(enumvar, 0, NULL, NULL); + ok(hr == E_POINTER, "IEnumVARIANT_Next returned: 0x%08x.\n", hr); + hr = IEnumVARIANT_Next(enumvar, 0, NULL, &fetched); + ok(hr == E_POINTER, "IEnumVARIANT_Next failed: 0x%08x.\n", hr); + ok(fetched == 0xdeadbeef, "got %u.\n", fetched); + hr = IEnumVARIANT_Next(enumvar, 0, &var, &fetched); + ok(hr == S_OK, "IEnumVARIANT_Next returned: 0x%08x.\n", hr); + ok(fetched == 0, "got %u.\n", fetched); + hr = IEnumVARIANT_Next(enumvar, 0, &var, NULL); + ok(hr == S_OK, "IEnumVARIANT_Next returned: 0x%08x.\n", hr); + hr = IEnumVARIANT_Clone(enumvar, NULL); + ok(hr == E_POINTER, "IEnumVARIANT_Clone failed: 0x%08x.\n", hr); + + hr = IEnumVARIANT_Next(enumvar, ARRAY_SIZE(vars), vars, &fetched); + ok(hr == S_OK, "IEnumVARIANT_Next failed: 0x%08x.\n", hr); + ok(fetched == ARRAY_SIZE(vars), "got %u.\n", fetched); + hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched); + ok(hr == S_FALSE, "IEnumVARIANT_Next failed: 0x%08x.\n", hr); + ok(fetched == 0, "got %u.\n", fetched); + hr = IEnumVARIANT_Skip(enumvar, 0); + ok(hr == S_OK, "IEnumVARIANT_Skip failed: 0x%08x.\n", hr); + hr = IEnumVARIANT_Skip(enumvar, 1); + ok(hr == S_FALSE, "IEnumVARIANT_Skip failed: 0x%08x.\n", hr); + hr = IEnumVARIANT_Clone(enumvar, &enumvar2); + ok(hr == S_OK, "IEnumVARIANT_Clone failed: 0x%08x.\n", hr); + hr = IEnumVARIANT_Skip(enumvar2, 1); + ok(hr == S_FALSE, "IEnumVARIANT_Skip failed: 0x%08x.\n", hr); + IEnumVARIANT_Release(enumvar2); + + for (i = 0; i < ARRAY_SIZE(vars); i++) + { + ok(V_VT(&vars[i]) == VT_DISPATCH, "V_VT(vars[%u]) = %d.\n", i, V_VT(&vars[i])); + hr = IDispatch_QueryInterface(V_DISPATCH(&vars[i]), &IID_IScriptModule, (void**)&mod); + ok(hr == S_OK, "Failed to query IScriptModule from vars[%u]: 0x%08x.\n", i, hr); + IScriptModule_Release(mod); + VariantClear(&vars[i]); + } + /* The 'Global' module is the same as the script control */ str = SysAllocString(L"add(10, 5)"); hr = IScriptControl_Eval(sc, str, &var); @@ -2465,6 +2518,17 @@ static void test_IScriptControl_get_Modules(void) IScriptModule_Release(mod); SysFreeString(str);
+ /* The enumerator is also invalid */ + hr = IEnumVARIANT_Reset(enumvar); + ok(hr == E_FAIL, "IEnumVARIANT_Skip returned: 0x%08x.\n", hr); + hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched); + ok(hr == E_FAIL, "IEnumVARIANT_Next returned: 0x%08x.\n", hr); + hr = IEnumVARIANT_Skip(enumvar, 0); + ok(hr == E_FAIL, "IEnumVARIANT_Skip returned: 0x%08x.\n", hr); + hr = IEnumVARIANT_Clone(enumvar, &enumvar2); + ok(hr == E_FAIL, "IEnumVARIANT_Clone returned: 0x%08x.\n", hr); + IEnumVARIANT_Release(enumvar); + hr = IScriptControl_put_Language(sc, NULL); ok(hr == S_OK, "IScriptControl_put_Language failed: 0x%08x.\n", hr);
@@ -2480,6 +2544,8 @@ static void test_IScriptControl_get_Modules(void) hr = IScriptModuleCollection_Add(mods, str, &var, &mod); ok(hr == E_FAIL, "IScriptModuleCollection_Add returned: 0x%08x.\n", hr); SysFreeString(str); + hr = IScriptModuleCollection_get__NewEnum(mods, &unknown); + ok(hr == E_FAIL, "IScriptModuleCollection_get__NewEnum returned: 0x%08x.\n", hr);
IScriptModuleCollection_Release(mods); hr = IScriptControl_get_Modules(sc, &mods); @@ -2640,6 +2706,72 @@ static void test_IScriptControl_get_Modules(void) SET_EXPECT(Close); IScriptModule_Release(mod); CHECK_CALLED(Close); + + /* Hold an enumerator while releasing the script control */ + 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_Modules(sc, &mods); + ok(hr == S_OK, "IScriptControl_get_Modules failed: 0x%08x.\n", hr); + IScriptControl_Release(sc); + + SET_EXPECT(AddNamedItem); + str = SysAllocString(L"bar"); + AddNamedItem_expected_name = str; + AddNamedItem_expected_flags = SCRIPTITEM_CODEONLY; + V_VT(&var) = VT_DISPATCH; + V_DISPATCH(&var) = NULL; + hr = IScriptModuleCollection_Add(mods, str, &var, &mod); + ok(hr == S_OK, "IScriptModuleCollection_Add failed: 0x%08x.\n", hr); + IScriptModule_Release(mod); + VariantClear(&var); + SysFreeString(str); + CHECK_CALLED(AddNamedItem); + + hr = IScriptModuleCollection_get__NewEnum(mods, &unknown); + ok(hr == S_OK, "IScriptModuleCollection_get__NewEnum failed: 0x%08x.\n", hr); + hr = IUnknown_QueryInterface(unknown, &IID_IEnumVARIANT, (void**)&enumvar); + ok(hr == S_OK, "Failed to query for IEnumVARIANT: 0x%08x.\n", hr); + IUnknown_Release(unknown); + + IScriptModuleCollection_Release(mods); + IActiveScriptSite_Release(site); + + hr = IEnumVARIANT_Next(enumvar, ARRAY_SIZE(vars), vars, &fetched); + ok(hr == S_FALSE, "IEnumVARIANT_Next failed: 0x%08x.\n", hr); + ok(fetched == 2, "got %u.\n", fetched); + for (i = 0; i < fetched; i++) + { + ok(V_VT(&vars[i]) == VT_DISPATCH, "V_VT(vars[%u]) = %d.\n", i, V_VT(&vars[i])); + hr = IDispatch_QueryInterface(V_DISPATCH(&vars[i]), &IID_IScriptModule, (void**)&mod); + ok(hr == S_OK, "Failed to query IScriptModule from vars[%u]: 0x%08x.\n", i, hr); + hr = IScriptModule_get_Name(mod, &str); + ok(hr == S_OK, "IScriptModule_get_Name failed for vars[%u]: 0x%08x.\n", i, hr); + ok(!lstrcmpW(str, i ? L"bar" : L"Global"), "wrong name for vars[%u]: %s.\n", i, wine_dbgstr_w(str)); + IScriptModule_Release(mod); + VariantClear(&vars[i]); + SysFreeString(str); + } + + SET_EXPECT(Close); + IEnumVARIANT_Release(enumvar); + CHECK_CALLED(Close); } }
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/msscript.ocx/msscript.c | 97 +++++++++++++++++++----------------- 1 file changed, 51 insertions(+), 46 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index 352bcab..db5d97d 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -314,6 +314,56 @@ static HRESULT parse_script_text(ScriptModule *module, BSTR script_text, DWORD f return hr; }
+static HRESULT run_procedure(ScriptModule *module, BSTR procedure_name, SAFEARRAY *args, VARIANT *res) +{ + IDispatchEx *dispex; + IDispatch *disp; + DISPPARAMS dp; + DISPID dispid; + HRESULT hr; + UINT i; + + hr = start_script(module->host); + if (FAILED(hr)) return hr; + + hr = get_script_dispatch(module, &disp); + if (FAILED(hr)) return hr; + + hr = IDispatch_GetIDsOfNames(disp, &IID_NULL, &procedure_name, 1, LOCALE_USER_DEFAULT, &dispid); + if (FAILED(hr)) return hr; + + dp.cArgs = args->rgsabound[0].cElements; + dp.rgdispidNamedArgs = NULL; + dp.cNamedArgs = 0; + dp.rgvarg = heap_alloc(dp.cArgs * sizeof(*dp.rgvarg)); + if (!dp.rgvarg) return E_OUTOFMEMORY; + + hr = SafeArrayLock(args); + if (SUCCEEDED(hr)) + { + /* The DISPPARAMS are stored in reverse order */ + for (i = 0; i < dp.cArgs; i++) + dp.rgvarg[i] = *(VARIANT*)((char*)(args->pvData) + (dp.cArgs - i - 1) * args->cbElements); + SafeArrayUnlock(args); + + hr = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); + if (FAILED(hr)) + { + hr = IDispatch_Invoke(disp, dispid, &IID_NULL, LOCALE_USER_DEFAULT, + DISPATCH_METHOD, &dp, res, NULL, NULL); + } + else + { + hr = IDispatchEx_InvokeEx(dispex, dispid, LOCALE_USER_DEFAULT, + DISPATCH_METHOD, &dp, res, NULL, NULL); + IDispatchEx_Release(dispex); + } + } + heap_free(dp.rgvarg); + + return hr; +} + static inline ScriptControl *impl_from_IScriptControl(IScriptControl *iface) { return CONTAINING_RECORD(iface, ScriptControl, IScriptControl_iface); @@ -1782,13 +1832,7 @@ static HRESULT WINAPI ScriptControl_ExecuteStatement(IScriptControl *iface, BSTR static HRESULT WINAPI ScriptControl_Run(IScriptControl *iface, BSTR procedure_name, SAFEARRAY **parameters, VARIANT *res) { ScriptControl *This = impl_from_IScriptControl(iface); - IDispatchEx *dispex; - IDispatch *disp; SAFEARRAY *sa; - DISPPARAMS dp; - DISPID dispid; - HRESULT hr; - UINT i;
TRACE("(%p)->(%s %p %p)\n", This, debugstr_w(procedure_name), parameters, res);
@@ -1798,48 +1842,9 @@ static HRESULT WINAPI ScriptControl_Run(IScriptControl *iface, BSTR procedure_na V_VT(res) = VT_EMPTY; if (sa->cDims == 0) return DISP_E_BADINDEX; if (!(sa->fFeatures & FADF_VARIANT)) return DISP_E_BADVARTYPE; - - if (!This->host) return E_FAIL; - hr = start_script(This->host); - if (FAILED(hr)) return hr; - - hr = get_script_dispatch(This->modules[0], &disp); - if (FAILED(hr)) return hr; - - hr = IDispatch_GetIDsOfNames(disp, &IID_NULL, &procedure_name, 1, LOCALE_USER_DEFAULT, &dispid); - if (FAILED(hr)) return hr; - - dp.cArgs = sa->rgsabound[0].cElements; - dp.rgdispidNamedArgs = NULL; - dp.cNamedArgs = 0; - dp.rgvarg = heap_alloc(dp.cArgs * sizeof(*dp.rgvarg)); - if (!dp.rgvarg) return E_OUTOFMEMORY;
- hr = SafeArrayLock(sa); - if (SUCCEEDED(hr)) - { - /* The DISPPARAMS are stored in reverse order */ - for (i = 0; i < dp.cArgs; i++) - dp.rgvarg[i] = *(VARIANT*)((char*)(sa->pvData) + (dp.cArgs - i - 1) * sa->cbElements); - SafeArrayUnlock(sa); - - hr = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); - if (FAILED(hr)) - { - hr = IDispatch_Invoke(disp, dispid, &IID_NULL, LOCALE_USER_DEFAULT, - DISPATCH_METHOD, &dp, res, NULL, NULL); - } - else - { - hr = IDispatchEx_InvokeEx(dispex, dispid, LOCALE_USER_DEFAULT, - DISPATCH_METHOD, &dp, res, NULL, NULL); - IDispatchEx_Release(dispex); - } - } - heap_free(dp.rgvarg); - - return hr; + return run_procedure(This->modules[0], procedure_name, sa, res); }
static const IScriptControlVtbl ScriptControlVtbl = {
Hi Gabriel,
Could we just move it to ScriptModule::Run and call it from here like you do for get_CodeObject in the other patch?
Thanks,
Jacek
On 04/08/2020 18:04, Jacek Caban wrote:
Hi Gabriel,
Could we just move it to ScriptModule::Run and call it from here like you do for get_CodeObject in the other patch?
Thanks,
Jacek
Hi Jacek,
Unfortunately we'd still have to do all the extra error checking before calling it, because it seems it matters for the tests and how they report the errors (in what order).
So it wouldn't change much, except not have the helper. Do you still think it's worth it?
Thanks, Gabriel
Signed-off-by: Jacek Caban jacek@codeweavers.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/msscript.ocx/msscript.c | 13 +++++- dlls/msscript.ocx/tests/msscript.c | 75 ++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 2 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index db5d97d..c36a5db 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -885,10 +885,19 @@ static HRESULT WINAPI ScriptModule_ExecuteStatement(IScriptModule *iface, BSTR s static HRESULT WINAPI ScriptModule_Run(IScriptModule *iface, BSTR procedure_name, SAFEARRAY **parameters, VARIANT *res) { ScriptModule *This = impl_from_IScriptModule(iface); + SAFEARRAY *sa;
- FIXME("(%p)->(%s %p %p)\n", This, debugstr_w(procedure_name), parameters, res); + TRACE("(%p)->(%s %p %p)\n", This, debugstr_w(procedure_name), parameters, res);
- return E_NOTIMPL; + if (!parameters || !res) return E_POINTER; + if (!(sa = *parameters)) return E_POINTER; + + V_VT(res) = VT_EMPTY; + if (sa->cDims == 0) return DISP_E_BADINDEX; + if (!(sa->fFeatures & FADF_VARIANT)) return DISP_E_BADVARTYPE; + if (!This->host) return E_FAIL; + + return run_procedure(This, procedure_name, sa, res); }
static const IScriptModuleVtbl ScriptModuleVtbl = { diff --git a/dlls/msscript.ocx/tests/msscript.c b/dlls/msscript.ocx/tests/msscript.c index 9986fbf..7f121e0 100644 --- a/dlls/msscript.ocx/tests/msscript.c +++ b/dlls/msscript.ocx/tests/msscript.c @@ -2307,11 +2307,18 @@ static void test_IScriptControl_Run(void)
static void test_IScriptControl_get_Modules(void) { + SAFEARRAYBOUND bnd[] = { { 2, 0 }, { 2, 0 } }; + LONG idx0_0[] = { 0, 0 }; + LONG idx0_1[] = { 1, 0 }; + LONG idx1_0[] = { 0, 1 }; + LONG idx1_1[] = { 1, 1 }; + IEnumVARIANT *enumvar, *enumvar2; IScriptModuleCollection *mods; VARIANT var, vars[3]; IScriptModule *mod; IScriptControl *sc; + SAFEARRAY *params; IUnknown *unknown; ULONG fetched; LONG count; @@ -2492,6 +2499,69 @@ static void test_IScriptControl_get_Modules(void) ok(FAILED(hr), "IScriptControl_Eval succeeded: 0x%08x.\n", hr); SysFreeString(str);
+ V_VT(&var) = VT_R4; + V_R4(&var) = 2.0f; + hr = IScriptModuleCollection_get_Item(mods, var, &mod); + ok(hr == S_OK, "IScriptModuleCollection_get_Item failed: 0x%08x.\n", hr); + + params = SafeArrayCreate(VT_VARIANT, 1, bnd); + ok(params != NULL, "Failed to create SafeArray.\n"); + + V_VT(&var) = VT_I4; + V_I4(&var) = 10; + SafeArrayPutElement(params, idx0_0, &var); + V_I4(&var) = 3; + SafeArrayPutElement(params, idx0_1, &var); + + str = SysAllocString(L"sub"); + hr = IScriptModule_Run(mod, str, NULL, &var); + ok(hr == E_POINTER, "IScriptModule_Run returned: 0x%08x.\n", hr); + hr = IScriptModule_Run(mod, str, ¶ms, NULL); + ok(hr == E_POINTER, "IScriptModule_Run returned: 0x%08x.\n", hr); + + hr = IScriptControl_Run(sc, str, ¶ms, &var); + ok(hr == DISP_E_UNKNOWNNAME, "IScriptControl_Run failed: 0x%08x.\n", hr); + hr = IScriptModule_Run(mod, str, ¶ms, &var); + ok(hr == S_OK, "IScriptModule_Run failed: 0x%08x.\n", hr); + ok((V_VT(&var) == VT_I4) && (V_I4(&var) == 7), "V_VT(var) = %d, V_I4(var) = %d.\n", V_VT(&var), V_I4(&var)); + SysFreeString(str); + + str = SysAllocString(L"add"); + hr = IScriptControl_Run(sc, str, ¶ms, &var); + ok(hr == S_OK, "IScriptControl_Run failed: 0x%08x.\n", hr); + ok((V_VT(&var) == VT_I4) && (V_I4(&var) == 13), "V_VT(var) = %d, V_I4(var) = %d.\n", V_VT(&var), V_I4(&var)); + hr = IScriptModule_Run(mod, str, ¶ms, &var); + ok(hr == DISP_E_UNKNOWNNAME, "IScriptModule_Run failed: 0x%08x.\n", hr); + SysFreeString(str); + + SafeArrayDestroy(params); + params = SafeArrayCreate(VT_VARIANT, 2, bnd); + ok(params != NULL, "Failed to create SafeArray.\n"); + + V_VT(&var) = VT_I4; + V_I4(&var) = 49; + SafeArrayPutElement(params, idx0_0, &var); + V_I4(&var) = 7; + SafeArrayPutElement(params, idx0_1, &var); + V_I4(&var) = 30; + SafeArrayPutElement(params, idx1_0, &var); + V_I4(&var) = 25; + SafeArrayPutElement(params, idx1_1, &var); + + str = SysAllocString(L"sub"); + hr = IScriptModule_Run(mod, str, ¶ms, &var); + ok(hr == S_OK, "IScriptModule_Run failed: 0x%08x.\n", hr); + ok((V_VT(&var) == VT_I4) && (V_I4(&var) == 42), "V_VT(var) = %d, V_I4(var) = %d.\n", V_VT(&var), V_I4(&var)); + + params->cDims = 0; + hr = IScriptModule_Run(mod, str, ¶ms, &var); + ok(hr == DISP_E_BADINDEX, "IScriptModule_Run returned: 0x%08x.\n", hr); + ok(V_VT(&var) == VT_EMPTY, "V_VT(var) = %d.\n", V_VT(&var)); + params->cDims = 2; + SysFreeString(str); + + IScriptModule_Release(mod); + /* Grab a module ref and change the language to something valid */ V_VT(&var) = VT_I2; V_I2(&var) = 3; @@ -2515,7 +2585,12 @@ static void test_IScriptControl_get_Modules(void) str = SysAllocString(L"sub closed\nend sub"); hr = IScriptModule_AddCode(mod, str); ok(hr == E_FAIL, "IScriptModule_AddCode failed: 0x%08x.\n", hr); + SysFreeString(str); + str = SysAllocString(L"identifier"); + hr = IScriptModule_Run(mod, str, ¶ms, &var); + ok(hr == E_FAIL, "IScriptModule_Run returned: 0x%08x.\n", hr); IScriptModule_Release(mod); + SafeArrayDestroy(params); SysFreeString(str);
/* The enumerator is also invalid */
Signed-off-by: Jacek Caban jacek@codeweavers.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/msscript.ocx/msscript.c | 14 +++++++++-- dlls/msscript.ocx/tests/msscript.c | 37 ++++++++++++++++++++++++++++-- 2 files changed, 47 insertions(+), 4 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index c36a5db..94d6dda 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -828,10 +828,20 @@ static HRESULT WINAPI ScriptModule_get_Name(IScriptModule *iface, BSTR *pbstrNam static HRESULT WINAPI ScriptModule_get_CodeObject(IScriptModule *iface, IDispatch **ppdispObject) { ScriptModule *This = impl_from_IScriptModule(iface); + HRESULT hr;
- FIXME("(%p)->(%p)\n", This, ppdispObject); + TRACE("(%p)->(%p)\n", This, ppdispObject);
- return E_NOTIMPL; + if (!This->host) return E_FAIL; + + hr = start_script(This->host); + if (FAILED(hr)) return hr; + + hr = get_script_dispatch(This, ppdispObject); + if (FAILED(hr)) return hr; + + IDispatch_AddRef(*ppdispObject); + return hr; }
static HRESULT WINAPI ScriptModule_get_Procedures(IScriptModule *iface, IScriptProcedureCollection **ppdispProcedures) diff --git a/dlls/msscript.ocx/tests/msscript.c b/dlls/msscript.ocx/tests/msscript.c index 7f121e0..90f6d19 100644 --- a/dlls/msscript.ocx/tests/msscript.c +++ b/dlls/msscript.ocx/tests/msscript.c @@ -549,11 +549,13 @@ static HRESULT WINAPI ActiveScript_AddTypeLib(IActiveScript *iface, REFGUID rgui return E_NOTIMPL; }
+static const WCHAR *GetScriptDispatch_expected_name; static HRESULT WINAPI ActiveScript_GetScriptDispatch(IActiveScript *iface, LPCOLESTR pstrItemName, IDispatch **ppdisp) { CHECK_EXPECT(GetScriptDispatch); - ok(!pstrItemName, "pstrItemName not NULL, got %s.\n", wine_dbgstr_w(pstrItemName)); + ok(GetScriptDispatch_expected_name ? (pstrItemName && !lstrcmpW(pstrItemName, GetScriptDispatch_expected_name)) : !pstrItemName, + "pstrItemName not %s, got %s.\n", wine_dbgstr_w(GetScriptDispatch_expected_name), wine_dbgstr_w(pstrItemName));
*ppdisp = (IDispatch*)&DispatchEx;
@@ -2234,6 +2236,7 @@ static void test_IScriptControl_Run(void) CHECK_CALLED(QI_IActiveScriptParse); CHECK_CALLED(InitNew);
+ GetScriptDispatch_expected_name = NULL; SET_EXPECT(SetScriptState_STARTED); SET_EXPECT(GetScriptDispatch); SET_EXPECT(QI_IDispatchEx); @@ -2320,9 +2323,11 @@ static void test_IScriptControl_get_Modules(void) IScriptControl *sc; SAFEARRAY *params; IUnknown *unknown; + IDispatch *disp; ULONG fetched; LONG count; HRESULT hr; + DISPID id; BSTR str; UINT i;
@@ -2504,6 +2509,23 @@ static void test_IScriptControl_get_Modules(void) hr = IScriptModuleCollection_get_Item(mods, var, &mod); ok(hr == S_OK, "IScriptModuleCollection_get_Item failed: 0x%08x.\n", hr);
+ hr = IScriptModule_get_CodeObject(mod, &disp); + ok(hr == S_OK, "IScriptModule_get_CodeObject failed: 0x%08x.\n", hr); + + str = SysAllocString(L"sub"); + hr = IDispatch_GetIDsOfNames(disp, &IID_NULL, &str, 1, LOCALE_USER_DEFAULT, &id); + ok(hr == S_OK, "IDispatch_GetIDsOfNames failed: 0x%08x.\n", hr); + ok(id != -1, "Unexpected id %d.\n", id); + SysFreeString(str); + + str = SysAllocString(L"add"); + hr = IDispatch_GetIDsOfNames(disp, &IID_NULL, &str, 1, LOCALE_USER_DEFAULT, &id); + ok(hr == DISP_E_UNKNOWNNAME, "IDispatch_GetIDsOfNames returned: 0x%08x.\n", hr); + ok(id == -1, "Unexpected id %d.\n", id); + SysFreeString(str); + + IDispatch_Release(disp); + params = SafeArrayCreate(VT_VARIANT, 1, bnd); ok(params != NULL, "Failed to create SafeArray.\n");
@@ -2578,6 +2600,8 @@ static void test_IScriptControl_get_Modules(void) ok(count == 1, "count is not 1, got %d.\n", count); hr = IScriptModule_get_Name(mod, &str); 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); str = SysAllocString(L"function closed() { }\n"); hr = IScriptModule_AddCode(mod, str); ok(hr == E_FAIL, "IScriptModule_AddCode failed: 0x%08x.\n", hr); @@ -2703,14 +2727,23 @@ static void test_IScriptControl_get_Modules(void) ok(unknown == (IUnknown*)&testdisp, "Unexpected IUnknown for the item: %p.\n", unknown); IUnknown_Release(unknown);
+ GetScriptDispatch_expected_name = str; SET_EXPECT(SetScriptState_STARTED); + SET_EXPECT(GetScriptDispatch); + hr = IScriptModule_get_CodeObject(mod, &disp); + ok(hr == S_OK, "IScriptModule_get_CodeObject failed: 0x%08x.\n", hr); + ok(disp == (IDispatch*)&DispatchEx, "Unexpected code object %p.\n", disp); + CHECK_CALLED(GetScriptDispatch); + CHECK_CALLED(SetScriptState_STARTED); + GetScriptDispatch_expected_name = NULL; + IDispatch_Release(disp); + SET_EXPECT(ParseScriptText); parse_item_name = str; parse_flags = SCRIPTTEXT_ISVISIBLE; code_str = SysAllocString(L"some code"); hr = IScriptModule_AddCode(mod, code_str); ok(hr == S_OK, "IScriptControl_AddCode failed: 0x%08x.\n", hr); - CHECK_CALLED(SetScriptState_STARTED); CHECK_CALLED(ParseScriptText); SysFreeString(code_str); SysFreeString(str);
Signed-off-by: Jacek Caban jacek@codeweavers.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/msscript.ocx/msscript.c | 8 +++- dlls/msscript.ocx/tests/msscript.c | 67 ++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 2 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index 94d6dda..3fc4aca 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -1760,8 +1760,12 @@ static HRESULT WINAPI ScriptControl_get_Error(IScriptControl *iface, IScriptErro static HRESULT WINAPI ScriptControl_get_CodeObject(IScriptControl *iface, IDispatch **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_CodeObject(&This->modules[0]->IScriptModule_iface, p); }
static HRESULT WINAPI ScriptControl_get_Procedures(IScriptControl *iface, IScriptProcedureCollection **p) diff --git a/dlls/msscript.ocx/tests/msscript.c b/dlls/msscript.ocx/tests/msscript.c index 90f6d19..352bf78 100644 --- a/dlls/msscript.ocx/tests/msscript.c +++ b/dlls/msscript.ocx/tests/msscript.c @@ -2883,6 +2883,72 @@ static void test_IScriptControl_get_Modules(void) } }
+static void test_IScriptControl_get_CodeObject(void) +{ + IScriptControl *sc; + IDispatch *disp; + HRESULT hr; + BSTR str; + + 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_CodeObject(sc, &disp); + ok(hr == E_FAIL, "IScriptControl_get_CodeObject 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_CodeObject(sc, &disp); + ok(hr == S_OK, "IScriptControl_get_CodeObject failed: 0x%08x.\n", hr); + + IDispatch_Release(disp); + 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); + + GetScriptDispatch_expected_name = NULL; + SET_EXPECT(SetScriptState_STARTED); + SET_EXPECT(GetScriptDispatch); + hr = IScriptControl_get_CodeObject(sc, &disp); + ok(hr == S_OK, "IScriptControl_get_CodeObject failed: 0x%08x.\n", hr); + ok(disp == (IDispatch*)&DispatchEx, "unexpected code object %p\n", disp); + CHECK_CALLED(GetScriptDispatch); + CHECK_CALLED(SetScriptState_STARTED); + + IDispatch_Release(disp); + IActiveScriptSite_Release(site); + + SET_EXPECT(Close); + IScriptControl_Release(sc); + CHECK_CALLED(Close); + } +} + START_TEST(msscript) { IUnknown *unk; @@ -2921,6 +2987,7 @@ START_TEST(msscript) test_IScriptControl_ExecuteStatement(); test_IScriptControl_Run(); test_IScriptControl_get_Modules(); + test_IScriptControl_get_CodeObject();
init_registry(FALSE);
Signed-off-by: Jacek Caban jacek@codeweavers.com