Adopt wil::unique_* RAII for Win32 handles + BSTR/CoTaskMem#39
Conversation
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The three TAP CLR-hosting paths (WPF/WinForms/Avalonia TryNetCore) load hostfxr.dll only as a fallback when it isn't already resident. The original code loaded it and intentionally left it loaded for the process lifetime, since it pins the hosted CoreCLR resolver in a foreign, injected process. The WIL refactor wrapped that fallback load in a scope-owned wil::unique_hmodule, which would FreeLibrary(hostfxr) on TryNetCore return -- a behavior change that could unload a host library out from under the still-running runtime. (In the common case hostfxr is already loaded, so the wrapper was empty and this only bit the load-fallback path.) Restore the exact original behavior: load hostfxr as a raw, intentionally resident HMODULE with a comment explaining why it must not be scope-freed. mscoree in the .NET Framework path is unaffected -- it is a shim over the app's own already-loaded CLR and was already freed by the original, so unique_hmodule there is a safe improvement. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Review follow-up: kept hostfxr resident in the TAP CLR hosts (pushed f786a64)Reviewed the full diff (screenshot GDI, all pipe/event handles, process-injection, plugin loader, tap natives). The handle mapping is correct throughout — notably One behavior change fixed (commit f786a64): the three Validation after the fix: |
cdb validation of the full handle refactor (139 sites) — cleanRan lvt.exe under cdb (which raises
This exercises both sides of the refactor: lvt.exe's inject/pipe/screenshot/plugin-loader handle code and the injected TAP DLLs' handle code (a target-side double-close would crash the target — none did). Enrichment succeeding proves the handle code ran the full inject→pipe→read→graft path, not just early-outs. Combined with: build green, 60/60 unit, CI green, and the hostfxr fix being a proven revert to Caveat (unchanged): the rare hostfxr load-fallback branch still isn't force-exercised (a running .NET app has hostfxr resident), but everything around it is now debugger-verified and the fix itself is behavior-identical to shipped |
Fixes #37
Summary
wil::unique_*RAII across core providers, plugin loader, plugins, TAP DLLs, screenshot GDI, and integration fixtures.src\tap\lvt_tap.cpptowil::unique_bstrandwil::unique_cotaskmem.lvt_avalonia_plugin,lvt_avalonia_tap,lvt_chromium_plugin, andlvt_chromium_host.Converted sites
unique_handle28,unique_event16,unique_hfile12,unique_hmodule8,unique_hlocal6,unique_hfind4,unique_bstr8,unique_cotaskmem2, plusunique_hdc/GDI wrappers,unique_hkey, andunique_hwnd.CloseHandle,FreeLibrary,DeleteObject,DeleteDC,RegCloseKey,FindClose,SysFreeString,CoTaskMemFree,LocalFree,DestroyWindow).Deliberately left raw
tests\integration_tests.cppwindow-procDestroyWindow(hwnd): the HWND is destroyed on its owning UI thread in response to a close message, not a scope-owned resource.FreeLibraryAndExitThreadcalls remain raw by design because they atomically unload the injected DLL and exit the worker thread.GetStdHandleandGetModuleHandle*results remain raw/non-owning borrowed handles.Validation
cmake --preset defaultpassed.dotnet build src\tap_wpf\LvtWpfTap.csproj -c Releasepassed.dotnet build src\plugin_avalonia\LvtAvaloniaTreeWalker\LvtAvaloniaTreeWalker.csproj -c Releasepassed.dotnet build src\tap_winforms\LvtWinFormsTap.csproj -c Releasepassed.cmake --build buildpassed (existing Avalonia package vulnerability warnings; WinUI3 projection macro warning).build\lvt_unit_tests.exe: 60/60 passed.build\lvt_chromium_tests.exe: 18/18 passed.build\lvt_integration_tests.exe: 31 passed, 1 skipped (NotepadFixture.XamlBoundsIfDetected, XAML/UWP not detected for this Notepad instance).KnownWindowFixture.*:ComCtlWindowFixture.*5/5 passed.--frameworksreturnedwin32+winui3 2.2.0.0; screenshot smoke wrote a 47,748-byte PNG and was cleaned up; WinUI3 sample XML smoke wrote 36,560 bytes.