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