diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c
index db4507dbd14499556c4e59c00dc2e0c97c971150..c34b541f5572b923a2f85c1c5054a0a484f934c1 100644
--- a/dlls/dinput/device.c
+++ b/dlls/dinput/device.c
@@ -1551,7 +1551,10 @@ HRESULT WINAPI IDirectInputDevice2WImpl_CreateEffect(LPDIRECTINPUTDEVICE8W iface
                                                      LPDIRECTINPUTEFFECT *ppdef, LPUNKNOWN pUnkOuter)
 {
     FIXME("(this=%p,%s,%p,%p,%p): stub!\n", iface, debugstr_guid(rguid), lpeff, ppdef, pUnkOuter);
-    return DI_OK;
+
+    FIXME("not available in the generic implementation\n");
+    *ppdef = NULL;
+    return DIERR_UNSUPPORTED;
 }
 
 HRESULT WINAPI IDirectInputDevice2AImpl_CreateEffect(LPDIRECTINPUTDEVICE8A iface, REFGUID rguid, LPCDIEFFECT lpeff,
diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c
index 6fa599758f09fa65ab5e87a5377a5888b34b103d..ecd239cdd90495b766f7dfbdaa4a6806ca6dfa83 100644
--- a/dlls/dinput/joystick_linuxinput.c
+++ b/dlls/dinput/joystick_linuxinput.c
@@ -1049,10 +1049,16 @@ static HRESULT WINAPI JoystickWImpl_CreateEffect(LPDIRECTINPUTDEVICE8W iface, RE
     JoystickImpl* This = impl_from_IDirectInputDevice8W(iface);
     TRACE("(this=%p,%p,%p,%p,%p)\n", This, rguid, lpeff, ppdef, pUnkOuter);
 
-#ifndef HAVE_STRUCT_FF_EFFECT_DIRECTION
-    TRACE("not available (compiled w/o ff support)\n");
     *ppdef = NULL;
-    return DI_OK;
+    if (!This->joydev->has_ff)
+    {
+        TRACE("No force feedback support\n");
+        return DIERR_UNSUPPORTED;
+    }
+
+#ifndef HAVE_STRUCT_FF_EFFECT_DIRECTION
+    TRACE("not available (compiled w/o force feedback support)\n");
+    return DIERR_UNSUPPORTED;
 #else
 
     if (!(new_effect = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_effect))))
diff --git a/dlls/dinput/joystick_osx.c b/dlls/dinput/joystick_osx.c
index 24f60d75b30877ecc162ce2de63113405b68a924..43fa20ea94c09336fba4b40d2a848006c3bea37e 100644
--- a/dlls/dinput/joystick_osx.c
+++ b/dlls/dinput/joystick_osx.c
@@ -1398,7 +1398,7 @@ static HRESULT WINAPI JoystickWImpl_CreateEffect(IDirectInputDevice8W *iface,
     if(!This->ff){
         TRACE("No force feedback support\n");
         *out = NULL;
-        return S_OK;
+        return DIERR_UNSUPPORTED;
     }
 
     if(outer)
diff --git a/dlls/dinput/tests/joystick.c b/dlls/dinput/tests/joystick.c
index af36e6df0deef117bd4e3ea68f084a758df25a85..ed74bb924a29d2c67dec0ee13000a8c606db82c3 100644
--- a/dlls/dinput/tests/joystick.c
+++ b/dlls/dinput/tests/joystick.c
@@ -186,6 +186,15 @@ static BOOL CALLBACK EnumJoysticks(const DIDEVICEINSTANCEA *lpddi, void *pvRef)
     WCHAR nameBuffer[MAX_PATH];
     HWND hWnd = get_hwnd();
     char oldstate[248], curstate[248];
+    DWORD axes[2] = {DIJOFS_X, DIJOFS_Y};
+    LONG  direction[2] = {0, 0};
+    DICONSTANTFORCE force = {0};
+    DIEFFECT eff;
+    LPDIRECTINPUTEFFECT effect = NULL;
+    LONG cnt1, cnt2;
+    HWND real_hWnd;
+    HINSTANCE hInstance = GetModuleHandleW(NULL);
+    DIPROPDWORD dip_gain_set, dip_gain_get;
 
     ok(data->version > 0x0300, "Joysticks not supported in version 0x%04x\n", data->version);
  
@@ -384,54 +393,46 @@ static BOOL CALLBACK EnumJoysticks(const DIDEVICEINSTANCEA *lpddi, void *pvRef)
         ok(js.rgdwPOV[3] == -1, "Default for unassigned POV should be -1 not: %d\n", js.rgdwPOV[3]);
     }
 
