Update of /cvsroot/perl-win32-gui/Win32-GUI
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv8818
Modified Files:
CHANGELOG GUI_Events.cpp GUI_MessageLoops.cpp
Log Message:
Fix crashes when windows destroyed during callbacks to perl
Index: CHANGELOG
===================================================================
RCS file: /cvsroot/perl-win32-gui/Win32-GUI/CHANGELOG,v
retrieving revision 1.113
retrieving revision 1.114
diff -C2 -d -r1.113 -r1.114
*** CHANGELOG 15 Jul 2007 18:39:51 -0000 1.113
--- CHANGELOG 15 Jul 2007 18:47:13 -0000 1.114
***************
*** 16,19 ****
--- 16,21 ----
- DC.xs - Rework DrawFrameControl() to allow DFCS_ADJUSTRECT to modify
input parameters
+ - GUI_Events.cpp, GUI_MessageLoops.cpp - handle window being destroyed in
+ callback by checking validity with IsWindow(hwnd) in many places
+ [Robert May] : 20 January 2007 - Restore Original WndProc
Index: GUI_Events.cpp
===================================================================
RCS file: /cvsroot/perl-win32-gui/Win32-GUI/GUI_Events.cpp,v
retrieving revision 1.14
retrieving revision 1.15
diff -C2 -d -r1.14 -r1.15
*** GUI_Events.cpp 3 Aug 2006 22:20:02 -0000 1.14
--- GUI_Events.cpp 15 Jul 2007 18:47:13 -0000 1.15
***************
*** 10,13 ****
--- 10,26 ----
#include "GUI.h"
+ /* IMPORTANT:
+ * Whenever we make a callback into perl, we cannot know what evil things
+ * the script writer will have done. In particular, it is possible for
+ * the called code to cause the window for which the event is being
+ * handled to be destroyed before the callback returns. If this happens
+ * we will have a non-NULL perlud pointer, but the underlying memory
+ * will have been freed. Don't try to access perlud after a callback
+ * without checking that the window still exists. Currently the code
+ * below gets the window handle BEFORE the callback (from perud->svSelf),
+ * and checks it afterwards with IsWindow(). This is not infallable as
the
+ * hwnd could have been recycled - this is, however, unlikely
+ */
+
/*
##########################################################################
***************
*** 47,50 ****
--- 60,64 ----
int PerlResult = 1;
+ HWND hwnd = handle_From(NOTXSCALL perlud->svSelf);
perlud->dwPlStyle &= ~PERLWIN32GUI_EVENTHANDLING;
***************
*** 101,104 ****
--- 115,120 ----
LEAVE;
+ if(!IsWindow(hwnd)) return PerlResult;
+
// Must set after event call because this event can generate more
event.
perlud->dwPlStyle |= PERLWIN32GUI_EVENTHANDLING;
***************
*** 163,166 ****
--- 179,184 ----
LEAVE;
+ if(!IsWindow(hwnd)) return PerlResult;
+
// Must set after event call because this event can generate more
event.
perlud->dwPlStyle |= PERLWIN32GUI_EVENTHANDLING;
***************
*** 279,282 ****
--- 297,301 ----
SV* acc_sub = NULL;
int PerlResult = 1;
+ HWND hwnd = handle_From(NOTXSCALL perlud->svSelf);
perlud->dwPlStyle &= ~PERLWIN32GUI_EVENTHANDLING;
***************
*** 298,308 ****
// Find for a child with AcceleratorName name
if (strcmp (perlud->szWindowName, AcceleratorName) != 0) {
-
- HWND hWndParent = handle_From(NOTXSCALL perlud->svSelf);
st_FindChildWindow st;
st.perlchild = NULL;
st.Name = AcceleratorName;
! EnumChildWindows(hWndParent, (WNDENUMPROC)
FindChildWindowsProc, (LPARAM) &st);
perlchild = st.perlchild;
}
--- 317,325 ----
// Find for a child with AcceleratorName name
if (strcmp (perlud->szWindowName, AcceleratorName) != 0) {
st_FindChildWindow st;
st.perlchild = NULL;
st.Name = AcceleratorName;
! EnumChildWindows(hwnd, (WNDENUMPROC) FindChildWindowsProc,
(LPARAM) &st);
perlchild = st.perlchild;
}
***************
*** 334,337 ****
--- 351,356 ----
LEAVE;
+ if(!IsWindow(hwnd)) return PerlResult;
+
// Must set after event call because this event can generate more
event.
perlud->dwPlStyle |= PERLWIN32GUI_EVENTHANDLING;
***************
*** 363,366 ****
--- 382,387 ----
LEAVE;
+ if(!IsWindow(hwnd)) return PerlResult;
+
// Must set after event call because this event can generate more
event.
perlud->dwPlStyle |= PERLWIN32GUI_EVENTHANDLING;
***************
*** 394,397 ****
--- 415,420 ----
LEAVE;
+ if(!IsWindow(hwnd)) return PerlResult;
+
// Must set after event call because this event can generate more
event.
perlud->dwPlStyle |= PERLWIN32GUI_EVENTHANDLING;
***************
*** 426,429 ****
--- 449,454 ----
LEAVE;
+ if(!IsWindow(hwnd)) return PerlResult;
+
// Must set after event call because this event can generate more
event.
perlud->dwPlStyle |= PERLWIN32GUI_EVENTHANDLING;
***************
*** 448,452 ****
int count;
int argtype;
! static char *textneeded = NULL;
if(textneeded != NULL) {
safefree(textneeded);
--- 473,478 ----
int count;
int argtype;
! HWND hwnd = handle_From(NOTXSCALL perlud->svSelf);
! static char *textneeded = NULL; /* XXX: Not Thread Safe */
if(textneeded != NULL) {
safefree(textneeded);
***************
*** 515,518 ****
--- 541,546 ----
LEAVE;
+ if(!IsWindow(hwnd)) return textneeded;
+
// Must set after event call because this event can generate more
event.
perlud->dwPlStyle |= PERLWIN32GUI_EVENTHANDLING;
***************
*** 583,586 ****
--- 611,616 ----
LEAVE;
+ if(!IsWindow(hwnd)) return textneeded;
+
// Must set after event call because this event can generate more
event.
perlud->dwPlStyle |= PERLWIN32GUI_EVENTHANDLING;
***************
*** 609,612 ****
--- 639,643 ----
int PerlResult = 1;
+ HWND hwnd = handle_From(NOTXSCALL perlud->svSelf);
perlud->dwPlStyle &= ~PERLWIN32GUI_EVENTHANDLING;
***************
*** 674,677 ****
--- 705,710 ----
LEAVE;
+ if(!IsWindow(hwnd)) return PerlResult;
+
// Must set after event call because this event can generate more
event.
perlud->dwPlStyle |= PERLWIN32GUI_EVENTHANDLING;
***************
*** 733,736 ****
--- 766,771 ----
LEAVE;
+ if(!IsWindow(hwnd)) return PerlResult;
+
// Must set after event call because this event can generate more
event.
perlud->dwPlStyle |= PERLWIN32GUI_EVENTHANDLING;
***************
*** 758,761 ****
--- 793,797 ----
SV** events = NULL;
int PerlResult = 1;
+ HWND hwnd = handle_From(NOTXSCALL perlud->svSelf);
perlud->dwPlStyle &= ~PERLWIN32GUI_EVENTHANDLING;
***************
*** 829,832 ****
--- 865,870 ----
LEAVE;
+ if(!IsWindow(hwnd)) return PerlResult;
+
// Must set after event call because this event can generate more
event.
perlud->dwPlStyle |= PERLWIN32GUI_EVENTHANDLING;
***************
*** 888,891 ****
--- 926,931 ----
LEAVE;
+ if(!IsWindow(hwnd)) return PerlResult;
+
// Must set after event call because this event can generate more
event.
perlud->dwPlStyle |= PERLWIN32GUI_EVENTHANDLING;
***************
*** 906,909 ****
--- 946,950 ----
SV* newdc;
int PerlResult = 1;
+ HWND hwnd = handle_From(NOTXSCALL perlud->svSelf);
perlud->dwPlStyle &= ~PERLWIN32GUI_EVENTHANDLING;
***************
*** 949,952 ****
--- 990,995 ----
LEAVE;
+ if(!IsWindow(hwnd)) return PerlResult;
+
// Must set after event call because this event can generate more
event.
perlud->dwPlStyle |= PERLWIN32GUI_EVENTHANDLING;
***************
*** 998,1001 ****
--- 1041,1046 ----
LEAVE;
+ if(!IsWindow(hwnd)) return PerlResult;
+
// Must set after event call because this event can generate more
event.
perlud->dwPlStyle |= PERLWIN32GUI_EVENTHANDLING;
Index: GUI_MessageLoops.cpp
===================================================================
RCS file: /cvsroot/perl-win32-gui/Win32-GUI/GUI_MessageLoops.cpp,v
retrieving revision 1.22
retrieving revision 1.23
diff -C2 -d -r1.22 -r1.23
*** GUI_MessageLoops.cpp 16 Jul 2006 11:08:27 -0000 1.22
--- GUI_MessageLoops.cpp 15 Jul 2007 18:47:13 -0000 1.23
***************
*** 262,269 ****
PerlResult = OnEvent[childud->iClass](NOTXSCALL childud,
uMsg, wParam, lParam);
! if (childud->avHooks != NULL)
DoHook(NOTXSCALL childud, (UINT) HIWORD(wParam), wParam,
lParam, &PerlResult, WM_COMMAND);
! if(childud->forceResult != 0) {
perlud->forceResult = childud->forceResult;
childud->forceResult = 0;
--- 262,269 ----
PerlResult = OnEvent[childud->iClass](NOTXSCALL childud,
uMsg, wParam, lParam);
! if (IsWindow((HWND)lParam) && childud->avHooks != NULL)
DoHook(NOTXSCALL childud, (UINT) HIWORD(wParam), wParam,
lParam, &PerlResult, WM_COMMAND);
! if(IsWindow((HWND)lParam) && childud->forceResult != 0) {
perlud->forceResult = childud->forceResult;
childud->forceResult = 0;
***************
*** 328,335 ****
}
! if (childud->avHooks != NULL)
DoHook(NOTXSCALL childud, (UINT) (((LPNMHDR) lParam)->code),
wParam, lParam, &PerlResult, WM_NOTIFY);
! if(childud->forceResult != 0) {
perlud->forceResult = childud->forceResult;
childud->forceResult = 0;
--- 328,335 ----
}
! if (IsWindow(((LPNMHDR)lParam)->hwndFrom) && childud->avHooks !=
NULL)
DoHook(NOTXSCALL childud, (UINT) (((LPNMHDR) lParam)->code),
wParam, lParam, &PerlResult, WM_NOTIFY);
! if (IsWindow(((LPNMHDR)lParam)->hwndFrom) && childud->forceResult
!= 0) {
perlud->forceResult = childud->forceResult;
childud->forceResult = 0;
***************
*** 654,658 ****
// Hook processing
! if(perlud->avHooks != NULL) {
DoHook(NOTXSCALL perlud, uMsg, wParam, lParam, &PerlResult,0);
}
--- 654,658 ----
// Hook processing
! if(IsWindow(hwnd) && perlud->avHooks != NULL) {
DoHook(NOTXSCALL perlud, uMsg, wParam, lParam, &PerlResult,0);
}
***************
*** 660,669 ****
// Default processing
if(PerlResult == -1) {
! PostMessage(hwnd, WM_EXITLOOP, (WPARAM) -1, 0);
PerlResult = 0;
! } else if (PerlResult != 0) {
PerlResult = CommonMsgLoop(NOTXSCALL hwnd, uMsg, wParam, lParam,
perlud->WndProc);
}
! else if (perlud->forceResult != 0) {
return perlud->forceResult;
}
--- 660,673 ----
// Default processing
if(PerlResult == -1) {
! if(IsWindow(hwnd)) {
! PostMessage(hwnd, WM_EXITLOOP, (WPARAM) -1, 0);
! } else {
! PostThreadMessage(GetCurrentThreadId(), WM_EXITLOOP, (WPARAM) -1,
0);
! }
PerlResult = 0;
! } else if (IsWindow(hwnd) && PerlResult != 0) {
PerlResult = CommonMsgLoop(NOTXSCALL hwnd, uMsg, wParam, lParam,
perlud->WndProc);
}
! else if (IsWindow(hwnd) && perlud->forceResult != 0) {
return perlud->forceResult;
}
***************
*** 996,1007 ****
}
! if (perlud->avHooks != NULL)
DoHook(NOTXSCALL perlud, uMsg,wParam,lParam,&PerlResult,0);
!
! if (PerlResult != 0) {
PerlResult = CommonMsgLoop(NOTXSCALL hwnd, uMsg, wParam, lParam,
perlud->WndProc);
}
! else if ( perlud->forceResult != 0) {
return perlud->forceResult;
}
--- 1000,1010 ----
}
! if (IsWindow(hwnd) && perlud->avHooks != NULL)
DoHook(NOTXSCALL perlud, uMsg,wParam,lParam,&PerlResult,0);
! if (IsWindow(hwnd) && PerlResult != 0) {
PerlResult = CommonMsgLoop(NOTXSCALL hwnd, uMsg, wParam, lParam,
perlud->WndProc);
}
! else if (IsWindow(hwnd) && perlud->forceResult != 0) {
return perlud->forceResult;
}
***************
*** 1102,1109 ****
// Hook for non interactive control
! if (perlud->avHooks != NULL && !(perlud->dwPlStyle &
PERLWIN32GUI_INTERACTIVE))
DoHook(NOTXSCALL perlud, uMsg,wParam,lParam,&PerlResult,0);
! if (PerlResult != 0) {
// If interactive control, call ControlMsgLoop
if (perlud->dwPlStyle & PERLWIN32GUI_INTERACTIVE)
--- 1105,1112 ----
// Hook for non interactive control
! if (IsWindow(hwnd) && perlud->avHooks != NULL && !(perlud->dwPlStyle &
PERLWIN32GUI_INTERACTIVE))
DoHook(NOTXSCALL perlud, uMsg,wParam,lParam,&PerlResult,0);
! if (IsWindow(hwnd) && PerlResult != 0) {
// If interactive control, call ControlMsgLoop
if (perlud->dwPlStyle & PERLWIN32GUI_INTERACTIVE)
***************
*** 1112,1116 ****
PerlResult = CommonMsgLoop(NOTXSCALL hwnd, uMsg, wParam, lParam,
perlud->WndProc);
}
! else if (perlud->forceResult != 0) {
return perlud->forceResult;
}
--- 1115,1119 ----
PerlResult = CommonMsgLoop(NOTXSCALL hwnd, uMsg, wParam, lParam,
perlud->WndProc);
}
! else if (IsWindow(hwnd) && perlud->forceResult != 0) {
return perlud->forceResult;
}