[PATCH v4 2/3] ntdll: Load builtin sxs dlls with the correct path

Fabian Maurer dark.shadow4 at web.de
Thu Jun 20 10:50:31 CDT 2019


---
 dlls/kernel32/tests/actctx.c |   1 -
 dlls/ntdll/loader.c          | 202 +++++++++++++++++++----------------
 2 files changed, 109 insertions(+), 94 deletions(-)

diff --git a/dlls/kernel32/tests/actctx.c b/dlls/kernel32/tests/actctx.c
index 19a51db742..76368e273e 100644
--- a/dlls/kernel32/tests/actctx.c
+++ b/dlls/kernel32/tests/actctx.c
@@ -3481,7 +3481,6 @@ static void test_builtin_sxs(void)
     GetModuleFileNameA(module_msvcp, path_msvcp, sizeof(path_msvcp));
     GetModuleFileNameA(module_msvcr, path_msvcr, sizeof(path_msvcr));
     ok(strncasecmp(expected_path, path_msvcp, strlen(expected_path)) == 0, "Expected path to start with %s, got %s\n", expected_path, path_msvcp);
-    todo_wine
     ok(strncasecmp(expected_path, path_msvcr, strlen(expected_path)) == 0, "Expected path to start with %s, got %s\n", expected_path, path_msvcr);

     DeactivateActCtx(0, cookie);
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
index 3d747edaba..c6d37ab14e 100644
--- a/dlls/ntdll/loader.c
+++ b/dlls/ntdll/loader.c
@@ -1710,6 +1710,99 @@ NTSTATUS WINAPI LdrGetProcedureAddress(HMODULE module, const ANSI_STRING *name,
 }


+/***********************************************************************
+ *  find_actctx_dll
+ *
+ * Find the full path (if any) of the dll from the activation context.
+ */
+static NTSTATUS find_actctx_dll( LPCWSTR libname, LPWSTR *fullname )
+{
+    static const WCHAR winsxsW[] = {'\\','w','i','n','s','x','s','\\'};
+    static const WCHAR dotManifestW[] = {'.','m','a','n','i','f','e','s','t',0};
+
+    ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *info;
+    ACTCTX_SECTION_KEYED_DATA data;
+    UNICODE_STRING nameW;
+    NTSTATUS status;
+    SIZE_T needed, size = 1024;
+    WCHAR *p;
+
+    RtlInitUnicodeString( &nameW, libname );
+    data.cbSize = sizeof(data);
+    status = RtlFindActivationContextSectionString( FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX, NULL,
+                                                    ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION,
+                                                    &nameW, &data );
+    if (status != STATUS_SUCCESS) return status;
+
+    for (;;)
+    {
+        if (!(info = RtlAllocateHeap( GetProcessHeap(), 0, size )))
+        {
+            status = STATUS_NO_MEMORY;
+            goto done;
+        }
+        status = RtlQueryInformationActivationContext( 0, data.hActCtx, &data.ulAssemblyRosterIndex,
+                                                       AssemblyDetailedInformationInActivationContext,
+                                                       info, size, &needed );
+        if (status == STATUS_SUCCESS) break;
+        if (status != STATUS_BUFFER_TOO_SMALL) goto done;
+        RtlFreeHeap( GetProcessHeap(), 0, info );
+        size = needed;
+        /* restart with larger buffer */
+    }
+
+    if (!info->lpAssemblyManifestPath || !info->lpAssemblyDirectoryName)
+    {
+        status = STATUS_SXS_KEY_NOT_FOUND;
+        goto done;
+    }
+
+    if ((p = strrchrW( info->lpAssemblyManifestPath, '\\' )))
+    {
+        DWORD dirlen = info->ulAssemblyDirectoryNameLength / sizeof(WCHAR);
+
+        p++;
+        if (strncmpiW( p, info->lpAssemblyDirectoryName, dirlen ) || strcmpiW( p + dirlen, dotManifestW ))
+        {
+            /* manifest name does not match directory name, so it's not a global
+             * windows/winsxs manifest; use the manifest directory name instead */
+            dirlen = p - info->lpAssemblyManifestPath;
+            needed = (dirlen + 1) * sizeof(WCHAR) + nameW.Length;
+            if (!(*fullname = p = RtlAllocateHeap( GetProcessHeap(), 0, needed )))
+            {
+                status = STATUS_NO_MEMORY;
+                goto done;
+            }
+            memcpy( p, info->lpAssemblyManifestPath, dirlen * sizeof(WCHAR) );
+            p += dirlen;
+            strcpyW( p, libname );
+            goto done;
+        }
+    }
+
+    needed = (strlenW(user_shared_data->NtSystemRoot) * sizeof(WCHAR) +
+              sizeof(winsxsW) + info->ulAssemblyDirectoryNameLength + nameW.Length + 2*sizeof(WCHAR));
+
+    if (!(*fullname = p = RtlAllocateHeap( GetProcessHeap(), 0, needed )))
+    {
+        status = STATUS_NO_MEMORY;
+        goto done;
+    }
+    strcpyW( p, user_shared_data->NtSystemRoot );
+    p += strlenW(p);
+    memcpy( p, winsxsW, sizeof(winsxsW) );
+    p += ARRAY_SIZE( winsxsW );
+    memcpy( p, info->lpAssemblyDirectoryName, info->ulAssemblyDirectoryNameLength );
+    p += info->ulAssemblyDirectoryNameLength / sizeof(WCHAR);
+    *p++ = '\\';
+    strcpyW( p, libname );
+done:
+    RtlFreeHeap( GetProcessHeap(), 0, info );
+    RtlReleaseActivationContext( data.hActCtx );
+    return status;
+}
+
+
 /***********************************************************************
  *           get_builtin_fullname
  *
@@ -1722,6 +1815,8 @@ static BOOL get_builtin_fullname( UNICODE_STRING *nt_name, const UNICODE_STRING
     static const WCHAR soW[] = {'.','s','o',0};
     WCHAR *p, *fullname;
     size_t i, len = strlen(filename);
+    WCHAR buffer[MAX_PATH];
+    NTSTATUS status;

     /* check if path can correspond to the dll we have */
     if (path && (p = strrchrW( path->Buffer, '\\' )))
