Merge branch 'wine-heap-fix'

Wine heap fix and other global memory-related cleanup.

See https://github.com/wxWidgets/wxWidgets/pull/2030
This commit is contained in:
Vadim Zeitlin
2020-08-24 00:18:57 +02:00
5 changed files with 80 additions and 89 deletions

View File

@@ -773,6 +773,15 @@ public:
void *Get() const { return m_ptr; } void *Get() const { return m_ptr; }
operator void *() const { return m_ptr; } operator void *() const { return m_ptr; }
size_t GetSize() const
{
const size_t size = ::GlobalSize(m_hGlobal);
if ( !size )
wxLogLastError(wxT("GlobalSize"));
return size;
}
private: private:
HGLOBAL m_hGlobal; HGLOBAL m_hGlobal;
void *m_ptr; void *m_ptr;

View File

@@ -245,9 +245,12 @@ bool wxSetClipboardData(wxDataFormat dataFormat,
abs(ds.dsBmih.biHeight); abs(ds.dsBmih.biHeight);
HANDLE hMem; HANDLE hMem;
hMem = ::GlobalAlloc(GHND, ds.dsBmih.biSize + numColors*sizeof(RGBQUAD) + bmpSize); hMem = ::GlobalAlloc(GHND, ds.dsBmih.biSize + numColors*sizeof(RGBQUAD) + bmpSize);
if ( hMem ) if ( !hMem )
break;
{ {
char* pDst = (char*)::GlobalLock(hMem); GlobalPtrLock ptr(hMem);
char* pDst = (char*)ptr.Get();
memcpy(pDst, &ds.dsBmih, ds.dsBmih.biSize); memcpy(pDst, &ds.dsBmih, ds.dsBmih.biSize);
pDst += ds.dsBmih.biSize; pDst += ds.dsBmih.biSize;
if ( numColors > 0 ) if ( numColors > 0 )
@@ -259,9 +262,9 @@ bool wxSetClipboardData(wxDataFormat dataFormat,
pDst += numColors*sizeof(RGBQUAD); pDst += numColors*sizeof(RGBQUAD);
} }
memcpy(pDst, dib.GetData(), bmpSize); memcpy(pDst, dib.GetData(), bmpSize);
::GlobalUnlock(hMem); } // unlock hMem
handle = ::SetClipboardData(CF_DIB, hMem);
} handle = ::SetClipboardData(CF_DIB, hMem);
} }
} }
break; break;
@@ -276,14 +279,16 @@ bool wxSetClipboardData(wxDataFormat dataFormat,
{ {
wxMetafile *wxMF = (wxMetafile *)data; wxMetafile *wxMF = (wxMetafile *)data;
HANDLE data = GlobalAlloc(GHND, sizeof(METAFILEPICT) + 1); HANDLE data = GlobalAlloc(GHND, sizeof(METAFILEPICT) + 1);
METAFILEPICT *mf = (METAFILEPICT *)GlobalLock(data); {
GlobalPtrLock ptr(data);
METAFILEPICT *mf = (METAFILEPICT *)data.Get();
mf->mm = wxMF->GetWindowsMappingMode(); mf->mm = wxMF->GetWindowsMappingMode();
mf->xExt = width; mf->xExt = width;
mf->yExt = height; mf->yExt = height;
mf->hMF = (HMETAFILE) wxMF->GetHMETAFILE(); mf->hMF = (HMETAFILE) wxMF->GetHMETAFILE();
GlobalUnlock(data); wxMF->SetHMETAFILE((WXHANDLE) NULL);
wxMF->SetHMETAFILE((WXHANDLE) NULL); } // unlock data
handle = SetClipboardData(CF_METAFILEPICT, data); handle = SetClipboardData(CF_METAFILEPICT, data);
break; break;
@@ -326,11 +331,7 @@ bool wxSetClipboardData(wxDataFormat dataFormat,
HANDLE hGlobalMemory = GlobalAlloc(GHND, l); HANDLE hGlobalMemory = GlobalAlloc(GHND, l);
if ( hGlobalMemory ) if ( hGlobalMemory )
{ {
LPSTR lpGlobalMemory = (LPSTR)GlobalLock(hGlobalMemory); memcpy(GlobalPtrLock(hGlobalMemory), s, l);
memcpy(lpGlobalMemory, s, l);
GlobalUnlock(hGlobalMemory);
} }
handle = SetClipboardData(dataFormat, hGlobalMemory); handle = SetClipboardData(dataFormat, hGlobalMemory);
@@ -344,9 +345,7 @@ bool wxSetClipboardData(wxDataFormat dataFormat,
HANDLE hGlobalMemory = ::GlobalAlloc(GHND, size); HANDLE hGlobalMemory = ::GlobalAlloc(GHND, size);
if ( hGlobalMemory ) if ( hGlobalMemory )
{ {
LPWSTR lpGlobalMemory = (LPWSTR)::GlobalLock(hGlobalMemory); memcpy(GlobalPtrLock(hGlobalMemory), s, size);
memcpy(lpGlobalMemory, s, size);
::GlobalUnlock(hGlobalMemory);
} }
handle = ::SetClipboardData(CF_UNICODETEXT, hGlobalMemory); handle = ::SetClipboardData(CF_UNICODETEXT, hGlobalMemory);
@@ -407,9 +406,7 @@ bool wxSetClipboardData(wxDataFormat dataFormat,
HGLOBAL hText = GlobalAlloc(GMEM_MOVEABLE |GMEM_DDESHARE, strlen(buf)+4); HGLOBAL hText = GlobalAlloc(GMEM_MOVEABLE |GMEM_DDESHARE, strlen(buf)+4);
// Put your string in the global memory... // Put your string in the global memory...
ptr = (char *)GlobalLock(hText); strcpy((char*)GlobalPtrLock(hText).Get(), buf);
strcpy(ptr, buf);
GlobalUnlock(hText);
handle = ::SetClipboardData(gs_htmlcfid, hText); handle = ::SetClipboardData(gs_htmlcfid, hText);
@@ -861,11 +858,9 @@ bool wxClipboard::GetData( wxDataObject& data )
if ( hMem ) if ( hMem )
{ {
wxTextDataObject& textDataObject = (wxTextDataObject &)data; wxTextDataObject& textDataObject = (wxTextDataObject &)data;
const void* buf = ::GlobalLock(hMem);
DWORD size = ::GlobalSize(hMem); GlobalPtrLock ptr(hMem);
bool ok = textDataObject.SetData(size, buf); return textDataObject.SetData(ptr.GetSize(), ptr);
::GlobalUnlock(hMem);
return ok;
} }
} }
break; break;
@@ -885,11 +880,9 @@ bool wxClipboard::GetData( wxDataObject& data )
if ( hMem ) if ( hMem )
{ {
wxBitmapDataObject& bitmapDataObject = (wxBitmapDataObject &)data; wxBitmapDataObject& bitmapDataObject = (wxBitmapDataObject &)data;
const void* buf = ::GlobalLock(hMem);
DWORD size = ::GlobalSize(hMem); GlobalPtrLock ptr(hMem);
bool ok = bitmapDataObject.SetData(size, buf); return bitmapDataObject.SetData(ptr.GetSize(), ptr);
::GlobalUnlock(hMem);
return ok;
} }
} }
break; break;
@@ -901,11 +894,9 @@ bool wxClipboard::GetData( wxDataObject& data )
if ( hMem ) if ( hMem )
{ {
wxMetafileDataObject& metaFileDataObject = (wxMetafileDataObject &)data; wxMetafileDataObject& metaFileDataObject = (wxMetafileDataObject &)data;
const void* buf = ::GlobalLock(hMem);
DWORD size = ::GlobalSize(hMem); GlobalPtrLock ptr(hMem);
bool ok = metaFileDataObject.SetData(wxDF_METAFILE, size, buf); return metaFileDataObject.SetData(wxDF_METAFILE, ptr.GetSize(), ptr);
::GlobalUnlock(hMem);
return ok;
} }
} }
break; break;

