-- v2: windows.gaming.ui.gamebar: Add IGameBarStatics interface. windows.gaming.ui.gamebar: Add stub DLL. include: Add windows.gaming.ui.idl.
From: Paul Gofman pgofman@codeweavers.com
--- include/Makefile.in | 1 + include/windows.gaming.ui.idl | 57 +++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 include/windows.gaming.ui.idl
diff --git a/include/Makefile.in b/include/Makefile.in index 28ac4b3f2dc..6083fd2754d 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -800,6 +800,7 @@ SOURCES = \ windows.gaming.input.custom.idl \ windows.gaming.input.forcefeedback.idl \ windows.gaming.input.idl \ + windows.gaming.ui.idl \ windows.globalization.idl \ windows.h \ windows.media.closedcaptioning.idl \ diff --git a/include/windows.gaming.ui.idl b/include/windows.gaming.ui.idl new file mode 100644 index 00000000000..fc7e661ccf9 --- /dev/null +++ b/include/windows.gaming.ui.idl @@ -0,0 +1,57 @@ +/* + * Copyright 2022 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 + */ + +#ifdef __WIDL__ +#pragma winrt ns_prefix +#endif + +#ifndef DO_NO_IMPORTS +import "inspectable.idl"; +import "eventtoken.idl"; +import "windowscontracts.idl"; +import "windows.foundation.idl"; +#endif + +namespace Windows.Gaming.UI { + runtimeclass GameBar; + + [ + contract(Windows.Foundation.UniversalApiContract, 2.0), + exclusiveto(Windows.Gaming.UI.GameBar), + uuid(1db9a292-cc78-4173-be45-b61e67283ea7) + ] + interface IGameBarStatics : IInspectable + { + [eventadd] HRESULT VisibilityChanged([in] Windows.Foundation.EventHandler<IInspectable *> *handler, [out, retval] EventRegistrationToken *token); + [eventremove] HRESULT VisibilityChanged([in] EventRegistrationToken token); + [eventadd] HRESULT IsInputRedirectedChanged([in] Windows.Foundation.EventHandler<IInspectable *> *handler, [out, retval] EventRegistrationToken *token); + [eventremove] HRESULT IsInputRedirectedChanged([in] EventRegistrationToken token); + [propget] HRESULT Visible([out, retval] boolean *value); + [propget] HRESULT IsInputRedirected([out, retval] boolean *value); + } + + [ + contract(Windows.Foundation.UniversalApiContract, 2.0), + marshaling_behavior(agile), + static(Windows.Gaming.UI.IGameBarStatics, Windows.Foundation.UniversalApiContract, 2.0), + threading(both) + ] + runtimeclass GameBar + { + } +}
From: Paul Gofman pgofman@codeweavers.com
--- configure.ac | 2 + dlls/windows.gaming.ui.gamebar/Makefile.in | 8 + dlls/windows.gaming.ui.gamebar/classes.idl | 33 ++++ dlls/windows.gaming.ui.gamebar/main.c | 153 ++++++++++++++++++ dlls/windows.gaming.ui.gamebar/private.h | 31 ++++ .../tests/Makefile.in | 5 + .../windows.gaming.ui.gamebar/tests/gamebar.c | 83 ++++++++++ .../windows.gaming.ui.gamebar.spec | 3 + 8 files changed, 318 insertions(+) create mode 100644 dlls/windows.gaming.ui.gamebar/Makefile.in create mode 100644 dlls/windows.gaming.ui.gamebar/classes.idl create mode 100644 dlls/windows.gaming.ui.gamebar/main.c create mode 100644 dlls/windows.gaming.ui.gamebar/private.h create mode 100644 dlls/windows.gaming.ui.gamebar/tests/Makefile.in create mode 100644 dlls/windows.gaming.ui.gamebar/tests/gamebar.c create mode 100644 dlls/windows.gaming.ui.gamebar/windows.gaming.ui.gamebar.spec
diff --git a/configure.ac b/configure.ac index 8295ce4c09c..2907dbd7d84 100644 --- a/configure.ac +++ b/configure.ac @@ -3198,6 +3198,8 @@ WINE_CONFIG_MAKEFILE(dlls/windows.devices.enumeration) WINE_CONFIG_MAKEFILE(dlls/windows.devices.enumeration/tests) WINE_CONFIG_MAKEFILE(dlls/windows.gaming.input) WINE_CONFIG_MAKEFILE(dlls/windows.gaming.input/tests) +WINE_CONFIG_MAKEFILE(dlls/windows.gaming.ui.gamebar) +WINE_CONFIG_MAKEFILE(dlls/windows.gaming.ui.gamebar/tests) WINE_CONFIG_MAKEFILE(dlls/windows.globalization) WINE_CONFIG_MAKEFILE(dlls/windows.globalization/tests) WINE_CONFIG_MAKEFILE(dlls/windows.media.devices) diff --git a/dlls/windows.gaming.ui.gamebar/Makefile.in b/dlls/windows.gaming.ui.gamebar/Makefile.in new file mode 100644 index 00000000000..a0eefc4b951 --- /dev/null +++ b/dlls/windows.gaming.ui.gamebar/Makefile.in @@ -0,0 +1,8 @@ +MODULE = windows.gaming.ui.gamebar.dll +IMPORTS = combase uuid + +C_SRCS = \ + main.c + +IDL_SRCS = \ + classes.idl diff --git a/dlls/windows.gaming.ui.gamebar/classes.idl b/dlls/windows.gaming.ui.gamebar/classes.idl new file mode 100644 index 00000000000..ef10fcb6283 --- /dev/null +++ b/dlls/windows.gaming.ui.gamebar/classes.idl @@ -0,0 +1,33 @@ +/* + * Runtime Classes for windows.gaming.ui.gamebar.dll + * + * Copyright 2022 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 + */ + +#pragma makedep register + +#ifdef __WIDL__ +#pragma winrt ns_prefix +#endif + +import "inspectable.idl"; +import "eventtoken.idl"; +import "windowscontracts.idl"; +import "windows.foundation.idl"; + +#define DO_NO_IMPORTS +#include "windows.gaming.ui.idl" diff --git a/dlls/windows.gaming.ui.gamebar/main.c b/dlls/windows.gaming.ui.gamebar/main.c new file mode 100644 index 00000000000..517a96bcc23 --- /dev/null +++ b/dlls/windows.gaming.ui.gamebar/main.c @@ -0,0 +1,153 @@ +/* WinRT Windows.Gaming.UI.GameBar implementation + * + * Copyright 2022 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 "initguid.h" +#include "private.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(gamebar); + +struct gamebar_statics +{ + IActivationFactory IActivationFactory_iface; + LONG ref; +}; + +static inline struct gamebar_statics *impl_from_IActivationFactory( IActivationFactory *iface ) +{ + return CONTAINING_RECORD( iface, struct gamebar_statics, IActivationFactory_iface ); +} + +static HRESULT WINAPI factory_QueryInterface( IActivationFactory *iface, REFIID iid, void **out ) +{ + struct gamebar_statics *impl = impl_from_IActivationFactory( iface ); + + TRACE( "iface %p, iid %s, out %p.\n", iface, debugstr_guid( iid ), out ); + + if (IsEqualGUID( iid, &IID_IUnknown ) || + IsEqualGUID( iid, &IID_IInspectable ) || + IsEqualGUID( iid, &IID_IAgileObject ) || + IsEqualGUID( iid, &IID_IActivationFactory )) + { + *out = &impl->IActivationFactory_iface; + IInspectable_AddRef( *out ); + return S_OK; + } + + FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) ); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI factory_AddRef( IActivationFactory *iface ) +{ + struct gamebar_statics *impl = impl_from_IActivationFactory( iface ); + ULONG ref = InterlockedIncrement( &impl->ref ); + TRACE( "iface %p increasing refcount to %lu.\n", iface, ref ); + return ref; +} + +static ULONG WINAPI factory_Release( IActivationFactory *iface ) +{ + struct gamebar_statics *impl = impl_from_IActivationFactory( iface ); + ULONG ref = InterlockedDecrement( &impl->ref ); + TRACE( "iface %p decreasing refcount to %lu.\n", iface, ref ); + return ref; +} + +static HRESULT WINAPI factory_GetIids( IActivationFactory *iface, ULONG *iid_count, IID **iids ) +{ + FIXME( "iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids ); + return E_NOTIMPL; +} + +static HRESULT WINAPI factory_GetRuntimeClassName( IActivationFactory *iface, HSTRING *class_name ) +{ + FIXME( "iface %p, class_name %p stub!\n", iface, class_name ); + return E_NOTIMPL; +} + +static HRESULT WINAPI factory_GetTrustLevel( IActivationFactory *iface, TrustLevel *trust_level ) +{ + FIXME( "iface %p, trust_level %p stub!\n", iface, trust_level ); + return E_NOTIMPL; +} + +static 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 gamebar_statics gamebar_statics = +{ + {&factory_vtbl}, + 1, +}; + +static IActivationFactory *gamebar_factory = &gamebar_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 class_str, IActivationFactory **factory ) +{ + const WCHAR *buffer = WindowsGetStringRawBuffer( class_str, NULL ); + + TRACE( "class %s, factory %p.\n", debugstr_w(buffer), factory ); + + *factory = NULL; + + if (!wcscmp( buffer, RuntimeClass_Windows_Gaming_UI_GameBar )) + IActivationFactory_QueryInterface( gamebar_factory, &IID_IActivationFactory, (void **)factory ); + + if (*factory) return S_OK; + return CLASS_E_CLASSNOTAVAILABLE; +} + +BOOL WINAPI DllMain( HINSTANCE instance, DWORD reason, void *reserved ) +{ + TRACE( "instance %p, reason %lu, reserved %p.\n", instance, reason, reserved ); + + switch (reason) + { + case DLL_PROCESS_ATTACH: + DisableThreadLibraryCalls( instance ); + break; + } + return TRUE; +} diff --git a/dlls/windows.gaming.ui.gamebar/private.h b/dlls/windows.gaming.ui.gamebar/private.h new file mode 100644 index 00000000000..545f4a2fd24 --- /dev/null +++ b/dlls/windows.gaming.ui.gamebar/private.h @@ -0,0 +1,31 @@ +/* WinRT Windows.Gaming.UI.GameBar implementation + * + * Copyright 2022 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 <stdarg.h> +#include <stddef.h> + +#define COBJMACROS +#include "windef.h" +#include "winbase.h" +#include "winstring.h" + +#define WIDL_using_Windows_Foundation +#define WIDL_using_Windows_Gaming_UI +#include "activation.h" +#include "windows.gaming.ui.h" diff --git a/dlls/windows.gaming.ui.gamebar/tests/Makefile.in b/dlls/windows.gaming.ui.gamebar/tests/Makefile.in new file mode 100644 index 00000000000..67d70eee241 --- /dev/null +++ b/dlls/windows.gaming.ui.gamebar/tests/Makefile.in @@ -0,0 +1,5 @@ +TESTDLL = windows.gaming.ui.gamebar.dll +IMPORTS = combase + +C_SRCS = \ + gamebar.c diff --git a/dlls/windows.gaming.ui.gamebar/tests/gamebar.c b/dlls/windows.gaming.ui.gamebar/tests/gamebar.c new file mode 100644 index 00000000000..503e0809157 --- /dev/null +++ b/dlls/windows.gaming.ui.gamebar/tests/gamebar.c @@ -0,0 +1,83 @@ +/* + * Copyright 2022 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 + */ +#define COBJMACROS +#include "initguid.h" +#include <stdarg.h> + +#include "windef.h" +#include "winbase.h" +#include "winerror.h" +#include "winstring.h" + +#include "roapi.h" + +#define WIDL_using_Windows_Foundation +#define WIDL_using_Windows_Gaming_UI +#include "windows.foundation.h" +#include "windows.gaming.ui.h" + +#include "wine/test.h" + +static void test_GameBarStatics(void) +{ + static const WCHAR *gamebar_statics_name = L"Windows.Gaming.UI.GameBar"; + + IActivationFactory *factory = NULL; + IInspectable *inspectable = NULL; + IAgileObject *agile_object = NULL; + HSTRING str; + HRESULT hr; + LONG ref; + + hr = WindowsCreateString(gamebar_statics_name, wcslen(gamebar_statics_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(gamebar_statics_name)); + return; + } + + hr = IActivationFactory_QueryInterface(factory, &IID_IInspectable, (void **)&inspectable); + ok(hr == S_OK, "got hr %#lx.\n", hr); + + hr = IActivationFactory_QueryInterface(factory, &IID_IAgileObject, (void **)&agile_object); + ok(hr == S_OK, "got hr %#lx.\n", hr); + + ref = IAgileObject_Release(agile_object); + ok(ref == 3, "got ref %ld.\n", ref); + ref = IInspectable_Release(inspectable); + ok(ref == 2, "got ref %ld.\n", ref); + ref = IActivationFactory_Release(factory); + ok(ref == 1, "got ref %ld.\n", ref); +} + +START_TEST(gamebar) +{ + HRESULT hr; + + hr = RoInitialize(RO_INIT_MULTITHREADED); + ok(hr == S_OK, "RoInitialize failed, hr %#lx\n", hr); + + test_GameBarStatics(); + + RoUninitialize(); +} diff --git a/dlls/windows.gaming.ui.gamebar/windows.gaming.ui.gamebar.spec b/dlls/windows.gaming.ui.gamebar/windows.gaming.ui.gamebar.spec new file mode 100644 index 00000000000..20a8bfa98ea --- /dev/null +++ b/dlls/windows.gaming.ui.gamebar/windows.gaming.ui.gamebar.spec @@ -0,0 +1,3 @@ +@ stdcall -private DllCanUnloadNow() +@ stdcall -private DllGetActivationFactory(ptr ptr) +@ stdcall -private DllGetClassObject(ptr ptr ptr)
From: Paul Gofman pgofman@codeweavers.com
--- dlls/windows.gaming.ui.gamebar/main.c | 79 +++++++++++++++++++ dlls/windows.gaming.ui.gamebar/private.h | 38 +++++++++ .../windows.gaming.ui.gamebar/tests/gamebar.c | 35 +++++++- 3 files changed, 148 insertions(+), 4 deletions(-)
diff --git a/dlls/windows.gaming.ui.gamebar/main.c b/dlls/windows.gaming.ui.gamebar/main.c index 517a96bcc23..91086395ecf 100644 --- a/dlls/windows.gaming.ui.gamebar/main.c +++ b/dlls/windows.gaming.ui.gamebar/main.c @@ -24,9 +24,12 @@
WINE_DEFAULT_DEBUG_CHANNEL(gamebar);
+static EventRegistrationToken dummy_token = {.value = 0xdeadbeef}; + struct gamebar_statics { IActivationFactory IActivationFactory_iface; + IGameBarStatics IGameBarStatics_iface; LONG ref; };
@@ -51,6 +54,13 @@ static HRESULT WINAPI factory_QueryInterface( IActivationFactory *iface, REFIID return S_OK; }
+ if (IsEqualGUID( iid, &IID_IGameBarStatics )) + { + *out = &impl->IGameBarStatics_iface; + IInspectable_AddRef( *out ); + return S_OK; + } + FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) ); *out = NULL; return E_NOINTERFACE; @@ -109,9 +119,78 @@ static const struct IActivationFactoryVtbl factory_vtbl = factory_ActivateInstance, };
+DEFINE_IINSPECTABLE( statics, IGameBarStatics, struct gamebar_statics, IActivationFactory_iface ) + +static HRESULT WINAPI statics_add_VisibilityChanged( IGameBarStatics *iface, + IEventHandler_IInspectable *handler, + EventRegistrationToken *token ) +{ + FIXME( "iface %p, handler %p, token %p stub.\n", iface, handler, token ); + *token = dummy_token; + return S_OK; +} + +static HRESULT WINAPI statics_remove_VisibilityChanged( IGameBarStatics *iface, EventRegistrationToken token ) +{ + FIXME( "iface %p, token %#I64x stub.\n", iface, token.value ); + return S_OK; +} + +static HRESULT WINAPI statics_add_IsInputRedirectedChanged( IGameBarStatics *iface, + IEventHandler_IInspectable *handler, + EventRegistrationToken *token ) +{ + FIXME( "iface %p, handler %p, token %p stub.\n", iface, handler, token ); + *token = dummy_token; + return S_OK; +} + +static HRESULT WINAPI statics_remove_IsInputRedirectedChanged( IGameBarStatics *iface, EventRegistrationToken token ) +{ + FIXME( "iface %p, token %#I64x stub.\n", iface, token.value ); + return S_OK; +} + +static HRESULT WINAPI statics_get_Visible( IGameBarStatics *iface, BOOLEAN *value) +{ + TRACE( "iface %p, value %p.\n", iface, value ); + + if (!value) return E_INVALIDARG; + *value = FALSE; + return S_OK; +} + +static HRESULT WINAPI statics_get_IsInputRedirected( IGameBarStatics *iface, BOOLEAN *value ) +{ + TRACE( "iface %p, value %p.\n", iface, value ); + + if (!value) return E_INVALIDARG; + *value = FALSE; + return S_OK; +} + +static const struct IGameBarStaticsVtbl statics_vtbl = +{ + statics_QueryInterface, + statics_AddRef, + statics_Release, + /* IInspectable methods */ + statics_GetIids, + statics_GetRuntimeClassName, + statics_GetTrustLevel, + /* IGameBarStatics methods */ + statics_add_VisibilityChanged, + statics_remove_VisibilityChanged, + statics_add_IsInputRedirectedChanged, + statics_remove_IsInputRedirectedChanged, + statics_get_Visible, + statics_get_IsInputRedirected, +}; + static struct gamebar_statics gamebar_statics = { {&factory_vtbl}, + {&statics_vtbl}, 1, };
diff --git a/dlls/windows.gaming.ui.gamebar/private.h b/dlls/windows.gaming.ui.gamebar/private.h index 545f4a2fd24..85f87b56e7b 100644 --- a/dlls/windows.gaming.ui.gamebar/private.h +++ b/dlls/windows.gaming.ui.gamebar/private.h @@ -29,3 +29,41 @@ #define WIDL_using_Windows_Gaming_UI #include "activation.h" #include "windows.gaming.ui.h" + +#define DEFINE_IINSPECTABLE_( pfx, iface_type, impl_type, impl_from, iface_mem, expr ) \ + static inline impl_type *impl_from( iface_type *iface ) \ + { \ + return CONTAINING_RECORD( iface, impl_type, iface_mem ); \ + } \ + static HRESULT WINAPI pfx##_QueryInterface( iface_type *iface, REFIID iid, void **out ) \ + { \ + impl_type *impl = impl_from( iface ); \ + return IInspectable_QueryInterface( (IInspectable *)(expr), iid, out ); \ + } \ + static ULONG WINAPI pfx##_AddRef( iface_type *iface ) \ + { \ + impl_type *impl = impl_from( iface ); \ + return IInspectable_AddRef( (IInspectable *)(expr) ); \ + } \ + static ULONG WINAPI pfx##_Release( iface_type *iface ) \ + { \ + impl_type *impl = impl_from( iface ); \ + return IInspectable_Release( (IInspectable *)(expr) ); \ + } \ + static HRESULT WINAPI pfx##_GetIids( iface_type *iface, ULONG *iid_count, IID **iids ) \ + { \ + impl_type *impl = impl_from( iface ); \ + return IInspectable_GetIids( (IInspectable *)(expr), iid_count, iids ); \ + } \ + static HRESULT WINAPI pfx##_GetRuntimeClassName( iface_type *iface, HSTRING *class_name ) \ + { \ + impl_type *impl = impl_from( iface ); \ + return IInspectable_GetRuntimeClassName( (IInspectable *)(expr), class_name ); \ + } \ + static HRESULT WINAPI pfx##_GetTrustLevel( iface_type *iface, TrustLevel *trust_level ) \ + { \ + impl_type *impl = impl_from( iface ); \ + return IInspectable_GetTrustLevel( (IInspectable *)(expr), trust_level ); \ + } +#define DEFINE_IINSPECTABLE( pfx, iface_type, impl_type, base_iface ) \ + DEFINE_IINSPECTABLE_( pfx, iface_type, impl_type, impl_from_##iface_type, iface_type##_iface, &impl->base_iface ) diff --git a/dlls/windows.gaming.ui.gamebar/tests/gamebar.c b/dlls/windows.gaming.ui.gamebar/tests/gamebar.c index 503e0809157..a68d4619362 100644 --- a/dlls/windows.gaming.ui.gamebar/tests/gamebar.c +++ b/dlls/windows.gaming.ui.gamebar/tests/gamebar.c @@ -38,8 +38,10 @@ static void test_GameBarStatics(void) static const WCHAR *gamebar_statics_name = L"Windows.Gaming.UI.GameBar";
IActivationFactory *factory = NULL; - IInspectable *inspectable = NULL; - IAgileObject *agile_object = NULL; + IInspectable *inspectable = NULL, *tmp_inspectable = NULL; + IAgileObject *agile_object = NULL, *tmp_agile_object = NULL; + IGameBarStatics *gamebar_statics = NULL; + BOOLEAN value; HSTRING str; HRESULT hr; LONG ref; @@ -62,11 +64,36 @@ static void test_GameBarStatics(void) hr = IActivationFactory_QueryInterface(factory, &IID_IAgileObject, (void **)&agile_object); ok(hr == S_OK, "got hr %#lx.\n", hr);
+ hr = IActivationFactory_QueryInterface(factory, &IID_IGameBarStatics, (void **)&gamebar_statics); + ok(hr == S_OK, "got hr %#lx.\n", hr); + + hr = IGameBarStatics_QueryInterface(gamebar_statics, &IID_IInspectable, (void **)&tmp_inspectable); + ok(hr == S_OK, "got hr %#lx.\n", hr); + ok(tmp_inspectable == inspectable, "got %p, expected %p.\n", tmp_inspectable, inspectable); + IInspectable_Release(tmp_inspectable); + + hr = IGameBarStatics_QueryInterface(gamebar_statics, &IID_IAgileObject, (void **)&tmp_agile_object); + ok(hr == S_OK, "got hr %#lx.\n", hr); + ok(tmp_agile_object == agile_object, "got %p, expected %p.\n", tmp_agile_object, agile_object); + IAgileObject_Release(tmp_agile_object); + + value = TRUE; + hr = IGameBarStatics_get_Visible(gamebar_statics, &value); + ok(hr == S_OK, "got hr %#lx.\n", hr); + ok(!value, "got %d.\n", value); + + value = TRUE; + hr = IGameBarStatics_get_IsInputRedirected(gamebar_statics, &value); + ok(hr == S_OK, "got hr %#lx.\n", hr); + ok(!value, "got %d.\n", value); + ref = IAgileObject_Release(agile_object); - ok(ref == 3, "got ref %ld.\n", ref); + ok(ref == 4, "got ref %ld.\n", ref); ref = IInspectable_Release(inspectable); - ok(ref == 2, "got ref %ld.\n", ref); + ok(ref == 3, "got ref %ld.\n", ref); ref = IActivationFactory_Release(factory); + ok(ref == 2, "got ref %ld.\n", ref); + ref = IGameBarStatics_Release(gamebar_statics); ok(ref == 1, "got ref %ld.\n", ref); }
v2: - [out] [retva] -> [out, retval]; - IInspectable_AddRef( (*out = &impl->IGameBarStatics_iface) ) in factory_QueryInterface() -> move assignment out of macro argument.
On Thu Nov 3 18:21:40 2022 +0000, **** wrote:
Paul Gofman replied on the mailing list:
On 11/3/22 12:10, Paul Gofman wrote: > On 11/3/22 12:01, Bernhard Kölbl (@besentv) wrote: >> Bernhard Kölbl (@besentv) commented about >> dlls/windows.gaming.ui.gamebar/main.c: >>> return S_OK; >>> } >>> + if (IsEqualGUID( iid, &IID_IGameBarStatics )) >>> + { >>> + *out = &impl->IGameBarStatics_iface; >>> + IInspectable_AddRef( *out ); >> You could probably make this a one-liner as well, like in line 52. >> > TBH I intentionally removed it (and missed in line 52) as in general I > think assignment in a function call argument used to be considered a > bad practice in Wine. Unless anyone feels striong about it I'd rather > change it in line 52. > > Actually, IInspectable_AddRef is a macro, which gives more reasons to avoid assignment in the argument as a general practice.
Idk, we already did it a bunch of times so far, let's leave it up to Rémi.
On 11/3/22 12:24, Bernhard Kölbl (@besentv) wrote:
On Thu Nov 3 18:21:40 2022 +0000, **** wrote:
Paul Gofman replied on the mailing list:
On 11/3/22 12:10, Paul Gofman wrote: > On 11/3/22 12:01, Bernhard Kölbl (@besentv) wrote: >> Bernhard Kölbl (@besentv) commented about >> dlls/windows.gaming.ui.gamebar/main.c: >>> return S_OK; >>> } >>> + if (IsEqualGUID( iid, &IID_IGameBarStatics )) >>> + { >>> + *out = &impl->IGameBarStatics_iface; >>> + IInspectable_AddRef( *out ); >> You could probably make this a one-liner as well, like in line 52. >> > TBH I intentionally removed it (and missed in line 52) as in general I > think assignment in a function call argument used to be considered a > bad practice in Wine. Unless anyone feels striong about it I'd rather > change it in line 52. > > Actually, IInspectable_AddRef is a macro, which gives more reasons to avoid assignment in the argument as a general practice.
Idk, we already did it a bunch of times so far, let's leave it up to Rémi.
Thing is, the macro may (and does so in this specific case) substitue the argument more than once. That means that the statement given as macro argument will be executed multiple times. That is a problem in case when a function call involved in the statement, probably less so if it is an assignment like here. But IMO it is easier and more readable to just avoid such inlining rather than reasoning about what such an inlined statement can legitimately do or what it should not.
On Thu Nov 3 18:31:43 2022 +0000, **** wrote:
Paul Gofman replied on the mailing list:
On 11/3/22 12:24, Bernhard Kölbl (@besentv) wrote: > On Thu Nov 3 18:21:40 2022 +0000, **** wrote: >> Paul Gofman replied on the mailing list: >> \`\`\` >> On 11/3/22 12:10, Paul Gofman wrote: >>> On 11/3/22 12:01, Bernhard Kölbl (@besentv) wrote: >>>> Bernhard Kölbl (@besentv) commented about >>>> dlls/windows.gaming.ui.gamebar/main.c: >>>>> return S_OK; >>>>> } >>>>> + if (IsEqualGUID( iid, &IID_IGameBarStatics )) >>>>> + { >>>>> + *out = &impl->IGameBarStatics_iface; >>>>> + IInspectable_AddRef( *out ); >>>> You could probably make this a one-liner as well, like in line 52. >>>> >>> TBH I intentionally removed it (and missed in line 52) as in general I >>> think assignment in a function call argument used to be considered a >>> bad practice in Wine. Unless anyone feels striong about it I'd rather >>> change it in line 52. >>> >>> >> Actually, IInspectable_AddRef is a macro, which gives more reasons to >> avoid assignment in the argument as a general practice. >> \`\`\` > Idk, we already did it a bunch of times so far, let's leave it up to Rémi. > Thing is, the macro may (and does so in this specific case) substitue the argument more than once. That means that the statement given as macro argument will be executed multiple times. That is a problem in case when a function call involved in the statement, probably less so if it is an assignment like here. But IMO it is easier and more readable to just avoid such inlining rather than reasoning about what such an inlined statement can legitimately do or what it should not.
Personally, I know what "pattern" I want to see in a QI function, and in-lining the assignment removes "reading indirection" in my brain, and gives me a smoother experience. But however you like. :smile:
On 03/11/2022 20:39, Bernhard Kölbl (@besentv) wrote:
On Thu Nov 3 18:31:43 2022 +0000, **** wrote:
Paul Gofman replied on the mailing list:
On 11/3/22 12:24, Bernhard Kölbl (@besentv) wrote: > On Thu Nov 3 18:21:40 2022 +0000, **** wrote: >> Paul Gofman replied on the mailing list: >> \`\`\` >> On 11/3/22 12:10, Paul Gofman wrote: >>> On 11/3/22 12:01, Bernhard Kölbl (@besentv) wrote: >>>> Bernhard Kölbl (@besentv) commented about >>>> dlls/windows.gaming.ui.gamebar/main.c: >>>>> return S_OK; >>>>> } >>>>> + if (IsEqualGUID( iid, &IID_IGameBarStatics )) >>>>> + { >>>>> + *out = &impl->IGameBarStatics_iface; >>>>> + IInspectable_AddRef( *out ); >>>> You could probably make this a one-liner as well, like in line 52. >>>> >>> TBH I intentionally removed it (and missed in line 52) as in general I >>> think assignment in a function call argument used to be considered a >>> bad practice in Wine. Unless anyone feels striong about it I'd rather >>> change it in line 52. >>> >>> >> Actually, IInspectable_AddRef is a macro, which gives more reasons to >> avoid assignment in the argument as a general practice. >> \`\`\` > Idk, we already did it a bunch of times so far, let's leave it up to Rémi. > Thing is, the macro may (and does so in this specific case) substitue the argument more than once. That means that the statement given as macro argument will be executed multiple times. That is a problem in case when a function call involved in the statement, probably less so if it is an assignment like here. But IMO it is easier and more readable to just avoid such inlining rather than reasoning about what such an inlined statement can legitimately do or what it should not.
Personally, I know what "pattern" I want to see in a QI function, and in-lining the assignment removes "reading indirection" in my brain, and gives me a smoother experience. But however you like. :smile:
I usually prefer them on one line where possible, especially when there's a lot of repetitive boilerplate around, makes it easier to read through relevant parts of the code.
Rémi Bernon (@rbernon) commented about dlls/windows.gaming.ui.gamebar/tests/gamebar.c:
- ok(ref == 2, "got ref %ld.\n", ref);
- ref = IActivationFactory_Release(factory);
- ok(ref == 1, "got ref %ld.\n", ref);
+}
+START_TEST(gamebar) +{
- HRESULT hr;
- hr = RoInitialize(RO_INIT_MULTITHREADED);
- ok(hr == S_OK, "RoInitialize failed, hr %#lx\n", hr);
- test_GameBarStatics();
- RoUninitialize();
+}
Would you mind updating the test style to match the module (or the other way if you like best, but I personally started to like spaces)?
Rémi Bernon (@rbernon) commented about dlls/windows.gaming.ui.gamebar/tests/gamebar.c:
hr = IActivationFactory_QueryInterface(factory, &IID_IAgileObject, (void **)&agile_object); ok(hr == S_OK, "got hr %#lx.\n", hr);
- hr = IActivationFactory_QueryInterface(factory, &IID_IGameBarStatics, (void **)&gamebar_statics);
- ok(hr == S_OK, "got hr %#lx.\n", hr);
- hr = IGameBarStatics_QueryInterface(gamebar_statics, &IID_IInspectable, (void **)&tmp_inspectable);
- ok(hr == S_OK, "got hr %#lx.\n", hr);
- ok(tmp_inspectable == inspectable, "got %p, expected %p.\n", tmp_inspectable, inspectable);
- IInspectable_Release(tmp_inspectable);
- hr = IGameBarStatics_QueryInterface(gamebar_statics, &IID_IAgileObject, (void **)&tmp_agile_object);
- ok(hr == S_OK, "got hr %#lx.\n", hr);
- ok(tmp_agile_object == agile_object, "got %p, expected %p.\n", tmp_agile_object, agile_object);
- IAgileObject_Release(tmp_agile_object);
I'd be okay with assuming a few things about WinRT objects, statics and factories, and just use some check_interface to validate the iface presence. I don't mind if you want to keep the detailed checks.
Rémi Bernon (@rbernon) commented about dlls/windows.gaming.ui.gamebar/main.c:
- FIXME( "iface %p, handler %p, token %p stub.\n", iface, handler, token );
- *token = dummy_token;
- return S_OK;
+}
+static HRESULT WINAPI statics_remove_IsInputRedirectedChanged( IGameBarStatics *iface, EventRegistrationToken token ) +{
- FIXME( "iface %p, token %#I64x stub.\n", iface, token.value );
- return S_OK;
+}
+static HRESULT WINAPI statics_get_Visible( IGameBarStatics *iface, BOOLEAN *value) +{
- TRACE( "iface %p, value %p.\n", iface, value );
- if (!value) return E_INVALIDARG;
A test for these checks could be welcome to validate the result, or not checking at all is probably also okay.
On Thu Nov 3 20:47:20 2022 +0000, Rémi Bernon wrote:
A test for these checks could be welcome to validate the result, or not checking at all is probably also okay.
Also a semi-stub message is also probably more appropriate here, unless it's called often?
On Thu Nov 3 20:49:15 2022 +0000, Rémi Bernon wrote:
Also a semi-stub message is also probably more appropriate here, unless it's called often?
Well, my reasoning was that since we don't have GameBar in Wine returning false for its visibility and the input redirection is not a stub, it just correctly relays the state of things. And I put the fixmes into callback registration function because I do not implement any callback tracking, nor I bothered to make any test for those. Please let me know if you think it is still worth chaning anything WRT these traces.
On Thu Nov 3 20:55:56 2022 +0000, Paul Gofman wrote:
Well, my reasoning was that since we don't have GameBar in Wine returning false for its visibility and the input redirection is not a stub, it just correctly relays the state of things. And I put the fixmes into callback registration function because I do not implement any callback tracking, nor I bothered to make any test for those. Please let me know if you think it is still worth chaning anything WRT these traces.
Yeah it's probably fine.