From: Piotr Caban Subject: ntdll: Handle ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID flag when opening manifest in RtlCreateActivationContext (try2) Message-Id: <547641E2.2060006@codeweavers.com> Date: Wed, 26 Nov 2014 22:10:58 +0100 try2: - fix compilation warning - change return value in out of memory case --- dlls/kernel32/tests/actctx.c | 59 ++++++++++++++++++++++++++++++++++++++++++++ dlls/ntdll/actctx.c | 31 ++++++++++++++++++++++- 2 files changed, 89 insertions(+), 1 deletion(-) diff --git a/dlls/kernel32/tests/actctx.c b/dlls/kernel32/tests/actctx.c index 1f5683f..c964743 100644 --- a/dlls/kernel32/tests/actctx.c +++ b/dlls/kernel32/tests/actctx.c @@ -2166,6 +2166,65 @@ todo_wine handle = pCreateActCtxA(&actctx); ok(handle == INVALID_HANDLE_VALUE, "got handle %p\n", handle); ok(GetLastError() == ERROR_RESOURCE_TYPE_NOT_FOUND, "got error %d\n", GetLastError()); + + /* load manifest from lpAssemblyDirectory directory */ + write_manifest("testdir.manifest", manifest1); + GetTempPathA(sizeof(path)/sizeof(path[0]), path); + SetCurrentDirectoryA(path); + strcat(path, "assembly_dir"); + strcpy(dir, path); + strcat(path, "\\testdir.manifest"); + + memset(&actctx, 0, sizeof(actctx)); + actctx.cbSize = sizeof(actctx); + actctx.dwFlags = ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID; + actctx.lpSource = "testdir.manifest"; + actctx.lpAssemblyDirectory = dir; + + SetLastError(0xdeadbeef); + handle = pCreateActCtxA(&actctx); + ok(handle == INVALID_HANDLE_VALUE, "got handle %p\n", handle); + ok(GetLastError()==ERROR_PATH_NOT_FOUND || + broken(GetLastError()==ERROR_FILE_NOT_FOUND) /* WinXP */, + "got error %d\n", GetLastError()); + + CreateDirectoryA(dir, NULL); + memset(&actctx, 0, sizeof(actctx)); + actctx.cbSize = sizeof(actctx); + actctx.dwFlags = ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID; + actctx.lpSource = "testdir.manifest"; + actctx.lpAssemblyDirectory = dir; + + SetLastError(0xdeadbeef); + handle = pCreateActCtxA(&actctx); + ok(handle == INVALID_HANDLE_VALUE, "got handle %p\n", handle); + ok(GetLastError() == ERROR_FILE_NOT_FOUND, "got error %d\n", GetLastError()); + SetCurrentDirectoryW(work_dir); + + write_manifest("assembly_dir\\testdir.manifest", manifest1); + memset(&actctx, 0, sizeof(actctx)); + actctx.cbSize = sizeof(actctx); + actctx.dwFlags = ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID; + actctx.lpSource = "testdir.manifest"; + actctx.lpAssemblyDirectory = dir; + + handle = pCreateActCtxA(&actctx); + ok(handle != INVALID_HANDLE_VALUE, "got handle %p\n", handle); + pReleaseActCtx(handle); + + memset(&actctx, 0, sizeof(actctx)); + actctx.cbSize = sizeof(actctx); + actctx.dwFlags = ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID; + actctx.lpSource = path; + actctx.lpAssemblyDirectory = dir; + + handle = pCreateActCtxA(&actctx); + ok(handle != INVALID_HANDLE_VALUE, "got handle %p\n", handle); + pReleaseActCtx(handle); + + delete_manifest_file("testdir.manifest"); + delete_manifest_file("assembly_dir\\testdir.manifest"); + RemoveDirectoryA(dir); } static BOOL init_funcs(void) diff --git a/dlls/ntdll/actctx.c b/dlls/ntdll/actctx.c index 9a9dec9..e96e1d5 100644 --- a/dlls/ntdll/actctx.c +++ b/dlls/ntdll/actctx.c @@ -4535,7 +4535,36 @@ NTSTATUS WINAPI RtlCreateActivationContext( HANDLE *handle, const void *ptr ) if (pActCtx->lpSource && !((pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID) && (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID))) { - if (!RtlDosPathNameToNtPathName_U(pActCtx->lpSource, &nameW, NULL, NULL)) + const WCHAR *source; + BOOLEAN ret; + + if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID && + RtlDetermineDosPathNameType_U(pActCtx->lpSource) == RELATIVE_PATH) + { + DWORD dir_len, source_len; + WCHAR *src; + + dir_len = strlenW(pActCtx->lpAssemblyDirectory); + source_len = strlenW(pActCtx->lpSource); + if (!(src = RtlAllocateHeap( GetProcessHeap(), 0, (dir_len+source_len+2)*sizeof(WCHAR)))) + { + status = STATUS_NO_MEMORY; + goto error; + } + + memcpy(src, pActCtx->lpAssemblyDirectory, dir_len*sizeof(WCHAR)); + src[dir_len] = '\\'; + memcpy(src+dir_len+1, pActCtx->lpSource, (source_len+1)*sizeof(WCHAR)); + source = src; + } + else + { + source = pActCtx->lpSource; + } + + ret = RtlDosPathNameToNtPathName_U(source, &nameW, NULL, NULL); + if (source != pActCtx->lpSource) RtlFreeHeap( GetProcessHeap(), 0, source ); + if (!ret) { status = STATUS_NO_SUCH_FILE; goto error;