- Let the subclassing stack grow the opposite way to make the code
more transparent.
- Remove SubclassWndProc and move its logic to DefSubclassProc.
diff --git a/dlls/comctl32/comctl32.h b/dlls/comctl32/comctl32.h
index 6e467b2..a508553 100644
--- a/dlls/comctl32/comctl32.h
+++ b/dlls/comctl32/comctl32.h
@@ -154,7 +154,7 @@
} SubclassProcs[31];
int stackpos;
int stacknum;
- int stacknew;
+ int wndprocrecursion;
WNDPROC origproc;
} SUBCLASS_INFO, *LPSUBCLASS_INFO;
diff --git a/dlls/comctl32/commctrl.c b/dlls/comctl32/commctrl.c
index ad242df..2eb5436 100644
--- a/dlls/comctl32/commctrl.c
+++ b/dlls/comctl32/commctrl.c
@@ -114,7 +114,6 @@
extern void UPDOWN_Register(void);
extern void UPDOWN_Unregister(void);
-static LRESULT WINAPI SubclassWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
LPSTR COMCTL32_aSubclass = NULL;
HMODULE COMCTL32_hModule = 0;
@@ -1085,7 +1084,7 @@
UINT_PTR uIDSubclass, DWORD_PTR dwRef)
{
LPSUBCLASS_INFO stack;
- int newnum, n;
+ int n;
TRACE ("(%p, %p, %x, %lx)\n", hWnd, pfnSubclass, uIDSubclass, dwRef);
@@ -1109,10 +1108,10 @@
/* set window procedure to our own and save the current one */
if (IsWindowUnicode (hWnd))
stack->origproc = (WNDPROC)SetWindowLongW (hWnd, GWL_WNDPROC,
- (LONG)SubclassWndProc);
+ (LONG)DefSubclassProc);
else
stack->origproc = (WNDPROC)SetWindowLongA (hWnd, GWL_WNDPROC,
- (LONG)SubclassWndProc);
+ (LONG)DefSubclassProc);
} else {
WNDPROC current;
if (IsWindowUnicode (hWnd))
@@ -1120,7 +1119,7 @@
else
current = (WNDPROC)GetWindowLongA (hWnd, GWL_WNDPROC);
- if (current != SubclassWndProc) {
+ if (current != DefSubclassProc) {
ERR ("Application has subclassed with our procedure, then manually, then with us again. The current implementation can't handle this.\n");
return FALSE;
}
@@ -1128,32 +1127,28 @@
/* Check to see if we have called this function with the same uIDSubClass
* and pfnSubclass */
- for (n = 0; n <= stack->stacknum + stack->stacknew - 1; n++)
+ for (n = 0; n < stack->stacknum; n++)
if ((stack->SubclassProcs[n].id == uIDSubclass) &&
(stack->SubclassProcs[n].subproc == pfnSubclass)) {
stack->SubclassProcs[n].ref = dwRef;
return TRUE;
}
- if ((stack->stacknum + stack->stacknew) >= 32) {
+ if (stack->stacknum >= 32) {
ERR ("We have a Subclass stack overflow, please increment size\n");
return FALSE;
}
- /* we can't simply increment both stackpos and stacknum because there might
- * be a window procedure running lower in the stack, we can only get them
- * up to date once the last window procedure has run */
- if (stack->stacknum == stack->stackpos) {
- stack->stacknum++;
+ memmove (&stack->SubclassProcs[1], &stack->SubclassProcs[0],
+ sizeof(stack->SubclassProcs[0]) * stack->stacknum);
+
+ stack->stacknum++;
+ if (stack->wndprocrecursion)
stack->stackpos++;
- } else
- stack->stacknew++;
- newnum = stack->stacknew + stack->stacknum - 1;
-
- stack->SubclassProcs[newnum].subproc = pfnSubclass;
- stack->SubclassProcs[newnum].ref = dwRef;
- stack->SubclassProcs[newnum].id = uIDSubclass;
+ stack->SubclassProcs[0].subproc = pfnSubclass;
+ stack->SubclassProcs[0].ref = dwRef;
+ stack->SubclassProcs[0].id = uIDSubclass;
return TRUE;
}
@@ -1188,7 +1183,7 @@
if (!stack)
return FALSE;
- for (n = 0; n <= stack->stacknum + stack->stacknew - 1; n++)
+ for (n = 0; n < stack->stacknum; n++)
if ((stack->SubclassProcs[n].id == uID) &&
(stack->SubclassProcs[n].subproc == pfnSubclass)) {
*pdwRef = stack->SubclassProcs[n].ref;
@@ -1226,7 +1221,8 @@
if (!stack)
return FALSE;
- if ((stack->stacknum == 1) && (stack->stackpos == 1) && !stack->stacknew) {
+ if ((stack->stacknum == 1) && (stack->stackpos == 1) &&
+ !stack->wndprocrecursion) {
TRACE("Last Subclass removed, cleaning up\n");
/* clean up our heap and reset the origional window procedure */
if (IsWindowUnicode (hWnd))
@@ -1238,24 +1234,21 @@
return TRUE;
}
- for (n = stack->stacknum + stack->stacknew - 1; n >= 0; n--)
+ for (n = stack->stacknum - 1; n >= 0; n--)
if ((stack->SubclassProcs[n].id == uID) &&
(stack->SubclassProcs[n].subproc == pfnSubclass)) {
- if (n != (stack->stacknum + stack->stacknew))
+ if (n != stack->stacknum)
/* Fill the hole in the stack */
memmove (&stack->SubclassProcs[n], &stack->SubclassProcs[n + 1],
- sizeof(stack->SubclassProcs[0]) * (stack->stacknew + stack->stacknum - n));
+ sizeof(stack->SubclassProcs[0]) * (stack->stacknum - n));
stack->SubclassProcs[n].subproc = NULL;
stack->SubclassProcs[n].ref = 0;
stack->SubclassProcs[n].id = 0;
- /* If we are currently running a window procedure we have to manipulate
- * the stack position pointers so that we don't corrupt the stack */
- if ((n < stack->stackpos) || (stack->stackpos == stack->stacknum)) {
- stack->stacknum--;
+ stack->stacknum--;
+ if (n < stack->stackpos && stack->wndprocrecursion)
stack->stackpos--;
- } else if (n >= stack->stackpos)
- stack->stacknew--;
+
return TRUE;
}
@@ -1264,33 +1257,6 @@
/***********************************************************************
- * SubclassWndProc (internal)
- *
- * Window procedure for all subclassed windows.
- * Saves the current subclassing stack position to support nested messages
- */
-
-static LRESULT WINAPI SubclassWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- LPSUBCLASS_INFO stack;
- int stackpos;
- LRESULT ret;
-
- /* retrieve our little stack from the Properties */
- stack = (LPSUBCLASS_INFO)GetPropA (hWnd, COMCTL32_aSubclass);
- if (!stack) {
- ERR ("Our sub classing stack got erased for %p!! Nothing we can do\n", hWnd);
- return 0;
- }
- stackpos = stack->stackpos;
- stack->stackpos = stack->stacknum;
- ret = DefSubclassProc(hWnd,uMsg,wParam,lParam);
- stack->stackpos = stackpos;
- return ret;
-}
-
-
-/***********************************************************************
* DefSubclassProc [COMCTL32.413]
*
* Calls the next window procedure (ie. the one before this subclass)
@@ -1309,7 +1275,6 @@
LRESULT WINAPI DefSubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LPSUBCLASS_INFO stack;
- int stackpos;
LRESULT ret;
/* retrieve our little stack from the Properties */
@@ -1319,24 +1284,27 @@
return 0;
}
- /* If we are at pos 0 then we have to call the origional window procedure */
- if (stack->stackpos == 0) {
+ stack->wndprocrecursion++;
+
+ /* If we are at the end of stack then we have to call the original
+ * window procedure */
+ if (stack->stackpos == stack->stacknum) {
if (IsWindowUnicode (hWnd))
- return CallWindowProcW (stack->origproc, hWnd, uMsg, wParam, lParam);
+ ret = CallWindowProcW (stack->origproc, hWnd, uMsg, wParam, lParam);
else
- return CallWindowProcA (stack->origproc, hWnd, uMsg, wParam, lParam);
+ ret = CallWindowProcA (stack->origproc, hWnd, uMsg, wParam, lParam);
+ } else {
+ stack->stackpos++;
+ /* call the Subclass procedure from the stack */
+ ret = stack->SubclassProcs[stack->stackpos - 1].subproc (hWnd, uMsg, wParam, lParam,
+ stack->SubclassProcs[stack->stackpos - 1].id, stack->SubclassProcs[stack->stackpos - 1].ref);
+ stack->stackpos--;
}
- stackpos = --stack->stackpos;
- /* call the Subclass procedure from the stack */
- ret = stack->SubclassProcs[stackpos].subproc (hWnd, uMsg, wParam, lParam,
- stack->SubclassProcs[stackpos].id, stack->SubclassProcs[stackpos].ref);
- stack->stackpos++;
-
- if ((stack->stackpos == stack->stacknum) && stack->stacknew) {
- stack->stacknum += stack->stacknew;
- stack->stackpos += stack->stacknew;
- stack->stacknew = 0;
+ /* We finished the recursion, so let's reinitalize the stack position to
+ * beginning */
+ if ((--stack->wndprocrecursion) == 0) {
+ stack->stackpos = 0;
}
/* If we removed the last entry in our stack while a window procedure was