Nikolay Sivov : ntdll: Try application manifest path when searching for dependent assemblies.

Alexandre Julliard julliard at winehq.org
Wed Sep 11 16:01:46 CDT 2013


Module: wine
Branch: master
Commit: 37182e3f0ffdf462d48a098405089388aa7bc28a
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=37182e3f0ffdf462d48a098405089388aa7bc28a

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Tue Sep 10 20:16:17 2013 +0400

ntdll: Try application manifest path when searching for dependent assemblies.

---

 dlls/kernel32/tests/actctx.c |   68 ++++++++++++++++++++++++++++++++++++++++++
 dlls/kernel32/tests/path.c   |    1 -
 dlls/ntdll/actctx.c          |   27 ++++++++++++----
 3 files changed, 88 insertions(+), 8 deletions(-)

diff --git a/dlls/kernel32/tests/actctx.c b/dlls/kernel32/tests/actctx.c
index ae44fb4..631e2c0 100644
--- a/dlls/kernel32/tests/actctx.c
+++ b/dlls/kernel32/tests/actctx.c
@@ -28,6 +28,7 @@
 #include "initguid.h"
 
 static BOOL   (WINAPI *pActivateActCtx)(HANDLE,ULONG_PTR*);
+static HANDLE (WINAPI *pCreateActCtxA)(PCACTCTXA);
 static HANDLE (WINAPI *pCreateActCtxW)(PCACTCTXW);
 static BOOL   (WINAPI *pDeactivateActCtx)(DWORD,ULONG_PTR);
 static BOOL   (WINAPI *pFindActCtxSectionStringW)(DWORD,const GUID *,ULONG,LPCWSTR,PACTCTX_SECTION_KEYED_DATA);
@@ -1964,12 +1965,78 @@ static void init_paths(void)
     lstrcpyW(app_manifest_path+lstrlenW(app_manifest_path), dot_manifest);
 }
 
+static void write_manifest(const char *filename, const char *manifest)
+{
+    HANDLE file;
+    DWORD size;
+    CHAR path[MAX_PATH];
+
+    GetTempPathA(sizeof(path)/sizeof(CHAR), path);
+    strcat(path, filename);
+
+    file = CreateFileA(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+    ok(file != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError());
+    WriteFile(file, manifest, strlen(manifest), &size, NULL);
+    CloseHandle(file);
+}
+
+static void delete_manifest_file(const char *filename)
+{
+    CHAR path[MAX_PATH];
+
+    GetTempPathA(sizeof(path)/sizeof(CHAR), path);
+    strcat(path, filename);
+    DeleteFileA(path);
+}
+
+static void test_CreateActCtx(void)
+{
+    CHAR path[MAX_PATH], dir[MAX_PATH];
+    ACTCTXA actctx;
+    HANDLE handle;
+
+    GetTempPathA(sizeof(path)/sizeof(CHAR), path);
+    strcat(path, "main_wndcls.manifest");
+
+    write_manifest("testdep1.manifest", manifest_wndcls1);
+    write_manifest("testdep2.manifest", manifest_wndcls2);
+    write_manifest("main_wndcls.manifest", manifest_wndcls_main);
+
+    memset(&actctx, 0, sizeof(ACTCTXA));
+    actctx.cbSize = sizeof(ACTCTXA);
+    actctx.lpSource = path;
+
+    /* create using lpSource without specified directory */
+    handle = pCreateActCtxA(&actctx);
+    ok(handle != INVALID_HANDLE_VALUE, "failed to generate context, error %u\n", GetLastError());
+    pReleaseActCtx(handle);
+
+    /* with specified directory, that doesn't contain dependent assembly */
+    GetWindowsDirectoryA(dir, sizeof(dir)/sizeof(CHAR));
+
+    memset(&actctx, 0, sizeof(ACTCTXA));
+    actctx.cbSize = sizeof(ACTCTXA);
+    actctx.dwFlags = ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID;
+    actctx.lpAssemblyDirectory = dir;
+    actctx.lpSource = path;
+
+    handle = pCreateActCtxA(&actctx);
+todo_wine
+    ok(handle == INVALID_HANDLE_VALUE && GetLastError() == ERROR_SXS_CANT_GEN_ACTCTX,
+        "got handle %p, supposed to fail\n", handle);
+    if (handle != INVALID_HANDLE_VALUE) pReleaseActCtx(handle);
+
+    delete_manifest_file("main.manifest");
+    delete_manifest_file("testdep1.manifest");
+}
+
 static BOOL init_funcs(void)
 {
     HMODULE hKernel32 = GetModuleHandle("kernel32");
 
 #define X(f) if (!(p##f = (void*)GetProcAddress(hKernel32, #f))) return FALSE;
     X(ActivateActCtx);
+    X(CreateActCtxA);
     X(CreateActCtxW);
     X(DeactivateActCtx);
     X(FindActCtxSectionStringW);
@@ -2003,5 +2070,6 @@ START_TEST(actctx)
     }
 
     test_actctx();
+    test_CreateActCtx();
     run_child_process();
 }
