windows.devices.geolocation.geolocator: Implement IWeakReference.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=55126
This commit is contained in:
parent
f40c3f6323
commit
9617c784b9
2 changed files with 129 additions and 6 deletions
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue