2 * Copyright (C) 2012 Alistair Leslie-Hughes
3 * Copyright 2015 Nikolay Sivov for CodeWeavers
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "wine/port.h"
32 #include "scrrun_private.h"
34 #include "wine/debug.h"
35 #include "wine/unicode.h"
36 #include "wine/list.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(scrrun
);
40 #define BUCKET_COUNT 509
41 #define DICT_HASH_MOD 1201
43 /* Implementation details
45 Dictionary contains one list that links all pairs, this way
46 order in which they were added is preserved. Each bucket has
47 its own list to hold all pairs in this bucket. Initially all
48 bucket lists are zeroed and we init them once we about to add
51 When pair is removed it's unlinked from both lists; if it was
52 a last pair in a bucket list it stays empty in initialized state.
54 Preserving pair order is important for enumeration, so far testing
55 indicates that pairs are not reordered basing on hash value.
68 IDictionary IDictionary_iface
;
74 struct list buckets
[BUCKET_COUNT
];
78 struct dictionary_enum
{
79 IEnumVARIANT IEnumVARIANT_iface
;
87 static inline dictionary
*impl_from_IDictionary(IDictionary
*iface
)
89 return CONTAINING_RECORD(iface
, dictionary
, IDictionary_iface
);
92 static inline struct dictionary_enum
*impl_from_IEnumVARIANT(IEnumVARIANT
*iface
)
94 return CONTAINING_RECORD(iface
, struct dictionary_enum
, IEnumVARIANT_iface
);
97 static inline struct list
*get_bucket_head(dictionary
*dict
, DWORD hash
)
99 return &dict
->buckets
[hash
% BUCKET_COUNT
];
102 static inline BOOL
is_string_key(const VARIANT
*key
)
104 return V_VT(key
) == VT_BSTR
|| V_VT(key
) == (VT_BSTR
|VT_BYREF
);
107 /* Only for VT_BSTR or VT_BSTR|VT_BYREF types */
108 static inline WCHAR
*get_key_strptr(const VARIANT
*key
)
110 if (V_VT(key
) == VT_BSTR
)
114 return *V_BSTRREF(key
);
119 /* should be used only when both keys are of string type, it's not checked */
120 static inline int strcmp_key(const dictionary
*dict
, const VARIANT
*key1
, const VARIANT
*key2
)
122 const WCHAR
*str1
, *str2
;
124 str1
= get_key_strptr(key1
);
125 str2
= get_key_strptr(key2
);
126 return dict
->method
== BinaryCompare
? strcmpW(str1
, str2
) : strcmpiW(str1
, str2
);
129 static BOOL
is_matching_key(const dictionary
*dict
, const struct keyitem_pair
*pair
, const VARIANT
*key
, DWORD hash
)
131 if (is_string_key(key
) && is_string_key(&pair
->key
)) {
132 if (hash
!= pair
->hash
)
135 return strcmp_key(dict
, key
, &pair
->key
) == 0;
138 if ((is_string_key(key
) && !is_string_key(&pair
->key
)) ||
139 (!is_string_key(key
) && is_string_key(&pair
->key
)))
142 /* for numeric keys only check hash */
143 return hash
== pair
->hash
;
146 static struct keyitem_pair
*get_keyitem_pair(dictionary
*dict
, VARIANT
*key
)
148 struct keyitem_pair
*pair
;
149 struct list
*head
, *entry
;
153 hr
= IDictionary_get_HashVal(&dict
->IDictionary_iface
, key
, &hash
);
157 head
= get_bucket_head(dict
, V_I4(&hash
));
158 if (!head
->next
|| list_empty(head
))
161 entry
= list_head(head
);
163 pair
= LIST_ENTRY(entry
, struct keyitem_pair
, bucket
);
164 if (is_matching_key(dict
, pair
, key
, V_I4(&hash
))) return pair
;
165 } while ((entry
= list_next(head
, entry
)));
170 static HRESULT
add_keyitem_pair(dictionary
*dict
, VARIANT
*key
, VARIANT
*item
)
172 struct keyitem_pair
*pair
;
177 hr
= IDictionary_get_HashVal(&dict
->IDictionary_iface
, key
, &hash
);
181 pair
= heap_alloc(sizeof(*pair
));
183 return E_OUTOFMEMORY
;
185 pair
->hash
= V_I4(&hash
);
186 VariantInit(&pair
->key
);
187 VariantInit(&pair
->item
);
189 hr
= VariantCopyInd(&pair
->key
, key
);
193 hr
= VariantCopyInd(&pair
->item
, item
);
197 head
= get_bucket_head(dict
, pair
->hash
);
199 /* this only happens once per bucket */
202 /* link to bucket list and to full list */
203 list_add_tail(head
, &pair
->bucket
);
204 list_add_tail(&dict
->pairs
, &pair
->entry
);
209 VariantClear(&pair
->key
);
210 VariantClear(&pair
->item
);
215 static void free_keyitem_pair(struct keyitem_pair
*pair
)
217 VariantClear(&pair
->key
);
218 VariantClear(&pair
->item
);
222 static HRESULT WINAPI
dict_enum_QueryInterface(IEnumVARIANT
*iface
, REFIID riid
, void **obj
)
224 struct dictionary_enum
*This
= impl_from_IEnumVARIANT(iface
);
226 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), obj
);
228 if (IsEqualIID(riid
, &IID_IEnumVARIANT
) || IsEqualIID(riid
, &IID_IUnknown
)) {
230 IEnumVARIANT_AddRef(iface
);
234 WARN("interface not supported %s\n", debugstr_guid(riid
));
236 return E_NOINTERFACE
;
240 static ULONG WINAPI
dict_enum_AddRef(IEnumVARIANT
*iface
)
242 struct dictionary_enum
*This
= impl_from_IEnumVARIANT(iface
);
243 TRACE("(%p)\n", This
);
244 return InterlockedIncrement(&This
->ref
);
247 static ULONG WINAPI
dict_enum_Release(IEnumVARIANT
*iface
)
249 struct dictionary_enum
*This
= impl_from_IEnumVARIANT(iface
);
252 TRACE("(%p)\n", This
);
254 ref
= InterlockedDecrement(&This
->ref
);
256 list_remove(&This
->notify
);
257 IDictionary_Release(&This
->dict
->IDictionary_iface
);
264 static HRESULT WINAPI
dict_enum_Next(IEnumVARIANT
*iface
, ULONG count
, VARIANT
*keys
, ULONG
*fetched
)
266 struct dictionary_enum
*This
= impl_from_IEnumVARIANT(iface
);
267 struct keyitem_pair
*pair
;
270 TRACE("(%p)->(%u %p %p)\n", This
, count
, keys
, fetched
);
278 while (This
->cur
&& i
< count
) {
279 pair
= LIST_ENTRY(This
->cur
, struct keyitem_pair
, entry
);
280 VariantCopy(&keys
[i
], &pair
->key
);
281 This
->cur
= list_next(&This
->dict
->pairs
, This
->cur
);
288 return i
< count
? S_FALSE
: S_OK
;
291 static HRESULT WINAPI
dict_enum_Skip(IEnumVARIANT
*iface
, ULONG count
)
293 struct dictionary_enum
*This
= impl_from_IEnumVARIANT(iface
);
295 TRACE("(%p)->(%u)\n", This
, count
);
304 This
->cur
= list_next(&This
->dict
->pairs
, This
->cur
);
305 if (!This
->cur
) break;
308 return count
== 0 ? S_OK
: S_FALSE
;
311 static HRESULT WINAPI
dict_enum_Reset(IEnumVARIANT
*iface
)
313 struct dictionary_enum
*This
= impl_from_IEnumVARIANT(iface
);
315 TRACE("(%p)\n", This
);
317 This
->cur
= list_head(&This
->dict
->pairs
);
321 static HRESULT
create_dict_enum(dictionary
*, IUnknown
**);
323 static HRESULT WINAPI
dict_enum_Clone(IEnumVARIANT
*iface
, IEnumVARIANT
**cloned
)
325 struct dictionary_enum
*This
= impl_from_IEnumVARIANT(iface
);
326 TRACE("(%p)->(%p)\n", This
, cloned
);
327 return create_dict_enum(This
->dict
, (IUnknown
**)cloned
);
330 static const IEnumVARIANTVtbl dictenumvtbl
= {
331 dict_enum_QueryInterface
,
340 static HRESULT
create_dict_enum(dictionary
*dict
, IUnknown
**ret
)
342 struct dictionary_enum
*This
;
346 This
= heap_alloc(sizeof(*This
));
348 return E_OUTOFMEMORY
;
350 This
->IEnumVARIANT_iface
.lpVtbl
= &dictenumvtbl
;
352 This
->cur
= list_head(&dict
->pairs
);
353 list_add_tail(&dict
->notifier
, &This
->notify
);
355 IDictionary_AddRef(&dict
->IDictionary_iface
);
357 *ret
= (IUnknown
*)&This
->IEnumVARIANT_iface
;
361 static void notify_remove_pair(struct list
*notifier
, struct list
*pair
)
363 struct dictionary_enum
*dict_enum
;
366 LIST_FOR_EACH(cur
, notifier
) {
367 dict_enum
= LIST_ENTRY(cur
, struct dictionary_enum
, notify
);
369 dict_enum
->cur
= list_head(&dict_enum
->dict
->pairs
);
370 else if (dict_enum
->cur
== pair
) {
371 dict_enum
->cur
= list_next(&dict_enum
->dict
->pairs
, dict_enum
->cur
);
376 static HRESULT WINAPI
dictionary_QueryInterface(IDictionary
*iface
, REFIID riid
, void **obj
)
378 dictionary
*This
= impl_from_IDictionary(iface
);
379 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), obj
);
383 if(IsEqualIID(riid
, &IID_IUnknown
) ||
384 IsEqualIID(riid
, &IID_IDispatch
) ||
385 IsEqualIID(riid
, &IID_IDictionary
))
387 *obj
= &This
->IDictionary_iface
;
389 else if ( IsEqualGUID( riid
, &IID_IDispatchEx
))
391 TRACE("Interface IDispatchEx not supported - returning NULL\n");
393 return E_NOINTERFACE
;
395 else if ( IsEqualGUID( riid
, &IID_IObjectWithSite
))
397 TRACE("Interface IObjectWithSite not supported - returning NULL\n");
399 return E_NOINTERFACE
;
403 WARN("interface %s not implemented\n", debugstr_guid(riid
));
404 return E_NOINTERFACE
;
407 IDictionary_AddRef(iface
);
411 static ULONG WINAPI
dictionary_AddRef(IDictionary
*iface
)
413 dictionary
*This
= impl_from_IDictionary(iface
);
414 TRACE("(%p)\n", This
);
416 return InterlockedIncrement(&This
->ref
);
419 static ULONG WINAPI
dictionary_Release(IDictionary
*iface
)
421 dictionary
*This
= impl_from_IDictionary(iface
);
424 TRACE("(%p)\n", This
);
426 ref
= InterlockedDecrement(&This
->ref
);
428 IDictionary_RemoveAll(iface
);
435 static HRESULT WINAPI
dictionary_GetTypeInfoCount(IDictionary
*iface
, UINT
*pctinfo
)
437 dictionary
*This
= impl_from_IDictionary(iface
);
439 TRACE("(%p)->()\n", This
);
445 static HRESULT WINAPI
dictionary_GetTypeInfo(IDictionary
*iface
, UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
447 dictionary
*This
= impl_from_IDictionary(iface
);
449 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
450 return get_typeinfo(IDictionary_tid
, ppTInfo
);
453 static HRESULT WINAPI
dictionary_GetIDsOfNames(IDictionary
*iface
, REFIID riid
, LPOLESTR
*rgszNames
,
454 UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
456 dictionary
*This
= impl_from_IDictionary(iface
);
460 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
462 hr
= get_typeinfo(IDictionary_tid
, &typeinfo
);
465 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
466 ITypeInfo_Release(typeinfo
);
472 static HRESULT WINAPI
dictionary_Invoke(IDictionary
*iface
, DISPID dispIdMember
, REFIID riid
,
473 LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
474 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
476 dictionary
*This
= impl_from_IDictionary(iface
);
480 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
481 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
483 hr
= get_typeinfo(IDictionary_tid
, &typeinfo
);
486 hr
= ITypeInfo_Invoke(typeinfo
, &This
->IDictionary_iface
, dispIdMember
, wFlags
,
487 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
488 ITypeInfo_Release(typeinfo
);
494 static HRESULT WINAPI
dictionary_putref_Item(IDictionary
*iface
, VARIANT
*Key
, VARIANT
*pRetItem
)
496 dictionary
*This
= impl_from_IDictionary(iface
);
498 FIXME("(%p)->(%p %p)\n", This
, Key
, pRetItem
);
503 static HRESULT WINAPI
dictionary_put_Item(IDictionary
*iface
, VARIANT
*key
, VARIANT
*item
)
505 dictionary
*This
= impl_from_IDictionary(iface
);
506 struct keyitem_pair
*pair
;
508 TRACE("(%p)->(%s %s)\n", This
, debugstr_variant(key
), debugstr_variant(item
));
510 if ((pair
= get_keyitem_pair(This
, key
)))
511 return VariantCopyInd(&pair
->item
, item
);
513 return IDictionary_Add(iface
, key
, item
);
516 static HRESULT WINAPI
dictionary_get_Item(IDictionary
*iface
, VARIANT
*key
, VARIANT
*item
)
518 dictionary
*This
= impl_from_IDictionary(iface
);
519 struct keyitem_pair
*pair
;
521 TRACE("(%p)->(%s %p)\n", This
, debugstr_variant(key
), item
);
523 if ((pair
= get_keyitem_pair(This
, key
)))
524 VariantCopy(item
, &pair
->item
);
527 return IDictionary_Add(iface
, key
, item
);
533 static HRESULT WINAPI
dictionary_Add(IDictionary
*iface
, VARIANT
*key
, VARIANT
*item
)
535 dictionary
*This
= impl_from_IDictionary(iface
);
537 TRACE("(%p)->(%s %s)\n", This
, debugstr_variant(key
), debugstr_variant(item
));
539 if (get_keyitem_pair(This
, key
))
540 return CTL_E_KEY_ALREADY_EXISTS
;
542 return add_keyitem_pair(This
, key
, item
);
545 static HRESULT WINAPI
dictionary_get_Count(IDictionary
*iface
, LONG
*count
)
547 dictionary
*This
= impl_from_IDictionary(iface
);
549 TRACE("(%p)->(%p)\n", This
, count
);
551 *count
= This
->count
;
555 static HRESULT WINAPI
dictionary_Exists(IDictionary
*iface
, VARIANT
*key
, VARIANT_BOOL
*exists
)
557 dictionary
*This
= impl_from_IDictionary(iface
);
559 TRACE("(%p)->(%s %p)\n", This
, debugstr_variant(key
), exists
);
562 return CTL_E_ILLEGALFUNCTIONCALL
;
564 *exists
= get_keyitem_pair(This
, key
) != NULL
? VARIANT_TRUE
: VARIANT_FALSE
;
568 static HRESULT WINAPI
dictionary_Items(IDictionary
*iface
, VARIANT
*items
)
570 dictionary
*This
= impl_from_IDictionary(iface
);
571 struct keyitem_pair
*pair
;
572 SAFEARRAYBOUND bound
;
578 TRACE("(%p)->(%p)\n", This
, items
);
584 bound
.cElements
= This
->count
;
585 sa
= SafeArrayCreate(VT_VARIANT
, 1, &bound
);
587 return E_OUTOFMEMORY
;
589 hr
= SafeArrayAccessData(sa
, (void**)&v
);
591 SafeArrayDestroy(sa
);
596 LIST_FOR_EACH_ENTRY(pair
, &This
->pairs
, struct keyitem_pair
, entry
) {
597 VariantCopy(&v
[i
], &pair
->item
);
600 SafeArrayUnaccessData(sa
);
602 V_VT(items
) = VT_ARRAY
|VT_VARIANT
;
607 static HRESULT WINAPI
dictionary_put_Key(IDictionary
*iface
, VARIANT
*key
, VARIANT
*newkey
)
609 dictionary
*This
= impl_from_IDictionary(iface
);
610 struct keyitem_pair
*pair
;
614 TRACE("(%p)->(%s %s)\n", This
, debugstr_variant(key
), debugstr_variant(newkey
));
616 if ((pair
= get_keyitem_pair(This
, key
))) {
617 /* found existing pair for a key, add new pair with new key
618 and old item and remove old pair after that */
620 hr
= IDictionary_Add(iface
, newkey
, &pair
->item
);
624 return IDictionary_Remove(iface
, key
);
628 return IDictionary_Add(iface
, newkey
, &empty
);
631 static HRESULT WINAPI
dictionary_Keys(IDictionary
*iface
, VARIANT
*keys
)
633 dictionary
*This
= impl_from_IDictionary(iface
);
634 struct keyitem_pair
*pair
;
635 SAFEARRAYBOUND bound
;
641 TRACE("(%p)->(%p)\n", This
, keys
);
647 bound
.cElements
= This
->count
;
648 sa
= SafeArrayCreate(VT_VARIANT
, 1, &bound
);
650 return E_OUTOFMEMORY
;
652 hr
= SafeArrayAccessData(sa
, (void**)&v
);
654 SafeArrayDestroy(sa
);
659 LIST_FOR_EACH_ENTRY(pair
, &This
->pairs
, struct keyitem_pair
, entry
) {
660 VariantCopy(&v
[i
], &pair
->key
);
663 SafeArrayUnaccessData(sa
);
665 V_VT(keys
) = VT_ARRAY
|VT_VARIANT
;
670 static HRESULT WINAPI
dictionary_Remove(IDictionary
*iface
, VARIANT
*key
)
672 dictionary
*This
= impl_from_IDictionary(iface
);
673 struct keyitem_pair
*pair
;
675 TRACE("(%p)->(%s)\n", This
, debugstr_variant(key
));
677 if (!(pair
= get_keyitem_pair(This
, key
)))
678 return CTL_E_ELEMENT_NOT_FOUND
;
680 notify_remove_pair(&This
->notifier
, &pair
->entry
);
681 list_remove(&pair
->entry
);
682 list_remove(&pair
->bucket
);
685 free_keyitem_pair(pair
);
689 static HRESULT WINAPI
dictionary_RemoveAll(IDictionary
*iface
)
691 dictionary
*This
= impl_from_IDictionary(iface
);
692 struct keyitem_pair
*pair
, *pair2
;
694 TRACE("(%p)\n", This
);
696 if (This
->count
== 0)
699 notify_remove_pair(&This
->notifier
, NULL
);
700 LIST_FOR_EACH_ENTRY_SAFE(pair
, pair2
, &This
->pairs
, struct keyitem_pair
, entry
) {
701 list_remove(&pair
->entry
);
702 list_remove(&pair
->bucket
);
703 free_keyitem_pair(pair
);
710 static HRESULT WINAPI
dictionary_put_CompareMode(IDictionary
*iface
, CompareMethod method
)
712 dictionary
*This
= impl_from_IDictionary(iface
);
714 TRACE("(%p)->(%d)\n", This
, method
);
717 return CTL_E_ILLEGALFUNCTIONCALL
;
719 This
->method
= method
;
723 static HRESULT WINAPI
dictionary_get_CompareMode(IDictionary
*iface
, CompareMethod
*method
)
725 dictionary
*This
= impl_from_IDictionary(iface
);
727 TRACE("(%p)->(%p)\n", This
, method
);
729 *method
= This
->method
;
733 static HRESULT WINAPI
dictionary__NewEnum(IDictionary
*iface
, IUnknown
**ret
)
735 dictionary
*This
= impl_from_IDictionary(iface
);
737 TRACE("(%p)->(%p)\n", This
, ret
);
739 return create_dict_enum(This
, ret
);
742 static DWORD
get_str_hash(const WCHAR
*str
, CompareMethod method
)
750 ch
= (method
== TextCompare
|| method
== DatabaseCompare
) ? tolowerW(*str
) : *str
;
752 hash
+= (hash
<< 4) + ch
;
757 return hash
% DICT_HASH_MOD
;
760 static DWORD
get_num_hash(FLOAT num
)
762 return (*((DWORD
*)&num
)) % DICT_HASH_MOD
;
765 static HRESULT
get_flt_hash(FLOAT flt
, LONG
*hash
)
771 else if (!isnan(flt
)) {
772 *hash
= get_num_hash(flt
);
778 return CTL_E_ILLEGALFUNCTIONCALL
;
781 static DWORD
get_ptr_hash(void *ptr
)
783 return PtrToUlong(ptr
) % DICT_HASH_MOD
;
786 static HRESULT WINAPI
dictionary_get_HashVal(IDictionary
*iface
, VARIANT
*key
, VARIANT
*hash
)
788 dictionary
*This
= impl_from_IDictionary(iface
);
790 TRACE("(%p)->(%s %p)\n", This
, debugstr_variant(key
), hash
);
795 case VT_BSTR
|VT_BYREF
:
797 V_I4(hash
) = get_str_hash(get_key_strptr(key
), This
->method
);
799 case VT_UI1
|VT_BYREF
:
801 V_I4(hash
) = get_num_hash(V_VT(key
) & VT_BYREF
? *V_UI1REF(key
) : V_UI1(key
));
805 V_I4(hash
) = get_num_hash(V_VT(key
) & VT_BYREF
? *V_I2REF(key
) : V_I2(key
));
809 V_I4(hash
) = get_num_hash(V_VT(key
) & VT_BYREF
? *V_I4REF(key
) : V_I4(key
));
811 case VT_UNKNOWN
|VT_BYREF
:
812 case VT_DISPATCH
|VT_BYREF
:
816 IUnknown
*src
= (V_VT(key
) & VT_BYREF
) ? *V_UNKNOWNREF(key
) : V_UNKNOWN(key
);
817 IUnknown
*unk
= NULL
;
824 IUnknown_QueryInterface(src
, &IID_IUnknown
, (void**)&unk
);
827 return CTL_E_ILLEGALFUNCTIONCALL
;
829 V_I4(hash
) = get_ptr_hash(unk
);
830 IUnknown_Release(unk
);
833 case VT_DATE
|VT_BYREF
:
835 return get_flt_hash(V_VT(key
) & VT_BYREF
? *V_DATEREF(key
) : V_DATE(key
), &V_I4(hash
));
838 return get_flt_hash(V_VT(key
) & VT_BYREF
? *V_R4REF(key
) : V_R4(key
), &V_I4(hash
));
841 return get_flt_hash(V_VT(key
) & VT_BYREF
? *V_R8REF(key
) : V_R8(key
), &V_I4(hash
));
849 return CTL_E_ILLEGALFUNCTIONCALL
;
851 FIXME("not implemented for type %d\n", V_VT(key
));
858 static const struct IDictionaryVtbl dictionary_vtbl
=
860 dictionary_QueryInterface
,
863 dictionary_GetTypeInfoCount
,
864 dictionary_GetTypeInfo
,
865 dictionary_GetIDsOfNames
,
867 dictionary_putref_Item
,
871 dictionary_get_Count
,
877 dictionary_RemoveAll
,
878 dictionary_put_CompareMode
,
879 dictionary_get_CompareMode
,
881 dictionary_get_HashVal
884 HRESULT WINAPI
Dictionary_CreateInstance(IClassFactory
*factory
,IUnknown
*outer
,REFIID riid
, void **obj
)
888 TRACE("(%p)\n", obj
);
892 This
= heap_alloc(sizeof(*This
));
893 if(!This
) return E_OUTOFMEMORY
;
895 This
->IDictionary_iface
.lpVtbl
= &dictionary_vtbl
;
897 This
->method
= BinaryCompare
;
899 list_init(&This
->pairs
);
900 list_init(&This
->notifier
);
901 memset(This
->buckets
, 0, sizeof(This
->buckets
));
903 *obj
= &This
->IDictionary_iface
;