Commit 9617c784 authored by Fabian Maurer's avatar Fabian Maurer Committed by Alexandre Julliard

windows.devices.geolocation.geolocator: Implement IWeakReference.

parent f40c3f63
...@@ -34,7 +34,9 @@ struct geolocator ...@@ -34,7 +34,9 @@ struct geolocator
{ {
IGeolocator IGeolocator_iface; IGeolocator IGeolocator_iface;
IWeakReferenceSource IWeakReferenceSource_iface; IWeakReferenceSource IWeakReferenceSource_iface;
LONG ref; IWeakReference IWeakReference_iface;
LONG ref_public;
LONG ref_weak;
}; };
static inline struct geolocator *impl_from_IGeolocator(IGeolocator *iface) static inline struct geolocator *impl_from_IGeolocator(IGeolocator *iface)
...@@ -73,16 +75,18 @@ static HRESULT WINAPI geolocator_QueryInterface(IGeolocator *iface, REFIID iid, ...@@ -73,16 +75,18 @@ static HRESULT WINAPI geolocator_QueryInterface(IGeolocator *iface, REFIID iid,
static ULONG WINAPI geolocator_AddRef(IGeolocator *iface) static ULONG WINAPI geolocator_AddRef(IGeolocator *iface)
{ {
struct geolocator *impl = impl_from_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); TRACE("iface %p increasing refcount to %lu.\n", iface, ref);
IWeakReference_AddRef(&impl->IWeakReference_iface);
return ref; return ref;
} }
static ULONG WINAPI geolocator_Release(IGeolocator *iface) static ULONG WINAPI geolocator_Release(IGeolocator *iface)
{ {
struct geolocator *impl = impl_from_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); TRACE("iface %p decreasing refcount to %lu.\n", iface, ref);
IWeakReference_Release(&impl->IWeakReference_iface);
return ref; return ref;
} }
...@@ -207,6 +211,77 @@ static const struct IGeolocatorVtbl geolocator_vtbl = ...@@ -207,6 +211,77 @@ static const struct IGeolocatorVtbl geolocator_vtbl =
geolocator_remove_StatusChanged, 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) static inline struct geolocator *impl_from_IWeakReferenceSource(IWeakReferenceSource *iface)
{ {
return CONTAINING_RECORD(iface, struct geolocator, IWeakReferenceSource_iface); return CONTAINING_RECORD(iface, struct geolocator, IWeakReferenceSource_iface);
...@@ -232,8 +307,12 @@ static ULONG WINAPI weak_reference_source_Release(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) static HRESULT WINAPI weak_reference_source_GetWeakReference(IWeakReferenceSource *iface, IWeakReference **ref)
{ {
FIXME("iface %p, ref %p stub.\n", iface, ref); struct geolocator *impl = impl_from_IWeakReferenceSource(iface);
return E_NOTIMPL;
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 = static const struct IWeakReferenceSourceVtbl weak_reference_source_vtbl =
...@@ -321,7 +400,9 @@ static HRESULT WINAPI factory_ActivateInstance(IActivationFactory *iface, IInspe ...@@ -321,7 +400,9 @@ static HRESULT WINAPI factory_ActivateInstance(IActivationFactory *iface, IInspe
impl->IGeolocator_iface.lpVtbl = &geolocator_vtbl; impl->IGeolocator_iface.lpVtbl = &geolocator_vtbl;
impl->IWeakReferenceSource_iface.lpVtbl = &weak_reference_source_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; *instance = (IInspectable *)&impl->IGeolocator_iface;
return S_OK; return S_OK;
......
...@@ -54,7 +54,11 @@ void test_basic(void) ...@@ -54,7 +54,11 @@ void test_basic(void)
IActivationFactory *factory; IActivationFactory *factory;
IInspectable *inspectable; IInspectable *inspectable;
IGeolocator *geolocator; IGeolocator *geolocator;
IGeolocator *geolocator2;
IWeakReferenceSource *weak_reference_source; IWeakReferenceSource *weak_reference_source;
IWeakReference *weak_reference;
IUnknown* unknown;
void *dummy;
HSTRING str; HSTRING str;
HRESULT hr; HRESULT hr;
...@@ -91,9 +95,47 @@ void test_basic(void) ...@@ -91,9 +95,47 @@ void test_basic(void)
hr = IGeolocator_QueryInterface(geolocator, &IID_IWeakReferenceSource, (void **)&weak_reference_source); hr = IGeolocator_QueryInterface(geolocator, &IID_IWeakReferenceSource, (void **)&weak_reference_source);
ok(hr == S_OK && weak_reference_source, "got hr %#lx.\n", hr); 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); 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); 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); IActivationFactory_Release(factory);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment