diff --git a/include/wx/msw/private/cotaskmemptr.h b/include/wx/msw/private/cotaskmemptr.h new file mode 100644 index 0000000000..96d54c42ed --- /dev/null +++ b/include/wx/msw/private/cotaskmemptr.h @@ -0,0 +1,85 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: wx/msw/private/cotaskmemptr.h +// Purpose: RAII class for pointers to be freed with ::CoTaskMemFree(). +// Author: PB +// Created: 2020-06-09 +// Copyright: (c) 2020 wxWidgets team +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_MSW_PRIVATE_COTASKMEMPTR_H_ +#define _WX_MSW_PRIVATE_COTASKMEMPTR_H_ + +// needed for ::CoTaskMem{Alloc|Free}() +#include "wx/msw/wrapwin.h" + +// ---------------------------------------------------------------------------- +// wxCoTaskMemPtr: A barebone RAII class for pointers to be freed with ::CoTaskMemFree(). +// ---------------------------------------------------------------------------- + +template +class wxCoTaskMemPtr +{ +public: + typedef T element_type; + + wxCoTaskMemPtr() + : m_ptr(NULL) + {} + + explicit wxCoTaskMemPtr(T* ptr) + : m_ptr(ptr) + {} + + // Uses ::CoTaskMemAlloc() to allocate size bytes. + explicit wxCoTaskMemPtr(size_t size) + : m_ptr(static_cast(::CoTaskMemAlloc(size))) + {} + + ~wxCoTaskMemPtr() + { + ::CoTaskMemFree(m_ptr); + } + + void reset(T* ptr = NULL) + { + if ( m_ptr != ptr ) + { + ::CoTaskMemFree(m_ptr); + m_ptr = ptr; + } + } + + operator T*() const + { + return m_ptr; + } + + // It would be better to forbid direct access completely but we do need it, + // so provide it but it can only be used to initialize the pointer, + // not to modify an existing one. + T** operator&() + { + wxASSERT_MSG(!m_ptr, + wxS("Can't get direct access to initialized pointer")); + + return &m_ptr; + } + + // Gives up the ownership of the pointer, + // making the caller responsible for freeing it. + T* release() + { + T* ptr(m_ptr); + + m_ptr = NULL; + return ptr; + } + +private: + T* m_ptr; + + wxDECLARE_NO_COPY_TEMPLATE_CLASS(wxCoTaskMemPtr, T); +}; + +#endif // _WX_MSW_PRIVATE_COTASKMEMPTR_H_ diff --git a/src/msw/stdpaths.cpp b/src/msw/stdpaths.cpp index 52f7fadb5d..61d183386f 100644 --- a/src/msw/stdpaths.cpp +++ b/src/msw/stdpaths.cpp @@ -36,6 +36,7 @@ #include "wx/msw/private.h" #include "wx/msw/wrapshl.h" +#include "wx/msw/private/cotaskmemptr.h" #include // ---------------------------------------------------------------------------- @@ -171,12 +172,11 @@ wxString wxStandardPaths::DoGetKnownFolder(const GUID& rfid) if ( gs_shellFuncs.pSHGetKnownFolderPath ) { - PWSTR pDir; + wxCoTaskMemPtr pDir; HRESULT hr = gs_shellFuncs.pSHGetKnownFolderPath(rfid, 0, 0, &pDir); if ( SUCCEEDED(hr) ) { dir = pDir; - CoTaskMemFree(pDir); } } diff --git a/src/msw/taskbarbutton.cpp b/src/msw/taskbarbutton.cpp index 7aa6719890..a521cc7c44 100644 --- a/src/msw/taskbarbutton.cpp +++ b/src/msw/taskbarbutton.cpp @@ -29,6 +29,7 @@ #include "wx/msw/taskbarbutton.h" #include "wx/scopedptr.h" #include "wx/msw/private/comptr.h" +#include "wx/msw/private/cotaskmemptr.h" #include #include @@ -498,10 +499,9 @@ wxTaskBarJumpListItem* GetItemFromIShellItem(IShellItem *shellItem) wxTaskBarJumpListItem *item = new wxTaskBarJumpListItem(NULL, wxTASKBAR_JUMP_LIST_DESTINATION); - wchar_t *name; + wxCoTaskMemPtr name; shellItem->GetDisplayName(SIGDN_FILESYSPATH, &name); item->SetFilePath(wxString(name)); - CoTaskMemFree(name); return item; } diff --git a/src/msw/textentry.cpp b/src/msw/textentry.cpp index 0571aa0f70..4939acb3e5 100644 --- a/src/msw/textentry.cpp +++ b/src/msw/textentry.cpp @@ -37,6 +37,7 @@ #include "wx/msw/private.h" #include "wx/msw/private/winstyle.h" +#include "wx/msw/private/cotaskmemptr.h" #if wxUSE_UXTHEME #include "wx/msw/uxtheme.h" @@ -207,13 +208,13 @@ public: const wxWX2WCbuf wcbuf = s.wc_str(); const size_t size = (wcslen(wcbuf) + 1)*sizeof(wchar_t); - void *olestr = CoTaskMemAlloc(size); + wxCoTaskMemPtr olestr(size); + if ( !olestr ) return E_OUTOFMEMORY; memcpy(olestr, wcbuf, size); - - *rgelt++ = static_cast(olestr); + *rgelt++ = olestr.release(); ++(*pceltFetched); } diff --git a/src/msw/webview_edge.cpp b/src/msw/webview_edge.cpp index 4d93570dc6..a907b50d26 100644 --- a/src/msw/webview_edge.cpp +++ b/src/msw/webview_edge.cpp @@ -26,6 +26,7 @@ #include "wx/private/jsscriptwrapper.h" #include "wx/private/json.h" #include "wx/msw/private.h" +#include "wx/msw/private/cotaskmemptr.h" #include "wx/msw/private/webview_edge.h" #include @@ -124,16 +125,10 @@ bool wxWebViewEdgeImpl::Initialize() return false; // Check if a Edge browser can be found by the loader DLL - LPWSTR versionStr; + wxCoTaskMemPtr versionStr; HRESULT hr = wxGetAvailableCoreWebView2BrowserVersionString(NULL, &versionStr); - if (SUCCEEDED(hr)) - { - if (versionStr) - { - CoTaskMemFree(versionStr); - return true; - } - } + if (SUCCEEDED(hr) && versionStr) + return true; else wxLogApiError("GetCoreWebView2BrowserVersionInfo", hr); @@ -161,12 +156,10 @@ HRESULT wxWebViewEdgeImpl::OnNavigationStarting(ICoreWebView2* WXUNUSED(sender), { m_isBusy = true; wxString evtURL; - LPWSTR uri; + wxCoTaskMemPtr uri; if (SUCCEEDED(args->get_Uri(&uri))) - { evtURL = wxString(uri); - CoTaskMemFree(uri); - } + wxWebViewEvent event(wxEVT_WEBVIEW_NAVIGATING, m_ctrl->GetId(), evtURL, wxString()); event.SetEventObject(m_ctrl); m_ctrl->HandleWindowEvent(event); @@ -245,13 +238,10 @@ HRESULT wxWebViewEdgeImpl::OnNavigationCompleted(ICoreWebView2* WXUNUSED(sender) HRESULT wxWebViewEdgeImpl::OnNewWindowRequested(ICoreWebView2* WXUNUSED(sender), ICoreWebView2NewWindowRequestedEventArgs* args) { - LPWSTR uri; + wxCoTaskMemPtr uri; wxString evtURL; if (SUCCEEDED(args->get_Uri(&uri))) - { evtURL = wxString(uri); - CoTaskMemFree(uri); - } wxWebViewNavigationActionFlags navFlags = wxWEBVIEW_NAV_ACTION_OTHER; BOOL isUserInitiated; @@ -519,26 +509,18 @@ bool wxWebViewEdge::IsBusy() const wxString wxWebViewEdge::GetCurrentURL() const { - LPWSTR uri; + wxCoTaskMemPtr uri; if (m_impl->m_webView && SUCCEEDED(m_impl->m_webView->get_Source(&uri))) - { - wxString uriStr(uri); - CoTaskMemFree(uri); - return uriStr; - } + return wxString(uri); else return wxString(); } wxString wxWebViewEdge::GetCurrentTitle() const { - LPWSTR title; + wxCoTaskMemPtr title; if (m_impl->m_webView && SUCCEEDED(m_impl->m_webView->get_DocumentTitle(&title))) - { - wxString titleStr(title); - CoTaskMemFree(title); - return titleStr; - } + return wxString(title); else return wxString(); }