From 797a6910fd4575805c5f054f680f12f1924ec116 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 9 Dec 2020 20:28:51 -0800 Subject: [PATCH] Fixed bug 5375 - WGI: Fix HSTRING memory leak. Joel Linn TLDR; https://godbolt.org/z/43fd8G Let's deduce this from C++ reference code: https://docs.microsoft.com/en-us/cpp/cppcx/wrl/how-to-activate-and-use-a-windows-runtime-component-using-wrl?view=msvc-160 At the bottom of the page there is this snippet: ``` int wmain() { /* ... more code ... */ // Get the domain part of the URI. HString domainName; hr = uri->get_Domain(domainName.GetAddressOf()); if (FAILED(hr)) { return PrintError(__LINE__, hr); } // Print the domain name and return. wprintf_s(L"Domain name: %s\n", domainName.GetRawBuffer(nullptr)); // All smart pointers and RAII objects go out of scope here. } ``` `HString` is defined in `corewrappers.h` and the call chain for the destructor is: `~HString() -> Release() -> ::WindowsDeleteString()` QED --- .../windows/SDL_windows_gaming_input.c | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/joystick/windows/SDL_windows_gaming_input.c b/src/joystick/windows/SDL_windows_gaming_input.c index daf9bfe20..29a9c7682 100644 --- a/src/joystick/windows/SDL_windows_gaming_input.c +++ b/src/joystick/windows/SDL_windows_gaming_input.c @@ -184,23 +184,25 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(controller, &IID_IRawGameController2, (void **)&controller2); if (SUCCEEDED(hr)) { - HSTRING hString; + HMODULE hModule = LoadLibraryA("combase.dll"); + if (hModule != NULL) { + typedef PCWSTR (WINAPI *WindowsGetStringRawBuffer_t)(HSTRING string, UINT32 *length); + typedef HRESULT (WINAPI *WindowsDeleteString_t)(HSTRING string); - hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController2_get_DisplayName(controller2, &hString); - if (SUCCEEDED(hr)) { - HMODULE hModule = LoadLibraryA("combase.dll"); - if (hModule != NULL) { - typedef PCWSTR (WINAPI *WindowsGetStringRawBuffer_t)(HSTRING string, UINT32 *length); - - WindowsGetStringRawBuffer_t WindowsGetStringRawBufferFunc = (WindowsGetStringRawBuffer_t)GetProcAddress(hModule, "WindowsGetStringRawBuffer"); - if (WindowsGetStringRawBufferFunc) { + WindowsGetStringRawBuffer_t WindowsGetStringRawBufferFunc = (WindowsGetStringRawBuffer_t)GetProcAddress(hModule, "WindowsGetStringRawBuffer"); + WindowsDeleteString_t WindowsDeleteStringFunc = (WindowsDeleteString_t)GetProcAddress(hModule, "WindowsDeleteString"); + if (WindowsGetStringRawBufferFunc && WindowsDeleteStringFunc) { + HSTRING hString; + hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController2_get_DisplayName(controller2, &hString); + if (SUCCEEDED(hr)) { PCWSTR string = WindowsGetStringRawBufferFunc(hString, NULL); if (string) { name = WIN_StringToUTF8(string); } + WindowsDeleteStringFunc(hString); } - FreeLibrary(hModule); } + FreeLibrary(hModule); } __x_ABI_CWindows_CGaming_CInput_CIRawGameController2_Release(controller2); }