-    if (caps.dwFlags & DIDC_FORCEFEEDBACK)
-    {
-        DWORD axes[2] = {DIJOFS_X, DIJOFS_Y};
-        LONG  direction[2] = {0, 0};
-        DICONSTANTFORCE force = {0};
-        DIEFFECT eff;
-        LPDIRECTINPUTEFFECT effect = NULL;
-        LONG cnt1, cnt2;
-        HWND real_hWnd;
-        HINSTANCE hInstance = GetModuleHandleW(NULL);
-        DIPROPDWORD dip_gain_set, dip_gain_get;
-
-        trace("Testing force-feedback\n");
-        memset(&eff, 0, sizeof(eff));
-        eff.dwSize                = sizeof(eff);
-        eff.dwFlags               = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
-        eff.dwDuration            = INFINITE;
-        eff.dwGain                = DI_FFNOMINALMAX;
-        eff.dwTriggerButton       = DIEB_NOTRIGGER;
-        eff.cAxes                 = sizeof(axes) / sizeof(axes[0]);
-        eff.rgdwAxes              = axes;
-        eff.rglDirection          = direction;
-        eff.cbTypeSpecificParams  = sizeof(force);
-        eff.lpvTypeSpecificParams = &force;
-
-        /* Sending effects to joystick requires
-         * calling IDirectInputEffect_Initialize, which requires
-         * having exclusive access to the device, which requires
-         * - not having acquired the joystick when calling
-         *   IDirectInputDevice_SetCooperativeLevel
-         * - a visible window
-         */
-        real_hWnd = CreateWindowExA(0, "EDIT", "Test text", 0, 10, 10, 300, 300, NULL, NULL,
-                                    hInstance, NULL);
-        ok(real_hWnd!=0,"CreateWindowExA failed: %p\n", real_hWnd);
-        ShowWindow(real_hWnd, SW_SHOW);
-        hr = IDirectInputDevice_Unacquire(pJoystick);
-        ok(hr==DI_OK,"IDirectInputDevice_Unacquire() failed: %08x\n", hr);
-        hr = IDirectInputDevice_SetCooperativeLevel(pJoystick, real_hWnd,
-                                                    DISCL_EXCLUSIVE | DISCL_FOREGROUND);
-        ok(hr==DI_OK,"IDirectInputDevice_SetCooperativeLevel() failed: %08x\n", hr);
-        hr = IDirectInputDevice_Acquire(pJoystick);
-        ok(hr==DI_OK,"IDirectInputDevice_Acquire() failed: %08x\n", hr);
+    trace("Testing force feedback\n");
+    memset(&eff, 0, sizeof(eff));
+    eff.dwSize                = sizeof(eff);
+    eff.dwFlags               = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
+    eff.dwDuration            = INFINITE;
+    eff.dwGain                = DI_FFNOMINALMAX;
+    eff.dwTriggerButton       = DIEB_NOTRIGGER;
+    eff.cAxes                 = sizeof(axes) / sizeof(axes[0]);
+    eff.rgdwAxes              = axes;
+    eff.rglDirection          = direction;
+    eff.cbTypeSpecificParams  = sizeof(force);
+    eff.lpvTypeSpecificParams = &force;
+
+    /* Sending effects to joystick requires
+     * calling IDirectInputEffect_Initialize, which requires
+     * having exclusive access to the device, which requires
+     * - not having acquired the joystick when calling
+     *   IDirectInputDevice_SetCooperativeLevel
+     * - a visible window
+     */
+    real_hWnd = CreateWindowExA(0, "EDIT", "Test text", 0, 10, 10, 300, 300, NULL, NULL,
+                                hInstance, NULL);
+    ok(real_hWnd!=0,"CreateWindowExA failed: %p\n", real_hWnd);
+    ShowWindow(real_hWnd, SW_SHOW);
+    hr = IDirectInputDevice_Unacquire(pJoystick);
+    ok(hr==DI_OK,"IDirectInputDevice_Unacquire() failed: %08x\n", hr);
+    hr = IDirectInputDevice_SetCooperativeLevel(pJoystick, real_hWnd,
+                                                DISCL_EXCLUSIVE | DISCL_FOREGROUND);
+    ok(hr==DI_OK,"IDirectInputDevice_SetCooperativeLevel() failed: %08x\n", hr);
+    hr = IDirectInputDevice_Acquire(pJoystick);
+    ok(hr==DI_OK,"IDirectInputDevice_Acquire() failed: %08x\n", hr);
 
-        cnt1 = get_refcount((IUnknown*)pJoystick);
+    cnt1 = get_refcount((IUnknown*)pJoystick);
 
-        hr = IDirectInputDevice2_CreateEffect((IDirectInputDevice2A*)pJoystick, &GUID_ConstantForce,
-                                              &eff, &effect, NULL);
+    effect = (void *)0xdeadbeef;
+    hr = IDirectInputDevice2_CreateEffect((IDirectInputDevice2A*)pJoystick, &GUID_ConstantForce,
+                                          &eff, &effect, NULL);
+    if (caps.dwFlags & DIDC_FORCEFEEDBACK)
+    {
+        trace("force feedback supported\n");
         ok(hr == DI_OK, "IDirectInputDevice_CreateEffect() failed: %08x\n", hr);
         cnt2 = get_refcount((IUnknown*)pJoystick);
         ok(cnt1 == cnt2, "Ref count is wrong %d != %d\n", cnt1, cnt2);
@@ -622,18 +623,27 @@ static BOOL CALLBACK EnumJoysticks(const DIDEVICEINSTANCEA *lpddi, void *pvRef)
         }
         cnt1 = get_refcount((IUnknown*)pJoystick);
         ok(cnt1 == cnt2, "Ref count is wrong %d != %d\n", cnt1, cnt2);
-
-        /* Before destroying the window, release joystick to revert to
-         * non-exclusive, background cooperative level. */
-        hr = IDirectInputDevice_Unacquire(pJoystick);
-        ok(hr==DI_OK,"IDirectInputDevice_Unacquire() failed: %08x\n", hr);
-        hr = IDirectInputDevice_SetCooperativeLevel(pJoystick, hWnd,
-                                                    DISCL_NONEXCLUSIVE | DISCL_BACKGROUND);
-        ok(hr==DI_OK,"IDirectInputDevice_SetCooperativeLevel() failed: %08x\n", hr);
-        DestroyWindow (real_hWnd);
-        hr = IDirectInputDevice_Acquire(pJoystick);
-        ok(hr==DI_OK,"IDirectInputDevice_Acquire() failed: %08x\n", hr);
     }
