From b5dbb5c65dbb59dbe9c4883b33410f1c1bab92b5 Mon Sep 17 00:00:00 2001 From: Copilot <223556219+Copilot@users.noreply.github.com> Date: Sun, 31 May 2026 20:16:57 -0700 Subject: [PATCH] Pin the host module instead of wrapping a borrowed HMODULE PluginSystem::Load stored the result of GetModuleHandleA(nullptr) in a wil::unique_hmodule for the .exe path. GetModuleHandle returns a borrowed handle that, per the Microsoft docs, must not be passed to FreeLibrary. wil::unique_hmodule calls FreeLibrary on destruction, so the loader refcount on the host module was being decremented in two paths every startup: the immediate destruct when the host did not export Supports, and the eventual unload through PluginBase::m_module when the host was accepted as a plugin. Acquire a real reference with GetModuleHandleExW( GET_MODULE_HANDLE_EX_FLAG_PIN, ...) instead. Pinning makes the eventual FreeLibrary a documented no-op, the loader bookkeeping stays balanced, and the existing RAII model in PluginBase does not have to change. Fixes #142 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/dll/Systems/PluginSystem.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/dll/Systems/PluginSystem.cpp b/src/dll/Systems/PluginSystem.cpp index 8e6f2b1a..685668fa 100644 --- a/src/dll/Systems/PluginSystem.cpp +++ b/src/dll/Systems/PluginSystem.cpp @@ -235,7 +235,16 @@ void PluginSystem::Load(const std::filesystem::path& aPath, bool aUseAlteredSear wil::unique_hmodule handle; if (aPath.extension() == L".exe") - handle.reset(GetModuleHandleA(nullptr)); + { + // GetModuleHandle returns a borrowed handle that must not be passed to FreeLibrary, but + // PluginBase stores the handle in another wil::unique_hmodule. Pin the host module so the + // eventual FreeLibrary call is a documented no-op and the loader refcount stays balanced. + HMODULE raw = nullptr; + if (GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN, nullptr, &raw)) + { + handle.reset(raw); + } + } else handle.reset(LoadLibraryEx(aPath.c_str(), nullptr, flags));