diff --git a/dlls/kernel32/tests/path.c b/dlls/kernel32/tests/path.c
index fd40547..601c2e5 100644
--- a/dlls/kernel32/tests/path.c
+++ b/dlls/kernel32/tests/path.c
@@ -1621,7 +1621,6 @@ static HANDLE test_create(const char *file)
     actctx.lpSource = manifest_path;
 
     handle = pCreateActCtxW(&actctx);
-todo_wine
     ok(handle != INVALID_HANDLE_VALUE, "failed to create context, error %u\n", GetLastError());
 
     ok(actctx.cbSize == sizeof(actctx), "cbSize=%d\n", actctx.cbSize);
diff --git a/dlls/ntdll/actctx.c b/dlls/ntdll/actctx.c
index 259e395..795f7c6 100644
--- a/dlls/ntdll/actctx.c
+++ b/dlls/ntdll/actctx.c
@@ -2767,6 +2767,7 @@ static NTSTATUS lookup_assembly(struct actctx_loader* acl,
     NTSTATUS status;
     UNICODE_STRING nameW;
     HANDLE file;
+    DWORD len;
 
     TRACE( "looking for name=%s version=%s arch=%s\n",
            debugstr_w(ai->name), debugstr_version(&ai->version), debugstr_w(ai->arch) );
@@ -2775,9 +2776,12 @@ static NTSTATUS lookup_assembly(struct actctx_loader* acl,
 
     /* FIXME: add support for language specific lookup */
 
+    len = max(RtlGetFullPathName_U(acl->actctx->assemblies->manifest.info, 0, NULL, NULL) / sizeof(WCHAR),
+        strlenW(acl->actctx->appdir.info));
+
     nameW.Buffer = NULL;
     if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
-                                    (strlenW(acl->actctx->appdir.info) + 2 * strlenW(ai->name) + 2) * sizeof(WCHAR) + sizeof(dotManifestW) )))
+                                    (len + 2 * strlenW(ai->name) + 2) * sizeof(WCHAR) + sizeof(dotManifestW) )))
         return STATUS_NO_MEMORY;
 
     if (!(directory = build_assembly_dir( ai )))
@@ -2786,16 +2790,25 @@ static NTSTATUS lookup_assembly(struct actctx_loader* acl,
         return STATUS_NO_MEMORY;
     }
 
-    /* lookup in appdir\name.dll
-     *           appdir\name.manifest
-     *           appdir\name\name.dll
-     *           appdir\name\name.manifest
+    /* Lookup in <dir>\name.dll
+     *           <dir>\name.manifest
+     *           <dir>\name\name.dll
+     *           <dir>\name\name.manifest
+     *
+     * First 'appdir' is used as <dir>, if that failed
+     * it tries application manifest file path.
      */
     strcpyW( buffer, acl->actctx->appdir.info );
     p = buffer + strlenW(buffer);
-    for (i = 0; i < 2; i++)
+    for (i = 0; i < 4; i++)
     {
-        *p++ = '\\';
+        if (i == 2)
+        {
+            struct assembly *assembly = acl->actctx->assemblies;
+            if (!RtlGetFullPathName_U(assembly->manifest.info, len * sizeof(WCHAR), buffer, &p)) break;
+        }
+        else *p++ = '\\';
+
         strcpyW( p, ai->name );
         p += strlenW(p);
 




More information about the wine-cvs mailing list