1
0
mirror of https://github.com/wine-mirror/wine synced 2024-07-05 17:28:47 +00:00

windows.devices.geolocation.geolocator: Implement IWeakReference.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=55126
This commit is contained in:
Fabian Maurer 2023-06-29 20:55:08 +02:00 committed by Alexandre Julliard
parent f40c3f6323
commit 9617c784b9
2 changed files with 129 additions and 6 deletions

View File

@ -34,7 +34,9 @@ struct geolocator
{
IGeolocator IGeolocator_iface;
IWeakReferenceSource IWeakReferenceSource_iface;
LONG ref;
IWeakReference IWeakReference_iface;
LONG ref_public;
LONG ref_weak;
};
static inline struct geolocator *impl_from_IGeolocator(IGeolocator *iface)
@ -73,16 +75,18 @@ static HRESULT WINAPI geolocator_QueryInterface(IGeolocator *iface, REFIID iid,
static ULONG WINAPI geolocator_AddRef(IGeolocator *iface)
{
struct geolocator *impl = impl_from_IGeolocator(iface);
ULONG ref = InterlockedIncrement(&impl->ref);
ULONG ref = InterlockedIncrement(&impl->ref_public);
TRACE("iface %p increasing refcount to %lu.\n", iface, ref);
IWeakReference_AddRef(&impl->IWeakReference_iface);
return ref;
}
static ULONG WINAPI geolocator_Release(IGeolocator *iface)
{
struct geolocator *impl = impl_from_IGeolocator(iface);
ULONG ref = InterlockedDecrement(&impl->ref);
ULONG ref = InterlockedDecrement(&impl->ref_public);
TRACE("iface %p decreasing refcount to %lu.\n", iface, ref);
IWeakReference_Release(&impl->IWeakReference_iface);
return ref;
}
@ -207,6 +211,77 @@ static const struct IGeolocatorVtbl geolocator_vtbl =
geolocator_remove_StatusChanged,
};
static inline struct geolocator *impl_from_IWeakReference(IWeakReference *iface)
{
return CONTAINING_RECORD(iface, struct geolocator, IWeakReference_iface);
}
static HRESULT WINAPI weak_reference_QueryInterface(IWeakReference *iface, REFIID iid, void **out)
{
struct geolocator *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 geolocator *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 geolocator *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 geolocator *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_public)))
return S_OK;
} while (ref != InterlockedCompareExchange(&impl->ref_public, ref + 1, ref));
hr = IGeolocator_QueryInterface(&impl->IGeolocator_iface, iid, (void **)out);
InterlockedDecrement(&impl->ref_public);
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 geolocator *impl_from_IWeakReferenceSource(IWeakReferenceSource *iface)
{
return CONTAINING_RECORD(iface, struct geolocator, IWeakReferenceSource_iface);
@ -232,8 +307,12 @@ 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 geolocator *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 =
@ -321,7 +400,9 @@ static HRESULT WINAPI factory_ActivateInstance(IActivationFactory *iface, IInspe
impl->IGeolocator_iface.lpVtbl = &geolocator_vtbl;
impl->IWeakReferenceSource_iface.lpVtbl = &weak_reference_source_vtbl;
impl->ref = 1;
impl->IWeakReference_iface.lpVtbl = &weak_reference_vtbl;
impl->ref_public = 1;
impl->ref_weak = 1;
*instance = (IInspectable *)&impl->IGeolocator_iface;
return S_OK;

View File

@ -54,7 +54,11 @@ void test_basic(void)
IActivationFactory *factory;
IInspectable *inspectable;
IGeolocator *geolocator;
IGeolocator *geolocator2;
IWeakReferenceSource *weak_reference_source;
IWeakReference *weak_reference;
IUnknown* unknown;
void *dummy;
HSTRING str;
HRESULT hr;
@ -91,9 +95,47 @@ void test_basic(void)
hr = IGeolocator_QueryInterface(geolocator, &IID_IWeakReferenceSource, (void **)&weak_reference_source);
ok(hr == S_OK && weak_reference_source, "got hr %#lx.\n", hr);
hr = IWeakReferenceSource_GetWeakReference(weak_reference_source, &weak_reference);
ok(hr == S_OK && weak_reference, "got hr %#lx.\n", hr);
IWeakReferenceSource_Release(weak_reference_source);
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_IGeolocator, (IInspectable **)&geolocator2);
ok(hr == S_OK && geolocator2, "got hr %#lx.\n", hr);
hr = IWeakReference_Resolve(weak_reference, &IID_IInspectable, &inspectable);
ok(hr == S_OK && inspectable, "got hr %#lx.\n", hr);
ok((void *)inspectable == (void *)geolocator, "Interfaces are not the same\n");
ok((void *)unknown == (void *)geolocator, "Interfaces are not the same\n");
IUnknown_Release(unknown);
IGeolocator_Release(geolocator2);
geolocator2 = 0;
IInspectable_Release(inspectable);
inspectable = 0;
dummy = (void *)0xdeadbeef;
hr = IWeakReference_Resolve(weak_reference, &IID_IWeakReference, (IInspectable **)&dummy);
ok(hr == E_NOINTERFACE && !dummy, "got hr %#lx.\n", hr);
check_interface(weak_reference, &IID_IUnknown);
check_interface(weak_reference, &IID_IWeakReference);
hr = IWeakReference_QueryInterface(weak_reference, &IID_IGeolocator, &dummy);
ok(hr == E_NOINTERFACE && !dummy, "got hr %#lx.\n", hr);
hr = IWeakReference_QueryInterface(weak_reference, &IID_IAgileObject, &dummy);
ok(hr == E_NOINTERFACE && !dummy, "got hr %#lx.\n", hr);
hr = IWeakReference_QueryInterface(weak_reference, &IID_IInspectable, &dummy);
ok(hr == E_NOINTERFACE && !dummy, "got hr %#lx.\n", hr);
/* Free geolocator, weak reference should fail to resolve now */
IGeolocator_Release(geolocator);
hr = IWeakReference_Resolve(weak_reference, &IID_IGeolocator, (IInspectable **)&geolocator2);
ok(hr == S_OK && !geolocator2, "got hr %#lx.\n", hr);
hr = IWeakReference_Resolve(weak_reference, &IID_IWeakReference, (IInspectable **)&dummy);
ok(hr == S_OK && !dummy, "got hr %#lx.\n", hr);
IWeakReference_Release(weak_reference);
IActivationFactory_Release(factory);
}