msscript.ocx: Implement the ScriptProcedure enumerator.
Signed-off-by: Gabriel Ivăncescu <gabrielopcode@gmail.com> Signed-off-by: Jacek Caban <jacek@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
6e0e890fba
commit
3a9c50e3ff
|
@ -110,6 +110,15 @@ struct ScriptProcedureCollection {
|
|||
struct list hash_table[43];
|
||||
};
|
||||
|
||||
struct procedure_enum {
|
||||
IEnumVARIANT IEnumVARIANT_iface;
|
||||
LONG ref;
|
||||
|
||||
WORD pos;
|
||||
WORD count;
|
||||
ScriptProcedureCollection *procedures;
|
||||
};
|
||||
|
||||
struct ScriptHost {
|
||||
IActiveScriptSite IActiveScriptSite_iface;
|
||||
IActiveScriptSiteWindow IActiveScriptSiteWindow_iface;
|
||||
|
@ -532,6 +541,11 @@ static inline struct module_enum *module_enum_from_IEnumVARIANT(IEnumVARIANT *if
|
|||
return CONTAINING_RECORD(iface, struct module_enum, IEnumVARIANT_iface);
|
||||
}
|
||||
|
||||
static inline struct procedure_enum *procedure_enum_from_IEnumVARIANT(IEnumVARIANT *iface)
|
||||
{
|
||||
return CONTAINING_RECORD(iface, struct procedure_enum, IEnumVARIANT_iface);
|
||||
}
|
||||
|
||||
/* IActiveScriptSite */
|
||||
static HRESULT WINAPI ActiveScriptSite_QueryInterface(IActiveScriptSite *iface, REFIID riid, void **ppv)
|
||||
{
|
||||
|
@ -976,6 +990,151 @@ done:
|
|||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI procedure_enum_QueryInterface(IEnumVARIANT *iface, REFIID riid, void **ppv)
|
||||
{
|
||||
struct procedure_enum *This = procedure_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 procedure_enum_AddRef(IEnumVARIANT *iface)
|
||||
{
|
||||
struct procedure_enum *This = procedure_enum_from_IEnumVARIANT(iface);
|
||||
LONG ref = InterlockedIncrement(&This->ref);
|
||||
|
||||
TRACE("(%p) ref=%d\n", This, ref);
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
static ULONG WINAPI procedure_enum_Release(IEnumVARIANT *iface)
|
||||
{
|
||||
struct procedure_enum *This = procedure_enum_from_IEnumVARIANT(iface);
|
||||
LONG ref = InterlockedDecrement(&This->ref);
|
||||
|
||||
TRACE("(%p) ref=%d\n", This, ref);
|
||||
|
||||
if (!ref)
|
||||
{
|
||||
IScriptProcedureCollection_Release(&This->procedures->IScriptProcedureCollection_iface);
|
||||
heap_free(This);
|
||||
}
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI procedure_enum_Next(IEnumVARIANT *iface, ULONG celt, VARIANT *rgVar, ULONG *pCeltFetched)
|
||||
{
|
||||
struct procedure_enum *This = procedure_enum_from_IEnumVARIANT(iface);
|
||||
FUNCDESC *desc;
|
||||
ITypeInfo *ti;
|
||||
UINT i, num;
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("(%p)->(%u %p %p)\n", This, celt, rgVar, pCeltFetched);
|
||||
|
||||
if (!rgVar) return E_POINTER;
|
||||
if (!This->procedures->module->host) return E_FAIL;
|
||||
|
||||
hr = start_script(This->procedures->module->host);
|
||||
if (FAILED(hr)) return hr;
|
||||
|
||||
hr = get_script_typeinfo(This->procedures->module, &ti);
|
||||
if (FAILED(hr)) return hr;
|
||||
|
||||
num = min(celt, This->count - This->pos);
|
||||
for (i = 0; i < num; i++)
|
||||
{
|
||||
hr = ITypeInfo_GetFuncDesc(ti, This->pos + i, &desc);
|
||||
if (FAILED(hr)) break;
|
||||
|
||||
hr = get_script_procedure(This->procedures, ti, desc, (IScriptProcedure**)&V_DISPATCH(rgVar + i));
|
||||
if (FAILED(hr)) break;
|
||||
|
||||
V_VT(rgVar + i) = VT_DISPATCH;
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
while (i--)
|
||||
VariantClear(rgVar + i);
|
||||
if (pCeltFetched) *pCeltFetched = 0;
|
||||
return hr;
|
||||
}
|
||||
|
||||
This->pos += i;
|
||||
|
||||
if (pCeltFetched) *pCeltFetched = i;
|
||||
return i == celt ? S_OK : S_FALSE;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI procedure_enum_Skip(IEnumVARIANT *iface, ULONG celt)
|
||||
{
|
||||
struct procedure_enum *This = procedure_enum_from_IEnumVARIANT(iface);
|
||||
|
||||
TRACE("(%p)->(%u)\n", This, celt);
|
||||
|
||||
if (This->count - This->pos < celt)
|
||||
{
|
||||
This->pos = This->count;
|
||||
return S_FALSE;
|
||||
}
|
||||
This->pos += celt;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI procedure_enum_Reset(IEnumVARIANT *iface)
|
||||
{
|
||||
struct procedure_enum *This = procedure_enum_from_IEnumVARIANT(iface);
|
||||
|
||||
TRACE("(%p)\n", This);
|
||||
|
||||
This->pos = 0;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI procedure_enum_Clone(IEnumVARIANT *iface, IEnumVARIANT **ppEnum)
|
||||
{
|
||||
struct procedure_enum *This = procedure_enum_from_IEnumVARIANT(iface);
|
||||
struct procedure_enum *clone;
|
||||
|
||||
TRACE("(%p)->(%p)\n", This, ppEnum);
|
||||
|
||||
if (!ppEnum) return E_POINTER;
|
||||
|
||||
if (!(clone = heap_alloc(sizeof(*clone))))
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
*clone = *This;
|
||||
clone->ref = 1;
|
||||
IScriptProcedureCollection_AddRef(&This->procedures->IScriptProcedureCollection_iface);
|
||||
|
||||
*ppEnum = &clone->IEnumVARIANT_iface;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static const IEnumVARIANTVtbl procedure_enum_vtbl = {
|
||||
procedure_enum_QueryInterface,
|
||||
procedure_enum_AddRef,
|
||||
procedure_enum_Release,
|
||||
procedure_enum_Next,
|
||||
procedure_enum_Skip,
|
||||
procedure_enum_Reset,
|
||||
procedure_enum_Clone
|
||||
};
|
||||
|
||||
static HRESULT WINAPI ScriptProcedureCollection_QueryInterface(IScriptProcedureCollection *iface, REFIID riid, void **ppv)
|
||||
{
|
||||
ScriptProcedureCollection *This = impl_from_IScriptProcedureCollection(iface);
|
||||
|
@ -1091,10 +1250,41 @@ static HRESULT WINAPI ScriptProcedureCollection_Invoke(IScriptProcedureCollectio
|
|||
static HRESULT WINAPI ScriptProcedureCollection_get__NewEnum(IScriptProcedureCollection *iface, IUnknown **ppenumProcedures)
|
||||
{
|
||||
ScriptProcedureCollection *This = impl_from_IScriptProcedureCollection(iface);
|
||||
struct procedure_enum *proc_enum;
|
||||
TYPEATTR *attr;
|
||||
ITypeInfo *ti;
|
||||
UINT count;
|
||||
HRESULT hr;
|
||||
|
||||
FIXME("(%p)->(%p)\n", This, ppenumProcedures);
|
||||
TRACE("(%p)->(%p)\n", This, ppenumProcedures);
|
||||
|
||||
return E_NOTIMPL;
|
||||
if (!ppenumProcedures) 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, &ti);
|
||||
if (FAILED(hr)) return hr;
|
||||
|
||||
hr = ITypeInfo_GetTypeAttr(ti, &attr);
|
||||
if (FAILED(hr)) return hr;
|
||||
|
||||
count = attr->cFuncs;
|
||||
ITypeInfo_ReleaseTypeAttr(ti, attr);
|
||||
|
||||
if (!(proc_enum = heap_alloc(sizeof(*proc_enum))))
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
proc_enum->IEnumVARIANT_iface.lpVtbl = &procedure_enum_vtbl;
|
||||
proc_enum->ref = 1;
|
||||
proc_enum->pos = 0;
|
||||
proc_enum->count = count;
|
||||
proc_enum->procedures = This;
|
||||
IScriptProcedureCollection_AddRef(&This->IScriptProcedureCollection_iface);
|
||||
|
||||
*ppenumProcedures = (IUnknown*)&proc_enum->IEnumVARIANT_iface;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI ScriptProcedureCollection_get_Item(IScriptProcedureCollection *iface, VARIANT index,
|
||||
|
|
|
@ -3293,9 +3293,12 @@ static void test_IScriptControl_get_CodeObject(void)
|
|||
static void test_IScriptControl_get_Procedures(void)
|
||||
{
|
||||
IScriptProcedureCollection *procs, *procs2;
|
||||
IEnumVARIANT *enumvar, *enumvar2;
|
||||
IScriptProcedure *proc, *proc2;
|
||||
IScriptControl *sc;
|
||||
IUnknown *unknown;
|
||||
VARIANT_BOOL vbool;
|
||||
ULONG fetched;
|
||||
VARIANT var;
|
||||
LONG count;
|
||||
HRESULT hr;
|
||||
|
@ -3548,6 +3551,44 @@ static void test_IScriptControl_get_Procedures(void)
|
|||
ok(hr == E_INVALIDARG, "IScriptProcedureCollection_get_Item returned: 0x%08x.\n", hr);
|
||||
CHECK_CALLED(GetFuncDesc);
|
||||
|
||||
/* _NewEnum never caches the function count */
|
||||
hr = IScriptProcedureCollection_get__NewEnum(procs, NULL);
|
||||
ok(hr == E_POINTER, "IScriptProcedureCollection_get__NewEnum returned: 0x%08x.\n", hr);
|
||||
SET_EXPECT(GetTypeAttr);
|
||||
SET_EXPECT(ReleaseTypeAttr);
|
||||
hr = IScriptProcedureCollection_get__NewEnum(procs, &unknown);
|
||||
ok(hr == S_OK, "IScriptProcedureCollection_get__NewEnum failed: 0x%08x.\n", hr);
|
||||
CHECK_CALLED(GetTypeAttr);
|
||||
CHECK_CALLED(ReleaseTypeAttr);
|
||||
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);
|
||||
IEnumVARIANT_Release(enumvar);
|
||||
IUnknown_Release(unknown);
|
||||
SET_EXPECT(GetTypeAttr);
|
||||
SET_EXPECT(ReleaseTypeAttr);
|
||||
hr = IScriptProcedureCollection_get__NewEnum(procs, &unknown);
|
||||
ok(hr == S_OK, "IScriptProcedureCollection_get__NewEnum failed: 0x%08x.\n", hr);
|
||||
CHECK_CALLED(GetTypeAttr);
|
||||
CHECK_CALLED(ReleaseTypeAttr);
|
||||
hr = IUnknown_QueryInterface(unknown, &IID_IEnumVARIANT, (void**)&enumvar);
|
||||
ok(hr == S_OK, "Failed to query for IEnumVARIANT: 0x%08x.\n", hr);
|
||||
IUnknown_Release(unknown);
|
||||
|
||||
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);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(custom_engine_funcs); i++)
|
||||
{
|
||||
/* Querying by index still goes through the Bind process */
|
||||
|
@ -3583,6 +3624,25 @@ static void test_IScriptControl_get_Procedures(void)
|
|||
CHECK_CALLED(GetNames);
|
||||
CHECK_CALLED(ReleaseFuncDesc);
|
||||
|
||||
/* Compare with the enumerator */
|
||||
SET_EXPECT(GetFuncDesc);
|
||||
SET_EXPECT(GetNames);
|
||||
SET_EXPECT(ReleaseFuncDesc);
|
||||
hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched);
|
||||
ok(hr == S_OK, "IEnumVARIANT_Next for index %u failed: 0x%08x.\n", i, hr);
|
||||
ok(fetched == 1, "got %u.\n", fetched);
|
||||
ok(V_VT(&var) == VT_DISPATCH, "V_VT(var) = %d.\n", V_VT(&var));
|
||||
CHECK_CALLED(GetFuncDesc);
|
||||
CHECK_CALLED(GetNames);
|
||||
CHECK_CALLED(ReleaseFuncDesc);
|
||||
hr = IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IScriptProcedure, (void**)&proc2);
|
||||
ok(hr == S_OK, "Failed to query IScriptProcedure for index %u: 0x%08x.\n", i, hr);
|
||||
VariantClear(&var);
|
||||
|
||||
ok(proc == proc2, "proc and proc2 are not the same for %s and enum index %u.\n",
|
||||
wine_dbgstr_w(custom_engine_funcs[i].name), i);
|
||||
IScriptProcedure_Release(proc2);
|
||||
|
||||
/* 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);
|
||||
|
@ -3601,6 +3661,26 @@ static void test_IScriptControl_get_Procedures(void)
|
|||
IScriptProcedure_Release(proc);
|
||||
}
|
||||
|
||||
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_Reset(enumvar);
|
||||
ok(hr == S_OK, "IEnumVARIANT_Reset failed: 0x%08x.\n", hr);
|
||||
hr = IEnumVARIANT_Skip(enumvar, ARRAY_SIZE(custom_engine_funcs) - 1);
|
||||
ok(hr == S_OK, "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_OK, "IEnumVARIANT_Skip failed: 0x%08x.\n", hr);
|
||||
hr = IEnumVARIANT_Skip(enumvar2, 1);
|
||||
ok(hr == S_FALSE, "IEnumVARIANT_Skip failed: 0x%08x.\n", hr);
|
||||
|
||||
IEnumVARIANT_Release(enumvar2);
|
||||
IEnumVARIANT_Release(enumvar);
|
||||
IScriptProcedureCollection_Release(procs);
|
||||
IActiveScriptSite_Release(site);
|
||||
|
||||
|
|
Loading…
Reference in New Issue