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