[PATCH] user32: Enable window class redirection

Nikolay Sivov nsivov at codeweavers.com
Fri Jan 26 05:51:41 CST 2018


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/user32/class.c       | 79 +++++++++++++++++++++++++++++++++++++++++------
 dlls/user32/tests/class.c |  9 ------
 2 files changed, 69 insertions(+), 19 deletions(-)

diff --git a/dlls/user32/class.c b/dlls/user32/class.c
index fae88f20b3..8aa568dde3 100644
--- a/dlls/user32/class.c
+++ b/dlls/user32/class.c
@@ -161,6 +161,32 @@ static BOOL is_comctl32_class( const WCHAR *name )
     return FALSE;
 }
 
+static BOOL is_builtin_class( const WCHAR *name )
+{
+    static const WCHAR classesW[][20] =
+    {
+        {'B','u','t','t','o','n',0},
+        {'C','o','m','b','o','B','o','x',0},
+        {'C','o','m','b','o','L','B','o','x',0},
+        {'E','d','i','t',0},
+        {'I','M','E',0},
+        {'L','i','s','t','B','o','x',0},
+        {'M','D','I','C','l','i','e','n','t',0},
+        {'S','c','r','o','l','l','b','a','r',0},
+        {'S','t','a','t','i','c',0},
+    };
+
+    int min = 0, max = (sizeof(classesW) / sizeof(classesW[0])) - 1;
+
+    while (min <= max)
+    {
+        int res, pos = (min + max) / 2;
+        if (!(res = strcmpiW( name, classesW[pos] ))) return TRUE;
+        if (res < 0) max = pos - 1;
+        else min = pos + 1;
+    }
+    return FALSE;
+}
 
 /***********************************************************************
  *           set_server_info
@@ -299,6 +325,32 @@ static void CLASS_FreeClass( CLASS *classPtr )
     USER_Unlock();
 }
 
+static const WCHAR *CLASS_GetVersionedName( const WCHAR *name )
+{
+    ACTCTX_SECTION_KEYED_DATA data;
+    struct wndclass_redirect_data
+    {
+        ULONG size;
+        DWORD res;
+        ULONG name_len;
+        ULONG name_offset;
+        ULONG module_len;
+        ULONG module_offset;
+    } *wndclass;
+
+    if (IS_INTRESOURCE( name ))
+        return name;
+
+    if (is_comctl32_class( name ) || is_builtin_class( name ))
+        return name;
+
+    data.cbSize = sizeof(data);
+    if (!FindActCtxSectionStringW(0, NULL, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION, name, &data))
+        return name;
+
+    wndclass = (struct wndclass_redirect_data *)data.lpData;
+    return (const WCHAR *)((BYTE *)wndclass + wndclass->name_offset);
+}
 
 /***********************************************************************
  *           CLASS_FindClass
@@ -315,6 +367,8 @@ static CLASS *CLASS_FindClass( LPCWSTR name, HINSTANCE hinstance )
 
     if (!name) return NULL;
 
+    name = CLASS_GetVersionedName( name );
+
     for (;;)
     {
         USER_Lock();
@@ -561,6 +615,8 @@ ATOM WINAPI RegisterClassW( const WNDCLASSW* wc )
  */
 ATOM WINAPI RegisterClassExA( const WNDCLASSEXA* wc )
 {
+    const WCHAR *classname = NULL;
+    WCHAR name[MAX_ATOM_LEN + 1];
     ATOM atom;
     CLASS *classPtr;
     HINSTANCE instance;
@@ -577,10 +633,9 @@ ATOM WINAPI RegisterClassExA( const WNDCLASSEXA* wc )
 
     if (!IS_INTRESOURCE(wc->lpszClassName))
     {
-        WCHAR name[MAX_ATOM_LEN + 1];
-
         if (!MultiByteToWideChar( CP_ACP, 0, wc->lpszClassName, -1, name, MAX_ATOM_LEN + 1 )) return 0;
-        classPtr = CLASS_RegisterClass( name, instance, !(wc->style & CS_GLOBALCLASS),
+        classname = CLASS_GetVersionedName( name );
+        classPtr = CLASS_RegisterClass( classname, instance, !(wc->style & CS_GLOBALCLASS),
                                         wc->style, wc->cbClsExtra, wc->cbWndExtra );
     }
     else
@@ -592,9 +647,9 @@ ATOM WINAPI RegisterClassExA( const WNDCLASSEXA* wc )
     if (!classPtr) return 0;
     atom = classPtr->atomName;
 
-    TRACE("name=%s atom=%04x wndproc=%p hinst=%p bg=%p style=%08x clsExt=%d winExt=%d class=%p\n",
-          debugstr_a(wc->lpszClassName), atom, wc->lpfnWndProc, instance, wc->hbrBackground,
-          wc->style, wc->cbClsExtra, wc->cbWndExtra, classPtr );
+    TRACE("name=%s%s%s atom=%04x wndproc=%p hinst=%p bg=%p style=%08x clsExt=%d winExt=%d class=%p\n",
+          debugstr_a(wc->lpszClassName), classname != name ? "->" : "", classname != name ? debugstr_w(classname) : "",
+          atom, wc->lpfnWndProc, instance, wc->hbrBackground, wc->style, wc->cbClsExtra, wc->cbWndExtra, classPtr );
 
     classPtr->hIcon         = wc->hIcon;
     classPtr->hIconSm       = wc->hIconSm;
@@ -617,6 +672,7 @@ ATOM WINAPI RegisterClassExA( const WNDCLASSEXA* wc )
  */
 ATOM WINAPI RegisterClassExW( const WNDCLASSEXW* wc )
 {
+    const WCHAR *classname;
     ATOM atom;
     CLASS *classPtr;
     HINSTANCE instance;
@@ -631,15 +687,17 @@ ATOM WINAPI RegisterClassExW( const WNDCLASSEXW* wc )
     }
     if (!(instance = wc->hInstance)) instance = GetModuleHandleW( NULL );
 
-    if (!(classPtr = CLASS_RegisterClass( wc->lpszClassName, instance, !(wc->style & CS_GLOBALCLASS),
+    classname = CLASS_GetVersionedName( wc->lpszClassName );
+    if (!(classPtr = CLASS_RegisterClass( classname, instance, !(wc->style & CS_GLOBALCLASS),
                                           wc->style, wc->cbClsExtra, wc->cbWndExtra )))
         return 0;
 
     atom = classPtr->atomName;
 
-    TRACE("name=%s atom=%04x wndproc=%p hinst=%p bg=%p style=%08x clsExt=%d winExt=%d class=%p\n",
-          debugstr_w(wc->lpszClassName), atom, wc->lpfnWndProc, instance, wc->hbrBackground,
-          wc->style, wc->cbClsExtra, wc->cbWndExtra, classPtr );
+    TRACE("name=%s%s%s atom=%04x wndproc=%p hinst=%p bg=%p style=%08x clsExt=%d winExt=%d class=%p\n",
+          debugstr_w(wc->lpszClassName), classname != wc->lpszClassName ? "->" : "",
+          classname != wc->lpszClassName ? debugstr_w(classname) : "", atom, wc->lpfnWndProc, instance,
+          wc->hbrBackground, wc->style, wc->cbClsExtra, wc->cbWndExtra, classPtr );
 
     classPtr->hIcon         = wc->hIcon;
     classPtr->hIconSm       = wc->hIconSm;
@@ -682,6 +740,7 @@ BOOL WINAPI UnregisterClassW( LPCWSTR className, HINSTANCE hInstance )
 
     GetDesktopWindow();  /* create the desktop window to trigger builtin class registration */
 
+    className = CLASS_GetVersionedName( className );
     SERVER_START_REQ( destroy_class )
     {
         req->instance = wine_server_client_ptr( hInstance );
diff --git a/dlls/user32/tests/class.c b/dlls/user32/tests/class.c
index dd8f266217..88e4bfcfa4 100644
--- a/dlls/user32/tests/class.c
+++ b/dlls/user32/tests/class.c
@@ -1243,7 +1243,6 @@ static void test_actctx_classes(void)
     ok(ret, "Failed to get class info.\n");
 
     ret = GetClassInfoA(hinst, "4.3.2.1!MyTestClass", &wc);
-todo_wine
     ok(ret, "Failed to get class info.\n");
 
     ret = UnregisterClassA("MyTestClass", hinst);
@@ -1262,7 +1261,6 @@ todo_wine
 
     wc.lpszClassName = "MyTestClass";
     class = RegisterClassA(&wc);
-todo_wine
     ok(class == 0, "Expected failure.\n");
 
     ret = DeactivateActCtx(0, cookie);
@@ -1277,28 +1275,23 @@ todo_wine
 
     wc.lpszClassName = "MyTestClass";
     class = RegisterClassA(&wc);
-todo_wine
     ok(class != 0, "Failed to register class\n");
 
     ret = DeactivateActCtx(0, cookie);
     ok(ret, "Failed to deactivate context.\n");
 
     ret = GetClassInfoA(hinst, "MyTestClass", &wc);
-todo_wine
     ok(!ret, "Expected failure.\n");
 
     ret = GetClassInfoA(hinst, "4.3.2.1!MyTestClass", &wc);
-todo_wine
     ok(ret, "Failed to get class info.\n");
 
     ret = UnregisterClassA("4.3.2.1!MyTestClass", hinst);
-todo_wine
     ok(ret, "Failed to unregister class.\n");
 
     /* Register regular name first, it's not considered when versioned name is registered. */
     wc.lpszClassName = "MyTestClass";
     class = RegisterClassA(&wc);
-todo_wine
     ok(class != 0, "Failed to register class.\n");
 
     ret = ActivateActCtx(context, &cookie);
@@ -1306,14 +1299,12 @@ todo_wine
 
     wc.lpszClassName = "MyTestClass";
     class = RegisterClassA(&wc);
-todo_wine
     ok(class != 0, "Failed to register class.\n");
 
     ret = DeactivateActCtx(0, cookie);
     ok(ret, "Failed to deactivate context.\n");
 
     ret = UnregisterClassA("4.3.2.1!MyTestClass", hinst);
-todo_wine
     ok(ret, "Failed to unregister class.\n");
 
     ret = UnregisterClassA("MyTestClass", hinst);
-- 
2.15.1




More information about the wine-devel mailing list