[PATCH v3 3/6] windows.gaming.input: Implement IForceFeedbackEffect interface for ConstantForceEffect.
Rémi Bernon
wine at gitlab.winehq.org
Fri May 13 03:46:06 CDT 2022
From: Rémi Bernon <rbernon at codeweavers.com>
Using COM aggregation and a new IWineForceFeedbackEffectImpl interface,
deriving from IUnknown as it is only used internally.
Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
dlls/dinput/tests/force_feedback.c | 3 +-
dlls/windows.gaming.input/constant_effect.c | 21 +++-
dlls/windows.gaming.input/force_feedback.c | 133 ++++++++++++++++++++
dlls/windows.gaming.input/private.h | 3 +
dlls/windows.gaming.input/provider.idl | 14 +++
5 files changed, 168 insertions(+), 6 deletions(-)
diff --git a/dlls/dinput/tests/force_feedback.c b/dlls/dinput/tests/force_feedback.c
index e688f575704..bbd9ed2310b 100644
--- a/dlls/dinput/tests/force_feedback.c
+++ b/dlls/dinput/tests/force_feedback.c
@@ -5628,10 +5628,8 @@ static void test_windows_gaming_input(void)
IActivationFactory_Release( activation_factory );
hr = IInspectable_QueryInterface( tmp_inspectable, &IID_IForceFeedbackEffect, (void **)&effect );
- todo_wine
ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
IInspectable_Release( tmp_inspectable );
- if (hr != S_OK) goto skip_tests;
hr = IForceFeedbackEffect_QueryInterface( effect, &IID_IConstantForceEffect, (void **)&constant_effect );
ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
@@ -5670,6 +5668,7 @@ static void test_windows_gaming_input(void)
hr = IForceFeedbackMotor_LoadEffectAsync( motor, effect, &result_async );
todo_wine
ok( hr == S_OK, "LoadEffectAsync returned %#lx\n", hr );
+ if (hr != S_OK) goto skip_tests;
result_async_handler = default_result_async_handler;
result_async_handler.event = CreateEventW( NULL, FALSE, FALSE, NULL );
ok( !!result_async_handler.event, "CreateEventW failed, error %lu\n", GetLastError() );
diff --git a/dlls/windows.gaming.input/constant_effect.c b/dlls/windows.gaming.input/constant_effect.c
index a491d49c18c..ae0c0f9904d 100644
--- a/dlls/windows.gaming.input/constant_effect.c
+++ b/dlls/windows.gaming.input/constant_effect.c
@@ -25,6 +25,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(input);
struct constant_effect
{
IConstantForceEffect IConstantForceEffect_iface;
+ IWineForceFeedbackEffectImpl *IWineForceFeedbackEffectImpl_inner;
LONG ref;
};
@@ -48,9 +49,7 @@ static HRESULT WINAPI effect_QueryInterface( IConstantForceEffect *iface, REFIID
return S_OK;
}
- FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) );
- *out = NULL;
- return E_NOINTERFACE;
+ return IWineForceFeedbackEffectImpl_QueryInterface( impl->IWineForceFeedbackEffectImpl_inner, iid, out );
}
static ULONG WINAPI effect_AddRef( IConstantForceEffect *iface )
@@ -68,7 +67,13 @@ static ULONG WINAPI effect_Release( IConstantForceEffect *iface )
TRACE( "iface %p decreasing refcount to %lu.\n", iface, ref );
- if (!ref) free( impl );
+ if (!ref)
+ {
+ /* guard against re-entry if inner releases an outer iface */
+ InterlockedIncrement( &impl->ref );
+ IWineForceFeedbackEffectImpl_Release( impl->IWineForceFeedbackEffectImpl_inner );
+ free( impl );
+ }
return ref;
}
@@ -192,6 +197,7 @@ static HRESULT WINAPI activation_GetTrustLevel( IActivationFactory *iface, Trust
static HRESULT WINAPI activation_ActivateInstance( IActivationFactory *iface, IInspectable **instance )
{
struct constant_effect *impl;
+ HRESULT hr;
TRACE( "iface %p, instance %p.\n", iface, instance );
@@ -199,6 +205,13 @@ static HRESULT WINAPI activation_ActivateInstance( IActivationFactory *iface, II
impl->IConstantForceEffect_iface.lpVtbl = &effect_vtbl;
impl->ref = 1;
+ if (FAILED(hr = force_feedback_effect_create( (IInspectable *)&impl->IConstantForceEffect_iface,
+ &impl->IWineForceFeedbackEffectImpl_inner )))
+ {
+ free( impl );
+ return hr;
+ }
+
*instance = (IInspectable *)&impl->IConstantForceEffect_iface;
TRACE( "created ConstantForceEffect %p\n", *instance );
return S_OK;
diff --git a/dlls/windows.gaming.input/force_feedback.c b/dlls/windows.gaming.input/force_feedback.c
index 3fdcc636bbd..ab29a179c6a 100644
--- a/dlls/windows.gaming.input/force_feedback.c
+++ b/dlls/windows.gaming.input/force_feedback.c
@@ -27,6 +27,139 @@
WINE_DEFAULT_DEBUG_CHANNEL(input);
+struct effect
+{
+ IWineForceFeedbackEffectImpl IWineForceFeedbackEffectImpl_iface;
+ IForceFeedbackEffect IForceFeedbackEffect_iface;
+ IInspectable *IInspectable_outer;
+ LONG ref;
+};
+
+static inline struct effect *impl_from_IWineForceFeedbackEffectImpl( IWineForceFeedbackEffectImpl *iface )
+{
+ return CONTAINING_RECORD( iface, struct effect, IWineForceFeedbackEffectImpl_iface );
+}
+
+static HRESULT WINAPI effect_impl_QueryInterface( IWineForceFeedbackEffectImpl *iface, REFIID iid, void **out )
+{
+ struct effect *impl = impl_from_IWineForceFeedbackEffectImpl( 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_IWineForceFeedbackEffectImpl ))
+ {
+ IWineForceFeedbackEffectImpl_AddRef( (*out = &impl->IWineForceFeedbackEffectImpl_iface) );
+ return S_OK;
+ }
+
+ if (IsEqualGUID( iid, &IID_IForceFeedbackEffect ))
+ {
+ IInspectable_AddRef( (*out = &impl->IForceFeedbackEffect_iface) );
+ return S_OK;
+ }
+
+ FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) );
+ *out = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI effect_impl_AddRef( IWineForceFeedbackEffectImpl *iface )
+{
+ struct effect *impl = impl_from_IWineForceFeedbackEffectImpl( iface );
+ ULONG ref = InterlockedIncrement( &impl->ref );
+ TRACE( "iface %p increasing refcount to %lu.\n", iface, ref );
+ return ref;
+}
+
+static ULONG WINAPI effect_impl_Release( IWineForceFeedbackEffectImpl *iface )
+{
+ struct effect *impl = impl_from_IWineForceFeedbackEffectImpl( iface );
+ ULONG ref = InterlockedDecrement( &impl->ref );
+
+ TRACE( "iface %p decreasing refcount to %lu.\n", iface, ref );
+
+ if (!ref) free( impl );
+
+ return ref;
+}
+
+static const struct IWineForceFeedbackEffectImplVtbl effect_impl_vtbl =
+{
+ effect_impl_QueryInterface,
+ effect_impl_AddRef,
+ effect_impl_Release,
+ /* IWineForceFeedbackEffectImpl methods */
+};
+
+DEFINE_IINSPECTABLE_OUTER( effect, IForceFeedbackEffect, struct effect, IInspectable_outer )
+
+static HRESULT WINAPI effect_get_Gain( IForceFeedbackEffect *iface, DOUBLE *value )
+{
+ FIXME( "iface %p, value %p stub!\n", iface, value );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI effect_put_Gain( IForceFeedbackEffect *iface, DOUBLE value )
+{
+ FIXME( "iface %p, value %f stub!\n", iface, value );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI effect_get_State( IForceFeedbackEffect *iface, ForceFeedbackEffectState *value )
+{
+ FIXME( "iface %p, value %p stub!\n", iface, value );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI effect_Start( IForceFeedbackEffect *iface )
+{
+ FIXME( "iface %p stub!\n", iface );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI effect_Stop( IForceFeedbackEffect *iface )
+{
+ FIXME( "iface %p stub!\n", iface );
+ return E_NOTIMPL;
+}
+
+static const struct IForceFeedbackEffectVtbl effect_vtbl =
+{
+ effect_QueryInterface,
+ effect_AddRef,
+ effect_Release,
+ /* IInspectable methods */
+ effect_GetIids,
+ effect_GetRuntimeClassName,
+ effect_GetTrustLevel,
+ /* IForceFeedbackEffect methods */
+ effect_get_Gain,
+ effect_put_Gain,
+ effect_get_State,
+ effect_Start,
+ effect_Stop,
+};
+
+HRESULT force_feedback_effect_create( IInspectable *outer, IWineForceFeedbackEffectImpl **out )
+{
+ struct effect *impl;
+
+ TRACE( "outer %p, out %p\n", outer, out );
+
+ if (!(impl = calloc( 1, sizeof(*impl) ))) return E_OUTOFMEMORY;
+ impl->IWineForceFeedbackEffectImpl_iface.lpVtbl = &effect_impl_vtbl;
+ impl->IForceFeedbackEffect_iface.lpVtbl = &effect_vtbl;
+ impl->IInspectable_outer = outer;
+ impl->ref = 1;
+
+ *out = &impl->IWineForceFeedbackEffectImpl_iface;
+ TRACE( "created ForceFeedbackEffect %p\n", *out );
+ return S_OK;
+}
+
struct motor
{
IForceFeedbackMotor IForceFeedbackMotor_iface;
diff --git a/dlls/windows.gaming.input/private.h b/dlls/windows.gaming.input/private.h
index 9bbaae5554b..58378304a26 100644
--- a/dlls/windows.gaming.input/private.h
+++ b/dlls/windows.gaming.input/private.h
@@ -42,6 +42,8 @@
#include "wine/debug.h"
#include "wine/list.h"
+#include "provider.h"
+
extern HINSTANCE windows_gaming_input;
extern ICustomGameControllerFactory *controller_factory;
extern ICustomGameControllerFactory *gamepad_factory;
@@ -69,6 +71,7 @@ extern HRESULT event_handlers_remove( struct list *list, EventRegistrationToken
extern void event_handlers_notify( struct list *list, IInspectable *element );
extern HRESULT force_feedback_motor_create( IDirectInputDevice8W *device, IForceFeedbackMotor **out );
+extern HRESULT force_feedback_effect_create( IInspectable *outer, IWineForceFeedbackEffectImpl **out );
typedef HRESULT (WINAPI *async_operation_callback)( IUnknown *invoker, IUnknown *param, PROPVARIANT *result );
extern HRESULT async_operation_boolean_create( IUnknown *invoker, IUnknown *param, async_operation_callback callback,
diff --git a/dlls/windows.gaming.input/provider.idl b/dlls/windows.gaming.input/provider.idl
index af5fbff05df..fbfa15f4100 100644
--- a/dlls/windows.gaming.input/provider.idl
+++ b/dlls/windows.gaming.input/provider.idl
@@ -34,6 +34,7 @@ import "windows.gaming.input.forcefeedback.idl";
namespace Windows.Gaming.Input.Custom {
typedef enum WineGameControllerType WineGameControllerType;
+ typedef enum WineForceFeedbackEffectType WineForceFeedbackEffectType;
typedef struct WineGameControllerState WineGameControllerState;
typedef struct WineGameControllerVibration WineGameControllerVibration;
interface IWineGameControllerProvider;
@@ -49,6 +50,11 @@ namespace Windows.Gaming.Input.Custom {
RacingWheel = 2,
};
+ enum WineForceFeedbackEffectType
+ {
+ Constant = 1,
+ };
+
struct WineGameControllerState
{
UINT64 timestamp;
@@ -94,6 +100,14 @@ namespace Windows.Gaming.Input.Custom {
[propget] HRESULT ForceFeedbackMotor([out, retval] Windows.Gaming.Input.ForceFeedback.ForceFeedbackMotor **motor);
}
+ [
+ uuid(27833469-7760-417e-adbe-e011a66e16ee)
+ ]
+ interface IWineForceFeedbackEffectImpl : IUnknown
+ requires Windows.Gaming.Input.ForceFeedback.IForceFeedbackEffect
+ {
+ }
+
[
uuid(83f377ee-c799-11ec-9d64-0242ac120002)
]
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/62
More information about the wine-devel
mailing list