| /* | |
| * Copyright (C) 2012 Alistair Leslie-Hughes | |
| * Copyright 2015 Nikolay Sivov for CodeWeavers | |
| * | |
| * This library is free software; you can redistribute it and/or | |
| * modify it under the terms of the GNU Lesser General Public | |
| * License as published by the Free Software Foundation; either | |
| * version 2.1 of the License, or (at your option) any later version. | |
| * | |
| * This library is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| * Lesser General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU Lesser General Public | |
| * License along with this library; if not, write to the Free Software | |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA | |
| */ | |
| #define COBJMACROS | |
| #include <stdio.h> | |
| #include "windows.h" | |
| #include "ole2.h" | |
| #include "oleauto.h" | |
| #include "olectl.h" | |
| #include "dispex.h" | |
| #include "wine/test.h" | |
| #include "scrrun.h" | |
| #define test_provideclassinfo(a, b) _test_provideclassinfo((IDispatch*)a, b, __LINE__) | |
| static void _test_provideclassinfo(IDispatch *disp, const GUID *guid, int line) | |
| { | |
| IProvideClassInfo *classinfo; | |
| TYPEATTR *attr; | |
| ITypeInfo *ti; | |
| IUnknown *unk; | |
| HRESULT hr; | |
| hr = IDispatch_QueryInterface(disp, &IID_IProvideClassInfo, (void **)&classinfo); | |
| ok_(__FILE__,line) (hr == S_OK, "Failed to get IProvideClassInfo, %#x.\n", hr); | |
| hr = IProvideClassInfo_GetClassInfo(classinfo, &ti); | |
| ok_(__FILE__,line) (hr == S_OK, "GetClassInfo() failed, %#x.\n", hr); | |
| hr = ITypeInfo_GetTypeAttr(ti, &attr); | |
| ok_(__FILE__,line) (hr == S_OK, "GetTypeAttr() failed, %#x.\n", hr); | |
| ok_(__FILE__,line) (IsEqualGUID(&attr->guid, guid), "Unexpected typeinfo %s, expected %s\n", wine_dbgstr_guid(&attr->guid), | |
| wine_dbgstr_guid(guid)); | |
| hr = IProvideClassInfo_QueryInterface(classinfo, &IID_IUnknown, (void **)&unk); | |
| ok(hr == S_OK, "Failed to QI for IUnknown.\n"); | |
| ok(unk == (IUnknown *)disp, "Got unk %p, original %p\n", unk, disp); | |
| IUnknown_Release(unk); | |
| IProvideClassInfo_Release(classinfo); | |
| ITypeInfo_ReleaseTypeAttr(ti, attr); | |
| ITypeInfo_Release(ti); | |
| } | |
| static void test_interfaces(void) | |
| { | |
| static const WCHAR key_add[] = {'a', 0}; | |
| static const WCHAR key_add_value[] = {'a', 0}; | |
| static const WCHAR key_non_exist[] = {'b', 0}; | |
| HRESULT hr; | |
| IDispatch *disp; | |
| IDispatchEx *dispex; | |
| IDictionary *dict; | |
| IObjectWithSite *site; | |
| VARIANT key, value; | |
| VARIANT_BOOL exists; | |
| LONG count = 0; | |
| hr = CoCreateInstance(&CLSID_Dictionary, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, | |
| &IID_IDispatch, (void**)&disp); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| VariantInit(&key); | |
| VariantInit(&value); | |
| hr = IDispatch_QueryInterface(disp, &IID_IDictionary, (void**)&dict); | |
| ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK); | |
| hr = IDispatch_QueryInterface(disp, &IID_IObjectWithSite, (void**)&site); | |
| ok(hr == E_NOINTERFACE, "got 0x%08x, expected 0x%08x\n", hr, E_NOINTERFACE); | |
| hr = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); | |
| ok(hr == E_NOINTERFACE, "got 0x%08x, expected 0x%08x\n", hr, E_NOINTERFACE); | |
| test_provideclassinfo(disp, &CLSID_Dictionary); | |
| V_VT(&key) = VT_BSTR; | |
| V_BSTR(&key) = SysAllocString(key_add); | |
| V_VT(&value) = VT_BSTR; | |
| V_BSTR(&value) = SysAllocString(key_add_value); | |
| hr = IDictionary_Add(dict, &key, &value); | |
| ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK); | |
| VariantClear(&value); | |
| exists = VARIANT_FALSE; | |
| hr = IDictionary_Exists(dict, &key, &exists); | |
| ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK); | |
| ok(exists == VARIANT_TRUE, "Expected TRUE but got FALSE.\n"); | |
| VariantClear(&key); | |
| exists = VARIANT_TRUE; | |
| V_VT(&key) = VT_BSTR; | |
| V_BSTR(&key) = SysAllocString(key_non_exist); | |
| hr = IDictionary_Exists(dict, &key, &exists); | |
| ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK); | |
| ok(exists == VARIANT_FALSE, "Expected FALSE but got TRUE.\n"); | |
| VariantClear(&key); | |
| hr = IDictionary_get_Count(dict, &count); | |
| ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK); | |
| ok(count == 1, "got %d, expected 1\n", count); | |
| IDictionary_Release(dict); | |
| IDispatch_Release(disp); | |
| } | |
| static void test_comparemode(void) | |
| { | |
| CompareMethod method; | |
| IDictionary *dict; | |
| VARIANT key, item; | |
| HRESULT hr; | |
| hr = CoCreateInstance(&CLSID_Dictionary, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, | |
| &IID_IDictionary, (void**)&dict); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| if (0) /* crashes on native */ | |
| hr = IDictionary_get_CompareMode(dict, NULL); | |
| method = 10; | |
| hr = IDictionary_get_CompareMode(dict, &method); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(method == BinaryCompare, "got %d\n", method); | |
| /* invalid mode value is not checked */ | |
| hr = IDictionary_put_CompareMode(dict, 10); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| hr = IDictionary_get_CompareMode(dict, &method); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(method == 10, "got %d\n", method); | |
| hr = IDictionary_put_CompareMode(dict, DatabaseCompare); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| hr = IDictionary_get_CompareMode(dict, &method); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(method == DatabaseCompare, "got %d\n", method); | |
| /* try to change mode of a non-empty dict */ | |
| V_VT(&key) = VT_I2; | |
| V_I2(&key) = 0; | |
| VariantInit(&item); | |
| hr = IDictionary_Add(dict, &key, &item); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| hr = IDictionary_put_CompareMode(dict, BinaryCompare); | |
| ok(hr == CTL_E_ILLEGALFUNCTIONCALL, "got 0x%08x\n", hr); | |
| IDictionary_Release(dict); | |
| } | |
| static DWORD get_str_hash(const WCHAR *str, CompareMethod method) | |
| { | |
| DWORD hash = 0; | |
| while (*str) { | |
| WCHAR ch; | |
| if (method == TextCompare || method == DatabaseCompare) | |
| ch = PtrToInt(CharLowerW(IntToPtr(*str))); | |
| else | |
| ch = *str; | |
| hash += (hash << 4) + ch; | |
| str++; | |
| } | |
| return hash % 1201; | |
| } | |
| static DWORD get_num_hash(FLOAT num) | |
| { | |
| return (*((DWORD*)&num)) % 1201; | |
| } | |
| static DWORD get_ptr_hash(void *ptr) | |
| { | |
| return PtrToUlong(ptr) % 1201; | |
| } | |
| typedef union | |
| { | |
| struct | |
| { | |
| unsigned int m : 23; | |
| unsigned int exp_bias : 8; | |
| unsigned int sign : 1; | |
| } i; | |
| float f; | |
| } R4_FIELDS; | |
| typedef union | |
| { | |
| struct | |
| { | |
| unsigned int m_lo : 32; /* 52 bits of precision */ | |
| unsigned int m_hi : 20; | |
| unsigned int exp_bias : 11; /* bias == 1023 */ | |
| unsigned int sign : 1; | |
| } i; | |
| double d; | |
| } R8_FIELDS; | |
| static HRESULT WINAPI test_unk_QI(IUnknown *iface, REFIID riid, void **obj) | |
| { | |
| if (IsEqualIID(riid, &IID_IUnknown)) { | |
| *obj = iface; | |
| return S_OK; | |
| } | |
| ok(0, "unexpected %s\n", wine_dbgstr_guid(riid)); | |
| *obj = NULL; | |
| return E_NOINTERFACE; | |
| } | |
| static HRESULT WINAPI test_unk_no_QI(IUnknown *iface, REFIID riid, void **obj) | |
| { | |
| *obj = NULL; | |
| return E_NOINTERFACE; | |
| } | |
| static ULONG WINAPI test_unk_AddRef(IUnknown *iface) | |
| { | |
| ok(0, "unexpected\n"); | |
| return 2; | |
| } | |
| static ULONG WINAPI test_unk_Release(IUnknown *iface) | |
| { | |
| return 1; | |
| } | |
| static const IUnknownVtbl test_unk_vtbl = { | |
| test_unk_QI, | |
| test_unk_AddRef, | |
| test_unk_Release | |
| }; | |
| static const IUnknownVtbl test_unk_no_vtbl = { | |
| test_unk_no_QI, | |
| test_unk_AddRef, | |
| test_unk_Release | |
| }; | |
| static HRESULT WINAPI test_disp_QI(IDispatch *iface, REFIID riid, void **obj) | |
| { | |
| if (IsEqualIID(riid, &IID_IDispatch) || IsEqualIID(riid, &IID_IUnknown)) { | |
| *obj = iface; | |
| return S_OK; | |
| } | |
| ok(0, "unexpected %s\n", wine_dbgstr_guid(riid)); | |
| *obj = NULL; | |
| return E_NOINTERFACE; | |
| } | |
| static ULONG WINAPI test_disp_AddRef(IDispatch *iface) | |
| { | |
| ok(0, "unexpected\n"); | |
| return 2; | |
| } | |
| static ULONG WINAPI test_disp_Release(IDispatch *iface) | |
| { | |
| return 1; | |
| } | |
| static HRESULT WINAPI test_disp_GetTypeInfoCount(IDispatch *iface, UINT *count) | |
| { | |
| ok(0, "unexpected call\n"); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI test_disp_GetTypeInfo(IDispatch *iface, UINT index, LCID lcid, ITypeInfo **ti) | |
| { | |
| ok(0, "unexpected call\n"); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI test_disp_GetIDsOfNames(IDispatch *iface, REFIID riid, LPOLESTR *names, | |
| UINT name_count, LCID lcid, DISPID *dispid) | |
| { | |
| ok(0, "unexpected call\n"); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI test_disp_Invoke(IDispatch *iface, DISPID dispid, REFIID riid, | |
| LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *result, EXCEPINFO *excepinfo, UINT *arg_err) | |
| { | |
| ok(0, "unexpected call\n"); | |
| return E_NOTIMPL; | |
| } | |
| static const IDispatchVtbl test_disp_vtbl = { | |
| test_disp_QI, | |
| test_disp_AddRef, | |
| test_disp_Release, | |
| test_disp_GetTypeInfoCount, | |
| test_disp_GetTypeInfo, | |
| test_disp_GetIDsOfNames, | |
| test_disp_Invoke | |
| }; | |
| static IUnknown test_unk = { &test_unk_vtbl }; | |
| static IUnknown test_unk2 = { &test_unk_no_vtbl }; | |
| static IDispatch test_disp = { &test_disp_vtbl }; | |
| static void test_hash_value(void) | |
| { | |
| /* string test data */ | |
| static const WCHAR str_hash_tests[][10] = { | |
| {'a','b','c','d',0}, | |
| {'a','B','C','d','1',0}, | |
| {'1','2','3',0}, | |
| {'A',0}, | |
| {'a',0}, | |
| { 0 } | |
| }; | |
| static const int int_hash_tests[] = { | |
| 0, -1, 100, 1, 255 | |
| }; | |
| static const FLOAT float_hash_tests[] = { | |
| 0.0, -1.0, 100.0, 1.0, 255.0, 1.234 | |
| }; | |
| IDictionary *dict; | |
| VARIANT key, hash; | |
| IDispatch *disp; | |
| DWORD expected; | |
| IUnknown *unk; | |
| R8_FIELDS fx8; | |
| R4_FIELDS fx4; | |
| HRESULT hr; | |
| unsigned i; | |
| hr = CoCreateInstance(&CLSID_Dictionary, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, | |
| &IID_IDictionary, (void**)&dict); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| V_VT(&key) = VT_BSTR; | |
| V_BSTR(&key) = NULL; | |
| VariantInit(&hash); | |
| hr = IDictionary_get_HashVal(dict, &key, &hash); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash)); | |
| ok(V_I4(&hash) == 0, "got %d\n", V_I4(&hash)); | |
| for (i = 0; i < sizeof(str_hash_tests)/sizeof(str_hash_tests[0]); i++) { | |
| expected = get_str_hash(str_hash_tests[i], BinaryCompare); | |
| hr = IDictionary_put_CompareMode(dict, BinaryCompare); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| V_VT(&key) = VT_BSTR; | |
| V_BSTR(&key) = SysAllocString(str_hash_tests[i]); | |
| VariantInit(&hash); | |
| hr = IDictionary_get_HashVal(dict, &key, &hash); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash)); | |
| ok(V_I4(&hash) == expected, "%d: binary mode: got hash 0x%08x, expected 0x%08x\n", i, V_I4(&hash), | |
| expected); | |
| VariantClear(&key); | |
| expected = get_str_hash(str_hash_tests[i], TextCompare); | |
| hr = IDictionary_put_CompareMode(dict, TextCompare); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| V_VT(&key) = VT_BSTR; | |
| V_BSTR(&key) = SysAllocString(str_hash_tests[i]); | |
| VariantInit(&hash); | |
| hr = IDictionary_get_HashVal(dict, &key, &hash); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash)); | |
| ok(V_I4(&hash) == expected, "%d: text mode: got hash 0x%08x, expected 0x%08x\n", i, V_I4(&hash), | |
| expected); | |
| VariantClear(&key); | |
| expected = get_str_hash(str_hash_tests[i], DatabaseCompare); | |
| hr = IDictionary_put_CompareMode(dict, DatabaseCompare); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| V_VT(&key) = VT_BSTR; | |
| V_BSTR(&key) = SysAllocString(str_hash_tests[i]); | |
| VariantInit(&hash); | |
| hr = IDictionary_get_HashVal(dict, &key, &hash); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash)); | |
| ok(V_I4(&hash) == expected, "%d: db mode: got hash 0x%08x, expected 0x%08x\n", i, V_I4(&hash), | |
| expected); | |
| VariantClear(&key); | |
| } | |
| V_VT(&key) = VT_INT; | |
| V_INT(&key) = 1; | |
| VariantInit(&hash); | |
| hr = IDictionary_get_HashVal(dict, &key, &hash); | |
| ok(hr == CTL_E_ILLEGALFUNCTIONCALL || broken(hr == S_OK) /* win2k, win2k3 */, "got 0x%08x\n", hr); | |
| ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash)); | |
| ok(V_I4(&hash) == ~0u, "got hash 0x%08x\n", V_I4(&hash)); | |
| V_VT(&key) = VT_UINT; | |
| V_UINT(&key) = 1; | |
| VariantInit(&hash); | |
| hr = IDictionary_get_HashVal(dict, &key, &hash); | |
| ok(hr == CTL_E_ILLEGALFUNCTIONCALL || broken(hr == S_OK) /* win2k, win2k3 */, "got 0x%08x\n", hr); | |
| ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash)); | |
| ok(V_I4(&hash) == ~0u, "got hash 0x%08x\n", V_I4(&hash)); | |
| V_VT(&key) = VT_I1; | |
| V_I1(&key) = 1; | |
| VariantInit(&hash); | |
| hr = IDictionary_get_HashVal(dict, &key, &hash); | |
| ok(hr == CTL_E_ILLEGALFUNCTIONCALL || broken(hr == S_OK) /* win2k, win2k3 */, "got 0x%08x\n", hr); | |
| ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash)); | |
| ok(V_I4(&hash) == ~0u || broken(V_I4(&hash) == 0xa1), "got hash 0x%08x\n", V_I4(&hash)); | |
| V_VT(&key) = VT_I8; | |
| V_I8(&key) = 1; | |
| VariantInit(&hash); | |
| hr = IDictionary_get_HashVal(dict, &key, &hash); | |
| ok(hr == CTL_E_ILLEGALFUNCTIONCALL || broken(hr == S_OK) /* win2k, win2k3 */, "got 0x%08x\n", hr); | |
| ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash)); | |
| ok(V_I4(&hash) == ~0u, "got hash 0x%08x\n", V_I4(&hash)); | |
| V_VT(&key) = VT_UI2; | |
| V_UI2(&key) = 1; | |
| VariantInit(&hash); | |
| hr = IDictionary_get_HashVal(dict, &key, &hash); | |
| ok(hr == CTL_E_ILLEGALFUNCTIONCALL || broken(hr == S_OK) /* win2k, win2k3 */, "got 0x%08x\n", hr); | |
| ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash)); | |
| ok(V_I4(&hash) == ~0u, "got hash 0x%08x\n", V_I4(&hash)); | |
| V_VT(&key) = VT_UI4; | |
| V_UI4(&key) = 1; | |
| VariantInit(&hash); | |
| hr = IDictionary_get_HashVal(dict, &key, &hash); | |
| ok(hr == CTL_E_ILLEGALFUNCTIONCALL || broken(hr == S_OK) /* win2k, win2k3 */, "got 0x%08x\n", hr); | |
| ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash)); | |
| ok(V_I4(&hash) == ~0u, "got hash 0x%08x\n", V_I4(&hash)); | |
| for (i = 0; i < sizeof(int_hash_tests)/sizeof(int_hash_tests[0]); i++) { | |
| SHORT i2; | |
| BYTE ui1; | |
| LONG i4; | |
| expected = get_num_hash(int_hash_tests[i]); | |
| V_VT(&key) = VT_I2; | |
| V_I2(&key) = int_hash_tests[i]; | |
| VariantInit(&hash); | |
| hr = IDictionary_get_HashVal(dict, &key, &hash); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash)); | |
| ok(V_I4(&hash) == expected, "%d: got hash 0x%08x, expected 0x%08x\n", i, V_I4(&hash), | |
| expected); | |
| i2 = int_hash_tests[i]; | |
| V_VT(&key) = VT_I2|VT_BYREF; | |
| V_I2REF(&key) = &i2; | |
| VariantInit(&hash); | |
| hr = IDictionary_get_HashVal(dict, &key, &hash); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash)); | |
| ok(V_I4(&hash) == expected, "%d: got hash 0x%08x, expected 0x%08x\n", i, V_I4(&hash), | |
| expected); | |
| V_VT(&key) = VT_I4; | |
| V_I4(&key) = int_hash_tests[i]; | |
| VariantInit(&hash); | |
| hr = IDictionary_get_HashVal(dict, &key, &hash); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash)); | |
| ok(V_I4(&hash) == expected, "%d: got hash 0x%08x, expected 0x%08x\n", i, V_I4(&hash), | |
| expected); | |
| i4 = int_hash_tests[i]; | |
| V_VT(&key) = VT_I4|VT_BYREF; | |
| V_I4REF(&key) = &i4; | |
| VariantInit(&hash); | |
| hr = IDictionary_get_HashVal(dict, &key, &hash); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash)); | |
| ok(V_I4(&hash) == expected, "%d: got hash 0x%08x, expected 0x%08x\n", i, V_I4(&hash), | |
| expected); | |
| expected = get_num_hash((FLOAT)(BYTE)int_hash_tests[i]); | |
| V_VT(&key) = VT_UI1; | |
| V_UI1(&key) = int_hash_tests[i]; | |
| VariantInit(&hash); | |
| hr = IDictionary_get_HashVal(dict, &key, &hash); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash)); | |
| ok(V_I4(&hash) == expected, "%d: got hash 0x%08x, expected 0x%08x\n", i, V_I4(&hash), | |
| expected); | |
| ui1 = int_hash_tests[i]; | |
| V_VT(&key) = VT_UI1|VT_BYREF; | |
| V_UI1REF(&key) = &ui1; | |
| VariantInit(&hash); | |
| hr = IDictionary_get_HashVal(dict, &key, &hash); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash)); | |
| ok(V_I4(&hash) == expected, "%d: got hash 0x%08x, expected 0x%08x\n", i, V_I4(&hash), | |
| expected); | |
| } | |
| /* nan */ | |
| fx4.f = 10.0; | |
| fx4.i.exp_bias = 0xff; | |
| V_VT(&key) = VT_R4; | |
| V_R4(&key) = fx4.f; | |
| VariantInit(&hash); | |
| hr = IDictionary_get_HashVal(dict, &key, &hash); | |
| ok(hr == CTL_E_ILLEGALFUNCTIONCALL || broken(hr == S_OK) /* win2k, win2k3 */, "got 0x%08x\n", hr); | |
| ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash)); | |
| ok(V_I4(&hash) == ~0u || broken(V_I4(&hash) == 0 /* win2k */ || | |
| V_I4(&hash) == 0x1f4 /* vista, win2k8 */), "got hash 0x%08x\n", V_I4(&hash)); | |
| /* inf */ | |
| fx4.f = 10.0; | |
| fx4.i.m = 0; | |
| fx4.i.exp_bias = 0xff; | |
| V_VT(&key) = VT_R4; | |
| V_R4(&key) = fx4.f; | |
| V_I4(&hash) = 10; | |
| hr = IDictionary_get_HashVal(dict, &key, &hash); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash)); | |
| ok(V_I4(&hash) == 0, "got hash 0x%08x\n", V_I4(&hash)); | |
| /* nan */ | |
| fx8.d = 10.0; | |
| fx8.i.exp_bias = 0x7ff; | |
| V_VT(&key) = VT_R8; | |
| V_R8(&key) = fx8.d; | |
| VariantInit(&hash); | |
| hr = IDictionary_get_HashVal(dict, &key, &hash); | |
| ok(hr == CTL_E_ILLEGALFUNCTIONCALL || broken(hr == S_OK) /* win2k, win2k3 */, "got 0x%08x\n", hr); | |
| ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash)); | |
| ok(V_I4(&hash) == ~0u || broken(V_I4(&hash) == 0 /* win2k */ || | |
| V_I4(&hash) == 0x1f4 /* vista, win2k8 */), "got hash 0x%08x\n", V_I4(&hash)); | |
| V_VT(&key) = VT_DATE; | |
| V_DATE(&key) = fx8.d; | |
| VariantInit(&hash); | |
| hr = IDictionary_get_HashVal(dict, &key, &hash); | |
| ok(hr == CTL_E_ILLEGALFUNCTIONCALL || broken(hr == S_OK) /* win2k, win2k3 */, "got 0x%08x\n", hr); | |
| ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash)); | |
| ok(V_I4(&hash) == ~0u || broken(V_I4(&hash) == 0 /* win2k */ || | |
| V_I4(&hash) == 0x1f4 /* vista, win2k8 */), "got hash 0x%08x\n", V_I4(&hash)); | |
| /* inf */ | |
| fx8.d = 10.0; | |
| fx8.i.m_lo = 0; | |
| fx8.i.m_hi = 0; | |
| fx8.i.exp_bias = 0x7ff; | |
| V_VT(&key) = VT_R8; | |
| V_R8(&key) = fx8.d; | |
| V_I4(&hash) = 10; | |
| hr = IDictionary_get_HashVal(dict, &key, &hash); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash)); | |
| ok(V_I4(&hash) == 0, "got hash 0x%08x\n", V_I4(&hash)); | |
| V_VT(&key) = VT_DATE; | |
| V_DATE(&key) = fx8.d; | |
| V_I4(&hash) = 10; | |
| hr = IDictionary_get_HashVal(dict, &key, &hash); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash)); | |
| ok(V_I4(&hash) == 0, "got hash 0x%08x\n", V_I4(&hash)); | |
| for (i = 0; i < sizeof(float_hash_tests)/sizeof(float_hash_tests[0]); i++) { | |
| double dbl; | |
| FLOAT flt; | |
| DATE date; | |
| expected = get_num_hash(float_hash_tests[i]); | |
| V_VT(&key) = VT_R4; | |
| V_R4(&key) = float_hash_tests[i]; | |
| VariantInit(&hash); | |
| hr = IDictionary_get_HashVal(dict, &key, &hash); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash)); | |
| ok(V_I4(&hash) == expected, "%d: got hash 0x%08x, expected 0x%08x\n", i, V_I4(&hash), | |
| expected); | |
| flt = float_hash_tests[i]; | |
| V_VT(&key) = VT_R4|VT_BYREF; | |
| V_R4REF(&key) = &flt; | |
| VariantInit(&hash); | |
| hr = IDictionary_get_HashVal(dict, &key, &hash); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash)); | |
| ok(V_I4(&hash) == expected, "%d: got hash 0x%08x, expected 0x%08x\n", i, V_I4(&hash), | |
| expected); | |
| V_VT(&key) = VT_R8; | |
| V_R8(&key) = float_hash_tests[i]; | |
| VariantInit(&hash); | |
| hr = IDictionary_get_HashVal(dict, &key, &hash); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash)); | |
| ok(V_I4(&hash) == expected, "%d: got hash 0x%08x, expected 0x%08x\n", i, V_I4(&hash), | |
| expected); | |
| dbl = float_hash_tests[i]; | |
| V_VT(&key) = VT_R8|VT_BYREF; | |
| V_R8REF(&key) = &dbl; | |
| VariantInit(&hash); | |
| hr = IDictionary_get_HashVal(dict, &key, &hash); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash)); | |
| ok(V_I4(&hash) == expected, "%d: got hash 0x%08x, expected 0x%08x\n", i, V_I4(&hash), | |
| expected); | |
| V_VT(&key) = VT_DATE; | |
| V_DATE(&key) = float_hash_tests[i]; | |
| VariantInit(&hash); | |
| hr = IDictionary_get_HashVal(dict, &key, &hash); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash)); | |
| ok(V_I4(&hash) == expected, "%d: got hash 0x%08x, expected 0x%08x\n", i, V_I4(&hash), | |
| expected); | |
| V_VT(&key) = VT_DATE|VT_BYREF; | |
| date = float_hash_tests[i]; | |
| V_DATEREF(&key) = &date; | |
| VariantInit(&hash); | |
| hr = IDictionary_get_HashVal(dict, &key, &hash); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash)); | |
| ok(V_I4(&hash) == expected, "%d: got hash 0x%08x, expected 0x%08x\n", i, V_I4(&hash), | |
| expected); | |
| } | |
| /* interface pointers as keys */ | |
| V_VT(&key) = VT_UNKNOWN; | |
| V_UNKNOWN(&key) = 0; | |
| VariantInit(&hash); | |
| V_I4(&hash) = 1; | |
| hr = IDictionary_get_HashVal(dict, &key, &hash); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash)); | |
| ok(V_I4(&hash) == 0, "got hash 0x%08x, expected 0\n", V_I4(&hash)); | |
| /* QI doesn't work */ | |
| V_VT(&key) = VT_UNKNOWN; | |
| V_UNKNOWN(&key) = &test_unk2; | |
| VariantInit(&hash); | |
| expected = get_ptr_hash(&test_unk2); | |
| hr = IDictionary_get_HashVal(dict, &key, &hash); | |
| ok(hr == CTL_E_ILLEGALFUNCTIONCALL || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr); | |
| ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash)); | |
| ok(V_I4(&hash) == ~0u, "got hash 0x%08x, expected 0x%08x\n", V_I4(&hash), expected); | |
| V_VT(&key) = VT_UNKNOWN; | |
| V_UNKNOWN(&key) = &test_unk; | |
| VariantInit(&hash); | |
| expected = get_ptr_hash(&test_unk); | |
| hr = IDictionary_get_HashVal(dict, &key, &hash); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash)); | |
| ok(V_I4(&hash) == expected, "got hash 0x%08x, expected 0x%08x\n", V_I4(&hash), expected); | |
| /* interface without IDispatch support */ | |
| V_VT(&key) = VT_DISPATCH; | |
| V_DISPATCH(&key) = (IDispatch*)&test_unk; | |
| VariantInit(&hash); | |
| expected = get_ptr_hash(&test_unk); | |
| hr = IDictionary_get_HashVal(dict, &key, &hash); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash)); | |
| ok(V_I4(&hash) == expected, "got hash 0x%08x, expected 0x%08x\n", V_I4(&hash), expected); | |
| V_VT(&key) = VT_DISPATCH; | |
| V_DISPATCH(&key) = &test_disp; | |
| VariantInit(&hash); | |
| expected = get_ptr_hash(&test_disp); | |
| hr = IDictionary_get_HashVal(dict, &key, &hash); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash)); | |
| ok(V_I4(&hash) == expected, "got hash 0x%08x, expected 0x%08x\n", V_I4(&hash), expected); | |
| /* same with BYREF */ | |
| if (0) { /* crashes on native */ | |
| V_VT(&key) = VT_UNKNOWN|VT_BYREF; | |
| V_UNKNOWNREF(&key) = 0; | |
| hr = IDictionary_get_HashVal(dict, &key, &hash); | |
| } | |
| unk = NULL; | |
| V_VT(&key) = VT_UNKNOWN|VT_BYREF; | |
| V_UNKNOWNREF(&key) = &unk; | |
| VariantInit(&hash); | |
| V_I4(&hash) = 1; | |
| hr = IDictionary_get_HashVal(dict, &key, &hash); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash)); | |
| ok(V_I4(&hash) == 0, "got hash 0x%08x, expected 0\n", V_I4(&hash)); | |
| V_VT(&key) = VT_UNKNOWN|VT_BYREF; | |
| unk = &test_unk; | |
| V_UNKNOWNREF(&key) = &unk; | |
| VariantInit(&hash); | |
| expected = get_ptr_hash(&test_unk); | |
| hr = IDictionary_get_HashVal(dict, &key, &hash); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash)); | |
| ok(V_I4(&hash) == expected, "got hash 0x%08x, expected 0x%08x\n", V_I4(&hash), expected); | |
| /* interface without IDispatch support */ | |
| V_VT(&key) = VT_DISPATCH|VT_BYREF; | |
| unk = &test_unk; | |
| V_DISPATCHREF(&key) = (IDispatch**)&unk; | |
| VariantInit(&hash); | |
| expected = get_ptr_hash(&test_unk); | |
| hr = IDictionary_get_HashVal(dict, &key, &hash); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash)); | |
| ok(V_I4(&hash) == expected, "got hash 0x%08x, expected 0x%08x\n", V_I4(&hash), expected); | |
| V_VT(&key) = VT_DISPATCH|VT_BYREF; | |
| disp = &test_disp; | |
| V_DISPATCHREF(&key) = &disp; | |
| VariantInit(&hash); | |
| expected = get_ptr_hash(&test_disp); | |
| hr = IDictionary_get_HashVal(dict, &key, &hash); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash)); | |
| ok(V_I4(&hash) == expected, "got hash 0x%08x, expected 0x%08x\n", V_I4(&hash), expected); | |
| IDictionary_Release(dict); | |
| } | |
| static void test_Exists(void) | |
| { | |
| VARIANT_BOOL exists; | |
| IDictionary *dict; | |
| VARIANT key, item; | |
| HRESULT hr; | |
| hr = CoCreateInstance(&CLSID_Dictionary, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, | |
| &IID_IDictionary, (void**)&dict); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| if (0) /* crashes on native */ | |
| hr = IDictionary_Exists(dict, NULL, NULL); | |
| V_VT(&key) = VT_I2; | |
| V_I2(&key) = 0; | |
| hr = IDictionary_Exists(dict, &key, NULL); | |
| ok(hr == CTL_E_ILLEGALFUNCTIONCALL, "got 0x%08x\n", hr); | |
| V_VT(&key) = VT_I2; | |
| V_I2(&key) = 0; | |
| exists = VARIANT_TRUE; | |
| hr = IDictionary_Exists(dict, &key, &exists); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(exists == VARIANT_FALSE, "got %x\n", exists); | |
| VariantInit(&item); | |
| hr = IDictionary_Add(dict, &key, &item); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| V_VT(&key) = VT_R4; | |
| V_R4(&key) = 0.0; | |
| hr = IDictionary_Add(dict, &key, &item); | |
| ok(hr == CTL_E_KEY_ALREADY_EXISTS, "got 0x%08x\n", hr); | |
| V_VT(&key) = VT_I2; | |
| V_I2(&key) = 0; | |
| hr = IDictionary_Exists(dict, &key, NULL); | |
| ok(hr == CTL_E_ILLEGALFUNCTIONCALL, "got 0x%08x\n", hr); | |
| V_VT(&key) = VT_I2; | |
| V_I2(&key) = 0; | |
| exists = VARIANT_FALSE; | |
| hr = IDictionary_Exists(dict, &key, &exists); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(exists == VARIANT_TRUE, "got %x\n", exists); | |
| /* key of different type, but resolves to same hash value */ | |
| V_VT(&key) = VT_R4; | |
| V_R4(&key) = 0.0; | |
| exists = VARIANT_FALSE; | |
| hr = IDictionary_Exists(dict, &key, &exists); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(exists == VARIANT_TRUE, "got %x\n", exists); | |
| IDictionary_Release(dict); | |
| } | |
| static void test_Keys(void) | |
| { | |
| VARIANT key, keys, item; | |
| IDictionary *dict; | |
| LONG index; | |
| HRESULT hr; | |
| hr = CoCreateInstance(&CLSID_Dictionary, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, | |
| &IID_IDictionary, (void**)&dict); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| hr = IDictionary_Keys(dict, NULL); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| VariantInit(&keys); | |
| hr = IDictionary_Keys(dict, &keys); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(V_VT(&keys) == (VT_ARRAY|VT_VARIANT), "got %d\n", V_VT(&keys)); | |
| VariantClear(&keys); | |
| V_VT(&key) = VT_R4; | |
| V_R4(&key) = 0.0; | |
| VariantInit(&item); | |
| hr = IDictionary_Add(dict, &key, &item); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| VariantInit(&keys); | |
| hr = IDictionary_Keys(dict, &keys); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(V_VT(&keys) == (VT_ARRAY|VT_VARIANT), "got %d\n", V_VT(&keys)); | |
| VariantInit(&key); | |
| index = 0; | |
| hr = SafeArrayGetElement(V_ARRAY(&keys), &index, &key); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(V_VT(&key) == VT_R4, "got %d\n", V_VT(&key)); | |
| index = SafeArrayGetDim(V_ARRAY(&keys)); | |
| ok(index == 1, "got %d\n", index); | |
| hr = SafeArrayGetUBound(V_ARRAY(&keys), 1, &index); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(index == 0, "got %d\n", index); | |
| VariantClear(&keys); | |
| IDictionary_Release(dict); | |
| } | |
| static void test_Remove(void) | |
| { | |
| VARIANT key, item; | |
| IDictionary *dict; | |
| HRESULT hr; | |
| hr = CoCreateInstance(&CLSID_Dictionary, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, | |
| &IID_IDictionary, (void**)&dict); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| if (0) | |
| hr = IDictionary_Remove(dict, NULL); | |
| /* nothing added yet */ | |
| V_VT(&key) = VT_R4; | |
| V_R4(&key) = 0.0; | |
| hr = IDictionary_Remove(dict, &key); | |
| ok(hr == CTL_E_ELEMENT_NOT_FOUND, "got 0x%08x\n", hr); | |
| VariantInit(&item); | |
| hr = IDictionary_Add(dict, &key, &item); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| hr = IDictionary_Remove(dict, &key); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| IDictionary_Release(dict); | |
| } | |
| static void test_Item(void) | |
| { | |
| VARIANT key, item; | |
| IDictionary *dict; | |
| HRESULT hr; | |
| hr = CoCreateInstance(&CLSID_Dictionary, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, | |
| &IID_IDictionary, (void**)&dict); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| V_VT(&key) = VT_I2; | |
| V_I2(&key) = 10; | |
| V_VT(&item) = VT_I2; | |
| V_I2(&item) = 123; | |
| hr = IDictionary_get_Item(dict, &key, &item); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(V_VT(&item) == VT_EMPTY, "got %d\n", V_VT(&item)); | |
| V_VT(&key) = VT_I2; | |
| V_I2(&key) = 10; | |
| V_VT(&item) = VT_I2; | |
| hr = IDictionary_get_Item(dict, &key, &item); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(V_VT(&item) == VT_EMPTY, "got %d\n", V_VT(&item)); | |
| IDictionary_Release(dict); | |
| } | |
| static void test_Add(void) | |
| { | |
| static const WCHAR testW[] = {'t','e','s','t','W',0}; | |
| VARIANT key, item; | |
| IDictionary *dict; | |
| HRESULT hr; | |
| BSTR str; | |
| hr = CoCreateInstance(&CLSID_Dictionary, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, | |
| &IID_IDictionary, (void**)&dict); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| str = SysAllocString(testW); | |
| V_VT(&key) = VT_I2; | |
| V_I2(&key) = 1; | |
| V_VT(&item) = VT_BSTR|VT_BYREF; | |
| V_BSTRREF(&item) = &str; | |
| hr = IDictionary_Add(dict, &key, &item); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| hr = IDictionary_get_Item(dict, &key, &item); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(V_VT(&item) == VT_BSTR, "got %d\n", V_VT(&item)); | |
| SysFreeString(str); | |
| IDictionary_Release(dict); | |
| } | |
| static void test_IEnumVARIANT(void) | |
| { | |
| IUnknown *enum1, *enum2; | |
| IEnumVARIANT *enumvar; | |
| VARIANT key, item; | |
| IDictionary *dict; | |
| ULONG fetched; | |
| HRESULT hr; | |
| hr = CoCreateInstance(&CLSID_Dictionary, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, | |
| &IID_IDictionary, (void**)&dict); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| if (0) /* crashes on native */ | |
| hr = IDictionary__NewEnum(dict, NULL); | |
| hr = IDictionary__NewEnum(dict, &enum1); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| hr = IDictionary__NewEnum(dict, &enum2); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(enum1 != enum2, "got %p, %p\n", enum2, enum1); | |
| IUnknown_Release(enum2); | |
| hr = IUnknown_QueryInterface(enum1, &IID_IEnumVARIANT, (void**)&enumvar); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| IUnknown_Release(enum1); | |
| /* dictionary is empty */ | |
| hr = IEnumVARIANT_Skip(enumvar, 1); | |
| ok(hr == S_FALSE, "got 0x%08x\n", hr); | |
| hr = IEnumVARIANT_Skip(enumvar, 0); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| V_VT(&key) = VT_I2; | |
| V_I2(&key) = 1; | |
| V_VT(&item) = VT_I4; | |
| V_I4(&item) = 100; | |
| hr = IDictionary_Add(dict, &key, &item); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| hr = IEnumVARIANT_Skip(enumvar, 0); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| hr = IEnumVARIANT_Reset(enumvar); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| hr = IEnumVARIANT_Skip(enumvar, 1); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| hr = IEnumVARIANT_Skip(enumvar, 1); | |
| ok(hr == S_FALSE, "got 0x%08x\n", hr); | |
| V_VT(&key) = VT_I2; | |
| V_I2(&key) = 4000; | |
| V_VT(&item) = VT_I4; | |
| V_I4(&item) = 200; | |
| hr = IDictionary_Add(dict, &key, &item); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| V_VT(&key) = VT_I2; | |
| V_I2(&key) = 0; | |
| V_VT(&item) = VT_I4; | |
| V_I4(&item) = 300; | |
| hr = IDictionary_Add(dict, &key, &item); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| hr = IEnumVARIANT_Reset(enumvar); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| VariantInit(&key); | |
| hr = IEnumVARIANT_Next(enumvar, 1, &key, &fetched); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(V_VT(&key) == VT_I2, "got %d\n", V_VT(&key)); | |
| ok(V_I2(&key) == 1, "got %d\n", V_I2(&key)); | |
| ok(fetched == 1, "got %u\n", fetched); | |
| hr = IEnumVARIANT_Reset(enumvar); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| hr = IDictionary_Remove(dict, &key); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| VariantInit(&key); | |
| hr = IEnumVARIANT_Next(enumvar, 1, &key, &fetched); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(V_VT(&key) == VT_I2, "got %d\n", V_VT(&key)); | |
| ok(V_I2(&key) == 4000, "got %d\n", V_I2(&key)); | |
| ok(fetched == 1, "got %u\n", fetched); | |
| VariantInit(&key); | |
| hr = IEnumVARIANT_Next(enumvar, 1, &key, &fetched); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| ok(V_VT(&key) == VT_I2, "got %d\n", V_VT(&key)); | |
| ok(V_I2(&key) == 0, "got %d\n", V_I2(&key)); | |
| ok(fetched == 1, "got %u\n", fetched); | |
| /* enumeration reached the bottom, add one more pair */ | |
| VariantInit(&key); | |
| hr = IEnumVARIANT_Next(enumvar, 1, &key, &fetched); | |
| ok(hr == S_FALSE, "got 0x%08x\n", hr); | |
| V_VT(&key) = VT_I2; | |
| V_I2(&key) = 13; | |
| V_VT(&item) = VT_I4; | |
| V_I4(&item) = 350; | |
| hr = IDictionary_Add(dict, &key, &item); | |
| ok(hr == S_OK, "got 0x%08x\n", hr); | |
| /* still doesn't work until Reset() */ | |
| VariantInit(&key); | |
| hr = IEnumVARIANT_Next(enumvar, 1, &key, &fetched); | |
| ok(hr == S_FALSE, "got 0x%08x\n", hr); | |
| IEnumVARIANT_Release(enumvar); | |
| IDictionary_Release(dict); | |
| } | |
| START_TEST(dictionary) | |
| { | |
| IDispatch *disp; | |
| HRESULT hr; | |
| CoInitialize(NULL); | |
| hr = CoCreateInstance(&CLSID_Dictionary, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, | |
| &IID_IDispatch, (void**)&disp); | |
| if(FAILED(hr)) { | |
| win_skip("Dictionary object is not supported: %08x\n", hr); | |
| CoUninitialize(); | |
| return; | |
| } | |
| IDispatch_Release(disp); | |
| test_interfaces(); | |
| test_comparemode(); | |
| test_hash_value(); | |
| test_Exists(); | |
| test_Keys(); | |
| test_Remove(); | |
| test_Item(); | |
| test_Add(); | |
| test_IEnumVARIANT(); | |
| CoUninitialize(); | |
| } |