From: Paul Gofman pgofman@codeweavers.com
--- include/windows.perception.spatial.idl | 159 +++++++++++++++++++++++++ 1 file changed, 159 insertions(+)
diff --git a/include/windows.perception.spatial.idl b/include/windows.perception.spatial.idl index d19330963f7..93be78a6d74 100644 --- a/include/windows.perception.spatial.idl +++ b/include/windows.perception.spatial.idl @@ -36,13 +36,24 @@ namespace Windows.Perception.Spatial { typedef struct SpatialBoundingFrustum SpatialBoundingFrustum; typedef struct SpatialBoundingOrientedBox SpatialBoundingOrientedBox; typedef struct SpatialBoundingSphere SpatialBoundingSphere; + typedef enum SpatialAnchorExportPurpose SpatialAnchorExportPurpose;
interface ISpatialBoundingVolume; interface ISpatialBoundingVolumeStatics; interface ISpatialCoordinateSystem; + interface ISpatialAnchorRawCoordinateSystemAdjustedEventArgs; + interface ISpatialAnchor; + interface ISpatialAnchorStatics; + interface ISpatialAnchorExportSufficiency; + interface ISpatialAnchorExporter; + interface ISpatialAnchorExporterStatics;
runtimeclass SpatialBoundingVolume; runtimeclass SpatialCoordinateSystem; + runtimeclass SpatialAnchorRawCoordinateSystemAdjustedEventArgs; + runtimeclass SpatialAnchor; + runtimeclass SpatialAnchorExportSufficiency; + runtimeclass SpatialAnchorExporter;
declare { interface Windows.Foundation.Collections.IIterable<Windows.Perception.Spatial.SpatialBoundingVolume *>; @@ -52,6 +63,9 @@ namespace Windows.Perception.Spatial { interface Windows.Foundation.IReference<Windows.Perception.Spatial.SpatialBoundingBox>; interface Windows.Foundation.IReference<Windows.Perception.Spatial.SpatialBoundingFrustum>; interface Windows.Foundation.IReference<Windows.Perception.Spatial.SpatialBoundingOrientedBox>; + interface Windows.Foundation.TypedEventHandler<Windows.Perception.Spatial.SpatialAnchor *, Windows.Perception.Spatial.SpatialAnchorRawCoordinateSystemAdjustedEventArgs *>; + interface Windows.Foundation.AsyncOperationCompletedHandler<Windows.Perception.Spatial.SpatialAnchorExportSufficiency *>; + interface Windows.Foundation.IAsyncOperation<Windows.Perception.Spatial.SpatialAnchorExportSufficiency *>; }
[ @@ -65,6 +79,15 @@ namespace Windows.Perception.Spatial { DeniedBySystem = 3, };
+ [ + contract(Windows.Foundation.UniversalApiContract, 7.0) + ] + enum SpatialAnchorExportPurpose + { + Relocalization = 0, + Sharing = 1 + }; + [ contract(Windows.Foundation.UniversalApiContract, 2.0) ] @@ -157,6 +180,100 @@ namespace Windows.Perception.Spatial { ); }
+ [ + contract(Windows.Foundation.UniversalApiContract, 2.0), + exclusiveto(Windows.Perception.Spatial.SpatialAnchor), + uuid(a9928642-0174-311c-ae79-0e5107669f16), + ] + interface ISpatialAnchorStatics : IInspectable + { + [overload("TryCreateRelativeTo")] HRESULT TryCreateRelativeTo( + [in] Windows.Perception.Spatial.SpatialCoordinateSystem *coord_system, + [out] [retval] Windows.Perception.Spatial.SpatialAnchor **value + ); + [overload("TryCreateRelativeTo")] HRESULT TryCreateWithPositionRelativeTo( + [in] Windows.Perception.Spatial.SpatialCoordinateSystem *coord_system, + [in] Windows.Foundation.Numerics.Vector3 position, + [out] [retval] Windows.Perception.Spatial.SpatialAnchor **value + ); + [overload("TryCreateRelativeTo")] HRESULT TryCreateWithPositionAndOrientationRelativeTo( + [in] Windows.Perception.Spatial.SpatialCoordinateSystem *coord_system, + [in] Windows.Foundation.Numerics.Vector3 position, + [in] Windows.Foundation.Numerics.Quaternion orientation, + [out] [retval] Windows.Perception.Spatial.SpatialAnchor **value + ); + } + + [ + contract(Windows.Foundation.UniversalApiContract, 2.0), + exclusiveto(Windows.Perception.Spatial.SpatialAnchor), + uuid(0529e5ce-1d34-3702-bcec-eabff578a869), + ] + interface ISpatialAnchor : IInspectable + { + [propget] HRESULT CoordinateSystem([out] [retval] Windows.Perception.Spatial.SpatialCoordinateSystem **value); + [propget] HRESULT RawCoordinateSystem([out] [retval] Windows.Perception.Spatial.SpatialCoordinateSystem **value); + [eventadd] HRESULT RawCoordinateSystemAdjusted( + [in] Windows.Foundation.TypedEventHandler<Windows.Perception.Spatial.SpatialAnchor *, + Windows.Perception.Spatial.SpatialAnchorRawCoordinateSystemAdjustedEventArgs*> *handler, + [out] [retval] EventRegistrationToken *cookie + ); + [eventremove] HRESULT RawCoordinateSystemAdjusted([in] EventRegistrationToken cookie); + } + + [ + contract(Windows.Foundation.UniversalApiContract, 7.0), + exclusiveto(Windows.Perception.Spatial.SpatialAnchorExportSufficiency), + uuid(77c25b2b-3409-4088-b91b-fdfd05d1648f), + ] + interface ISpatialAnchorExportSufficiency : IInspectable + { + [propget] HRESULT IsMinimallySufficient([out] [retval] boolean *value); + [propget] HRESULT SufficiencyLevel([out] [retval] DOUBLE *value); + [propget] HRESULT RecommendedSufficiencyLevel([out] [retval] DOUBLE *value); + } + + [ + contract(Windows.Foundation.UniversalApiContract, 2.0), + exclusiveto(Windows.Perception.Spatial.SpatialAnchorRawCoordinateSystemAdjustedEventArgs), + uuid(a1e81eb8-56c7-3117-a2e4-81e0fcf28e00), + ] + interface ISpatialAnchorRawCoordinateSystemAdjustedEventArgs : IInspectable + { + [propget] HRESULT OldRawCoordinateSystemToNewRawCoordinateSystemTransform([out] [retval] Windows.Foundation.Numerics.Matrix4x4 *value); + } + + [ + contract(Windows.Foundation.UniversalApiContract, 7.0), + exclusiveto(Windows.Perception.Spatial.SpatialAnchorExporter), + uuid(9a2a4338-24fb-4269-89c5-88304aeef20f), + ] + interface ISpatialAnchorExporter : IInspectable + { + HRESULT GetAnchorExportSufficiencyAsync( + [in] Windows.Perception.Spatial.SpatialAnchor *anchor, + [in] Windows.Perception.Spatial.SpatialAnchorExportPurpose purpose, + [out] [retval] Windows.Foundation.IAsyncOperation<Windows.Perception.Spatial.SpatialAnchorExportSufficiency*> **operation + ); + HRESULT TryExportAnchorAsync( + [in] Windows.Perception.Spatial.SpatialAnchor* anchor, + [in] Windows.Perception.Spatial.SpatialAnchorExportPurpose purpose, + [in] Windows.Storage.Streams.IOutputStream* stream, + [out] [retval] Windows.Foundation.IAsyncOperation<boolean>** operation + ); + } + + [ + contract(Windows.Foundation.UniversalApiContract, 7.0), + exclusiveto(Windows.Perception.Spatial.SpatialAnchorExporter), + uuid(ed2507b8-2475-439c-85ff-7fed341fdc88), + ] + interface ISpatialAnchorExporterStatics : IInspectable + { + HRESULT GetDefault([out] [retval] Windows.Perception.Spatial.SpatialAnchorExporter **value); + HRESULT RequestAccessAsync([out] [retval] Windows.Foundation.IAsyncOperation<Windows.Perception.Spatial.SpatialPerceptionAccessStatus> **result); + } + [ contract(Windows.Foundation.UniversalApiContract, 2.0), marshaling_behavior(agile), @@ -177,4 +294,46 @@ namespace Windows.Perception.Spatial { { [default] interface Windows.Perception.Spatial.ISpatialCoordinateSystem; } + + [ + contract(Windows.Foundation.UniversalApiContract, 2.0), + marshaling_behavior(agile), + static(Windows.Perception.Spatial.ISpatialAnchorStatics, Windows.Foundation.UniversalApiContract, 2.0), + threading(both), + ] + runtimeclass SpatialAnchor + { + [default] interface Windows.Perception.Spatial.ISpatialAnchor; + } + + [ + contract(Windows.Foundation.UniversalApiContract, 7.0), + marshaling_behavior(agile), + threading(both), + ] + runtimeclass SpatialAnchorExportSufficiency + { + [default] interface Windows.Perception.Spatial.ISpatialAnchorExportSufficiency; + } + + [ + contract(Windows.Foundation.UniversalApiContract, 2.0), + marshaling_behavior(agile), + threading(both), + ] + runtimeclass SpatialAnchorRawCoordinateSystemAdjustedEventArgs + { + [default] interface Windows.Perception.Spatial.ISpatialAnchorRawCoordinateSystemAdjustedEventArgs; + } + + [ + contract(Windows.Foundation.UniversalApiContract, 7.0), + marshaling_behavior(agile), + static(Windows.Perception.Spatial.ISpatialAnchorExporterStatics, Windows.Foundation.UniversalApiContract, 7.0), + threading(both), + ] + runtimeclass SpatialAnchorExporter + { + [default] interface Windows.Perception.Spatial.ISpatialAnchorExporter; + } }
From: Paul Gofman pgofman@codeweavers.com
--- dlls/windows.perception.stub/Makefile.in | 1 + dlls/windows.perception.stub/anchor.c | 155 ++++++++++++++++++ dlls/windows.perception.stub/classes.idl | 4 + dlls/windows.perception.stub/main.c | 2 + dlls/windows.perception.stub/private.h | 2 + .../tests/perception.c | 25 +++ 6 files changed, 189 insertions(+) create mode 100644 dlls/windows.perception.stub/anchor.c
diff --git a/dlls/windows.perception.stub/Makefile.in b/dlls/windows.perception.stub/Makefile.in index f7b6065cb0d..0ba9db95a5e 100644 --- a/dlls/windows.perception.stub/Makefile.in +++ b/dlls/windows.perception.stub/Makefile.in @@ -3,6 +3,7 @@ IMPORTS = combase user32
SOURCES = \ classes.idl \ + anchor.c \ holographic_space.c \ main.c \ observer.c diff --git a/dlls/windows.perception.stub/anchor.c b/dlls/windows.perception.stub/anchor.c new file mode 100644 index 00000000000..77baa0f2133 --- /dev/null +++ b/dlls/windows.perception.stub/anchor.c @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2025 Paul Gofman for CodeWeavers + * + * 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 "private.h" +#include "wine/debug.h" + +#include "private.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(perception); + +struct exporter +{ + IActivationFactory IActivationFactory_iface; + ISpatialAnchorExporterStatics ISpatialAnchorExporterStatics_iface; + LONG ref; +}; + +static inline struct exporter *impl_from_IActivationFactory( IActivationFactory *iface ) +{ + return CONTAINING_RECORD( iface, struct exporter, IActivationFactory_iface ); +} + +static HRESULT WINAPI factory_QueryInterface( IActivationFactory *iface, REFIID iid, void **out ) +{ + struct exporter *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; + } + + if (IsEqualGUID( iid, &IID_ISpatialAnchorExporterStatics )) + { + *out = &impl->ISpatialAnchorExporterStatics_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 exporter *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 exporter *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, +}; + +DEFINE_IINSPECTABLE( exporter_statics, ISpatialAnchorExporterStatics, struct exporter, IActivationFactory_iface ) + +static HRESULT WINAPI exporter_statics_GetDefault( ISpatialAnchorExporterStatics *iface, ISpatialAnchorExporter **value ) +{ + FIXME( "iface %p, value %p stub.\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI exporter_statics_RequestAccessAsync( ISpatialAnchorExporterStatics *iface, IAsyncOperation_SpatialPerceptionAccessStatus **result ) +{ + FIXME( "iface %p, result %p stub.\n", iface, result ); + return E_NOTIMPL; +} + +static const struct ISpatialAnchorExporterStaticsVtbl exporter_statics_vtbl = +{ + exporter_statics_QueryInterface, + exporter_statics_AddRef, + exporter_statics_Release, + /* IInspectable methods */ + exporter_statics_GetIids, + exporter_statics_GetRuntimeClassName, + exporter_statics_GetTrustLevel, + /* ISpatialAnchorExporterStatics methods */ + exporter_statics_GetDefault, + exporter_statics_RequestAccessAsync, +}; + +static struct exporter exporter_statics = +{ + {&factory_vtbl}, + {&exporter_statics_vtbl}, + 1, +}; + +IActivationFactory *anchor_exporter_factory = &exporter_statics.IActivationFactory_iface; diff --git a/dlls/windows.perception.stub/classes.idl b/dlls/windows.perception.stub/classes.idl index e79c20c715b..a901784a47e 100644 --- a/dlls/windows.perception.stub/classes.idl +++ b/dlls/windows.perception.stub/classes.idl @@ -24,6 +24,10 @@ import "windows.perception.spatial.surfaces.idl"; import "windows.graphics.holographic.idl";
+ +namespace Windows.Perception.Spatial { + runtimeclass SpatialAnchorExporter; +} namespace Windows.Perception.Spatial.Surfaces { runtimeclass SpatialSurfaceObserver; } diff --git a/dlls/windows.perception.stub/main.c b/dlls/windows.perception.stub/main.c index de3b7d389e8..e47f794ab0e 100644 --- a/dlls/windows.perception.stub/main.c +++ b/dlls/windows.perception.stub/main.c @@ -42,6 +42,8 @@ HRESULT WINAPI DllGetActivationFactory( HSTRING classid, IActivationFactory **fa IActivationFactory_QueryInterface( observer_factory, &IID_IActivationFactory, (void **)factory ); if (!wcscmp( buffer, RuntimeClass_Windows_Graphics_Holographic_HolographicSpace )) IActivationFactory_QueryInterface( holographic_space_factory, &IID_IActivationFactory, (void **)factory ); + if (!wcscmp( buffer, RuntimeClass_Windows_Perception_Spatial_SpatialAnchorExporter )) + IActivationFactory_QueryInterface( anchor_exporter_factory, &IID_IActivationFactory, (void **)factory );
if (*factory) return S_OK; return CLASS_E_CLASSNOTAVAILABLE; diff --git a/dlls/windows.perception.stub/private.h b/dlls/windows.perception.stub/private.h index bf233e72fd4..f89cd0905a3 100644 --- a/dlls/windows.perception.stub/private.h +++ b/dlls/windows.perception.stub/private.h @@ -32,6 +32,7 @@ #define WIDL_using_Windows_Foundation #define WIDL_using_Windows_Foundation_Collections #include "windows.foundation.h" +#define WIDL_using_Windows_Perception_Spatial #define WIDL_using_Windows_Perception_Spatial_Surfaces #include "windows.perception.spatial.surfaces.h" #define WIDL_using_Windows_Graphics_Holographic @@ -41,6 +42,7 @@
extern IActivationFactory *observer_factory; extern IActivationFactory *holographic_space_factory; +extern IActivationFactory *anchor_exporter_factory;
#define DEFINE_IINSPECTABLE_( pfx, iface_type, impl_type, impl_from, iface_mem, expr ) \ static inline impl_type *impl_from( iface_type *iface ) \ diff --git a/dlls/windows.perception.stub/tests/perception.c b/dlls/windows.perception.stub/tests/perception.c index 8fea17882b0..91cf7c36589 100644 --- a/dlls/windows.perception.stub/tests/perception.c +++ b/dlls/windows.perception.stub/tests/perception.c @@ -284,6 +284,30 @@ done: ok( ref == 1, "got ref %ld.\n", ref ); }
+static void test_SpatialAnchorExporter(void) +{ + static const WCHAR *class_name = L"Windows.Perception.Spatial.SpatialAnchorExporter"; + IActivationFactory *factory; + HSTRING str; + HRESULT hr; + LONG ref; + + hr = WindowsCreateString( class_name, wcslen( class_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( class_name ) ); + return; + } + + ref = IActivationFactory_Release( factory ); + ok( ref == 1, "got ref %ld.\n", ref ); +} + START_TEST(perception) { HRESULT hr; @@ -293,6 +317,7 @@ START_TEST(perception)
test_ObserverStatics(); test_HolographicSpaceStatics(); + test_SpatialAnchorExporter();
RoUninitialize(); }
From: Paul Gofman pgofman@codeweavers.com
--- dlls/windows.perception.stub/anchor.c | 132 ++++++++++++++++- .../tests/perception.c | 134 ++++++++++++++++++ 2 files changed, 264 insertions(+), 2 deletions(-)
diff --git a/dlls/windows.perception.stub/anchor.c b/dlls/windows.perception.stub/anchor.c index 77baa0f2133..3d3ff4a4268 100644 --- a/dlls/windows.perception.stub/anchor.c +++ b/dlls/windows.perception.stub/anchor.c @@ -117,6 +117,134 @@ static const struct IActivationFactoryVtbl factory_vtbl = factory_ActivateInstance, };
+struct async_access_status +{ + IAsyncOperation_SpatialPerceptionAccessStatus IAsyncOperation_SpatialPerceptionAccessStatus_iface; + LONG ref; +}; + +static inline struct async_access_status *impl_from_IAsyncOperation_SpatialPerceptionAccessStatus( IAsyncOperation_SpatialPerceptionAccessStatus *iface ) +{ + return CONTAINING_RECORD( iface, struct async_access_status, IAsyncOperation_SpatialPerceptionAccessStatus_iface ); +} + +static HRESULT WINAPI async_SpatialPerceptionAccessStatus_QueryInterface( IAsyncOperation_SpatialPerceptionAccessStatus *iface, REFIID iid, void **out ) +{ + struct async_access_status *impl = impl_from_IAsyncOperation_SpatialPerceptionAccessStatus( 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_IAsyncOperation_SpatialPerceptionAccessStatus )) + { + IInspectable_AddRef( (*out = &impl->IAsyncOperation_SpatialPerceptionAccessStatus_iface) ); + return S_OK; + } + + FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) ); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI async_SpatialPerceptionAccessStatus_AddRef( IAsyncOperation_SpatialPerceptionAccessStatus *iface ) +{ + struct async_access_status *impl = impl_from_IAsyncOperation_SpatialPerceptionAccessStatus( iface ); + ULONG ref = InterlockedIncrement( &impl->ref ); + TRACE( "iface %p, ref %lu.\n", iface, ref ); + return ref; +} + +static ULONG WINAPI async_SpatialPerceptionAccessStatus_Release( IAsyncOperation_SpatialPerceptionAccessStatus *iface ) +{ + struct async_access_status *impl = impl_from_IAsyncOperation_SpatialPerceptionAccessStatus( iface ); + ULONG ref = InterlockedDecrement( &impl->ref ); + TRACE( "iface %p, ref %lu.\n", iface, ref ); + + if (!ref) + free( impl ); + + return ref; +} + +static HRESULT WINAPI async_SpatialPerceptionAccessStatus_GetIids( IAsyncOperation_SpatialPerceptionAccessStatus *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 async_SpatialPerceptionAccessStatus_GetRuntimeClassName( IAsyncOperation_SpatialPerceptionAccessStatus *iface, HSTRING *class_name ) +{ + return WindowsCreateString( L"Windows.Foundation.IAsyncOperation`1<SpatialPerceptionAccessStatus>", + ARRAY_SIZE(L"Windows.Foundation.IAsyncOperation`1<SpatialPerceptionAccessStatus>"), + class_name ); +} + +static HRESULT WINAPI async_SpatialPerceptionAccessStatus_GetTrustLevel( IAsyncOperation_SpatialPerceptionAccessStatus *iface, TrustLevel *trust_level ) +{ + FIXME( "iface %p, trust_level %p stub!\n", iface, trust_level ); + return E_NOTIMPL; +} + +static HRESULT WINAPI async_SpatialPerceptionAccessStatus_put_Completed( IAsyncOperation_SpatialPerceptionAccessStatus *iface, + IAsyncOperationCompletedHandler_SpatialPerceptionAccessStatus *handler ) +{ + TRACE( "iface %p, handler %p.\n", iface, handler ); + + IAsyncOperationCompletedHandler_SpatialPerceptionAccessStatus_AddRef( handler ); + IAsyncOperationCompletedHandler_SpatialPerceptionAccessStatus_Invoke( handler, iface, Completed ); + IAsyncOperationCompletedHandler_SpatialPerceptionAccessStatus_Release( handler ); + return S_OK; +} + +static HRESULT WINAPI async_SpatialPerceptionAccessStatus_get_Completed( IAsyncOperation_SpatialPerceptionAccessStatus *iface, + IAsyncOperationCompletedHandler_SpatialPerceptionAccessStatus **handler ) +{ + TRACE( "iface %p, handler %p.\n", iface, handler ); + + *handler = NULL; + return S_OK; +} + +static HRESULT WINAPI async_SpatialPerceptionAccessStatus_GetResults( IAsyncOperation_SpatialPerceptionAccessStatus *iface, SpatialPerceptionAccessStatus *results ) +{ + TRACE( "iface %p, results %p.\n", iface, results ); + + *results = SpatialPerceptionAccessStatus_DeniedBySystem; + return S_OK; +} + +static const struct IAsyncOperation_SpatialPerceptionAccessStatusVtbl async_SpatialPerceptionAccessStatus_vtbl = +{ + /* IUnknown methods */ + async_SpatialPerceptionAccessStatus_QueryInterface, + async_SpatialPerceptionAccessStatus_AddRef, + async_SpatialPerceptionAccessStatus_Release, + /* IInspectable methods */ + async_SpatialPerceptionAccessStatus_GetIids, + async_SpatialPerceptionAccessStatus_GetRuntimeClassName, + async_SpatialPerceptionAccessStatus_GetTrustLevel, + /* IAsyncOperation<SpatialPerceptionAccessStatus> */ + async_SpatialPerceptionAccessStatus_put_Completed, + async_SpatialPerceptionAccessStatus_get_Completed, + async_SpatialPerceptionAccessStatus_GetResults, +}; + +static HRESULT async_operation_SpatialPerceptionAccessStatus_create( IAsyncOperation_SpatialPerceptionAccessStatus **out ) +{ + struct async_access_status *impl; + + *out = NULL; + if (!(impl = calloc( 1, sizeof(*impl) ))) return E_OUTOFMEMORY; + impl->IAsyncOperation_SpatialPerceptionAccessStatus_iface.lpVtbl = &async_SpatialPerceptionAccessStatus_vtbl; + impl->ref = 1; + + *out = &impl->IAsyncOperation_SpatialPerceptionAccessStatus_iface; + TRACE( "created IAsyncOperation_SpatialPerceptionAccessStatus_iface %p\n", *out ); + return S_OK; +} + DEFINE_IINSPECTABLE( exporter_statics, ISpatialAnchorExporterStatics, struct exporter, IActivationFactory_iface )
static HRESULT WINAPI exporter_statics_GetDefault( ISpatialAnchorExporterStatics *iface, ISpatialAnchorExporter **value ) @@ -127,8 +255,8 @@ static HRESULT WINAPI exporter_statics_GetDefault( ISpatialAnchorExporterStatics
static HRESULT WINAPI exporter_statics_RequestAccessAsync( ISpatialAnchorExporterStatics *iface, IAsyncOperation_SpatialPerceptionAccessStatus **result ) { - FIXME( "iface %p, result %p stub.\n", iface, result ); - return E_NOTIMPL; + TRACE( "iface %p, result %p stub.\n", iface, result ); + return async_operation_SpatialPerceptionAccessStatus_create( result ); }
static const struct ISpatialAnchorExporterStaticsVtbl exporter_statics_vtbl = diff --git a/dlls/windows.perception.stub/tests/perception.c b/dlls/windows.perception.stub/tests/perception.c index 91cf7c36589..baa7031b0cf 100644 --- a/dlls/windows.perception.stub/tests/perception.c +++ b/dlls/windows.perception.stub/tests/perception.c @@ -28,6 +28,7 @@ #define WIDL_using_Windows_Foundation #define WIDL_using_Windows_Foundation_Collections #include "windows.foundation.h" +#define WIDL_using_Windows_Perception_Spatial #define WIDL_using_Windows_Perception_Spatial_Surfaces #include "windows.perception.spatial.surfaces.h" #define WIDL_using_Windows_Graphics_Holographic @@ -284,10 +285,102 @@ done: ok( ref == 1, "got ref %ld.\n", ref ); }
+struct status_async_handler +{ + IAsyncOperationCompletedHandler_SpatialPerceptionAccessStatus IAsyncOperationCompletedHandler_SpatialPerceptionAccessStatus_iface; + LONG refcount; + + IAsyncOperation_SpatialPerceptionAccessStatus *async; + AsyncStatus status; + BOOL invoked; + HANDLE event; +}; + +static inline struct status_async_handler *impl_from_IAsyncOperationCompletedHandler_SpatialPerceptionAccessStatus( + IAsyncOperationCompletedHandler_SpatialPerceptionAccessStatus *iface ) +{ + return CONTAINING_RECORD( iface, struct status_async_handler, IAsyncOperationCompletedHandler_SpatialPerceptionAccessStatus_iface ); +} + +static HRESULT WINAPI status_async_handler_QueryInterface( IAsyncOperationCompletedHandler_SpatialPerceptionAccessStatus *iface, + REFIID iid, void **out ) +{ + if (IsEqualGUID( iid, &IID_IUnknown ) || + IsEqualGUID( iid, &IID_IAgileObject ) || + IsEqualGUID( iid, &IID_IAsyncOperationCompletedHandler_SpatialPerceptionAccessStatus )) + { + IUnknown_AddRef( iface ); + *out = iface; + return S_OK; + } + + if (winetest_debug > 1) trace( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) ); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI status_async_handler_AddRef( IAsyncOperationCompletedHandler_SpatialPerceptionAccessStatus *iface ) +{ + struct status_async_handler *impl = impl_from_IAsyncOperationCompletedHandler_SpatialPerceptionAccessStatus( iface ); + return InterlockedIncrement( &impl->refcount ); +} + +static ULONG WINAPI status_async_handler_Release( IAsyncOperationCompletedHandler_SpatialPerceptionAccessStatus *iface ) +{ + struct status_async_handler *impl = impl_from_IAsyncOperationCompletedHandler_SpatialPerceptionAccessStatus( iface ); + ULONG ref = InterlockedDecrement( &impl->refcount ); + if (!ref) free( impl ); + return ref; +} + +static HRESULT WINAPI status_async_handler_Invoke( IAsyncOperationCompletedHandler_SpatialPerceptionAccessStatus *iface, + IAsyncOperation_SpatialPerceptionAccessStatus *async, AsyncStatus status ) +{ + struct status_async_handler *impl = impl_from_IAsyncOperationCompletedHandler_SpatialPerceptionAccessStatus( iface ); + + if (winetest_debug > 1) trace( "iface %p, async %p, status %u\n", iface, async, status ); + + ok( !impl->invoked, "invoked twice\n" ); + impl->invoked = TRUE; + impl->async = async; + impl->status = status; + if (impl->event) SetEvent( impl->event ); + + return S_OK; +} + +static IAsyncOperationCompletedHandler_SpatialPerceptionAccessStatusVtbl status_async_handler_vtbl = +{ + /*** IUnknown methods ***/ + status_async_handler_QueryInterface, + status_async_handler_AddRef, + status_async_handler_Release, + /*** IAsyncOperationCompletedHandler<boolean> methods ***/ + status_async_handler_Invoke, +}; + +static IAsyncOperationCompletedHandler_SpatialPerceptionAccessStatus *status_async_handler_create( HANDLE event ) +{ + struct status_async_handler *impl; + + if (!(impl = calloc( 1, sizeof(*impl) ))) return NULL; + impl->IAsyncOperationCompletedHandler_SpatialPerceptionAccessStatus_iface.lpVtbl = &status_async_handler_vtbl; + impl->event = event; + impl->refcount = 1; + + return &impl->IAsyncOperationCompletedHandler_SpatialPerceptionAccessStatus_iface; +} + static void test_SpatialAnchorExporter(void) { static const WCHAR *class_name = L"Windows.Perception.Spatial.SpatialAnchorExporter"; + IAsyncOperationCompletedHandler_SpatialPerceptionAccessStatus *handler; + IAsyncOperation_SpatialPerceptionAccessStatus *access_status; + struct status_async_handler *handler_impl; + ISpatialAnchorExporterStatics *statics; + SpatialPerceptionAccessStatus status; IActivationFactory *factory; + HANDLE event; HSTRING str; HRESULT hr; LONG ref; @@ -304,6 +397,47 @@ static void test_SpatialAnchorExporter(void) return; }
+ check_interface( factory, &IID_IUnknown, FALSE ); + check_interface( factory, &IID_IInspectable, FALSE ); + check_interface( factory, &IID_IAgileObject, FALSE ); + check_interface( factory, &IID_ISpatialAnchorExporterStatics, TRUE /* broken on Testbot Win1607 */ ); + + hr = IActivationFactory_QueryInterface( factory, &IID_ISpatialAnchorExporterStatics, (void **)&statics ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + + hr = ISpatialAnchorExporterStatics_RequestAccessAsync( statics, &access_status ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + + handler = (void *)0xdeadbeef; + hr = IAsyncOperation_SpatialPerceptionAccessStatus_get_Completed( access_status, &handler ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + ok( !handler, "got %p.\n", handler ); + + event = CreateEventW( NULL, FALSE, FALSE, NULL ); + handler = status_async_handler_create( event ); + hr = IAsyncOperation_SpatialPerceptionAccessStatus_put_Completed( access_status, handler ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + + handler_impl = impl_from_IAsyncOperationCompletedHandler_SpatialPerceptionAccessStatus( handler ); + if (!handler_impl->invoked) + { + /* Looks like it normally completes at once on Win11, while on some Win10 Testbot machines it doesn't. */ + WaitForSingleObject( event, INFINITE ); + } + CloseHandle( event ); + ok( handler_impl->invoked, "handler not invoked.\n" ); + ok( handler_impl->async == access_status, "got %p, %p.\n", handler_impl->async, access_status ); + ok( handler_impl->status == Completed, "got %d.\n", handler_impl->status ); + IAsyncOperationCompletedHandler_SpatialPerceptionAccessStatus_Release( handler ); + + hr = IAsyncOperation_SpatialPerceptionAccessStatus_GetResults( access_status, &status ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + ok( status == SpatialPerceptionAccessStatus_DeniedBySystem, "got %d.\n", status ); + + ref = IAsyncOperation_SpatialPerceptionAccessStatus_Release( access_status ); + ok( !ref, "got %ld.\n", ref ); + + ISpatialAnchorExporterStatics_Release( statics ); ref = IActivationFactory_Release( factory ); ok( ref == 1, "got ref %ld.\n", ref ); }
From: Paul Gofman pgofman@codeweavers.com
--- dlls/windows.perception.stub/anchor.c | 68 +++++++++++++++++++ .../tests/perception.c | 14 ++++ 2 files changed, 82 insertions(+)
diff --git a/dlls/windows.perception.stub/anchor.c b/dlls/windows.perception.stub/anchor.c index 3d3ff4a4268..e4c88358b73 100644 --- a/dlls/windows.perception.stub/anchor.c +++ b/dlls/windows.perception.stub/anchor.c @@ -120,9 +120,69 @@ static const struct IActivationFactoryVtbl factory_vtbl = struct async_access_status { IAsyncOperation_SpatialPerceptionAccessStatus IAsyncOperation_SpatialPerceptionAccessStatus_iface; + IAsyncInfo IAsyncInfo_iface; LONG ref; };
+DEFINE_IINSPECTABLE(async_info, IAsyncInfo, struct async_access_status, IAsyncOperation_SpatialPerceptionAccessStatus_iface) + +static HRESULT WINAPI async_info_get_Id( IAsyncInfo *iface, UINT32 *id ) +{ + TRACE( "iface %p, id %p.\n", iface, id ); + + *id = 1; + return S_OK; +} + +static HRESULT WINAPI async_info_get_Status( IAsyncInfo *iface, AsyncStatus *status ) +{ + TRACE( "iface %p, status %p.\n", iface, status ); + + *status = Completed; + return S_OK; +} + +static HRESULT WINAPI async_info_get_ErrorCode( IAsyncInfo *iface, HRESULT *error_code ) +{ + TRACE( "iface %p, error_code %p.\n", iface, error_code ); + + *error_code = S_OK; + return S_OK; +} + +static HRESULT WINAPI async_info_Cancel( IAsyncInfo *iface ) +{ + FIXME( "iface %p.\n", iface ); + + return S_OK; +} + +static HRESULT WINAPI async_info_Close( IAsyncInfo *iface ) +{ + FIXME( "iface %p.\n", iface ); + + return S_OK; +} + +static const struct IAsyncInfoVtbl async_info_vtbl = +{ + /* IUnknown methods */ + async_info_QueryInterface, + async_info_AddRef, + async_info_Release, + /* IInspectable methods */ + async_info_GetIids, + async_info_GetRuntimeClassName, + async_info_GetTrustLevel, + /* IAsyncInfo */ + async_info_get_Id, + async_info_get_Status, + async_info_get_ErrorCode, + async_info_Cancel, + async_info_Close, +}; + + static inline struct async_access_status *impl_from_IAsyncOperation_SpatialPerceptionAccessStatus( IAsyncOperation_SpatialPerceptionAccessStatus *iface ) { return CONTAINING_RECORD( iface, struct async_access_status, IAsyncOperation_SpatialPerceptionAccessStatus_iface ); @@ -143,6 +203,13 @@ static HRESULT WINAPI async_SpatialPerceptionAccessStatus_QueryInterface( IAsync return S_OK; }
+ if (IsEqualGUID( iid, &IID_IAsyncInfo )) + { + *out = &impl->IAsyncInfo_iface; + IAsyncInfo_AddRef( &impl->IAsyncInfo_iface ); + return S_OK; + } + FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) ); *out = NULL; return E_NOINTERFACE; @@ -238,6 +305,7 @@ static HRESULT async_operation_SpatialPerceptionAccessStatus_create( IAsyncOpera *out = NULL; if (!(impl = calloc( 1, sizeof(*impl) ))) return E_OUTOFMEMORY; impl->IAsyncOperation_SpatialPerceptionAccessStatus_iface.lpVtbl = &async_SpatialPerceptionAccessStatus_vtbl; + impl->IAsyncInfo_iface.lpVtbl = &async_info_vtbl; impl->ref = 1;
*out = &impl->IAsyncOperation_SpatialPerceptionAccessStatus_iface; diff --git a/dlls/windows.perception.stub/tests/perception.c b/dlls/windows.perception.stub/tests/perception.c index baa7031b0cf..9ba9441b9e1 100644 --- a/dlls/windows.perception.stub/tests/perception.c +++ b/dlls/windows.perception.stub/tests/perception.c @@ -380,9 +380,12 @@ static void test_SpatialAnchorExporter(void) ISpatialAnchorExporterStatics *statics; SpatialPerceptionAccessStatus status; IActivationFactory *factory; + AsyncStatus astatus; + IAsyncInfo *info; HANDLE event; HSTRING str; HRESULT hr; + UINT32 id; LONG ref;
hr = WindowsCreateString( class_name, wcslen( class_name ), &str ); @@ -434,6 +437,17 @@ static void test_SpatialAnchorExporter(void) ok( hr == S_OK, "got hr %#lx.\n", hr ); ok( status == SpatialPerceptionAccessStatus_DeniedBySystem, "got %d.\n", status );
+ hr = IAsyncOperation_SpatialPerceptionAccessStatus_QueryInterface( access_status, &IID_IAsyncInfo, (void **)&info ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + hr = IAsyncInfo_get_Id( info, &id ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + ok( id == 1, "got %u.\n", id ); + hr = IAsyncInfo_get_Status( info, &astatus ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + ok( astatus == Completed, "got %u.\n", id ); + ref = IAsyncInfo_Release( info ); + ok( ref == 1, "got ref %ld.\n", ref ); + ref = IAsyncOperation_SpatialPerceptionAccessStatus_Release( access_status ); ok( !ref, "got %ld.\n", ref );
Helps Modules game.
Rémi Bernon (@rbernon) commented about dlls/windows.perception.stub/anchor.c:
- async_SpatialPerceptionAccessStatus_GetResults,
+};
+static HRESULT async_operation_SpatialPerceptionAccessStatus_create( IAsyncOperation_SpatialPerceptionAccessStatus **out ) +{
- struct async_access_status *impl;
- *out = NULL;
- if (!(impl = calloc( 1, sizeof(*impl) ))) return E_OUTOFMEMORY;
- impl->IAsyncOperation_SpatialPerceptionAccessStatus_iface.lpVtbl = &async_SpatialPerceptionAccessStatus_vtbl;
- impl->ref = 1;
- *out = &impl->IAsyncOperation_SpatialPerceptionAccessStatus_iface;
- TRACE( "created IAsyncOperation_SpatialPerceptionAccessStatus_iface %p\n", *out );
- return S_OK;
+}
You should probably reuse the async.c helpers that are copied around in other WinRT modules.
On Fri Nov 28 17:49:25 2025 +0000, Rémi Bernon wrote:
You should probably reuse the async.c helpers that are copied around in other WinRT modules.
But those are not copied, they are different between modules. Then, they don't implement specific class IAsyncOperation_SpatialPerceptionAccessStatus, they won't work as is and would be different anyway. Then, they are more complicated and implement real async, they will also require extra code at usage. So, until we have some common winrt support library which could be updated as needed instead of copy-pasting and diverging, I thought this simple class is way better? FWIW I already did the same recently in 84cd975748b8609feb19d9083f6486ebf0720461.
I actually looked a bit to approach instead a generic helper for complete-at-once async which at the same time wouldn't be specific to types which can be just copied. But concluded so far that adding this here is a bit too weird for a little benefit. Needs a helper idl for providing generic IAsyncOperation_; that doesn't work for 'void *' template parameter; could use UINT32 to make it more generic wrapping specified IID for specific async but yet again didn't see much use in generalization while I am using that in one place in this dll and it is not shared for others (so, e. g., I could at once reuse for what 84cd975748b8609feb19d9083f6486ebf0720461 does).
On Fri Nov 28 18:03:04 2025 +0000, Paul Gofman wrote:
But those are not copied, they are different between modules. Then, they don't implement specific class IAsyncOperation_SpatialPerceptionAccessStatus, they won't work as is and would be different anyway. Then, they are more complicated and implement real async, they will also require extra code at usage. So, until we have some common winrt support library which could be updated as needed instead of copy-pasting and diverging, I thought this simple class is way better? FWIW I already did the same recently in 84cd975748b8609feb19d9083f6486ebf0720461. I actually looked a bit to approach instead a generic helper for complete-at-once async which at the same time wouldn't be specific to types which can be just copied. But concluded so far that adding this here is a bit too weird for a little benefit. Needs a helper idl for providing generic IAsyncOperation_; that doesn't work for 'void *' template parameter; could use UINT32 to make it more generic wrapping specified IID for specific async but yet again didn't see much use in generalization while I am using that in one place in this dll and it is not shared for others (so, e. g., I could at once reuse for what 84cd975748b8609feb19d9083f6486ebf0720461 does).
TL; DR; copying and reusing existing async.c (which are more complicated) will add dead code for more generic async handling and will immediately diverge from other copies anyway.
On Fri Nov 28 18:05:23 2025 +0000, Paul Gofman wrote:
TL; DR; copying and reusing existing async.c (which are more complicated) will add dead code for more generic async handling and will immediately diverge from other copies anyway.
The IAsyncInfo implementation is the same, and it's where the complicated details reside. The differences are in the various async operation frontend that need to be different because of different result types.
The IAsyncInfo implementation is the same, and it's where the complicated details reside.
Yes, and none of those complicated details are needed here (since we want just an already-completed async), they are going to be dead code, with additional need to provide proper callbacks. There is seemingly no way even to complete it at once without going through thread pool, without some changes? This simple IAsyncInfo variant is not so much of code, and `IAsyncOperation_SpatialPerceptionAccessStatus` will anyway be different. Do we really need this? Maybe if you see some use in a generic "typesless" synchronous async, I'd rather try to do that one?
On Fri Nov 28 19:01:24 2025 +0000, Paul Gofman wrote:
The IAsyncInfo implementation is the same, and it's where the
complicated details reside. Yes, and none of those complicated details are needed here (since we want just an already-completed async), they are going to be dead code, with additional need to provide proper callbacks. There is seemingly no way even to complete it at once without going through thread pool, without some changes? This simple IAsyncInfo variant is not so much of code, and `IAsyncOperation_SpatialPerceptionAccessStatus` will anyway be different. Do we really need this? Maybe if you see some use in a generic "typesless" synchronous async, I'd rather try to do that one?
I can copy async.c from windows.gaming.input but then modify it so there is the needed IAsyncOperation_SpatialPerceptionAccessStatus, IAsyncOperation_SpatialPerceptionAccessStatusResult and add a parameter to run the callback synchronously. Will it be better?
On Fri Nov 28 19:16:47 2025 +0000, Paul Gofman wrote:
I can copy async.c from windows.gaming.input but then modify it so there is the needed IAsyncOperation_SpatialPerceptionAccessStatus, IAsyncOperation_SpatialPerceptionAccessStatusResult and add a parameter to run the callback synchronously. Will it be better?
The tests have an explicit wait so it doesn't look like they are already completed upon return.
I don't see how it is so much of an issue to make it go through the thread pool when we don't even care about what it does. It's a bit of a waste but nothing really cares and the point is to make future refactoring of the various asyncs, replacing them by common shared code easier.
For the same reason I don't think making changes to the shared code is a good idea, and even if some functions are not called in the context of this module, they are still being called in other module. One could argue on whether it's dead code or not but I think we can live with it as long as it is copied pristine.
The tests have an explicit wait so it doesn't look like they are already completed upon return.
That's to help Testbot with old Win10's. On Win11 they are completed at once, I separately tested that Invoke is called from the same thread id which sets the handler, quite reliably here. If you think that helps, I can adapt the test to mark the wait case as broken and test a bit more details for the modern Windows path.
Introducing more complicated functioning with routing the completion truely async which has potential of breaking stuff because apps may not account for real async when it is always sync on Windows doesn't seem to be the right way? I wouldn't like to do that. I think it is rather common patter in WinRT to use IAsyncOperation wrappers to uniformly wrap what is actually always sync. Like in windows.media.speech in commit 84cd975748b8609feb19d9083f6486ebf0720461 where all the actual handling has been done async already and that status is always ready when async result can be requested.
On Fri Nov 28 19:42:50 2025 +0000, Paul Gofman wrote:
The tests have an explicit wait so it doesn't look like they are
already completed upon return. That's to help Testbot with old Win10's. On Win11 they are completed at once, I separately tested that Invoke is called from the same thread id which sets the handler, quite reliably here. If you think that helps, I can adapt the test to mark the wait case as broken and test a bit more details for the modern Windows path. Introducing more complicated functioning with routing the completion truely async which has potential of breaking stuff because apps may not account for real async when it is always sync on Windows doesn't seem to be the right way? I wouldn't like to do that. I think it is rather common patter in WinRT to use IAsyncOperation wrappers to uniformly wrap what is actually always sync. Like in windows.media.speech in commit 84cd975748b8609feb19d9083f6486ebf0720461 where all the actual handling has been done async already and that status is always ready when async result can be requested.
Instead of explicit new parameter for IAsyncOperation creation, the functional callback may be generalized to be always called before queueing with a flag and return some STATUS_PENDING if it doesn't assume to be run sync.
On Fri Nov 28 19:45:16 2025 +0000, Paul Gofman wrote:
Instead of explicit new parameter for IAsyncOperation creation, the functional callback may be generalized to be always called before queueing with a flag and return some STATUS_PENDING if it doesn't assume to be run sync.
And IIRC in windows.speech case the app motivated 84cd975748b8609feb19d9083f6486ebf0720461 doesn't even do anything to wait for the async result and proceedes to GetResults() at once. Introducing unndeeded async handling will be breaking such things.
On Fri Nov 28 19:47:23 2025 +0000, Paul Gofman wrote:
And IIRC in windows.speech case the app motivated 84cd975748b8609feb19d9083f6486ebf0720461 doesn't even do anything to wait for the async result and proceedes to GetResults() at once. Introducing unndeeded async handling will be breaking such things.
Well, idk. IMO it's not a good thing to spread semi-stubbed async implementations around when they are all supposed to be implemented based on some common templates.
If our shared code isn't capable of creating completed asyncs maybe it should be added, but it should probably be added everywhere and given the number of duplicates already that doesn't sound very exciting.
In this particular case I don't think we consider Win10 as an old and unsupported Windows version already, and so making the async go through the threadpool seems acceptable to me.
On Fri Nov 28 20:28:01 2025 +0000, Rémi Bernon wrote:
Well, idk. IMO it's not a good thing to spread semi-stubbed async implementations around when they are all supposed to be implemented based on some common templates. If our shared code isn't capable of creating completed asyncs maybe it should be added, but it should probably be added everywhere and given the number of duplicates already that doesn't sound very exciting. In this particular case I don't think we consider Win10 as an old and unsupported Windows version already, and so making the async go through the threadpool seems acceptable to me.
I can add similar interface change (adding a possibility to complete async) throughout the other instances of async.c if you think it is better. I can also change windows.speech thing to use the same. Will that help?
But honestly I don't want to add the wrong way of completing request, it is a way to not immediately obvious (as sync-related) bugs. If we have the choice between old behaviour and new one we should be prefering newer. It is not really more complicated in this case, rather the opposite, the only complication is that existing wrapper doesn't support it and I believe we'd be better off fixing that instead.
On Fri Nov 28 20:34:17 2025 +0000, Paul Gofman wrote:
I can add similar interface change (adding a possibility to complete async) throughout the other instances of async.c if you think it is better. I can also change windows.speech thing to use the same. Will that help? But honestly I don't want to add the wrong way of completing request, it is a way to not immediately obvious (as sync-related) bugs. If we have the choice between old behaviour and new one we should be prefering newer. It is not really more complicated in this case, rather the opposite, the only complication is that existing wrapper doesn't support it and I believe we'd be better off fixing that instead.
FWIW there are currently only 5 related async.c files in the codebase (the other bunch are thankfully unrelated, like ws2_32/async.c). And one of those in windows.media.speech already needs the same if we go the route of firmly reusing async.c's IAsyncInfo implementation (the test there firmly assumes synchronous completion and an app already depends on that).
On Fri Nov 28 20:50:20 2025 +0000, Paul Gofman wrote:
FWIW there are currently only 5 related async.c files in the codebase (the other bunch are thankfully unrelated, like ws2_32/async.c). And one of those in windows.media.speech already needs the same if we go the route of firmly reusing async.c's IAsyncInfo implementation (the test there firmly assumes synchronous completion and an app already depends on that).
Uh, and in windows.media.speech the async helper doesn't fit in anyway, because there is IAsyncOperationWithProgress instead of IAsyncOperation and that would require yet another addition to handle that in general. All that contributes to my impression that trying to keep those common places synchronized while we don't have a single common library to just update and add things there is a bit counterproductive. But I am still going make a change to make sync completion possible in async.c throughout the modules.