1 /*
2  * Copyright (C) 2012 Alistair Leslie-Hughes
3  * Copyright 2015 Nikolay Sivov for CodeWeavers
4  *
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.
9  *
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.
14  *
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
18  */
19 
20 #define COBJMACROS
21 #ifdef __REACTOS__
22 #define CONST_VTABLE
23 #endif
24 #include <stdio.h>
25 
26 #include "windows.h"
27 #include "ole2.h"
28 #include "oleauto.h"
29 #include "olectl.h"
30 #include "dispex.h"
31 
32 #include "wine/test.h"
33 
34 #include "scrrun.h"
35 
36 #define test_provideclassinfo(a, b) _test_provideclassinfo((IDispatch*)a, b, __LINE__)
37 static void _test_provideclassinfo(IDispatch *disp, const GUID *guid, int line)
38 {
39     IProvideClassInfo *classinfo;
40     TYPEATTR *attr;
41     ITypeInfo *ti;
42     IUnknown *unk;
43     HRESULT hr;
44 
45     hr = IDispatch_QueryInterface(disp, &IID_IProvideClassInfo, (void **)&classinfo);
46     ok_(__FILE__,line) (hr == S_OK, "Failed to get IProvideClassInfo, %#x.\n", hr);
47 
48     hr = IProvideClassInfo_GetClassInfo(classinfo, &ti);
49     ok_(__FILE__,line) (hr == S_OK, "GetClassInfo() failed, %#x.\n", hr);
50 
51     hr = ITypeInfo_GetTypeAttr(ti, &attr);
52     ok_(__FILE__,line) (hr == S_OK, "GetTypeAttr() failed, %#x.\n", hr);
53 
54     ok_(__FILE__,line) (IsEqualGUID(&attr->guid, guid), "Unexpected typeinfo %s, expected %s\n", wine_dbgstr_guid(&attr->guid),
55         wine_dbgstr_guid(guid));
56 
57     hr = IProvideClassInfo_QueryInterface(classinfo, &IID_IUnknown, (void **)&unk);
58     ok(hr == S_OK, "Failed to QI for IUnknown.\n");
59     ok(unk == (IUnknown *)disp, "Got unk %p, original %p\n", unk, disp);
60     IUnknown_Release(unk);
61 
62     IProvideClassInfo_Release(classinfo);
63     ITypeInfo_ReleaseTypeAttr(ti, attr);
64     ITypeInfo_Release(ti);
65 }
66 
67 static void test_interfaces(void)
68 {
69     static const WCHAR key_add[] = {'a', 0};
70     static const WCHAR key_add_value[] = {'a', 0};
71     static const WCHAR key_non_exist[] = {'b', 0};
72     HRESULT hr;
73     IDispatch *disp;
74     IDispatchEx *dispex;
75     IDictionary *dict;
76     IObjectWithSite *site;
77     VARIANT key, value;
78     VARIANT_BOOL exists;
79     LONG count = 0;
80 
81     hr = CoCreateInstance(&CLSID_Dictionary, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
82             &IID_IDispatch, (void**)&disp);
83     ok(hr == S_OK, "got 0x%08x\n", hr);
84 
85     VariantInit(&key);
86     VariantInit(&value);
87 
88     hr = IDispatch_QueryInterface(disp, &IID_IDictionary, (void**)&dict);
89     ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK);
90 
91     hr = IDispatch_QueryInterface(disp, &IID_IObjectWithSite, (void**)&site);
92     ok(hr == E_NOINTERFACE, "got 0x%08x, expected 0x%08x\n", hr, E_NOINTERFACE);
93 
94     hr = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
95     ok(hr == E_NOINTERFACE, "got 0x%08x, expected 0x%08x\n", hr, E_NOINTERFACE);
96 
97     test_provideclassinfo(disp, &CLSID_Dictionary);
98 
99     V_VT(&key) = VT_BSTR;
100     V_BSTR(&key) = SysAllocString(key_add);
101     V_VT(&value) = VT_BSTR;
102     V_BSTR(&value) = SysAllocString(key_add_value);
103     hr = IDictionary_Add(dict, &key, &value);
104     ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK);
105     VariantClear(&value);
106 
107     exists = VARIANT_FALSE;
108     hr = IDictionary_Exists(dict, &key, &exists);
109     ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK);
110     ok(exists == VARIANT_TRUE, "Expected TRUE but got FALSE.\n");
111     VariantClear(&key);
112 
113     exists = VARIANT_TRUE;
114     V_VT(&key) = VT_BSTR;
115     V_BSTR(&key) = SysAllocString(key_non_exist);
116     hr = IDictionary_Exists(dict, &key, &exists);
117     ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK);
118     ok(exists == VARIANT_FALSE, "Expected FALSE but got TRUE.\n");
119     VariantClear(&key);
120 
121     hr = IDictionary_get_Count(dict, &count);
122     ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK);
123     ok(count == 1, "got %d, expected 1\n", count);
124 
125     IDictionary_Release(dict);
126     IDispatch_Release(disp);
127 }
128 
129 static void test_comparemode(void)
130 {
131     CompareMethod method;
132     IDictionary *dict;
133     VARIANT key, item;
134     HRESULT hr;
135 
136     hr = CoCreateInstance(&CLSID_Dictionary, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
137             &IID_IDictionary, (void**)&dict);
138     ok(hr == S_OK, "got 0x%08x\n", hr);
139 
140     if (0) /* crashes on native */
141         hr = IDictionary_get_CompareMode(dict, NULL);
142 
143     method = 10;
144     hr = IDictionary_get_CompareMode(dict, &method);
145     ok(hr == S_OK, "got 0x%08x\n", hr);
146     ok(method == BinaryCompare, "got %d\n", method);
147 
148     /* invalid mode value is not checked */
149     hr = IDictionary_put_CompareMode(dict, 10);
150     ok(hr == S_OK, "got 0x%08x\n", hr);
151 
152     hr = IDictionary_get_CompareMode(dict, &method);
153     ok(hr == S_OK, "got 0x%08x\n", hr);
154     ok(method == 10, "got %d\n", method);
155 
156     hr = IDictionary_put_CompareMode(dict, DatabaseCompare);
157     ok(hr == S_OK, "got 0x%08x\n", hr);
158 
159     hr = IDictionary_get_CompareMode(dict, &method);
160     ok(hr == S_OK, "got 0x%08x\n", hr);
161     ok(method == DatabaseCompare, "got %d\n", method);
162 
163     /* try to change mode of a non-empty dict */
164     V_VT(&key) = VT_I2;
165     V_I2(&key) = 0;
166     VariantInit(&item);
167     hr = IDictionary_Add(dict, &key, &item);
168     ok(hr == S_OK, "got 0x%08x\n", hr);
169 
170     hr = IDictionary_put_CompareMode(dict, BinaryCompare);
171     ok(hr == CTL_E_ILLEGALFUNCTIONCALL, "got 0x%08x\n", hr);
172 
173     IDictionary_Release(dict);
174 }
175 
176 static DWORD get_str_hash(const WCHAR *str, CompareMethod method)
177 {
178     DWORD hash = 0;
179 
180     while (*str) {
181         WCHAR ch;
182 
183         if (method == TextCompare || method == DatabaseCompare)
184             ch = PtrToInt(CharLowerW(IntToPtr(*str)));
185         else
186             ch = *str;
187 
188         hash += (hash << 4) + ch;
189         str++;
190     }
191 
192     return hash % 1201;
193 }
194 
195 static DWORD get_num_hash(FLOAT num)
196 {
197     return (*((DWORD*)&num)) % 1201;
198 }
199 
200 static DWORD get_ptr_hash(void *ptr)
201 {
202     return PtrToUlong(ptr) % 1201;
203 }
204 
205 typedef union
206 {
207     struct
208     {
209         unsigned int m : 23;
210         unsigned int exp_bias : 8;
211         unsigned int sign : 1;
212     } i;
213     float f;
214 } R4_FIELDS;
215 
216 typedef union
217 {
218     struct
219     {
220         unsigned int m_lo : 32;     /* 52 bits of precision */
221         unsigned int m_hi : 20;
222         unsigned int exp_bias : 11; /* bias == 1023 */
223         unsigned int sign : 1;
224     } i;
225     double d;
226 } R8_FIELDS;
227 
228 static HRESULT WINAPI test_unk_QI(IUnknown *iface, REFIID riid, void **obj)
229 {
230     if (IsEqualIID(riid, &IID_IUnknown)) {
231         *obj = iface;
232         return S_OK;
233     }
234 
235     ok(0, "unexpected %s\n", wine_dbgstr_guid(riid));
236     *obj = NULL;
237     return E_NOINTERFACE;
238 }
239 
240 static HRESULT WINAPI test_unk_no_QI(IUnknown *iface, REFIID riid, void **obj)
241 {
242     *obj = NULL;
243     return E_NOINTERFACE;
244 }
245 
246 static ULONG WINAPI test_unk_AddRef(IUnknown *iface)
247 {
248     ok(0, "unexpected\n");
249     return 2;
250 }
251 
252 static ULONG WINAPI test_unk_Release(IUnknown *iface)
253 {
254     return 1;
255 }
256 
257 static const IUnknownVtbl test_unk_vtbl = {
258     test_unk_QI,
259     test_unk_AddRef,
260     test_unk_Release
261 };
262 
263 static const IUnknownVtbl test_unk_no_vtbl = {
264     test_unk_no_QI,
265     test_unk_AddRef,
266     test_unk_Release
267 };
268 
269 static HRESULT WINAPI test_disp_QI(IDispatch *iface, REFIID riid, void **obj)
270 {
271     if (IsEqualIID(riid, &IID_IDispatch) || IsEqualIID(riid, &IID_IUnknown)) {
272         *obj = iface;
273         return S_OK;
274     }
275 
276     ok(0, "unexpected %s\n", wine_dbgstr_guid(riid));
277     *obj = NULL;
278     return E_NOINTERFACE;
279 }
280 
281 static ULONG WINAPI test_disp_AddRef(IDispatch *iface)
282 {
283     ok(0, "unexpected\n");
284     return 2;
285 }
286 
287 static ULONG WINAPI test_disp_Release(IDispatch *iface)
288 {
289     return 1;
290 }
291 
292 static HRESULT WINAPI test_disp_GetTypeInfoCount(IDispatch *iface, UINT *count)
293 {
294     ok(0, "unexpected call\n");
295     return E_NOTIMPL;
296 }
297 
298 static HRESULT WINAPI test_disp_GetTypeInfo(IDispatch *iface, UINT index, LCID lcid, ITypeInfo **ti)
299 {
300     ok(0, "unexpected call\n");
301     return E_NOTIMPL;
302 }
303 
304 static HRESULT WINAPI test_disp_GetIDsOfNames(IDispatch *iface, REFIID riid, LPOLESTR *names,
305     UINT name_count, LCID lcid, DISPID *dispid)
306 {
307     ok(0, "unexpected call\n");
308     return E_NOTIMPL;
309 }
310 
311 static HRESULT WINAPI test_disp_Invoke(IDispatch *iface, DISPID dispid, REFIID riid,
312     LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *result, EXCEPINFO *excepinfo, UINT *arg_err)
313 {
314     ok(0, "unexpected call\n");
315     return E_NOTIMPL;
316 }
317 
318 static const IDispatchVtbl test_disp_vtbl = {
319     test_disp_QI,
320     test_disp_AddRef,
321     test_disp_Release,
322     test_disp_GetTypeInfoCount,
323     test_disp_GetTypeInfo,
324     test_disp_GetIDsOfNames,
325     test_disp_Invoke
326 };
327 
328 static IUnknown test_unk = { &test_unk_vtbl };
329 static IUnknown test_unk2 = { &test_unk_no_vtbl };
330 static IDispatch test_disp = { &test_disp_vtbl };
331 
332 static void test_hash_value(void)
333 {
334     /* string test data */
335     static const WCHAR str_hash_tests[][10] = {
336         {'a','b','c','d',0},
337         {'a','B','C','d','1',0},
338         {'1','2','3',0},
339         {'A',0},
340         {'a',0},
341         { 0 }
342     };
343 
344     static const int int_hash_tests[] = {
345         0, -1, 100, 1, 255
346     };
347 
348     static const FLOAT float_hash_tests[] = {
349         0.0, -1.0, 100.0, 1.0, 255.0, 1.234
350     };
351 
352     IDictionary *dict;
353     VARIANT key, hash;
354     IDispatch *disp;
355     DWORD expected;
356     IUnknown *unk;
357     R8_FIELDS fx8;
358     R4_FIELDS fx4;
359     HRESULT hr;
360     unsigned i;
361 
362     hr = CoCreateInstance(&CLSID_Dictionary, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
363             &IID_IDictionary, (void**)&dict);
364     ok(hr == S_OK, "got 0x%08x\n", hr);
365 
366     V_VT(&key) = VT_BSTR;
367     V_BSTR(&key) = NULL;
368     VariantInit(&hash);
369     hr = IDictionary_get_HashVal(dict, &key, &hash);
370     ok(hr == S_OK, "got 0x%08x\n", hr);
371     ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash));
372     ok(V_I4(&hash) == 0, "got %d\n", V_I4(&hash));
373 
374     for (i = 0; i < ARRAY_SIZE(str_hash_tests); i++) {
375         expected = get_str_hash(str_hash_tests[i], BinaryCompare);
376 
377         hr = IDictionary_put_CompareMode(dict, BinaryCompare);
378         ok(hr == S_OK, "got 0x%08x\n", hr);
379 
380         V_VT(&key) = VT_BSTR;
381         V_BSTR(&key) = SysAllocString(str_hash_tests[i]);
382         VariantInit(&hash);
383         hr = IDictionary_get_HashVal(dict, &key, &hash);
384         ok(hr == S_OK, "got 0x%08x\n", hr);
385         ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash));
386         ok(V_I4(&hash) == expected, "%d: binary mode: got hash 0x%08x, expected 0x%08x\n", i, V_I4(&hash),
387             expected);
388         VariantClear(&key);
389 
390         expected = get_str_hash(str_hash_tests[i], TextCompare);
391         hr = IDictionary_put_CompareMode(dict, TextCompare);
392         ok(hr == S_OK, "got 0x%08x\n", hr);
393 
394         V_VT(&key) = VT_BSTR;
395         V_BSTR(&key) = SysAllocString(str_hash_tests[i]);
396         VariantInit(&hash);
397         hr = IDictionary_get_HashVal(dict, &key, &hash);
398         ok(hr == S_OK, "got 0x%08x\n", hr);
399         ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash));
400         ok(V_I4(&hash) == expected, "%d: text mode: got hash 0x%08x, expected 0x%08x\n", i, V_I4(&hash),
401             expected);
402         VariantClear(&key);
403 
404         expected = get_str_hash(str_hash_tests[i], DatabaseCompare);
405         hr = IDictionary_put_CompareMode(dict, DatabaseCompare);
406         ok(hr == S_OK, "got 0x%08x\n", hr);
407 
408         V_VT(&key) = VT_BSTR;
409         V_BSTR(&key) = SysAllocString(str_hash_tests[i]);
410         VariantInit(&hash);
411         hr = IDictionary_get_HashVal(dict, &key, &hash);
412         ok(hr == S_OK, "got 0x%08x\n", hr);
413         ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash));
414         ok(V_I4(&hash) == expected, "%d: db mode: got hash 0x%08x, expected 0x%08x\n", i, V_I4(&hash),
415             expected);
416         VariantClear(&key);
417     }
418 
419     V_VT(&key) = VT_INT;
420     V_INT(&key) = 1;
421     VariantInit(&hash);
422     hr = IDictionary_get_HashVal(dict, &key, &hash);
423     ok(hr == CTL_E_ILLEGALFUNCTIONCALL || broken(hr == S_OK) /* win2k, win2k3 */, "got 0x%08x\n", hr);
424     ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash));
425     ok(V_I4(&hash) == ~0u, "got hash 0x%08x\n", V_I4(&hash));
426 
427     V_VT(&key) = VT_UINT;
428     V_UINT(&key) = 1;
429     VariantInit(&hash);
430     hr = IDictionary_get_HashVal(dict, &key, &hash);
431     ok(hr == CTL_E_ILLEGALFUNCTIONCALL || broken(hr == S_OK) /* win2k, win2k3 */, "got 0x%08x\n", hr);
432     ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash));
433     ok(V_I4(&hash) == ~0u, "got hash 0x%08x\n", V_I4(&hash));
434 
435     V_VT(&key) = VT_I1;
436     V_I1(&key) = 1;
437     VariantInit(&hash);
438     hr = IDictionary_get_HashVal(dict, &key, &hash);
439     ok(hr == CTL_E_ILLEGALFUNCTIONCALL || broken(hr == S_OK) /* win2k, win2k3 */, "got 0x%08x\n", hr);
440     ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash));
441     ok(V_I4(&hash) == ~0u || broken(V_I4(&hash) == 0xa1), "got hash 0x%08x\n", V_I4(&hash));
442 
443     V_VT(&key) = VT_I8;
444     V_I8(&key) = 1;
445     VariantInit(&hash);
446     hr = IDictionary_get_HashVal(dict, &key, &hash);
447     ok(hr == CTL_E_ILLEGALFUNCTIONCALL || broken(hr == S_OK) /* win2k, win2k3 */, "got 0x%08x\n", hr);
448     ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash));
449     ok(V_I4(&hash) == ~0u, "got hash 0x%08x\n", V_I4(&hash));
450 
451     V_VT(&key) = VT_UI2;
452     V_UI2(&key) = 1;
453     VariantInit(&hash);
454     hr = IDictionary_get_HashVal(dict, &key, &hash);
455     ok(hr == CTL_E_ILLEGALFUNCTIONCALL || broken(hr == S_OK) /* win2k, win2k3 */, "got 0x%08x\n", hr);
456     ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash));
457     ok(V_I4(&hash) == ~0u, "got hash 0x%08x\n", V_I4(&hash));
458 
459     V_VT(&key) = VT_UI4;
460     V_UI4(&key) = 1;
461     VariantInit(&hash);
462     hr = IDictionary_get_HashVal(dict, &key, &hash);
463     ok(hr == CTL_E_ILLEGALFUNCTIONCALL || broken(hr == S_OK) /* win2k, win2k3 */, "got 0x%08x\n", hr);
464     ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash));
465     ok(V_I4(&hash) == ~0u, "got hash 0x%08x\n", V_I4(&hash));
466 
467     for (i = 0; i < ARRAY_SIZE(int_hash_tests); i++) {
468         SHORT i2;
469         BYTE ui1;
470         LONG i4;
471 
472         expected = get_num_hash(int_hash_tests[i]);
473 
474         V_VT(&key) = VT_I2;
475         V_I2(&key) = int_hash_tests[i];
476         VariantInit(&hash);
477         hr = IDictionary_get_HashVal(dict, &key, &hash);
478         ok(hr == S_OK, "got 0x%08x\n", hr);
479         ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash));
480         ok(V_I4(&hash) == expected, "%d: got hash 0x%08x, expected 0x%08x\n", i, V_I4(&hash),
481             expected);
482 
483         i2 = int_hash_tests[i];
484         V_VT(&key) = VT_I2|VT_BYREF;
485         V_I2REF(&key) = &i2;
486         VariantInit(&hash);
487         hr = IDictionary_get_HashVal(dict, &key, &hash);
488         ok(hr == S_OK, "got 0x%08x\n", hr);
489         ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash));
490         ok(V_I4(&hash) == expected, "%d: got hash 0x%08x, expected 0x%08x\n", i, V_I4(&hash),
491             expected);
492 
493         V_VT(&key) = VT_I4;
494         V_I4(&key) = int_hash_tests[i];
495         VariantInit(&hash);
496         hr = IDictionary_get_HashVal(dict, &key, &hash);
497         ok(hr == S_OK, "got 0x%08x\n", hr);
498         ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash));
499         ok(V_I4(&hash) == expected, "%d: got hash 0x%08x, expected 0x%08x\n", i, V_I4(&hash),
500             expected);
501 
502         i4 = int_hash_tests[i];
503         V_VT(&key) = VT_I4|VT_BYREF;
504         V_I4REF(&key) = &i4;
505         VariantInit(&hash);
506         hr = IDictionary_get_HashVal(dict, &key, &hash);
507         ok(hr == S_OK, "got 0x%08x\n", hr);
508         ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash));
509         ok(V_I4(&hash) == expected, "%d: got hash 0x%08x, expected 0x%08x\n", i, V_I4(&hash),
510             expected);
511 
512         expected = get_num_hash((FLOAT)(BYTE)int_hash_tests[i]);
513         V_VT(&key) = VT_UI1;
514         V_UI1(&key) = int_hash_tests[i];
515         VariantInit(&hash);
516         hr = IDictionary_get_HashVal(dict, &key, &hash);
517         ok(hr == S_OK, "got 0x%08x\n", hr);
518         ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash));
519         ok(V_I4(&hash) == expected, "%d: got hash 0x%08x, expected 0x%08x\n", i, V_I4(&hash),
520             expected);
521 
522         ui1 = int_hash_tests[i];
523         V_VT(&key) = VT_UI1|VT_BYREF;
524         V_UI1REF(&key) = &ui1;
525         VariantInit(&hash);
526         hr = IDictionary_get_HashVal(dict, &key, &hash);
527         ok(hr == S_OK, "got 0x%08x\n", hr);
528         ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash));
529         ok(V_I4(&hash) == expected, "%d: got hash 0x%08x, expected 0x%08x\n", i, V_I4(&hash),
530             expected);
531     }
532 
533     /* nan */
534     fx4.f = 10.0;
535     fx4.i.exp_bias = 0xff;
536 
537     V_VT(&key) = VT_R4;
538     V_R4(&key) = fx4.f;
539     VariantInit(&hash);
540     hr = IDictionary_get_HashVal(dict, &key, &hash);
541     ok(hr == CTL_E_ILLEGALFUNCTIONCALL || broken(hr == S_OK) /* win2k, win2k3 */, "got 0x%08x\n", hr);
542     ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash));
543     ok(V_I4(&hash) == ~0u || broken(V_I4(&hash) == 0 /* win2k */ ||
544         V_I4(&hash) == 0x1f4 /* vista, win2k8 */), "got hash 0x%08x\n", V_I4(&hash));
545 
546     /* inf */
547     fx4.f = 10.0;
548     fx4.i.m = 0;
549     fx4.i.exp_bias = 0xff;
550 
551     V_VT(&key) = VT_R4;
552     V_R4(&key) = fx4.f;
553     V_I4(&hash) = 10;
554     hr = IDictionary_get_HashVal(dict, &key, &hash);
555     ok(hr == S_OK, "got 0x%08x\n", hr);
556     ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash));
557     ok(V_I4(&hash) == 0, "got hash 0x%08x\n", V_I4(&hash));
558 
559     /* nan */
560     fx8.d = 10.0;
561     fx8.i.exp_bias = 0x7ff;
562 
563     V_VT(&key) = VT_R8;
564     V_R8(&key) = fx8.d;
565     VariantInit(&hash);
566     hr = IDictionary_get_HashVal(dict, &key, &hash);
567     ok(hr == CTL_E_ILLEGALFUNCTIONCALL || broken(hr == S_OK) /* win2k, win2k3 */, "got 0x%08x\n", hr);
568     ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash));
569     ok(V_I4(&hash) == ~0u || broken(V_I4(&hash) == 0 /* win2k */ ||
570         V_I4(&hash) == 0x1f4 /* vista, win2k8 */), "got hash 0x%08x\n", V_I4(&hash));
571 
572     V_VT(&key) = VT_DATE;
573     V_DATE(&key) = fx8.d;
574     VariantInit(&hash);
575     hr = IDictionary_get_HashVal(dict, &key, &hash);
576     ok(hr == CTL_E_ILLEGALFUNCTIONCALL || broken(hr == S_OK) /* win2k, win2k3 */, "got 0x%08x\n", hr);
577     ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash));
578     ok(V_I4(&hash) == ~0u || broken(V_I4(&hash) == 0 /* win2k */ ||
579         V_I4(&hash) == 0x1f4 /* vista, win2k8 */), "got hash 0x%08x\n", V_I4(&hash));
580 
581     /* inf */
582     fx8.d = 10.0;
583     fx8.i.m_lo = 0;
584     fx8.i.m_hi = 0;
585     fx8.i.exp_bias = 0x7ff;
586 
587     V_VT(&key) = VT_R8;
588     V_R8(&key) = fx8.d;
589     V_I4(&hash) = 10;
590     hr = IDictionary_get_HashVal(dict, &key, &hash);
591     ok(hr == S_OK, "got 0x%08x\n", hr);
592     ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash));
593     ok(V_I4(&hash) == 0, "got hash 0x%08x\n", V_I4(&hash));
594 
595     V_VT(&key) = VT_DATE;
596     V_DATE(&key) = fx8.d;
597     V_I4(&hash) = 10;
598     hr = IDictionary_get_HashVal(dict, &key, &hash);
599     ok(hr == S_OK, "got 0x%08x\n", hr);
600     ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash));
601     ok(V_I4(&hash) == 0, "got hash 0x%08x\n", V_I4(&hash));
602 
603     for (i = 0; i < ARRAY_SIZE(float_hash_tests); i++) {
604         double dbl;
605         FLOAT flt;
606         DATE date;
607 
608         expected = get_num_hash(float_hash_tests[i]);
609 
610         V_VT(&key) = VT_R4;
611         V_R4(&key) = float_hash_tests[i];
612         VariantInit(&hash);
613         hr = IDictionary_get_HashVal(dict, &key, &hash);
614         ok(hr == S_OK, "got 0x%08x\n", hr);
615         ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash));
616         ok(V_I4(&hash) == expected, "%d: got hash 0x%08x, expected 0x%08x\n", i, V_I4(&hash),
617             expected);
618 
619         flt = float_hash_tests[i];
620         V_VT(&key) = VT_R4|VT_BYREF;
621         V_R4REF(&key) = &flt;
622         VariantInit(&hash);
623         hr = IDictionary_get_HashVal(dict, &key, &hash);
624         ok(hr == S_OK, "got 0x%08x\n", hr);
625         ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash));
626         ok(V_I4(&hash) == expected, "%d: got hash 0x%08x, expected 0x%08x\n", i, V_I4(&hash),
627             expected);
628 
629         V_VT(&key) = VT_R8;
630         V_R8(&key) = float_hash_tests[i];
631         VariantInit(&hash);
632         hr = IDictionary_get_HashVal(dict, &key, &hash);
633         ok(hr == S_OK, "got 0x%08x\n", hr);
634         ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash));
635         ok(V_I4(&hash) == expected, "%d: got hash 0x%08x, expected 0x%08x\n", i, V_I4(&hash),
636             expected);
637 
638         dbl = float_hash_tests[i];
639         V_VT(&key) = VT_R8|VT_BYREF;
640         V_R8REF(&key) = &dbl;
641         VariantInit(&hash);
642         hr = IDictionary_get_HashVal(dict, &key, &hash);
643         ok(hr == S_OK, "got 0x%08x\n", hr);
644         ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash));
645         ok(V_I4(&hash) == expected, "%d: got hash 0x%08x, expected 0x%08x\n", i, V_I4(&hash),
646             expected);
647 
648         V_VT(&key) = VT_DATE;
649         V_DATE(&key) = float_hash_tests[i];
650         VariantInit(&hash);
651         hr = IDictionary_get_HashVal(dict, &key, &hash);
652         ok(hr == S_OK, "got 0x%08x\n", hr);
653         ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash));
654         ok(V_I4(&hash) == expected, "%d: got hash 0x%08x, expected 0x%08x\n", i, V_I4(&hash),
655             expected);
656 
657         V_VT(&key) = VT_DATE|VT_BYREF;
658         date = float_hash_tests[i];
659         V_DATEREF(&key) = &date;
660         VariantInit(&hash);
661         hr = IDictionary_get_HashVal(dict, &key, &hash);
662         ok(hr == S_OK, "got 0x%08x\n", hr);
663         ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash));
664         ok(V_I4(&hash) == expected, "%d: got hash 0x%08x, expected 0x%08x\n", i, V_I4(&hash),
665             expected);
666     }
667 
668     /* interface pointers as keys */
669     V_VT(&key) = VT_UNKNOWN;
670     V_UNKNOWN(&key) = 0;
671     VariantInit(&hash);
672     V_I4(&hash) = 1;
673     hr = IDictionary_get_HashVal(dict, &key, &hash);
674     ok(hr == S_OK, "got 0x%08x\n", hr);
675     ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash));
676     ok(V_I4(&hash) == 0, "got hash 0x%08x, expected 0\n", V_I4(&hash));
677 
678     /* QI doesn't work */
679     V_VT(&key) = VT_UNKNOWN;
680     V_UNKNOWN(&key) = &test_unk2;
681     VariantInit(&hash);
682     expected = get_ptr_hash(&test_unk2);
683     hr = IDictionary_get_HashVal(dict, &key, &hash);
684     ok(hr == CTL_E_ILLEGALFUNCTIONCALL || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
685     ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash));
686     ok(V_I4(&hash) == ~0u, "got hash 0x%08x, expected 0x%08x\n", V_I4(&hash), expected);
687 
688     V_VT(&key) = VT_UNKNOWN;
689     V_UNKNOWN(&key) = &test_unk;
690     VariantInit(&hash);
691     expected = get_ptr_hash(&test_unk);
692     hr = IDictionary_get_HashVal(dict, &key, &hash);
693     ok(hr == S_OK, "got 0x%08x\n", hr);
694     ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash));
695     ok(V_I4(&hash) == expected, "got hash 0x%08x, expected 0x%08x\n", V_I4(&hash), expected);
696 
697     /* interface without IDispatch support */
698     V_VT(&key) = VT_DISPATCH;
699     V_DISPATCH(&key) = (IDispatch*)&test_unk;
700     VariantInit(&hash);
701     expected = get_ptr_hash(&test_unk);
702     hr = IDictionary_get_HashVal(dict, &key, &hash);
703     ok(hr == S_OK, "got 0x%08x\n", hr);
704     ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash));
705     ok(V_I4(&hash) == expected, "got hash 0x%08x, expected 0x%08x\n", V_I4(&hash), expected);
706 
707     V_VT(&key) = VT_DISPATCH;
708     V_DISPATCH(&key) = &test_disp;
709     VariantInit(&hash);
710     expected = get_ptr_hash(&test_disp);
711     hr = IDictionary_get_HashVal(dict, &key, &hash);
712     ok(hr == S_OK, "got 0x%08x\n", hr);
713     ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash));
714     ok(V_I4(&hash) == expected, "got hash 0x%08x, expected 0x%08x\n", V_I4(&hash), expected);
715 
716     /* same with BYREF */
717 if (0) { /* crashes on native */
718     V_VT(&key) = VT_UNKNOWN|VT_BYREF;
719     V_UNKNOWNREF(&key) = 0;
720     hr = IDictionary_get_HashVal(dict, &key, &hash);
721 }
722     unk = NULL;
723     V_VT(&key) = VT_UNKNOWN|VT_BYREF;
724     V_UNKNOWNREF(&key) = &unk;
725     VariantInit(&hash);
726     V_I4(&hash) = 1;
727     hr = IDictionary_get_HashVal(dict, &key, &hash);
728     ok(hr == S_OK, "got 0x%08x\n", hr);
729     ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash));
730     ok(V_I4(&hash) == 0, "got hash 0x%08x, expected 0\n", V_I4(&hash));
731 
732     V_VT(&key) = VT_UNKNOWN|VT_BYREF;
733     unk = &test_unk;
734     V_UNKNOWNREF(&key) = &unk;
735     VariantInit(&hash);
736     expected = get_ptr_hash(&test_unk);
737     hr = IDictionary_get_HashVal(dict, &key, &hash);
738     ok(hr == S_OK, "got 0x%08x\n", hr);
739     ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash));
740     ok(V_I4(&hash) == expected, "got hash 0x%08x, expected 0x%08x\n", V_I4(&hash), expected);
741 
742     /* interface without IDispatch support */
743     V_VT(&key) = VT_DISPATCH|VT_BYREF;
744     unk = &test_unk;
745     V_DISPATCHREF(&key) = (IDispatch**)&unk;
746     VariantInit(&hash);
747     expected = get_ptr_hash(&test_unk);
748     hr = IDictionary_get_HashVal(dict, &key, &hash);
749     ok(hr == S_OK, "got 0x%08x\n", hr);
750     ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash));
751     ok(V_I4(&hash) == expected, "got hash 0x%08x, expected 0x%08x\n", V_I4(&hash), expected);
752 
753     V_VT(&key) = VT_DISPATCH|VT_BYREF;
754     disp = &test_disp;
755     V_DISPATCHREF(&key) = &disp;
756     VariantInit(&hash);
757     expected = get_ptr_hash(&test_disp);
758     hr = IDictionary_get_HashVal(dict, &key, &hash);
759     ok(hr == S_OK, "got 0x%08x\n", hr);
760     ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash));
761     ok(V_I4(&hash) == expected, "got hash 0x%08x, expected 0x%08x\n", V_I4(&hash), expected);
762 
763     IDictionary_Release(dict);
764 }
765 
766 static void test_Exists(void)
767 {
768     VARIANT_BOOL exists;
769     IDictionary *dict;
770     VARIANT key, item;
771     HRESULT hr;
772 
773     hr = CoCreateInstance(&CLSID_Dictionary, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
774             &IID_IDictionary, (void**)&dict);
775     ok(hr == S_OK, "got 0x%08x\n", hr);
776 
777 if (0) /* crashes on native */
778     hr = IDictionary_Exists(dict, NULL, NULL);
779 
780     V_VT(&key) = VT_I2;
781     V_I2(&key) = 0;
782     hr = IDictionary_Exists(dict, &key, NULL);
783     ok(hr == CTL_E_ILLEGALFUNCTIONCALL, "got 0x%08x\n", hr);
784 
785     V_VT(&key) = VT_I2;
786     V_I2(&key) = 0;
787     exists = VARIANT_TRUE;
788     hr = IDictionary_Exists(dict, &key, &exists);
789     ok(hr == S_OK, "got 0x%08x\n", hr);
790     ok(exists == VARIANT_FALSE, "got %x\n", exists);
791 
792     VariantInit(&item);
793     hr = IDictionary_Add(dict, &key, &item);
794     ok(hr == S_OK, "got 0x%08x\n", hr);
795 
796     V_VT(&key) = VT_R4;
797     V_R4(&key) = 0.0;
798     hr = IDictionary_Add(dict, &key, &item);
799     ok(hr == CTL_E_KEY_ALREADY_EXISTS, "got 0x%08x\n", hr);
800 
801     V_VT(&key) = VT_I2;
802     V_I2(&key) = 0;
803     hr = IDictionary_Exists(dict, &key, NULL);
804     ok(hr == CTL_E_ILLEGALFUNCTIONCALL, "got 0x%08x\n", hr);
805 
806     V_VT(&key) = VT_I2;
807     V_I2(&key) = 0;
808     exists = VARIANT_FALSE;
809     hr = IDictionary_Exists(dict, &key, &exists);
810     ok(hr == S_OK, "got 0x%08x\n", hr);
811     ok(exists == VARIANT_TRUE, "got %x\n", exists);
812 
813     /* key of different type, but resolves to same hash value */
814     V_VT(&key) = VT_R4;
815     V_R4(&key) = 0.0;
816     exists = VARIANT_FALSE;
817     hr = IDictionary_Exists(dict, &key, &exists);
818     ok(hr == S_OK, "got 0x%08x\n", hr);
819     ok(exists == VARIANT_TRUE, "got %x\n", exists);
820 
821     IDictionary_Release(dict);
822 }
823 
824 static void test_Keys(void)
825 {
826     VARIANT key, keys, item;
827     IDictionary *dict;
828     LONG index;
829     HRESULT hr;
830 
831     hr = CoCreateInstance(&CLSID_Dictionary, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
832             &IID_IDictionary, (void**)&dict);
833     ok(hr == S_OK, "got 0x%08x\n", hr);
834 
835     hr = IDictionary_Keys(dict, NULL);
836     ok(hr == S_OK, "got 0x%08x\n", hr);
837 
838     VariantInit(&keys);
839     hr = IDictionary_Keys(dict, &keys);
840     ok(hr == S_OK, "got 0x%08x\n", hr);
841     ok(V_VT(&keys) == (VT_ARRAY|VT_VARIANT), "got %d\n", V_VT(&keys));
842     VariantClear(&keys);
843 
844     V_VT(&key) = VT_R4;
845     V_R4(&key) = 0.0;
846     VariantInit(&item);
847     hr = IDictionary_Add(dict, &key, &item);
848     ok(hr == S_OK, "got 0x%08x\n", hr);
849 
850     VariantInit(&keys);
851     hr = IDictionary_Keys(dict, &keys);
852     ok(hr == S_OK, "got 0x%08x\n", hr);
853     ok(V_VT(&keys) == (VT_ARRAY|VT_VARIANT), "got %d\n", V_VT(&keys));
854 
855     VariantInit(&key);
856     index = 0;
857     hr = SafeArrayGetElement(V_ARRAY(&keys), &index, &key);
858     ok(hr == S_OK, "got 0x%08x\n", hr);
859     ok(V_VT(&key) == VT_R4, "got %d\n", V_VT(&key));
860 
861     index = SafeArrayGetDim(V_ARRAY(&keys));
862     ok(index == 1, "got %d\n", index);
863 
864     hr = SafeArrayGetUBound(V_ARRAY(&keys), 1, &index);
865     ok(hr == S_OK, "got 0x%08x\n", hr);
866     ok(index == 0, "got %d\n", index);
867 
868     VariantClear(&keys);
869 
870     IDictionary_Release(dict);
871 }
872 
873 static void test_Remove(void)
874 {
875     VARIANT key, item;
876     IDictionary *dict;
877     HRESULT hr;
878 
879     hr = CoCreateInstance(&CLSID_Dictionary, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
880             &IID_IDictionary, (void**)&dict);
881     ok(hr == S_OK, "got 0x%08x\n", hr);
882 
883 if (0)
884     hr = IDictionary_Remove(dict, NULL);
885 
886     /* nothing added yet */
887     V_VT(&key) = VT_R4;
888     V_R4(&key) = 0.0;
889     hr = IDictionary_Remove(dict, &key);
890     ok(hr == CTL_E_ELEMENT_NOT_FOUND, "got 0x%08x\n", hr);
891 
892     VariantInit(&item);
893     hr = IDictionary_Add(dict, &key, &item);
894     ok(hr == S_OK, "got 0x%08x\n", hr);
895 
896     hr = IDictionary_Remove(dict, &key);
897     ok(hr == S_OK, "got 0x%08x\n", hr);
898 
899     IDictionary_Release(dict);
900 }
901 
902 static void test_Item(void)
903 {
904     VARIANT key, item;
905     IDictionary *dict;
906     HRESULT hr;
907 
908     hr = CoCreateInstance(&CLSID_Dictionary, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
909             &IID_IDictionary, (void**)&dict);
910     ok(hr == S_OK, "got 0x%08x\n", hr);
911 
912     V_VT(&key) = VT_I2;
913     V_I2(&key) = 10;
914     V_VT(&item) = VT_I2;
915     V_I2(&item) = 123;
916     hr = IDictionary_get_Item(dict, &key, &item);
917     ok(hr == S_OK, "got 0x%08x\n", hr);
918     ok(V_VT(&item) == VT_EMPTY, "got %d\n", V_VT(&item));
919 
920     V_VT(&key) = VT_I2;
921     V_I2(&key) = 10;
922     V_VT(&item) = VT_I2;
923     hr = IDictionary_get_Item(dict, &key, &item);
924     ok(hr == S_OK, "got 0x%08x\n", hr);
925     ok(V_VT(&item) == VT_EMPTY, "got %d\n", V_VT(&item));
926 
927     IDictionary_Release(dict);
928 }
929 
930 static void test_Add(void)
931 {
932     static const WCHAR testW[] = {'t','e','s','t','W',0};
933     VARIANT key, item;
934     IDictionary *dict;
935     HRESULT hr;
936     BSTR str;
937 
938     hr = CoCreateInstance(&CLSID_Dictionary, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
939             &IID_IDictionary, (void**)&dict);
940     ok(hr == S_OK, "got 0x%08x\n", hr);
941 
942     str = SysAllocString(testW);
943     V_VT(&key) = VT_I2;
944     V_I2(&key) = 1;
945     V_VT(&item) = VT_BSTR|VT_BYREF;
946     V_BSTRREF(&item) = &str;
947     hr = IDictionary_Add(dict, &key, &item);
948     ok(hr == S_OK, "got 0x%08x\n", hr);
949 
950     hr = IDictionary_get_Item(dict, &key, &item);
951     ok(hr == S_OK, "got 0x%08x\n", hr);
952     ok(V_VT(&item) == VT_BSTR, "got %d\n", V_VT(&item));
953 
954     SysFreeString(str);
955 
956     IDictionary_Release(dict);
957 }
958 
959 static void test_IEnumVARIANT(void)
960 {
961     IUnknown *enum1, *enum2;
962     IEnumVARIANT *enumvar;
963     VARIANT key, item;
964     IDictionary *dict;
965     ULONG fetched;
966     HRESULT hr;
967 
968     hr = CoCreateInstance(&CLSID_Dictionary, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
969             &IID_IDictionary, (void**)&dict);
970     ok(hr == S_OK, "got 0x%08x\n", hr);
971 
972     if (0) /* crashes on native */
973         hr = IDictionary__NewEnum(dict, NULL);
974 
975     hr = IDictionary__NewEnum(dict, &enum1);
976     ok(hr == S_OK, "got 0x%08x\n", hr);
977 
978     hr = IDictionary__NewEnum(dict, &enum2);
979     ok(hr == S_OK, "got 0x%08x\n", hr);
980     ok(enum1 != enum2, "got %p, %p\n", enum2, enum1);
981     IUnknown_Release(enum2);
982 
983     hr = IUnknown_QueryInterface(enum1, &IID_IEnumVARIANT, (void**)&enumvar);
984     ok(hr == S_OK, "got 0x%08x\n", hr);
985     IUnknown_Release(enum1);
986 
987     /* dictionary is empty */
988     hr = IEnumVARIANT_Skip(enumvar, 1);
989     ok(hr == S_FALSE, "got 0x%08x\n", hr);
990 
991     hr = IEnumVARIANT_Skip(enumvar, 0);
992     ok(hr == S_OK, "got 0x%08x\n", hr);
993 
994     V_VT(&key) = VT_I2;
995     V_I2(&key) = 1;
996     V_VT(&item) = VT_I4;
997     V_I4(&item) = 100;
998     hr = IDictionary_Add(dict, &key, &item);
999     ok(hr == S_OK, "got 0x%08x\n", hr);
1000 
1001     hr = IEnumVARIANT_Skip(enumvar, 0);
1002     ok(hr == S_OK, "got 0x%08x\n", hr);
1003 
1004     hr = IEnumVARIANT_Reset(enumvar);
1005     ok(hr == S_OK, "got 0x%08x\n", hr);
1006     hr = IEnumVARIANT_Skip(enumvar, 1);
1007     ok(hr == S_OK, "got 0x%08x\n", hr);
1008     hr = IEnumVARIANT_Skip(enumvar, 1);
1009     ok(hr == S_FALSE, "got 0x%08x\n", hr);
1010 
1011     V_VT(&key) = VT_I2;
1012     V_I2(&key) = 4000;
1013     V_VT(&item) = VT_I4;
1014     V_I4(&item) = 200;
1015     hr = IDictionary_Add(dict, &key, &item);
1016     ok(hr == S_OK, "got 0x%08x\n", hr);
1017 
1018     V_VT(&key) = VT_I2;
1019     V_I2(&key) = 0;
1020     V_VT(&item) = VT_I4;
1021     V_I4(&item) = 300;
1022     hr = IDictionary_Add(dict, &key, &item);
1023     ok(hr == S_OK, "got 0x%08x\n", hr);
1024 
1025     hr = IEnumVARIANT_Reset(enumvar);
1026     ok(hr == S_OK, "got 0x%08x\n", hr);
1027 
1028     VariantInit(&key);
1029     hr = IEnumVARIANT_Next(enumvar, 1, &key, &fetched);
1030     ok(hr == S_OK, "got 0x%08x\n", hr);
1031     ok(V_VT(&key) == VT_I2, "got %d\n", V_VT(&key));
1032     ok(V_I2(&key) == 1, "got %d\n", V_I2(&key));
1033     ok(fetched == 1, "got %u\n", fetched);
1034 
1035     hr = IEnumVARIANT_Reset(enumvar);
1036     ok(hr == S_OK, "got 0x%08x\n", hr);
1037 
1038     hr = IDictionary_Remove(dict, &key);
1039     ok(hr == S_OK, "got 0x%08x\n", hr);
1040 
1041     VariantInit(&key);
1042     hr = IEnumVARIANT_Next(enumvar, 1, &key, &fetched);
1043     ok(hr == S_OK, "got 0x%08x\n", hr);
1044     ok(V_VT(&key) == VT_I2, "got %d\n", V_VT(&key));
1045     ok(V_I2(&key) == 4000, "got %d\n", V_I2(&key));
1046     ok(fetched == 1, "got %u\n", fetched);
1047 
1048     VariantInit(&key);
1049     hr = IEnumVARIANT_Next(enumvar, 1, &key, &fetched);
1050     ok(hr == S_OK, "got 0x%08x\n", hr);
1051     ok(V_VT(&key) == VT_I2, "got %d\n", V_VT(&key));
1052     ok(V_I2(&key) == 0, "got %d\n", V_I2(&key));
1053     ok(fetched == 1, "got %u\n", fetched);
1054 
1055     /* enumeration reached the bottom, add one more pair */
1056     VariantInit(&key);
1057     hr = IEnumVARIANT_Next(enumvar, 1, &key, &fetched);
1058     ok(hr == S_FALSE, "got 0x%08x\n", hr);
1059 
1060     V_VT(&key) = VT_I2;
1061     V_I2(&key) = 13;
1062     V_VT(&item) = VT_I4;
1063     V_I4(&item) = 350;
1064     hr = IDictionary_Add(dict, &key, &item);
1065     ok(hr == S_OK, "got 0x%08x\n", hr);
1066 
1067     /* still doesn't work until Reset() */
1068     VariantInit(&key);
1069     hr = IEnumVARIANT_Next(enumvar, 1, &key, &fetched);
1070     ok(hr == S_FALSE, "got 0x%08x\n", hr);
1071 
1072     IEnumVARIANT_Release(enumvar);
1073     IDictionary_Release(dict);
1074 }
1075 
1076 START_TEST(dictionary)
1077 {
1078     IDispatch *disp;
1079     HRESULT hr;
1080 
1081     CoInitialize(NULL);
1082 
1083     hr = CoCreateInstance(&CLSID_Dictionary, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
1084             &IID_IDispatch, (void**)&disp);
1085     if(FAILED(hr)) {
1086         win_skip("Dictionary object is not supported: %08x\n", hr);
1087         CoUninitialize();
1088         return;
1089     }
1090     IDispatch_Release(disp);
1091 
1092     test_interfaces();
1093     test_comparemode();
1094     test_hash_value();
1095     test_Exists();
1096     test_Keys();
1097     test_Remove();
1098     test_Item();
1099     test_Add();
1100     test_IEnumVARIANT();
1101 
1102     CoUninitialize();
1103 }
1104