[RFC 1/11] Linux FF: Joystick control panel program
Andrew Eikum
aeikum at codeweavers.com
Mon Mar 10 10:47:47 CDT 2014
On Fri, Mar 07, 2014 at 10:01:30PM +0100, Elias Vanderstuyft wrote:
> On Wed, Mar 5, 2014 at 3:49 PM, Andrew Eikum <aeikum at codeweavers.com> wrote:
> > On Tue, Mar 04, 2014 at 08:19:16PM +0100, Elias Vanderstuyft wrote:
> >> a) When unloading conditional effects in joy.cpl, the program crashes:
> >> When unloading the conditional effect array entries,
> >> Wine tries to access an invalid (high) address because
> >> dieffect.lpvTypeSpecificParams was not set at the time the
> >> effect was created.
> >> So declare a valid 'standard' (maxed out) conditional effect.
> >> For other unknown effects:
> >> - The same can happen when CustomForce effects are available,
> >> but because Wine's FF dinput->linux translation does
> >> not support this yet,
> >> we simply print a FIXME to indicate a possible cause
> >> if a crash would happen.
> >> - The same for other (unsupported) effects (this is
> >> probably not safe?),
> >> but then we print a WARN.
> >
> > For unhandled types, it's probably best to print a FIXME and return
> > DIENUM_CONTINUE, rather than continue to rely on uninitialized data.
>
> Alright.
> Should I also write the extra if-test for the CustomForce type, or do
> I have to cover it with one if-test as an unhandled type?
>
I'd just treat it as an unhandled type.
> > Additionally, our IDirectInputEffect implementations could check for
> > NULL lpvTypeSpecificParams and fail appropriately instead of crashing,
> > if this is what Windows does.
>
> Well, I checked the SetParameters() function, and it does correctly
> check on NULL lpvTypeSpecificParams and fail appropriately.
> The problem seems again to be related with joy.cpl/main.c: there is no
> check performed on the result of IDirectInputDevice2_CreateEffect(),
> so change joy.cpl/main.c:784 :
> hr = IDirectInputDevice2_CreateEffect(
> joystick->device, &pdei->guid, &dieffect,
> &joystick->effects[joystick->cur_effect].effect, NULL);
>
> joystick->effects[joystick->cur_effect].params = dieffect;
> joystick->effects[joystick->cur_effect].info = *pdei;
> joystick->cur_effect += 1;
>
> return DIENUM_CONTINUE;
> to :
> hr = IDirectInputDevice2_CreateEffect(
> joystick->device, &pdei->guid, &dieffect,
> &joystick->effects[joystick->cur_effect].effect, NULL);
> if (FAILED(hr))
> return DIENUM_CONTINUE;
>
> joystick->effects[joystick->cur_effect].params = dieffect;
> joystick->effects[joystick->cur_effect].info = *pdei;
> joystick->cur_effect += 1;
>
> return DIENUM_CONTINUE;
>
Sure.
> Before I knew the joy.cpl app was to be blamed, and was searching in
> the IDirectInputEffect implementions, I saw something that is not
> conform MSDN:
> JoystickAImpl_EnumEffects and JoystickWImpl_EnumEffects should check
> on DIENUM_CONTINUE to continue the enumeration, or DIENUM_STOP to stop
> it:
> http://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.callback.dienumeffectscallback%28v=vs.85%29.aspx
> For example, in JoystickWImpl_EnumEffects(), each occurrence of
> "(*lpCallback)(&dei, pvRef);" should check whether the return value is
> DIENUM_CONTINUE or DIENUM_STOP. When the latter is the case, should we
> then first add a "goto" statement to jump to the last "if (xfd == -1)
> IDirectInputDevice8_Unacquire(iface);" statement, or directly return?
> And what should it return in that case, "DIERR_NOTINITIALIZED" (does
> stopping enumeration mean failure? that's not clear in MSDN), or
> "DI_OK"?
Probably the goto. I'm not sure about the return value, you would need
tests to be certain. Probably DI_OK is correct.
> And even worse, what if the return value of "(*lpCallback)(&dei,
> pvRef);" is not equal to DIENUM_CONTINUE or DIENUM_STOP? Should
> JoystickWImpl_EnumEffects() interpret it as the former or as the
> latter? (also not mentioned in MSDN)
>
Again, you'd need tests to confirm.
> dieffect.cAxes = 2;
> dieffect.rgdwAxes = axes;
> dieffect.rglDirection = direction;
>
> DIRAMPFORCE rforce;
> DICONSTANTFORCE cforce;
> DIPERIODIC pforce;
> DICONDITION cxyforce[2];
>
> if (IsEqualGUID(&pdei->guid, &GUID_RampForce))
>
Yes, but the declarations have to be at the very top of the function,
alongside all of the other declarations.
Andrew
More information about the wine-devel
mailing list