Module: wine Branch: master Commit: 37182e3f0ffdf462d48a098405089388aa7bc28a URL: http://source.winehq.org/git/wine.git/?a=commit;h=37182e3f0ffdf462d48a098405...
Author: Nikolay Sivov nsivov@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);