scrrun: Added support for interface pointers as keys for dictionary.
This commit is contained in:
parent
c5dda71cd4
commit
5189dc417a
|
@ -38,6 +38,7 @@
|
|||
WINE_DEFAULT_DEBUG_CHANNEL(scrrun);
|
||||
|
||||
#define BUCKET_COUNT 509
|
||||
#define DICT_HASH_MOD 1201
|
||||
|
||||
/* Implementation details
|
||||
|
||||
|
@ -752,12 +753,17 @@ static DWORD get_str_hash(const WCHAR *str, CompareMethod method)
|
|||
}
|
||||
}
|
||||
|
||||
return hash % 1201;
|
||||
return hash % DICT_HASH_MOD;
|
||||
}
|
||||
|
||||
static DWORD get_num_hash(FLOAT num)
|
||||
{
|
||||
return (*((DWORD*)&num)) % 1201;
|
||||
return (*((DWORD*)&num)) % DICT_HASH_MOD;
|
||||
}
|
||||
|
||||
static DWORD get_ptr_hash(void *ptr)
|
||||
{
|
||||
return PtrToUlong(ptr) % DICT_HASH_MOD;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI dictionary_get_HashVal(IDictionary *iface, VARIANT *key, VARIANT *hash)
|
||||
|
@ -782,6 +788,28 @@ static HRESULT WINAPI dictionary_get_HashVal(IDictionary *iface, VARIANT *key, V
|
|||
case VT_I4:
|
||||
V_I4(hash) = get_num_hash(V_I4(key));
|
||||
break;
|
||||
case VT_UNKNOWN|VT_BYREF:
|
||||
case VT_DISPATCH|VT_BYREF:
|
||||
case VT_UNKNOWN:
|
||||
case VT_DISPATCH:
|
||||
{
|
||||
IUnknown *src = (V_VT(key) & VT_BYREF) ? *V_UNKNOWNREF(key) : V_UNKNOWN(key);
|
||||
IUnknown *unk = NULL;
|
||||
|
||||
if (!src) {
|
||||
V_I4(hash) = 0;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
IUnknown_QueryInterface(src, &IID_IUnknown, (void**)&unk);
|
||||
if (!unk) {
|
||||
V_I4(hash) = ~0u;
|
||||
return CTL_E_ILLEGALFUNCTIONCALL;
|
||||
}
|
||||
V_I4(hash) = get_ptr_hash(unk);
|
||||
IUnknown_Release(unk);
|
||||
break;
|
||||
}
|
||||
case VT_R4:
|
||||
case VT_R8:
|
||||
{
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* 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
|
||||
|
@ -160,6 +161,11 @@ 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
|
||||
|
@ -183,6 +189,110 @@ typedef union
|
|||
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, "unxpected\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, "unxpected\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 */
|
||||
|
@ -205,6 +315,9 @@ static void test_hash_value(void)
|
|||
|
||||
IDictionary *dict;
|
||||
VARIANT key, hash;
|
||||
IDispatch *disp;
|
||||
DWORD expected;
|
||||
IUnknown *unk;
|
||||
R8_FIELDS fx8;
|
||||
R4_FIELDS fx4;
|
||||
HRESULT hr;
|
||||
|
@ -223,7 +336,7 @@ static void test_hash_value(void)
|
|||
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++) {
|
||||
DWORD expected = get_str_hash(str_hash_tests[i], BinaryCompare);
|
||||
expected = get_str_hash(str_hash_tests[i], BinaryCompare);
|
||||
|
||||
hr = IDictionary_put_CompareMode(dict, BinaryCompare);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
|
@ -316,7 +429,7 @@ static void test_hash_value(void)
|
|||
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++) {
|
||||
DWORD expected = get_num_hash(int_hash_tests[i]);
|
||||
expected = get_num_hash(int_hash_tests[i]);
|
||||
|
||||
V_VT(&key) = VT_I2;
|
||||
V_I2(&key) = int_hash_tests[i];
|
||||
|
@ -401,7 +514,7 @@ static void test_hash_value(void)
|
|||
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++) {
|
||||
DWORD expected = get_num_hash(float_hash_tests[i]);
|
||||
expected = get_num_hash(float_hash_tests[i]);
|
||||
|
||||
V_VT(&key) = VT_R4;
|
||||
V_R4(&key) = float_hash_tests[i];
|
||||
|
@ -422,6 +535,101 @@ static void test_hash_value(void)
|
|||
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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue