Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
June 2022
- 68 participants
- 3274 messages
[PATCH v2 5/5] d2d1: Implement UnregisterEffect().
by Ziqing Hui
Signed-off-by: Ziqing Hui <zhui(a)codeweavers.com>
---
dlls/d2d1/factory.c | 21 +++++++++++++++++++--
dlls/d2d1/tests/d2d1.c | 28 ++++++++++++++--------------
2 files changed, 33 insertions(+), 16 deletions(-)
diff --git a/dlls/d2d1/factory.c b/dlls/d2d1/factory.c
index 31bad2cdb63..2adcd1bd575 100644
--- a/dlls/d2d1/factory.c
+++ b/dlls/d2d1/factory.c
@@ -963,9 +963,26 @@ done:
static HRESULT STDMETHODCALLTYPE d2d_factory_UnregisterEffect(ID2D1Factory3 *iface, REFCLSID effect_id)
{
- FIXME("iface %p, effect_id %s stub!\n", iface, debugstr_guid(effect_id));
+ struct d2d_factory *factory = impl_from_ID2D1Factory3(iface);
+ struct d2d_effect_reg *iter, *iter2;
- return E_NOTIMPL;
+ TRACE("iface %p, effect_id %s.\n", iface, debugstr_guid(effect_id));
+
+ LIST_FOR_EACH_ENTRY_SAFE(iter, iter2, &factory->effect_regs, struct d2d_effect_reg, entry)
+ {
+ if (IsEqualGUID(effect_id, &iter->id))
+ {
+ --iter->count;
+ if (!iter->count)
+ {
+ list_remove(&iter->entry);
+ d2d_effect_reg_cleanup(iter);
+ }
+ return S_OK;
+ }
+ }
+
+ return D2DERR_EFFECT_IS_NOT_REGISTERED;
}
static HRESULT STDMETHODCALLTYPE d2d_factory_GetRegisteredEffects(ID2D1Factory3 *iface,
diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c
index 970706bc569..76b10f3339e 100644
--- a/dlls/d2d1/tests/d2d1.c
+++ b/dlls/d2d1/tests/d2d1.c
@@ -10772,7 +10772,8 @@ static void test_effect_register(BOOL d3d11)
winetest_push_context("Test %u", i);
hr = ID2D1Factory1_RegisterEffectFromString(factory, &CLSID_TestEffect, test->xml, NULL, 0, effect_impl_create);
- todo_wine_if(test->hr != S_OK)
+ todo_wine_if(test->xml == effect_xml_min_max_inputs_a
+ || test->xml == effect_xml_without_inputs)
ok(hr == test->hr, "Got unexpected hr %#lx, expected %#lx.\n", hr, test->hr);
if (hr == S_OK)
{
@@ -10780,9 +10781,9 @@ static void test_effect_register(BOOL d3d11)
hr = ID2D1DeviceContext_CreateEffect(device_context, &CLSID_TestEffect, &effect);
todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
hr = ID2D1Factory1_UnregisterEffect(factory, &CLSID_TestEffect);
- todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
hr = ID2D1Factory1_UnregisterEffect(factory, &CLSID_TestEffect);
- todo_wine ok(hr == D2DERR_EFFECT_IS_NOT_REGISTERED, "Got unexpected hr %#lx.\n", hr);
+ ok(hr == D2DERR_EFFECT_IS_NOT_REGISTERED, "Got unexpected hr %#lx.\n", hr);
if (effect)
ID2D1Effect_Release(effect);
}
@@ -10805,11 +10806,11 @@ static void test_effect_register(BOOL d3d11)
hr = ID2D1Factory1_RegisterEffectFromString(factory, &CLSID_TestEffect, test->xml, NULL, 0, effect_impl_create);
ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
hr = ID2D1Factory1_UnregisterEffect(factory, &CLSID_TestEffect);
- todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
hr = ID2D1Factory1_UnregisterEffect(factory, &CLSID_TestEffect);
- todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
hr = ID2D1Factory1_UnregisterEffect(factory, &CLSID_TestEffect);
- todo_wine ok(hr == D2DERR_EFFECT_IS_NOT_REGISTERED, "Got unexpected hr %#lx.\n", hr);
+ ok(hr == D2DERR_EFFECT_IS_NOT_REGISTERED, "Got unexpected hr %#lx.\n", hr);
winetest_pop_context();
}
@@ -10844,9 +10845,9 @@ static void test_effect_register(BOOL d3d11)
}
hr = ID2D1Factory1_UnregisterEffect(factory, &CLSID_TestEffect);
- todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
hr = ID2D1Factory1_UnregisterEffect(factory, &CLSID_TestEffect);
- todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
/* Register effect with property binding */
for (i = 0; i < ARRAY_SIZE(binding_tests); ++i)
@@ -10905,13 +10906,13 @@ static void test_effect_register(BOOL d3d11)
}
hr = ID2D1Factory1_UnregisterEffect(factory, &CLSID_TestEffect);
- todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
hr = ID2D1Factory1_UnregisterEffect(factory, &CLSID_TestEffect);
- todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
/* Unregister builtin effect */
hr = ID2D1Factory1_UnregisterEffect(factory, &CLSID_D2D1Composite);
- todo_wine ok(hr == D2DERR_EFFECT_IS_NOT_REGISTERED, "Got unexpected hr %#lx.\n", hr);
+ ok(hr == D2DERR_EFFECT_IS_NOT_REGISTERED, "Got unexpected hr %#lx.\n", hr);
release_test_context(&ctx);
}
@@ -10989,7 +10990,6 @@ done:
if (effect)
ID2D1Effect_Release(effect);
hr = ID2D1Factory1_UnregisterEffect(factory, &CLSID_TestEffect);
- todo_wine
ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
release_test_context(&ctx);
}
@@ -11147,7 +11147,7 @@ static void test_effect_properties(BOOL d3d11)
if (effect)
ID2D1Effect_Release(effect);
hr = ID2D1Factory1_UnregisterEffect(factory, &CLSID_TestEffect);
- todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
winetest_pop_context();
}
@@ -11240,7 +11240,7 @@ done:
if (effect)
ID2D1Effect_Release(effect);
hr = ID2D1Factory1_UnregisterEffect(factory, &CLSID_TestEffect);
- todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
release_test_context(&ctx);
}
--
2.25.1
June 12, 2022
[PATCH v2 4/5] d2d1: Implement RegisterEffectFromString().
by Ziqing Hui
Signed-off-by: Ziqing Hui <zhui(a)codeweavers.com>
---
v2: Write then seek.
dlls/d2d1/factory.c | 24 +++++++++++++++++++++---
1 file changed, 21 insertions(+), 3 deletions(-)
diff --git a/dlls/d2d1/factory.c b/dlls/d2d1/factory.c
index 0bffae15ff6..31bad2cdb63 100644
--- a/dlls/d2d1/factory.c
+++ b/dlls/d2d1/factory.c
@@ -937,10 +937,28 @@ static HRESULT STDMETHODCALLTYPE d2d_factory_RegisterEffectFromString(ID2D1Facto
REFCLSID effect_id, const WCHAR *property_xml, const D2D1_PROPERTY_BINDING *bindings,
UINT32 binding_count, PD2D1_EFFECT_FACTORY effect_factory)
{
- FIXME("iface %p, effect_id %s, property_xml %s, bindings %p, binding_count %u, effect_factory %p stub!\n",
- iface, debugstr_guid(effect_id), debugstr_w(property_xml), bindings, binding_count, effect_factory);
+ static const LARGE_INTEGER zero;
+ IStream *stream;
+ ULONG size;
+ HRESULT hr;
- return S_OK;
+ TRACE("iface %p, effect_id %s, property_xml %s, bindings %p, binding_count %u, effect_factory %p.\n",
+ iface, debugstr_guid(effect_id), debugstr_w(property_xml), bindings, binding_count, effect_factory);
+
+ if (FAILED(hr = CreateStreamOnHGlobal(NULL, TRUE, &stream)))
+ return hr;
+
+ size = sizeof(*property_xml) * (wcslen(property_xml) + 1);
+ if (FAILED(hr = IStream_Write(stream, property_xml, size, NULL)))
+ goto done;
+ if (FAILED(hr = IStream_Seek(stream, zero, SEEK_SET, NULL)))
+ goto done;
+
+ hr = ID2D1Factory3_RegisterEffectFromStream(iface, effect_id, stream, bindings, binding_count, effect_factory);
+
+done:
+ IStream_Release(stream);
+ return hr;
}
static HRESULT STDMETHODCALLTYPE d2d_factory_UnregisterEffect(ID2D1Factory3 *iface, REFCLSID effect_id)
--
2.25.1
June 12, 2022
[PATCH v2 3/5] d2d1: Implement property parsing for RegisterEffectFromStream().
by Ziqing Hui
Signed-off-by: Ziqing Hui <zhui(a)codeweavers.com>
---
v2: Rework.
dlls/d2d1/d2d1_private.h | 25 +++++
dlls/d2d1/factory.c | 203 ++++++++++++++++++++++++++++++++++++++-
2 files changed, 226 insertions(+), 2 deletions(-)
diff --git a/dlls/d2d1/d2d1_private.h b/dlls/d2d1/d2d1_private.h
index efc9247a822..b57c971a2ce 100644
--- a/dlls/d2d1/d2d1_private.h
+++ b/dlls/d2d1/d2d1_private.h
@@ -603,6 +603,15 @@ struct d2d_effect_context
void d2d_effect_context_init(struct d2d_effect_context *effect_context,
struct d2d_device_context *device_context) DECLSPEC_HIDDEN;
+struct d2d_effect_property
+{
+ WCHAR *name;
+ D2D1_PROPERTY_TYPE type;
+ BYTE *value;
+ PD2D1_PROPERTY_SET_FUNCTION set_function;
+ PD2D1_PROPERTY_GET_FUNCTION get_function;
+};
+
struct d2d_effect_info
{
const CLSID *clsid;
@@ -768,4 +777,20 @@ static inline const char *debug_d2d_ellipse(const D2D1_ELLIPSE *ellipse)
ellipse->point.x, ellipse->point.y, ellipse->radiusX, ellipse->radiusY);
}
+static inline WCHAR *heap_strdupW(const WCHAR *str)
+{
+ WCHAR *ret = NULL;
+ size_t size;
+
+ if(!str)
+ return ret;
+
+ size = (wcslen(str) + 1) * sizeof(*str);
+ if(!(ret = heap_alloc(size)))
+ return ret;
+ memcpy(ret, str, size);
+
+ return ret;
+}
+
#endif /* __WINE_D2D1_PRIVATE_H */
diff --git a/dlls/d2d1/factory.c b/dlls/d2d1/factory.c
index 38b5c59e879..0bffae15ff6 100644
--- a/dlls/d2d1/factory.c
+++ b/dlls/d2d1/factory.c
@@ -37,6 +37,11 @@ struct d2d_effect_reg
UINT32 input_count;
+ struct d2d_effect_property *properties;
+ size_t property_size;
+ size_t property_count;
+ size_t system_property_count;
+
struct list entry;
};
@@ -68,9 +73,18 @@ static inline struct d2d_factory *impl_from_ID2D1Multithread(ID2D1Multithread *i
static void d2d_effect_reg_cleanup(struct d2d_effect_reg *reg)
{
+ size_t i;
+
if (!reg)
return;
+ for (i = 0; i < reg->property_count; ++i)
+ {
+ heap_free(reg->properties[i].name);
+ heap_free(reg->properties[i].value);
+ }
+ heap_free(reg->properties);
+
heap_free(reg);
}
@@ -603,10 +617,168 @@ static BOOL next_xml_node(IXmlReader *xml_reader, XmlNodeType *node_type, const
return S_FALSE;
}
+static HRESULT heap_get_attr(IXmlReader *xml_reader, const WCHAR *name, WCHAR **ptr)
+{
+ const WCHAR *attr_value;
+
+ *ptr = NULL;
+
+ if (IXmlReader_MoveToAttributeByName(xml_reader, name, NULL) != S_OK)
+ return E_INVALIDARG;
+ if (IXmlReader_GetValue(xml_reader, &attr_value, NULL) != S_OK)
+ return E_INVALIDARG;
+ if (!(*ptr = heap_strdupW(attr_value)))
+ return E_OUTOFMEMORY;
+
+ return S_OK;
+}
+
+static HRESULT get_property_type(IXmlReader *xml_reader, D2D1_PROPERTY_TYPE *type)
+{
+ const WCHAR *str;
+ unsigned int i;
+
+ static const WCHAR *type_str[] =
+ {
+ L"", /* D2D1_PROPERTY_TYPE_UNKNOWN */
+ L"string", /* D2D1_PROPERTY_TYPE_STRING */
+ L"bool", /* D2D1_PROPERTY_TYPE_BOOL */
+ L"uint32", /* D2D1_PROPERTY_TYPE_UINT32 */
+ L"int32", /* D2D1_PROPERTY_TYPE_INT32 */
+ L"float", /* D2D1_PROPERTY_TYPE_FLOAT */
+ L"vector2", /* D2D1_PROPERTY_TYPE_VECTOR2 */
+ L"vector3", /* D2D1_PROPERTY_TYPE_VECTOR3 */
+ L"vector4", /* D2D1_PROPERTY_TYPE_VECTOR4 */
+ L"blob", /* D2D1_PROPERTY_TYPE_BLOB */
+ L"iunknown", /* D2D1_PROPERTY_TYPE_IUNKNOWN */
+ L"enum", /* D2D1_PROPERTY_TYPE_ENUM */
+ L"array", /* D2D1_PROPERTY_TYPE_ARRAY */
+ L"clsid", /* D2D1_PROPERTY_TYPE_CLSID */
+ L"matrix3x2", /* D2D1_PROPERTY_TYPE_MATRIX_3X2 */
+ L"matrix4x3", /* D2D1_PROPERTY_TYPE_MATRIX_4X3 */
+ L"matrix4x4", /* D2D1_PROPERTY_TYPE_MATRIX_4X4 */
+ L"matrix5x4", /* D2D1_PROPERTY_TYPE_MATRIX_5X4 */
+ L"colorcontext", /* D2D1_PROPERTY_TYPE_COLOR_CONTEXT */
+ };
+
+ if (IXmlReader_MoveToAttributeByName(xml_reader, L"type", NULL) != S_OK)
+ return E_INVALIDARG;
+ if (IXmlReader_GetValue(xml_reader, &str, NULL) != S_OK)
+ return E_INVALIDARG;
+
+ for (i = 0; i < ARRAY_SIZE(type_str); ++i)
+ {
+ if (!wcscmp(str, type_str[i]))
+ {
+ *type = i;
+ return S_OK;
+ }
+ }
+
+ return E_INVALIDARG;
+}
+
+static HRESULT add_property(struct d2d_effect_reg *reg, WCHAR *name, D2D1_PROPERTY_TYPE type, BYTE *value)
+{
+ struct d2d_effect_property *entry;
+
+ if (!d2d_array_reserve((void **)®->properties, ®->property_size, reg->property_count + 1, sizeof(*reg->properties)))
+ {
+ ERR("Failed to resize properties array.\n");
+ return E_OUTOFMEMORY;
+ }
+
+ if (!wcscmp(name, L"DisplayName")
+ || !wcscmp(name, L"Author")
+ || !wcscmp(name, L"Category")
+ || !wcscmp(name, L"Description"))
+ {
+ if (type != D2D1_PROPERTY_TYPE_STRING)
+ return E_INVALIDARG;
+ ++reg->system_property_count;
+ }
+
+ entry = ®->properties[reg->property_count++];
+ entry->name = name;
+ entry->type = type;
+ entry->value = value;
+ entry->set_function = NULL;
+ entry->get_function = NULL;
+
+ return S_OK;
+}
+
+static HRESULT parse_sub_property(IXmlReader *xml_reader, struct d2d_effect_reg *reg)
+{
+ /* FIXME: Sub property is ignored. */
+ return S_OK;
+}
+
static HRESULT parse_property(IXmlReader *xml_reader, struct d2d_effect_reg *reg)
{
- /* FIXME: Property parsing is not implemented. */
- return S_OK;
+ WCHAR *name = NULL, *value = NULL;
+ D2D1_PROPERTY_TYPE type;
+ const WCHAR *node_name;
+ XmlNodeType node_type;
+ BOOL end_node_found;
+ unsigned int i;
+ HRESULT hr;
+
+ /* Get property name, type, value */
+ if (FAILED(hr = heap_get_attr(xml_reader, L"name", &name)))
+ return hr;
+ if (FAILED(hr = get_property_type(xml_reader, &type)))
+ goto done;
+ heap_get_attr(xml_reader, L"value", &value);
+
+ /* Check if property is already set */
+ for (i = 0; i < reg->property_count; ++i)
+ {
+ if (!wcscmp(name, reg->properties[i].name))
+ {
+ hr = E_INVALIDARG;
+ goto done;
+ }
+ }
+
+ /* Parse sub properties */
+ if (FAILED(hr = IXmlReader_MoveToElement(xml_reader)))
+ goto done;
+ if (!IXmlReader_IsEmptyElement(xml_reader))
+ {
+ end_node_found = FALSE;
+ while ((hr = next_xml_node(xml_reader, &node_type, &node_name)) == S_OK)
+ {
+ if (node_type == XmlNodeType_Element && !wcscmp(node_name, L"Property"))
+ {
+ if (FAILED(hr = parse_sub_property(xml_reader, reg)))
+ goto done;
+ }
+ else if (node_type == XmlNodeType_EndElement && !wcscmp(node_name, L"Property"))
+ {
+ end_node_found = TRUE;
+ break;
+ }
+ }
+
+ if (FAILED(hr) || !end_node_found)
+ {
+ hr = E_INVALIDARG;
+ goto done;
+ }
+ }
+
+ /* Add property to array */
+ hr = add_property(reg, name, type, (BYTE *)value);
+
+done:
+ if (hr != S_OK)
+ {
+ heap_free(value);
+ heap_free(name);
+ }
+
+ return hr;
}
static HRESULT parse_inputs(IXmlReader *xml_reader, struct d2d_effect_reg *reg)
@@ -700,6 +872,7 @@ static HRESULT STDMETHODCALLTYPE d2d_factory_RegisterEffectFromStream(ID2D1Facto
{
struct d2d_factory *factory = impl_from_ID2D1Factory3(iface);
struct d2d_effect_reg *iter, *entry = NULL;
+ unsigned int i, j;
HRESULT hr;
TRACE("iface %p, effect_id %s, property_xml %p, bindings %p, binding_count %u, effect_factory %p.\n",
@@ -723,6 +896,32 @@ static HRESULT STDMETHODCALLTYPE d2d_factory_RegisterEffectFromStream(ID2D1Facto
if (FAILED(hr = parse_effect_xml(property_xml, entry)))
goto done;
+ /* System properties: DisplayName, Author, Category, Description are required */
+ if (entry->system_property_count != 4)
+ {
+ hr = E_INVALIDARG;
+ goto done;
+ }
+
+ /* bind getter and setter to properties */
+ for (i = 0; i < binding_count; ++i)
+ {
+ for (j = 0; j < entry->property_count; ++j)
+ {
+ if (!wcscmp(bindings[i].propertyName, entry->properties[j].name))
+ {
+ entry->properties[j].get_function = bindings[i].getFunction;
+ entry->properties[j].set_function = bindings[i].setFunction;
+ break;
+ }
+ }
+ if (j > entry->property_count)
+ {
+ hr = D2DERR_INVALID_PROPERTY;
+ goto done;
+ }
+ }
+
entry->count = 1;
entry->id = *effect_id;
entry->factory = effect_factory;
--
2.25.1
June 12, 2022
[PATCH v2 2/5] d2d1: Partially implement RegisterEffectFromStream().
by Ziqing Hui
Signed-off-by: Ziqing Hui <zhui(a)codeweavers.com>
---
v2: Rework.
dlls/d2d1/Makefile.in | 2 +-
dlls/d2d1/factory.c | 165 +++++++++++++++++++++++++++++++++++++++++-
system_property_count | 0
3 files changed, 164 insertions(+), 3 deletions(-)
create mode 100644 system_property_count
diff --git a/dlls/d2d1/Makefile.in b/dlls/d2d1/Makefile.in
index 413571338ba..2456c63c336 100644
--- a/dlls/d2d1/Makefile.in
+++ b/dlls/d2d1/Makefile.in
@@ -1,6 +1,6 @@
MODULE = d2d1.dll
IMPORTLIB = d2d1
-IMPORTS = d3d10_1 dxguid uuid gdi32 user32 advapi32
+IMPORTS = d3d10_1 dxguid uuid gdi32 user32 advapi32 ole32 xmllite
DELAYIMPORTS = dwrite
C_SRCS = \
diff --git a/dlls/d2d1/factory.c b/dlls/d2d1/factory.c
index 01dac8051c0..38b5c59e879 100644
--- a/dlls/d2d1/factory.c
+++ b/dlls/d2d1/factory.c
@@ -18,6 +18,8 @@
#define D2D1_INIT_GUID
#include "d2d1_private.h"
+#include "xmllite.h"
+#include "wine/list.h"
WINE_DECLARE_DEBUG_CHANNEL(winediag);
WINE_DEFAULT_DEBUG_CHANNEL(d2d);
@@ -27,6 +29,17 @@ struct d2d_settings d2d_settings =
~0u, /* No ID2D1Factory version limit by default. */
};
+struct d2d_effect_reg
+{
+ CLSID id;
+ PD2D1_EFFECT_FACTORY factory;
+ UINT32 count;
+
+ UINT32 input_count;
+
+ struct list entry;
+};
+
struct d2d_factory
{
ID2D1Factory3 ID2D1Factory3_iface;
@@ -39,6 +52,8 @@ struct d2d_factory
float dpi_y;
CRITICAL_SECTION cs;
+
+ struct list effect_regs;
};
static inline struct d2d_factory *impl_from_ID2D1Factory3(ID2D1Factory3 *iface)
@@ -51,6 +66,14 @@ static inline struct d2d_factory *impl_from_ID2D1Multithread(ID2D1Multithread *i
return CONTAINING_RECORD(iface, struct d2d_factory, ID2D1Multithread_iface);
}
+static void d2d_effect_reg_cleanup(struct d2d_effect_reg *reg)
+{
+ if (!reg)
+ return;
+
+ heap_free(reg);
+}
+
static HRESULT d2d_factory_reload_sysmetrics(struct d2d_factory *factory)
{
HDC hdc;
@@ -112,6 +135,7 @@ static ULONG STDMETHODCALLTYPE d2d_factory_Release(ID2D1Factory3 *iface)
{
struct d2d_factory *factory = impl_from_ID2D1Factory3(iface);
ULONG refcount = InterlockedDecrement(&factory->refcount);
+ struct d2d_effect_reg *iter, *iter2;
TRACE("%p decreasing refcount to %lu.\n", iface, refcount);
@@ -120,6 +144,8 @@ static ULONG STDMETHODCALLTYPE d2d_factory_Release(ID2D1Factory3 *iface)
if (factory->device)
ID3D10Device1_Release(factory->device);
DeleteCriticalSection(&factory->cs);
+ LIST_FOR_EACH_ENTRY_SAFE(iter, iter2, &factory->effect_regs, struct d2d_effect_reg, entry)
+ d2d_effect_reg_cleanup(iter);
heap_free(factory);
}
@@ -564,14 +590,148 @@ static HRESULT STDMETHODCALLTYPE d2d_factory_CreateGdiMetafile(ID2D1Factory3 *if
return E_NOTIMPL;
}
+static BOOL next_xml_node(IXmlReader *xml_reader, XmlNodeType *node_type, const WCHAR **node_name)
+{
+ while (IXmlReader_Read(xml_reader, node_type) == S_OK)
+ {
+ if (*node_type == XmlNodeType_Whitespace)
+ continue;
+ if (FAILED(IXmlReader_GetLocalName(xml_reader, node_name, NULL)))
+ return E_INVALIDARG;
+ return S_OK;
+ }
+ return S_FALSE;
+}
+
+static HRESULT parse_property(IXmlReader *xml_reader, struct d2d_effect_reg *reg)
+{
+ /* FIXME: Property parsing is not implemented. */
+ return S_OK;
+}
+
+static HRESULT parse_inputs(IXmlReader *xml_reader, struct d2d_effect_reg *reg)
+{
+ const WCHAR *node_name;
+ XmlNodeType node_type;
+
+ if (IXmlReader_IsEmptyElement(xml_reader))
+ return S_OK;
+
+ while (next_xml_node(xml_reader, &node_type, &node_name) == S_OK)
+ {
+ if (node_type == XmlNodeType_Element && !wcscmp(node_name, L"Input"))
+ {
+ ++reg->input_count;
+ /* FIXME: Name attribute of input is ignored. */
+ }
+ else if (node_type == XmlNodeType_EndElement && !wcscmp(node_name, L"Inputs"))
+ {
+ return S_OK;
+ }
+ else
+ {
+ return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
+ }
+ }
+
+ return E_INVALIDARG;
+}
+
+static HRESULT parse_effect_xml(IStream *property_xml, struct d2d_effect_reg *reg)
+{
+ IXmlReader *xml_reader;
+ const WCHAR *node_name;
+ XmlNodeType node_type;
+ BOOL end_node_found;
+ HRESULT hr;
+
+ if (FAILED(hr = CreateXmlReader(&IID_IXmlReader, (void **)&xml_reader, NULL)))
+ return hr;
+ if (FAILED(hr = IXmlReader_SetInput(xml_reader, (IUnknown *)property_xml)))
+ goto done;
+
+ /* Read version node */
+ if (next_xml_node(xml_reader, &node_type, &node_name) != S_OK || node_type != XmlNodeType_XmlDeclaration)
+ {
+ hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
+ goto done;
+ }
+
+ /* Read effect node */
+ if (next_xml_node(xml_reader, &node_type, &node_name) != S_OK
+ || node_type != XmlNodeType_Element || wcscmp(node_name, L"Effect") != 0)
+ {
+ hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
+ goto done;
+ }
+
+ /* Loop inside effect node */
+ end_node_found = FALSE;
+ while ((hr = next_xml_node(xml_reader, &node_type, &node_name)) == S_OK)
+ {
+ if (node_type == XmlNodeType_Element)
+ {
+ if (!wcscmp(node_name, L"Property"))
+ hr = parse_property(xml_reader, reg);
+ else if (!wcscmp(node_name, L"Inputs"))
+ hr = parse_inputs(xml_reader, reg);
+ else
+ hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
+
+ if (FAILED(hr))
+ goto done;
+ }
+ else if (node_type == XmlNodeType_EndElement && !wcscmp(node_name, L"Effect"))
+ {
+ end_node_found = TRUE;
+ break;
+ }
+ }
+ hr = (SUCCEEDED(hr) && end_node_found) ? S_OK : E_INVALIDARG;
+
+done:
+ IXmlReader_Release(xml_reader);
+ return hr;
+}
+
static HRESULT STDMETHODCALLTYPE d2d_factory_RegisterEffectFromStream(ID2D1Factory3 *iface,
REFCLSID effect_id, IStream *property_xml, const D2D1_PROPERTY_BINDING *bindings,
UINT32 binding_count, PD2D1_EFFECT_FACTORY effect_factory)
{
- FIXME("iface %p, effect_id %s, property_xml %p, bindings %p, binding_count %u, effect_factory %p stub!\n",
+ struct d2d_factory *factory = impl_from_ID2D1Factory3(iface);
+ struct d2d_effect_reg *iter, *entry = NULL;
+ HRESULT hr;
+
+ TRACE("iface %p, effect_id %s, property_xml %p, bindings %p, binding_count %u, effect_factory %p.\n",
iface, debugstr_guid(effect_id), property_xml, bindings, binding_count, effect_factory);
- return E_NOTIMPL;
+ LIST_FOR_EACH_ENTRY(iter, &factory->effect_regs, struct d2d_effect_reg, entry)
+ {
+ if (IsEqualGUID(effect_id, &iter->id))
+ {
+ ++iter->count;
+ return S_OK;
+ }
+ }
+
+ if (!(entry = heap_alloc_zero(sizeof(*entry))))
+ {
+ hr = E_OUTOFMEMORY;
+ goto done;
+ }
+
+ if (FAILED(hr = parse_effect_xml(property_xml, entry)))
+ goto done;
+
+ entry->count = 1;
+ entry->id = *effect_id;
+ entry->factory = effect_factory;
+ list_add_tail(&factory->effect_regs, &entry->entry);
+
+done:
+ if (hr != S_OK)
+ d2d_effect_reg_cleanup(entry);
+ return hr;
}
static HRESULT STDMETHODCALLTYPE d2d_factory_RegisterEffectFromString(ID2D1Factory3 *iface,
@@ -743,6 +903,7 @@ static void d2d_factory_init(struct d2d_factory *factory, D2D1_FACTORY_TYPE fact
factory->refcount = 1;
d2d_factory_reload_sysmetrics(factory);
InitializeCriticalSection(&factory->cs);
+ list_init(&factory->effect_regs);
}
HRESULT WINAPI D2D1CreateFactory(D2D1_FACTORY_TYPE factory_type, REFIID iid,
diff --git a/system_property_count b/system_property_count
new file mode 100644
index 00000000000..e69de29bb2d
--
2.25.1
June 12, 2022
[PATCH v2 1/5] d2d1/tests: Add more test xml.
by Ziqing Hui
Signed-off-by: Ziqing Hui <zhui(a)codeweavers.com>
---
v2: Add case tests and min/max inputs tests.
dlls/d2d1/tests/d2d1.c | 120 ++++++++++++++++++++++++++++++++++++++---
1 file changed, 112 insertions(+), 8 deletions(-)
diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c
index bc662b4f8ae..970706bc569 100644
--- a/dlls/d2d1/tests/d2d1.c
+++ b/dlls/d2d1/tests/d2d1.c
@@ -99,6 +99,17 @@ L"<?xml version='1.0'?> \
</Effect> \
";
+static const WCHAR *effect_xml_inputs_attribute =
+L"<?xml version='1.0'?> \
+ <Effect> \
+ <Property name='DisplayName' type='string'/> \
+ <Property name='Author' type='string'/> \
+ <Property name='Category' type='string'/> \
+ <Property name='Description' type='string'/> \
+ <Inputs min='1' max='10' deadbeef='abcdef'/> \
+ </Effect> \
+";
+
static const WCHAR *effect_xml_without_version =
L"<Effect> \
<Property name='DisplayName' type='string'/> \
@@ -170,6 +181,90 @@ L"<?xml version='1.0'?> \
</Effect> \
";
+static const WCHAR *effect_xml_wrong_type =
+L"<?xml version='1.0'?> \
+ <Effect> \
+ <Property name='DisplayName' type='string' value='TestEffect'/> \
+ <Property name='Author' type='uint32' value='32'/> \
+ <Property name='Category' type='string' value='Test'/> \
+ <Property name='Description' type='string' value='Test effect.'/> \
+ <Inputs/> \
+ </Effect> \
+";
+
+static const WCHAR *effect_xml_duplicate_property =
+L"<?xml version='1.0'?> \
+ <Effect> \
+ <Property name='DisplayName' type='string'/> \
+ <Property name='Author' type='string'/> \
+ <Property name='Category' type='string'/> \
+ <Property name='Description' type='string'/> \
+ <Property name='Description' type='string'/> \
+ <Inputs/> \
+ </Effect> \
+";
+
+static const WCHAR *effect_xml_lower_case_effect =
+L"<?xml version='1.0'?> \
+ <effect> \
+ <Property name='DisplayName' type='string'/> \
+ <Property name='Author' type='string'/> \
+ <Property name='Category' type='string'/> \
+ <Property name='Description' type='string'/> \
+ <Inputs/> \
+ </effect> \
+";
+
+static const WCHAR *effect_xml_lower_case_property =
+L"<?xml version='1.0'?> \
+ <Effect> \
+ <property name='DisplayName' type='string'/> \
+ <property name='Author' type='string'/> \
+ <property name='Category' type='string'/> \
+ <property name='Description' type='string'/> \
+ <Inputs/> \
+ </Effect> \
+";
+
+static const WCHAR *effect_xml_lower_case_inputs =
+L"<?xml version='1.0'?> \
+ <Effect> \
+ <Property name='DisplayName' type='string'/> \
+ <Property name='Author' type='string'/> \
+ <Property name='Category' type='string'/> \
+ <Property name='Description' type='string'/> \
+ <inputs/> \
+ </Effect> \
+";
+
+static const WCHAR *effect_xml_min_max_inputs_a =
+L"<?xml version='1.0'?> \
+ <Effect> \
+ <Property name='DisplayName' type='string'/> \
+ <Property name='Author' type='string'/> \
+ <Property name='Category' type='string'/> \
+ <Property name='Description' type='string'/> \
+ <Property name='MinInputs' type='uint32' value='1'/> \
+ <Property name='MaxInputs' type='uint32' value='2'/> \
+ <Inputs/> \
+ </Effect> \
+";
+
+static const WCHAR *effect_xml_min_max_inputs_b =
+L"<?xml version='1.0'?> \
+ <Effect> \
+ <Property name='DisplayName' type='string'/> \
+ <Property name='Author' type='string'/> \
+ <Property name='Category' type='string'/> \
+ <Property name='Description' type='string'/> \
+ <Inputs> \
+ <Property name='Min' type='uint32' value='1'/> \
+ <Property name='Max' type='uint32' value='2'/> \
+ </Inputs> \
+ </Effect> \
+";
+
+
static const DWORD test_vs[] =
{
#if 0
@@ -10604,10 +10699,11 @@ static void test_effect_register(BOOL d3d11)
}
xml_tests[] =
{
- {effect_xml_a, S_OK},
- {effect_xml_b, S_OK},
- {effect_xml_c, S_OK},
- {effect_xml_minimum, S_OK},
+ {effect_xml_a, S_OK},
+ {effect_xml_b, S_OK},
+ {effect_xml_c, S_OK},
+ {effect_xml_minimum, S_OK},
+ {effect_xml_inputs_attribute, S_OK},
{effect_xml_without_version, HRESULT_FROM_WIN32(ERROR_NOT_FOUND)},
{effect_xml_without_inputs, E_INVALIDARG},
{effect_xml_without_name, E_INVALIDARG},
@@ -10615,6 +10711,13 @@ static void test_effect_register(BOOL d3d11)
{effect_xml_without_category, E_INVALIDARG},
{effect_xml_without_description, E_INVALIDARG},
{effect_xml_without_type, E_INVALIDARG},
+ {effect_xml_wrong_type, E_INVALIDARG},
+ {effect_xml_duplicate_property, E_INVALIDARG},
+ {effect_xml_lower_case_effect, HRESULT_FROM_WIN32(ERROR_NOT_FOUND)},
+ {effect_xml_lower_case_property, HRESULT_FROM_WIN32(ERROR_NOT_FOUND)},
+ {effect_xml_lower_case_inputs, HRESULT_FROM_WIN32(ERROR_NOT_FOUND)},
+ {effect_xml_min_max_inputs_a, E_INVALIDARG},
+ {effect_xml_min_max_inputs_b, HRESULT_FROM_WIN32(ERROR_NOT_FOUND)},
};
const D2D1_PROPERTY_BINDING binding[] =
@@ -10926,10 +11029,11 @@ static void test_effect_properties(BOOL d3d11)
}
system_property_tests[] =
{
- {effect_xml_a, L"TestEffectA", effect_author, effect_category, effect_description, 1, 1},
- {effect_xml_b, L"TestEffectB", effect_author, effect_category, effect_description, 1, 1},
- {effect_xml_c, L"TestEffectC", effect_author, effect_category, effect_description, 1, 1},
- {effect_xml_minimum, L"", L"" ,L"", L"", 0, 0},
+ {effect_xml_a, L"TestEffectA", effect_author, effect_category, effect_description, 1, 1},
+ {effect_xml_b, L"TestEffectB", effect_author, effect_category, effect_description, 1, 1},
+ {effect_xml_c, L"TestEffectC", effect_author, effect_category, effect_description, 1, 1},
+ {effect_xml_minimum, L"", L"" ,L"", L"", 0, 0},
+ {effect_xml_inputs_attribute, L"", L"" ,L"", L"", 0, 0},
};
if (!init_test_context(&ctx, d3d11))
--
2.25.1
June 12, 2022
Re: [PATCH v2 3/3] shell32: Reimplement SHBindToParent.
by Marvin
Hi,
While running your changed tests, I think I found new failures.
Being a bot and all I'm not very good at pattern recognition, so I might be
wrong, but could you please double-check?
Full results can be found at:
https://testbot.winehq.org/JobDetails.pl?Key=116793
Your paranoid android.
=== debian11 (32 bit report) ===
shell32:
shlfolder.c:5462: Test failed: got DEADBEEF
=== debian11 (32 bit Chinese:China report) ===
shell32:
shlfolder.c:5462: Test failed: got DEADBEEF
=== debian11 (32 bit WoW report) ===
shell32:
shlfolder.c:5462: Test failed: got DEADBEEF
=== debian11 (64 bit WoW report) ===
shell32:
shlfolder.c:5462: Test failed: got 00000000DEADBEEF
June 12, 2022
Re: [PATCH v2 2/3] shell32: Add SHBindToFolderIDListParent tests.
by Marvin
Hi,
While running your changed tests, I think I found new failures.
Being a bot and all I'm not very good at pattern recognition, so I might be
wrong, but could you please double-check?
Full results can be found at:
https://testbot.winehq.org/JobDetails.pl?Key=116792
Your paranoid android.
=== w1064v1809 (32 bit report) ===
shell32:
shlfolder.c:4979: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 40000)
=== w1064 (32 bit report) ===
shell32:
shlfolder.c:4962: Test failed: MKDIR: expected notification type 8, got: 40000
shlfolder.c:4969: Test failed: GetDisplayNameOf failed: 0x80070057
shlfolder.c:4979: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 8)
=== w1064_tsign (32 bit report) ===
shell32:
shlfolder.c:4962: Test failed: CREATE: expected notification type 2, got: 40000
shlfolder.c:4969: Test failed: GetDisplayNameOf failed: 0x80070057
shlfolder.c:4979: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 2)
=== w10pro64 (32 bit report) ===
shell32:
shlfolder.c:4979: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3)
shlfolder.c:4979: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3)
shlfolder.c:4962: Test failed: CREATE: expected notification type 2, got: 4000000
shlfolder.c:4969: Test failed: GetDisplayNameOf failed: 0x80070057
shlfolder.c:4970: Test failed: Expected PIDL to be NULL
shlfolder.c:4979: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3)
shlfolder.c:4979: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3)
=== w1064v1809 (64 bit report) ===
shell32:
shlfolder.c:4979: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3)
=== w1064 (64 bit report) ===
shell32:
shlfolder.c:4962: Test failed: RMDIR: expected notification type 10, got: 40000
shlfolder.c:4969: Test failed: GetDisplayNameOf failed: 0x80070057
shlfolder.c:4979: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 10)
=== w1064_2qxl (64 bit report) ===
shell32:
shlfolder.c:4979: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 40000)
=== w1064_adm (64 bit report) ===
shell32:
shlfolder.c:4962: Test failed: CREATE: expected notification type 2, got: 40000
shlfolder.c:4969: Test failed: GetDisplayNameOf failed: 0x80070057
shlfolder.c:4979: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 2)
=== w1064_tsign (64 bit report) ===
shell32:
shlfolder.c:4979: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 40000)
=== w10pro64 (64 bit report) ===
shell32:
shlfolder.c:4979: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3)
shlfolder.c:4979: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3)
shlfolder.c:4979: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3)
shlfolder.c:4979: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3)
shlfolder.c:4979: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3)
shlfolder.c:4962: Test failed: RMDIR: expected notification type 10, got: 40000
shlfolder.c:4969: Test failed: GetDisplayNameOf failed: 0x80070057
shlfolder.c:4979: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3)
=== w10pro64_en_AE_u8 (64 bit report) ===
shell32:
shlfolder.c:4979: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3)
shlfolder.c:4979: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3)
shlfolder.c:4979: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3)
=== w10pro64_ar (64 bit report) ===
shell32:
shlfolder.c:4962: Test failed: RMDIR: expected notification type 10, got: 40000
shlfolder.c:4969: Test failed: GetDisplayNameOf failed: 0x80070057
shlfolder.c:4979: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 10)
shlfolder.c:4979: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3)
shlfolder.c:4979: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3)
shlfolder.c:4979: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3)
=== w10pro64_zh_CN (64 bit report) ===
shell32:
shlfolder.c:4979: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3)
shlfolder.c:4979: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3)
shlfolder.c:4979: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3)
shlfolder.c:4979: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3)
shlfolder.c:4979: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3)
shlfolder.c:4962: Test failed: RMDIR: expected notification type 10, got: 40000
shlfolder.c:4969: Test failed: GetDisplayNameOf failed: 0x80070057
shlfolder.c:4979: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3)
=== debian11 (32 bit report) ===
shell32:
shlfolder.c:5462: Test failed: got DEADBEEF
=== debian11 (32 bit Arabic:Morocco report) ===
shell32:
shlfolder.c:5462: Test failed: got DEADBEEF
=== debian11 (32 bit German report) ===
shell32:
shlfolder.c:5462: Test failed: got DEADBEEF
=== debian11 (32 bit French report) ===
shell32:
shlfolder.c:5462: Test failed: got DEADBEEF
=== debian11 (32 bit Hebrew:Israel report) ===
shell32:
shlfolder.c:5462: Test failed: got DEADBEEF
=== debian11 (32 bit Hindi:India report) ===
shell32:
shlfolder.c:5462: Test failed: got DEADBEEF
=== debian11 (32 bit Japanese:Japan report) ===
shell32:
shlfolder.c:5462: Test failed: got DEADBEEF
=== debian11 (32 bit Chinese:China report) ===
shell32:
shlfolder.c:5462: Test failed: got DEADBEEF
=== debian11 (32 bit WoW report) ===
shell32:
shlfolder.c:5462: Test failed: got DEADBEEF
=== debian11 (64 bit WoW report) ===
shell32:
shlfolder.c:5462: Test failed: got 00000000DEADBEEF
June 12, 2022
[PATCH v2 3/3] shell32: Reimplement SHBindToParent.
by Mohamad Al-Jaf
Signed-off-by: Mohamad Al-Jaf <mohamadaljaf(a)gmail.com>
---
dlls/shell32/pidl.c | 38 +-------------------------------------
1 file changed, 1 insertion(+), 37 deletions(-)
diff --git a/dlls/shell32/pidl.c b/dlls/shell32/pidl.c
index e659427f9cd..59968b066e4 100644
--- a/dlls/shell32/pidl.c
+++ b/dlls/shell32/pidl.c
@@ -1339,43 +1339,7 @@ HRESULT WINAPI SHBindToFolderIDListParent(IShellFolder *psf, LPCITEMIDLIST pidl,
*/
HRESULT WINAPI SHBindToParent(LPCITEMIDLIST pidl, REFIID riid, LPVOID *ppv, LPCITEMIDLIST *ppidlLast)
{
- IShellFolder * psfDesktop;
- HRESULT hr=E_FAIL;
-
- TRACE_(shell)("pidl=%p\n", pidl);
- pdump(pidl);
-
- if (!pidl || !ppv)
- return E_INVALIDARG;
-
- *ppv = NULL;
- if (ppidlLast)
- *ppidlLast = NULL;
-
- hr = SHGetDesktopFolder(&psfDesktop);
- if (FAILED(hr))
- return hr;
-
- if (_ILIsPidlSimple(pidl))
- {
- /* we are on desktop level */
- hr = IShellFolder_QueryInterface(psfDesktop, riid, ppv);
- }
- else
- {
- LPITEMIDLIST pidlParent = ILClone(pidl);
- ILRemoveLastID(pidlParent);
- hr = IShellFolder_BindToObject(psfDesktop, pidlParent, NULL, riid, ppv);
- SHFree (pidlParent);
- }
-
- IShellFolder_Release(psfDesktop);
-
- if (SUCCEEDED(hr) && ppidlLast)
- *ppidlLast = ILFindLastID(pidl);
-
- TRACE_(shell)("-- psf=%p pidl=%p ret=0x%08lx\n", *ppv, (ppidlLast)?*ppidlLast:NULL, hr);
- return hr;
+ return SHBindToFolderIDListParent(NULL, pidl, riid, ppv, ppidlLast);
}
HRESULT WINAPI SHBindToObject(IShellFolder *psf, LPCITEMIDLIST pidl, IBindCtx *pbc, REFIID riid, void **ppv)
--
2.36.1
June 12, 2022
[PATCH v2 2/3] shell32: Add SHBindToFolderIDListParent tests.
by Mohamad Al-Jaf
From: Dmitry Timoshkov <dmitry(a)baikal.ru>
Signed-off-by: Mohamad Al-Jaf <mohamadaljaf(a)gmail.com>
---
dlls/shell32/tests/shlfolder.c | 53 ++++++++++++++++++++++++++++++++++
1 file changed, 53 insertions(+)
diff --git a/dlls/shell32/tests/shlfolder.c b/dlls/shell32/tests/shlfolder.c
index da606a9e707..1c482c06407 100644
--- a/dlls/shell32/tests/shlfolder.c
+++ b/dlls/shell32/tests/shlfolder.c
@@ -60,6 +60,7 @@ static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
static HRESULT (WINAPI *pSHCreateDefaultContextMenu)(const DEFCONTEXTMENU*,REFIID,void**);
static BOOL (WINAPI *pSHGetPathFromIDListEx)(PCIDLIST_ABSOLUTE,WCHAR*,DWORD,GPFIDL_FLAGS);
static HRESULT (WINAPI *pSHGetSetFolderCustomSettings)(LPSHFOLDERCUSTOMSETTINGS,PCWSTR,DWORD);
+static HRESULT (WINAPI *pSHBindToFolderIDListParent)(IShellFolder*,LPCITEMIDLIST,REFIID,void **,LPCITEMIDLIST*);
static WCHAR *make_wstr(const char *str)
{
@@ -89,6 +90,7 @@ static void init_function_pointers(void)
hmod = GetModuleHandleA("shell32.dll");
#define MAKEFUNC(f) (p##f = (void*)GetProcAddress(hmod, #f))
+ MAKEFUNC(SHBindToFolderIDListParent);
MAKEFUNC(SHCreateItemFromIDList);
MAKEFUNC(SHCreateItemFromParsingName);
MAKEFUNC(SHCreateItemFromRelativeName);
@@ -5410,6 +5412,56 @@ static void test_SHGetSetFolderCustomSettings(void)
RemoveDirectoryW(pathW);
}
+static void test_SHBindToFolderIDListParent(void)
+{
+ IShellFolder *psf_desktop;
+ LPITEMIDLIST pidl;
+ HRESULT hr;
+ WCHAR path[MAX_PATH];
+ SHITEMID empty_item = { 0, { 0 } };
+ LPITEMIDLIST pidl_empty = (LPITEMIDLIST)&empty_item;
+ LPCITEMIDLIST pidl_last;
+ IShellFolder *psf;
+
+ if (!pSHBindToFolderIDListParent)
+ {
+ win_skip("SHBindToFolderIDListParent not available\n");
+ return;
+ }
+
+ GetTempPathW(ARRAY_SIZE(path), path);
+ SHGetDesktopFolder(&psf_desktop);
+
+ hr = IShellFolder_ParseDisplayName(psf_desktop, NULL, NULL, path, NULL, &pidl, 0);
+ ok(hr == S_OK, "got %#lx\n", hr);
+
+ pidl_last = NULL;
+ hr = pSHBindToFolderIDListParent(psf_desktop, pidl, &IID_IShellFolder, (void **)&psf, &pidl_last);
+ ok(hr == S_OK, "got %#lx\n", hr);
+ ok(pidl_last != NULL, "got %p\n", pidl_last);
+ IShellFolder_Release(psf);
+
+ hr = pSHBindToFolderIDListParent(NULL, pidl_empty, &IID_IShellFolder, (void **)&psf, &pidl_last);
+ ok(hr == S_OK, "got %#lx\n", hr);
+ ok(pidl_last == pidl_empty, "got %p\n", pidl_last);
+ IShellFolder_Release(psf);
+
+ hr = pSHBindToFolderIDListParent(NULL, pidl, &IID_IShellFolder, (void **)&psf, NULL);
+ ok(hr == S_OK, "got %#lx\n", hr);
+ IShellFolder_Release(psf);
+
+ if (0) /* crashes under Windows */
+ hr = pSHBindToFolderIDListParent(NULL, pidl, &IID_IShellFolder, NULL, NULL);
+
+ ILFree(pidl);
+ IShellFolder_Release(psf_desktop);
+
+ pidl_last = (LPITEMIDLIST)0xdeadbeef;
+ hr = pSHBindToFolderIDListParent(NULL, NULL, &IID_IShellFolder, (void **)&psf, &pidl_last);
+ ok(hr == E_INVALIDARG, "got %#lx\n", hr);
+ ok(pidl_last == NULL, "got %p\n", pidl_last);
+}
+
START_TEST(shlfolder)
{
init_function_pointers();
@@ -5417,6 +5469,7 @@ START_TEST(shlfolder)
CO_E_NOTINITIALIZED for malformed directory names */
OleInitialize(NULL);
+ test_SHBindToFolderIDListParent();
test_ParseDisplayName();
test_SHParseDisplayName();
test_BindToObject();
--
2.36.1
June 12, 2022
[PATCH v2 1/3] shell32: Implement SHBindToFolderIDListParent.
by Mohamad Al-Jaf
Called by IE11.
Signed-off-by: Mohamad Al-Jaf <mohamadaljaf(a)gmail.com>
---
This is the code I submitted on May 3.
---
dlls/shell32/pidl.c | 49 +++++++++++++++++++++++++++++++++++++++
dlls/shell32/shell32.spec | 1 +
include/shlobj.h | 2 ++
3 files changed, 52 insertions(+)
diff --git a/dlls/shell32/pidl.c b/dlls/shell32/pidl.c
index f9c91a79132..e659427f9cd 100644
--- a/dlls/shell32/pidl.c
+++ b/dlls/shell32/pidl.c
@@ -1285,6 +1285,55 @@ BOOL WINAPI SHGetPathFromIDListEx(LPCITEMIDLIST pidl, WCHAR *path, DWORD path_si
return SUCCEEDED(hr);
}
+/*************************************************************************
+ * SHBindToFolderIDListParent [SHELL32.@]
+ */
+HRESULT WINAPI SHBindToFolderIDListParent(IShellFolder *psf, LPCITEMIDLIST pidl, REFIID riid, LPVOID *ppv, LPCITEMIDLIST *ppidlLast)
+{
+ IShellFolder *psfDesktop = NULL;
+ HRESULT hr;
+
+ TRACE_(shell)("%p,%p,%s\n", psf, pidl, debugstr_guid(riid));
+ pdump(pidl);
+
+ if (!pidl || !ppv)
+ return E_INVALIDARG;
+
+ *ppv = NULL;
+ if (ppidlLast)
+ *ppidlLast = NULL;
+
+ if (!psf)
+ {
+ hr = SHGetDesktopFolder(&psfDesktop);
+ if (FAILED(hr))
+ return hr;
+ psf = psfDesktop;
+ }
+
+ if (_ILIsPidlSimple(pidl))
+ {
+ /* we are on desktop level */
+ hr = IShellFolder_QueryInterface(psf, riid, ppv);
+ }
+ else
+ {
+ LPITEMIDLIST pidlParent = ILClone(pidl);
+ ILRemoveLastID(pidlParent);
+ hr = IShellFolder_BindToObject(psf, pidlParent, NULL, riid, ppv);
+ SHFree (pidlParent);
+ }
+
+ if (psfDesktop)
+ IShellFolder_Release(psfDesktop);
+
+ if (SUCCEEDED(hr) && ppidlLast)
+ *ppidlLast = ILFindLastID(pidl);
+
+ TRACE_(shell)("-- ppv=%p pidl=%p ret=0x%08lx\n", *ppv, (ppidlLast)?*ppidlLast:NULL, hr);
+ return hr;
+}
+
/*************************************************************************
* SHBindToParent [shell version 5.0]
*/
diff --git a/dlls/shell32/shell32.spec b/dlls/shell32/shell32.spec
index f8bf8f246e8..5b812774e1f 100644
--- a/dlls/shell32/shell32.spec
+++ b/dlls/shell32/shell32.spec
@@ -334,6 +334,7 @@
@ stdcall SHAssocEnumHandlers(wstr long ptr)
@ stdcall SHBindToObject(ptr ptr ptr ptr ptr)
@ stdcall SHBindToParent(ptr ptr ptr ptr)
+@ stdcall SHBindToFolderIDListParent(ptr ptr ptr ptr ptr)
@ stdcall SHBrowseForFolder(ptr) SHBrowseForFolderA
@ stdcall SHBrowseForFolderA(ptr)
@ stdcall SHBrowseForFolderW(ptr)
diff --git a/include/shlobj.h b/include/shlobj.h
index d30944662f7..93f0201a991 100644
--- a/include/shlobj.h
+++ b/include/shlobj.h
@@ -1639,6 +1639,8 @@ HRESULT WINAPI SHGetFolderPathW(HWND hwnd, int nFolder, HANDLE hToken, DWORD dwF
*/
HRESULT WINAPI SHGetDesktopFolder(IShellFolder * *);
+HRESULT WINAPI SHBindToFolderIDListParent(IShellFolder *psf, LPCITEMIDLIST pidl, REFIID riid, LPVOID *ppv, LPCITEMIDLIST *ppidlLast);
+
/****************************************************************************
* SHBindToParent API
*/
--
2.36.1
June 12, 2022