@@ -1741,6 +1836,20 @@ static BOOL get_builtin_fullname( UNICODE_STRING *nt_name, const UNICODE_STRING
         }
     }

+    ascii_to_unicode(buffer, filename, strlen(filename) + 1);
+    status = find_actctx_dll(buffer, &fullname);
+    if (status == STATUS_SUCCESS)
+    {
+        strcpyW(buffer, fullname);
+        RtlFreeHeap(GetProcessHeap(), 0, fullname);
+        if (!(fullname = RtlAllocateHeap(GetProcessHeap(), 0,
+                                        (strlenW(nt_prefixW) + strlenW(buffer) + 1) * sizeof(WCHAR))))
+               return FALSE;
+        strcpyW(fullname, nt_prefixW);
+        strcatW(fullname, buffer);
+        goto done;
+    }
+
     if (!(fullname = RtlAllocateHeap( GetProcessHeap(), 0,
                                       (strlenW(system_dir) + len + 5) * sizeof(WCHAR) )))
         return FALSE;
@@ -2529,99 +2638,6 @@ static NTSTATUS load_builtin_dll( LPCWSTR load_path, const UNICODE_STRING *nt_na
 }


-/***********************************************************************
- *	find_actctx_dll
- *
- * Find the full path (if any) of the dll from the activation context.
- */
-static NTSTATUS find_actctx_dll( LPCWSTR libname, LPWSTR *fullname )
-{
-    static const WCHAR winsxsW[] = {'\\','w','i','n','s','x','s','\\'};
-    static const WCHAR dotManifestW[] = {'.','m','a','n','i','f','e','s','t',0};
-
-    ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *info;
-    ACTCTX_SECTION_KEYED_DATA data;
-    UNICODE_STRING nameW;
-    NTSTATUS status;
-    SIZE_T needed, size = 1024;
-    WCHAR *p;
-
-    RtlInitUnicodeString( &nameW, libname );
-    data.cbSize = sizeof(data);
-    status = RtlFindActivationContextSectionString( FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX, NULL,
-                                                    ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION,
-                                                    &nameW, &data );
-    if (status != STATUS_SUCCESS) return status;
-
-    for (;;)
-    {
-        if (!(info = RtlAllocateHeap( GetProcessHeap(), 0, size )))
-        {
-            status = STATUS_NO_MEMORY;
-            goto done;
-        }
-        status = RtlQueryInformationActivationContext( 0, data.hActCtx, &data.ulAssemblyRosterIndex,
-                                                       AssemblyDetailedInformationInActivationContext,
-                                                       info, size, &needed );
-        if (status == STATUS_SUCCESS) break;
-        if (status != STATUS_BUFFER_TOO_SMALL) goto done;
-        RtlFreeHeap( GetProcessHeap(), 0, info );
-        size = needed;
-        /* restart with larger buffer */
-    }
-
-    if (!info->lpAssemblyManifestPath || !info->lpAssemblyDirectoryName)
-    {
-        status = STATUS_SXS_KEY_NOT_FOUND;
-        goto done;
-    }
-
-    if ((p = strrchrW( info->lpAssemblyManifestPath, '\\' )))
-    {
-        DWORD dirlen = info->ulAssemblyDirectoryNameLength / sizeof(WCHAR);
-
-        p++;
-        if (strncmpiW( p, info->lpAssemblyDirectoryName, dirlen ) || strcmpiW( p + dirlen, dotManifestW ))
-        {
-            /* manifest name does not match directory name, so it's not a global
-             * windows/winsxs manifest; use the manifest directory name instead */
-            dirlen = p - info->lpAssemblyManifestPath;
-            needed = (dirlen + 1) * sizeof(WCHAR) + nameW.Length;
-            if (!(*fullname = p = RtlAllocateHeap( GetProcessHeap(), 0, needed )))
-            {
-                status = STATUS_NO_MEMORY;
-                goto done;
-            }
-            memcpy( p, info->lpAssemblyManifestPath, dirlen * sizeof(WCHAR) );
-            p += dirlen;
-            strcpyW( p, libname );
-            goto done;
-        }
-    }
-
-    needed = (strlenW(user_shared_data->NtSystemRoot) * sizeof(WCHAR) +
-              sizeof(winsxsW) + info->ulAssemblyDirectoryNameLength + nameW.Length + 2*sizeof(WCHAR));
-
-    if (!(*fullname = p = RtlAllocateHeap( GetProcessHeap(), 0, needed )))
-    {
-        status = STATUS_NO_MEMORY;
-        goto done;
-    }
-    strcpyW( p, user_shared_data->NtSystemRoot );
-    p += strlenW(p);
-    memcpy( p, winsxsW, sizeof(winsxsW) );
-    p += ARRAY_SIZE( winsxsW );
-    memcpy( p, info->lpAssemblyDirectoryName, info->ulAssemblyDirectoryNameLength );
-    p += info->ulAssemblyDirectoryNameLength / sizeof(WCHAR);
-    *p++ = '\\';
-    strcpyW( p, libname );
-done:
-    RtlFreeHeap( GetProcessHeap(), 0, info );
-    RtlReleaseActivationContext( data.hActCtx );
-    return status;
-}
-
-
 /***********************************************************************
  *	search_dll_file
  *
--
2.22.0




More information about the wine-devel mailing list