0

I have made a plugin for a game, to add support for alternative input devices for that game, such as steering wheels.

Some of my users have been getting an exception when they try to set-up their wheels for my plugin. This only occurs for those specific wheels and when another plugin is present. The exception thrown is 0xC00000FD, and occurs when calling CreateEffect.

I've had a hard time reproducing this error as I don't have access to the troublesome hardware. Specifically it only seems to happen with the Logitech G920 steering wheel, and only when the game is launched normally while the ScriptHookVDotNet plugin is also active. Since the reports came in, I have only managed to add more logging, which has lead me to the exception code and the function that causes it.

The issue can be circumvented by either not using the plugin, not using that specific steering wheel, or by launching the game through a third-party launcher (RagePluginHook).

As a proof-of-concept, I have re-used the offending code in a separate Windows Console application (to configure the inputs), where this problem does not occur.

My code is hosted on GitHub, here is the specific line that causes the issue:

    // These are class members
    LPDIRECTINPUTEFFECT m_cfEffect = nullptr;
    DICONSTANTFORCE m_constantForceParams;

    // LPDIRECTINPUTDEVICE8 diDevice has been retrieved elsewhere

    DIEFFECT cfEffect;
    createConstantForceEffect(DIJOFS_X, 1, cfEffect);
    HRESULT hr = diDevice->CreateEffect(GUID_ConstantForce, &cfEffect, &m_cfEffect, nullptr); // This causes the exception

createConstantForceEffect has been made after a Microsoft example:

void WheelDirectInput::createConstantForceEffect(DWORD axis, int numAxes, DIEFFECT &diEffect) {
    DWORD rgdwAxes[1] = { axis };
    LONG rglDirection[1] = { 0 };
    m_constantForceParams.lMagnitude = 0;

    ZeroMemory(&diEffect, sizeof(diEffect));
    diEffect.dwSize = sizeof(DIEFFECT);
    diEffect.rgdwAxes = rgdwAxes;
    diEffect.rglDirection = rglDirection;
    diEffect.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
    diEffect.dwDuration = INFINITE;
    diEffect.dwSamplePeriod = 0;
    diEffect.dwGain = DI_FFNOMINALMAX;
    diEffect.dwTriggerButton = DIEB_NOTRIGGER;
    diEffect.dwTriggerRepeatInterval = 0;

    diEffect.cAxes = numAxes;
    diEffect.lpEnvelope = nullptr;
    diEffect.cbTypeSpecificParams = diEffect.cAxes * sizeof(DICONSTANTFORCE);
    diEffect.lpvTypeSpecificParams = &m_constantForceParams;
    diEffect.dwStartDelay = 0;
}

I'd just like to know why this error is caused in this specific situation, and what I can do to extract more error than just catching the exception.

The exception 0xC00000FD seems to be pointing to a stack overflow error, but I wouldn't know what could cause that error. There is no recursion on my side and my code runs fine for virtually all other hardware/software combinations.

ikt
  • 3
  • 4
  • Run under windbg. It will break on 0xC00000FD. Then type `k` in windbg to see the call stack. Visual Studio debugger will also work. – rustyx Apr 05 '19 at 11:58
  • @rustyx I can't reproduce the error without the hardware, and the host application has anti-debugging features baked in. Users of my plugin probably aren't able to use WinDbg for this. Thanks though, I remember I had a snippet that could dump a stack trace, so I'll add that back for more info on an exception. – ikt Apr 05 '19 at 13:43

0 Answers0