diff --git a/Dalamud.Boot/dllmain.cpp b/Dalamud.Boot/dllmain.cpp index 06538a38f..2ad8bb20d 100644 --- a/Dalamud.Boot/dllmain.cpp +++ b/Dalamud.Boot/dllmain.cpp @@ -59,7 +59,7 @@ bool is_full_dumps() return check_env_var("DALAMUD_IS_VEH_FULL"); } -DllExport DWORD WINAPI Initialize(LPVOID lpParam) +DllExport DWORD WINAPI Initialize(LPVOID lpParam, HANDLE hMainThreadContinue) { #ifndef NDEBUG ConsoleSetup(L"Dalamud Boot"); @@ -97,7 +97,7 @@ DllExport DWORD WINAPI Initialize(LPVOID lpParam) if (result != 0) return result; - typedef void (CORECLR_DELEGATE_CALLTYPE* custom_component_entry_point_fn)(LPVOID); + typedef void (CORECLR_DELEGATE_CALLTYPE* custom_component_entry_point_fn)(LPVOID, HANDLE); custom_component_entry_point_fn entrypoint_fn = reinterpret_cast(entrypoint_vfn); // ============================== VEH ======================================== // @@ -121,7 +121,7 @@ DllExport DWORD WINAPI Initialize(LPVOID lpParam) // ============================== Dalamud ==================================== // printf("Initializing Dalamud... "); - entrypoint_fn(lpParam); + entrypoint_fn(lpParam, hMainThreadContinue); printf("Done!\n"); #ifndef NDEBUG diff --git a/Dalamud.Boot/rewrite_entrypoint.cpp b/Dalamud.Boot/rewrite_entrypoint.cpp index c79960859..4092a39bc 100644 --- a/Dalamud.Boot/rewrite_entrypoint.cpp +++ b/Dalamud.Boot/rewrite_entrypoint.cpp @@ -1,6 +1,6 @@ #include "pch.h" -DllExport DWORD WINAPI Initialize(LPVOID lpParam); +DllExport DWORD WINAPI Initialize(LPVOID lpParam, HANDLE hMainThreadContinue); struct RewrittenEntryPointParameters { void* pAllocation; @@ -379,8 +379,9 @@ DllExport void WINAPI RewrittenEntryPoint(RewrittenEntryPointParameters& params) params.hMainThread = CreateThread(nullptr, 0, [](void* p) -> DWORD { try { std::string loadInfo; + auto& params = *reinterpret_cast(p); { - auto& params = *reinterpret_cast(p); + // Restore original entry point. // Use WriteProcessMemory instead of memcpy to avoid having to fiddle with VirtualProtect. @@ -390,12 +391,12 @@ DllExport void WINAPI RewrittenEntryPoint(RewrittenEntryPointParameters& params) loadInfo = params.pLoadInfo; // Let the game initialize. - SetEvent(params.hMainThreadContinue); + //SetEvent(params.hMainThreadContinue); } - wait_for_game_window(); + //wait_for_game_window(); - Initialize(&loadInfo[0]); + Initialize(&loadInfo[0], params.hMainThreadContinue); return 0; } catch (const std::exception& e) { MessageBoxA(nullptr, std::format("Failed to load Dalamud.\n\nError: {}", e.what()).c_str(), "Dalamud.Boot", MB_OK | MB_ICONERROR); diff --git a/Dalamud/Dalamud.cs b/Dalamud/Dalamud.cs index b515a36d7..033d06f41 100644 --- a/Dalamud/Dalamud.cs +++ b/Dalamud/Dalamud.cs @@ -49,6 +49,7 @@ namespace Dalamud private readonly ManualResetEvent unloadSignal; private readonly ManualResetEvent finishUnloadSignal; + private readonly IntPtr mainThreadContinueEvent; private MonoMod.RuntimeDetour.Hook processMonoHook; private bool hasDisposedPlugins = false; @@ -61,7 +62,8 @@ namespace Dalamud /// LoggingLevelSwitch to control Serilog level. /// Signal signalling shutdown. /// The Dalamud configuration. - public Dalamud(DalamudStartInfo info, LoggingLevelSwitch loggingLevelSwitch, ManualResetEvent finishSignal, DalamudConfiguration configuration) + /// Event used to signal the main thread to continue. + public Dalamud(DalamudStartInfo info, LoggingLevelSwitch loggingLevelSwitch, ManualResetEvent finishSignal, DalamudConfiguration configuration, IntPtr mainThreadContinueEvent) { this.ApplyProcessPatch(); @@ -76,6 +78,8 @@ namespace Dalamud this.finishUnloadSignal = finishSignal; this.finishUnloadSignal.Reset(); + + this.mainThreadContinueEvent = mainThreadContinueEvent; } /// @@ -107,6 +111,13 @@ namespace Dalamud var gameFixes = Service.Set(); gameFixes.Apply(); + Log.Information("[T1] GameFixes OK!"); + + // Signal the main game thread to continue + NativeFunctions.SetEvent(this.mainThreadContinueEvent); + + Log.Information("[T1] Game thread continued!"); + // Initialize FFXIVClientStructs function resolver FFXIVClientStructs.Resolver.Initialize(); Log.Information("[T1] FFXIVClientStructs initialized!"); diff --git a/Dalamud/EntryPoint.cs b/Dalamud/EntryPoint.cs index 4cb413f90..c02557741 100644 --- a/Dalamud/EntryPoint.cs +++ b/Dalamud/EntryPoint.cs @@ -29,7 +29,8 @@ namespace Dalamud /// A delegate used during initialization of the CLR from Dalamud.Boot. /// /// Pointer to a serialized data. - public delegate void InitDelegate(IntPtr infoPtr); + /// Event used to signal the main thread to continue. + public delegate void InitDelegate(IntPtr infoPtr, IntPtr mainThreadContinueEvent); /// /// A delegate used from VEH handler on exception which CoreCLR will fast fail by default. @@ -43,12 +44,13 @@ namespace Dalamud /// Initialize Dalamud. /// /// Pointer to a serialized data. - public static void Initialize(IntPtr infoPtr) + /// Event used to signal the main thread to continue. + public static void Initialize(IntPtr infoPtr, IntPtr mainThreadContinueEvent) { var infoStr = Marshal.PtrToStringUTF8(infoPtr); var info = JsonConvert.DeserializeObject(infoStr); - new Thread(() => RunThread(info)).Start(); + new Thread(() => RunThread(info, mainThreadContinueEvent)).Start(); } /// @@ -106,7 +108,8 @@ namespace Dalamud /// Initialize all Dalamud subsystems and start running on the main thread. /// /// The containing information needed to initialize Dalamud. - private static void RunThread(DalamudStartInfo info) + /// Event used to signal the main thread to continue. + private static void RunThread(DalamudStartInfo info, IntPtr mainThreadContinueEvent) { // Setup logger var levelSwitch = InitLogging(info.WorkingDirectory); @@ -142,11 +145,12 @@ namespace Dalamud if (!Util.IsLinux()) InitSymbolHandler(info); - var dalamud = new Dalamud(info, levelSwitch, finishSignal, configuration); + var dalamud = new Dalamud(info, levelSwitch, finishSignal, configuration, mainThreadContinueEvent); Log.Information("Starting a session.."); // Run session dalamud.LoadTier1(); + dalamud.WaitForUnload(); dalamud.Dispose(); diff --git a/Dalamud/Fixes/WndProcNullRefFix.cs b/Dalamud/Fixes/WndProcNullRefFix.cs index 472c2cfca..d97263560 100644 --- a/Dalamud/Fixes/WndProcNullRefFix.cs +++ b/Dalamud/Fixes/WndProcNullRefFix.cs @@ -46,8 +46,10 @@ internal class WndProcNullRefFix : IGameFix, IDisposable Log.Information($"Applying WndProcNullRefFix at {patchAddress:X} with o1 {this.object1Address:X}, o2 {this.object2Address:X}"); - this.wndProcHook = new Hook(patchAddress, this.WndProcDetour); + this.wndProcHook = new Hook(patchAddress, this.WndProcDetour, true); + Log.Information("Set up hook"); this.wndProcHook.Enable(); + Log.Information("Enabled hook"); } /// diff --git a/Dalamud/Interface/Internal/DalamudInterface.cs b/Dalamud/Interface/Internal/DalamudInterface.cs index af096cc8a..9130f2072 100644 --- a/Dalamud/Interface/Internal/DalamudInterface.cs +++ b/Dalamud/Interface/Internal/DalamudInterface.cs @@ -1,12 +1,17 @@ + + +#define BOOT_AGING + using System; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; +using System.Net.Http; using System.Numerics; using System.Reflection; using System.Runtime.InteropServices; - +using System.Threading.Tasks; using CheapLoc; using Dalamud.Configuration.Internal; using Dalamud.Game.ClientState.Conditions; @@ -29,7 +34,6 @@ using ImGuiNET; using ImGuiScene; using PInvoke; using Serilog.Events; - namespace Dalamud.Interface.Internal { /// @@ -350,10 +354,25 @@ namespace Dalamud.Interface.Internal #endregion + private bool signaledBoot = false; + private void OnDraw() { this.frameCount++; +#if BOOT_AGING + if (this.frameCount > 500 && !this.signaledBoot) + { + this.signaledBoot = true; + + Task.Run(async () => + { + using var client = new HttpClient(); + await client.PostAsync("http://localhost:1415/aging/success", new StringContent(string.Empty)); + }); + } +#endif + try { this.DrawHiddenDevMenuOpener(); diff --git a/Dalamud/NativeFunctions.cs b/Dalamud/NativeFunctions.cs index d11c39464..5b03eeb33 100644 --- a/Dalamud/NativeFunctions.cs +++ b/Dalamud/NativeFunctions.cs @@ -1393,6 +1393,18 @@ namespace Dalamud WriteCombine = 0x400, } + /// + /// See https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-setevent + /// Sets the specified event object to the signaled state. + /// + /// A handle to the event object. The CreateEvent or OpenEvent function returns this handle. + /// + /// If the function succeeds, the return value is nonzero. + /// If the function fails, the return value is zero. To get extended error information, call GetLastError. + /// + [DllImport("kernel32.dll")] + public static extern bool SetEvent(IntPtr hEvent); + /// /// See https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-freelibrary. /// Frees the loaded dynamic-link library (DLL) module and, if necessary, decrements its reference count. When the reference diff --git a/lib/CoreCLR/boot.cpp b/lib/CoreCLR/boot.cpp index acdba1909..0ff9a00a0 100644 --- a/lib/CoreCLR/boot.cpp +++ b/lib/CoreCLR/boot.cpp @@ -105,7 +105,7 @@ int InitializeClrAndGetEntryPoint( dotnet_path, }; - printf("Loading coreclr... ");; + printf("Loading coreclr... "); if ((result = g_clr->load_runtime(runtimeconfig_path, &runtime_parameters)) != 0) { printf("\nError: Failed to load coreclr (err=%d)\n", result);