From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/windows.gaming.input/async.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/dlls/windows.gaming.input/async.c b/dlls/windows.gaming.input/async.c index 1426b3d8481..dfcb4144e74 100644 --- a/dlls/windows.gaming.input/async.c +++ b/dlls/windows.gaming.input/async.c @@ -146,7 +146,8 @@ static HRESULT WINAPI async_impl_get_Completed( IWineAsyncInfoImpl *iface, IWine
EnterCriticalSection( &impl->cs ); if (impl->status == Closed) hr = E_ILLEGAL_METHOD_CALL; - *handler = (impl->handler != HANDLER_NOT_SET) ? impl->handler : NULL; + if (impl->handler == NULL || impl->handler == HANDLER_NOT_SET) *handler = NULL; + else IWineAsyncOperationCompletedHandler_AddRef( (*handler = impl->handler) ); LeaveCriticalSection( &impl->cs );
return hr;
From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/windows.gaming.input/async.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/dlls/windows.gaming.input/async.c b/dlls/windows.gaming.input/async.c index dfcb4144e74..fc593bc6121 100644 --- a/dlls/windows.gaming.input/async.c +++ b/dlls/windows.gaming.input/async.c @@ -98,6 +98,7 @@ static ULONG WINAPI async_impl_Release( IWineAsyncInfoImpl *iface ) IAsyncInfo_Close( &impl->IAsyncInfo_iface ); if (impl->param) IUnknown_Release( impl->param ); if (impl->invoker) IUnknown_Release( impl->invoker ); + impl->cs.DebugInfo->Spare[0] = 0; DeleteCriticalSection( &impl->cs ); free( impl ); }
From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/windows.gaming.input/provider.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/dlls/windows.gaming.input/provider.c b/dlls/windows.gaming.input/provider.c index 70900000eef..1f3f4e047f5 100644 --- a/dlls/windows.gaming.input/provider.c +++ b/dlls/windows.gaming.input/provider.c @@ -572,7 +572,7 @@ void provider_create( const WCHAR *device_path )
EnterCriticalSection( &provider_cs ); LIST_FOR_EACH_ENTRY( entry, &provider_list, struct provider, entry ) - if ((found = !wcscmp( entry->device_path, device_path ))) break; + if ((found = !wcsicmp( entry->device_path, device_path ))) break; if (!found) list_add_tail( &provider_list, &impl->entry ); LeaveCriticalSection( &provider_cs );
@@ -592,11 +592,12 @@ void provider_remove( const WCHAR *device_path )
EnterCriticalSection( &provider_cs ); LIST_FOR_EACH_ENTRY( entry, &provider_list, struct provider, entry ) - if ((found = !wcscmp( entry->device_path, device_path ))) break; + if ((found = !wcsicmp( entry->device_path, device_path ))) break; if (found) list_remove( &entry->entry ); LeaveCriticalSection( &provider_cs );
- if (found) + if (!found) WARN( "provider not found for device %s\n", debugstr_w( device_path ) ); + else { provider = &entry->IGameControllerProvider_iface; manager_on_provider_removed( provider );
From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/windows.gaming.input/classes.idl | 3 ++- include/windows.gaming.input.forcefeedback.idl | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/dlls/windows.gaming.input/classes.idl b/dlls/windows.gaming.input/classes.idl index ca3bd5d8dd7..2adf43cdbb0 100644 --- a/dlls/windows.gaming.input/classes.idl +++ b/dlls/windows.gaming.input/classes.idl @@ -29,11 +29,12 @@ import "asyncinfo.idl"; import "eventtoken.idl"; import "windowscontracts.idl"; import "windows.foundation.idl"; +import "windows.foundation.numerics.idl"; import "windows.devices.haptics.idl"; -import "windows.gaming.input.forcefeedback.idl"; import "windows.system.idl"; import "windows.devices.power.idl";
#define DO_NO_IMPORTS +#include "windows.gaming.input.forcefeedback.idl" #include "windows.gaming.input.idl" #include "windows.gaming.input.custom.idl" diff --git a/include/windows.gaming.input.forcefeedback.idl b/include/windows.gaming.input.forcefeedback.idl index 290d1f62971..82fb083b34b 100644 --- a/include/windows.gaming.input.forcefeedback.idl +++ b/include/windows.gaming.input.forcefeedback.idl @@ -20,12 +20,14 @@ #pragma winrt ns_prefix #endif
+#ifndef DO_NO_IMPORTS import "inspectable.idl"; import "asyncinfo.idl"; import "eventtoken.idl"; import "windowscontracts.idl"; import "windows.foundation.idl"; import "windows.foundation.numerics.idl"; +#endif
namespace Windows.Gaming.Input.ForceFeedback { typedef enum ForceFeedbackEffectAxes ForceFeedbackEffectAxes;
From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/tests/force_feedback.c | 3 +- dlls/windows.gaming.input/Makefile.in | 1 + dlls/windows.gaming.input/constant_effect.c | 117 ++++++++++++++++++++ dlls/windows.gaming.input/main.c | 3 + dlls/windows.gaming.input/private.h | 1 + 5 files changed, 123 insertions(+), 2 deletions(-) create mode 100644 dlls/windows.gaming.input/constant_effect.c
diff --git a/dlls/dinput/tests/force_feedback.c b/dlls/dinput/tests/force_feedback.c index f5b387f3566..0981bbe65e1 100644 --- a/dlls/dinput/tests/force_feedback.c +++ b/dlls/dinput/tests/force_feedback.c @@ -5620,15 +5620,14 @@ static void test_windows_gaming_input(void) hr = pWindowsCreateString( constant_effect_class_name, wcslen( constant_effect_class_name ), &str ); ok( hr == S_OK, "WindowsCreateString returned %#lx\n", hr ); hr = pRoGetActivationFactory( str, &IID_IActivationFactory, (void **)&activation_factory ); - todo_wine ok( hr == S_OK, "RoGetActivationFactory returned %#lx\n", hr ); pWindowsDeleteString( str ); - if (hr != S_OK) goto skip_tests;
hr = IActivationFactory_ActivateInstance( activation_factory, &tmp_inspectable ); todo_wine ok( hr == S_OK, "QueryInterface returned %#lx\n", hr ); IActivationFactory_Release( activation_factory ); + if (hr != S_OK) goto skip_tests;
hr = IInspectable_QueryInterface( tmp_inspectable, &IID_IForceFeedbackEffect, (void **)&effect ); todo_wine diff --git a/dlls/windows.gaming.input/Makefile.in b/dlls/windows.gaming.input/Makefile.in index 463f6b97f74..8f3af4fec62 100644 --- a/dlls/windows.gaming.input/Makefile.in +++ b/dlls/windows.gaming.input/Makefile.in @@ -3,6 +3,7 @@ IMPORTS = combase uuid user32 dinput8 setupapi hid
C_SRCS = \ async.c \ + constant_effect.c \ controller.c \ event_handlers.c \ force_feedback.c \ diff --git a/dlls/windows.gaming.input/constant_effect.c b/dlls/windows.gaming.input/constant_effect.c new file mode 100644 index 00000000000..a27258dd9bf --- /dev/null +++ b/dlls/windows.gaming.input/constant_effect.c @@ -0,0 +1,117 @@ +/* WinRT Windows.Gaming.Input implementation + * + * Copyright 2022 Rémi Bernon 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 "provider.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(input); + +struct constant_factory +{ + IActivationFactory IActivationFactory_iface; + LONG ref; +}; + +static inline struct constant_factory *impl_from_IActivationFactory( IActivationFactory *iface ) +{ + return CONTAINING_RECORD( iface, struct constant_factory, IActivationFactory_iface ); +} + +static HRESULT WINAPI activation_QueryInterface( IActivationFactory *iface, REFIID iid, void **out ) +{ + struct constant_factory *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 )) + { + IInspectable_AddRef( (*out = &impl->IActivationFactory_iface) ); + return S_OK; + } + + FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) ); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI activation_AddRef( IActivationFactory *iface ) +{ + struct constant_factory *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 activation_Release( IActivationFactory *iface ) +{ + struct constant_factory *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 activation_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 activation_GetRuntimeClassName( IActivationFactory *iface, HSTRING *class_name ) +{ + FIXME( "iface %p, class_name %p stub!\n", iface, class_name ); + return E_NOTIMPL; +} + +static HRESULT WINAPI activation_GetTrustLevel( IActivationFactory *iface, TrustLevel *trust_level ) +{ + FIXME( "iface %p, trust_level %p stub!\n", iface, trust_level ); + return E_NOTIMPL; +} + +static HRESULT WINAPI activation_ActivateInstance( IActivationFactory *iface, IInspectable **instance ) +{ + FIXME( "iface %p, instance %p stub!\n", iface, instance ); + return E_NOTIMPL; +} + +static const struct IActivationFactoryVtbl activation_vtbl = +{ + activation_QueryInterface, + activation_AddRef, + activation_Release, + /* IInspectable methods */ + activation_GetIids, + activation_GetRuntimeClassName, + activation_GetTrustLevel, + /* IActivationFactory methods */ + activation_ActivateInstance, +}; + +static struct constant_factory constant_statics = +{ + {&activation_vtbl}, + 1, +}; + +IInspectable *constant_effect_factory = (IInspectable *)&constant_statics.IActivationFactory_iface; diff --git a/dlls/windows.gaming.input/main.c b/dlls/windows.gaming.input/main.c index 21808d9c2ad..aeb870b039b 100644 --- a/dlls/windows.gaming.input/main.c +++ b/dlls/windows.gaming.input/main.c @@ -185,6 +185,9 @@ HRESULT WINAPI DllGetActivationFactory( HSTRING class_str, IActivationFactory ** if (!wcscmp( buffer, RuntimeClass_Windows_Gaming_Input_Custom_GameControllerFactoryManager )) IGameControllerFactoryManagerStatics2_QueryInterface( manager_factory, &IID_IActivationFactory, (void **)factory );
+ if (!wcscmp( buffer, RuntimeClass_Windows_Gaming_Input_ForceFeedback_ConstantForceEffect )) + IInspectable_QueryInterface( constant_effect_factory, &IID_IActivationFactory, (void **)factory ); + if (*factory) return S_OK; return CLASS_E_CLASSNOTAVAILABLE; } diff --git a/dlls/windows.gaming.input/private.h b/dlls/windows.gaming.input/private.h index 68f6bdcf5b6..2e97f182e78 100644 --- a/dlls/windows.gaming.input/private.h +++ b/dlls/windows.gaming.input/private.h @@ -45,6 +45,7 @@ extern ICustomGameControllerFactory *controller_factory; extern ICustomGameControllerFactory *gamepad_factory; extern ICustomGameControllerFactory *racing_wheel_factory; extern IGameControllerFactoryManagerStatics2 *manager_factory; +extern IInspectable *constant_effect_factory;
struct vector_iids {
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=114295
Your paranoid android.
=== debian11 (32 bit Hindi:India report) ===
dinput: force_feedback.c:5539: Test failed: WaitForSingleObject returned 0x102 force_feedback.c:5539: Test failed: GetOverlappedResult returned 996 force_feedback.c:5539: Test failed: IOCTL_WINETEST_HID_WAIT_EXPECT failed, last error 996 force_feedback.c:5543: Test failed: got status 3 force_feedback.c:5543: Test failed: got error 0x8007001e force_feedback.c:5543: Test failed: GetResults returned 0x8007001e force_feedback.c:5543: Test failed: got result 0 force_feedback.c:5547: Test failed: got status 3 force_feedback.c:5584: Test failed: WaitForSingleObject returned 0x102 force_feedback.c:5584: Test failed: GetOverlappedResult returned 996 force_feedback.c:5584: Test failed: IOCTL_WINETEST_HID_WAIT_EXPECT failed, last error 996 driver_bus.c:139: Test failed: hid.c:5539 expect[0]: missing (code 0xb000f id 6 len 2) driver_bus.c:139: Test failed: hid.c:5584 expect[0]: missing (code 0xb000f id 6 len 2)
=== debian11 (32 bit Chinese:China report) ===
dinput: force_feedback.c:5539: Test failed: WaitForSingleObject returned 0x102 force_feedback.c:5539: Test failed: GetOverlappedResult returned 996 force_feedback.c:5539: Test failed: IOCTL_WINETEST_HID_WAIT_EXPECT failed, last error 996 force_feedback.c:5543: Test failed: got status 3 force_feedback.c:5543: Test failed: got error 0x8007001e force_feedback.c:5543: Test failed: GetResults returned 0x8007001e force_feedback.c:5543: Test failed: got result 0 force_feedback.c:5547: Test failed: got status 3 force_feedback.c:5584: Test failed: WaitForSingleObject returned 0x102 force_feedback.c:5584: Test failed: GetOverlappedResult returned 996 force_feedback.c:5584: Test failed: IOCTL_WINETEST_HID_WAIT_EXPECT failed, last error 996 driver_bus.c:139: Test failed: hid.c:5539 expect[0]: missing (code 0xb000f id 6 len 2) driver_bus.c:139: Test failed: hid.c:5584 expect[0]: missing (code 0xb000f id 6 len 2)
This merge request was approved by Rémi Bernon.