diff --git a/WineFix/Patches/FontEnumerationPatch.cs b/WineFix/Patches/FontEnumerationPatch.cs new file mode 100644 index 0000000..85cbee1 --- /dev/null +++ b/WineFix/Patches/FontEnumerationPatch.cs @@ -0,0 +1,55 @@ +using System; +using System.Linq; +using System.Reflection; +using HarmonyLib; +using AffinityPluginLoader.Core; + +namespace WineFix.Patches +{ + /// + /// Disables parallel font enumeration on Wine to avoid an intermittent + /// access violation (0xC0000005) in libkernel.dll during startup font loading. + /// + public static class FontEnumerationPatch + { + public static void ApplyPatches(Harmony harmony) + { + Logger.Info("Applying FontEnumeration patch (Wine fix)..."); + + var serifAssembly = AppDomain.CurrentDomain.GetAssemblies() + .FirstOrDefault(a => a.GetName().Name == "Serif.Affinity"); + + if (serifAssembly == null) + { + Logger.Error("Serif.Affinity assembly not found"); + return; + } + + var appType = serifAssembly.GetType("Serif.Affinity.Application"); + if (appType == null) + { + Logger.Error("Serif.Affinity.Application type not found"); + return; + } + + var prop = appType.GetProperty("ParallelFontEnumerationDisabled", + BindingFlags.Public | BindingFlags.Instance); + + if (prop?.GetGetMethod() != null) + { + harmony.Patch(prop.GetGetMethod(), + postfix: new HarmonyMethod(typeof(FontEnumerationPatch), nameof(ForceDisabled))); + Logger.Info("Patched ParallelFontEnumerationDisabled to return true"); + } + else + { + Logger.Error("ParallelFontEnumerationDisabled property not found"); + } + } + + public static void ForceDisabled(ref bool __result) + { + __result = true; + } + } +} diff --git a/WineFix/WineFixPlugin.cs b/WineFix/WineFixPlugin.cs index 58019a5..31d9982 100644 --- a/WineFix/WineFixPlugin.cs +++ b/WineFix/WineFixPlugin.cs @@ -1,5 +1,6 @@ using HarmonyLib; using AffinityPluginLoader; +using AffinityPluginLoader.Settings; namespace WineFix { @@ -8,10 +9,28 @@ namespace WineFix /// public class WineFixPlugin : AffinityPlugin { + public const string SettingForceSyncFontEnum = "force_sync_font_enum"; + + public override PluginSettingsDefinition DefineSettings() + { + return new PluginSettingsDefinition("winefix") + .AddSection("Crash Fixes") + .AddBool(SettingForceSyncFontEnum, "Force synchronous font enumeration", + defaultValue: true, + restartRequired: true, + description: "Disable parallel font enumeration to significantly reduce frequency of startup crashes. May increase application startup time on systems with lots of fonts."); + } + public override void OnPatch(Harmony harmony, IPluginContext context) { context.Patch("MainWindowLoaded fix", h => Patches.MainWindowLoadedPatch.ApplyPatches(h)); + + if (context.Settings.GetEffectiveValue(SettingForceSyncFontEnum)) + { + context.Patch("FontEnumeration fix", + h => Patches.FontEnumerationPatch.ApplyPatches(h)); + } } } }