// ==WindhawkMod==
// @id              dwmless-fixer
// @name            DWMLess Fixer
// @description     Fixes apps freezing for no reason when DWM is not running. Also blocks DComp
// @version         1.0
// @author          Ingan121
// @github          https://github.com/Ingan121
// @twitter         https://twitter.com/Ingan121
// @homepage        https://www.ingan121.com/
// @include         *
// @exclude         ctfmon.exe
// @compilerOptions -ldcomp
// ==/WindhawkMod==

// ==WindhawkModReadme==
/*
# DWMLess Fixer
* Fixes windowed applications freezing for no reason when DWM is not running, by denying the text input server creation that makes the window message loop stuck in DWM-less state.
* This mod also blocks applications from using DirectComposition. This should cause graceful fallback to non-DComp rendering for most third-party programs; however, this will (likely) break UWPs and other immersive stuff.
* So don't use this mod unless you have disabled DWM.
*/
// ==/WindhawkModReadme==

#include <windhawk_utils.h>
#include <dcomp.h>

#ifdef _WIN64
#define STHISCALL L"__cdecl"
#else
#define STHISCALL L"__thiscall"
#endif

HRESULT TextInputServerCreate_hook() {
    Wh_Log(L"Deny TIH Init!");
    return E_INVALIDARG;
}

void TextInputHost_Dtor_hook() {
    Wh_Log(L"Ignore TIH Release!");
}

HRESULT DCompositionCreateDevice_hook() {
    Wh_Log(L"Deny DComp Init! (1)");
    return E_INVALIDARG;
}

HRESULT DCompositionCreateDevice2_hook() {
    Wh_Log(L"Deny DComp Init! (2)");
    return E_INVALIDARG;
}

HRESULT DCompositionCreateDevice3_hook() {
    Wh_Log(L"Deny DComp Init! (3)");
    return E_INVALIDARG;
}

WindhawkUtils::SYMBOL_HOOK textInputFrameworkDllHooks[] = {
    {
        {
            L"private: virtual " STHISCALL " TextInputHost::~TextInputHost(void)"
        },
        NULL,
        (void*)TextInputHost_Dtor_hook,
        FALSE
    },
};

BOOL Wh_ModInit() {
    Wh_Log(L"Init");

    HMODULE hTif = LoadLibraryW(L"TextInputFramework.dll");
    if (hTif) {
        void* TextInputServerCreate = (void*)GetProcAddress(hTif, "TextInputServerCreate");
        if (TextInputServerCreate) {
            if (Wh_SetFunctionHook(TextInputServerCreate, (void*)TextInputServerCreate_hook, NULL)) {
                if (WindhawkUtils::HookSymbols(hTif, textInputFrameworkDllHooks, ARRAYSIZE(textInputFrameworkDllHooks))) {
                    Wh_Log(L"TIF Hook OK");
                }
            }
        } else {
            Wh_Log(L"GetProcAddress TextInputServerCreate failed");
        }
    } else {
        Wh_Log(L"TextInputFramework.dll not found");
    }

    if (Wh_SetFunctionHook((void*)DCompositionCreateDevice, (void*)DCompositionCreateDevice_hook, NULL)) {
        if (Wh_SetFunctionHook((void*)DCompositionCreateDevice2, (void*)DCompositionCreateDevice2_hook, NULL)) {
            if (Wh_SetFunctionHook((void*)DCompositionCreateDevice3, (void*)DCompositionCreateDevice3_hook, NULL)) {
                Wh_Log(L"DComp Hook OK");
            }
        }
    }

    return TRUE;
}

void Wh_ModUninit() {
    Wh_Log(L"Uninit");
}