Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=55126
-- v5: windows.devices.geolocation.geolocator: Implement IWeakReference. windows.devices.geolocation.geolocator: Implement IWeakReferenceSource. windows.devices.geolocation.geolocator: Fake success for PositionChanged_add. windows.devices.geolocation.geolocator: Add stubs for IGeolocator.
From: Fabian Maurer dark.shadow4@web.de
--- include/windows.foundation.idl | 1 + 1 file changed, 1 insertion(+)
diff --git a/include/windows.foundation.idl b/include/windows.foundation.idl index d89541740a7..281b51d0d6c 100644 --- a/include/windows.foundation.idl +++ b/include/windows.foundation.idl @@ -87,6 +87,7 @@ namespace Windows.Foundation { interface Windows.Foundation.IAsyncOperation<IInspectable *>; interface Windows.Foundation.IAsyncOperation<boolean>; interface Windows.Foundation.IReference<INT32>; + interface Windows.Foundation.IReference<DOUBLE>; interface Windows.Foundation.TypedEventHandler<IInspectable *, IInspectable *>; interface Windows.Foundation.TypedEventHandler<Windows.Foundation.IMemoryBufferReference *, IInspectable *>; }
From: Fabian Maurer dark.shadow4@web.de
--- include/Makefile.in | 1 + include/windows.devices.geolocation.idl | 223 ++++++++++++++++++++++++ 2 files changed, 224 insertions(+) create mode 100644 include/windows.devices.geolocation.idl
diff --git a/include/Makefile.in b/include/Makefile.in index e9f0aa8d5fb..94e733cc61c 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -808,6 +808,7 @@ SOURCES = \ windns.h \ windot11.h \ windows.devices.enumeration.idl \ + windows.devices.geolocation.idl \ windows.devices.haptics.idl \ windows.devices.power.idl \ windows.foundation.collections.idl \ diff --git a/include/windows.devices.geolocation.idl b/include/windows.devices.geolocation.idl new file mode 100644 index 00000000000..9d0033503e3 --- /dev/null +++ b/include/windows.devices.geolocation.idl @@ -0,0 +1,223 @@ +/* + * 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 + */ + +#ifdef __WIDL__ +#pragma winrt ns_prefix +#endif + +#ifndef DO_NO_IMPORTS +import "inspectable.idl"; +import "asyncinfo.idl"; +import "eventtoken.idl"; +import "windowscontracts.idl"; +import "windows.foundation.idl"; +#endif + +namespace Windows.Devices.Geolocation { + + typedef enum PositionAccuracy PositionAccuracy; + typedef enum PositionStatus PositionStatus; + + interface IGeolocator; + interface IGeoposition; + interface IGeocoordinate; + interface IPositionChangedEventArgs; + interface IStatusChangedEventArgs; + interface ICivicAddress; + + runtimeclass Geolocator; + runtimeclass Geoposition; + runtimeclass Geocoordinate; + runtimeclass PositionChangedEventArgs; + runtimeclass StatusChangedEventArgs; + runtimeclass CivicAddress; + + declare { + interface Windows.Foundation.AsyncOperationCompletedHandler<Windows.Devices.Geolocation.Geoposition*>; + interface Windows.Foundation.IAsyncOperation<Windows.Devices.Geolocation.Geoposition*>; + interface Windows.Foundation.TypedEventHandler<Windows.Devices.Geolocation.Geolocator*, Windows.Devices.Geolocation.PositionChangedEventArgs*>; + interface Windows.Foundation.TypedEventHandler<Windows.Devices.Geolocation.Geolocator*, Windows.Devices.Geolocation.StatusChangedEventArgs*>; + } + + [contract(Windows.Foundation.UniversalApiContract, 1.0)] + enum PositionAccuracy + { + Default = 0, + High = 1, + }; + + [contract(Windows.Foundation.UniversalApiContract, 1.0)] + enum PositionStatus + { + Ready = 0, + Initializing = 1, + NoData = 2, + Disabled = 3, + NotInitialized = 4, + NotAvailable = 5, + }; + + /* Interfaces */ + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + exclusiveto(Windows.Devices.Geolocation.Geolocator), + uuid(a9c3bf62-4524-4989-8aa9-de019d2e551f) + ] + interface IGeolocator : IInspectable + { + [propget] HRESULT DesiredAccuracy([out, retval] Windows.Devices.Geolocation.PositionAccuracy *value); + [propput] HRESULT DesiredAccuracy([in] Windows.Devices.Geolocation.PositionAccuracy value); + [propget] HRESULT MovementThreshold([out, retval] DOUBLE *value); + [propput] HRESULT MovementThreshold([in] DOUBLE value); + [propget] HRESULT ReportInterval([out, retval] UINT32 *value); + [propput] HRESULT ReportInterval([in] UINT32 value); + [propget] HRESULT LocationStatus([out, retval] Windows.Devices.Geolocation.PositionStatus *value); + [overload("GetGeopositionAsync")] + HRESULT GetGeopositionAsync([out, retval] Windows.Foundation.IAsyncOperation<Windows.Devices.Geolocation.Geoposition*> **value); + [overload("GetGeopositionAsync")] + HRESULT GetGeopositionAsyncWithAgeAndTimeout([in] Windows.Foundation.TimeSpan maximum_age, + [in] Windows.Foundation.TimeSpan timeout, + [out, retval] Windows.Foundation.IAsyncOperation<Windows.Devices.Geolocation.Geoposition*> **value); + [eventadd] HRESULT PositionChanged([in] Windows.Foundation.TypedEventHandler<Windows.Devices.Geolocation.Geolocator*, Windows.Devices.Geolocation.PositionChangedEventArgs*> *handler, + [out, retval] EventRegistrationToken *token); + [eventremove] HRESULT PositionChanged([in] EventRegistrationToken token); + [eventadd] HRESULT StatusChanged([in] Windows.Foundation.TypedEventHandler<Windows.Devices.Geolocation.Geolocator*, Windows.Devices.Geolocation.StatusChangedEventArgs*> *handler, + [out, retval] EventRegistrationToken *token); + [eventremove] HRESULT StatusChanged([in] EventRegistrationToken token); + } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + exclusiveto(Windows.Devices.Geolocation.Geoposition), + uuid(c18d0454-7d41-4ff7-a957-9dffb4ef7f5b) + ] + interface IGeoposition : IInspectable + { + [propget] HRESULT Coordinate([out, retval] Windows.Devices.Geolocation.Geocoordinate **value); + [propget] HRESULT CivicAddress([out, retval] Windows.Devices.Geolocation.CivicAddress **value); + } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + exclusiveto(Windows.Devices.Geolocation.Geocoordinate), + uuid(ee21a3aa-976a-ac70-803d-083ea55bcbc4) + ] + interface IGeocoordinate : IInspectable + { + [propget] HRESULT Latitude([out, retval] DOUBLE *value); + [propget] HRESULT Longitude([out, retval] DOUBLE *value); + [propget] HRESULT Altitude([out, retval] Windows.Foundation.IReference<DOUBLE> **value); + [propget] HRESULT Accuracy([out, retval] DOUBLE *value); + [propget] HRESULT AltitudeAccuracy([out, retval] Windows.Foundation.IReference<DOUBLE> **value); + [propget] HRESULT Heading([out, retval] Windows.Foundation.IReference<DOUBLE> **value); + [propget] HRESULT Speed([out, retval] Windows.Foundation.IReference<DOUBLE> **value); + [propget] HRESULT Timestamp([out, retval] Windows.Foundation.DateTime *value); + } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + exclusiveto(Windows.Devices.Geolocation.PositionChangedEventArgs), + uuid(37859ce5-9d1e-46c5-bf3b-6ad8cac1a093) + ] + interface IPositionChangedEventArgs : IInspectable + { + [propget] HRESULT Position([out, retval] Windows.Devices.Geolocation.Geoposition **value); + } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + exclusiveto(Windows.Devices.Geolocation.StatusChangedEventArgs), + uuid(3453d2da-8c93-4111-a205-9aecfc9be5c0) + ] + interface IStatusChangedEventArgs : IInspectable + { + [propget] HRESULT Status([out, retval] Windows.Devices.Geolocation.PositionStatus *value); + } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + exclusiveto(Windows.Devices.Geolocation.CivicAddress), + uuid(a8567a1a-64f4-4d48-bcea-f6b008eca34c) + ] + interface ICivicAddress : IInspectable + { + [propget] HRESULT Country([out, retval] HSTRING *value); + [propget] HRESULT State([out, retval] HSTRING *value); + [propget] HRESULT City([out, retval] HSTRING *value); + [propget] HRESULT PostalCode([out, retval] HSTRING *value); + [propget] HRESULT Timestamp([out, retval] Windows.Foundation.DateTime *value); + } + + /* Runtime Classes */ + + [ + activatable(Windows.Foundation.UniversalApiContract, 1.0), + contract(Windows.Foundation.UniversalApiContract, 1.0), + marshaling_behavior(agile), + threading(both) + ] + runtimeclass Geolocator + { + [default] interface Windows.Devices.Geolocation.IGeolocator; + } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + marshaling_behavior(agile) + ] + runtimeclass Geoposition + { + [default] interface Windows.Devices.Geolocation.IGeoposition; + } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + marshaling_behavior(agile) + ] + runtimeclass Geocoordinate + { + [default] interface Windows.Devices.Geolocation.IGeocoordinate; + } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + marshaling_behavior(agile) + ] + runtimeclass PositionChangedEventArgs + { + [default] interface Windows.Devices.Geolocation.IPositionChangedEventArgs; + } + + [ + marshaling_behavior(agile) + ] + runtimeclass StatusChangedEventArgs + { + [default] interface Windows.Devices.Geolocation.IStatusChangedEventArgs; + } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + marshaling_behavior(agile) + ] + runtimeclass CivicAddress + { + [default] interface Windows.Devices.Geolocation.ICivicAddress; + } +}
From: Fabian Maurer dark.shadow4@web.de
--- configure | 11 +- configure.ac | 2 + .../Makefile.in | 7 + .../classes.idl | 26 +++ .../main.c | 148 ++++++++++++++++++ .../private.h | 38 +++++ .../tests/Makefile.in | 5 + .../tests/geolocator.c | 85 ++++++++++ ...indows.devices.geolocation.geolocator.spec | 3 + 9 files changed, 321 insertions(+), 4 deletions(-) create mode 100644 dlls/windows.devices.geolocation.geolocator/Makefile.in create mode 100644 dlls/windows.devices.geolocation.geolocator/classes.idl create mode 100644 dlls/windows.devices.geolocation.geolocator/main.c create mode 100644 dlls/windows.devices.geolocation.geolocator/private.h create mode 100644 dlls/windows.devices.geolocation.geolocator/tests/Makefile.in create mode 100644 dlls/windows.devices.geolocation.geolocator/tests/geolocator.c create mode 100644 dlls/windows.devices.geolocation.geolocator/windows.devices.geolocation.geolocator.spec
diff --git a/configure b/configure index d530de3ced1..9727a419b60 100755 --- a/configure +++ b/configure @@ -1456,6 +1456,7 @@ enable_wiaservc enable_wimgapi enable_win32u enable_windows_devices_enumeration +enable_windows_devices_geolocation_geolocator enable_windows_gaming_input enable_windows_gaming_ui_gamebar enable_windows_globalization @@ -5912,11 +5913,11 @@ if test x$ac_prog_cxx_stdcxx = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++11 features" >&5 printf %s "checking for $CXX option to enable C++11 features... " >&6; } -if test ${ac_cv_prog_cxx_cxx11+y} +if test ${ac_cv_prog_cxx_11+y} then : printf %s "(cached) " >&6 else $as_nop - ac_cv_prog_cxx_cxx11=no + ac_cv_prog_cxx_11=no ac_save_CXX=$CXX cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -5958,11 +5959,11 @@ if test x$ac_prog_cxx_stdcxx = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++98 features" >&5 printf %s "checking for $CXX option to enable C++98 features... " >&6; } -if test ${ac_cv_prog_cxx_cxx98+y} +if test ${ac_cv_prog_cxx_98+y} then : printf %s "(cached) " >&6 else $as_nop - ac_cv_prog_cxx_cxx98=no + ac_cv_prog_cxx_98=no ac_save_CXX=$CXX cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -21966,6 +21967,8 @@ wine_fn_config_makefile dlls/winaspi.dll16 enable_win16 wine_fn_config_makefile dlls/windebug.dll16 enable_win16 wine_fn_config_makefile dlls/windows.devices.enumeration enable_windows_devices_enumeration wine_fn_config_makefile dlls/windows.devices.enumeration/tests enable_tests +wine_fn_config_makefile dlls/windows.devices.geolocation.geolocator enable_windows_devices_geolocation_geolocator +wine_fn_config_makefile dlls/windows.devices.geolocation.geolocator/tests enable_tests wine_fn_config_makefile dlls/windows.gaming.input enable_windows_gaming_input wine_fn_config_makefile dlls/windows.gaming.input/tests enable_tests wine_fn_config_makefile dlls/windows.gaming.ui.gamebar enable_windows_gaming_ui_gamebar diff --git a/configure.ac b/configure.ac index 90c95c89ffb..22f8580ae23 100644 --- a/configure.ac +++ b/configure.ac @@ -3141,6 +3141,8 @@ WINE_CONFIG_MAKEFILE(dlls/winaspi.dll16,enable_win16) WINE_CONFIG_MAKEFILE(dlls/windebug.dll16,enable_win16) WINE_CONFIG_MAKEFILE(dlls/windows.devices.enumeration) WINE_CONFIG_MAKEFILE(dlls/windows.devices.enumeration/tests) +WINE_CONFIG_MAKEFILE(dlls/windows.devices.geolocation.geolocator) +WINE_CONFIG_MAKEFILE(dlls/windows.devices.geolocation.geolocator/tests) WINE_CONFIG_MAKEFILE(dlls/windows.gaming.input) WINE_CONFIG_MAKEFILE(dlls/windows.gaming.input/tests) WINE_CONFIG_MAKEFILE(dlls/windows.gaming.ui.gamebar) diff --git a/dlls/windows.devices.geolocation.geolocator/Makefile.in b/dlls/windows.devices.geolocation.geolocator/Makefile.in new file mode 100644 index 00000000000..42b5e50442b --- /dev/null +++ b/dlls/windows.devices.geolocation.geolocator/Makefile.in @@ -0,0 +1,7 @@ +MODULE = windows.devices.geolocation.geolocator.dll +IMPORTS = combase uuid + +C_SRCS = \ + main.c + +IDL_SRCS = classes.idl diff --git a/dlls/windows.devices.geolocation.geolocator/classes.idl b/dlls/windows.devices.geolocation.geolocator/classes.idl new file mode 100644 index 00000000000..9c55cf20446 --- /dev/null +++ b/dlls/windows.devices.geolocation.geolocator/classes.idl @@ -0,0 +1,26 @@ +/* Runtime Classes for windows.devices.geolocation.geolocator.dll + * + * 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 + */ + +#pragma makedep register + +#ifdef __WIDL__ +#pragma winrt ns_prefix +#endif + +#include "windows.devices.geolocation.idl" diff --git a/dlls/windows.devices.geolocation.geolocator/main.c b/dlls/windows.devices.geolocation.geolocator/main.c new file mode 100644 index 00000000000..290a63a992e --- /dev/null +++ b/dlls/windows.devices.geolocation.geolocator/main.c @@ -0,0 +1,148 @@ +/* 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); + +static const char *debugstr_hstring(HSTRING hstr) +{ + const WCHAR *str; + UINT32 len; + if (hstr && !((ULONG_PTR)hstr >> 16)) return "(invalid)"; + str = WindowsGetStringRawBuffer(hstr, &len); + return wine_dbgstr_wn(str, len); +} + +struct geolocator +{ + IActivationFactory IActivationFactory_iface; + LONG ref; +}; + +static inline struct geolocator *impl_from_IActivationFactory(IActivationFactory *iface) +{ + return CONTAINING_RECORD(iface, struct geolocator, IActivationFactory_iface); +} + +static HRESULT WINAPI factory_QueryInterface(IActivationFactory *iface, REFIID iid, void **out) +{ + struct geolocator *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 *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 *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 HRESULT WINAPI factory_ActivateInstance(IActivationFactory *iface, IInspectable **instance) +{ + FIXME("iface %p, instance %p stub!\n", iface, instance); + return E_NOTIMPL; +} + +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 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; +} diff --git a/dlls/windows.devices.geolocation.geolocator/private.h b/dlls/windows.devices.geolocation.geolocator/private.h new file mode 100644 index 00000000000..b03c6cfc9d0 --- /dev/null +++ b/dlls/windows.devices.geolocation.geolocator/private.h @@ -0,0 +1,38 @@ +/* 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 + */ + +#ifndef __WINE_WINDOWS_DEVICES_GEOLOCATION_GEOLOCATOR_PRIVATE_H +#define __WINE_WINDOWS_DEVICES_GEOLOCATION_GEOLOCATOR_PRIVATE_H + +#include <stdarg.h> + +#define COBJMACROS +#include "windef.h" +#include "winbase.h" +#include "winstring.h" + +#include "activation.h" + +#define WIDL_using_Windows_Foundation +#define WIDL_using_Windows_Foundation_Collections +#include "windows.foundation.h" +#define WIDL_using_Windows_Devices_Geolocation +#include "windows.devices.geolocation.h" + +#endif diff --git a/dlls/windows.devices.geolocation.geolocator/tests/Makefile.in b/dlls/windows.devices.geolocation.geolocator/tests/Makefile.in new file mode 100644 index 00000000000..1be5ca78258 --- /dev/null +++ b/dlls/windows.devices.geolocation.geolocator/tests/Makefile.in @@ -0,0 +1,5 @@ +TESTDLL = windows.devices.geolocation.geolocator.dll +IMPORTS = combase uuid + +C_SRCS = \ + geolocator.c diff --git a/dlls/windows.devices.geolocation.geolocator/tests/geolocator.c b/dlls/windows.devices.geolocation.geolocator/tests/geolocator.c new file mode 100644 index 00000000000..eb22407c74a --- /dev/null +++ b/dlls/windows.devices.geolocation.geolocator/tests/geolocator.c @@ -0,0 +1,85 @@ +/* + * 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 + */ +#define COBJMACROS +#include <stdarg.h> + +#include "windef.h" +#include "winbase.h" +#include "winerror.h" +#include "winstring.h" + +#include "initguid.h" +#include "roapi.h" + +#define WIDL_using_Windows_Foundation +#define WIDL_using_Windows_Foundation_Collections +#include "windows.foundation.h" +#define WIDL_using_Windows_Devices_Geolocation +#include "windows.devices.geolocation.h" + +#include "wine/test.h" + +#define check_interface(obj, iid, broken_win8) check_interface_(__LINE__, obj, iid, broken_win8) +static void check_interface_(unsigned int line, void *obj, const IID *iid, BOOL broken_win8) +{ + IUnknown *iface = obj; + IUnknown *unk; + HRESULT hr; + + hr = IUnknown_QueryInterface(iface, iid, (void **)&unk); + ok_(__FILE__, line)(hr == S_OK || (broken_win8 && broken(hr == E_NOINTERFACE)), "got hr %#lx.\n", hr); + if (hr == S_OK) + IUnknown_Release(unk); +} + +void test_basic(void) +{ + static const WCHAR *geolocator_name = L"Windows.Devices.Geolocation.Geolocator"; + IActivationFactory *factory; + HSTRING str; + HRESULT hr; + + hr = WindowsCreateString(geolocator_name, wcslen(geolocator_name), &str); + ok(hr == S_OK, "got hr %#lx.\n", hr); + + hr = RoGetActivationFactory(str, &IID_IActivationFactory, (void **)&factory); + WindowsDeleteString(str); + 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(geolocator_name)); + return; + } + + check_interface(factory, &IID_IUnknown, FALSE); + check_interface(factory, &IID_IInspectable, FALSE); + check_interface(factory, &IID_IAgileObject, TRUE); + check_interface(factory, &IID_IActivationFactory, FALSE); +} + +START_TEST(geolocator) +{ + HRESULT hr; + + hr = RoInitialize(RO_INIT_MULTITHREADED); + ok(hr == S_OK, "RoInitialize failed, hr %#lx\n", hr); + + test_basic(); + + RoUninitialize(); +} diff --git a/dlls/windows.devices.geolocation.geolocator/windows.devices.geolocation.geolocator.spec b/dlls/windows.devices.geolocation.geolocator/windows.devices.geolocation.geolocator.spec new file mode 100644 index 00000000000..721493229c2 --- /dev/null +++ b/dlls/windows.devices.geolocation.geolocator/windows.devices.geolocation.geolocator.spec @@ -0,0 +1,3 @@ +1 stdcall -private DllCanUnloadNow() +2 stdcall -private DllGetActivationFactory(ptr ptr) +3 stdcall -private DllGetClassObject(ptr ptr ptr)
From: Fabian Maurer dark.shadow4@web.de
--- .../main.c | 205 +++++++++++++++++- .../tests/geolocator.c | 18 ++ 2 files changed, 214 insertions(+), 9 deletions(-)
diff --git a/dlls/windows.devices.geolocation.geolocator/main.c b/dlls/windows.devices.geolocation.geolocator/main.c index 290a63a992e..0c4c01e78dd 100644 --- a/dlls/windows.devices.geolocation.geolocator/main.c +++ b/dlls/windows.devices.geolocation.geolocator/main.c @@ -33,20 +33,192 @@ static const char *debugstr_hstring(HSTRING hstr) return wine_dbgstr_wn(str, len); }
-struct geolocator +struct geolocator_factory { IActivationFactory IActivationFactory_iface; LONG ref; };
-static inline struct geolocator *impl_from_IActivationFactory(IActivationFactory *iface) +struct geolocator +{ + IGeolocator IGeolocator_iface; + LONG ref; +}; + +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; + } + + 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); + TRACE("iface %p increasing refcount to %lu.\n", iface, ref); + return ref; +} + +static ULONG WINAPI geolocator_Release(IGeolocator *iface) +{ + struct geolocator *impl = impl_from_IGeolocator(iface); + ULONG ref = InterlockedDecrement(&impl->ref); + TRACE("iface %p decreasing refcount to %lu.\n", iface, ref); + 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); + *value = 0; + 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); + *value = 0; + 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); + *value = 0; + 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 E_NOTIMPL; +} + +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_factory *impl_from_IActivationFactory(IActivationFactory *iface) { - return CONTAINING_RECORD(iface, struct geolocator, IActivationFactory_iface); + return CONTAINING_RECORD(iface, struct geolocator_factory, IActivationFactory_iface); }
static HRESULT WINAPI factory_QueryInterface(IActivationFactory *iface, REFIID iid, void **out) { - struct geolocator *impl = impl_from_IActivationFactory(iface); + struct geolocator_factory *impl = impl_from_IActivationFactory(iface);
TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
@@ -67,7 +239,7 @@ static HRESULT WINAPI factory_QueryInterface(IActivationFactory *iface, REFIID i
static ULONG WINAPI factory_AddRef(IActivationFactory *iface) { - struct geolocator *impl = impl_from_IActivationFactory(iface); + struct geolocator_factory *impl = impl_from_IActivationFactory(iface); ULONG ref = InterlockedIncrement(&impl->ref); TRACE("iface %p increasing refcount to %lu.\n", iface, ref); return ref; @@ -75,7 +247,7 @@ static ULONG WINAPI factory_AddRef(IActivationFactory *iface)
static ULONG WINAPI factory_Release(IActivationFactory *iface) { - struct geolocator *impl = impl_from_IActivationFactory(iface); + struct geolocator_factory *impl = impl_from_IActivationFactory(iface); ULONG ref = InterlockedDecrement(&impl->ref); TRACE("iface %p decreasing refcount to %lu.\n", iface, ref); return ref; @@ -99,10 +271,25 @@ static HRESULT WINAPI factory_GetTrustLevel(IActivationFactory *iface, TrustLeve return E_NOTIMPL; }
+static const struct IActivationFactoryVtbl factory_vtbl; + static HRESULT WINAPI factory_ActivateInstance(IActivationFactory *iface, IInspectable **instance) { - FIXME("iface %p, instance %p stub!\n", iface, instance); - return E_NOTIMPL; + 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->ref = 1; + + *instance = (IInspectable *)&impl->IGeolocator_iface; + return S_OK; }
static const struct IActivationFactoryVtbl factory_vtbl = @@ -118,7 +305,7 @@ static const struct IActivationFactoryVtbl factory_vtbl = factory_ActivateInstance, };
-static struct geolocator geolocator_statics = +static struct geolocator_factory geolocator_statics = { {&factory_vtbl}, 1, diff --git a/dlls/windows.devices.geolocation.geolocator/tests/geolocator.c b/dlls/windows.devices.geolocation.geolocator/tests/geolocator.c index eb22407c74a..046eacd9c84 100644 --- a/dlls/windows.devices.geolocation.geolocator/tests/geolocator.c +++ b/dlls/windows.devices.geolocation.geolocator/tests/geolocator.c @@ -51,6 +51,8 @@ void test_basic(void) { static const WCHAR *geolocator_name = L"Windows.Devices.Geolocation.Geolocator"; IActivationFactory *factory; + IInspectable *inspectable; + IGeolocator *geolocator; HSTRING str; HRESULT hr;
@@ -70,6 +72,22 @@ void test_basic(void) check_interface(factory, &IID_IInspectable, FALSE); check_interface(factory, &IID_IAgileObject, TRUE); check_interface(factory, &IID_IActivationFactory, FALSE); + + hr = IActivationFactory_ActivateInstance(factory, &inspectable); + ok(hr == S_OK && inspectable, "got hr %#lx.\n", hr); + + check_interface(inspectable, &IID_IUnknown, FALSE); + check_interface(inspectable, &IID_IInspectable, FALSE); + check_interface(inspectable, &IID_IAgileObject, FALSE); + + hr = IInspectable_QueryInterface(inspectable, &IID_IGeolocator, (void **)&geolocator); + ok(hr == S_OK && geolocator, "got hr %#lx.\n", hr); + ok((void*)inspectable == (void*)geolocator, "Interfaces are not the same\n"); + + IInspectable_Release(inspectable); + inspectable = 0; + + IGeolocator_Release(geolocator); }
START_TEST(geolocator)
From: Fabian Maurer dark.shadow4@web.de
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=55126 --- dlls/windows.devices.geolocation.geolocator/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/windows.devices.geolocation.geolocator/main.c b/dlls/windows.devices.geolocation.geolocator/main.c index 0c4c01e78dd..afaff202fd8 100644 --- a/dlls/windows.devices.geolocation.geolocator/main.c +++ b/dlls/windows.devices.geolocation.geolocator/main.c @@ -165,7 +165,7 @@ HRESULT WINAPI geolocator_GetGeopositionAsyncWithAgeAndTimeout(IGeolocator *ifac 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 E_NOTIMPL; + return S_OK; }
HRESULT WINAPI geolocator_remove_PositionChanged(IGeolocator *iface, EventRegistrationToken token)
From: Fabian Maurer dark.shadow4@web.de
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=55126 --- .../main.c | 49 +++++++++++++++++++ .../private.h | 1 + .../tests/geolocator.c | 6 +++ 3 files changed, 56 insertions(+)
diff --git a/dlls/windows.devices.geolocation.geolocator/main.c b/dlls/windows.devices.geolocation.geolocator/main.c index afaff202fd8..f7773b8cd59 100644 --- a/dlls/windows.devices.geolocation.geolocator/main.c +++ b/dlls/windows.devices.geolocation.geolocator/main.c @@ -42,6 +42,7 @@ struct geolocator_factory struct geolocator { IGeolocator IGeolocator_iface; + IWeakReferenceSource IWeakReferenceSource_iface; LONG ref; };
@@ -66,6 +67,13 @@ static HRESULT WINAPI geolocator_QueryInterface(IGeolocator *iface, REFIID iid, 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; @@ -147,6 +155,7 @@ HRESULT WINAPI geolocator_set_ReportInterval(IGeolocator *iface, UINT32 value) HRESULT WINAPI geolocator_LocationStatus(IGeolocator *iface, PositionStatus *value) { FIXME("iface %p, value %p stub.\n", iface, value); + *value = 0; return E_NOTIMPL; }
@@ -211,6 +220,45 @@ static const struct IGeolocatorVtbl geolocator_vtbl = geolocator_remove_StatusChanged, };
+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) +{ + FIXME("iface %p, ref %p stub.\n", iface, ref); + *ref = 0; + 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, +}; + static inline struct geolocator_factory *impl_from_IActivationFactory(IActivationFactory *iface) { return CONTAINING_RECORD(iface, struct geolocator_factory, IActivationFactory_iface); @@ -286,6 +334,7 @@ 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;
*instance = (IInspectable *)&impl->IGeolocator_iface; diff --git a/dlls/windows.devices.geolocation.geolocator/private.h b/dlls/windows.devices.geolocation.geolocator/private.h index b03c6cfc9d0..7250bc1fe36 100644 --- a/dlls/windows.devices.geolocation.geolocator/private.h +++ b/dlls/windows.devices.geolocation.geolocator/private.h @@ -28,6 +28,7 @@ #include "winstring.h"
#include "activation.h" +#include "weakreference.h"
#define WIDL_using_Windows_Foundation #define WIDL_using_Windows_Foundation_Collections diff --git a/dlls/windows.devices.geolocation.geolocator/tests/geolocator.c b/dlls/windows.devices.geolocation.geolocator/tests/geolocator.c index 046eacd9c84..b4759e2aef2 100644 --- a/dlls/windows.devices.geolocation.geolocator/tests/geolocator.c +++ b/dlls/windows.devices.geolocation.geolocator/tests/geolocator.c @@ -26,6 +26,7 @@ #include "initguid.h" #include "roapi.h"
+#include "weakreference.h" #define WIDL_using_Windows_Foundation #define WIDL_using_Windows_Foundation_Collections #include "windows.foundation.h" @@ -53,6 +54,7 @@ void test_basic(void) IActivationFactory *factory; IInspectable *inspectable; IGeolocator *geolocator; + IWeakReferenceSource *weak_reference_source; HSTRING str; HRESULT hr;
@@ -87,6 +89,10 @@ void test_basic(void) IInspectable_Release(inspectable); inspectable = 0;
+ hr = IGeolocator_QueryInterface(geolocator, &IID_IWeakReferenceSource, (void **)&weak_reference_source); + ok(hr == S_OK && weak_reference_source, "got hr %#lx.\n", hr); + IWeakReferenceSource_Release(weak_reference_source); + IGeolocator_Release(geolocator); }
From: Fabian Maurer dark.shadow4@web.de
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=55126 --- .../main.c | 81 +++++++++++++++++-- .../tests/geolocator.c | 14 ++++ 2 files changed, 88 insertions(+), 7 deletions(-)
diff --git a/dlls/windows.devices.geolocation.geolocator/main.c b/dlls/windows.devices.geolocation.geolocator/main.c index f7773b8cd59..fae5b0088d9 100644 --- a/dlls/windows.devices.geolocation.geolocator/main.c +++ b/dlls/windows.devices.geolocation.geolocator/main.c @@ -43,7 +43,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) @@ -82,7 +84,7 @@ 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); return ref; } @@ -90,7 +92,11 @@ static ULONG WINAPI geolocator_AddRef(IGeolocator *iface) 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); + if (ref == 0) + { + IWeakReference_Release(&impl->IWeakReference_iface);; + } TRACE("iface %p decreasing refcount to %lu.\n", iface, ref); return ref; } @@ -220,6 +226,62 @@ 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); + return geolocator_QueryInterface(&impl->IGeolocator_iface, iid, out); +} + +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 == 0) + { + free(impl); + } + return ref; +} + +static HRESULT WINAPI weak_reference_Resolve(IWeakReference *iface, REFIID iid, IInspectable **ref) +{ + struct geolocator *impl = impl_from_IWeakReference(iface); + TRACE("iface %p, ref %p stub.\n", iface, ref); + + if (!impl->ref_public) + { + *ref = 0; + } + else + { + *ref = (IInspectable*)&impl->IGeolocator_iface; + IInspectable_AddRef(*ref); + } + return S_OK; +} + +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); @@ -245,9 +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); - *ref = 0; - 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 = @@ -335,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; diff --git a/dlls/windows.devices.geolocation.geolocator/tests/geolocator.c b/dlls/windows.devices.geolocation.geolocator/tests/geolocator.c index b4759e2aef2..211eb671125 100644 --- a/dlls/windows.devices.geolocation.geolocator/tests/geolocator.c +++ b/dlls/windows.devices.geolocation.geolocator/tests/geolocator.c @@ -54,7 +54,9 @@ void test_basic(void) IActivationFactory *factory; IInspectable *inspectable; IGeolocator *geolocator; + IGeolocator *geolocator2; IWeakReferenceSource *weak_reference_source; + IWeakReference *weak_reference; HSTRING str; HRESULT hr;
@@ -91,9 +93,21 @@ 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_IGeolocator, (IInspectable**)&geolocator2); + ok(hr == S_OK && geolocator2, "got hr %#lx.\n", hr); + IGeolocator_Release(geolocator2); + IGeolocator_Release(geolocator); + + hr = IWeakReference_Resolve(weak_reference, &IID_IGeolocator, (IInspectable**)&geolocator2); + ok(hr == S_OK && !geolocator2, "got hr %#lx.\n", hr); + + IWeakReference_Release(weak_reference); }
START_TEST(geolocator)
On Thu Jun 29 20:08:18 2023 +0000, Fabian Maurer wrote:
@besentv Sure, if you wouldn't mind? @rbernon I fixed the other issues, would you mind reviewing those changes already? Thanks for the in-depth review btw, really appreciate it!
Alright but might take s few days.
Rémi Bernon (@rbernon) commented about dlls/windows.devices.geolocation.geolocator/tests/geolocator.c:
+#include "winerror.h" +#include "winstring.h"
+#include "initguid.h" +#include "roapi.h"
+#define WIDL_using_Windows_Foundation +#define WIDL_using_Windows_Foundation_Collections +#include "windows.foundation.h" +#define WIDL_using_Windows_Devices_Geolocation +#include "windows.devices.geolocation.h"
+#include "wine/test.h"
+#define check_interface(obj, iid, broken_win8) check_interface_(__LINE__, obj, iid, broken_win8) +static void check_interface_(unsigned int line, void *obj, const IID *iid, BOOL broken_win8)
It is confusing that the third bool parameter here is not whether the interface is supported or not, but a "broken" flag. You should keep the same API as the usual check_interface calls elsewhere.
For the broken case I'd suggest to either
* not check that interface, possibly keeping it as commented with an explanation, or,
* add a fourth optional parameter (only the function, and the macro would pass FALSE to it), and use the function call for that interface only.
Rémi Bernon (@rbernon) commented about dlls/windows.devices.geolocation.geolocator/main.c:
return wine_dbgstr_wn(str, len);
}
-struct geolocator +struct geolocator_factory
Maybe use the right name in the commit that introduces the structure. I'd prefer `struct geolocator_statics`, matching the variable and the way its named elsewhere, it may end up with more interfaces than just the factory.
Rémi Bernon (@rbernon) commented about dlls/windows.devices.geolocation.geolocator/main.c:
+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);
- *value = 0;
I think stubs should not do *anything*.
Rémi Bernon (@rbernon) commented about dlls/windows.devices.geolocation.geolocator/tests/geolocator.c:
check_interface(factory, &IID_IInspectable, FALSE); check_interface(factory, &IID_IAgileObject, TRUE); check_interface(factory, &IID_IActivationFactory, FALSE);
- hr = IActivationFactory_ActivateInstance(factory, &inspectable);
- ok(hr == S_OK && inspectable, "got hr %#lx.\n", hr);
- check_interface(inspectable, &IID_IUnknown, FALSE);
- check_interface(inspectable, &IID_IInspectable, FALSE);
- check_interface(inspectable, &IID_IAgileObject, FALSE);
- hr = IInspectable_QueryInterface(inspectable, &IID_IGeolocator, (void **)&geolocator);
- ok(hr == S_OK && geolocator, "got hr %#lx.\n", hr);
- ok((void*)inspectable == (void*)geolocator, "Interfaces are not the same\n");
```suggestion:-0+0 ok((void *)inspectable == (void *)geolocator, "Interfaces are not the same\n"); ```
Rémi Bernon (@rbernon) commented about configure:
then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++11 features" >&5 printf %s "checking for $CXX option to enable C++11 features... " >&6; } -if test ${ac_cv_prog_cxx_cxx11+y} +if test ${ac_cv_prog_cxx_11+y} then : printf %s "(cached) " >&6 else $as_nop
- ac_cv_prog_cxx_cxx11=no
- ac_cv_prog_cxx_11=no
ac_save_CXX=$CXX
You don't have to, and should not commit configure changes (for reasons like here, this is an unrelated change).
Rémi Bernon (@rbernon) commented about dlls/windows.devices.geolocation.geolocator/tests/geolocator.c:
- ok(hr == S_OK, "got hr %#lx.\n", hr);
- hr = RoGetActivationFactory(str, &IID_IActivationFactory, (void **)&factory);
- WindowsDeleteString(str);
- 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(geolocator_name));
return;
- }
- check_interface(factory, &IID_IUnknown, FALSE);
- check_interface(factory, &IID_IInspectable, FALSE);
- check_interface(factory, &IID_IAgileObject, TRUE);
- check_interface(factory, &IID_IActivationFactory, FALSE);
+}
Although it doesn't really matter as it's static you're leaking the IActivationFactory reference here, please release it.
Rémi Bernon (@rbernon) commented about dlls/windows.devices.geolocation.geolocator/main.c:
HRESULT WINAPI geolocator_LocationStatus(IGeolocator *iface, PositionStatus *value) { FIXME("iface %p, value %p stub.\n", iface, value);
- *value = 0;
This is unrelated, and I think it should not be here as this is a stub.
Rémi Bernon (@rbernon) commented about dlls/windows.devices.geolocation.geolocator/main.c:
+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) +{
- FIXME("iface %p, ref %p stub.\n", iface, ref);
- *ref = 0;
Same.
Rémi Bernon (@rbernon) commented about dlls/windows.devices.geolocation.geolocator/tests/geolocator.c:
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_IGeolocator, (IInspectable**)&geolocator2);
```suggestion:-0+0 hr = IWeakReference_Resolve(weak_reference, &IID_IGeolocator, (IInspectable **)&geolocator2); ```
Rémi Bernon (@rbernon) commented about dlls/windows.devices.geolocation.geolocator/tests/geolocator.c:
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_IGeolocator, (IInspectable**)&geolocator2);
ok(hr == S_OK && geolocator2, "got hr %#lx.\n", hr);
IGeolocator_Release(geolocator2);
IGeolocator_Release(geolocator);
hr = IWeakReference_Resolve(weak_reference, &IID_IGeolocator, (IInspectable**)&geolocator2);
```suggestion:-0+0 hr = IWeakReference_Resolve(weak_reference, &IID_IGeolocator, (IInspectable **)&geolocator2); ```
Rémi Bernon (@rbernon) commented about dlls/windows.devices.geolocation.geolocator/main.c:
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);
- return geolocator_QueryInterface(&impl->IGeolocator_iface, iid, out);
I suspect that this should not do that, and only let you query the IWeakReference interface. Otherwise this would be a way to acquire public reference on an invalid (with ref_public == 0) object.
Rémi Bernon (@rbernon) commented about dlls/windows.devices.geolocation.geolocator/main.c:
+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 == 0)
- {
free(impl);
- }
```suggestion:-3+0 if (!ref) free(impl); ```
I think we usually prefer this rather than comparing to 0.
Rémi Bernon (@rbernon) commented about dlls/windows.devices.geolocation.geolocator/main.c:
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);
- if (ref == 0)
- {
IWeakReference_Release(&impl->IWeakReference_iface);;
- }
```suggestion:-3+0 if (!ref) IWeakReference_Release(&impl->IWeakReference_iface); ```
Rémi Bernon (@rbernon) commented about dlls/windows.devices.geolocation.geolocator/main.c:
+}
+static HRESULT WINAPI weak_reference_Resolve(IWeakReference *iface, REFIID iid, IInspectable **ref) +{
- struct geolocator *impl = impl_from_IWeakReference(iface);
- TRACE("iface %p, ref %p stub.\n", iface, ref);
- if (!impl->ref_public)
- {
*ref = 0;
- }
- else
- {
*ref = (IInspectable*)&impl->IGeolocator_iface;
IInspectable_AddRef(*ref);
- }
This will need to be done in an atomic way. You also probably need to respect the iid that is passed. I also suggest to rename `ref` parameter to out, as `ref` is often used for refcount values.
You may have a thread B currently releasing the last public reference on the object right after the current thread A checks this. This would result in the thread B seeing Release return 0, indicating the object is now invalid, while the thread A increasing the public ref again to 1, receiving a valid object, which is incorrect.
I think this will need to be done this way:
1) in Resolve:
```c if ((ref = InterlockedIncrement(&impl->ref_public)) > 1) hr = IGeolocator_QueryInterface(&impl->IGeolocator_iface, iid, out); else /* invalid object */ { *out = NULL; hr = S_OK; } InterlockedDecrement(&impl->ref_public); ```
Also now there's an issue as we increase the public refcount here, and we may end up releasing the last public ref. It could either also include the same check as in `geolocator_Release` and release a weak ref as well.
Or, perhaps better as it would be more consistent, change `geolocator_AddRef` / `geolocator_Release` to also always add/release a weak reference:
2) in geolocator_AddRef / geolocator_Release:
```c 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; } ```
Rémi Bernon (@rbernon) commented about dlls/windows.devices.geolocation.geolocator/main.c:
+static ULONG WINAPI weak_reference_Release(IWeakReference *iface) +{
- struct geolocator *impl = impl_from_IWeakReference(iface);
- ULONG ref = InterlockedDecrement(&impl->ref_weak);
- if (ref == 0)
- {
free(impl);
- }
- return ref;
+}
+static HRESULT WINAPI weak_reference_Resolve(IWeakReference *iface, REFIID iid, IInspectable **ref) +{
- struct geolocator *impl = impl_from_IWeakReference(iface);
- TRACE("iface %p, ref %p stub.\n", iface, ref);
You should trace the iid here.
On Mon Jul 3 09:42:26 2023 +0000, Rémi Bernon wrote:
I suspect that this should not do that, and only let you query the IWeakReference interface. Otherwise this would be a way to acquire public reference on an invalid (with ref_public == 0) object.
Fwiw this could be a test, checking that IWeakReference_QueryInterface only let you query IWeakReference iface, could also be interesting to check what it does for IAgileObject which is often implemented everywhere.
On Thu Jun 29 20:36:04 2023 +0000, **** wrote:
Marvin replied on the mailing list:
Hi, It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated. The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details: The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=134319 Your paranoid android. === w8 (32 bit report) === windows.devices.geolocation.geolocator: geolocator.c:77: Test failed: got hr 0x80004002. === w8adm (32 bit report) === windows.devices.geolocation.geolocator: geolocator.c:77: Test failed: got hr 0x80004002. === w864 (32 bit report) === windows.devices.geolocation.geolocator: geolocator.c:77: Test failed: got hr 0x80004002. === w864 (64 bit report) === windows.devices.geolocation.geolocator: geolocator.c:77: Test failed: got hr 0x80004002. === debian11 (32 bit report) === wmvcore: wmvcore.c:1713: Test failed: Stream 0: Format 4: Got hr 0xc00d0041. wmvcore.c:1730: Test failed: Stream 0: Format 4: Media types didn't match.
Should be fixed
On Mon Jul 3 09:42:19 2023 +0000, Rémi Bernon wrote:
It is confusing that the third bool parameter here is not whether the interface is supported or not, but a "broken" flag. You should keep the same API as the usual check_interface calls elsewhere. For the broken case I'd suggest to either
- not check that interface, possibly keeping it as commented with an
explanation, or,
- add a fourth optional parameter (only the function, and the macro
would pass FALSE to it), and use the function call for that interface only.
Makes sense, will be fixed in the next version
On Mon Jul 3 09:42:19 2023 +0000, Rémi Bernon wrote:
Maybe use the right name in the commit that introduces the structure. I'd prefer `struct geolocator_statics`, matching the variable and the way its named elsewhere, it may end up with more interfaces than just the factory.
Will be fixed in the next version
On Mon Jul 3 09:42:20 2023 +0000, Rémi Bernon wrote:
I think stubs should not do *anything*.
Alright, removed in the next version
On Mon Jul 3 09:42:21 2023 +0000, Rémi Bernon wrote:
ok((void *)inspectable == (void *)geolocator, "Interfaces are not the same\n");
Fixed for the next version
On Mon Jul 3 09:42:22 2023 +0000, Rémi Bernon wrote:
You don't have to, and should not commit configure changes (for reasons like here, this is an unrelated change).
Sorry, after having to rerun configure after every rebase I figured it'd make things easier to just check it in.
On Mon Jul 3 09:42:24 2023 +0000, Rémi Bernon wrote:
This is unrelated, and I think it should not be here as this is a stub.
Fixed for the next version
On Mon Jul 3 09:42:23 2023 +0000, Rémi Bernon wrote:
Although it doesn't really matter as it's static you're leaking the IActivationFactory reference here, please release it.
Fixed for the next version
On Mon Jul 3 09:42:24 2023 +0000, Rémi Bernon wrote:
Same.
Fixed for the next version
On Mon Jul 3 09:42:26 2023 +0000, Rémi Bernon wrote:
hr = IWeakReference_Resolve(weak_reference, &IID_IGeolocator, (IInspectable **)&geolocator2);
Fixed for the next version
On Mon Jul 3 09:45:55 2023 +0000, Rémi Bernon wrote:
Fwiw this could be a test, checking that IWeakReference_QueryInterface only let you query IWeakReference iface, could also be interesting to check what it does for IAgileObject which is often implemented everywhere.
Added in the next version
On Mon Jul 3 09:42:27 2023 +0000, Rémi Bernon wrote:
if (!ref) free(impl);
I think we usually prefer this rather than comparing to 0.
Changed in the next version
On Mon Jul 3 09:42:28 2023 +0000, Rémi Bernon wrote:
if (!ref) IWeakReference_Release(&impl->IWeakReference_iface);
Changed in the next version
On Mon Jul 3 09:42:29 2023 +0000, Rémi Bernon wrote:
You should trace the iid here.
Fixed in the next version