[PATCH 2/3] Add support for window class redirection with SxS manifest

Nikolay Sivov bunglehead at gmail.com
Thu Dec 17 14:52:10 CST 2009


---
 dlls/user32/class.c    |   20 ++++++++++++
 dlls/user32/controls.h |    1 +
 dlls/user32/win.c      |   82 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 103 insertions(+), 0 deletions(-)

diff --git a/dlls/user32/class.c b/dlls/user32/class.c
index e8ca0e5..da0167d 100644
--- a/dlls/user32/class.c
+++ b/dlls/user32/class.c
@@ -384,6 +384,25 @@ static CLASS *CLASS_RegisterClass( LPCWSTR name, HINSTANCE hInstance, BOOL local
     return classPtr;
 }
 
+/***********************************************************************
+ *           is_class_redirectable
+ *
+ * Checks if class redirection through SxS is available for this class.
+ */
+BOOL is_class_redirectable( LPCWSTR className, ACTCTX_SECTION_KEYED_DATA *data )
+{
+    ACTCTX_SECTION_KEYED_DATA key_data = { sizeof(key_data) };
+
+    if (get_int_atom_value(className)) return FALSE;
+
+    if (!data) data = &key_data;
+
+    return FindActCtxSectionStringW(FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX,
+                                    NULL,
+                                    ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION,
+                                    className,
+                                    data);
+}
 
 /***********************************************************************
  *           register_builtin
@@ -395,6 +414,7 @@ static void register_builtin( const struct builtin_class_descr *descr )
 {
     CLASS *classPtr;
 
+    if (is_class_redirectable( descr->name, NULL )) return;
     if (!(classPtr = CLASS_RegisterClass( descr->name, user32_module, FALSE,
                                           descr->style, 0, descr->extra ))) return;
 
diff --git a/dlls/user32/controls.h b/dlls/user32/controls.h
index e7aa408..36a427d 100644
--- a/dlls/user32/controls.h
+++ b/dlls/user32/controls.h
@@ -125,6 +125,7 @@ extern WNDPROC get_class_winproc( struct tagCLASS *class ) DECLSPEC_HIDDEN;
 extern struct dce *get_class_dce( struct tagCLASS *class ) DECLSPEC_HIDDEN;
 extern struct dce *set_class_dce( struct tagCLASS *class, struct dce *dce ) DECLSPEC_HIDDEN;
 extern void CLASS_FreeModuleClasses( HMODULE16 hModule ) DECLSPEC_HIDDEN;
+extern BOOL is_class_redirectable( LPCWSTR className, ACTCTX_SECTION_KEYED_DATA *data ) DECLSPEC_HIDDEN;
 
 /* defwnd proc */
 extern HBRUSH DEFWND_ControlColor( HDC hDC, UINT ctlType ) DECLSPEC_HIDDEN;
diff --git a/dlls/user32/win.c b/dlls/user32/win.c
index 9712beb..cdc9f6d 100644
--- a/dlls/user32/win.c
+++ b/dlls/user32/win.c
@@ -1063,6 +1063,85 @@ static void dump_window_styles( DWORD style, DWORD exstyle )
 #undef DUMPED_EX_STYLES
 }
 
+/***********************************************************************
+ *  notify_class_redirection
+ *
+ *  Tries to redirect specified window class to SxS module that claims to
+ *  support it.
+ */
+static BOOL notify_class_redirection( LPCWSTR className )
+{
+    ASSEMBLY_FILE_DETAILED_INFORMATION *file_info;
+    ACTCTX_SECTION_KEYED_DATA key_data = { sizeof(key_data) };
+    ACTIVATION_CONTEXT_QUERY_INDEX query_index;
+    SIZE_T size;
+    BOOL ret;
+
+    PREGISTERCLASSNAMEW pRegisterClassNameW;
+    HMODULE mod;
+
+    TRACE("%s\n", wine_dbgstr_w(className));
+
+    if (!is_class_redirectable(className, &key_data)) return TRUE;
+
+    TRACE("string %s found\n", wine_dbgstr_w(className));
+    TRACE("hActCtx=%p, ulAssemblyRosterIndex=%u\n",
+           key_data.hActCtx, key_data.ulAssemblyRosterIndex);
+
+    query_index.ulAssemblyIndex = key_data.ulAssemblyRosterIndex - 1;
+    /* assuming single file SxS modules */
+    query_index.ulFileIndexInAssembly = 0;
+    size = 0;
+    ret = QueryActCtxW(0, key_data.hActCtx,
+                       &query_index,
+                       FileInformationInAssemblyOfAssemblyInActivationContext,
+                       NULL, 0, &size);
+
+    if (ret || GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+    {
+        ReleaseActCtx(key_data.hActCtx);
+        return TRUE;
+    }
+
+    file_info = HeapAlloc(GetProcessHeap(), 0, size);
+    if (!file_info) return TRUE;
+
+    ret = QueryActCtxW(0, key_data.hActCtx,
+                       &query_index,
+                       FileInformationInAssemblyOfAssemblyInActivationContext,
+                       file_info, size, NULL);
+
+    ReleaseActCtx(key_data.hActCtx);
+    if (!ret)
+    {
+        HeapFree(GetProcessHeap(), 0, file_info);
+        return TRUE;
+    }
+
+    TRACE("class redirection module found (%s)\n", wine_dbgstr_w(file_info->lpFileName));
+
+    if (!(mod = LoadLibraryW(file_info->lpFileName)))
+    {
+        WARN("failed to get module handle for (%s)\n", wine_dbgstr_w(file_info->lpFileName));
+        HeapFree(GetProcessHeap(), 0, file_info);
+        return TRUE;
+    }
+
+    if (!(pRegisterClassNameW = (void*)GetProcAddress(mod, "RegisterClassNameW")))
+    {
+        WARN("RegisterClassNameW() symbol not found in (%s)\n", wine_dbgstr_w(file_info->lpFileName));
+        ret = TRUE;
+        goto out;
+    }
+
+    /* native isn't protected from exception here too */
+    ret = pRegisterClassNameW(className);
+
+out:
+    HeapFree(GetProcessHeap(), 0, file_info);
+    FreeLibrary(mod);
+    return ret;
+}
 
 /***********************************************************************
  *           WIN_CreateWindowEx
@@ -1197,6 +1276,9 @@ HWND WIN_CreateWindowEx( CREATESTRUCTW *cs, LPCWSTR className, HINSTANCE module,
     else
         cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
 
+    /* Try window class redirection */
+    if (!notify_class_redirection( className )) return 0;
+
     /* Create the window structure */
 
     if (!(wndPtr = create_window_handle( parent, owner, className, module, unicode )))
-- 
1.5.6.5


--=-qdNhBdLRm72yfSMvbvRg--




More information about the wine-patches mailing list