Add wxCoTaskMemPtr and use it instead of manual calls to
::CoTaskMemFree().

See https://github.com/wxWidgets/wxWidgets/pull/1890
This commit is contained in:
Vadim Zeitlin 2020-06-10 18:02:50 +02:00
commit 5e06174c95
5 changed files with 104 additions and 36 deletions

View File

@ -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 T>
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<T*>(::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_

View File

@ -36,6 +36,7 @@
#include "wx/msw/private.h"
#include "wx/msw/wrapshl.h"
#include "wx/msw/private/cotaskmemptr.h"
#include <initguid.h>
// ----------------------------------------------------------------------------
@ -171,12 +172,11 @@ wxString wxStandardPaths::DoGetKnownFolder(const GUID& rfid)
if ( gs_shellFuncs.pSHGetKnownFolderPath )
{
PWSTR pDir;
wxCoTaskMemPtr<wchar_t> pDir;
HRESULT hr = gs_shellFuncs.pSHGetKnownFolderPath(rfid, 0, 0, &pDir);
if ( SUCCEEDED(hr) )
{
dir = pDir;
CoTaskMemFree(pDir);
}
}

View File

@ -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 <shlwapi.h>
#include <initguid.h>
@ -498,10 +499,9 @@ wxTaskBarJumpListItem* GetItemFromIShellItem(IShellItem *shellItem)
wxTaskBarJumpListItem *item =
new wxTaskBarJumpListItem(NULL, wxTASKBAR_JUMP_LIST_DESTINATION);
wchar_t *name;
wxCoTaskMemPtr<wchar_t> name;
shellItem->GetDisplayName(SIGDN_FILESYSPATH, &name);
item->SetFilePath(wxString(name));
CoTaskMemFree(name);
return item;
}

View File

@ -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<wchar_t> olestr(size);
if ( !olestr )
return E_OUTOFMEMORY;
memcpy(olestr, wcbuf, size);
*rgelt++ = static_cast<LPOLESTR>(olestr);
*rgelt++ = olestr.release();
++(*pceltFetched);
}

View File

@ -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 <wrl/event.h>
@ -124,16 +125,10 @@ bool wxWebViewEdgeImpl::Initialize()
return false;
// Check if a Edge browser can be found by the loader DLL
LPWSTR versionStr;
wxCoTaskMemPtr<wchar_t> 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<wchar_t> 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<wchar_t> 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<wchar_t> 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<wchar_t> 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();
}