For React Native.
From: Zhiyi Zhang zzhang@codeweavers.com
--- configure.ac | 2 + dlls/windows.ui.core.textinput/Makefile.in | 6 + dlls/windows.ui.core.textinput/classes.idl | 28 ++++ dlls/windows.ui.core.textinput/main.c | 135 ++++++++++++++++++ dlls/windows.ui.core.textinput/private.h | 31 ++++ .../tests/Makefile.in | 5 + .../tests/textinput.c | 82 +++++++++++ .../windows.ui.core.textinput.spec | 3 + 8 files changed, 292 insertions(+) create mode 100644 dlls/windows.ui.core.textinput/Makefile.in create mode 100644 dlls/windows.ui.core.textinput/classes.idl create mode 100644 dlls/windows.ui.core.textinput/main.c create mode 100644 dlls/windows.ui.core.textinput/private.h create mode 100644 dlls/windows.ui.core.textinput/tests/Makefile.in create mode 100644 dlls/windows.ui.core.textinput/tests/textinput.c create mode 100644 dlls/windows.ui.core.textinput/windows.ui.core.textinput.spec
diff --git a/configure.ac b/configure.ac index 0ab295b0f52..39d68b13635 100644 --- a/configure.ac +++ b/configure.ac @@ -3336,6 +3336,8 @@ WINE_CONFIG_MAKEFILE(dlls/windows.system.profile.systemid) WINE_CONFIG_MAKEFILE(dlls/windows.system.profile.systemid/tests) WINE_CONFIG_MAKEFILE(dlls/windows.system.profile.systemmanufacturers) WINE_CONFIG_MAKEFILE(dlls/windows.system.profile.systemmanufacturers/tests) +WINE_CONFIG_MAKEFILE(dlls/windows.ui.core.textinput) +WINE_CONFIG_MAKEFILE(dlls/windows.ui.core.textinput/tests) WINE_CONFIG_MAKEFILE(dlls/windows.ui.xaml) WINE_CONFIG_MAKEFILE(dlls/windows.ui.xaml/tests) WINE_CONFIG_MAKEFILE(dlls/windows.ui) diff --git a/dlls/windows.ui.core.textinput/Makefile.in b/dlls/windows.ui.core.textinput/Makefile.in new file mode 100644 index 00000000000..11890311a75 --- /dev/null +++ b/dlls/windows.ui.core.textinput/Makefile.in @@ -0,0 +1,6 @@ +MODULE = windows.ui.core.textinput.dll +IMPORTS = combase + +SOURCES = \ + classes.idl \ + main.c diff --git a/dlls/windows.ui.core.textinput/classes.idl b/dlls/windows.ui.core.textinput/classes.idl new file mode 100644 index 00000000000..71c1bf98634 --- /dev/null +++ b/dlls/windows.ui.core.textinput/classes.idl @@ -0,0 +1,28 @@ +/* + * Runtime Classes for windows.ui.core.textinput.dll + * + * Copyright 2025 Zhiyi Zhang for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#pragma makedep register +#pragma winrt ns_prefix + +import "windows.ui.viewmanagement.core.idl"; + +namespace Windows.UI.ViewManagement.Core { + runtimeclass CoreInputView; +} diff --git a/dlls/windows.ui.core.textinput/main.c b/dlls/windows.ui.core.textinput/main.c new file mode 100644 index 00000000000..b40bdf3cdff --- /dev/null +++ b/dlls/windows.ui.core.textinput/main.c @@ -0,0 +1,135 @@ +/* WinRT Windows.UI.ViewManagement.Core.CoreInputView Implementation + * + * Copyright 2025 Zhiyi Zhang for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "initguid.h" +#include "private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(coreinputview); + +struct core_input_view_statics +{ + IActivationFactory IActivationFactory_iface; + LONG ref; +}; + +static inline struct core_input_view_statics *impl_from_IActivationFactory(IActivationFactory *iface) +{ + return CONTAINING_RECORD(iface, struct core_input_view_statics, IActivationFactory_iface); +} + +static HRESULT WINAPI factory_QueryInterface(IActivationFactory *iface, REFIID iid, void **out) +{ + struct core_input_view_statics *impl = impl_from_IActivationFactory(iface); + + TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); + + if (IsEqualGUID(iid, &IID_IUnknown) + || IsEqualGUID(iid, &IID_IInspectable) + || IsEqualGUID(iid, &IID_IActivationFactory)) + { + *out = &impl->IActivationFactory_iface; + IActivationFactory_AddRef(*out); + return S_OK; + } + + FIXME("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI factory_AddRef(IActivationFactory *iface) +{ + struct core_input_view_statics *impl = impl_from_IActivationFactory(iface); + ULONG ref = InterlockedIncrement(&impl->ref); + TRACE("iface %p, ref %lu.\n", iface, ref); + return ref; +} + +static ULONG WINAPI factory_Release(IActivationFactory *iface) +{ + struct core_input_view_statics *impl = impl_from_IActivationFactory(iface); + ULONG ref = InterlockedDecrement(&impl->ref); + TRACE("iface %p, ref %lu.\n", iface, ref); + return ref; +} + +static HRESULT WINAPI factory_GetIids(IActivationFactory *iface, ULONG *iid_count, IID **iids) +{ + FIXME("iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids); + return E_NOTIMPL; +} + +static HRESULT WINAPI factory_GetRuntimeClassName(IActivationFactory *iface, HSTRING *class_name) +{ + FIXME("iface %p, class_name %p stub!\n", iface, class_name); + return E_NOTIMPL; +} + +static HRESULT WINAPI factory_GetTrustLevel(IActivationFactory *iface, TrustLevel *trust_level) +{ + FIXME("iface %p, trust_level %p stub!\n", iface, trust_level); + return E_NOTIMPL; +} + +static HRESULT WINAPI factory_ActivateInstance(IActivationFactory *iface, IInspectable **instance) +{ + FIXME("iface %p, instance %p stub!\n", iface, instance); + return E_NOTIMPL; +} + +static const struct IActivationFactoryVtbl factory_vtbl = +{ + factory_QueryInterface, + factory_AddRef, + factory_Release, + /* IInspectable methods */ + factory_GetIids, + factory_GetRuntimeClassName, + factory_GetTrustLevel, + /* IActivationFactory methods */ + factory_ActivateInstance, +}; + +static struct core_input_view_statics core_input_view_statics = +{ + {&factory_vtbl}, + 1, +}; + +static IActivationFactory *core_input_view_factory = &core_input_view_statics.IActivationFactory_iface; + +HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID riid, void **out) +{ + FIXME("clsid %s, riid %s, out %p stub!\n", debugstr_guid(clsid), debugstr_guid(riid), out); + return CLASS_E_CLASSNOTAVAILABLE; +} + +HRESULT WINAPI DllGetActivationFactory(HSTRING classid, IActivationFactory **factory) +{ + const WCHAR *name = WindowsGetStringRawBuffer(classid, NULL); + + TRACE("classid %s, factory %p.\n", debugstr_hstring(classid), factory); + + *factory = NULL; + + if (!wcscmp(name, RuntimeClass_Windows_UI_ViewManagement_Core_CoreInputView)) + IActivationFactory_QueryInterface(core_input_view_factory, &IID_IActivationFactory, (void **)factory); + + return *factory ? S_OK : CLASS_E_CLASSNOTAVAILABLE; +} diff --git a/dlls/windows.ui.core.textinput/private.h b/dlls/windows.ui.core.textinput/private.h new file mode 100644 index 00000000000..dfc22192e31 --- /dev/null +++ b/dlls/windows.ui.core.textinput/private.h @@ -0,0 +1,31 @@ +/* WinRT Windows.UI.ViewManagement.Core.CoreInputView Implementation + * + * Copyright 2025 Zhiyi Zhang for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <stdarg.h> +#include <stddef.h> + +#define COBJMACROS +#include "windef.h" +#include "winbase.h" +#include "winstring.h" +#include "activation.h" +#include "wine/debug.h" + +#define WIDL_using_Windows_UI_ViewManagement_Core +#include "windows.ui.viewmanagement.core.h" diff --git a/dlls/windows.ui.core.textinput/tests/Makefile.in b/dlls/windows.ui.core.textinput/tests/Makefile.in new file mode 100644 index 00000000000..c48c26350c0 --- /dev/null +++ b/dlls/windows.ui.core.textinput/tests/Makefile.in @@ -0,0 +1,5 @@ +TESTDLL = windows.ui.core.textinput.dll +IMPORTS = combase + +SOURCES = \ + textinput.c diff --git a/dlls/windows.ui.core.textinput/tests/textinput.c b/dlls/windows.ui.core.textinput/tests/textinput.c new file mode 100644 index 00000000000..30c4e81fe48 --- /dev/null +++ b/dlls/windows.ui.core.textinput/tests/textinput.c @@ -0,0 +1,82 @@ +/* + * Copyright 2025 Zhiyi Zhang for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <stdarg.h> +#define COBJMACROS +#include "initguid.h" +#include "windef.h" +#include "winbase.h" +#include "winstring.h" +#include "roapi.h" +#include "wine/test.h" + +#define WIDL_using_Windows_UI_ViewManagement_Core +#include "windows.ui.viewmanagement.core.h" + +#define check_interface(obj, iid, supported) _check_interface(__LINE__, obj, iid, supported) +static void _check_interface(unsigned int line, void *obj, const IID *iid, BOOL supported) +{ + IUnknown *iface = obj, *unknown; + HRESULT hr; + + hr = IUnknown_QueryInterface(iface, iid, (void **)&unknown); + ok_(__FILE__, line)(hr == S_OK || (!supported && hr == E_NOINTERFACE), "Got unexpected hr %#lx.\n", hr); + if (SUCCEEDED(hr)) + IUnknown_Release(unknown); +} + +static void test_CoreInputViewStatics(void) +{ + IActivationFactory *factory; + HSTRING str = NULL; + HRESULT hr; + LONG ref; + + hr = WindowsCreateString(RuntimeClass_Windows_UI_ViewManagement_Core_CoreInputView, + wcslen(RuntimeClass_Windows_UI_ViewManagement_Core_CoreInputView), &str); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + hr = RoGetActivationFactory(str, &IID_IActivationFactory, (void **)&factory); + WindowsDeleteString(str); + ok(hr == S_OK || broken(hr == REGDB_E_CLASSNOTREG), "got hr %#lx.\n", hr); + if (hr == REGDB_E_CLASSNOTREG) + { + win_skip("%s runtimeclass not registered, skipping tests.\n", + wine_dbgstr_w(RuntimeClass_Windows_UI_ViewManagement_Core_CoreInputView)); + return; + } + + check_interface(factory, &IID_IUnknown, TRUE); + check_interface(factory, &IID_IInspectable, TRUE); + check_interface(factory, &IID_IActivationFactory, TRUE); + check_interface(factory, &IID_IAgileObject, FALSE); + + ref = IActivationFactory_Release(factory); + ok(ref == 1, "Got unexpected refcount %ld.\n", ref); +} + +START_TEST(textinput) +{ + HRESULT hr; + + hr = RoInitialize(RO_INIT_MULTITHREADED); + ok(hr == S_OK, "RoInitialize failed, hr %#lx\n", hr); + + test_CoreInputViewStatics(); + + RoUninitialize(); +} diff --git a/dlls/windows.ui.core.textinput/windows.ui.core.textinput.spec b/dlls/windows.ui.core.textinput/windows.ui.core.textinput.spec new file mode 100644 index 00000000000..31a5eafe950 --- /dev/null +++ b/dlls/windows.ui.core.textinput/windows.ui.core.textinput.spec @@ -0,0 +1,3 @@ +@ stdcall -private DllGetActivationFactory(ptr ptr) +@ stdcall -private DllCanUnloadNow() +@ stdcall -private DllGetClassObject(ptr ptr ptr)
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/windows.ui.core.textinput/main.c | 32 +++++++++++++++ dlls/windows.ui.core.textinput/private.h | 39 +++++++++++++++++++ .../tests/textinput.c | 1 + 3 files changed, 72 insertions(+)
diff --git a/dlls/windows.ui.core.textinput/main.c b/dlls/windows.ui.core.textinput/main.c index b40bdf3cdff..848e6ec421f 100644 --- a/dlls/windows.ui.core.textinput/main.c +++ b/dlls/windows.ui.core.textinput/main.c @@ -25,6 +25,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(coreinputview); struct core_input_view_statics { IActivationFactory IActivationFactory_iface; + ICoreInputViewStatics ICoreInputViewStatics_iface; LONG ref; };
@@ -48,6 +49,13 @@ static HRESULT WINAPI factory_QueryInterface(IActivationFactory *iface, REFIID i return S_OK; }
+ if (IsEqualGUID(iid, &IID_ICoreInputViewStatics)) + { + *out = &impl->ICoreInputViewStatics_iface; + ICoreInputViewStatics_AddRef(*out); + return S_OK; + } + FIXME("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); *out = NULL; return E_NOINTERFACE; @@ -106,9 +114,33 @@ static const struct IActivationFactoryVtbl factory_vtbl = factory_ActivateInstance, };
+DEFINE_IINSPECTABLE(core_input_view_statics, ICoreInputViewStatics, struct core_input_view_statics, + IActivationFactory_iface) + +static HRESULT WINAPI core_input_view_statics_GetForCurrentView(ICoreInputViewStatics *iface, + ICoreInputView **result) +{ + FIXME("iface %p, result %p stub!\n", iface, result); + return E_NOTIMPL; +} + +static const struct ICoreInputViewStaticsVtbl core_input_view_statics_vtbl = +{ + core_input_view_statics_QueryInterface, + core_input_view_statics_AddRef, + core_input_view_statics_Release, + /* IInspectable methods */ + core_input_view_statics_GetIids, + core_input_view_statics_GetRuntimeClassName, + core_input_view_statics_GetTrustLevel, + /* ICoreInputViewStatics methods */ + core_input_view_statics_GetForCurrentView, +}; + static struct core_input_view_statics core_input_view_statics = { {&factory_vtbl}, + {&core_input_view_statics_vtbl}, 1, };
diff --git a/dlls/windows.ui.core.textinput/private.h b/dlls/windows.ui.core.textinput/private.h index dfc22192e31..64093ca9512 100644 --- a/dlls/windows.ui.core.textinput/private.h +++ b/dlls/windows.ui.core.textinput/private.h @@ -29,3 +29,42 @@
#define WIDL_using_Windows_UI_ViewManagement_Core #include "windows.ui.viewmanagement.core.h" + +#define DEFINE_IINSPECTABLE_(pfx, iface_type, impl_type, impl_from, iface_mem, expr) \ + static inline impl_type *impl_from(iface_type *iface) \ + { \ + return CONTAINING_RECORD(iface, impl_type, iface_mem); \ + } \ + static HRESULT WINAPI pfx##_QueryInterface(iface_type *iface, REFIID iid, void **out) \ + { \ + impl_type *impl = impl_from(iface); \ + return IInspectable_QueryInterface((IInspectable *)(expr), iid, out); \ + } \ + static ULONG WINAPI pfx##_AddRef(iface_type *iface) \ + { \ + impl_type *impl = impl_from(iface); \ + return IInspectable_AddRef((IInspectable *)(expr)); \ + } \ + static ULONG WINAPI pfx##_Release(iface_type *iface) \ + { \ + impl_type *impl = impl_from(iface); \ + return IInspectable_Release((IInspectable *)(expr)); \ + } \ + static HRESULT WINAPI pfx##_GetIids(iface_type *iface, ULONG *iid_count, IID **iids) \ + { \ + impl_type *impl = impl_from(iface); \ + return IInspectable_GetIids((IInspectable *)(expr), iid_count, iids); \ + } \ + static HRESULT WINAPI pfx##_GetRuntimeClassName(iface_type *iface, HSTRING *class_name) \ + { \ + impl_type *impl = impl_from(iface); \ + return IInspectable_GetRuntimeClassName((IInspectable *)(expr), class_name); \ + } \ + static HRESULT WINAPI pfx##_GetTrustLevel(iface_type *iface, TrustLevel *trust_level) \ + { \ + impl_type *impl = impl_from(iface); \ + return IInspectable_GetTrustLevel((IInspectable *)(expr), trust_level); \ + } + +#define DEFINE_IINSPECTABLE(pfx, iface_type, impl_type, base_iface) \ + DEFINE_IINSPECTABLE_(pfx, iface_type, impl_type, impl_from_##iface_type, iface_type##_iface, &impl->base_iface) diff --git a/dlls/windows.ui.core.textinput/tests/textinput.c b/dlls/windows.ui.core.textinput/tests/textinput.c index 30c4e81fe48..6c12aee239e 100644 --- a/dlls/windows.ui.core.textinput/tests/textinput.c +++ b/dlls/windows.ui.core.textinput/tests/textinput.c @@ -63,6 +63,7 @@ static void test_CoreInputViewStatics(void) check_interface(factory, &IID_IUnknown, TRUE); check_interface(factory, &IID_IInspectable, TRUE); check_interface(factory, &IID_IActivationFactory, TRUE); + check_interface(factory, &IID_ICoreInputViewStatics, TRUE); check_interface(factory, &IID_IAgileObject, FALSE);
ref = IActivationFactory_Release(factory);
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/windows.ui.core.textinput/main.c | 305 +++++++++++++++++- dlls/windows.ui.core.textinput/private.h | 2 + .../tests/textinput.c | 46 +++ 3 files changed, 351 insertions(+), 2 deletions(-)
diff --git a/dlls/windows.ui.core.textinput/main.c b/dlls/windows.ui.core.textinput/main.c index 848e6ec421f..bf79d4760a1 100644 --- a/dlls/windows.ui.core.textinput/main.c +++ b/dlls/windows.ui.core.textinput/main.c @@ -22,6 +22,291 @@
WINE_DEFAULT_DEBUG_CHANNEL(coreinputview);
+struct core_input_view +{ + ICoreInputView ICoreInputView_iface; + ICoreInputView2 ICoreInputView2_iface; + ICoreInputView3 ICoreInputView3_iface; + ICoreInputView4 ICoreInputView4_iface; + LONG ref; +}; + +static inline struct core_input_view *impl_from_ICoreInputView(ICoreInputView *iface) +{ + return CONTAINING_RECORD(iface, struct core_input_view, ICoreInputView_iface); +} + +static HRESULT WINAPI core_input_view_QueryInterface(ICoreInputView *iface, REFIID iid, void **out) +{ + struct core_input_view *impl = impl_from_ICoreInputView(iface); + + TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); + + *out = NULL; + + if (IsEqualGUID(iid, &IID_IUnknown) + || IsEqualGUID(iid, &IID_IInspectable) + || IsEqualGUID(iid, &IID_IAgileObject) + || IsEqualGUID(iid, &IID_ICoreInputView)) + { + *out = &impl->ICoreInputView_iface; + } + else if (IsEqualGUID(iid, &IID_ICoreInputView2)) + { + *out = &impl->ICoreInputView2_iface; + } + else if (IsEqualGUID(iid, &IID_ICoreInputView3)) + { + *out = &impl->ICoreInputView3_iface; + } + else if (IsEqualGUID(iid, &IID_ICoreInputView4)) + { + *out = &impl->ICoreInputView4_iface; + } + + if (*out) + { + IUnknown_AddRef((IUnknown *)*out); + return S_OK; + } + + FIXME("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI core_input_view_AddRef(ICoreInputView *iface) +{ + struct core_input_view *impl = impl_from_ICoreInputView(iface); + ULONG ref = InterlockedIncrement(&impl->ref); + TRACE("iface %p, ref %lu.\n", iface, ref); + return ref; +} + +static ULONG WINAPI core_input_view_Release(ICoreInputView *iface) +{ + struct core_input_view *impl = impl_from_ICoreInputView(iface); + ULONG ref = InterlockedDecrement(&impl->ref); + + TRACE("iface %p, ref %lu.\n", iface, ref); + + if (!ref) + free(impl); + return ref; +} + +static HRESULT WINAPI core_input_view_GetIids(ICoreInputView *iface, ULONG *iid_count, IID **iids) +{ + FIXME("iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids); + return E_NOTIMPL; +} + +static HRESULT WINAPI core_input_view_GetRuntimeClassName(ICoreInputView *iface, HSTRING *class_name) +{ + FIXME("iface %p, class_name %p stub!\n", iface, class_name); + return E_NOTIMPL; +} + +static HRESULT WINAPI core_input_view_GetTrustLevel(ICoreInputView *iface, TrustLevel *trust_level) +{ + FIXME("iface %p, trust_level %p stub!\n", iface, trust_level); + return E_NOTIMPL; +} + +static HRESULT WINAPI core_input_view_add_OcclusionsChanged(ICoreInputView *iface, + ITypedEventHandler_CoreInputView_CoreInputViewOcclusionsChangedEventArgs *handler, + EventRegistrationToken *token) +{ + FIXME("iface %p, handler %p, token %p stub!\n", iface, handler, token); + return E_NOTIMPL; +} + +static HRESULT WINAPI core_input_view_remove_OcclusionsChanged(ICoreInputView *iface, + EventRegistrationToken token) +{ + FIXME("iface %p, token %I64x stub!\n", iface, token.value); + return E_NOTIMPL; +} + +static HRESULT WINAPI core_input_view_GetCoreInputViewOcclusions(ICoreInputView *iface, + IVectorView_CoreInputViewOcclusion **result) +{ + FIXME("iface %p, result %p stub!\n", iface, result); + return E_NOTIMPL; +} + +static HRESULT WINAPI core_input_view_TryShowPrimaryView(ICoreInputView *iface, boolean *result) +{ + FIXME("iface %p, boolean %p stub!\n", iface, result); + return E_NOTIMPL; +} + +static HRESULT WINAPI core_input_view_TryHidePrimaryView(ICoreInputView *iface, boolean *result) +{ + FIXME("iface %p, boolean %p stub!\n", iface, result); + return E_NOTIMPL; +} + +static const struct ICoreInputViewVtbl core_input_view_vtbl = +{ + core_input_view_QueryInterface, + core_input_view_AddRef, + core_input_view_Release, + /* IInspectable methods */ + core_input_view_GetIids, + core_input_view_GetRuntimeClassName, + core_input_view_GetTrustLevel, + /* ICoreInputView methods */ + core_input_view_add_OcclusionsChanged, + core_input_view_remove_OcclusionsChanged, + core_input_view_GetCoreInputViewOcclusions, + core_input_view_TryShowPrimaryView, + core_input_view_TryHidePrimaryView, +}; + +DEFINE_IINSPECTABLE(core_input_view2, ICoreInputView2, struct core_input_view, ICoreInputView_iface) + +static HRESULT WINAPI core_input_view2_add_XYFocusTransferringFromPrimaryView(ICoreInputView2 *iface, + ITypedEventHandler_CoreInputView_CoreInputViewTransferringXYFocusEventArgs *handler, + EventRegistrationToken *token) +{ + FIXME("iface %p, handler %p, token %p stub!\n", iface, handler, token); + return E_NOTIMPL; +} + +static HRESULT WINAPI core_input_view2_remove_XYFocusTransferringFromPrimaryView(ICoreInputView2 *iface, + EventRegistrationToken token) +{ + FIXME("iface %p, token %I64x stub!\n", iface, token.value); + return E_NOTIMPL; +} + +static HRESULT WINAPI core_input_view2_add_XYFocusTransferredToPrimaryView(ICoreInputView2 *iface, + ITypedEventHandler_CoreInputView_IInspectable *handler, + EventRegistrationToken *token) +{ + FIXME("iface %p, handler %p, token %p stub!\n", iface, handler, token); + return E_NOTIMPL; +} + +static HRESULT WINAPI core_input_view2_remove_XYFocusTransferredToPrimaryView(ICoreInputView2 *iface, + EventRegistrationToken token) +{ + FIXME("iface %p, token %I64x stub!\n", iface, token.value); + return E_NOTIMPL; +} + +static HRESULT WINAPI core_input_view2_TryTransferXYFocusToPrimaryView(ICoreInputView2 *iface, + Rect origin, + CoreInputViewXYFocusTransferDirection direction, + boolean *result) +{ + FIXME("iface %p, origin (%f,%f %fx%f), direction %d, result %p stub!\n", iface, origin.X, + origin.Y, origin.Width, origin.Height, direction, result); + return E_NOTIMPL; +} + +static const struct ICoreInputView2Vtbl core_input_view2_vtbl = +{ + core_input_view2_QueryInterface, + core_input_view2_AddRef, + core_input_view2_Release, + /* IInspectable methods */ + core_input_view2_GetIids, + core_input_view2_GetRuntimeClassName, + core_input_view2_GetTrustLevel, + /* ICoreInputView2 methods */ + core_input_view2_add_XYFocusTransferringFromPrimaryView, + core_input_view2_remove_XYFocusTransferringFromPrimaryView, + core_input_view2_add_XYFocusTransferredToPrimaryView, + core_input_view2_remove_XYFocusTransferredToPrimaryView, + core_input_view2_TryTransferXYFocusToPrimaryView, +}; + +DEFINE_IINSPECTABLE(core_input_view3, ICoreInputView3, struct core_input_view, ICoreInputView_iface) + +static HRESULT WINAPI core_input_view3_TryShow(ICoreInputView3 *iface, boolean *result) +{ + FIXME("iface %p, result %p stub!\n", iface, result); + return E_NOTIMPL; +} + +static HRESULT WINAPI core_input_view3_TryShowWithKind(ICoreInputView3 *iface, + CoreInputViewKind type, + boolean *result) +{ + FIXME("iface %p, type %d, result %p stub!\n", iface, type, result); + return E_NOTIMPL; +} + +static HRESULT WINAPI core_input_view3_TryHide(ICoreInputView3 *iface, boolean *result) +{ + FIXME("iface %p, result %p stub!\n", iface, result); + return E_NOTIMPL; +} + +static const struct ICoreInputView3Vtbl core_input_view3_vtbl = +{ + core_input_view3_QueryInterface, + core_input_view3_AddRef, + core_input_view3_Release, + /* IInspectable methods */ + core_input_view3_GetIids, + core_input_view3_GetRuntimeClassName, + core_input_view3_GetTrustLevel, + /* ICoreInputView3 methods */ + core_input_view3_TryShow, + core_input_view3_TryShowWithKind, + core_input_view3_TryHide, +}; + +DEFINE_IINSPECTABLE(core_input_view4, ICoreInputView4, struct core_input_view, ICoreInputView_iface) + +static HRESULT WINAPI core_input_view4_add_PrimaryViewShowing(ICoreInputView4 *iface, + ITypedEventHandler_CoreInputView_CoreInputViewShowingEventArgs *handler, + EventRegistrationToken *token) +{ + FIXME("iface %p, handler %p, token %p stub!\n", iface, handler, token); + return E_NOTIMPL; +} + +static HRESULT WINAPI core_input_view4_remove_PrimaryViewShowing(ICoreInputView4 *iface, + EventRegistrationToken token) +{ + FIXME("iface %p, token %I64x stub!\n", iface, token.value); + return E_NOTIMPL; +} + +static HRESULT WINAPI core_input_view4_add_PrimaryViewHiding(ICoreInputView4 *iface, + ITypedEventHandler_CoreInputView_CoreInputViewHidingEventArgs *handler, + EventRegistrationToken *token) +{ + FIXME("iface %p, handler %p, token %p stub!\n", iface, handler, token); + return E_NOTIMPL; +} + +static HRESULT WINAPI core_input_view4_remove_PrimaryViewHiding(ICoreInputView4 *iface, + EventRegistrationToken token) +{ + FIXME("iface %p, token %I64x stub!\n", iface, token.value); + return E_NOTIMPL; +} + +static const struct ICoreInputView4Vtbl core_input_view4_vtbl = +{ + core_input_view4_QueryInterface, + core_input_view4_AddRef, + core_input_view4_Release, + /* IInspectable methods */ + core_input_view4_GetIids, + core_input_view4_GetRuntimeClassName, + core_input_view4_GetTrustLevel, + /* ICoreInputView4 methods */ + core_input_view4_add_PrimaryViewShowing, + core_input_view4_remove_PrimaryViewShowing, + core_input_view4_add_PrimaryViewHiding, + core_input_view4_remove_PrimaryViewHiding, +}; + struct core_input_view_statics { IActivationFactory IActivationFactory_iface; @@ -120,8 +405,24 @@ DEFINE_IINSPECTABLE(core_input_view_statics, ICoreInputViewStatics, struct core_ static HRESULT WINAPI core_input_view_statics_GetForCurrentView(ICoreInputViewStatics *iface, ICoreInputView **result) { - FIXME("iface %p, result %p stub!\n", iface, result); - return E_NOTIMPL; + struct core_input_view *view; + + FIXME("iface %p, result %p semi-stub.\n", iface, result); + + if (!(view = calloc(1, sizeof(*view)))) + { + *result = NULL; + return E_OUTOFMEMORY; + } + + view->ICoreInputView_iface.lpVtbl = &core_input_view_vtbl; + view->ICoreInputView2_iface.lpVtbl = &core_input_view2_vtbl; + view->ICoreInputView3_iface.lpVtbl = &core_input_view3_vtbl; + view->ICoreInputView4_iface.lpVtbl = &core_input_view4_vtbl; + view->ref = 1; + + *result = &view->ICoreInputView_iface; + return S_OK; }
static const struct ICoreInputViewStaticsVtbl core_input_view_statics_vtbl = diff --git a/dlls/windows.ui.core.textinput/private.h b/dlls/windows.ui.core.textinput/private.h index 64093ca9512..13e476f7abb 100644 --- a/dlls/windows.ui.core.textinput/private.h +++ b/dlls/windows.ui.core.textinput/private.h @@ -27,6 +27,8 @@ #include "activation.h" #include "wine/debug.h"
+#define WIDL_using_Windows_Foundation +#define WIDL_using_Windows_Foundation_Collections #define WIDL_using_Windows_UI_ViewManagement_Core #include "windows.ui.viewmanagement.core.h"
diff --git a/dlls/windows.ui.core.textinput/tests/textinput.c b/dlls/windows.ui.core.textinput/tests/textinput.c index 6c12aee239e..43e1a2a477d 100644 --- a/dlls/windows.ui.core.textinput/tests/textinput.c +++ b/dlls/windows.ui.core.textinput/tests/textinput.c @@ -70,6 +70,51 @@ static void test_CoreInputViewStatics(void) ok(ref == 1, "Got unexpected refcount %ld.\n", ref); }
+static void test_CoreInputView(void) +{ + ICoreInputViewStatics *core_input_view_statics; + ICoreInputView *core_input_view; + IActivationFactory *factory; + HSTRING str = NULL; + HRESULT hr; + LONG ref; + + hr = WindowsCreateString(RuntimeClass_Windows_UI_ViewManagement_Core_CoreInputView, + wcslen(RuntimeClass_Windows_UI_ViewManagement_Core_CoreInputView), &str); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + hr = RoGetActivationFactory(str, &IID_IActivationFactory, (void **)&factory); + WindowsDeleteString(str); + ok(hr == S_OK || broken(hr == REGDB_E_CLASSNOTREG), "got hr %#lx.\n", hr); + if (hr == REGDB_E_CLASSNOTREG) + { + win_skip("%s runtimeclass not registered, skipping tests.\n", + wine_dbgstr_w(RuntimeClass_Windows_UI_ViewManagement_Core_CoreInputView)); + return; + } + + hr = IActivationFactory_QueryInterface(factory, &IID_ICoreInputViewStatics, + (void **)&core_input_view_statics); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + hr = ICoreInputViewStatics_GetForCurrentView(core_input_view_statics, &core_input_view); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + check_interface(core_input_view, &IID_IUnknown, TRUE); + check_interface(core_input_view, &IID_IInspectable, TRUE); + check_interface(core_input_view, &IID_IAgileObject, TRUE); + check_interface(core_input_view, &IID_ICoreInputView, TRUE); + check_interface(core_input_view, &IID_ICoreInputView2, TRUE); + check_interface(core_input_view, &IID_ICoreInputView3, TRUE); + check_interface(core_input_view, &IID_ICoreInputView4, TRUE); + + ICoreInputView_Release(core_input_view); + + ref = ICoreInputViewStatics_Release(core_input_view_statics); + ok(ref == 2, "Got unexpected refcount %ld.\n", ref); + ref = IActivationFactory_Release(factory); + ok(ref == 1, "Got unexpected refcount %ld.\n", ref); +} + START_TEST(textinput) { HRESULT hr; @@ -78,6 +123,7 @@ START_TEST(textinput) ok(hr == S_OK, "RoInitialize failed, hr %#lx\n", hr);
test_CoreInputViewStatics(); + test_CoreInputView();
RoUninitialize(); }
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/windows.ui.core.textinput/Makefile.in | 3 +- dlls/windows.ui.core.textinput/main.c | 19 +- dlls/windows.ui.core.textinput/private.h | 9 + .../tests/textinput.c | 6 + dlls/windows.ui.core.textinput/vector.c | 673 ++++++++++++++++++ include/windows.ui.viewmanagement.core.idl | 1 + 6 files changed, 709 insertions(+), 2 deletions(-) create mode 100644 dlls/windows.ui.core.textinput/vector.c
diff --git a/dlls/windows.ui.core.textinput/Makefile.in b/dlls/windows.ui.core.textinput/Makefile.in index 11890311a75..02cd358ce37 100644 --- a/dlls/windows.ui.core.textinput/Makefile.in +++ b/dlls/windows.ui.core.textinput/Makefile.in @@ -3,4 +3,5 @@ IMPORTS = combase
SOURCES = \ classes.idl \ - main.c + main.c \ + vector.c diff --git a/dlls/windows.ui.core.textinput/main.c b/dlls/windows.ui.core.textinput/main.c index bf79d4760a1..69336b0466d 100644 --- a/dlls/windows.ui.core.textinput/main.c +++ b/dlls/windows.ui.core.textinput/main.c @@ -130,8 +130,25 @@ static HRESULT WINAPI core_input_view_remove_OcclusionsChanged(ICoreInputView *i static HRESULT WINAPI core_input_view_GetCoreInputViewOcclusions(ICoreInputView *iface, IVectorView_CoreInputViewOcclusion **result) { + static const struct vector_iids iids = + { + .vector = &IID_IVector_CoreInputViewOcclusion, + .view = &IID_IVectorView_CoreInputViewOcclusion, + .iterable = &IID_IIterable_CoreInputViewOcclusion, + .iterator = &IID_IIterator_CoreInputViewOcclusion, + }; + IVector_CoreInputViewOcclusion *vector; + HRESULT hr; + FIXME("iface %p, result %p stub!\n", iface, result); - return E_NOTIMPL; + + if (SUCCEEDED(hr = vector_create(&iids, (void **)&vector))) + { + hr = IVector_CoreInputViewOcclusion_GetView(vector, result); + IVector_CoreInputViewOcclusion_Release(vector); + } + + return hr; }
static HRESULT WINAPI core_input_view_TryShowPrimaryView(ICoreInputView *iface, boolean *result) diff --git a/dlls/windows.ui.core.textinput/private.h b/dlls/windows.ui.core.textinput/private.h index 13e476f7abb..8b9e6419410 100644 --- a/dlls/windows.ui.core.textinput/private.h +++ b/dlls/windows.ui.core.textinput/private.h @@ -32,6 +32,15 @@ #define WIDL_using_Windows_UI_ViewManagement_Core #include "windows.ui.viewmanagement.core.h"
+struct vector_iids +{ + const GUID *vector; + const GUID *view; + const GUID *iterable; + const GUID *iterator; +}; +extern HRESULT vector_create(const struct vector_iids *iids, void **out); + #define DEFINE_IINSPECTABLE_(pfx, iface_type, impl_type, impl_from, iface_mem, expr) \ static inline impl_type *impl_from(iface_type *iface) \ { \ diff --git a/dlls/windows.ui.core.textinput/tests/textinput.c b/dlls/windows.ui.core.textinput/tests/textinput.c index 43e1a2a477d..b2e7cd4e8c9 100644 --- a/dlls/windows.ui.core.textinput/tests/textinput.c +++ b/dlls/windows.ui.core.textinput/tests/textinput.c @@ -26,6 +26,7 @@ #include "wine/test.h"
#define WIDL_using_Windows_UI_ViewManagement_Core +#define WIDL_using_Windows_Foundation_Collections #include "windows.ui.viewmanagement.core.h"
#define check_interface(obj, iid, supported) _check_interface(__LINE__, obj, iid, supported) @@ -73,6 +74,7 @@ static void test_CoreInputViewStatics(void) static void test_CoreInputView(void) { ICoreInputViewStatics *core_input_view_statics; + IVectorView_CoreInputViewOcclusion *occlusions; ICoreInputView *core_input_view; IActivationFactory *factory; HSTRING str = NULL; @@ -107,6 +109,10 @@ static void test_CoreInputView(void) check_interface(core_input_view, &IID_ICoreInputView3, TRUE); check_interface(core_input_view, &IID_ICoreInputView4, TRUE);
+ hr = ICoreInputView_GetCoreInputViewOcclusions(core_input_view, &occlusions); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + IVectorView_CoreInputViewOcclusion_Release(occlusions); + ICoreInputView_Release(core_input_view);
ref = ICoreInputViewStatics_Release(core_input_view_statics); diff --git a/dlls/windows.ui.core.textinput/vector.c b/dlls/windows.ui.core.textinput/vector.c new file mode 100644 index 00000000000..f55b67fe70d --- /dev/null +++ b/dlls/windows.ui.core.textinput/vector.c @@ -0,0 +1,673 @@ +/* + * Copyright 2021 Rémi Bernon for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "private.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(combase); + +struct iterator +{ + IIterator_IInspectable IIterator_IInspectable_iface; + const GUID *iid; + LONG ref; + + IVectorView_IInspectable *view; + UINT32 index; + UINT32 size; +}; + +static inline struct iterator *impl_from_IIterator_IInspectable( IIterator_IInspectable *iface ) +{ + return CONTAINING_RECORD( iface, struct iterator, IIterator_IInspectable_iface ); +} + +static HRESULT WINAPI iterator_QueryInterface( IIterator_IInspectable *iface, REFIID iid, void **out ) +{ + struct iterator *impl = impl_from_IIterator_IInspectable( iface ); + + TRACE( "iface %p, iid %s, out %p.\n", iface, debugstr_guid( iid ), out ); + + if (IsEqualGUID( iid, &IID_IUnknown ) || + IsEqualGUID( iid, &IID_IInspectable ) || + IsEqualGUID( iid, &IID_IAgileObject ) || + IsEqualGUID( iid, impl->iid )) + { + IInspectable_AddRef( (*out = &impl->IIterator_IInspectable_iface) ); + return S_OK; + } + + FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) ); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI iterator_AddRef( IIterator_IInspectable *iface ) +{ + struct iterator *impl = impl_from_IIterator_IInspectable( iface ); + ULONG ref = InterlockedIncrement( &impl->ref ); + TRACE( "iface %p increasing refcount to %lu.\n", iface, ref ); + return ref; +} + +static ULONG WINAPI iterator_Release( IIterator_IInspectable *iface ) +{ + struct iterator *impl = impl_from_IIterator_IInspectable( iface ); + ULONG ref = InterlockedDecrement( &impl->ref ); + + TRACE( "iface %p decreasing refcount to %lu.\n", iface, ref ); + + if (!ref) + { + IVectorView_IInspectable_Release( impl->view ); + free( impl ); + } + + return ref; +} + +static HRESULT WINAPI iterator_GetIids( IIterator_IInspectable *iface, ULONG *iid_count, IID **iids ) +{ + FIXME( "iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids ); + return E_NOTIMPL; +} + +static HRESULT WINAPI iterator_GetRuntimeClassName( IIterator_IInspectable *iface, HSTRING *class_name ) +{ + FIXME( "iface %p, class_name %p stub!\n", iface, class_name ); + return E_NOTIMPL; +} + +static HRESULT WINAPI iterator_GetTrustLevel( IIterator_IInspectable *iface, TrustLevel *trust_level ) +{ + FIXME( "iface %p, trust_level %p stub!\n", iface, trust_level ); + return E_NOTIMPL; +} + +static HRESULT WINAPI iterator_get_Current( IIterator_IInspectable *iface, IInspectable **value ) +{ + struct iterator *impl = impl_from_IIterator_IInspectable( iface ); + TRACE( "iface %p, value %p.\n", iface, value ); + return IVectorView_IInspectable_GetAt( impl->view, impl->index, value ); +} + +static HRESULT WINAPI iterator_get_HasCurrent( IIterator_IInspectable *iface, boolean *value ) +{ + struct iterator *impl = impl_from_IIterator_IInspectable( iface ); + + TRACE( "iface %p, value %p.\n", iface, value ); + + *value = impl->index < impl->size; + return S_OK; +} + +static HRESULT WINAPI iterator_MoveNext( IIterator_IInspectable *iface, boolean *value ) +{ + struct iterator *impl = impl_from_IIterator_IInspectable( iface ); + + TRACE( "iface %p, value %p.\n", iface, value ); + + if (impl->index < impl->size) impl->index++; + return IIterator_IInspectable_get_HasCurrent( iface, value ); +} + +static HRESULT WINAPI iterator_GetMany( IIterator_IInspectable *iface, UINT32 items_size, + IInspectable **items, UINT *count ) +{ + struct iterator *impl = impl_from_IIterator_IInspectable( iface ); + TRACE( "iface %p, items_size %u, items %p, count %p.\n", iface, items_size, items, count ); + return IVectorView_IInspectable_GetMany( impl->view, impl->index, items_size, items, count ); +} + +static const IIterator_IInspectableVtbl iterator_vtbl = +{ + iterator_QueryInterface, + iterator_AddRef, + iterator_Release, + /* IInspectable methods */ + iterator_GetIids, + iterator_GetRuntimeClassName, + iterator_GetTrustLevel, + /* IIterator<IInspectable*> methods */ + iterator_get_Current, + iterator_get_HasCurrent, + iterator_MoveNext, + iterator_GetMany, +}; + +struct vector_view +{ + IVectorView_IInspectable IVectorView_IInspectable_iface; + IIterable_IInspectable IIterable_IInspectable_iface; + struct vector_iids iids; + LONG ref; + + UINT32 size; + IInspectable *elements[1]; +}; + +static inline struct vector_view *impl_from_IVectorView_IInspectable( IVectorView_IInspectable *iface ) +{ + return CONTAINING_RECORD( iface, struct vector_view, IVectorView_IInspectable_iface ); +} + +static HRESULT WINAPI vector_view_QueryInterface( IVectorView_IInspectable *iface, REFIID iid, void **out ) +{ + struct vector_view *impl = impl_from_IVectorView_IInspectable( iface ); + + TRACE( "iface %p, iid %s, out %p.\n", iface, debugstr_guid( iid ), out ); + + if (IsEqualGUID( iid, &IID_IUnknown ) || + IsEqualGUID( iid, &IID_IInspectable ) || + IsEqualGUID( iid, &IID_IAgileObject ) || + IsEqualGUID( iid, impl->iids.view )) + { + IInspectable_AddRef( (*out = &impl->IVectorView_IInspectable_iface) ); + return S_OK; + } + + if (IsEqualGUID( iid, impl->iids.iterable )) + { + IInspectable_AddRef( (*out = &impl->IIterable_IInspectable_iface) ); + return S_OK; + } + + FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) ); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI vector_view_AddRef( IVectorView_IInspectable *iface ) +{ + struct vector_view *impl = impl_from_IVectorView_IInspectable( iface ); + ULONG ref = InterlockedIncrement( &impl->ref ); + TRACE( "iface %p increasing refcount to %lu.\n", iface, ref ); + return ref; +} + +static ULONG WINAPI vector_view_Release( IVectorView_IInspectable *iface ) +{ + struct vector_view *impl = impl_from_IVectorView_IInspectable( iface ); + ULONG i, ref = InterlockedDecrement( &impl->ref ); + + TRACE( "iface %p decreasing refcount to %lu.\n", iface, ref ); + + if (!ref) + { + for (i = 0; i < impl->size; ++i) IInspectable_Release( impl->elements[i] ); + free( impl ); + } + + return ref; +} + +static HRESULT WINAPI vector_view_GetIids( IVectorView_IInspectable *iface, ULONG *iid_count, IID **iids ) +{ + FIXME( "iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids ); + return E_NOTIMPL; +} + +static HRESULT WINAPI vector_view_GetRuntimeClassName( IVectorView_IInspectable *iface, HSTRING *class_name ) +{ + FIXME( "iface %p, class_name %p stub!\n", iface, class_name ); + return E_NOTIMPL; +} + +static HRESULT WINAPI vector_view_GetTrustLevel( IVectorView_IInspectable *iface, TrustLevel *trust_level ) +{ + FIXME( "iface %p, trust_level %p stub!\n", iface, trust_level ); + return E_NOTIMPL; +} + +static HRESULT WINAPI vector_view_GetAt( IVectorView_IInspectable *iface, UINT32 index, IInspectable **value ) +{ + struct vector_view *impl = impl_from_IVectorView_IInspectable( iface ); + + TRACE( "iface %p, index %u, value %p.\n", iface, index, value ); + + *value = NULL; + if (index >= impl->size) return E_BOUNDS; + + IInspectable_AddRef( (*value = impl->elements[index]) ); + return S_OK; +} + +static HRESULT WINAPI vector_view_get_Size( IVectorView_IInspectable *iface, UINT32 *value ) +{ + struct vector_view *impl = impl_from_IVectorView_IInspectable( iface ); + + TRACE( "iface %p, value %p.\n", iface, value ); + + *value = impl->size; + return S_OK; +} + +static HRESULT WINAPI vector_view_IndexOf( IVectorView_IInspectable *iface, IInspectable *element, + UINT32 *index, BOOLEAN *found ) +{ + struct vector_view *impl = impl_from_IVectorView_IInspectable( iface ); + ULONG i; + + TRACE( "iface %p, element %p, index %p, found %p.\n", iface, element, index, found ); + + for (i = 0; i < impl->size; ++i) if (impl->elements[i] == element) break; + if ((*found = (i < impl->size))) *index = i; + else *index = 0; + + return S_OK; +} + +static HRESULT WINAPI vector_view_GetMany( IVectorView_IInspectable *iface, UINT32 start_index, + UINT32 items_size, IInspectable **items, UINT *count ) +{ + struct vector_view *impl = impl_from_IVectorView_IInspectable( iface ); + UINT32 i; + + TRACE( "iface %p, start_index %u, items_size %u, items %p, count %p.\n", + iface, start_index, items_size, items, count ); + + if (start_index >= impl->size) return E_BOUNDS; + + for (i = start_index; i < impl->size; ++i) + { + if (i - start_index >= items_size) break; + IInspectable_AddRef( (items[i - start_index] = impl->elements[i]) ); + } + *count = i - start_index; + + return S_OK; +} + +static const struct IVectorView_IInspectableVtbl vector_view_vtbl = +{ + vector_view_QueryInterface, + vector_view_AddRef, + vector_view_Release, + /* IInspectable methods */ + vector_view_GetIids, + vector_view_GetRuntimeClassName, + vector_view_GetTrustLevel, + /* IVectorView<IInspectable*> methods */ + vector_view_GetAt, + vector_view_get_Size, + vector_view_IndexOf, + vector_view_GetMany, +}; + +DEFINE_IINSPECTABLE_( iterable_view, IIterable_IInspectable, struct vector_view, view_impl_from_IIterable_IInspectable, + IIterable_IInspectable_iface, &impl->IVectorView_IInspectable_iface ) + +static HRESULT WINAPI iterable_view_First( IIterable_IInspectable *iface, IIterator_IInspectable **value ) +{ + struct vector_view *impl = view_impl_from_IIterable_IInspectable( iface ); + struct iterator *iter; + + TRACE( "iface %p, value %p.\n", iface, value ); + + if (!(iter = calloc( 1, sizeof(struct iterator) ))) return E_OUTOFMEMORY; + iter->IIterator_IInspectable_iface.lpVtbl = &iterator_vtbl; + iter->iid = impl->iids.iterator; + iter->ref = 1; + + IVectorView_IInspectable_AddRef( (iter->view = &impl->IVectorView_IInspectable_iface) ); + iter->size = impl->size; + + *value = &iter->IIterator_IInspectable_iface; + return S_OK; +} + +static const struct IIterable_IInspectableVtbl iterable_view_vtbl = +{ + iterable_view_QueryInterface, + iterable_view_AddRef, + iterable_view_Release, + /* IInspectable methods */ + iterable_view_GetIids, + iterable_view_GetRuntimeClassName, + iterable_view_GetTrustLevel, + /* IIterable<T> methods */ + iterable_view_First, +}; + +struct vector +{ + IVector_IInspectable IVector_IInspectable_iface; + IIterable_IInspectable IIterable_IInspectable_iface; + struct vector_iids iids; + LONG ref; + + UINT32 size; + UINT32 capacity; + IInspectable **elements; +}; + +static inline struct vector *impl_from_IVector_IInspectable( IVector_IInspectable *iface ) +{ + return CONTAINING_RECORD( iface, struct vector, IVector_IInspectable_iface ); +} + +static HRESULT WINAPI vector_QueryInterface( IVector_IInspectable *iface, REFIID iid, void **out ) +{ + struct vector *impl = impl_from_IVector_IInspectable( iface ); + + TRACE( "iface %p, iid %s, out %p.\n", iface, debugstr_guid( iid ), out ); + + if (IsEqualGUID( iid, &IID_IUnknown ) || + IsEqualGUID( iid, &IID_IInspectable ) || + IsEqualGUID( iid, &IID_IAgileObject ) || + IsEqualGUID( iid, impl->iids.vector )) + { + IInspectable_AddRef( (*out = &impl->IVector_IInspectable_iface) ); + return S_OK; + } + + if (IsEqualGUID( iid, impl->iids.iterable )) + { + IInspectable_AddRef( (*out = &impl->IIterable_IInspectable_iface) ); + return S_OK; + } + + FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) ); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI vector_AddRef( IVector_IInspectable *iface ) +{ + struct vector *impl = impl_from_IVector_IInspectable( iface ); + ULONG ref = InterlockedIncrement( &impl->ref ); + TRACE( "iface %p increasing refcount to %lu.\n", iface, ref ); + return ref; +} + +static ULONG WINAPI vector_Release( IVector_IInspectable *iface ) +{ + struct vector *impl = impl_from_IVector_IInspectable( iface ); + ULONG ref = InterlockedDecrement( &impl->ref ); + + TRACE( "iface %p decreasing refcount to %lu.\n", iface, ref ); + + if (!ref) + { + IVector_IInspectable_Clear( iface ); + free( impl ); + } + + return ref; +} + +static HRESULT WINAPI vector_GetIids( IVector_IInspectable *iface, ULONG *iid_count, IID **iids ) +{ + FIXME( "iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids ); + return E_NOTIMPL; +} + +static HRESULT WINAPI vector_GetRuntimeClassName( IVector_IInspectable *iface, HSTRING *class_name ) +{ + FIXME( "iface %p, class_name %p stub!\n", iface, class_name ); + return E_NOTIMPL; +} + +static HRESULT WINAPI vector_GetTrustLevel( IVector_IInspectable *iface, TrustLevel *trust_level ) +{ + FIXME( "iface %p, trust_level %p stub!\n", iface, trust_level ); + return E_NOTIMPL; +} + +static HRESULT WINAPI vector_GetAt( IVector_IInspectable *iface, UINT32 index, IInspectable **value ) +{ + struct vector *impl = impl_from_IVector_IInspectable( iface ); + + TRACE( "iface %p, index %u, value %p.\n", iface, index, value ); + + *value = NULL; + if (index >= impl->size) return E_BOUNDS; + + IInspectable_AddRef( (*value = impl->elements[index]) ); + return S_OK; +} + +static HRESULT WINAPI vector_get_Size( IVector_IInspectable *iface, UINT32 *value ) +{ + struct vector *impl = impl_from_IVector_IInspectable( iface ); + TRACE( "iface %p, value %p.\n", iface, value ); + *value = impl->size; + return S_OK; +} + +static HRESULT WINAPI vector_GetView( IVector_IInspectable *iface, IVectorView_IInspectable **value ) +{ + struct vector *impl = impl_from_IVector_IInspectable( iface ); + struct vector_view *view; + ULONG i; + + TRACE( "iface %p, value %p.\n", iface, value ); + + if (!(view = calloc( 1, offsetof( struct vector_view, elements[impl->size] ) ))) return E_OUTOFMEMORY; + view->IVectorView_IInspectable_iface.lpVtbl = &vector_view_vtbl; + view->IIterable_IInspectable_iface.lpVtbl = &iterable_view_vtbl; + view->iids = impl->iids; + view->ref = 1; + + for (i = 0; i < impl->size; ++i) IInspectable_AddRef( (view->elements[view->size++] = impl->elements[i]) ); + + *value = &view->IVectorView_IInspectable_iface; + return S_OK; +} + +static HRESULT WINAPI vector_IndexOf( IVector_IInspectable *iface, IInspectable *element, UINT32 *index, BOOLEAN *found ) +{ + struct vector *impl = impl_from_IVector_IInspectable( iface ); + ULONG i; + + TRACE( "iface %p, element %p, index %p, found %p.\n", iface, element, index, found ); + + for (i = 0; i < impl->size; ++i) if (impl->elements[i] == element) break; + if ((*found = (i < impl->size))) *index = i; + else *index = 0; + + return S_OK; +} + +static HRESULT WINAPI vector_SetAt( IVector_IInspectable *iface, UINT32 index, IInspectable *value ) +{ + struct vector *impl = impl_from_IVector_IInspectable( iface ); + + TRACE( "iface %p, index %u, value %p.\n", iface, index, value ); + + if (index >= impl->size) return E_BOUNDS; + IInspectable_Release( impl->elements[index] ); + IInspectable_AddRef( (impl->elements[index] = value) ); + return S_OK; +} + +static HRESULT WINAPI vector_InsertAt( IVector_IInspectable *iface, UINT32 index, IInspectable *value ) +{ + struct vector *impl = impl_from_IVector_IInspectable( iface ); + IInspectable **tmp = impl->elements; + + TRACE( "iface %p, index %u, value %p.\n", iface, index, value ); + + if (impl->size == impl->capacity) + { + impl->capacity = max( 32, impl->capacity * 3 / 2 ); + if (!(impl->elements = realloc( impl->elements, impl->capacity * sizeof(*impl->elements) ))) + { + impl->elements = tmp; + return E_OUTOFMEMORY; + } + } + + memmove( impl->elements + index + 1, impl->elements + index, (impl->size++ - index) * sizeof(*impl->elements) ); + IInspectable_AddRef( (impl->elements[index] = value) ); + return S_OK; +} + +static HRESULT WINAPI vector_RemoveAt( IVector_IInspectable *iface, UINT32 index ) +{ + struct vector *impl = impl_from_IVector_IInspectable( iface ); + + TRACE( "iface %p, index %u.\n", iface, index ); + + if (index >= impl->size) return E_BOUNDS; + IInspectable_Release( impl->elements[index] ); + memmove( impl->elements + index, impl->elements + index + 1, (--impl->size - index) * sizeof(*impl->elements) ); + return S_OK; +} + +static HRESULT WINAPI vector_Append( IVector_IInspectable *iface, IInspectable *value ) +{ + struct vector *impl = impl_from_IVector_IInspectable( iface ); + + TRACE( "iface %p, value %p.\n", iface, value ); + + return IVector_IInspectable_InsertAt( iface, impl->size, value ); +} + +static HRESULT WINAPI vector_RemoveAtEnd( IVector_IInspectable *iface ) +{ + struct vector *impl = impl_from_IVector_IInspectable( iface ); + + TRACE( "iface %p.\n", iface ); + + if (impl->size) IInspectable_Release( impl->elements[--impl->size] ); + return S_OK; +} + +static HRESULT WINAPI vector_Clear( IVector_IInspectable *iface ) +{ + struct vector *impl = impl_from_IVector_IInspectable( iface ); + + TRACE( "iface %p.\n", iface ); + + while (impl->size) IVector_IInspectable_RemoveAtEnd( iface ); + free( impl->elements ); + impl->capacity = 0; + impl->elements = NULL; + + return S_OK; +} + +static HRESULT WINAPI vector_GetMany( IVector_IInspectable *iface, UINT32 start_index, + UINT32 items_size, IInspectable **items, UINT *count ) +{ + struct vector *impl = impl_from_IVector_IInspectable( iface ); + UINT32 i; + + TRACE( "iface %p, start_index %u, items_size %u, items %p, count %p.\n", + iface, start_index, items_size, items, count ); + + if (start_index >= impl->size) return E_BOUNDS; + + for (i = start_index; i < impl->size; ++i) + { + if (i - start_index >= items_size) break; + IInspectable_AddRef( (items[i - start_index] = impl->elements[i]) ); + } + *count = i - start_index; + + return S_OK; +} + +static HRESULT WINAPI vector_ReplaceAll( IVector_IInspectable *iface, UINT32 count, IInspectable **items ) +{ + HRESULT hr; + ULONG i; + + TRACE( "iface %p, count %u, items %p.\n", iface, count, items ); + + hr = IVector_IInspectable_Clear( iface ); + for (i = 0; i < count && SUCCEEDED(hr); ++i) hr = IVector_IInspectable_Append( iface, items[i] ); + return hr; +} + +static const struct IVector_IInspectableVtbl vector_vtbl = +{ + vector_QueryInterface, + vector_AddRef, + vector_Release, + /* IInspectable methods */ + vector_GetIids, + vector_GetRuntimeClassName, + vector_GetTrustLevel, + /* IVector<IInspectable*> methods */ + vector_GetAt, + vector_get_Size, + vector_GetView, + vector_IndexOf, + vector_SetAt, + vector_InsertAt, + vector_RemoveAt, + vector_Append, + vector_RemoveAtEnd, + vector_Clear, + vector_GetMany, + vector_ReplaceAll, +}; + +DEFINE_IINSPECTABLE( iterable, IIterable_IInspectable, struct vector, IVector_IInspectable_iface ) + +static HRESULT WINAPI iterable_First( IIterable_IInspectable *iface, IIterator_IInspectable **value ) +{ + struct vector *impl = impl_from_IIterable_IInspectable( iface ); + IIterable_IInspectable *iterable; + IVectorView_IInspectable *view; + HRESULT hr; + + TRACE( "iface %p, value %p.\n", iface, value ); + + if (FAILED(hr = IVector_IInspectable_GetView( &impl->IVector_IInspectable_iface, &view ))) return hr; + + hr = IVectorView_IInspectable_QueryInterface( view, impl->iids.iterable, (void **)&iterable ); + IVectorView_IInspectable_Release( view ); + if (FAILED(hr)) return hr; + + hr = IIterable_IInspectable_First( iterable, value ); + IIterable_IInspectable_Release( iterable ); + return hr; +} + +static const struct IIterable_IInspectableVtbl iterable_vtbl = +{ + iterable_QueryInterface, + iterable_AddRef, + iterable_Release, + /* IInspectable methods */ + iterable_GetIids, + iterable_GetRuntimeClassName, + iterable_GetTrustLevel, + /* IIterable<T> methods */ + iterable_First, +}; + +HRESULT vector_create( const struct vector_iids *iids, void **out ) +{ + struct vector *impl; + + TRACE( "iid %s, out %p.\n", debugstr_guid( iids->vector ), out ); + + if (!(impl = calloc( 1, sizeof(*impl) ))) return E_OUTOFMEMORY; + impl->IVector_IInspectable_iface.lpVtbl = &vector_vtbl; + impl->IIterable_IInspectable_iface.lpVtbl = &iterable_vtbl; + impl->iids = *iids; + impl->ref = 1; + + *out = &impl->IVector_IInspectable_iface; + TRACE( "created %p\n", *out ); + return S_OK; +} diff --git a/include/windows.ui.viewmanagement.core.idl b/include/windows.ui.viewmanagement.core.idl index c3d7f0de1bf..83e5c73c5c6 100644 --- a/include/windows.ui.viewmanagement.core.idl +++ b/include/windows.ui.viewmanagement.core.idl @@ -56,6 +56,7 @@ namespace Windows.UI.ViewManagement.Core { interface Windows.Foundation.Collections.IIterable<Windows.UI.ViewManagement.Core.CoreInputViewOcclusion *>; interface Windows.Foundation.Collections.IIterator<Windows.UI.ViewManagement.Core.CoreInputViewOcclusion *>; + interface Windows.Foundation.Collections.IVector<Windows.UI.ViewManagement.Core.CoreInputViewOcclusion *>; interface Windows.Foundation.Collections.IVectorView<Windows.UI.ViewManagement.Core.CoreInputViewOcclusion *>; interface Windows.Foundation.TypedEventHandler<Windows.UI.ViewManagement.Core.CoreInputView *, IInspectable *>; interface Windows.Foundation.TypedEventHandler<Windows.UI.ViewManagement.Core.CoreInputView *, Windows.UI.ViewManagement.Core.CoreInputViewHidingEventArgs *>;
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/windows.ui.core.textinput/main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/dlls/windows.ui.core.textinput/main.c b/dlls/windows.ui.core.textinput/main.c index 69336b0466d..6ca81dc0e3c 100644 --- a/dlls/windows.ui.core.textinput/main.c +++ b/dlls/windows.ui.core.textinput/main.c @@ -117,7 +117,8 @@ static HRESULT WINAPI core_input_view_add_OcclusionsChanged(ICoreInputView *ifac EventRegistrationToken *token) { FIXME("iface %p, handler %p, token %p stub!\n", iface, handler, token); - return E_NOTIMPL; + token->value = 0xdeadbeef; + return S_OK; }
static HRESULT WINAPI core_input_view_remove_OcclusionsChanged(ICoreInputView *iface,
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/windows.ui.core.textinput/Makefile.in | 3 +- dlls/windows.ui.core.textinput/main.c | 21 ++- .../tests/textinput.c | 2 + dlls/windows.ui.core.textinput/weakref.c | 175 ++++++++++++++++++ dlls/windows.ui.core.textinput/weakref.h | 38 ++++ 5 files changed, 234 insertions(+), 5 deletions(-) create mode 100644 dlls/windows.ui.core.textinput/weakref.c create mode 100644 dlls/windows.ui.core.textinput/weakref.h
diff --git a/dlls/windows.ui.core.textinput/Makefile.in b/dlls/windows.ui.core.textinput/Makefile.in index 02cd358ce37..38d07a5a5c0 100644 --- a/dlls/windows.ui.core.textinput/Makefile.in +++ b/dlls/windows.ui.core.textinput/Makefile.in @@ -4,4 +4,5 @@ IMPORTS = combase SOURCES = \ classes.idl \ main.c \ - vector.c + vector.c \ + weakref.c diff --git a/dlls/windows.ui.core.textinput/main.c b/dlls/windows.ui.core.textinput/main.c index 6ca81dc0e3c..25110e09be9 100644 --- a/dlls/windows.ui.core.textinput/main.c +++ b/dlls/windows.ui.core.textinput/main.c @@ -19,6 +19,7 @@
#include "initguid.h" #include "private.h" +#include "weakref.h"
WINE_DEFAULT_DEBUG_CHANNEL(coreinputview);
@@ -28,7 +29,7 @@ struct core_input_view ICoreInputView2 ICoreInputView2_iface; ICoreInputView3 ICoreInputView3_iface; ICoreInputView4 ICoreInputView4_iface; - LONG ref; + struct weak_reference_source weak_reference_source; };
static inline struct core_input_view *impl_from_ICoreInputView(ICoreInputView *iface) @@ -63,6 +64,10 @@ static HRESULT WINAPI core_input_view_QueryInterface(ICoreInputView *iface, REFI { *out = &impl->ICoreInputView4_iface; } + else if (IsEqualGUID(iid, &IID_IWeakReferenceSource)) + { + *out = &impl->weak_reference_source.IWeakReferenceSource_iface; + }
if (*out) { @@ -77,7 +82,7 @@ static HRESULT WINAPI core_input_view_QueryInterface(ICoreInputView *iface, REFI static ULONG WINAPI core_input_view_AddRef(ICoreInputView *iface) { struct core_input_view *impl = impl_from_ICoreInputView(iface); - ULONG ref = InterlockedIncrement(&impl->ref); + ULONG ref = weak_reference_strong_add_ref(&impl->weak_reference_source); TRACE("iface %p, ref %lu.\n", iface, ref); return ref; } @@ -85,7 +90,7 @@ static ULONG WINAPI core_input_view_AddRef(ICoreInputView *iface) static ULONG WINAPI core_input_view_Release(ICoreInputView *iface) { struct core_input_view *impl = impl_from_ICoreInputView(iface); - ULONG ref = InterlockedDecrement(&impl->ref); + ULONG ref = weak_reference_strong_release(&impl->weak_reference_source);
TRACE("iface %p, ref %lu.\n", iface, ref);
@@ -424,6 +429,7 @@ static HRESULT WINAPI core_input_view_statics_GetForCurrentView(ICoreInputViewSt ICoreInputView **result) { struct core_input_view *view; + HRESULT hr;
FIXME("iface %p, result %p semi-stub.\n", iface, result);
@@ -437,7 +443,14 @@ static HRESULT WINAPI core_input_view_statics_GetForCurrentView(ICoreInputViewSt view->ICoreInputView2_iface.lpVtbl = &core_input_view2_vtbl; view->ICoreInputView3_iface.lpVtbl = &core_input_view3_vtbl; view->ICoreInputView4_iface.lpVtbl = &core_input_view4_vtbl; - view->ref = 1; + + if (FAILED(hr = weak_reference_source_init(&view->weak_reference_source, + (IUnknown *)&view->ICoreInputView_iface))) + { + *result = NULL; + free(view); + return hr; + }
*result = &view->ICoreInputView_iface; return S_OK; diff --git a/dlls/windows.ui.core.textinput/tests/textinput.c b/dlls/windows.ui.core.textinput/tests/textinput.c index b2e7cd4e8c9..1c83d56f070 100644 --- a/dlls/windows.ui.core.textinput/tests/textinput.c +++ b/dlls/windows.ui.core.textinput/tests/textinput.c @@ -23,6 +23,7 @@ #include "winbase.h" #include "winstring.h" #include "roapi.h" +#include "weakreference.h" #include "wine/test.h"
#define WIDL_using_Windows_UI_ViewManagement_Core @@ -104,6 +105,7 @@ static void test_CoreInputView(void) check_interface(core_input_view, &IID_IUnknown, TRUE); check_interface(core_input_view, &IID_IInspectable, TRUE); check_interface(core_input_view, &IID_IAgileObject, TRUE); + check_interface(core_input_view, &IID_IWeakReferenceSource, TRUE); check_interface(core_input_view, &IID_ICoreInputView, TRUE); check_interface(core_input_view, &IID_ICoreInputView2, TRUE); check_interface(core_input_view, &IID_ICoreInputView3, TRUE); diff --git a/dlls/windows.ui.core.textinput/weakref.c b/dlls/windows.ui.core.textinput/weakref.c new file mode 100644 index 00000000000..6a10390dd4c --- /dev/null +++ b/dlls/windows.ui.core.textinput/weakref.c @@ -0,0 +1,175 @@ +/* WinRT weak reference helpers + * + * Copyright 2025 Zhiyi Zhang for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS +#include "weakref.h" + +/* The control block is contained in struct weak_reference so that we don't have to allocate a + * separate struct for it */ +struct weak_reference +{ + IWeakReference IWeakReference_iface; + IUnknown *object; + /* control block */ + LONG ref_strong; + LONG ref_weak; +}; + +static inline struct weak_reference *impl_from_IWeakReference( IWeakReference *iface ) +{ + return CONTAINING_RECORD(iface, struct weak_reference, IWeakReference_iface); +} + +static HRESULT WINAPI weak_reference_QueryInterface( IWeakReference *iface, REFIID iid, void **out ) +{ + struct weak_reference *impl = impl_from_IWeakReference( iface ); + + if (IsEqualGUID( iid, &IID_IUnknown ) || IsEqualGUID( iid, &IID_IWeakReference )) + { + *out = &impl->IWeakReference_iface; + IWeakReference_AddRef( *out ); + return S_OK; + } + + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI weak_reference_AddRef( IWeakReference *iface ) +{ + struct weak_reference *impl = impl_from_IWeakReference( iface ); + return InterlockedIncrement( &impl->ref_weak ); +} + +static ULONG WINAPI weak_reference_Release( IWeakReference *iface ) +{ + struct weak_reference *impl = impl_from_IWeakReference( iface ); + ULONG ref = InterlockedDecrement( &impl->ref_weak ); + + if (!ref) + free( impl ); + return ref; +} + +static HRESULT WINAPI weak_reference_Resolve( IWeakReference *iface, REFIID iid, IInspectable **out ) +{ + struct weak_reference *impl = impl_from_IWeakReference( iface ); + HRESULT hr; + LONG ref; + + *out = NULL; + do + { + if (!(ref = ReadNoFence( &impl->ref_strong ))) + return S_OK; + } while (ref != InterlockedCompareExchange( &impl->ref_strong, ref + 1, ref )); + + hr = IUnknown_QueryInterface( impl->object, iid, (void **)out ); + IUnknown_Release( impl->object ); + return hr; +} + +static const struct IWeakReferenceVtbl weak_reference_vtbl = +{ + weak_reference_QueryInterface, + weak_reference_AddRef, + weak_reference_Release, + weak_reference_Resolve, +}; + +static inline struct weak_reference_source *impl_from_IWeakReferenceSource( IWeakReferenceSource *iface ) +{ + return CONTAINING_RECORD(iface, struct weak_reference_source, IWeakReferenceSource_iface); +} + +static HRESULT WINAPI weak_reference_source_QueryInterface( IWeakReferenceSource *iface, REFIID iid, void **out ) +{ + struct weak_reference_source *weak_reference_source = impl_from_IWeakReferenceSource( iface ); + struct weak_reference *weak_reference = impl_from_IWeakReference( weak_reference_source->weak_reference ); + return IUnknown_QueryInterface( weak_reference->object, iid, out ); +} + +static ULONG WINAPI weak_reference_source_AddRef( IWeakReferenceSource *iface ) +{ + struct weak_reference_source *weak_reference_source = impl_from_IWeakReferenceSource( iface ); + struct weak_reference *weak_reference = impl_from_IWeakReference( weak_reference_source->weak_reference ); + return IUnknown_AddRef( weak_reference->object ); +} + +static ULONG WINAPI weak_reference_source_Release( IWeakReferenceSource *iface ) +{ + struct weak_reference_source *weak_reference_source = impl_from_IWeakReferenceSource( iface ); + struct weak_reference *weak_reference = impl_from_IWeakReference( weak_reference_source->weak_reference ); + return IUnknown_Release( weak_reference->object ); +} + +static HRESULT WINAPI weak_reference_source_GetWeakReference( IWeakReferenceSource *iface, + IWeakReference **weak_reference ) +{ + struct weak_reference_source *impl = impl_from_IWeakReferenceSource( iface ); + + *weak_reference = impl->weak_reference; + IWeakReference_AddRef( *weak_reference ); + return S_OK; +} + +static const struct IWeakReferenceSourceVtbl weak_reference_source_vtbl = +{ + weak_reference_source_QueryInterface, + weak_reference_source_AddRef, + weak_reference_source_Release, + weak_reference_source_GetWeakReference, +}; + +static HRESULT weak_reference_create( IUnknown *object, IWeakReference **out ) +{ + struct weak_reference *weak_reference; + + if (!(weak_reference = calloc( 1, sizeof(*weak_reference) ))) + return E_OUTOFMEMORY; + + weak_reference->IWeakReference_iface.lpVtbl = &weak_reference_vtbl; + weak_reference->ref_strong = 1; + weak_reference->ref_weak = 1; + weak_reference->object = object; + *out = &weak_reference->IWeakReference_iface; + return S_OK; +} + +HRESULT weak_reference_source_init( struct weak_reference_source *source, IUnknown *object ) +{ + source->IWeakReferenceSource_iface.lpVtbl = &weak_reference_source_vtbl; + return weak_reference_create( object, &source->weak_reference ); +} + +ULONG weak_reference_strong_add_ref( struct weak_reference_source *source ) +{ + struct weak_reference *impl = impl_from_IWeakReference( source->weak_reference ); + return InterlockedIncrement( &impl->ref_strong ); +} + +ULONG weak_reference_strong_release( struct weak_reference_source *source ) +{ + struct weak_reference *impl = impl_from_IWeakReference( source->weak_reference ); + ULONG ref = InterlockedDecrement( &impl->ref_strong ); + + if (!ref) + IWeakReference_Release( source->weak_reference ); + return ref; +} diff --git a/dlls/windows.ui.core.textinput/weakref.h b/dlls/windows.ui.core.textinput/weakref.h new file mode 100644 index 00000000000..7d4bc22b087 --- /dev/null +++ b/dlls/windows.ui.core.textinput/weakref.h @@ -0,0 +1,38 @@ +/* WinRT weak reference helpers + * + * Copyright 2025 Zhiyi Zhang for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __WINE_WEAKREF_H +#define __WINE_WEAKREF_H + +#include "weakreference.h" + +struct weak_reference_source +{ + IWeakReferenceSource IWeakReferenceSource_iface; + IWeakReference *weak_reference; +}; + +/* Initialize a IWeakReferenceSource with the object to manage */ +HRESULT weak_reference_source_init( struct weak_reference_source *source, IUnknown *object ); +/* Add a strong reference to the managed object */ +ULONG weak_reference_strong_add_ref( struct weak_reference_source *source ); +/* Release a strong reference to the managed object */ +ULONG weak_reference_strong_release( struct weak_reference_source *source ); + +#endif /* __WINE_WEAKREF_H */