[PATCH] commctrl: Use rbtree to keep private data instead of PropW.

Rémi Bernon rbernon at codeweavers.com
Thu Sep 10 11:56:37 CDT 2020


Wine's wordpad.exe takes minutes to start because of the wineserver
roundtrip Get/Set/RemovePropW induce. It's just used to track if the
window procedure has already been hooked and the cross-process support
doesn't seem to be useful here.

Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---

I'm exagerating a bit but wordpad.exe takes about 40s to start on latest
HEAD. It may be doing something very wrong and maybe this isn't the
right fix, but at least it makes it start in a few seconds instead.

 dlls/comctl32/comctl32.h |  4 +++
 dlls/comctl32/commctrl.c | 63 ++++++++++++++++++++++++++++++++++------
 2 files changed, 58 insertions(+), 9 deletions(-)

diff --git a/dlls/comctl32/comctl32.h b/dlls/comctl32/comctl32.h
index 66b341ae5ad..55e55b8979c 100644
--- a/dlls/comctl32/comctl32.h
+++ b/dlls/comctl32/comctl32.h
@@ -35,6 +35,8 @@
 #include "winnls.h"
 #include "commctrl.h"
 
+#include "wine/rbtree.h"
+
 extern HMODULE COMCTL32_hModule DECLSPEC_HIDDEN;
 extern HBRUSH  COMCTL32_hPattern55AABrush DECLSPEC_HIDDEN;
 
@@ -209,6 +211,8 @@ typedef struct
    SUBCLASSPROCS *stackpos;
    WNDPROC origproc;
    int running;
+   struct wine_rb_entry entry;
+   HWND hwnd;
 } SUBCLASS_INFO, *LPSUBCLASS_INFO;
 
 /* undocumented functions */
diff --git a/dlls/comctl32/commctrl.c b/dlls/comctl32/commctrl.c
index 744188a64a1..4bdf6f2683e 100644
--- a/dlls/comctl32/commctrl.c
+++ b/dlls/comctl32/commctrl.c
@@ -73,9 +73,54 @@
 #include "shlwapi.h"
 #include "comctl32.h"
 #include "wine/debug.h"
+#include "wine/rbtree.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(commctrl);
 
+static CRITICAL_SECTION commctrl_cs;
+static CRITICAL_SECTION_DEBUG commctrl_cs_debug =
+{
+    0, 0, &commctrl_cs,
+    { &commctrl_cs_debug.ProcessLocksList, &commctrl_cs_debug.ProcessLocksList },
+      0, 0, { (DWORD_PTR)(__FILE__ ": commctrl_cs") }
+};
+static CRITICAL_SECTION commctrl_cs = { &commctrl_cs_debug, -1, 0, 0, 0, 0 };
+
+static int commctrl_stack_compare (const void *key, const struct wine_rb_entry *entry)
+{
+    SUBCLASS_INFO *stack = WINE_RB_ENTRY_VALUE (entry, SUBCLASS_INFO, entry);
+    return (HWND)key - stack->hwnd;
+}
+
+static struct wine_rb_tree commctrl_stack_tree = { commctrl_stack_compare };
+
+static SUBCLASS_INFO *commctrl_get_stack (HWND hwnd)
+{
+    struct wine_rb_entry *entry;
+    SUBCLASS_INFO *stack = NULL;
+
+    EnterCriticalSection (&commctrl_cs);
+    if ((entry = wine_rb_get (&commctrl_stack_tree, hwnd)))
+        stack = WINE_RB_ENTRY_VALUE (entry, SUBCLASS_INFO, entry);
+    LeaveCriticalSection (&commctrl_cs);
+
+    return stack;
+}
+
+static void commctrl_set_stack (HWND hwnd, SUBCLASS_INFO *stack)
+{
+    EnterCriticalSection (&commctrl_cs);
+    stack->hwnd = hwnd;
+    wine_rb_put (&commctrl_stack_tree, hwnd, &stack->entry);
+    LeaveCriticalSection (&commctrl_cs);
+}
+
+static void commctrl_remove_stack (SUBCLASS_INFO *stack)
+{
+    EnterCriticalSection (&commctrl_cs);
+    wine_rb_remove (&commctrl_stack_tree, &stack->entry);
+    LeaveCriticalSection (&commctrl_cs);
+}
 
 static LRESULT WINAPI COMCTL32_SubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
 
