Handle exceptions in user drop targets code in wxMSW
All exceptions thrown by wxDropTarget::OnXXX() must be caught and handled in the same way as we already do it for the exceptions in the event handlers as we can't let the exceptions escape into system/kernel code: while it can work in some cases, it doesn't work in general, e.g. exceptions simply disappear when they happen in 32 bit programs under 64 bit Windows 7.
This commit is contained in:
@@ -27,6 +27,7 @@
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/msw/wrapwin.h"
|
||||
#include "wx/except.h"
|
||||
#include "wx/log.h"
|
||||
#endif
|
||||
|
||||
@@ -181,68 +182,72 @@ STDMETHODIMP wxIDropTarget::DragEnter(IDataObject *pIDataSource,
|
||||
POINTL pt,
|
||||
DWORD *pdwEffect)
|
||||
{
|
||||
wxLogTrace(wxTRACE_OleCalls, wxT("IDropTarget::DragEnter"));
|
||||
wxTRY
|
||||
{
|
||||
wxLogTrace(wxTRACE_OleCalls, wxT("IDropTarget::DragEnter"));
|
||||
|
||||
wxASSERT_MSG( m_pIDataObject == NULL,
|
||||
wxT("drop target must have data object") );
|
||||
wxASSERT_MSG( m_pIDataObject == NULL,
|
||||
wxT("drop target must have data object") );
|
||||
|
||||
// show the list of formats supported by the source data object for the
|
||||
// debugging purposes, this is quite useful sometimes - please don't remove
|
||||
// show the list of formats supported by the source data object for the
|
||||
// debugging purposes, this is quite useful sometimes - please don't remove
|
||||
#if 0
|
||||
IEnumFORMATETC *penumFmt;
|
||||
if ( SUCCEEDED(pIDataSource->EnumFormatEtc(DATADIR_GET, &penumFmt)) )
|
||||
{
|
||||
FORMATETC fmt;
|
||||
while ( penumFmt->Next(1, &fmt, NULL) == S_OK )
|
||||
IEnumFORMATETC *penumFmt;
|
||||
if ( SUCCEEDED(pIDataSource->EnumFormatEtc(DATADIR_GET, &penumFmt)) )
|
||||
{
|
||||
wxLogDebug(wxT("Drop source supports format %s"),
|
||||
wxDataObject::GetFormatName(fmt.cfFormat));
|
||||
}
|
||||
FORMATETC fmt;
|
||||
while ( penumFmt->Next(1, &fmt, NULL) == S_OK )
|
||||
{
|
||||
wxLogDebug(wxT("Drop source supports format %s"),
|
||||
wxDataObject::GetFormatName(fmt.cfFormat));
|
||||
}
|
||||
|
||||
penumFmt->Release();
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogLastError(wxT("IDataObject::EnumFormatEtc"));
|
||||
}
|
||||
penumFmt->Release();
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogLastError(wxT("IDataObject::EnumFormatEtc"));
|
||||
}
|
||||
#endif // 0
|
||||
|
||||
if ( !m_pTarget->MSWIsAcceptedData(pIDataSource) ) {
|
||||
// we don't accept this kind of data
|
||||
*pdwEffect = DROPEFFECT_NONE;
|
||||
if ( !m_pTarget->MSWIsAcceptedData(pIDataSource) ) {
|
||||
// we don't accept this kind of data
|
||||
*pdwEffect = DROPEFFECT_NONE;
|
||||
|
||||
// Don't do anything else if we don't support this format at all, notably
|
||||
// don't call our OnEnter() below which would show misleading cursor to
|
||||
// the user.
|
||||
return S_OK;
|
||||
// Don't do anything else if we don't support this format at all, notably
|
||||
// don't call our OnEnter() below which would show misleading cursor to
|
||||
// the user.
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// for use in OnEnter and OnDrag calls
|
||||
m_pTarget->MSWSetDataSource(pIDataSource);
|
||||
|
||||
// get hold of the data object
|
||||
m_pIDataObject = pIDataSource;
|
||||
m_pIDataObject->AddRef();
|
||||
|
||||
// we need client coordinates to pass to wxWin functions
|
||||
if ( !ScreenToClient(m_hwnd, (POINT *)&pt) )
|
||||
{
|
||||
wxLogLastError(wxT("ScreenToClient"));
|
||||
}
|
||||
|
||||
// give some visual feedback
|
||||
*pdwEffect = ConvertDragResultToEffect(
|
||||
m_pTarget->OnEnter(pt.x, pt.y, ConvertDragEffectToResult(
|
||||
GetDropEffect(grfKeyState, m_pTarget->GetDefaultAction(), *pdwEffect))
|
||||
)
|
||||
);
|
||||
|
||||
// update drag image
|
||||
const wxDragResult res = ConvertDragEffectToResult(*pdwEffect);
|
||||
m_pTarget->MSWUpdateDragImageOnEnter(pt.x, pt.y, res);
|
||||
m_pTarget->MSWUpdateDragImageOnDragOver(pt.x, pt.y, res);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// for use in OnEnter and OnDrag calls
|
||||
m_pTarget->MSWSetDataSource(pIDataSource);
|
||||
|
||||
// get hold of the data object
|
||||
m_pIDataObject = pIDataSource;
|
||||
m_pIDataObject->AddRef();
|
||||
|
||||
// we need client coordinates to pass to wxWin functions
|
||||
if ( !ScreenToClient(m_hwnd, (POINT *)&pt) )
|
||||
{
|
||||
wxLogLastError(wxT("ScreenToClient"));
|
||||
}
|
||||
|
||||
// give some visual feedback
|
||||
*pdwEffect = ConvertDragResultToEffect(
|
||||
m_pTarget->OnEnter(pt.x, pt.y, ConvertDragEffectToResult(
|
||||
GetDropEffect(grfKeyState, m_pTarget->GetDefaultAction(), *pdwEffect))
|
||||
)
|
||||
);
|
||||
|
||||
// update drag image
|
||||
const wxDragResult res = ConvertDragEffectToResult(*pdwEffect);
|
||||
m_pTarget->MSWUpdateDragImageOnEnter(pt.x, pt.y, res);
|
||||
m_pTarget->MSWUpdateDragImageOnDragOver(pt.x, pt.y, res);
|
||||
|
||||
return S_OK;
|
||||
wxCATCH_ALL( wxEvtHandler::WXConsumeException(); return E_UNEXPECTED; )
|
||||
}
|
||||
|
||||
|
||||
@@ -260,38 +265,42 @@ STDMETHODIMP wxIDropTarget::DragOver(DWORD grfKeyState,
|
||||
POINTL pt,
|
||||
LPDWORD pdwEffect)
|
||||
{
|
||||
// there are too many of them... wxLogDebug("IDropTarget::DragOver");
|
||||
wxTRY
|
||||
{
|
||||
// there are too many of them... wxLogDebug("IDropTarget::DragOver");
|
||||
|
||||
wxDragResult result;
|
||||
if ( m_pIDataObject ) {
|
||||
result = ConvertDragEffectToResult(
|
||||
GetDropEffect(grfKeyState, m_pTarget->GetDefaultAction(), *pdwEffect));
|
||||
}
|
||||
else {
|
||||
// can't accept data anyhow normally
|
||||
result = wxDragNone;
|
||||
}
|
||||
|
||||
if ( result != wxDragNone ) {
|
||||
// we need client coordinates to pass to wxWin functions
|
||||
if ( !ScreenToClient(m_hwnd, (POINT *)&pt) )
|
||||
{
|
||||
wxLogLastError(wxT("ScreenToClient"));
|
||||
wxDragResult result;
|
||||
if ( m_pIDataObject ) {
|
||||
result = ConvertDragEffectToResult(
|
||||
GetDropEffect(grfKeyState, m_pTarget->GetDefaultAction(), *pdwEffect));
|
||||
}
|
||||
else {
|
||||
// can't accept data anyhow normally
|
||||
result = wxDragNone;
|
||||
}
|
||||
|
||||
*pdwEffect = ConvertDragResultToEffect(
|
||||
m_pTarget->OnDragOver(pt.x, pt.y, result)
|
||||
);
|
||||
}
|
||||
else {
|
||||
*pdwEffect = DROPEFFECT_NONE;
|
||||
}
|
||||
if ( result != wxDragNone ) {
|
||||
// we need client coordinates to pass to wxWin functions
|
||||
if ( !ScreenToClient(m_hwnd, (POINT *)&pt) )
|
||||
{
|
||||
wxLogLastError(wxT("ScreenToClient"));
|
||||
}
|
||||
|
||||
// update drag image
|
||||
m_pTarget->MSWUpdateDragImageOnDragOver(pt.x, pt.y,
|
||||
ConvertDragEffectToResult(*pdwEffect));
|
||||
*pdwEffect = ConvertDragResultToEffect(
|
||||
m_pTarget->OnDragOver(pt.x, pt.y, result)
|
||||
);
|
||||
}
|
||||
else {
|
||||
*pdwEffect = DROPEFFECT_NONE;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
// update drag image
|
||||
m_pTarget->MSWUpdateDragImageOnDragOver(pt.x, pt.y,
|
||||
ConvertDragEffectToResult(*pdwEffect));
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
wxCATCH_ALL( wxEvtHandler::WXConsumeException(); return E_UNEXPECTED; )
|
||||
}
|
||||
|
||||
// Name : wxIDropTarget::DragLeave
|
||||
@@ -300,18 +309,22 @@ STDMETHODIMP wxIDropTarget::DragOver(DWORD grfKeyState,
|
||||
// Notes : good place to do any clean-up
|
||||
STDMETHODIMP wxIDropTarget::DragLeave()
|
||||
{
|
||||
wxLogTrace(wxTRACE_OleCalls, wxT("IDropTarget::DragLeave"));
|
||||
wxTRY
|
||||
{
|
||||
wxLogTrace(wxTRACE_OleCalls, wxT("IDropTarget::DragLeave"));
|
||||
|
||||
// remove the UI feedback
|
||||
m_pTarget->OnLeave();
|
||||
// remove the UI feedback
|
||||
m_pTarget->OnLeave();
|
||||
|
||||
// release the held object
|
||||
RELEASE_AND_NULL(m_pIDataObject);
|
||||
// release the held object
|
||||
RELEASE_AND_NULL(m_pIDataObject);
|
||||
|
||||
// update drag image
|
||||
m_pTarget->MSWUpdateDragImageOnLeave();
|
||||
// update drag image
|
||||
m_pTarget->MSWUpdateDragImageOnLeave();
|
||||
|
||||
return S_OK;
|
||||
return S_OK;
|
||||
}
|
||||
wxCATCH_ALL( wxEvtHandler::WXConsumeException(); return E_UNEXPECTED; )
|
||||
}
|
||||
|
||||
// Name : wxIDropTarget::Drop
|
||||
@@ -328,48 +341,52 @@ STDMETHODIMP wxIDropTarget::Drop(IDataObject *pIDataSource,
|
||||
POINTL pt,
|
||||
DWORD *pdwEffect)
|
||||
{
|
||||
wxLogTrace(wxTRACE_OleCalls, wxT("IDropTarget::Drop"));
|
||||
|
||||
// TODO I don't know why there is this parameter, but so far I assume
|
||||
// that it's the same we've already got in DragEnter
|
||||
wxASSERT( m_pIDataObject == pIDataSource );
|
||||
|
||||
// we need client coordinates to pass to wxWin functions
|
||||
if ( !ScreenToClient(m_hwnd, (POINT *)&pt) )
|
||||
wxTRY
|
||||
{
|
||||
wxLogLastError(wxT("ScreenToClient"));
|
||||
}
|
||||
wxLogTrace(wxTRACE_OleCalls, wxT("IDropTarget::Drop"));
|
||||
|
||||
// first ask the drop target if it wants data
|
||||
if ( m_pTarget->OnDrop(pt.x, pt.y) ) {
|
||||
// it does, so give it the data source
|
||||
m_pTarget->MSWSetDataSource(pIDataSource);
|
||||
// TODO I don't know why there is this parameter, but so far I assume
|
||||
// that it's the same we've already got in DragEnter
|
||||
wxASSERT( m_pIDataObject == pIDataSource );
|
||||
|
||||
// and now it has the data
|
||||
wxDragResult rc = ConvertDragEffectToResult(
|
||||
GetDropEffect(grfKeyState, m_pTarget->GetDefaultAction(), *pdwEffect));
|
||||
rc = m_pTarget->OnData(pt.x, pt.y, rc);
|
||||
if ( wxIsDragResultOk(rc) ) {
|
||||
// operation succeeded
|
||||
*pdwEffect = ConvertDragResultToEffect(rc);
|
||||
// we need client coordinates to pass to wxWin functions
|
||||
if ( !ScreenToClient(m_hwnd, (POINT *)&pt) )
|
||||
{
|
||||
wxLogLastError(wxT("ScreenToClient"));
|
||||
}
|
||||
|
||||
// first ask the drop target if it wants data
|
||||
if ( m_pTarget->OnDrop(pt.x, pt.y) ) {
|
||||
// it does, so give it the data source
|
||||
m_pTarget->MSWSetDataSource(pIDataSource);
|
||||
|
||||
// and now it has the data
|
||||
wxDragResult rc = ConvertDragEffectToResult(
|
||||
GetDropEffect(grfKeyState, m_pTarget->GetDefaultAction(), *pdwEffect));
|
||||
rc = m_pTarget->OnData(pt.x, pt.y, rc);
|
||||
if ( wxIsDragResultOk(rc) ) {
|
||||
// operation succeeded
|
||||
*pdwEffect = ConvertDragResultToEffect(rc);
|
||||
}
|
||||
else {
|
||||
*pdwEffect = DROPEFFECT_NONE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// OnDrop() returned false, no need to copy data
|
||||
*pdwEffect = DROPEFFECT_NONE;
|
||||
}
|
||||
|
||||
// release the held object
|
||||
RELEASE_AND_NULL(m_pIDataObject);
|
||||
|
||||
// update drag image
|
||||
m_pTarget->MSWUpdateDragImageOnData(pt.x, pt.y,
|
||||
ConvertDragEffectToResult(*pdwEffect));
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
else {
|
||||
// OnDrop() returned false, no need to copy data
|
||||
*pdwEffect = DROPEFFECT_NONE;
|
||||
}
|
||||
|
||||
// release the held object
|
||||
RELEASE_AND_NULL(m_pIDataObject);
|
||||
|
||||
// update drag image
|
||||
m_pTarget->MSWUpdateDragImageOnData(pt.x, pt.y,
|
||||
ConvertDragEffectToResult(*pdwEffect));
|
||||
|
||||
return S_OK;
|
||||
wxCATCH_ALL( wxEvtHandler::WXConsumeException(); return E_UNEXPECTED; )
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
|
Reference in New Issue
Block a user