wine/dlls/geolocation/main.c

451 lines
14 KiB
C

/* WinRT Windows.Devices.Geolocation.Geolocator Implementation
*
* Copyright 2023 Fabian Maurer
*
* 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"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(geolocator);
struct geolocator_statics
{
IActivationFactory IActivationFactory_iface;
LONG ref;
};
struct geolocator
{
IGeolocator IGeolocator_iface;
IWeakReferenceSource IWeakReferenceSource_iface;
IWeakReference IWeakReference_iface;
LONG ref_public;
LONG ref_weak;
};
static inline struct geolocator *impl_from_IGeolocator(IGeolocator *iface)
{
return CONTAINING_RECORD(iface, struct geolocator, IGeolocator_iface);
}
static HRESULT WINAPI geolocator_QueryInterface(IGeolocator *iface, REFIID iid, void **out)
{
struct geolocator *impl = impl_from_IGeolocator(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, &IID_IGeolocator))
{
*out = &impl->IGeolocator_iface;
IInspectable_AddRef(*out);
return S_OK;
}
if (IsEqualGUID(iid, &IID_IWeakReferenceSource))
{
*out = &impl->IWeakReferenceSource_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 geolocator_AddRef(IGeolocator *iface)
{
struct geolocator *impl = impl_from_IGeolocator(iface);
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_public);
TRACE("iface %p decreasing refcount to %lu.\n", iface, ref);
IWeakReference_Release(&impl->IWeakReference_iface);
return ref;
}
static HRESULT WINAPI geolocator_GetIids(IGeolocator *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 geolocator_GetRuntimeClassName(IGeolocator *iface, HSTRING *class_name)
{
FIXME("iface %p, class_name %p stub!\n", iface, class_name);
return E_NOTIMPL;
}
static HRESULT WINAPI geolocator_GetTrustLevel(IGeolocator *iface, TrustLevel *trust_level)
{
FIXME("iface %p, trust_level %p stub!\n", iface, trust_level);
return E_NOTIMPL;
}
HRESULT WINAPI geolocator_get_DesiredAccuracy(IGeolocator *iface, PositionAccuracy *value)
{
FIXME("iface %p, value %p stub.\n", iface, value);
return E_NOTIMPL;
}
HRESULT WINAPI geolocator_set_DesiredAccuracy(IGeolocator *iface, PositionAccuracy value)
{
FIXME("iface %p, value %d stub.\n", iface, value);
return E_NOTIMPL;
}
HRESULT WINAPI geolocator_get_MovementThreshold(IGeolocator *iface, DOUBLE *value)
{
FIXME("iface %p, value %p stub.\n", iface, value);
return E_NOTIMPL;
}
HRESULT WINAPI geolocator_set_MovementThreshold(IGeolocator *iface, DOUBLE value)
{
FIXME("iface %p, value %f stub.\n", iface, value);
return E_NOTIMPL;
}
HRESULT WINAPI geolocator_get_ReportInterval(IGeolocator *iface, UINT32 *value)
{
FIXME("iface %p, value %p stub.\n", iface, value);
return E_NOTIMPL;
}
HRESULT WINAPI geolocator_set_ReportInterval(IGeolocator *iface, UINT32 value)
{
FIXME("iface %p, value %u stub.\n", iface, value);
return E_NOTIMPL;
}
HRESULT WINAPI geolocator_LocationStatus(IGeolocator *iface, PositionStatus *value)
{
FIXME("iface %p, value %p stub.\n", iface, value);
return E_NOTIMPL;
}
HRESULT WINAPI geolocator_GetGeopositionAsync(IGeolocator *iface, IAsyncOperation_Geoposition **value)
{
FIXME("iface %p, value %p stub.\n", iface, value);
return E_NOTIMPL;
}
HRESULT WINAPI geolocator_GetGeopositionAsyncWithAgeAndTimeout(IGeolocator *iface, TimeSpan maximum_age, TimeSpan timeout, IAsyncOperation_Geoposition **value)
{
FIXME("iface %p, maximum_age %#I64x, timeout %#I64x, value %p stub.\n", iface, maximum_age.Duration, timeout.Duration, value);
return E_NOTIMPL;
}
HRESULT WINAPI geolocator_add_PositionChanged(IGeolocator *iface, ITypedEventHandler_Geolocator_PositionChangedEventArgs *handler, EventRegistrationToken *token)
{
FIXME("iface %p, handler %p, token %p stub.\n", iface, handler, token);
return S_OK;
}
HRESULT WINAPI geolocator_remove_PositionChanged(IGeolocator *iface, EventRegistrationToken token)
{
FIXME("iface %p, token %#I64x stub.\n", iface, token.value);
return E_NOTIMPL;
}
HRESULT WINAPI geolocator_add_StatusChanged(IGeolocator *iface, ITypedEventHandler_Geolocator_StatusChangedEventArgs *handler, EventRegistrationToken *token)
{
FIXME("iface %p, handler %p, token %p stub.\n", iface, handler, token);
return E_NOTIMPL;
}
HRESULT WINAPI geolocator_remove_StatusChanged(IGeolocator *iface, EventRegistrationToken token)
{
FIXME("iface %p, token %#I64x stub.\n", iface, token.value);
return E_NOTIMPL;
}
static const struct IGeolocatorVtbl geolocator_vtbl =
{
geolocator_QueryInterface,
geolocator_AddRef,
geolocator_Release,
/* IInspectable methods */
geolocator_GetIids,
geolocator_GetRuntimeClassName,
geolocator_GetTrustLevel,
/* IGeolocator methods */
geolocator_get_DesiredAccuracy,
geolocator_set_DesiredAccuracy,
geolocator_get_MovementThreshold,
geolocator_set_MovementThreshold,
geolocator_get_ReportInterval,
geolocator_set_ReportInterval,
geolocator_LocationStatus,
geolocator_GetGeopositionAsync,
geolocator_GetGeopositionAsyncWithAgeAndTimeout,
geolocator_add_PositionChanged,
geolocator_remove_PositionChanged,
geolocator_add_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)
{
return CONTAINING_RECORD(iface, struct geolocator, IWeakReferenceSource_iface);
}
static HRESULT WINAPI weak_reference_source_QueryInterface(IWeakReferenceSource *iface, REFIID iid, void **out)
{
struct geolocator *impl = impl_from_IWeakReferenceSource(iface);
return geolocator_QueryInterface(&impl->IGeolocator_iface, iid, out);
}
static ULONG WINAPI weak_reference_source_AddRef(IWeakReferenceSource *iface)
{
struct geolocator *impl = impl_from_IWeakReferenceSource(iface);
return geolocator_AddRef(&impl->IGeolocator_iface);
}
static ULONG WINAPI weak_reference_source_Release(IWeakReferenceSource *iface)
{
struct geolocator *impl = impl_from_IWeakReferenceSource(iface);
return geolocator_Release(&impl->IGeolocator_iface);
}
static HRESULT WINAPI weak_reference_source_GetWeakReference(IWeakReferenceSource *iface, IWeakReference **ref)
{
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 =
{
weak_reference_source_QueryInterface,
weak_reference_source_AddRef,
weak_reference_source_Release,
/* IWeakReferenceSource methods */
weak_reference_source_GetWeakReference,
};
static inline struct geolocator_statics *impl_from_IActivationFactory(IActivationFactory *iface)
{
return CONTAINING_RECORD(iface, struct geolocator_statics, IActivationFactory_iface);
}
static HRESULT WINAPI factory_QueryInterface(IActivationFactory *iface, REFIID iid, void **out)
{
struct geolocator_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_IAgileObject) ||
IsEqualGUID(iid, &IID_IActivationFactory))
{
*out = &impl->IActivationFactory_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 factory_AddRef(IActivationFactory *iface)
{
struct geolocator_statics *impl = impl_from_IActivationFactory(iface);
ULONG ref = InterlockedIncrement(&impl->ref);
TRACE("iface %p increasing refcount to %lu.\n", iface, ref);
return ref;
}
static ULONG WINAPI factory_Release(IActivationFactory *iface)
{
struct geolocator_statics *impl = impl_from_IActivationFactory(iface);
ULONG ref = InterlockedDecrement(&impl->ref);
TRACE("iface %p decreasing refcount to %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 const struct IActivationFactoryVtbl factory_vtbl;
static HRESULT WINAPI factory_ActivateInstance(IActivationFactory *iface, IInspectable **instance)
{
struct geolocator *impl;
TRACE("iface %p, instance %p.\n", iface, instance);
if (!(impl = calloc(1, sizeof(*impl))))
{
*instance = NULL;
return E_OUTOFMEMORY;
}
impl->IGeolocator_iface.lpVtbl = &geolocator_vtbl;
impl->IWeakReferenceSource_iface.lpVtbl = &weak_reference_source_vtbl;
impl->IWeakReference_iface.lpVtbl = &weak_reference_vtbl;
impl->ref_public = 1;
impl->ref_weak = 1;
*instance = (IInspectable *)&impl->IGeolocator_iface;
return S_OK;
}
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 geolocator_statics geolocator_statics =
{
{&factory_vtbl},
1,
};
static IActivationFactory *geolocator_factory = &geolocator_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_Devices_Geolocation_Geolocator))
IActivationFactory_QueryInterface(geolocator_factory, &IID_IActivationFactory, (void **)factory);
if (*factory) return S_OK;
return CLASS_E_CLASSNOTAVAILABLE;
}