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
Having problems (re-)building i686 wine staging rpm's on fedora
by Hin-Tak Leung
Due to having a few modifications considered unsuitable for upstreaming, I have been grabbing the official fedora rpm's since at least wine-1.9.20 / 2016 , patching the spec file, adding my patches, plus a "Epoch: 100" line, so it blocks auto--upgrades, until I rebuild it myself every two or three wine releases. This has worked well for 6+ years, until 7.3+ . I last built 7.2 staging with
(rpmbuild -bb wine.spec && rpmbuild --target=i686 -bb wine.spec) 2>&1 | tee build-log .
Fedora's koji build farm only have 7.3, 7.5, 7.9, and 7.10.
I tried 7.10 and the x86_64 part finished (*see notes below), but the i686 part just wouldn't go ahead, due to some PE-related collisions.
I back-tracked, and found the failure was between 7.3 and 7.5.
===
i686-w64-mingw32-gcc -c -o dlls/windowscodecs/libjpeg.cross.o dlls/windowscodecs/libjpeg.c -Idlls/windowscodecs -Iinclude -Iinclude/msvcrt \
-I/usr/include -I./libs/png -D__WINESRC__ -D_UCRT -D__WINE_PE_BUILD -Wall -fno-strict-aliasing \
-Wdeclaration-after-statement -Wempty-body -Wignored-qualifiers -Winit-self \
-Wno-packed-not-aligned -Wshift-overflow=2 -Wstrict-prototypes -Wtype-limits \
-Wunused-but-set-parameter -Wvla -Wwrite-strings -Wpointer-arith -Wlogical-op -Wabsolute-value \
-fno-omit-frame-pointer -gdwarf-4 -g -O2
In file included from include/objbase.h:20,
from dlls/windowscodecs/libjpeg.c:31:
include/rpcndr.h:73:23: error: conflicting types for 'boolean'; have 'unsigned char'
73 | typedef unsigned char boolean;
| ^~~~~~~
In file included from /usr/include/jpeglib.h:31,
from dlls/windowscodecs/libjpeg.c:24:
/usr/include/jmorecfg.h:207:13: note: previous declaration of 'boolean' with type 'boolean' {aka 'int'}
207 | typedef int boolean;
| ^~~~~~~
dlls/windowscodecs/libjpeg.c: In function 'jpeg_decoder_initialize':
dlls/windowscodecs/libjpeg.c:180:40: warning: assignment to 'boolean (*)(struct jpeg_decompress_struct *)' {aka 'int (*)(struct jpeg_decompress_struct *)'} from incompatible pointer type 'boolean (*)(struct jpeg_decompress_struct *)' {aka 'unsigned char (*)(struct jpeg_decompress_struct *)'} [-Wincompatible-pointer-types]
180 | This->source_mgr.fill_input_buffer = source_mgr_fill_input_buffer;
| ^
dlls/windowscodecs/libjpeg.c: In function 'jpeg_encoder_initialize':
dlls/windowscodecs/libjpeg.c:466:40: warning: assignment to 'boolean (*)(struct jpeg_compress_struct *)' {aka 'int (*)(struct jpeg_compress_struct *)'} from incompatible pointer type 'boolean (*)(struct jpeg_compress_struct *)' {aka 'unsigned char (*)(struct jpeg_compress_struct *)'} [-Wincompatible-pointer-types]
466 | This->dest_mgr.empty_output_buffer = dest_mgr_empty_output_buffer;
| ^
make: *** [Makefile:127914: dlls/windowscodecs/libjpeg.cross.o] Error 1
===
I tried setting PNG_PE_CFLAGS, ZLIB_PE_CFLAGS, LCMS2_PE_CFLAGS, JPEG_PE_CFLAGS, JPEG_PE_LIBS etc explicitly, and sometimes it get worse.
Anyway, I have tried some many things that I thought it might be worth reaching out to the people who maintain the fedora rpm's as well as well wine-devel.
A few questions/thoughts:
- it seems that the build system is getting confused occasionally about say, native headers vs mingw headers like jpeg-devel; at some point, I got a error saying I was trying to build one of the unixlib.c's with mingw headers, for example. But I see for example that in the generated Makefile for dlls/windowscodecs/ , It is feeding *PE_FLAGS to unixlib.c (plus the PE stub), and I explicitly put -I...mingw32/include to *PE_FLAGS. That seems wrong.
- I don't understand why --target=x86_64 rebuild works, built --target=i686 rebuild fails with the above error. My list of mingw32-* packages and mingw64-* packages are almost identical, I think, and certainly regarding libjpeg (zlib/png dependencies) .
I have the 29MB combined x86-64 and i686 build-log of 7.3, plus the 15MB x86-64 and ~3MB i686 failure of each of 7.5/7.9/7.10 ; but it is kind of difficult to see what to check. Any hints on what to look at at config.log would be useful.
*note rpmbuild detects isdn4k-utils on my system so I needed to add these two lines
+%{_libdir}/wine/%{winesodir}/capi2032.so
+%{_libdir}/wine/%{winepedir}/capi2032.dll
to my modified spec. I suppose I should formalize this part of my diff with one furthe line of BuildRequires: isdn4k-utils-devel as a reminder to myself.
June 11, 2022
[PATCH 3/3] uiautomationcore: Implement NavigateDirection_Parent for MSAA Providers.
by Connor McAdams
From: Connor McAdams <cmcadams(a)codeweavers.com>
Signed-off-by: Connor McAdams <cmcadams(a)codeweavers.com>
---
dlls/uiautomationcore/tests/uiautomation.c | 96 ++++++++++------------
dlls/uiautomationcore/uia_provider.c | 64 ++++++++++++++-
2 files changed, 104 insertions(+), 56 deletions(-)
diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c
index b4958d2dc70..885e520bfd3 100644
--- a/dlls/uiautomationcore/tests/uiautomation.c
+++ b/dlls/uiautomationcore/tests/uiautomation.c
@@ -1078,38 +1078,35 @@ static void test_uia_prov_from_acc_navigation(void)
elfrag2 = (void *)0xdeadbeef;
hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_Parent, &elfrag2);
ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
- todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
ok(!elfrag2, "elfrag2 != NULL\n");
- todo_wine CHECK_CALLED(winproc_GETOBJECT_CLIENT);
- todo_wine CHECK_CALLED(Accessible_get_accRole);
- todo_wine CHECK_CALLED(Accessible_get_accState);
- todo_wine CHECK_CALLED(Accessible_get_accChildCount);
- todo_wine CHECK_CALLED(Accessible_accLocation);
- todo_wine CHECK_CALLED(Accessible_get_accName);
- todo_wine CHECK_CALLED(Accessible2_get_accRole);
- todo_wine CHECK_CALLED(Accessible2_get_accState);
- todo_wine CHECK_CALLED(Accessible2_get_accChildCount);
- todo_wine CHECK_CALLED(Accessible2_accLocation);
- todo_wine CHECK_CALLED(Accessible2_get_accName);
+ CHECK_CALLED(winproc_GETOBJECT_CLIENT);
+ CHECK_CALLED(Accessible_get_accRole);
+ CHECK_CALLED(Accessible_get_accState);
+ CHECK_CALLED(Accessible_get_accChildCount);
+ CHECK_CALLED(Accessible_accLocation);
+ CHECK_CALLED(Accessible_get_accName);
+ CHECK_CALLED(Accessible2_get_accRole);
+ CHECK_CALLED(Accessible2_get_accState);
+ CHECK_CALLED(Accessible2_get_accChildCount);
+ CHECK_CALLED(Accessible2_accLocation);
+ CHECK_CALLED(Accessible2_get_accName);
todo_wine CHECK_CALLED(Accessible2_QI_IAccIdentity);
todo_wine CHECK_CALLED(Accessible2_get_accParent);
acc_client = NULL;
- if (SUCCEEDED(hr))
- {
- /* No check against root IAccessible, since it was done previously. */
- elprov2 = (void *)0xdeadbeef;
- hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
- ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
- ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
- IRawElementProviderSimple_Release(elprov2);
- }
+ /* No check against root IAccessible, since it was done previously. */
+ elprov2 = (void *)0xdeadbeef;
+ hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
+ IRawElementProviderSimple_Release(elprov2);
/* Do nothing. */
elfrag2 = (void *)0xdeadbeef;
hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_Parent, &elfrag2);
ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
- todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
ok(!elfrag2, "elfrag2 != NULL\n");
elfrag2 = (void *)0xdeadbeef;
@@ -1284,36 +1281,30 @@ static void test_uia_prov_from_acc_navigation(void)
SET_EXPECT(Accessible2_QI_IAccIdentity);
SET_EXPECT(Accessible2_get_accParent);
hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_Parent, &elfrag2);
- todo_wine ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
- todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
- todo_wine ok(!!elfrag2, "elfrag2 == NULL\n");
- todo_wine CHECK_CALLED(Accessible_child_get_accParent);
- todo_wine CHECK_CALLED(Accessible_child_get_accRole);
- todo_wine CHECK_CALLED(Accessible2_get_accRole);
+ ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(!!elfrag2, "elfrag2 == NULL\n");
+ CHECK_CALLED(Accessible_child_get_accParent);
+ CHECK_CALLED(Accessible_child_get_accRole);
+ CHECK_CALLED(Accessible2_get_accRole);
todo_wine CHECK_CALLED(Accessible2_QI_IAccIdentity);
todo_wine CHECK_CALLED(Accessible2_get_accParent);
- todo_wine CHECK_CALLED(winproc_GETOBJECT_CLIENT);
- if (elfrag2)
- {
- check_fragment_acc(elfrag2, &Accessible.IAccessible_iface, CHILDID_SELF);
- IRawElementProviderFragment_Release(elfrag2);
- ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
- }
+ CHECK_CALLED(winproc_GETOBJECT_CLIENT);
+ check_fragment_acc(elfrag2, &Accessible.IAccessible_iface, CHILDID_SELF);
+ IRawElementProviderFragment_Release(elfrag2);
+ ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
acc_client = NULL;
/* Second call only does get_accParent, no root check. */
SET_EXPECT(Accessible_child_get_accParent);
hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_Parent, &elfrag2);
- todo_wine ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
- todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
- todo_wine ok(!!elfrag2, "elfrag2 == NULL\n");
- todo_wine CHECK_CALLED(Accessible_child_get_accParent);
- if (elfrag2)
- {
- check_fragment_acc(elfrag2, &Accessible.IAccessible_iface, CHILDID_SELF);
- IRawElementProviderFragment_Release(elfrag2);
- ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
- }
+ ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(!!elfrag2, "elfrag2 == NULL\n");
+ CHECK_CALLED(Accessible_child_get_accParent);
+ check_fragment_acc(elfrag2, &Accessible.IAccessible_iface, CHILDID_SELF);
+ IRawElementProviderFragment_Release(elfrag2);
+ ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
/* ChildCount of 0, do nothing for First/Last child.*/
SET_EXPECT(Accessible_child_get_accChildCount);
@@ -1434,15 +1425,12 @@ static void test_uia_prov_from_acc_navigation(void)
* can't be the root IAccessible.
*/
hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_Parent, &elfrag2);
- todo_wine ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref);
- todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
- todo_wine ok(!!elfrag2, "elfrag2 == NULL\n");
- if (elfrag2)
- {
- check_fragment_acc(elfrag2, &Accessible.IAccessible_iface, CHILDID_SELF);
- IRawElementProviderFragment_Release(elfrag2);
- ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
- }
+ ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(!!elfrag2, "elfrag2 == NULL\n");
+ check_fragment_acc(elfrag2, &Accessible.IAccessible_iface, CHILDID_SELF);
+ IRawElementProviderFragment_Release(elfrag2);
+ ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
/*
* Test NavigateDirection_First/LastChild on simple child element. Does
diff --git a/dlls/uiautomationcore/uia_provider.c b/dlls/uiautomationcore/uia_provider.c
index 8701d67a89f..1dfe447331e 100644
--- a/dlls/uiautomationcore/uia_provider.c
+++ b/dlls/uiautomationcore/uia_provider.c
@@ -205,6 +205,21 @@ exit:
return matched;
}
+static HRESULT msaa_acc_get_parent(IAccessible *acc, IAccessible **parent)
+{
+ IDispatch *disp = NULL;
+ HRESULT hr;
+
+ *parent = NULL;
+ hr = IAccessible_get_accParent(acc, &disp);
+ if (FAILED(hr) || !disp)
+ return hr;
+
+ hr = IDispatch_QueryInterface(disp, &IID_IAccessible, (void**)parent);
+ IDispatch_Release(disp);
+ return hr;
+}
+
static LONG msaa_role_to_uia_control_type(LONG role)
{
switch (role)
@@ -515,9 +530,54 @@ static ULONG WINAPI msaa_fragment_Release(IRawElementProviderFragment *iface)
static HRESULT WINAPI msaa_fragment_Navigate(IRawElementProviderFragment *iface,
enum NavigateDirection direction, IRawElementProviderFragment **ret_val)
{
- FIXME("%p, %d, %p: stub!\n", iface, direction, ret_val);
+ struct msaa_provider *msaa_prov = impl_from_msaa_fragment(iface);
+ IRawElementProviderSimple *elprov;
+ IAccessible *acc;
+ HRESULT hr;
+
+ TRACE("%p, %d, %p\n", iface, direction, ret_val);
+
*ret_val = NULL;
- return E_NOTIMPL;
+ switch (direction)
+ {
+ case NavigateDirection_Parent:
+ if (msaa_check_root_acc(msaa_prov))
+ break;
+
+ if (V_I4(&msaa_prov->cid) == CHILDID_SELF)
+ {
+ hr = msaa_acc_get_parent(msaa_prov->acc, &acc);
+ if (FAILED(hr) || !acc)
+ break;
+ }
+ else
+ acc = msaa_prov->acc;
+
+ hr = UiaProviderFromIAccessible(acc, CHILDID_SELF, 0, &elprov);
+ if (SUCCEEDED(hr))
+ {
+ struct msaa_provider *prov = impl_from_msaa_provider(elprov);
+ *ret_val = &prov->IRawElementProviderFragment_iface;
+ }
+
+ if (acc != msaa_prov->acc)
+ IAccessible_Release(acc);
+
+ break;
+
+ case NavigateDirection_FirstChild:
+ case NavigateDirection_LastChild:
+ case NavigateDirection_NextSibling:
+ case NavigateDirection_PreviousSibling:
+ FIXME("Unimplemented NavigateDirection %d\n", direction);
+ return E_NOTIMPL;
+
+ default:
+ FIXME("Invalid NavigateDirection %d\n", direction);
+ return E_INVALIDARG;
+ }
+
+ return S_OK;
}
static HRESULT WINAPI msaa_fragment_GetRuntimeId(IRawElementProviderFragment *iface,
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/230
June 11, 2022
[PATCH 2/3] uiautomationcore/tests: Add navigation tests for MSAA providers.
by Connor McAdams
From: Connor McAdams <cmcadams(a)codeweavers.com>
Signed-off-by: Connor McAdams <cmcadams(a)codeweavers.com>
---
dlls/uiautomationcore/tests/uiautomation.c | 630 ++++++++++++++++++++-
1 file changed, 618 insertions(+), 12 deletions(-)
diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c
index 6c07edcffa8..b4958d2dc70 100644
--- a/dlls/uiautomationcore/tests/uiautomation.c
+++ b/dlls/uiautomationcore/tests/uiautomation.c
@@ -30,27 +30,36 @@
static HRESULT (WINAPI *pUiaProviderFromIAccessible)(IAccessible *, long, DWORD, IRawElementProviderSimple **);
#define DEFINE_EXPECT(func) \
- static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
+ static int expect_ ## func = 0, called_ ## func = 0
#define SET_EXPECT(func) \
- do { called_ ## func = FALSE; expect_ ## func = TRUE; } while(0)
+ do { called_ ## func = 0; expect_ ## func = 1; } while(0)
+
+#define SET_EXPECT_MULTI(func, num) \
+ do { called_ ## func = 0; expect_ ## func = num; } while(0)
#define CHECK_EXPECT2(func) \
do { \
ok(expect_ ##func, "unexpected call " #func "\n"); \
- called_ ## func = TRUE; \
+ called_ ## func++; \
}while(0)
#define CHECK_EXPECT(func) \
do { \
CHECK_EXPECT2(func); \
- expect_ ## func = FALSE; \
+ expect_ ## func--; \
}while(0)
#define CHECK_CALLED(func) \
do { \
ok(called_ ## func, "expected " #func "\n"); \
- expect_ ## func = called_ ## func = FALSE; \
+ expect_ ## func = called_ ## func = 0; \
+ }while(0)
+
+#define CHECK_CALLED_MULTI(func, num) \
+ do { \
+ ok(called_ ## func == num, "expected " #func " %d times (got %d)\n", num, called_ ## func); \
+ expect_ ## func = called_ ## func = 0; \
}while(0)
#define NAVDIR_INTERNAL_HWND 10
@@ -63,6 +72,7 @@ DEFINE_EXPECT(Accessible_get_accName);
DEFINE_EXPECT(Accessible_get_accRole);
DEFINE_EXPECT(Accessible_get_accState);
DEFINE_EXPECT(Accessible_accLocation);
+DEFINE_EXPECT(Accessible_get_accChild);
DEFINE_EXPECT(Accessible2_get_accParent);
DEFINE_EXPECT(Accessible2_get_accChildCount);
DEFINE_EXPECT(Accessible2_get_accName);
@@ -72,6 +82,18 @@ DEFINE_EXPECT(Accessible2_accLocation);
DEFINE_EXPECT(Accessible2_QI_IAccIdentity);
DEFINE_EXPECT(Accessible_child_accNavigate);
DEFINE_EXPECT(Accessible_child_get_accParent);
+DEFINE_EXPECT(Accessible_child_get_accChildCount);
+DEFINE_EXPECT(Accessible_child_get_accName);
+DEFINE_EXPECT(Accessible_child_get_accRole);
+DEFINE_EXPECT(Accessible_child_get_accState);
+DEFINE_EXPECT(Accessible_child_accLocation);
+DEFINE_EXPECT(Accessible_child2_accNavigate);
+DEFINE_EXPECT(Accessible_child2_get_accParent);
+DEFINE_EXPECT(Accessible_child2_get_accChildCount);
+DEFINE_EXPECT(Accessible_child2_get_accName);
+DEFINE_EXPECT(Accessible_child2_get_accRole);
+DEFINE_EXPECT(Accessible_child2_get_accState);
+DEFINE_EXPECT(Accessible_child2_accLocation);
static BOOL check_variant_i4(VARIANT *v, int val)
{
@@ -117,7 +139,7 @@ static struct Accessible
LONG child_count;
LPCWSTR name;
LONG left, top, width, height;
-} Accessible, Accessible2, Accessible_child;
+} Accessible, Accessible2, Accessible_child, Accessible_child2;
static inline struct Accessible* impl_from_Accessible(IAccessible *iface)
{
@@ -195,6 +217,8 @@ static HRESULT WINAPI Accessible_get_accParent(IAccessible *iface, IDispatch **o
if (This == &Accessible_child)
CHECK_EXPECT(Accessible_child_get_accParent);
+ else if (This == &Accessible_child2)
+ CHECK_EXPECT(Accessible_child2_get_accParent);
else if (This == &Accessible2)
CHECK_EXPECT(Accessible2_get_accParent);
else
@@ -211,7 +235,11 @@ static HRESULT WINAPI Accessible_get_accChildCount(IAccessible *iface, LONG *out
{
struct Accessible *This = impl_from_Accessible(iface);
- if (This == &Accessible2)
+ if (This == &Accessible_child)
+ CHECK_EXPECT(Accessible_child_get_accChildCount);
+ else if (This == &Accessible_child2)
+ CHECK_EXPECT(Accessible_child2_get_accChildCount);
+ else if (This == &Accessible2)
CHECK_EXPECT(Accessible2_get_accChildCount);
else
CHECK_EXPECT(Accessible_get_accChildCount);
@@ -228,7 +256,38 @@ static HRESULT WINAPI Accessible_get_accChildCount(IAccessible *iface, LONG *out
static HRESULT WINAPI Accessible_get_accChild(IAccessible *iface, VARIANT child_id,
IDispatch **out_child)
{
- ok(0, "unexpected call\n");
+ struct Accessible *This = impl_from_Accessible(iface);
+
+ CHECK_EXPECT(Accessible_get_accChild);
+ ok(This == &Accessible, "unexpected call\n");
+
+ *out_child = NULL;
+ if (V_VT(&child_id) != VT_I4)
+ return E_INVALIDARG;
+
+ if (This == &Accessible)
+ {
+ switch (V_I4(&child_id))
+ {
+ case CHILDID_SELF:
+ return IAccessible_QueryInterface(&This->IAccessible_iface, &IID_IDispatch, (void **)out_child);
+
+ /* Simple element children. */
+ case 1:
+ case 3:
+ return S_FALSE;
+
+ case 2:
+ return IAccessible_QueryInterface(&Accessible_child.IAccessible_iface, &IID_IDispatch, (void **)out_child);
+
+ case 4:
+ return IAccessible_QueryInterface(&Accessible_child2.IAccessible_iface, &IID_IDispatch, (void **)out_child);
+
+ default:
+ break;
+
+ }
+ }
return E_NOTIMPL;
}
@@ -238,7 +297,11 @@ static HRESULT WINAPI Accessible_get_accName(IAccessible *iface, VARIANT child_i
struct Accessible *This = impl_from_Accessible(iface);
*out_name = NULL;
- if (This == &Accessible2)
+ if (This == &Accessible_child)
+ CHECK_EXPECT(Accessible_child_get_accName);
+ else if (This == &Accessible_child2)
+ CHECK_EXPECT(Accessible_child2_get_accName);
+ else if (This == &Accessible2)
CHECK_EXPECT(Accessible2_get_accName);
else
CHECK_EXPECT(Accessible_get_accName);
@@ -271,7 +334,11 @@ static HRESULT WINAPI Accessible_get_accRole(IAccessible *iface, VARIANT child_i
{
struct Accessible *This = impl_from_Accessible(iface);
- if (This == &Accessible2)
+ if (This == &Accessible_child)
+ CHECK_EXPECT(Accessible_child_get_accRole);
+ else if (This == &Accessible_child2)
+ CHECK_EXPECT(Accessible_child2_get_accRole);
+ else if (This == &Accessible2)
CHECK_EXPECT(Accessible2_get_accRole);
else
CHECK_EXPECT(Accessible_get_accRole);
@@ -291,11 +358,39 @@ static HRESULT WINAPI Accessible_get_accState(IAccessible *iface, VARIANT child_
{
struct Accessible *This = impl_from_Accessible(iface);
- if (This == &Accessible2)
+ if (This == &Accessible_child)
+ CHECK_EXPECT(Accessible_child_get_accState);
+ else if (This == &Accessible_child2)
+ CHECK_EXPECT(Accessible_child2_get_accState);
+ else if (This == &Accessible2)
CHECK_EXPECT(Accessible2_get_accState);
else
CHECK_EXPECT(Accessible_get_accState);
+ if (V_VT(&child_id) != VT_I4)
+ return E_INVALIDARG;
+
+ if (This == &Accessible && V_I4(&child_id) != CHILDID_SELF)
+ {
+ switch (V_I4(&child_id))
+ {
+ case 1:
+ V_VT(out_state) = VT_I4;
+ V_I4(out_state) = STATE_SYSTEM_INVISIBLE;
+ break;
+
+ case 3:
+ V_VT(out_state) = VT_I4;
+ V_I4(out_state) = STATE_SYSTEM_FOCUSABLE;
+ break;
+
+ default:
+ return E_INVALIDARG;
+ }
+
+ return S_OK;
+ }
+
if (This->state)
{
V_VT(out_state) = VT_I4;
@@ -358,7 +453,11 @@ static HRESULT WINAPI Accessible_accLocation(IAccessible *iface, LONG *out_left,
{
struct Accessible *This = impl_from_Accessible(iface);
- if (This == &Accessible2)
+ if (This == &Accessible_child)
+ CHECK_EXPECT(Accessible_child_accLocation);
+ else if (This == &Accessible_child2)
+ CHECK_EXPECT(Accessible_child2_accLocation);
+ else if (This == &Accessible2)
CHECK_EXPECT(Accessible2_accLocation);
else
CHECK_EXPECT(Accessible_accLocation);
@@ -382,6 +481,8 @@ static HRESULT WINAPI Accessible_accNavigate(IAccessible *iface, LONG nav_direct
if (This == &Accessible_child)
CHECK_EXPECT(Accessible_child_accNavigate);
+ else if (This == &Accessible_child2)
+ CHECK_EXPECT(Accessible_child2_accNavigate);
else
CHECK_EXPECT(Accessible_accNavigate);
VariantInit(out_var);
@@ -535,6 +636,17 @@ static struct Accessible Accessible_child =
0, 0, 0, 0,
};
+static struct Accessible Accessible_child2 =
+{
+ { &AccessibleVtbl },
+ { &OleWindowVtbl },
+ 1,
+ &Accessible.IAccessible_iface,
+ 0, 0,
+ 0, 0, 0, NULL,
+ 0, 0, 0, 0,
+};
+
static IAccessible *acc_client;
static LRESULT WINAPI test_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
@@ -890,6 +1002,499 @@ static void set_accessible_props(struct Accessible *acc, INT role, INT state,
acc->height = height;
}
+#define check_fragment_acc( fragment, acc, cid) \
+ check_fragment_acc_( (fragment), (acc), (cid), __LINE__)
+static void check_fragment_acc_(IRawElementProviderFragment *elfrag, IAccessible *acc,
+ INT cid, int line)
+{
+ ILegacyIAccessibleProvider *accprov;
+ IAccessible *accessible;
+ INT child_id;
+ HRESULT hr;
+
+ hr = IRawElementProviderFragment_QueryInterface(elfrag, &IID_ILegacyIAccessibleProvider, (void **)&accprov);
+ ok_(__FILE__, line) (hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok_(__FILE__, line) (!!accprov, "accprov == NULL\n");
+
+ hr = ILegacyIAccessibleProvider_GetIAccessible(accprov, &accessible);
+ ok_(__FILE__, line) (hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok_(__FILE__, line) (accessible == acc, "accessible != acc\n");
+ IAccessible_Release(accessible);
+
+ hr = ILegacyIAccessibleProvider_get_ChildId(accprov, &child_id);
+ ok_(__FILE__, line) (hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok_(__FILE__, line) (child_id == cid, "child_id != cid\n");
+
+ ILegacyIAccessibleProvider_Release(accprov);
+}
+
+static void test_uia_prov_from_acc_navigation(void)
+{
+ IRawElementProviderFragment *elfrag, *elfrag2, *elfrag3;
+ IRawElementProviderSimple *elprov, *elprov2;
+ HRESULT hr;
+
+ /*
+ * Full IAccessible parent, with 4 children:
+ * childid 1 is a simple element, with STATE_SYSTEM_INVISIBLE.
+ * childid 2 is Accessible_child.
+ * childid 3 is a simple element with STATE_SYSTEM_NORMAL.
+ * childid 4 is Accessible_child2.
+ */
+ hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
+
+ hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragment, (void **)&elfrag);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(!!elfrag, "elfrag == NULL\n");
+
+ /*
+ * First time doing NavigateDirection_Parent will result in the same root
+ * accessible check as get_HostRawElementProvider. If this IAccessible is
+ * the root for its associated HWND, NavigateDirection_Parent and
+ * NavigateDirection_Next/PreviousSibling will do nothing, as UI Automation
+ * provides non-client area providers for the root IAccessible's parent
+ * and siblings.
+ */
+ set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 4,
+ L"acc_name", 0, 0, 50, 50);
+ set_accessible_props(&Accessible2, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 4,
+ L"acc_name", 0, 0, 50, 50);
+ acc_client = &Accessible2.IAccessible_iface;
+ SET_EXPECT(winproc_GETOBJECT_CLIENT);
+ SET_EXPECT(Accessible_get_accRole);
+ SET_EXPECT(Accessible_get_accState);
+ SET_EXPECT(Accessible_get_accChildCount);
+ SET_EXPECT(Accessible_accLocation);
+ SET_EXPECT(Accessible_get_accName);
+ SET_EXPECT(Accessible2_get_accRole);
+ SET_EXPECT(Accessible2_get_accState);
+ SET_EXPECT(Accessible2_get_accChildCount);
+ SET_EXPECT(Accessible2_accLocation);
+ SET_EXPECT(Accessible2_get_accName);
+ SET_EXPECT(Accessible2_QI_IAccIdentity);
+ SET_EXPECT(Accessible2_get_accParent);
+ elfrag2 = (void *)0xdeadbeef;
+ hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_Parent, &elfrag2);
+ ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
+ todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(!elfrag2, "elfrag2 != NULL\n");
+ todo_wine CHECK_CALLED(winproc_GETOBJECT_CLIENT);
+ todo_wine CHECK_CALLED(Accessible_get_accRole);
+ todo_wine CHECK_CALLED(Accessible_get_accState);
+ todo_wine CHECK_CALLED(Accessible_get_accChildCount);
+ todo_wine CHECK_CALLED(Accessible_accLocation);
+ todo_wine CHECK_CALLED(Accessible_get_accName);
+ todo_wine CHECK_CALLED(Accessible2_get_accRole);
+ todo_wine CHECK_CALLED(Accessible2_get_accState);
+ todo_wine CHECK_CALLED(Accessible2_get_accChildCount);
+ todo_wine CHECK_CALLED(Accessible2_accLocation);
+ todo_wine CHECK_CALLED(Accessible2_get_accName);
+ todo_wine CHECK_CALLED(Accessible2_QI_IAccIdentity);
+ todo_wine CHECK_CALLED(Accessible2_get_accParent);
+ acc_client = NULL;
+
+ if (SUCCEEDED(hr))
+ {
+ /* No check against root IAccessible, since it was done previously. */
+ elprov2 = (void *)0xdeadbeef;
+ hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
+ IRawElementProviderSimple_Release(elprov2);
+ }
+
+ /* Do nothing. */
+ elfrag2 = (void *)0xdeadbeef;
+ hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_Parent, &elfrag2);
+ ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
+ todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(!elfrag2, "elfrag2 != NULL\n");
+
+ elfrag2 = (void *)0xdeadbeef;
+ hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_NextSibling, &elfrag2);
+ ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
+ todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(!elfrag2, "elfrag2 != NULL\n");
+
+ elfrag2 = (void *)0xdeadbeef;
+ hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_PreviousSibling, &elfrag2);
+ ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
+ todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(!elfrag2, "elfrag2 != NULL\n");
+
+ /*
+ * Retrieve childid 2 (Accessible_child) as first child. childid 1 is skipped due to
+ * having a state of STATE_SYSTEM_INVISIBLE.
+ */
+ set_accessible_props(&Accessible_child, 0, STATE_SYSTEM_FOCUSABLE, 0, NULL, 0, 0, 0, 0);
+ set_accessible_props(&Accessible_child2, 0, STATE_SYSTEM_FOCUSABLE, 0, NULL, 0, 0, 0, 0);
+ SET_EXPECT_MULTI(Accessible_get_accChildCount, 3);
+ SET_EXPECT_MULTI(Accessible_get_accChild, 2);
+ SET_EXPECT(Accessible_get_accState);
+ SET_EXPECT(Accessible_child_get_accState);
+ SET_EXPECT(Accessible_child_accNavigate);
+ SET_EXPECT(Accessible_child_get_accParent);
+ hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_FirstChild, &elfrag2);
+ todo_wine ok(Accessible_child.ref == 2, "Unexpected refcnt %ld\n", Accessible_child.ref);
+ todo_wine ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref);
+ todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ todo_wine ok(!!elfrag2, "elfrag2 == NULL\n");
+ todo_wine CHECK_CALLED_MULTI(Accessible_get_accChildCount, 3);
+ todo_wine CHECK_CALLED_MULTI(Accessible_get_accChild, 2);
+ todo_wine CHECK_CALLED(Accessible_child_get_accState);
+ todo_wine CHECK_CALLED(Accessible_child_accNavigate);
+ todo_wine CHECK_CALLED(Accessible_child_get_accParent);
+ if (elfrag2)
+ {
+ check_fragment_acc(elfrag2, &Accessible_child.IAccessible_iface, CHILDID_SELF);
+
+ SET_EXPECT(Accessible_get_accChildCount);
+ SET_EXPECT(Accessible_get_accChild);
+ SET_EXPECT(Accessible_get_accState);
+ hr = IRawElementProviderFragment_Navigate(elfrag2, NavigateDirection_NextSibling, &elfrag3);
+ ok(Accessible.ref == 5, "Unexpected refcnt %ld\n", Accessible.ref);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(!!elfrag3, "elfrag2 == NULL\n");
+ CHECK_CALLED(Accessible_get_accChildCount);
+ CHECK_CALLED(Accessible_get_accChild);
+ CHECK_CALLED(Accessible_get_accState);
+ check_fragment_acc(elfrag3, &Accessible.IAccessible_iface, 3);
+
+ IRawElementProviderFragment_Release(elfrag3);
+ ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref);
+ IRawElementProviderFragment_Release(elfrag2);
+ ok(Accessible_child.ref == 1, "Unexpected refcnt %ld\n", Accessible_child.ref);
+ ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
+ }
+
+ /* Retrieve childid 3 as first child now that Accessible_child is invisible. */
+ set_accessible_props(&Accessible_child, 0, STATE_SYSTEM_INVISIBLE, 0, NULL, 0, 0, 0, 0);
+ SET_EXPECT_MULTI(Accessible_get_accChildCount, 4);
+ SET_EXPECT_MULTI(Accessible_get_accChild, 3);
+ SET_EXPECT_MULTI(Accessible_get_accState, 2);
+ SET_EXPECT(Accessible_child_get_accState);
+ hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_FirstChild, &elfrag2);
+ todo_wine ok(Accessible.ref == 4, "Unexpected refcnt %ld\n", Accessible.ref);
+ todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ todo_wine ok(!!elfrag2, "elfrag2 == NULL\n");
+ todo_wine CHECK_CALLED_MULTI(Accessible_get_accChildCount, 4);
+ todo_wine CHECK_CALLED_MULTI(Accessible_get_accChild, 3);
+ todo_wine CHECK_CALLED_MULTI(Accessible_get_accState, 2);
+ todo_wine CHECK_CALLED(Accessible_child_get_accState);
+ if (elfrag2)
+ {
+ check_fragment_acc(elfrag2, &Accessible.IAccessible_iface, 3);
+ IRawElementProviderFragment_Release(elfrag2);
+ ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
+ }
+
+ /* Retrieve childid 4 (Accessible_child2) as last child. */
+ set_accessible_props(&Accessible_child2, 0, STATE_SYSTEM_FOCUSABLE, 0, NULL, 0, 0, 0, 0);
+ SET_EXPECT_MULTI(Accessible_get_accChildCount, 2);
+ SET_EXPECT(Accessible_get_accChild);
+ SET_EXPECT(Accessible_child2_get_accState);
+ SET_EXPECT(Accessible_child2_accNavigate);
+ SET_EXPECT(Accessible_child2_get_accParent);
+ hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_LastChild, &elfrag2);
+ todo_wine ok(Accessible_child2.ref == 2, "Unexpected refcnt %ld\n", Accessible_child2.ref);
+ todo_wine ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref);
+ todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ todo_wine ok(!!elfrag2, "elfrag2 == NULL\n");
+ todo_wine CHECK_CALLED_MULTI(Accessible_get_accChildCount, 2);
+ todo_wine CHECK_CALLED(Accessible_get_accChild);
+ todo_wine CHECK_CALLED(Accessible_child2_get_accState);
+ todo_wine CHECK_CALLED(Accessible_child2_accNavigate);
+ todo_wine CHECK_CALLED(Accessible_child2_get_accParent);
+ if (elfrag2)
+ {
+ check_fragment_acc(elfrag2, &Accessible_child2.IAccessible_iface, CHILDID_SELF);
+
+ SET_EXPECT(Accessible_get_accChildCount);
+ SET_EXPECT(Accessible_get_accChild);
+ SET_EXPECT(Accessible_get_accState);
+ hr = IRawElementProviderFragment_Navigate(elfrag2, NavigateDirection_PreviousSibling, &elfrag3);
+ ok(Accessible.ref == 5, "Unexpected refcnt %ld\n", Accessible.ref);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(!!elfrag3, "elfrag2 == NULL\n");
+ CHECK_CALLED(Accessible_get_accChildCount);
+ CHECK_CALLED(Accessible_get_accChild);
+ CHECK_CALLED(Accessible_get_accState);
+ check_fragment_acc(elfrag3, &Accessible.IAccessible_iface, 3);
+
+ IRawElementProviderFragment_Release(elfrag3);
+ ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref);
+ IRawElementProviderFragment_Release(elfrag2);
+ ok(Accessible_child2.ref == 1, "Unexpected refcnt %ld\n", Accessible_child2.ref);
+ ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
+ }
+
+ /* Retrieve childid 3 as last child, now that Accessible_child2 is STATE_SYSTEM_INVISIBLE. */
+ set_accessible_props(&Accessible_child2, 0, STATE_SYSTEM_INVISIBLE, 0, NULL, 0, 0, 0, 0);
+ SET_EXPECT_MULTI(Accessible_get_accChildCount, 3);
+ SET_EXPECT_MULTI(Accessible_get_accChild, 2);
+ SET_EXPECT(Accessible_get_accState);
+ SET_EXPECT(Accessible_child2_get_accState);
+ hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_LastChild, &elfrag2);
+ todo_wine ok(Accessible.ref == 4, "Unexpected refcnt %ld\n", Accessible.ref);
+ todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ todo_wine ok(!!elfrag2, "elfrag2 == NULL\n");
+ todo_wine CHECK_CALLED_MULTI(Accessible_get_accChildCount, 3);
+ todo_wine CHECK_CALLED_MULTI(Accessible_get_accChild, 2);
+ todo_wine CHECK_CALLED(Accessible_get_accState);
+ todo_wine CHECK_CALLED(Accessible_child2_get_accState);
+ if (elfrag2)
+ {
+ check_fragment_acc(elfrag2, &Accessible.IAccessible_iface, 3);
+ IRawElementProviderFragment_Release(elfrag2);
+ ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
+ }
+
+ IRawElementProviderFragment_Release(elfrag);
+ IRawElementProviderSimple_Release(elprov);
+ ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
+
+ /*
+ * Full IAccessible child tests.
+ */
+ SET_EXPECT(Accessible_child_accNavigate);
+ SET_EXPECT(Accessible_child_get_accParent);
+ hr = pUiaProviderFromIAccessible(&Accessible_child.IAccessible_iface, 0, UIA_PFIA_DEFAULT, &elprov);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ CHECK_CALLED(Accessible_child_accNavigate);
+ CHECK_CALLED(Accessible_child_get_accParent);
+ ok(Accessible_child.ref == 2, "Unexpected refcnt %ld\n", Accessible_child.ref);
+
+ hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragment, (void **)&elfrag);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(!!elfrag, "elfrag == NULL\n");
+
+ /*
+ * After determining this isn't the root IAccessible, get_accParent will
+ * be used to get the parent.
+ */
+ set_accessible_props(&Accessible2, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 0, NULL, 0, 0, 0, 0);
+ set_accessible_props(&Accessible_child, ROLE_SYSTEM_CLIENT, STATE_SYSTEM_FOCUSABLE, 0, NULL, 0, 0, 0, 0);
+ acc_client = &Accessible2.IAccessible_iface;
+ SET_EXPECT(winproc_GETOBJECT_CLIENT);
+ SET_EXPECT(Accessible_child_get_accRole);
+ SET_EXPECT(Accessible_child_get_accParent);
+ SET_EXPECT(Accessible2_get_accRole);
+ SET_EXPECT(Accessible2_QI_IAccIdentity);
+ SET_EXPECT(Accessible2_get_accParent);
+ hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_Parent, &elfrag2);
+ todo_wine ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
+ todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ todo_wine ok(!!elfrag2, "elfrag2 == NULL\n");
+ todo_wine CHECK_CALLED(Accessible_child_get_accParent);
+ todo_wine CHECK_CALLED(Accessible_child_get_accRole);
+ todo_wine CHECK_CALLED(Accessible2_get_accRole);
+ todo_wine CHECK_CALLED(Accessible2_QI_IAccIdentity);
+ todo_wine CHECK_CALLED(Accessible2_get_accParent);
+ todo_wine CHECK_CALLED(winproc_GETOBJECT_CLIENT);
+ if (elfrag2)
+ {
+ check_fragment_acc(elfrag2, &Accessible.IAccessible_iface, CHILDID_SELF);
+ IRawElementProviderFragment_Release(elfrag2);
+ ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
+ }
+ acc_client = NULL;
+
+ /* Second call only does get_accParent, no root check. */
+ SET_EXPECT(Accessible_child_get_accParent);
+ hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_Parent, &elfrag2);
+ todo_wine ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
+ todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ todo_wine ok(!!elfrag2, "elfrag2 == NULL\n");
+ todo_wine CHECK_CALLED(Accessible_child_get_accParent);
+ if (elfrag2)
+ {
+ check_fragment_acc(elfrag2, &Accessible.IAccessible_iface, CHILDID_SELF);
+ IRawElementProviderFragment_Release(elfrag2);
+ ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
+ }
+
+ /* ChildCount of 0, do nothing for First/Last child.*/
+ SET_EXPECT(Accessible_child_get_accChildCount);
+ hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_FirstChild, &elfrag2);
+ todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(!elfrag2, "elfrag2 != NULL\n");
+ todo_wine CHECK_CALLED(Accessible_child_get_accChildCount);
+
+ SET_EXPECT(Accessible_child_get_accChildCount);
+ hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_LastChild, &elfrag2);
+ todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(!elfrag2, "elfrag2 != NULL\n");
+ todo_wine CHECK_CALLED(Accessible_child_get_accChildCount);
+
+ /*
+ * In the case of sibling navigation on an IAccessible that wasn't
+ * received through previous navigation from a parent (i.e, from
+ * NavigateDirection_First/LastChild), we have to figure out which
+ * IAccessible child we represent by comparing against all children of our
+ * IAccessible parent. If we find more than one IAccessible that matches,
+ * or none at all that do, navigation will fail.
+ */
+ set_accessible_props(&Accessible_child, ROLE_SYSTEM_CLIENT, STATE_SYSTEM_FOCUSABLE, 1,
+ L"acc_child", 0, 0, 50, 50);
+ set_accessible_props(&Accessible_child2, ROLE_SYSTEM_CLIENT, STATE_SYSTEM_FOCUSABLE, 1,
+ L"acc_child", 0, 0, 50, 50);
+ SET_EXPECT_MULTI(Accessible_get_accChildCount, 5);
+ SET_EXPECT_MULTI(Accessible_get_accChild, 4);
+ SET_EXPECT(Accessible_child_get_accParent);
+ SET_EXPECT(Accessible_child_get_accRole);
+ SET_EXPECT(Accessible_child_get_accState);
+ SET_EXPECT(Accessible_child_get_accChildCount);
+ SET_EXPECT(Accessible_child_accLocation);
+ SET_EXPECT(Accessible_child_get_accName);
+ SET_EXPECT(Accessible_child2_get_accRole);
+ SET_EXPECT(Accessible_child2_get_accState);
+ SET_EXPECT(Accessible_child2_get_accChildCount);
+ SET_EXPECT(Accessible_child2_accLocation);
+ SET_EXPECT(Accessible_child2_get_accName);
+ hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_NextSibling, &elfrag2);
+ todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(!elfrag2, "elfrag2 != NULL\n");
+ todo_wine CHECK_CALLED_MULTI(Accessible_get_accChildCount, 5);
+ todo_wine CHECK_CALLED_MULTI(Accessible_get_accChild, 4);
+ todo_wine CHECK_CALLED(Accessible_child_get_accParent);
+ todo_wine CHECK_CALLED(Accessible_child_get_accRole);
+ todo_wine CHECK_CALLED(Accessible_child_get_accState);
+ todo_wine CHECK_CALLED(Accessible_child_get_accChildCount);
+ todo_wine CHECK_CALLED(Accessible_child_accLocation);
+ todo_wine CHECK_CALLED(Accessible_child_get_accName);
+ todo_wine CHECK_CALLED(Accessible_child2_get_accRole);
+ todo_wine CHECK_CALLED(Accessible_child2_get_accState);
+ todo_wine CHECK_CALLED(Accessible_child2_get_accChildCount);
+ todo_wine CHECK_CALLED(Accessible_child2_accLocation);
+ todo_wine CHECK_CALLED(Accessible_child2_get_accName);
+
+ /* Now they have a role mismatch, we can determine our position. */
+ set_accessible_props(&Accessible_child2, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 1,
+ L"acc_child", 0, 0, 50, 50);
+ SET_EXPECT_MULTI(Accessible_get_accChildCount, 6);
+ SET_EXPECT_MULTI(Accessible_get_accChild, 5);
+ /* Check ChildID 1 for STATE_SYSTEM_INVISIBLE. */
+ SET_EXPECT(Accessible_get_accState);
+ SET_EXPECT(Accessible_child_get_accParent);
+ SET_EXPECT(Accessible_child_get_accRole);
+ SET_EXPECT(Accessible_child2_get_accRole);
+ hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_PreviousSibling, &elfrag2);
+ /*
+ * Even though we didn't get a new fragment, now that we know our
+ * position, a reference is added to the parent IAccessible.
+ */
+ todo_wine ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
+ todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(!elfrag2, "elfrag2 != NULL\n");
+ todo_wine CHECK_CALLED_MULTI(Accessible_get_accChildCount, 6);
+ todo_wine CHECK_CALLED_MULTI(Accessible_get_accChild, 5);
+ todo_wine CHECK_CALLED(Accessible_get_accState);
+ todo_wine CHECK_CALLED(Accessible_child_get_accParent);
+ todo_wine CHECK_CALLED(Accessible_child_get_accRole);
+ todo_wine CHECK_CALLED(Accessible_child2_get_accRole);
+
+ /* Now that we know our position, no extra nav work. */
+ SET_EXPECT(Accessible_get_accChildCount);
+ SET_EXPECT(Accessible_get_accChild);
+ SET_EXPECT(Accessible_get_accState);
+ hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_NextSibling, &elfrag2);
+ todo_wine ok(Accessible.ref == 4, "Unexpected refcnt %ld\n", Accessible.ref);
+ todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ todo_wine ok(!!elfrag2, "elfrag2 == NULL\n");
+ todo_wine CHECK_CALLED(Accessible_get_accChildCount);
+ todo_wine CHECK_CALLED(Accessible_get_accChild);
+ todo_wine CHECK_CALLED(Accessible_get_accState);
+ if (elfrag2)
+ {
+ check_fragment_acc(elfrag2, &Accessible.IAccessible_iface, 3);
+ IRawElementProviderFragment_Release(elfrag2);
+ ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
+ }
+
+ IRawElementProviderFragment_Release(elfrag);
+ IRawElementProviderSimple_Release(elprov);
+ ok(Accessible_child.ref == 1, "Unexpected refcnt %ld\n", Accessible_child.ref);
+ ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
+
+ /*
+ * Simple element child tests.
+ */
+ hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, 1, UIA_PFIA_DEFAULT, &elprov);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
+
+ hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragment, (void **)&elfrag);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(!!elfrag, "elfrag == NULL\n");
+
+ /*
+ * Simple child elements don't check the root IAccessible, because they
+ * can't be the root IAccessible.
+ */
+ hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_Parent, &elfrag2);
+ todo_wine ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref);
+ todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ todo_wine ok(!!elfrag2, "elfrag2 == NULL\n");
+ if (elfrag2)
+ {
+ check_fragment_acc(elfrag2, &Accessible.IAccessible_iface, CHILDID_SELF);
+ IRawElementProviderFragment_Release(elfrag2);
+ ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
+ }
+
+ /*
+ * Test NavigateDirection_First/LastChild on simple child element. Does
+ * nothing, as simple children cannot have children.
+ */
+ hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_FirstChild, &elfrag2);
+ ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
+ todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(!elfrag2, "elfrag2 != NULL\n");
+
+ hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_LastChild, &elfrag2);
+ ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
+ todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(!elfrag2, "elfrag2 != NULL\n");
+
+ /*
+ * NavigateDirection_Next/PreviousSibling behaves normally, no IAccessible
+ * comparisons.
+ */
+ SET_EXPECT(Accessible_get_accChildCount);
+ SET_EXPECT(Accessible_get_accChild);
+ SET_EXPECT(Accessible_child_get_accState);
+ SET_EXPECT(Accessible_child_accNavigate);
+ SET_EXPECT(Accessible_child_get_accParent);
+ hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_NextSibling, &elfrag2);
+ todo_wine ok(Accessible_child.ref == 2, "Unexpected refcnt %ld\n", Accessible_child.ref);
+ todo_wine ok(Accessible.ref == 4, "Unexpected refcnt %ld\n", Accessible.ref);
+ todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ todo_wine ok(!!elfrag2, "elfrag2 == NULL\n");
+ todo_wine CHECK_CALLED(Accessible_get_accChildCount);
+ todo_wine CHECK_CALLED(Accessible_get_accChild);
+ todo_wine CHECK_CALLED(Accessible_child_get_accState);
+ todo_wine CHECK_CALLED(Accessible_child_accNavigate);
+ todo_wine CHECK_CALLED(Accessible_child_get_accParent);
+ if (elfrag2)
+ {
+ check_fragment_acc(elfrag2, &Accessible_child.IAccessible_iface, CHILDID_SELF);
+ IRawElementProviderFragment_Release(elfrag2);
+ ok(Accessible_child.ref == 1, "Unexpected refcnt %ld\n", Accessible_child.ref);
+ ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref);
+ }
+
+ IRawElementProviderFragment_Release(elfrag);
+ IRawElementProviderSimple_Release(elprov);
+ ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
+
+ set_accessible_props(&Accessible, 0, 0, 0, NULL, 0, 0, 0, 0);
+ set_accessible_props(&Accessible2, 0, 0, 0, NULL, 0, 0, 0, 0);
+ set_accessible_props(&Accessible_child, 0, 0, 0, NULL, 0, 0, 0, 0);
+ set_accessible_props(&Accessible_child2, 0, 0, 0, NULL, 0, 0, 0, 0);
+}
+
static void test_uia_prov_from_acc_properties(void)
{
IRawElementProviderSimple *elprov;
@@ -1510,6 +2115,7 @@ static void test_UiaProviderFromIAccessible(void)
ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
test_uia_prov_from_acc_properties();
+ test_uia_prov_from_acc_navigation();
CoUninitialize();
DestroyWindow(hwnd);
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/230
June 11, 2022
[PATCH 1/3] uiautomationcore: Add stub IRawElementProviderFragment for MSAA providers.
by Connor McAdams
From: Connor McAdams <cmcadams(a)codeweavers.com>
Signed-off-by: Connor McAdams <cmcadams(a)codeweavers.com>
---
dlls/uiautomationcore/uia_provider.c | 89 ++++++++++++++++++++++++++++
1 file changed, 89 insertions(+)
diff --git a/dlls/uiautomationcore/uia_provider.c b/dlls/uiautomationcore/uia_provider.c
index 9d8d44c90fd..8701d67a89f 100644
--- a/dlls/uiautomationcore/uia_provider.c
+++ b/dlls/uiautomationcore/uia_provider.c
@@ -289,6 +289,7 @@ static LONG msaa_role_to_uia_control_type(LONG role)
*/
struct msaa_provider {
IRawElementProviderSimple IRawElementProviderSimple_iface;
+ IRawElementProviderFragment IRawElementProviderFragment_iface;
ILegacyIAccessibleProvider ILegacyIAccessibleProvider_iface;
LONG refcount;
@@ -336,6 +337,8 @@ HRESULT WINAPI msaa_provider_QueryInterface(IRawElementProviderSimple *iface, RE
*ppv = NULL;
if (IsEqualIID(riid, &IID_IRawElementProviderSimple) || IsEqualIID(riid, &IID_IUnknown))
*ppv = iface;
+ else if (IsEqualIID(riid, &IID_IRawElementProviderFragment))
+ *ppv = &msaa_prov->IRawElementProviderFragment_iface;
else if (IsEqualIID(riid, &IID_ILegacyIAccessibleProvider))
*ppv = &msaa_prov->ILegacyIAccessibleProvider_iface;
else
@@ -481,6 +484,91 @@ static const IRawElementProviderSimpleVtbl msaa_provider_vtbl = {
msaa_provider_get_HostRawElementProvider,
};
+/*
+ * IRawElementProviderFragment interface for UiaProviderFromIAccessible
+ * providers.
+ */
+static inline struct msaa_provider *impl_from_msaa_fragment(IRawElementProviderFragment *iface)
+{
+ return CONTAINING_RECORD(iface, struct msaa_provider, IRawElementProviderFragment_iface);
+}
+
+static HRESULT WINAPI msaa_fragment_QueryInterface(IRawElementProviderFragment *iface, REFIID riid,
+ void **ppv)
+{
+ struct msaa_provider *msaa_prov = impl_from_msaa_fragment(iface);
+ return IRawElementProviderSimple_QueryInterface(&msaa_prov->IRawElementProviderSimple_iface, riid, ppv);
+}
+
+static ULONG WINAPI msaa_fragment_AddRef(IRawElementProviderFragment *iface)
+{
+ struct msaa_provider *msaa_prov = impl_from_msaa_fragment(iface);
+ return IRawElementProviderSimple_AddRef(&msaa_prov->IRawElementProviderSimple_iface);
+}
+
+static ULONG WINAPI msaa_fragment_Release(IRawElementProviderFragment *iface)
+{
+ struct msaa_provider *msaa_prov = impl_from_msaa_fragment(iface);
+ return IRawElementProviderSimple_Release(&msaa_prov->IRawElementProviderSimple_iface);
+}
+
+static HRESULT WINAPI msaa_fragment_Navigate(IRawElementProviderFragment *iface,
+ enum NavigateDirection direction, IRawElementProviderFragment **ret_val)
+{
+ FIXME("%p, %d, %p: stub!\n", iface, direction, ret_val);
+ *ret_val = NULL;
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI msaa_fragment_GetRuntimeId(IRawElementProviderFragment *iface,
+ SAFEARRAY **ret_val)
+{
+ FIXME("%p, %p: stub!\n", iface, ret_val);
+ *ret_val = NULL;
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI msaa_fragment_get_BoundingRectangle(IRawElementProviderFragment *iface,
+ struct UiaRect *ret_val)
+{
+ FIXME("%p, %p: stub!\n", iface, ret_val);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI msaa_fragment_GetEmbeddedFragmentRoots(IRawElementProviderFragment *iface,
+ SAFEARRAY **ret_val)
+{
+ FIXME("%p, %p: stub!\n", iface, ret_val);
+ *ret_val = NULL;
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI msaa_fragment_SetFocus(IRawElementProviderFragment *iface)
+{
+ FIXME("%p: stub!\n", iface);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI msaa_fragment_get_FragmentRoot(IRawElementProviderFragment *iface,
+ IRawElementProviderFragmentRoot **ret_val)
+{
+ FIXME("%p, %p: stub!\n", iface, ret_val);
+ *ret_val = NULL;
+ return E_NOTIMPL;
+}
+
+static const IRawElementProviderFragmentVtbl msaa_fragment_vtbl = {
+ msaa_fragment_QueryInterface,
+ msaa_fragment_AddRef,
+ msaa_fragment_Release,
+ msaa_fragment_Navigate,
+ msaa_fragment_GetRuntimeId,
+ msaa_fragment_get_BoundingRectangle,
+ msaa_fragment_GetEmbeddedFragmentRoots,
+ msaa_fragment_SetFocus,
+ msaa_fragment_get_FragmentRoot,
+};
+
/*
* ILegacyIAccessibleProvider interface for UiaProviderFromIAccessible
* providers.
@@ -682,6 +770,7 @@ HRESULT WINAPI UiaProviderFromIAccessible(IAccessible *acc, long child_id, DWORD
return E_OUTOFMEMORY;
msaa_prov->IRawElementProviderSimple_iface.lpVtbl = &msaa_provider_vtbl;
+ msaa_prov->IRawElementProviderFragment_iface.lpVtbl = &msaa_fragment_vtbl;
msaa_prov->ILegacyIAccessibleProvider_iface.lpVtbl = &msaa_acc_provider_vtbl;
msaa_prov->refcount = 1;
msaa_prov->hwnd = hwnd;
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/230
June 11, 2022
[PATCH 0/3] MR230: UiaProviderFromIAccessible: Initial navigation patches.
by Connor McAdams (ï¼ cmcadams)
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/230
June 11, 2022
Re: [PATCH v2 resend 3/6] comctl32/listview: Send LVN_ODSTATECHANGED only for virtual lists.
by Angelo Haller
On 11/06/2022 10.30, Angelo Haller wrote:
> On 11/06/2022 03.02, Zhiyi Zhang wrote:
>>
>> On 6/11/22 07:56, Angelo Haller wrote:
>>> On 10/06/2022 03.13, Zhiyi Zhang wrote:
>>>> On 5/26/22 04:00, Angelo Haller wrote:
>>>>> From: Angelo Haller <angelo(a)szanni.org>
>>>>>
>>>>> The LVN_ODSTATECHANGED notification should only be sent to lists
>>>>> that have LVS_OWNERDATA set.
>>>>>
>>>>> Signed-off-by: Angelo Haller <angelo(a)szanni.org>
>>>>> ---
>>>>> Â Â dlls/comctl32/listview.c | 1 +
>>>>> Â Â 1 file changed, 1 insertion(+)
>>>>>
>>>>> diff --git a/dlls/comctl32/listview.c b/dlls/comctl32/listview.c
>>>>> index 72ade724313..318df0a4093 100644
>>>>> --- a/dlls/comctl32/listview.c
>>>>> +++ b/dlls/comctl32/listview.c
>>>>> @@ -8946,6 +8946,7 @@ static VOID
>>>>> LISTVIEW_SetOwnerDataState(LISTVIEW_INFO *infoPtr, INT nFirst, INT n
>>>>> Â Â {
>>>>> Â Â Â Â Â Â NMLVODSTATECHANGE nmlv;
>>>>> Â Â +Â Â Â if (!(infoPtr->dwStyle & LVS_OWNERDATA)) return;
>>>> Make sense. It will be better if you can add a simple test before
>>>> this patch and remove the todo_wines after the fix.
>>> Is this strictly necessary? The call site has special handling for:
>>> infoPtr->dwStyle & LVS_OWNERDATA
>>>
>>> We could guard the call to the function at the call site, if that is
>>> preferred.
>>>
>>> Apart from that I am not sure how to write a test for this. This bug
>>> is triggered by creating a non ownerdata list and selecting multiple
>>> entries holding shift+ctrl and clicking with the mouse. This will
>>> send an LVN_ODSTATECHANGED notification where it is not supposed to
>>> (as it is not an ownerdata list).
>> You can write a test that demonstrate the exact same thing. Create a
>> non onwerdata listview control and test the message sequence doesn't
>> contain LVN_ODSTATECHANGED, which should have a todo_wine
>> because Wine is currently broken in this case. Then you fix it in the
>> next patch and removes the todo_wine.
>>
>> As for the mouse emulation, could you do it using only the keyboard?
>> Such as sending VK_DOWN while holding Shift and Ctrl?
>>
> This is exactly what I was trying to communicate. I can NOT trigger
> the erroneous sending of LVN_ODSTATECHANGED via the keyboard.
>
> The bug is in LISTVIEW_AddGroupSelection which gets called from
> LISTVIEW_LButtonDown.
>
> Patch 2/6 moves the offending code to a new function
> LISTVIEW_SetOwnerdataState().
>
> This is why I asked about opening a bug report with an contrived
> application that crashes with wine but not with windows.
I just opened a bug report with a test application attached. Hope that
helps :)
https://bugs.winehq.org/show_bug.cgi?id=53123
>
>>> I have not found any test examples with mouse emulation. Maybe I
>>> missed something.
>>>
>>> Or should I open a separate bug report for this line?
>>>
>>>>> Â Â Â Â Â Â if (!item) return;
>>>>> Â Â Â Â Â Â Â ZeroMemory(&nmlv, sizeof(nmlv));
>>>
>
>
June 11, 2022
[PATCH v2 6/6] d3dx10/tests: Add D3DX10CreateAsyncTextureProcessor tests.
by Piotr Caban
From: Piotr Caban <piotr(a)codeweavers.com>
Signed-off-by: Piotr Caban <piotr(a)codeweavers.com>
---
dlls/d3dx10_43/tests/d3dx10.c | 64 +++++++++++++++++++++++++++++++++++
1 file changed, 64 insertions(+)
diff --git a/dlls/d3dx10_43/tests/d3dx10.c b/dlls/d3dx10_43/tests/d3dx10.c
index 54533f5c738..a0a2b4fc32b 100644
--- a/dlls/d3dx10_43/tests/d3dx10.c
+++ b/dlls/d3dx10_43/tests/d3dx10.c
@@ -2003,6 +2003,69 @@ static void test_D3DX10CreateAsyncTextureInfoProcessor(void)
CoUninitialize();
}
+static void test_D3DX10CreateAsyncTextureProcessor(void)
+{
+ ID3DX10DataProcessor *dp;
+ ID3D10Resource *resource;
+ ID3D10Device *device;
+ HRESULT hr;
+ int i;
+
+ device = create_device();
+ if (!device)
+ {
+ skip("Failed to create device, skipping tests.\n");
+ return;
+ }
+
+ CoInitialize(NULL);
+
+ hr = D3DX10CreateAsyncTextureProcessor(device, NULL, NULL);
+ ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
+
+ hr = D3DX10CreateAsyncTextureProcessor(NULL, NULL, &dp);
+ ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
+
+ hr = D3DX10CreateAsyncTextureProcessor(device, NULL, &dp);
+ ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
+ hr = ID3DX10DataProcessor_Process(dp, (void *)test_image[0].data, 0);
+ ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
+ hr = ID3DX10DataProcessor_Process(dp, NULL, test_image[0].size);
+ ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
+ hr = ID3DX10DataProcessor_Destroy(dp);
+ ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
+
+ for (i = 0; i < ARRAY_SIZE(test_image); ++i)
+ {
+ winetest_push_context("Test %u", i);
+
+ hr = D3DX10CreateAsyncTextureProcessor(device, NULL, &dp);
+ ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
+
+ hr = ID3DX10DataProcessor_Process(dp, (void *)test_image[i].data, test_image[i].size);
+ todo_wine_if(test_image[i].expected_info.MiscFlags & D3D10_RESOURCE_MISC_TEXTURECUBE)
+ ok(hr == S_OK || broken(hr == E_FAIL && test_image[i].expected_info.ImageFileFormat == D3DX10_IFF_WMP),
+ "Got unexpected hr %#x.\n", hr);
+ if (hr == S_OK)
+ {
+ hr = ID3DX10DataProcessor_CreateDeviceObject(dp, (void **)&resource);
+ ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
+ check_resource_info(resource, test_image + i, __LINE__);
+ check_resource_data(resource, test_image + i, __LINE__);
+ ID3D10Resource_Release(resource);
+ }
+
+ hr = ID3DX10DataProcessor_Destroy(dp);
+ ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
+
+ winetest_pop_context();
+ }
+
+ CoUninitialize();
+
+ ID3D10Device_Release(device);
+}
+
static void test_get_image_info(void)
{
static const WCHAR test_resource_name[] = L"resource.data";
@@ -3493,6 +3556,7 @@ START_TEST(d3dx10)
test_D3DX10CreateAsyncFileLoader();
test_D3DX10CreateAsyncResourceLoader();
test_D3DX10CreateAsyncTextureInfoProcessor();
+ test_D3DX10CreateAsyncTextureProcessor();
test_get_image_info();
test_create_texture();
test_font();
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/228
June 11, 2022
[PATCH v2 5/6] d3dx10: Add D3DX10CreateAsyncTextureProcessor implementation.
by Piotr Caban
From: Piotr Caban <piotr(a)codeweavers.com>
Signed-off-by: Piotr Caban <piotr(a)codeweavers.com>
---
dlls/d3dx10_43/async.c | 81 ++++++++++++++++-
dlls/d3dx10_43/dxhelpers.h | 7 ++
dlls/d3dx10_43/texture.c | 178 +++++++++++++++++++++++++++----------
3 files changed, 216 insertions(+), 50 deletions(-)
diff --git a/dlls/d3dx10_43/async.c b/dlls/d3dx10_43/async.c
index f0c726944c0..2e6eabea7a4 100644
--- a/dlls/d3dx10_43/async.c
+++ b/dlls/d3dx10_43/async.c
@@ -16,6 +16,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
+#define COBJMACROS
#include "d3d10_1.h"
#include "d3dx10.h"
#include "d3dcompiler.h"
@@ -315,6 +316,66 @@ static ID3DX10DataProcessorVtbl texture_info_processor_vtbl =
texture_info_processor_Destroy
};
+struct texture_processor
+{
+ ID3DX10DataProcessor ID3DX10DataProcessor_iface;
+ ID3D10Device *device;
+ D3DX10_IMAGE_LOAD_INFO info;
+ D3D10_SUBRESOURCE_DATA *resource_data;
+};
+
+static inline struct texture_processor *texture_processor_from_ID3DX10DataProcessor(ID3DX10DataProcessor *iface)
+{
+ return CONTAINING_RECORD(iface, struct texture_processor, ID3DX10DataProcessor_iface);
+}
+
+static HRESULT WINAPI texture_processor_Process(ID3DX10DataProcessor *iface, void *data, SIZE_T size)
+{
+ struct texture_processor *processor = texture_processor_from_ID3DX10DataProcessor(iface);
+
+ TRACE("iface %p, data %p, size %Iu.\n", iface, data, size);
+
+ if (processor->resource_data)
+ {
+ FIXME("called multiple times\n");
+ free(processor->resource_data);
+ processor->resource_data = NULL;
+ }
+ return create_resource_data(data, size, &processor->info, &processor->resource_data);
+}
+
+static HRESULT WINAPI texture_processor_CreateDeviceObject(ID3DX10DataProcessor *iface, void **object)
+{
+ struct texture_processor *processor = texture_processor_from_ID3DX10DataProcessor(iface);
+
+ TRACE("iface %p, object %p.\n", iface, object);
+
+ if (!processor->resource_data)
+ return E_FAIL;
+
+ return create_texture(processor->device, &processor->info,
+ processor->resource_data, (ID3D10Resource **)object);
+}
+
+static HRESULT WINAPI texture_processor_Destroy(ID3DX10DataProcessor *iface)
+{
+ struct texture_processor *processor = texture_processor_from_ID3DX10DataProcessor(iface);
+
+ TRACE("iface %p.\n", iface);
+
+ ID3D10Device_Release(processor->device);
+ free(processor->resource_data);
+ free(processor);
+ return S_OK;
+}
+
+static ID3DX10DataProcessorVtbl texture_processor_vtbl =
+{
+ texture_processor_Process,
+ texture_processor_CreateDeviceObject,
+ texture_processor_Destroy
+};
+
HRESULT WINAPI D3DX10CompileFromMemory(const char *data, SIZE_T data_size, const char *filename,
const D3D10_SHADER_MACRO *defines, ID3D10Include *include, const char *entry_point,
const char *target, UINT sflags, UINT eflags, ID3DX10ThreadPump *pump, ID3D10Blob **shader,
@@ -517,8 +578,24 @@ HRESULT WINAPI D3DX10CreateAsyncTextureInfoProcessor(D3DX10_IMAGE_INFO *info, ID
HRESULT WINAPI D3DX10CreateAsyncTextureProcessor(ID3D10Device *device,
D3DX10_IMAGE_LOAD_INFO *info, ID3DX10DataProcessor **processor)
{
- FIXME("device %p, info %p, processor %p stub!\n", device, info, processor);
- return E_NOTIMPL;
+ struct texture_processor *object;
+
+ TRACE("device %p, info %p, processor %p.\n", device, info, processor);
+
+ if (!device || !processor)
+ return E_INVALIDARG;
+
+ object = calloc(1, sizeof(*object));
+ if (!object)
+ return E_OUTOFMEMORY;
+
+ object->ID3DX10DataProcessor_iface.lpVtbl = &texture_processor_vtbl;
+ object->device = device;
+ ID3D10Device_AddRef(device);
+ create_image_load_info(info, &object->info);
+
+ *processor = &object->ID3DX10DataProcessor_iface;
+ return S_OK;
}
HRESULT WINAPI D3DX10PreprocessShaderFromMemory(const char *data, SIZE_T data_size, const char *filename,
diff --git a/dlls/d3dx10_43/dxhelpers.h b/dlls/d3dx10_43/dxhelpers.h
index 82fe639c2ea..6f7321ddade 100644
--- a/dlls/d3dx10_43/dxhelpers.h
+++ b/dlls/d3dx10_43/dxhelpers.h
@@ -23,3 +23,10 @@ extern HRESULT load_resourceW(HMODULE module, const WCHAR *resource,
void **data, DWORD *size) DECLSPEC_HIDDEN;
extern HRESULT get_image_info(const void *data, SIZE_T size, D3DX10_IMAGE_INFO *img_info) DECLSPEC_HIDDEN;
+
+extern void create_image_load_info(const D3DX10_IMAGE_LOAD_INFO *load_info,
+ D3DX10_IMAGE_LOAD_INFO *out) DECLSPEC_HIDDEN;
+extern HRESULT create_resource_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO *load_info,
+ D3D10_SUBRESOURCE_DATA **resource_data) DECLSPEC_HIDDEN;
+extern HRESULT create_texture(ID3D10Device *device, D3DX10_IMAGE_LOAD_INFO *load_info,
+ D3D10_SUBRESOURCE_DATA *resource_data, ID3D10Resource **texture) DECLSPEC_HIDDEN;
diff --git a/dlls/d3dx10_43/texture.c b/dlls/d3dx10_43/texture.c
index eae78c9f4f2..0b1d58e0432 100644
--- a/dlls/d3dx10_43/texture.c
+++ b/dlls/d3dx10_43/texture.c
@@ -571,6 +571,22 @@ HRESULT WINAPI D3DX10GetImageInfoFromMemory(const void *src_data, SIZE_T src_dat
return hr;
}
+static HRESULT create_texture_helper(ID3D10Device *device, const void *data, SIZE_T size,
+ D3DX10_IMAGE_LOAD_INFO *load_info, ID3D10Resource **texture)
+{
+ D3D10_SUBRESOURCE_DATA *resource_data;
+ D3DX10_IMAGE_LOAD_INFO info;
+ HRESULT hr;
+
+ create_image_load_info(load_info, &info);
+
+ if (FAILED((hr = create_resource_data(data, size, &info, &resource_data))))
+ return hr;
+ hr = create_texture(device, &info, resource_data, texture);
+ free(resource_data);
+ return hr;
+}
+
HRESULT WINAPI D3DX10CreateTextureFromFileA(ID3D10Device *device, const char *src_file,
D3DX10_IMAGE_LOAD_INFO *load_info, ID3DX10ThreadPump *pump, ID3D10Resource **texture, HRESULT *hresult)
{
@@ -669,56 +685,83 @@ HRESULT WINAPI D3DX10CreateTextureFromResourceW(ID3D10Device *device, HMODULE mo
return D3DX10CreateTextureFromMemory(device, buffer, size, load_info, pump, texture, hresult);
}
-HRESULT WINAPI D3DX10CreateTextureFromMemory(ID3D10Device *device, const void *src_data, SIZE_T src_data_size,
- D3DX10_IMAGE_LOAD_INFO *load_info, ID3DX10ThreadPump *pump, ID3D10Resource **texture, HRESULT *hresult)
+void create_image_load_info(const D3DX10_IMAGE_LOAD_INFO *load_info, D3DX10_IMAGE_LOAD_INFO *out)
+{
+ if (load_info)
+ {
+ *out = *load_info;
+ return;
+ }
+
+ out->Width = D3DX10_DEFAULT;
+ out->Height = D3DX10_DEFAULT;
+ out->Depth = D3DX10_DEFAULT;
+ out->FirstMipLevel = D3DX10_DEFAULT;
+ out->MipLevels = D3DX10_DEFAULT;
+ out->Usage = D3DX10_DEFAULT;
+ out->BindFlags = D3DX10_DEFAULT;
+ out->CpuAccessFlags = D3DX10_DEFAULT;
+ out->MiscFlags = D3DX10_DEFAULT;
+ out->Format = D3DX10_DEFAULT;
+ out->Filter = D3DX10_DEFAULT;
+ out->MipFilter = D3DX10_DEFAULT;
+ out->pSrcInfo = NULL;
+}
+
+HRESULT create_resource_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO *load_info,
+ D3D10_SUBRESOURCE_DATA **resource_data)
{
unsigned int frame_count, width, height, stride, frame_size;
IWICFormatConverter *converter = NULL;
IWICDdsFrameDecode *dds_frame = NULL;
- D3D10_TEXTURE2D_DESC texture_2d_desc;
- D3D10_SUBRESOURCE_DATA resource_data;
IWICBitmapFrameDecode *frame = NULL;
IWICImagingFactory *factory = NULL;
IWICBitmapDecoder *decoder = NULL;
- ID3D10Texture2D *texture_2d;
+ BYTE *res_data = NULL, *buffer;
D3DX10_IMAGE_INFO img_info;
IWICStream *stream = NULL;
const GUID *dst_format;
- BYTE *buffer = NULL;
BOOL can_convert;
GUID src_format;
HRESULT hr;
- TRACE("device %p, src_data %p, src_data_size %Iu, load_info %p, pump %p, texture %p, hresult %p.\n",
- device, src_data, src_data_size, load_info, pump, texture, hresult);
-
- if (!device)
- return E_INVALIDARG;
- if (!src_data)
- return E_FAIL;
- if (load_info)
- FIXME("load_info is ignored.\n");
- if (pump)
- FIXME("Thread pump is not supported yet.\n");
-
- if (FAILED(D3DX10GetImageInfoFromMemory(src_data, src_data_size, NULL, &img_info, NULL)))
- {
- if (hresult)
- *hresult = E_FAIL;
+ if (load_info->Width != D3DX10_DEFAULT)
+ FIXME("load_info->Width is ignored.\n");
+ if (load_info->Height != D3DX10_DEFAULT)
+ FIXME("load_info->Height is ignored.\n");
+ if (load_info->Depth != D3DX10_DEFAULT)
+ FIXME("load_info->Depth is ignored.\n");
+ if (load_info->FirstMipLevel != D3DX10_DEFAULT)
+ FIXME("load_info->FirstMipLevel is ignored.\n");
+ if (load_info->MipLevels != D3DX10_DEFAULT)
+ FIXME("load_info->MipLevels is ignored.\n");
+ if (load_info->Usage != D3DX10_DEFAULT)
+ FIXME("load_info->Usage is ignored.\n");
+ if (load_info->BindFlags != D3DX10_DEFAULT)
+ FIXME("load_info->BindFlags is ignored.\n");
+ if (load_info->CpuAccessFlags != D3DX10_DEFAULT)
+ FIXME("load_info->CpuAccessFlags is ignored.\n");
+ if (load_info->MiscFlags != D3DX10_DEFAULT)
+ FIXME("load_info->MiscFlags is ignored.\n");
+ if (load_info->Format != D3DX10_DEFAULT)
+ FIXME("load_info->Format is ignored.\n");
+ if (load_info->Filter != D3DX10_DEFAULT)
+ FIXME("load_info->Filter is ignored.\n");
+ if (load_info->MipFilter != D3DX10_DEFAULT)
+ FIXME("load_info->MipFilter is ignored.\n");
+ if (load_info->pSrcInfo)
+ FIXME("load_info->pSrcInfo is ignored.\n");
+
+ if (FAILED(D3DX10GetImageInfoFromMemory(data, size, NULL, &img_info, NULL)))
return E_FAIL;
- }
if (img_info.MiscFlags & D3D10_RESOURCE_MISC_TEXTURECUBE)
{
FIXME("Cube map is not supported.\n");
- if (hresult)
- *hresult = E_FAIL;
return E_FAIL;
}
if (img_info.ArraySize != 1)
{
- FIXME("img_info.ArraySize = %d\n", img_info.ArraySize);
- if (hresult)
- *hresult = E_NOTIMPL;
+ FIXME("img_info.ArraySize = %d not supported.\n", img_info.ArraySize);
return E_NOTIMPL;
}
@@ -726,7 +769,7 @@ HRESULT WINAPI D3DX10CreateTextureFromMemory(ID3D10Device *device, const void *s
goto end;
if (FAILED(hr = IWICImagingFactory_CreateStream(factory, &stream)))
goto end;
- if (FAILED(hr = IWICStream_InitializeFromMemory(stream, (BYTE *)src_data, src_data_size)))
+ if (FAILED(hr = IWICStream_InitializeFromMemory(stream, (BYTE *)data, size)))
goto end;
if (FAILED(hr = IWICImagingFactory_CreateDecoderFromStream(factory, (IStream *)stream, NULL, 0, &decoder)))
goto end;
@@ -747,11 +790,12 @@ HRESULT WINAPI D3DX10CreateTextureFromMemory(ID3D10Device *device, const void *s
stride = (width * get_bpp_from_format(img_info.Format) + 7) / 8;
frame_size = stride * height;
- if (!(buffer = malloc(frame_size)))
+ if(!(res_data = malloc(sizeof(**resource_data) + frame_size)))
{
hr = E_FAIL;
goto end;
}
+ buffer = res_data + sizeof(**resource_data);
if (is_block_compressed(img_info.Format))
{
@@ -794,25 +838,20 @@ HRESULT WINAPI D3DX10CreateTextureFromMemory(ID3D10Device *device, const void *s
}
}
- memset(&texture_2d_desc, 0, sizeof(texture_2d_desc));
- texture_2d_desc.Width = width;
- texture_2d_desc.Height = height;
- texture_2d_desc.MipLevels = 1;
- texture_2d_desc.ArraySize = img_info.ArraySize;
- texture_2d_desc.Format = img_info.Format;
- texture_2d_desc.SampleDesc.Count = 1;
- texture_2d_desc.Usage = D3D10_USAGE_DEFAULT;
- texture_2d_desc.BindFlags = D3D10_BIND_SHADER_RESOURCE;
- texture_2d_desc.MiscFlags = img_info.MiscFlags;
-
- resource_data.pSysMem = buffer;
- resource_data.SysMemPitch = stride;
- resource_data.SysMemSlicePitch = frame_size;
+ load_info->Width = width;
+ load_info->Height = height;
+ load_info->MipLevels = 1;
+ load_info->Format = img_info.Format;
+ load_info->Usage = D3D10_USAGE_DEFAULT;
+ load_info->BindFlags = D3D10_BIND_SHADER_RESOURCE;
+ load_info->MiscFlags = img_info.MiscFlags;
- if (FAILED(hr = ID3D10Device_CreateTexture2D(device, &texture_2d_desc, &resource_data, &texture_2d)))
- goto end;
+ *resource_data = (D3D10_SUBRESOURCE_DATA *)res_data;
+ res_data = NULL;
+ (*resource_data)->pSysMem = buffer;
+ (*resource_data)->SysMemPitch = stride;
+ (*resource_data)->SysMemSlicePitch = frame_size;
- *texture = (ID3D10Resource *)texture_2d;
hr = S_OK;
end:
@@ -820,7 +859,7 @@ end:
IWICFormatConverter_Release(converter);
if (dds_frame)
IWICDdsFrameDecode_Release(dds_frame);
- free(buffer);
+ free(res_data);
if (frame)
IWICBitmapFrameDecode_Release(frame);
if (decoder)
@@ -829,7 +868,50 @@ end:
IWICStream_Release(stream);
if (factory)
IWICImagingFactory_Release(factory);
+ return hr;
+}
+
+HRESULT create_texture(ID3D10Device *device, D3DX10_IMAGE_LOAD_INFO *load_info,
+ D3D10_SUBRESOURCE_DATA *resource_data, ID3D10Resource **texture)
+{
+ D3D10_TEXTURE2D_DESC texture_2d_desc;
+ ID3D10Texture2D *texture_2d;
+ HRESULT hr;
+
+ memset(&texture_2d_desc, 0, sizeof(texture_2d_desc));
+ texture_2d_desc.Width = load_info->Width;
+ texture_2d_desc.Height = load_info->Height;
+ texture_2d_desc.MipLevels = load_info->MipLevels;
+ texture_2d_desc.ArraySize = 1;
+ texture_2d_desc.Format = load_info->Format;
+ texture_2d_desc.SampleDesc.Count = 1;
+ texture_2d_desc.Usage = load_info->Usage;
+ texture_2d_desc.BindFlags = load_info->BindFlags;
+ texture_2d_desc.MiscFlags = load_info->MiscFlags;
+
+ if (FAILED(hr = ID3D10Device_CreateTexture2D(device, &texture_2d_desc, resource_data, &texture_2d)))
+ return hr;
+
+ *texture = (ID3D10Resource *)texture_2d;
+ return S_OK;
+}
+
+HRESULT WINAPI D3DX10CreateTextureFromMemory(ID3D10Device *device, const void *src_data, SIZE_T src_data_size,
+ D3DX10_IMAGE_LOAD_INFO *load_info, ID3DX10ThreadPump *pump, ID3D10Resource **texture, HRESULT *hresult)
+{
+ HRESULT hr;
+
+ TRACE("device %p, src_data %p, src_data_size %Iu, load_info %p, pump %p, texture %p, hresult %p.\n",
+ device, src_data, src_data_size, load_info, pump, texture, hresult);
+
+ if (!device)
+ return E_INVALIDARG;
+ if (!src_data)
+ return E_FAIL;
+ if (pump)
+ FIXME("Thread pump is not supported yet.\n");
+ hr = create_texture_helper(device, src_data, src_data_size, load_info, texture);
if (hresult)
*hresult = hr;
return hr;
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/228
June 11, 2022
[PATCH v2 4/6] d3dx10: Add D3DX10CreateAsyncTextureProcessor stub.
by Piotr Caban
From: Piotr Caban <piotr(a)codeweavers.com>
Signed-off-by: Piotr Caban <piotr(a)codeweavers.com>
---
dlls/d3dx10_43/async.c | 7 +++++++
dlls/d3dx10_43/d3dx10_43.spec | 2 +-
include/d3dx10async.h | 2 ++
3 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/dlls/d3dx10_43/async.c b/dlls/d3dx10_43/async.c
index 0d75a64ff9e..f0c726944c0 100644
--- a/dlls/d3dx10_43/async.c
+++ b/dlls/d3dx10_43/async.c
@@ -514,6 +514,13 @@ HRESULT WINAPI D3DX10CreateAsyncTextureInfoProcessor(D3DX10_IMAGE_INFO *info, ID
return S_OK;
}
+HRESULT WINAPI D3DX10CreateAsyncTextureProcessor(ID3D10Device *device,
+ D3DX10_IMAGE_LOAD_INFO *info, ID3DX10DataProcessor **processor)
+{
+ FIXME("device %p, info %p, processor %p stub!\n", device, info, processor);
+ return E_NOTIMPL;
+}
+
HRESULT WINAPI D3DX10PreprocessShaderFromMemory(const char *data, SIZE_T data_size, const char *filename,
const D3D10_SHADER_MACRO *defines, ID3DInclude *include, ID3DX10ThreadPump *pump, ID3D10Blob **shader_text,
ID3D10Blob **errors, HRESULT *hresult)
diff --git a/dlls/d3dx10_43/d3dx10_43.spec b/dlls/d3dx10_43/d3dx10_43.spec
index c0a2c9fa56c..95160a067c5 100644
--- a/dlls/d3dx10_43/d3dx10_43.spec
+++ b/dlls/d3dx10_43/d3dx10_43.spec
@@ -17,7 +17,7 @@
@ stub D3DX10CreateAsyncShaderPreprocessProcessor(str ptr ptr ptr ptr ptr)
@ stub D3DX10CreateAsyncShaderResourceViewProcessor(ptr ptr ptr)
@ stdcall D3DX10CreateAsyncTextureInfoProcessor(ptr ptr)
-@ stub D3DX10CreateAsyncTextureProcessor(ptr ptr ptr)
+@ stdcall D3DX10CreateAsyncTextureProcessor(ptr ptr ptr)
@ stdcall D3DX10CreateDevice(ptr long long long ptr)
@ stdcall D3DX10CreateDeviceAndSwapChain(ptr long long long ptr ptr ptr)
@ stdcall D3DX10CreateEffectFromFileA(str ptr ptr str long long ptr ptr ptr ptr ptr ptr)
diff --git a/include/d3dx10async.h b/include/d3dx10async.h
index c932be91b01..931458f4813 100644
--- a/include/d3dx10async.h
+++ b/include/d3dx10async.h
@@ -76,6 +76,8 @@ HRESULT WINAPI D3DX10CreateAsyncMemoryLoader(const void *data, SIZE_T datasize,
HRESULT WINAPI D3DX10CreateAsyncResourceLoaderA(HMODULE module, const char *resource, ID3DX10DataLoader **loader);
HRESULT WINAPI D3DX10CreateAsyncResourceLoaderW(HMODULE module, const WCHAR *resource, ID3DX10DataLoader **loader);
+HRESULT WINAPI D3DX10CreateAsyncTextureProcessor(ID3D10Device *device,
+ D3DX10_IMAGE_LOAD_INFO *info, ID3DX10DataProcessor **processor);
HRESULT WINAPI D3DX10CreateAsyncTextureInfoProcessor(D3DX10_IMAGE_INFO *info, ID3DX10DataProcessor **processor);
#endif
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/228
June 11, 2022
[PATCH v2 3/6] d3dx10: Exit early on volume textures in D3DX10CreateTextureFromMemory.
by Piotr Caban
From: Piotr Caban <piotr(a)codeweavers.com>
---
dlls/d3dx10_43/texture.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/dlls/d3dx10_43/texture.c b/dlls/d3dx10_43/texture.c
index d5066b9793b..eae78c9f4f2 100644
--- a/dlls/d3dx10_43/texture.c
+++ b/dlls/d3dx10_43/texture.c
@@ -714,6 +714,13 @@ HRESULT WINAPI D3DX10CreateTextureFromMemory(ID3D10Device *device, const void *s
*hresult = E_FAIL;
return E_FAIL;
}
+ if (img_info.ArraySize != 1)
+ {
+ FIXME("img_info.ArraySize = %d\n", img_info.ArraySize);
+ if (hresult)
+ *hresult = E_NOTIMPL;
+ return E_NOTIMPL;
+ }
if (FAILED(hr = WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION, &factory)))
goto end;
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/228
June 11, 2022