Commit 2d764e90 authored by Jacek Caban's avatar Jacek Caban Committed by Alexandre Julliard

ntdll: Use module path as assembly path for manifests embedded in resources.

Fixes Office 2016 installer, which removes its .exe directory from load path, but expects to be able to load files listed in manifest. Signed-off-by: 's avatarJacek Caban <jacek@codeweavers.com> Signed-off-by: 's avatarAlexandre Julliard <julliard@winehq.org>
parent dd74b9c8
......@@ -818,6 +818,29 @@ static inline const char* debugstr_version(const struct assembly_version *ver)
return wine_dbg_sprintf("%u.%u.%u.%u", ver->major, ver->minor, ver->build, ver->revision);
}
static NTSTATUS get_module_filename( HMODULE module, UNICODE_STRING *str, unsigned int extra_len )
{
NTSTATUS status;
ULONG_PTR magic;
LDR_MODULE *pldr;
LdrLockLoaderLock(0, NULL, &magic);
status = LdrFindEntryForAddress( module, &pldr );
if (status == STATUS_SUCCESS)
{
if ((str->Buffer = RtlAllocateHeap( GetProcessHeap(), 0,
pldr->FullDllName.Length + extra_len + sizeof(WCHAR) )))
{
memcpy( str->Buffer, pldr->FullDllName.Buffer, pldr->FullDllName.Length + sizeof(WCHAR) );
str->Length = pldr->FullDllName.Length;
str->MaximumLength = pldr->FullDllName.Length + extra_len + sizeof(WCHAR);
}
else status = STATUS_NO_MEMORY;
}
LdrUnlockLoaderLock(0, magic);
return status;
}
static struct assembly *add_assembly(ACTIVATION_CONTEXT *actctx, enum assembly_type at)
{
struct assembly *assembly;
......@@ -2790,7 +2813,7 @@ static NTSTATUS parse_manifest_buffer( struct actctx_loader* acl, struct assembl
}
static NTSTATUS parse_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
LPCWSTR filename, LPCWSTR directory, BOOL shared,
LPCWSTR filename, HANDLE module, LPCWSTR directory, BOOL shared,
const void *buffer, SIZE_T size )
{
xmlbuf_t xmlbuf;
......@@ -2806,7 +2829,14 @@ static NTSTATUS parse_manifest( struct actctx_loader* acl, struct assembly_ident
if (directory && !(assembly->directory = strdupW(directory)))
return STATUS_NO_MEMORY;
if (filename) assembly->manifest.info = strdupW( filename + 4 /* skip \??\ prefix */ );
if (!filename)
{
UNICODE_STRING module_path;
if ((status = get_module_filename( module, &module_path, 0 ))) return status;
assembly->manifest.info = module_path.Buffer;
}
else if(!(assembly->manifest.info = strdupW( filename + 4 /* skip \??\ prefix */ ))) return STATUS_NO_MEMORY;
assembly->manifest.type = assembly->manifest.info ? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
: ACTIVATION_CONTEXT_PATH_TYPE_NONE;
......@@ -2863,29 +2893,6 @@ static NTSTATUS open_nt_file( HANDLE *handle, UNICODE_STRING *name )
return NtOpenFile( handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT );
}
static NTSTATUS get_module_filename( HMODULE module, UNICODE_STRING *str, unsigned int extra_len )
{
NTSTATUS status;
ULONG_PTR magic;
LDR_MODULE *pldr;
LdrLockLoaderLock(0, NULL, &magic);
status = LdrFindEntryForAddress( module, &pldr );
if (status == STATUS_SUCCESS)
{
if ((str->Buffer = RtlAllocateHeap( GetProcessHeap(), 0,
pldr->FullDllName.Length + extra_len + sizeof(WCHAR) )))
{
memcpy( str->Buffer, pldr->FullDllName.Buffer, pldr->FullDllName.Length + sizeof(WCHAR) );
str->Length = pldr->FullDllName.Length;
str->MaximumLength = pldr->FullDllName.Length + extra_len + sizeof(WCHAR);
}
else status = STATUS_NO_MEMORY;
}
LdrUnlockLoaderLock(0, magic);
return status;
}
static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assembly_identity* ai,
LPCWSTR filename, LPCWSTR directory, BOOL shared,
HANDLE hModule, LPCWSTR resname, ULONG lang )
......@@ -2937,7 +2944,7 @@ static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assemb
if (status == STATUS_SUCCESS) status = LdrAccessResource(hModule, entry, &ptr, NULL);
if (status == STATUS_SUCCESS)
status = parse_manifest(acl, ai, filename, directory, shared, ptr, entry->Size);
status = parse_manifest(acl, ai, filename, hModule, directory, shared, ptr, entry->Size);
return status;
}
......@@ -3024,7 +3031,7 @@ static NTSTATUS get_manifest_in_manifest_file( struct actctx_loader* acl, struct
status = NtQueryInformationFile( file, &io, &info, sizeof(info), FileEndOfFileInformation );
if (status == STATUS_SUCCESS)
status = parse_manifest(acl, ai, filename, directory, shared, base, info.EndOfFile.QuadPart);
status = parse_manifest(acl, ai, filename, NULL, directory, shared, base, info.EndOfFile.QuadPart);
NtUnmapViewOfSection( GetCurrentProcess(), base );
return status;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment