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
Re: [PATCH 0/4] MR233: win32u: Partially move raw input APIs.
by Rémi Bernon
On Tue Jun 14 04:05:11 2022 +0000, **** wrote:
> Zebediah Figura replied on the mailing list:
> ```
> On 6/13/22 03:27, Rémi Bernon (@rbernon) wrote:
> > Rémi Bernon (@rbernon) commented about dlls/user32/tests/input.c:
> >> + ok(count == ~0u, "GetRawInputData returned %d\n", count);
> >> + ok(GetLastError() == ERROR_INVALID_PARAMETER,
> "GetRawInputData returned %08lx\n", GetLastError());
> >> + }
> >> + else if (is_wow64)
> >> + {
> >> + count = GetRawInputData((HRAWINPUT)lparam,
> RID_INPUT, &ri, &size, sizeof(RAWINPUTHEADER64));
> >> + todo_wine ok(count == sizeof(ri), "GetRawInputData
> returned %d\n", count);
> >> + ok(ri.data.mouse.lLastX == 6, "Unexpected rawinput
> data: %ld\n", ri.data.mouse.lLastX);
> >> + todo_wine ok(GetLastError() == 0xdeadbeef,
> "GetRawInputData returned %08lx\n", GetLastError());
> >> + }
> >> + else
> >> + {
> >> + count = GetRawInputData((HRAWINPUT)lparam,
> RID_INPUT, &ri, &size, sizeof(RAWINPUTHEADER64));
> >> + ok(count == ~0u, "GetRawInputData returned %d\n", count);
> >> + ok(GetLastError() == ERROR_INVALID_PARAMETER,
> "GetRawInputData returned %08lx\n", GetLastError());
> >> + }
> > It feels a bit unbalanced to test invalid cases at the same time as a
> valid case depending on the arch. Could we have instead a test for the
> invalid sizes, and the another one with valid size?
> I don't understand what you mean by this. Only one of these three tests
> makes sense, and on mutually exclusive architectures.
> I could separate the if/elif/else into three separate if blocks, but I
> doubt that's what you mean.
> ```
I mean that, like the `GetRawInputBuffer` tests below you check an invalid size and ERROR_INVALID_PARAMETER error case, but on wow64, you don't and instead you check a valid size and the returned data.
I think you should check the same cases on all arch if possible, so invalid size and error on all arch (similarly to `GetRawInputBuffer`), then the valid case and data on all arch as well.
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/233#note_2012
June 14, 2022
Re: [PATCH 0/6] MR226: winegstreamer: Leave stream_cs when calling the async reader callbacks. - approved
by Zebediah Figura (@zfigura)
This merge request was approved by Zebediah Figura.
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/226
June 14, 2022
[PATCH v3 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 | 32 +++++++++++++++++---------------
2 files changed, 36 insertions(+), 17 deletions(-)
diff --git a/dlls/d2d1/factory.c b/dlls/d2d1/factory.c
index e5a82f7ffdb..ae0fb51bde8 100644
--- a/dlls/d2d1/factory.c
+++ b/dlls/d2d1/factory.c
@@ -969,9 +969,26 @@ static HRESULT STDMETHODCALLTYPE d2d_factory_RegisterEffectFromString(ID2D1Facto
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..7d60d3c52a2 100644
--- a/dlls/d2d1/tests/d2d1.c
+++ b/dlls/d2d1/tests/d2d1.c
@@ -10772,7 +10772,11 @@ 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_without_inputs
+ || test->xml == effect_xml_lower_case_property
+ || test->xml == effect_xml_lower_case_inputs
+ || test->xml == effect_xml_min_max_inputs_a
+ || test->xml == effect_xml_min_max_inputs_b)
ok(hr == test->hr, "Got unexpected hr %#lx, expected %#lx.\n", hr, test->hr);
if (hr == S_OK)
{
@@ -10780,9 +10784,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 +10809,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 +10848,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)
@@ -10856,7 +10860,6 @@ static void test_effect_register(BOOL d3d11)
hr = ID2D1Factory1_RegisterEffectFromString(factory, &CLSID_TestEffect,
test->effect_xml, test->binding, test->binding_count, effect_impl_create);
- todo_wine_if(test->hr != S_OK)
ok(hr == test->hr, "Got unexpected hr %#lx, expected %#lx.\n", hr, test->hr);
ID2D1Factory1_UnregisterEffect(factory, &CLSID_TestEffect);
@@ -10905,13 +10908,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 +10992,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 +11149,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 +11242,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 14, 2022
[PATCH v3 4/5] d2d1: Implement RegisterEffectFromString().
by Ziqing Hui
Signed-off-by: Ziqing Hui <zhui(a)codeweavers.com>
---
v3: Remove goto.
dlls/d2d1/factory.c | 29 ++++++++++++++++++++++++++---
1 file changed, 26 insertions(+), 3 deletions(-)
diff --git a/dlls/d2d1/factory.c b/dlls/d2d1/factory.c
index 3f48557ca37..e5a82f7ffdb 100644
--- a/dlls/d2d1/factory.c
+++ b/dlls/d2d1/factory.c
@@ -938,10 +938,33 @@ 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)))
+ {
+ IStream_Release(stream);
+ return hr;
+ }
+ if (FAILED(hr = IStream_Seek(stream, zero, SEEK_SET, NULL)))
+ {
+ IStream_Release(stream);
+ return hr;
+ }
+
+ hr = ID2D1Factory3_RegisterEffectFromStream(iface, effect_id, stream, bindings, binding_count, effect_factory);
+
+ IStream_Release(stream);
+ return hr;
}
static HRESULT STDMETHODCALLTYPE d2d_factory_UnregisterEffect(ID2D1Factory3 *iface, REFCLSID effect_id)
--
2.25.1
June 14, 2022
[PATCH v3 3/5] d2d1: Implement property parsing for RegisterEffectFromStream().
by Ziqing Hui
Signed-off-by: Ziqing Hui <zhui(a)codeweavers.com>
---
v3: Don't check EndElement name.
Check required system property after XML parsing is done.
dlls/d2d1/d2d1_private.h | 25 +++++
dlls/d2d1/factory.c | 211 ++++++++++++++++++++++++++++++++++++++-
2 files changed, 234 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 273b699ef8d..3f48557ca37 100644
--- a/dlls/d2d1/factory.c
+++ b/dlls/d2d1/factory.c
@@ -37,6 +37,10 @@ struct d2d_effect_reg
UINT32 input_count;
+ struct d2d_effect_property *properties;
+ size_t property_size;
+ size_t property_count;
+
struct list entry;
};
@@ -68,9 +72,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 +616,155 @@ 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;
+ }
+
+ 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;
+ 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))
+ {
+ 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)
+ {
+ break;
+ }
+ }
+
+ if (FAILED(hr) || node_type != XmlNodeType_EndElement)
+ {
+ 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)
@@ -694,8 +852,10 @@ static HRESULT STDMETHODCALLTYPE d2d_factory_RegisterEffectFromStream(ID2D1Facto
REFCLSID effect_id, IStream *property_xml, const D2D1_PROPERTY_BINDING *bindings,
UINT32 binding_count, PD2D1_EFFECT_FACTORY effect_factory)
{
+ BOOL display_name = FALSE, author = FALSE, category = FALSE, description = FALSE, wrong_type = FALSE, system_property;
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",
@@ -719,6 +879,53 @@ static HRESULT STDMETHODCALLTYPE d2d_factory_RegisterEffectFromStream(ID2D1Facto
return hr;
}
+ /* Check system properties */
+ for (i = 0; i < entry->property_count; ++i)
+ {
+ system_property = TRUE;
+
+ if (!wcscmp(entry->properties[i].name, L"DisplayName"))
+ display_name = TRUE;
+ else if (!wcscmp(entry->properties[i].name, L"Author"))
+ author = TRUE;
+ else if (!wcscmp(entry->properties[i].name, L"Category"))
+ category = TRUE;
+ else if (!wcscmp(entry->properties[i].name, L"Description"))
+ description = TRUE;
+ else
+ system_property = FALSE;
+
+ if (system_property && entry->properties[i].type != D2D1_PROPERTY_TYPE_STRING)
+ {
+ wrong_type = TRUE;
+ break;
+ }
+ }
+ if (!display_name || !author || !category || !description || wrong_type)
+ {
+ d2d_effect_reg_cleanup(entry);
+ return E_INVALIDARG;
+ }
+
+ /* 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)
+ {
+ d2d_effect_reg_cleanup(entry);
+ return D2DERR_INVALID_PROPERTY;
+ }
+ }
+
entry->count = 1;
entry->id = *effect_id;
entry->factory = effect_factory;
--
2.25.1
June 14, 2022
[PATCH v3 2/5] d2d1: Partially implement RegisterEffectFromStream().
by Ziqing Hui
Signed-off-by: Ziqing Hui <zhui(a)codeweavers.com>
---
v3: Remove goto.
Don't check EndElement name.
dlls/d2d1/Makefile.in | 2 +-
dlls/d2d1/factory.c | 158 +++++++++++++++++++++++++++++++++++++++++-
system_property_count | 0
3 files changed, 157 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..273b699ef8d 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,141 @@ 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)
+ {
+ return S_OK;
+ }
+ }
+
+ 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;
+ HRESULT hr;
+
+ if (FAILED(hr = CreateXmlReader(&IID_IXmlReader, (void **)&xml_reader, NULL)))
+ return hr;
+ if (FAILED(hr = IXmlReader_SetInput(xml_reader, (IUnknown *)property_xml)))
+ {
+ IXmlReader_Release(xml_reader);
+ return hr;
+ }
+
+ /* Read version node */
+ if (next_xml_node(xml_reader, &node_type, &node_name) != S_OK || node_type != XmlNodeType_XmlDeclaration)
+ {
+ IXmlReader_Release(xml_reader);
+ return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
+ }
+
+ /* 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)
+ {
+ IXmlReader_Release(xml_reader);
+ return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
+ }
+
+ /* Loop inside effect node */
+ while (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);
+
+ if (FAILED(hr))
+ {
+ IXmlReader_Release(xml_reader);
+ return hr;
+ }
+ }
+ else if (node_type == XmlNodeType_EndElement)
+ {
+ IXmlReader_Release(xml_reader);
+ return S_OK;
+ }
+ }
+
+ IXmlReader_Release(xml_reader);
+ return E_INVALIDARG;
+}
+
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))))
+ return E_OUTOFMEMORY;
+
+ if (FAILED(hr = parse_effect_xml(property_xml, entry)))
+ {
+ d2d_effect_reg_cleanup(entry);
+ return hr;
+ }
+
+ entry->count = 1;
+ entry->id = *effect_id;
+ entry->factory = effect_factory;
+ list_add_tail(&factory->effect_regs, &entry->entry);
+
+ return S_OK;
}
static HRESULT STDMETHODCALLTYPE d2d_factory_RegisterEffectFromString(ID2D1Factory3 *iface,
@@ -743,6 +896,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 14, 2022
[PATCH v3 1/5] d2d1/tests: Add more test xml.
by Ziqing Hui
Signed-off-by: Ziqing Hui <zhui(a)codeweavers.com>
---
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 14, 2022
Re: [PATCH 0/4] MR233: win32u: Partially move raw input APIs.
by Zebediah Figura
On 6/13/22 03:27, Rémi Bernon (@rbernon) wrote:
> Rémi Bernon (@rbernon) commented about dlls/user32/tests/input.c:
>> + ok(count == ~0u, "GetRawInputData returned %d\n", count);
>> + ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetRawInputData returned %08lx\n", GetLastError());
>> + }
>> + else if (is_wow64)
>> + {
>> + count = GetRawInputData((HRAWINPUT)lparam, RID_INPUT, &ri, &size, sizeof(RAWINPUTHEADER64));
>> + todo_wine ok(count == sizeof(ri), "GetRawInputData returned %d\n", count);
>> + ok(ri.data.mouse.lLastX == 6, "Unexpected rawinput data: %ld\n", ri.data.mouse.lLastX);
>> + todo_wine ok(GetLastError() == 0xdeadbeef, "GetRawInputData returned %08lx\n", GetLastError());
>> + }
>> + else
>> + {
>> + count = GetRawInputData((HRAWINPUT)lparam, RID_INPUT, &ri, &size, sizeof(RAWINPUTHEADER64));
>> + ok(count == ~0u, "GetRawInputData returned %d\n", count);
>> + ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetRawInputData returned %08lx\n", GetLastError());
>> + }
> It feels a bit unbalanced to test invalid cases at the same time as a valid case depending on the arch. Could we have instead a test for the invalid sizes, and the another one with valid size?
I don't understand what you mean by this. Only one of these three tests
makes sense, and on mutually exclusive architectures.
I could separate the if/elif/else into three separate if blocks, but I
doubt that's what you mean.
June 14, 2022
Re: [PATCH 0/4] MR233: win32u: Partially move raw input APIs.
by Zebediah Figura
On 6/13/22 03:27, Rémi Bernon (@rbernon) wrote:
> Rémi Bernon (@rbernon) commented about dlls/user32/tests/input.c:
>> GetCursorPos(&pt);
>> ok(pt.x == 300 && pt.y == 300, "Unexpected cursor position pos %ldx%ld\n", pt.x, pt.y);
>>
>> - hwnd = CreateWindowA("static", "static", WS_VISIBLE | WS_POPUP,
>> + hwnd = CreateWindowA("static", "static", WS_POPUP,
>> 100, 100, 100, 100, 0, NULL, NULL, NULL);
>> SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONG_PTR)rawinputbuffer_wndproc);
>> ok(hwnd != 0, "CreateWindow failed\n");
> Wine currently doesn't listen to X11 mouse events in the background, it needs a visible window to receive them and only when the cursor moves over it.
>
> If you want to test `RIDEV_INPUTSINK` I think the best way is to use a second window (possibly invisible), and use it as the `hwndTarget`, while still moving the cursor over the first, visible, window.
>
I think that doesn't work, because they're still part of the same
process. It probably is best to just drop that part of the tests for now.
June 14, 2022
Re: [PATCH 0/4] MR233: win32u: Partially move raw input APIs.
by Zebediah Figura
On 6/13/22 03:27, Rémi Bernon (@rbernon) wrote:
> Rémi Bernon (@rbernon) commented about dlls/user32/tests/input.c:
>> ret = GetRawInputData((HRAWINPUT)lparam, RID_INPUT, &raw, &raw_size, sizeof(RAWINPUTHEADER));
>> ok(ret > 0 && ret != (UINT)-1, "GetRawInputData failed\n");
>> ok(raw.header.dwType == RIM_TYPEMOUSE, "Unexpected rawinput type: %lu\n", raw.header.dwType);
>> + ok(raw.header.dwSize == raw_size, "Expected size %u, got %lu\n", raw_size, raw.header.dwSize);
>> + todo_wine_if (wparam)
>> + ok(raw.header.wParam == wparam, "Expected wparam %Iu, got %Iu\n", wparam, raw.header.wParam);
> We don't usually indent `todo_wine_(if)`, do we?
>
Some people do. Semantically "todo_wine" is similar to "if (x)" [and
"todo_wine_if" is similar to "if"] so I indent it accordingly. This also
has the advantage that the line will be touched again when the todo_wine
is removed, which can make it easy to spot what commit fixed a test in
`git blame` (where applicable).
June 14, 2022