View File

@@ -266,14 +266,17 @@ static bool wxGetDefaultDeviceName(wxString& deviceName, wxString& portName)
if (pd.hDevNames) if (pd.hDevNames)
{ {
lpDevNames = (LPDEVNAMES)GlobalLock(pd.hDevNames); {
lpszDeviceName = (LPTSTR)lpDevNames + lpDevNames->wDeviceOffset; GlobalPtrLock ptr(pd.hDevNames);
lpszPortName = (LPTSTR)lpDevNames + lpDevNames->wOutputOffset;
deviceName = lpszDeviceName; lpDevNames = (LPDEVNAMES)ptr.Get();
portName = lpszPortName; lpszDeviceName = (LPTSTR)lpDevNames + lpDevNames->wDeviceOffset;
lpszPortName = (LPTSTR)lpDevNames + lpDevNames->wOutputOffset;
deviceName = lpszDeviceName;
portName = lpszPortName;
} // unlock pd.hDevNames
GlobalUnlock(pd.hDevNames);
GlobalFree(pd.hDevNames); GlobalFree(pd.hDevNames);
pd.hDevNames=NULL; pd.hDevNames=NULL;
} }

View File

@@ -95,16 +95,15 @@ HGLOBAL wxGlobalClone(HGLOBAL hglobIn)
{ {
HGLOBAL hglobOut = NULL; HGLOBAL hglobOut = NULL;
LPVOID pvIn = GlobalLock(hglobIn); GlobalPtrLock ptrIn(hglobIn);
if (pvIn) if (ptrIn)
{ {
SIZE_T cb = GlobalSize(hglobIn); SIZE_T cb = ptrIn.GetSize();
hglobOut = GlobalAlloc(GMEM_FIXED, cb); hglobOut = GlobalAlloc(GMEM_FIXED, cb);
if (hglobOut) if (hglobOut)
{ {
CopyMemory(hglobOut, pvIn, cb); CopyMemory(hglobOut, ptrIn, cb);
} }
GlobalUnlock(hglobIn);
} }
return hglobOut; return hglobOut;
@@ -637,27 +636,18 @@ STDMETHODIMP wxIDataObject::GetDataHere(FORMATETC *pformatetc,
case TYMED_HGLOBAL: case TYMED_HGLOBAL:
{ {
// copy data // copy data
HGLOBAL hGlobal = pmedium->hGlobal; GlobalPtrLock ptr(pmedium->hGlobal);
void *pBuf = GlobalLock(hGlobal); if ( !ptr )
if ( pBuf == NULL ) {
wxLogLastError(wxT("GlobalLock"));
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
}
wxDataFormat format = pformatetc->cfFormat; wxDataFormat format = pformatetc->cfFormat;
// possibly put the size in the beginning of the buffer // possibly put the size in the beginning of the buffer
pBuf = m_pDataObject->SetSizeInBuffer void* const pBuf =
( m_pDataObject->SetSizeInBuffer(ptr, ptr.GetSize(), format);
pBuf,
::GlobalSize(hGlobal),
format
);
if ( !m_pDataObject->GetDataHere(format, pBuf) ) if ( !m_pDataObject->GetDataHere(format, pBuf) )
return E_UNEXPECTED; return E_UNEXPECTED;
GlobalUnlock(hGlobal);
} }
break; break;
@@ -713,12 +703,9 @@ STDMETHODIMP wxIDataObject::SetData(FORMATETC *pformatetc,
} }
// copy data // copy data
const void *pBuf = GlobalLock(pmedium->hGlobal); GlobalPtrLock ptr(pmedium->hGlobal);
if ( pBuf == NULL ) { if ( !ptr )
wxLogLastError(wxT("GlobalLock"));
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
}
// we've got a problem with SetData() here because the base // we've got a problem with SetData() here because the base
// class version requires the size parameter which we don't // class version requires the size parameter which we don't
@@ -731,14 +718,14 @@ STDMETHODIMP wxIDataObject::SetData(FORMATETC *pformatetc,
case wxDF_HTML: case wxDF_HTML:
case CF_TEXT: case CF_TEXT:
case CF_OEMTEXT: case CF_OEMTEXT:
size = strlen((const char *)pBuf); size = strlen((const char *)ptr.Get());
break; break;
#if !(defined(__BORLANDC__) && (__BORLANDC__ < 0x500)) #if !(defined(__BORLANDC__) && (__BORLANDC__ < 0x500))
case CF_UNICODETEXT: case CF_UNICODETEXT:
#if ( defined(__BORLANDC__) && (__BORLANDC__ > 0x530) ) #if ( defined(__BORLANDC__) && (__BORLANDC__ > 0x530) )
size = std::wcslen((const wchar_t *)pBuf) * sizeof(wchar_t); size = std::wcslen((const wchar_t *)ptr.Get()) * sizeof(wchar_t);
#else #else
size = wxWcslen((const wchar_t *)pBuf) * sizeof(wchar_t); size = wxWcslen((const wchar_t *)ptr.Get()) * sizeof(wchar_t);
#endif #endif
break; break;
#endif #endif
@@ -758,19 +745,24 @@ STDMETHODIMP wxIDataObject::SetData(FORMATETC *pformatetc,
case CF_METAFILEPICT: case CF_METAFILEPICT:
size = sizeof(METAFILEPICT); size = sizeof(METAFILEPICT);
break; break;
default: default:
pBuf = m_pDataObject-> size = ptr.GetSize();
GetSizeFromBuffer(pBuf, &size, format);
size -= m_pDataObject->GetBufferOffset(format); // Account for the possible offset.
const size_t
ofs = m_pDataObject->GetBufferOffset(format);
// Check that it has a reasonable value to avoid
// overflow.
if ( ofs > size )
return E_UNEXPECTED;
size -= ofs;
} }
bool ok = m_pDataObject->SetData(format, size, pBuf); if ( !m_pDataObject->SetData(format, size, ptr.Get()) )
GlobalUnlock(pmedium->hGlobal);
if ( !ok ) {
return E_UNEXPECTED; return E_UNEXPECTED;
}
} }
break; break;
@@ -975,14 +967,10 @@ const void *wxDataObject::GetSizeFromBuffer(const void *buffer,
size_t *size, size_t *size,
const wxDataFormat& WXUNUSED(format)) const wxDataFormat& WXUNUSED(format))
{ {
// hack: the third parameter is declared non-const in Wine's headers so const size_t realsz = ::GlobalSize(::GlobalHandle(buffer));
// cast away the const if ( !realsz )
const size_t realsz = ::HeapSize(::GetProcessHeap(), 0,
const_cast<void*>(buffer));
if ( realsz == (size_t)-1 )
{ {
// note that HeapSize() does not set last error wxLogLastError(wxT("GlobalSize"));
wxLogApiError(wxT("HeapSize"), 0);
return NULL; return NULL;
} }

View File

@@ -147,7 +147,9 @@ wxCreateDevNames(const wxString& driverName,
( driverName.length() + 1 + ( driverName.length() + 1 +
printerName.length() + 1 + printerName.length() + 1 +
portName.length()+1 ) * sizeof(wxChar) ); portName.length()+1 ) * sizeof(wxChar) );
LPDEVNAMES lpDev = (LPDEVNAMES)GlobalLock(hDev);
GlobalPtrLock ptr(hDev);
LPDEVNAMES lpDev = (LPDEVNAMES)ptr.Get();
lpDev->wDriverOffset = sizeof(WORD) * 4 / sizeof(wxChar); lpDev->wDriverOffset = sizeof(WORD) * 4 / sizeof(wxChar);
wxStrcpy((wxChar*)lpDev + lpDev->wDriverOffset, driverName); wxStrcpy((wxChar*)lpDev + lpDev->wDriverOffset, driverName);
@@ -160,8 +162,6 @@ wxCreateDevNames(const wxString& driverName,
wxStrcpy((wxChar*)lpDev + lpDev->wOutputOffset, portName); wxStrcpy((wxChar*)lpDev + lpDev->wOutputOffset, portName);
lpDev->wDefault = 0; lpDev->wDefault = 0;
GlobalUnlock(hDev);
} }
return hDev; return hDev;