scrrun: Implement IEnumVARIANT support for dictionary.

This commit is contained in:
Nikolay Sivov 2015-03-18 15:11:32 +03:00 committed by Alexandre Julliard
parent 77432ac45d
commit ba48217429
2 changed files with 188 additions and 8 deletions

View File

@ -71,6 +71,7 @@ typedef struct
LONG count;
struct list pairs;
struct list buckets[BUCKET_COUNT];
struct list notifier;
} dictionary;
struct dictionary_enum {
@ -78,6 +79,8 @@ struct dictionary_enum {
LONG ref;
dictionary *dict;
struct list *cur;
struct list notify;
};
static inline dictionary *impl_from_IDictionary(IDictionary *iface)
@ -248,6 +251,7 @@ static ULONG WINAPI dict_enum_Release(IEnumVARIANT *iface)
ref = InterlockedDecrement(&This->ref);
if(ref == 0) {
list_remove(&This->notify);
IDictionary_Release(&This->dict->IDictionary_iface);
heap_free(This);
}
@ -258,29 +262,67 @@ static ULONG WINAPI dict_enum_Release(IEnumVARIANT *iface)
static HRESULT WINAPI dict_enum_Next(IEnumVARIANT *iface, ULONG count, VARIANT *keys, ULONG *fetched)
{
struct dictionary_enum *This = impl_from_IEnumVARIANT(iface);
FIXME("(%p)->(%u %p %p): stub\n", This, count, keys, fetched);
return E_NOTIMPL;
struct keyitem_pair *pair;
ULONG i = 0;
TRACE("(%p)->(%u %p %p)\n", This, count, keys, fetched);
if (fetched)
*fetched = 0;
if (!count)
return S_OK;
while (This->cur && i < count) {
pair = LIST_ENTRY(This->cur, struct keyitem_pair, entry);
VariantCopy(&keys[i], &pair->key);
This->cur = list_next(&This->dict->pairs, This->cur);
i++;
}
if (fetched)
*fetched = i;
return i < count ? S_FALSE : S_OK;
}
static HRESULT WINAPI dict_enum_Skip(IEnumVARIANT *iface, ULONG count)
{
struct dictionary_enum *This = impl_from_IEnumVARIANT(iface);
FIXME("(%p)->(%u): stub\n", This, count);
return E_NOTIMPL;
TRACE("(%p)->(%u)\n", This, count);
if (!count)
return S_OK;
if (!This->cur)
return S_FALSE;
while (count--) {
This->cur = list_next(&This->dict->pairs, This->cur);
if (!This->cur) break;
}
return count == 0 ? S_OK : S_FALSE;
}
static HRESULT WINAPI dict_enum_Reset(IEnumVARIANT *iface)
{
struct dictionary_enum *This = impl_from_IEnumVARIANT(iface);
FIXME("(%p): stub\n", This);
return E_NOTIMPL;
TRACE("(%p)\n", This);
This->cur = list_head(&This->dict->pairs);
return S_OK;
}
static HRESULT create_dict_enum(dictionary*, IUnknown**);
static HRESULT WINAPI dict_enum_Clone(IEnumVARIANT *iface, IEnumVARIANT **cloned)
{
struct dictionary_enum *This = impl_from_IEnumVARIANT(iface);
FIXME("(%p)->(%p): stub\n", This, cloned);
return E_NOTIMPL;
TRACE("(%p)->(%p)\n", This, cloned);
return create_dict_enum(This->dict, (IUnknown**)cloned);
}
static const IEnumVARIANTVtbl dictenumvtbl = {
@ -305,6 +347,8 @@ static HRESULT create_dict_enum(dictionary *dict, IUnknown **ret)
This->IEnumVARIANT_iface.lpVtbl = &dictenumvtbl;
This->ref = 1;
This->cur = list_head(&dict->pairs);
list_add_tail(&dict->notifier, &This->notify);
This->dict = dict;
IDictionary_AddRef(&dict->IDictionary_iface);
@ -312,6 +356,21 @@ static HRESULT create_dict_enum(dictionary *dict, IUnknown **ret)
return S_OK;
}
static void notify_remove_pair(struct list *notifier, struct list *pair)
{
struct dictionary_enum *dict_enum;
struct list *cur;
LIST_FOR_EACH(cur, notifier) {
dict_enum = LIST_ENTRY(cur, struct dictionary_enum, notify);
if (!pair)
dict_enum->cur = list_head(&dict_enum->dict->pairs);
else if (dict_enum->cur == pair) {
dict_enum->cur = list_next(&dict_enum->dict->pairs, dict_enum->cur);
}
}
}
static HRESULT WINAPI dictionary_QueryInterface(IDictionary *iface, REFIID riid, void **obj)
{
dictionary *This = impl_from_IDictionary(iface);
@ -616,6 +675,7 @@ static HRESULT WINAPI dictionary_Remove(IDictionary *iface, VARIANT *key)
if (!(pair = get_keyitem_pair(This, key)))
return CTL_E_ELEMENT_NOT_FOUND;
notify_remove_pair(&This->notifier, &pair->entry);
list_remove(&pair->entry);
list_remove(&pair->bucket);
This->count--;
@ -634,6 +694,7 @@ static HRESULT WINAPI dictionary_RemoveAll(IDictionary *iface)
if (This->count == 0)
return S_OK;
notify_remove_pair(&This->notifier, NULL);
LIST_FOR_EACH_ENTRY_SAFE(pair, pair2, &This->pairs, struct keyitem_pair, entry) {
list_remove(&pair->entry);
list_remove(&pair->bucket);
@ -796,6 +857,7 @@ HRESULT WINAPI Dictionary_CreateInstance(IClassFactory *factory,IUnknown *outer,
This->method = BinaryCompare;
This->count = 0;
list_init(&This->pairs);
list_init(&This->notifier);
memset(This->buckets, 0, sizeof(This->buckets));
*obj = &This->IDictionary_iface;

View File

@ -618,6 +618,123 @@ static void test_Add(void)
IDictionary_Release(dict);
}
static void test_IEnumVARIANT(void)
{
IUnknown *enum1, *enum2;
IEnumVARIANT *enumvar;
VARIANT key, item;
IDictionary *dict;
ULONG fetched;
HRESULT hr;
hr = CoCreateInstance(&CLSID_Dictionary, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
&IID_IDictionary, (void**)&dict);
ok(hr == S_OK, "got 0x%08x\n", hr);
if (0) /* crashes on native */
hr = IDictionary__NewEnum(dict, NULL);
hr = IDictionary__NewEnum(dict, &enum1);
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IDictionary__NewEnum(dict, &enum2);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(enum1 != enum2, "got %p, %p\n", enum2, enum1);
IUnknown_Release(enum2);
hr = IUnknown_QueryInterface(enum1, &IID_IEnumVARIANT, (void**)&enumvar);
ok(hr == S_OK, "got 0x%08x\n", hr);
IUnknown_Release(enum1);
/* dictionary is empty */
hr = IEnumVARIANT_Skip(enumvar, 1);
ok(hr == S_FALSE, "got 0x%08x\n", hr);
hr = IEnumVARIANT_Skip(enumvar, 0);
ok(hr == S_OK, "got 0x%08x\n", hr);
V_VT(&key) = VT_I2;
V_I2(&key) = 1;
V_VT(&item) = VT_I4;
V_I4(&item) = 100;
hr = IDictionary_Add(dict, &key, &item);
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IEnumVARIANT_Skip(enumvar, 0);
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IEnumVARIANT_Reset(enumvar);
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IEnumVARIANT_Skip(enumvar, 1);
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IEnumVARIANT_Skip(enumvar, 1);
ok(hr == S_FALSE, "got 0x%08x\n", hr);
V_VT(&key) = VT_I2;
V_I2(&key) = 4000;
V_VT(&item) = VT_I4;
V_I4(&item) = 200;
hr = IDictionary_Add(dict, &key, &item);
ok(hr == S_OK, "got 0x%08x\n", hr);
V_VT(&key) = VT_I2;
V_I2(&key) = 0;
V_VT(&item) = VT_I4;
V_I4(&item) = 300;
hr = IDictionary_Add(dict, &key, &item);
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IEnumVARIANT_Reset(enumvar);
ok(hr == S_OK, "got 0x%08x\n", hr);
VariantInit(&key);
hr = IEnumVARIANT_Next(enumvar, 1, &key, &fetched);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(V_VT(&key) == VT_I2, "got %d\n", V_VT(&key));
ok(V_I2(&key) == 1, "got %d\n", V_I2(&key));
ok(fetched == 1, "got %u\n", fetched);
hr = IEnumVARIANT_Reset(enumvar);
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IDictionary_Remove(dict, &key);
ok(hr == S_OK, "got 0x%08x\n", hr);
VariantInit(&key);
hr = IEnumVARIANT_Next(enumvar, 1, &key, &fetched);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(V_VT(&key) == VT_I2, "got %d\n", V_VT(&key));
ok(V_I2(&key) == 4000, "got %d\n", V_I2(&key));
ok(fetched == 1, "got %u\n", fetched);
VariantInit(&key);
hr = IEnumVARIANT_Next(enumvar, 1, &key, &fetched);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(V_VT(&key) == VT_I2, "got %d\n", V_VT(&key));
ok(V_I2(&key) == 0, "got %d\n", V_I2(&key));
ok(fetched == 1, "got %u\n", fetched);
/* enumeration reached the bottom, add one more pair */
VariantInit(&key);
hr = IEnumVARIANT_Next(enumvar, 1, &key, &fetched);
ok(hr == S_FALSE, "got 0x%08x\n", hr);
V_VT(&key) = VT_I2;
V_I2(&key) = 13;
V_VT(&item) = VT_I4;
V_I4(&item) = 350;
hr = IDictionary_Add(dict, &key, &item);
ok(hr == S_OK, "got 0x%08x\n", hr);
/* still doesn't work until Reset() */
VariantInit(&key);
hr = IEnumVARIANT_Next(enumvar, 1, &key, &fetched);
ok(hr == S_FALSE, "got 0x%08x\n", hr);
IEnumVARIANT_Release(enumvar);
IDictionary_Release(dict);
}
START_TEST(dictionary)
{
IDispatch *disp;
@ -642,6 +759,7 @@ START_TEST(dictionary)
test_Remove();
test_Item();
test_Add();
test_IEnumVARIANT();
CoUninitialize();
}