@@ -1094,7 +1139,7 @@ BOOL WINAPI SetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass,
     * from there. */
 
    /* See if we have been called for this window */
-   stack = GetPropW (hWnd, COMCTL32_wSubclass);
+   stack = commctrl_get_stack (hWnd);
    if (!stack) {
       /* allocate stack */
       stack = Alloc (sizeof(SUBCLASS_INFO));
@@ -1102,7 +1147,7 @@ BOOL WINAPI SetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass,
          ERR ("Failed to allocate our Subclassing stack\n");
          return FALSE;
       }
-      SetPropW (hWnd, COMCTL32_wSubclass, stack);
+      commctrl_set_stack (hWnd, stack);
 
       /* set window procedure to our own and save the current one */
       if (IsWindowUnicode (hWnd))
@@ -1133,8 +1178,8 @@ BOOL WINAPI SetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass,
          SetWindowLongPtrW (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
       else
          SetWindowLongPtrA (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
+      commctrl_remove_stack (stack);
       Free (stack);
-      RemovePropW( hWnd, COMCTL32_wSubclass );
       return FALSE;
    }
    
@@ -1173,7 +1218,7 @@ BOOL WINAPI GetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass,
    TRACE ("(%p, %p, %lx, %p)\n", hWnd, pfnSubclass, uID, pdwRef);
 
    /* See if we have been called for this window */
-   stack = GetPropW (hWnd, COMCTL32_wSubclass);
+   stack = commctrl_get_stack (hWnd);
    if (!stack)
       return FALSE;
 
@@ -1216,7 +1261,7 @@ BOOL WINAPI RemoveWindowSubclass(HWND hWnd, SUBCLASSPROC pfnSubclass, UINT_PTR u
    TRACE ("(%p, %p, %lx)\n", hWnd, pfnSubclass, uID);
 
    /* Find the Subclass to remove */
-   stack = GetPropW (hWnd, COMCTL32_wSubclass);
+   stack = commctrl_get_stack (hWnd);
    if (!stack)
       return FALSE;
 
@@ -1248,8 +1293,8 @@ BOOL WINAPI RemoveWindowSubclass(HWND hWnd, SUBCLASSPROC pfnSubclass, UINT_PTR u
          SetWindowLongPtrW (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
       else
          SetWindowLongPtrA (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
+      commctrl_remove_stack (stack);
       Free (stack);
-      RemovePropW( hWnd, COMCTL32_wSubclass );
    }
    
    return ret;
@@ -1269,7 +1314,7 @@ static LRESULT WINAPI COMCTL32_SubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam
     
    TRACE ("(%p, 0x%08x, 0x%08lx, 0x%08lx)\n", hWnd, uMsg, wParam, lParam);
 
-   stack = GetPropW (hWnd, COMCTL32_wSubclass);
+   stack = commctrl_get_stack (hWnd);
    if (!stack) {
       ERR ("Our sub classing stack got erased for %p!! Nothing we can do\n", hWnd);
       return 0;
@@ -1290,8 +1335,8 @@ static LRESULT WINAPI COMCTL32_SubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam
          SetWindowLongPtrW (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
       else
          SetWindowLongPtrA (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
+      commctrl_remove_stack (stack);
       Free (stack);
-      RemovePropW( hWnd, COMCTL32_wSubclass );
    }
    return ret;
 }
@@ -1320,7 +1365,7 @@ LRESULT WINAPI DefSubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar
    TRACE ("(%p, 0x%08x, 0x%08lx, 0x%08lx)\n", hWnd, uMsg, wParam, lParam);
 
    /* retrieve our little stack from the Properties */
-   stack = GetPropW (hWnd, COMCTL32_wSubclass);
+   stack = commctrl_get_stack (hWnd);
    if (!stack) {
       ERR ("Our sub classing stack got erased for %p!! Nothing we can do\n", hWnd);
       return 0;
-- 
2.28.0




More information about the wine-devel mailing list