+    /* No force feedback support, CreateEffect is supposed to fail. Fairy Bloom Freesia
+     * calls CreateEffect without checking the DIDC_FORCEFEEDBACK. It expects the correct
+     * error return to determine if force feedback is unsupported. */
+    else
+    {
+        trace("No force feedback support\n");
+        ok(hr==DIERR_UNSUPPORTED, "IDirectInputDevice_CreateEffect() must fail with DIERR_UNSUPPORTED, got: %08x\n", hr);
+        ok(effect == NULL, "effect must be NULL, got %p\n", effect);
+    }
+
+    /* Before destroying the window, release joystick to revert to
+     * non-exclusive, background cooperative level. */
+    hr = IDirectInputDevice_Unacquire(pJoystick);
+    ok(hr==DI_OK,"IDirectInputDevice_Unacquire() failed: %08x\n", hr);
+    hr = IDirectInputDevice_SetCooperativeLevel(pJoystick, hWnd,
+                                                DISCL_NONEXCLUSIVE | DISCL_BACKGROUND);
+    ok(hr==DI_OK,"IDirectInputDevice_SetCooperativeLevel() failed: %08x\n", hr);
+    DestroyWindow (real_hWnd);
+    hr = IDirectInputDevice_Acquire(pJoystick);
+    ok(hr==DI_OK,"IDirectInputDevice_Acquire() failed: %08x\n", hr);
 
     if (winetest_interactive) {
         trace("You have 30 seconds to test all axes, sliders, POVs and buttons\n");