For React Native.
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/windows.ui/tests/uisettings.c | 7 +++++ dlls/windows.ui/uisettings.c | 46 ++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+)
diff --git a/dlls/windows.ui/tests/uisettings.c b/dlls/windows.ui/tests/uisettings.c index 5fc60f7cedc..69b307d8877 100644 --- a/dlls/windows.ui/tests/uisettings.c +++ b/dlls/windows.ui/tests/uisettings.c @@ -22,6 +22,7 @@ #include "windef.h" #include "winbase.h" #include "winstring.h" +#include "weakreference.h"
#include "roapi.h"
@@ -213,7 +214,13 @@ static void test_UISettings(void) goto skip_uisettings3; }
+ check_interface( inspectable, &IID_IInspectable, TRUE ); check_interface( inspectable, &IID_IAgileObject, TRUE ); + check_interface( inspectable, &IID_IUISettings, TRUE ); + check_interface( inspectable, &IID_IUISettings2, TRUE ); + check_interface( inspectable, &IID_IUISettings3, TRUE ); + check_interface( inspectable, &IID_IWeakReferenceSource, TRUE ); + check_interface( inspectable, &IID_IWeakReference, FALSE );
test_AccentColor( uisettings3 );
diff --git a/dlls/windows.ui/uisettings.c b/dlls/windows.ui/uisettings.c index 2b889e16cb7..7497f3fe81d 100644 --- a/dlls/windows.ui/uisettings.c +++ b/dlls/windows.ui/uisettings.c @@ -18,6 +18,8 @@ */
#include "private.h" +#include "initguid.h" +#include "weakreference.h"
#include "wine/debug.h"
@@ -32,6 +34,7 @@ struct uisettings IUISettings3 IUISettings3_iface; IUISettings4 IUISettings4_iface; IUISettings5 IUISettings5_iface; + IWeakReferenceSource IWeakReferenceSource_iface; LONG ref; };
@@ -71,6 +74,10 @@ static HRESULT WINAPI uisettings_QueryInterface( IUISettings *iface, REFIID iid, { *out = &impl->IUISettings5_iface; } + else if (IsEqualGUID( iid, &IID_IWeakReferenceSource )) + { + *out = &impl->IWeakReferenceSource_iface; + }
if (!*out) { @@ -469,6 +476,44 @@ static const struct IUISettings5Vtbl uisettings5_vtbl = uisettings5_remove_AutoHideScrollBarsChanged, };
+static inline struct uisettings *impl_from_IWeakReferenceSource( IWeakReferenceSource *iface ) +{ + return CONTAINING_RECORD( iface, struct uisettings, IWeakReferenceSource_iface ); +} + +static HRESULT WINAPI weak_reference_source_QueryInterface( IWeakReferenceSource *iface, REFIID iid, void **out ) +{ + struct uisettings *impl = impl_from_IWeakReferenceSource( iface ); + return uisettings_QueryInterface( &impl->IUISettings_iface, iid, out ); +} + +static ULONG WINAPI weak_reference_source_AddRef( IWeakReferenceSource *iface ) +{ + struct uisettings *impl = impl_from_IWeakReferenceSource( iface ); + return uisettings_AddRef( &impl->IUISettings_iface ); +} + +static ULONG WINAPI weak_reference_source_Release( IWeakReferenceSource *iface ) +{ + struct uisettings *impl = impl_from_IWeakReferenceSource( iface ); + return uisettings_Release( &impl->IUISettings_iface ); +} + +static HRESULT WINAPI weak_reference_source_GetWeakReference( IWeakReferenceSource *iface, IWeakReference **ref ) +{ + FIXME( "iface %p, ref %p stub.\n", iface, ref ); + return E_NOTIMPL; +} + +static const struct IWeakReferenceSourceVtbl weak_reference_source_vtbl = +{ + weak_reference_source_QueryInterface, + weak_reference_source_AddRef, + weak_reference_source_Release, + /* IWeakReferenceSource methods */ + weak_reference_source_GetWeakReference, +}; + struct uisettings_statics { IActivationFactory IActivationFactory_iface; @@ -551,6 +596,7 @@ static HRESULT WINAPI factory_ActivateInstance( IActivationFactory *iface, IInsp impl->IUISettings3_iface.lpVtbl = &uisettings3_vtbl; impl->IUISettings4_iface.lpVtbl = &uisettings4_vtbl; impl->IUISettings5_iface.lpVtbl = &uisettings5_vtbl; + impl->IWeakReferenceSource_iface.lpVtbl = &weak_reference_source_vtbl; impl->ref = 1;
*instance = (IInspectable *)&impl->IUISettings3_iface;
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/windows.ui/tests/uisettings.c | 65 +++++++++++++++++++++ dlls/windows.ui/uisettings.c | 94 ++++++++++++++++++++++++++++-- 2 files changed, 153 insertions(+), 6 deletions(-)
diff --git a/dlls/windows.ui/tests/uisettings.c b/dlls/windows.ui/tests/uisettings.c index 69b307d8877..898b43e3167 100644 --- a/dlls/windows.ui/tests/uisettings.c +++ b/dlls/windows.ui/tests/uisettings.c @@ -270,6 +270,70 @@ skip_uisettings3: ok( ref == 1, "got ref %ld.\n", ref ); }
+static void test_UISettings_weak_ref(void) +{ + static const WCHAR *uisettings_name = L"Windows.UI.ViewManagement.UISettings"; + IWeakReferenceSource *weak_reference_source; + IInspectable *inspectable, *inspectable2; + IWeakReference *weak_reference; + IActivationFactory *factory; + IUISettings *uisettings; + IUnknown *unknown; + HSTRING str; + HRESULT hr; + LONG ref; + + hr = WindowsCreateString( uisettings_name, wcslen( uisettings_name ), &str ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + + hr = RoGetActivationFactory( str, &IID_IActivationFactory, (void **)&factory ); + 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( uisettings_name ) ); + return; + } + + hr = RoActivateInstance( str, &inspectable ); + ok( hr == S_OK, "Got unexpected hr %#lx.\n", hr ); + WindowsDeleteString( str ); + + hr = IInspectable_QueryInterface( inspectable, &IID_IWeakReferenceSource, (void **)&weak_reference_source ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + hr = IWeakReferenceSource_GetWeakReference( weak_reference_source, &weak_reference ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + IWeakReferenceSource_Release( weak_reference_source ); + + check_interface( weak_reference, &IID_IUnknown, TRUE ); + check_interface( weak_reference, &IID_IWeakReference, TRUE ); + check_interface( weak_reference, &IID_IInspectable, FALSE ); + check_interface( weak_reference, &IID_IAgileObject, FALSE ); + check_interface( weak_reference, &IID_IUISettings, FALSE ); + + hr = IWeakReference_Resolve( weak_reference, &IID_IUnknown, (IInspectable **)&unknown ); + ok( hr == S_OK && unknown, "got hr %#lx.\n", hr ); + hr = IWeakReference_Resolve( weak_reference, &IID_IInspectable, &inspectable2 ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + ok( (void *)inspectable2 == (void *)unknown, "Interfaces are not the same.\n" ); + IInspectable_Release( inspectable2 ); + hr = IWeakReference_Resolve( weak_reference, &IID_IUISettings, (IInspectable **)&uisettings ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + ok( (void *)uisettings == (void *)unknown, "Interfaces are not the same.\n" ); + IUISettings_Release( uisettings ); + IUnknown_Release( unknown ); + + /* Free inspectable, weak reference should fail to resolve now */ + IInspectable_Release( inspectable ); + + inspectable2 = (void *)0xdeadbeef; + hr = IWeakReference_Resolve( weak_reference, &IID_IInspectable, &inspectable2 ); + ok( hr == S_OK && !inspectable2, "got hr %#lx.\n", hr ); + + IWeakReference_Release( weak_reference ); + ref = IActivationFactory_Release( factory ); + ok( ref == 1, "got ref %ld.\n", ref ); +} + START_TEST(uisettings) { HRESULT hr; @@ -278,6 +342,7 @@ START_TEST(uisettings) ok( hr == S_OK, "RoInitialize failed, hr %#lx\n", hr );
test_UISettings(); + test_UISettings_weak_ref();
RoUninitialize(); } diff --git a/dlls/windows.ui/uisettings.c b/dlls/windows.ui/uisettings.c index 7497f3fe81d..a2b59c46cdf 100644 --- a/dlls/windows.ui/uisettings.c +++ b/dlls/windows.ui/uisettings.c @@ -35,7 +35,9 @@ struct uisettings IUISettings4 IUISettings4_iface; IUISettings5 IUISettings5_iface; IWeakReferenceSource IWeakReferenceSource_iface; - LONG ref; + IWeakReference IWeakReference_iface; + LONG ref_strong; + LONG ref_weak; };
static inline struct uisettings *impl_from_IUISettings( IUISettings *iface ) @@ -92,18 +94,20 @@ static HRESULT WINAPI uisettings_QueryInterface( IUISettings *iface, REFIID iid, static ULONG WINAPI uisettings_AddRef( IUISettings *iface ) { struct uisettings *impl = impl_from_IUISettings( iface ); - ULONG ref = InterlockedIncrement( &impl->ref ); + ULONG ref = InterlockedIncrement( &impl->ref_strong ); TRACE( "iface %p, ref %lu.\n", iface, ref ); + IWeakReference_AddRef( &impl->IWeakReference_iface ); return ref; }
static ULONG WINAPI uisettings_Release( IUISettings *iface ) { struct uisettings *impl = impl_from_IUISettings( iface ); - ULONG ref = InterlockedDecrement( &impl->ref ); + ULONG ref = InterlockedDecrement( &impl->ref_strong );
TRACE( "iface %p, ref %lu.\n", iface, ref );
+ IWeakReference_Release( &impl->IWeakReference_iface ); if (!ref) free( impl ); return ref; } @@ -476,6 +480,77 @@ static const struct IUISettings5Vtbl uisettings5_vtbl = uisettings5_remove_AutoHideScrollBarsChanged, };
+static inline struct uisettings *impl_from_IWeakReference( IWeakReference *iface ) +{ + return CONTAINING_RECORD( iface, struct uisettings, IWeakReference_iface ); +} + +static HRESULT WINAPI weak_reference_QueryInterface( IWeakReference *iface, REFIID iid, void **out ) +{ + struct uisettings *impl = impl_from_IWeakReference( iface ); + + TRACE( "iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out ); + + if (IsEqualGUID( iid, &IID_IUnknown ) || + IsEqualGUID( iid, &IID_IWeakReference )) + { + *out = &impl->IWeakReference_iface; + IInspectable_AddRef( *out ); + return S_OK; + } + + FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid) ); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI weak_reference_AddRef( IWeakReference *iface ) +{ + struct uisettings *impl = impl_from_IWeakReference( iface ); + ULONG ref = InterlockedIncrement( &impl->ref_weak ); + TRACE("iface %p increasing refcount to %lu.\n", iface, ref); + return ref; +} + +static ULONG WINAPI weak_reference_Release( IWeakReference *iface ) +{ + struct uisettings *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 uisettings *impl = impl_from_IWeakReference( iface ); + HRESULT hr; + LONG ref; + + TRACE( "iface %p, iid %s, out %p stub.\n", iface, debugstr_guid(iid), out ); + + *out = NULL; + + do + { + if (!(ref = ReadNoFence( &impl->ref_strong ))) + return S_OK; + } while (ref != InterlockedCompareExchange( &impl->ref_strong, ref + 1, ref )); + + hr = IUISettings_QueryInterface( &impl->IUISettings_iface, iid, (void **)out ); + InterlockedDecrement( &impl->ref_strong ); + return hr; +} + +static const struct IWeakReferenceVtbl weak_reference_vtbl = +{ + weak_reference_QueryInterface, + weak_reference_AddRef, + weak_reference_Release, + /* IWeakReference methods */ + weak_reference_Resolve, +}; + static inline struct uisettings *impl_from_IWeakReferenceSource( IWeakReferenceSource *iface ) { return CONTAINING_RECORD( iface, struct uisettings, IWeakReferenceSource_iface ); @@ -501,8 +576,13 @@ static ULONG WINAPI weak_reference_source_Release( IWeakReferenceSource *iface )
static HRESULT WINAPI weak_reference_source_GetWeakReference( IWeakReferenceSource *iface, IWeakReference **ref ) { - FIXME( "iface %p, ref %p stub.\n", iface, ref ); - return E_NOTIMPL; + struct uisettings *impl = impl_from_IWeakReferenceSource(iface); + + TRACE("iface %p, ref %p stub.\n", iface, ref); + + *ref = &impl->IWeakReference_iface; + IWeakReference_AddRef( *ref ); + return S_OK; }
static const struct IWeakReferenceSourceVtbl weak_reference_source_vtbl = @@ -597,7 +677,9 @@ static HRESULT WINAPI factory_ActivateInstance( IActivationFactory *iface, IInsp impl->IUISettings4_iface.lpVtbl = &uisettings4_vtbl; impl->IUISettings5_iface.lpVtbl = &uisettings5_vtbl; impl->IWeakReferenceSource_iface.lpVtbl = &weak_reference_source_vtbl; - impl->ref = 1; + impl->IWeakReference_iface.lpVtbl = &weak_reference_vtbl; + impl->ref_strong = 1; + impl->ref_weak = 1;
*instance = (IInspectable *)&impl->IUISettings3_iface; return S_OK;