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 ); }