ntdll: Store the base directory for an assembly (based on a patch by Eric Pouech).
This commit is contained in:
parent
4156a716b0
commit
ad0d2b90ee
|
@ -158,6 +158,7 @@ struct assembly
|
||||||
enum assembly_type type;
|
enum assembly_type type;
|
||||||
struct assembly_identity id;
|
struct assembly_identity id;
|
||||||
struct file_info manifest;
|
struct file_info manifest;
|
||||||
|
WCHAR *directory;
|
||||||
BOOL no_inherit;
|
BOOL no_inherit;
|
||||||
struct dll_redirect *dlls;
|
struct dll_redirect *dlls;
|
||||||
unsigned int num_dlls;
|
unsigned int num_dlls;
|
||||||
|
@ -234,7 +235,6 @@ static WCHAR *strdupW(const WCHAR* str)
|
||||||
{
|
{
|
||||||
WCHAR* ptr;
|
WCHAR* ptr;
|
||||||
|
|
||||||
if (!str) return NULL;
|
|
||||||
if (!(ptr = RtlAllocateHeap(GetProcessHeap(), 0, (strlenW(str) + 1) * sizeof(WCHAR))))
|
if (!(ptr = RtlAllocateHeap(GetProcessHeap(), 0, (strlenW(str) + 1) * sizeof(WCHAR))))
|
||||||
return NULL;
|
return NULL;
|
||||||
return strcpyW(ptr, str);
|
return strcpyW(ptr, str);
|
||||||
|
@ -480,6 +480,36 @@ static void free_depend_manifests(struct actctx_loader* acl)
|
||||||
RtlFreeHeap(GetProcessHeap(), 0, acl->dependencies);
|
RtlFreeHeap(GetProcessHeap(), 0, acl->dependencies);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static WCHAR *build_assembly_dir(struct assembly_identity* ai)
|
||||||
|
{
|
||||||
|
static const WCHAR undW[] = {'_',0};
|
||||||
|
static const WCHAR noneW[] = {'n','o','n','e',0};
|
||||||
|
static const WCHAR mskeyW[] = {'d','e','a','d','b','e','e','f',0};
|
||||||
|
static const WCHAR versionW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
|
||||||
|
|
||||||
|
const WCHAR *key = ai->public_key ? ai->public_key : noneW;
|
||||||
|
const WCHAR *lang = ai->language ? ai->language : noneW;
|
||||||
|
SIZE_T size = (strlenW(ai->arch) + 1 + strlenW(ai->name) + 1 + strlenW(key) + 24 + 1 +
|
||||||
|
strlenW(lang) + 1) * sizeof(WCHAR) + sizeof(mskeyW);
|
||||||
|
WCHAR *ret;
|
||||||
|
|
||||||
|
if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, size ))) return NULL;
|
||||||
|
|
||||||
|
strcpyW( ret, ai->arch );
|
||||||
|
strcatW( ret, undW );
|
||||||
|
strcatW( ret, ai->name );
|
||||||
|
strcatW( ret, undW );
|
||||||
|
strcatW( ret, key );
|
||||||
|
strcatW( ret, undW );
|
||||||
|
sprintfW( ret + strlenW(ret), versionW,
|
||||||
|
ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
|
||||||
|
strcatW( ret, undW );
|
||||||
|
strcatW( ret, lang );
|
||||||
|
strcatW( ret, undW );
|
||||||
|
strcatW( ret, mskeyW );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static ACTIVATION_CONTEXT *check_actctx( HANDLE h )
|
static ACTIVATION_CONTEXT *check_actctx( HANDLE h )
|
||||||
{
|
{
|
||||||
ACTIVATION_CONTEXT *actctx = h;
|
ACTIVATION_CONTEXT *actctx = h;
|
||||||
|
@ -517,6 +547,7 @@ static void actctx_release( ACTIVATION_CONTEXT *actctx )
|
||||||
}
|
}
|
||||||
RtlFreeHeap( GetProcessHeap(), 0, assembly->dlls );
|
RtlFreeHeap( GetProcessHeap(), 0, assembly->dlls );
|
||||||
RtlFreeHeap( GetProcessHeap(), 0, assembly->manifest.info );
|
RtlFreeHeap( GetProcessHeap(), 0, assembly->manifest.info );
|
||||||
|
RtlFreeHeap( GetProcessHeap(), 0, assembly->directory );
|
||||||
free_entity_array( &assembly->entities );
|
free_entity_array( &assembly->entities );
|
||||||
free_assembly_identity(&assembly->id);
|
free_assembly_identity(&assembly->id);
|
||||||
}
|
}
|
||||||
|
@ -1336,16 +1367,19 @@ static BOOL parse_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl,
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS parse_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
|
static NTSTATUS parse_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
|
||||||
LPCWSTR filename, xmlbuf_t* xmlbuf )
|
LPCWSTR filename, LPCWSTR directory, xmlbuf_t* xmlbuf )
|
||||||
{
|
{
|
||||||
xmlstr_t elem;
|
xmlstr_t elem;
|
||||||
struct assembly* assembly;
|
struct assembly* assembly;
|
||||||
|
|
||||||
TRACE( "parsing manifest loaded from %s\n", debugstr_w(filename) );
|
TRACE( "parsing manifest loaded from %s base dir %s\n", debugstr_w(filename), debugstr_w(directory) );
|
||||||
|
|
||||||
if (!(assembly = add_assembly(acl->actctx, ASSEMBLY_MANIFEST)))
|
if (!(assembly = add_assembly(acl->actctx, ASSEMBLY_MANIFEST)))
|
||||||
return STATUS_SXS_CANT_GEN_ACTCTX;
|
return STATUS_SXS_CANT_GEN_ACTCTX;
|
||||||
|
|
||||||
|
if (directory && !(assembly->directory = strdupW(directory)))
|
||||||
|
return STATUS_NO_MEMORY;
|
||||||
|
|
||||||
if (filename) assembly->manifest.info = strdupW( filename + 4 /* skip \??\ prefix */ );
|
if (filename) assembly->manifest.info = strdupW( filename + 4 /* skip \??\ prefix */ );
|
||||||
assembly->manifest.type = assembly->manifest.info ? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
|
assembly->manifest.type = assembly->manifest.info ? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
|
||||||
: ACTIVATION_CONTEXT_PATH_TYPE_NONE;
|
: ACTIVATION_CONTEXT_PATH_TYPE_NONE;
|
||||||
|
@ -1420,7 +1454,8 @@ static NTSTATUS get_module_filename( HMODULE module, UNICODE_STRING *str, unsign
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assembly_identity* ai,
|
static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assembly_identity* ai,
|
||||||
LPCWSTR filename, HANDLE hModule, LPCWSTR resname, ULONG lang )
|
LPCWSTR filename, LPCWSTR directory, HANDLE hModule,
|
||||||
|
LPCWSTR resname, ULONG lang )
|
||||||
{
|
{
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
UNICODE_STRING nameW;
|
UNICODE_STRING nameW;
|
||||||
|
@ -1463,13 +1498,14 @@ static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assemb
|
||||||
xmlbuf_t buf;
|
xmlbuf_t buf;
|
||||||
buf.ptr = ptr;
|
buf.ptr = ptr;
|
||||||
buf.end = buf.ptr + entry->Size;
|
buf.end = buf.ptr + entry->Size;
|
||||||
status = parse_manifest(acl, ai, filename, &buf);
|
status = parse_manifest(acl, ai, filename, directory, &buf);
|
||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS get_manifest_in_pe_file( struct actctx_loader* acl, struct assembly_identity* ai,
|
static NTSTATUS get_manifest_in_pe_file( struct actctx_loader* acl, struct assembly_identity* ai,
|
||||||
LPCWSTR filename, HANDLE file, LPCWSTR resname, ULONG lang )
|
LPCWSTR filename, LPCWSTR directory, HANDLE file,
|
||||||
|
LPCWSTR resname, ULONG lang )
|
||||||
{
|
{
|
||||||
HANDLE mapping;
|
HANDLE mapping;
|
||||||
OBJECT_ATTRIBUTES attr;
|
OBJECT_ATTRIBUTES attr;
|
||||||
|
@ -1504,7 +1540,7 @@ static NTSTATUS get_manifest_in_pe_file( struct actctx_loader* acl, struct assem
|
||||||
if (RtlImageNtHeader(base)) /* we got a PE file */
|
if (RtlImageNtHeader(base)) /* we got a PE file */
|
||||||
{
|
{
|
||||||
HANDLE module = (HMODULE)((ULONG_PTR)base | 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
|
HANDLE module = (HMODULE)((ULONG_PTR)base | 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
|
||||||
status = get_manifest_in_module( acl, ai, filename, module, resname, lang );
|
status = get_manifest_in_module( acl, ai, filename, directory, module, resname, lang );
|
||||||
}
|
}
|
||||||
else status = STATUS_INVALID_IMAGE_FORMAT;
|
else status = STATUS_INVALID_IMAGE_FORMAT;
|
||||||
|
|
||||||
|
@ -1513,7 +1549,7 @@ static NTSTATUS get_manifest_in_pe_file( struct actctx_loader* acl, struct assem
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS get_manifest_in_manifest_file( struct actctx_loader* acl, struct assembly_identity* ai,
|
static NTSTATUS get_manifest_in_manifest_file( struct actctx_loader* acl, struct assembly_identity* ai,
|
||||||
LPCWSTR filename, HANDLE file )
|
LPCWSTR filename, LPCWSTR directory, HANDLE file )
|
||||||
{
|
{
|
||||||
HANDLE mapping;
|
HANDLE mapping;
|
||||||
OBJECT_ATTRIBUTES attr;
|
OBJECT_ATTRIBUTES attr;
|
||||||
|
@ -1548,7 +1584,7 @@ static NTSTATUS get_manifest_in_manifest_file( struct actctx_loader* acl, struct
|
||||||
|
|
||||||
buf.ptr = base;
|
buf.ptr = base;
|
||||||
buf.end = buf.ptr + count;
|
buf.end = buf.ptr + count;
|
||||||
status = parse_manifest(acl, ai, filename, &buf);
|
status = parse_manifest(acl, ai, filename, directory, &buf);
|
||||||
|
|
||||||
NtUnmapViewOfSection( GetCurrentProcess(), base );
|
NtUnmapViewOfSection( GetCurrentProcess(), base );
|
||||||
return status;
|
return status;
|
||||||
|
@ -1556,7 +1592,7 @@ static NTSTATUS get_manifest_in_manifest_file( struct actctx_loader* acl, struct
|
||||||
|
|
||||||
/* try to load the .manifest file associated to the file */
|
/* try to load the .manifest file associated to the file */
|
||||||
static NTSTATUS get_manifest_in_associated_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
|
static NTSTATUS get_manifest_in_associated_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
|
||||||
LPCWSTR filename, HMODULE module, LPCWSTR resname )
|
LPCWSTR filename, LPCWSTR directory, HMODULE module, LPCWSTR resname )
|
||||||
{
|
{
|
||||||
static const WCHAR fmtW[] = { '.','%','l','u',0 };
|
static const WCHAR fmtW[] = { '.','%','l','u',0 };
|
||||||
WCHAR *buffer;
|
WCHAR *buffer;
|
||||||
|
@ -1597,7 +1633,7 @@ static NTSTATUS get_manifest_in_associated_manifest( struct actctx_loader* acl,
|
||||||
status = open_nt_file( &file, &nameW );
|
status = open_nt_file( &file, &nameW );
|
||||||
if (status == STATUS_SUCCESS)
|
if (status == STATUS_SUCCESS)
|
||||||
{
|
{
|
||||||
status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, file );
|
status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, file );
|
||||||
NtClose( file );
|
NtClose( file );
|
||||||
}
|
}
|
||||||
RtlFreeUnicodeString( &nameW );
|
RtlFreeUnicodeString( &nameW );
|
||||||
|
@ -1731,16 +1767,17 @@ static NTSTATUS lookup_winsxs(struct actctx_loader* acl, struct assembly_identit
|
||||||
|
|
||||||
path[path_us.Length/sizeof(WCHAR)] = '\\';
|
path[path_us.Length/sizeof(WCHAR)] = '\\';
|
||||||
strcpyW( path + path_us.Length/sizeof(WCHAR) + 1, file );
|
strcpyW( path + path_us.Length/sizeof(WCHAR) + 1, file );
|
||||||
RtlFreeHeap( GetProcessHeap(), 0, file );
|
|
||||||
RtlInitUnicodeString( &path_us, path );
|
RtlInitUnicodeString( &path_us, path );
|
||||||
|
*strrchrW(file, '.') = 0; /* remove .manifest extension */
|
||||||
|
|
||||||
if (!open_nt_file( &handle, &path_us ))
|
if (!open_nt_file( &handle, &path_us ))
|
||||||
{
|
{
|
||||||
io.u.Status = get_manifest_in_manifest_file(acl, &sxs_ai, path_us.Buffer, handle);
|
io.u.Status = get_manifest_in_manifest_file(acl, &sxs_ai, path_us.Buffer, file, handle);
|
||||||
NtClose( handle );
|
NtClose( handle );
|
||||||
}
|
}
|
||||||
else io.u.Status = STATUS_NO_SUCH_FILE;
|
else io.u.Status = STATUS_NO_SUCH_FILE;
|
||||||
|
|
||||||
|
RtlFreeHeap( GetProcessHeap(), 0, file );
|
||||||
RtlFreeUnicodeString( &path_us );
|
RtlFreeUnicodeString( &path_us );
|
||||||
return io.u.Status;
|
return io.u.Status;
|
||||||
}
|
}
|
||||||
|
@ -1750,7 +1787,7 @@ static NTSTATUS lookup_assembly(struct actctx_loader* acl,
|
||||||
{
|
{
|
||||||
static const WCHAR dotDllW[] = {'.','d','l','l',0};
|
static const WCHAR dotDllW[] = {'.','d','l','l',0};
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
WCHAR *buffer, *p;
|
WCHAR *buffer, *p, *directory;
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
UNICODE_STRING nameW;
|
UNICODE_STRING nameW;
|
||||||
HANDLE file;
|
HANDLE file;
|
||||||
|
@ -1764,6 +1801,12 @@ static NTSTATUS lookup_assembly(struct actctx_loader* acl,
|
||||||
(strlenW(acl->actctx->appdir.info) + 2 * strlenW(ai->name) + 2) * sizeof(WCHAR) + sizeof(dotManifestW) )))
|
(strlenW(acl->actctx->appdir.info) + 2 * strlenW(ai->name) + 2) * sizeof(WCHAR) + sizeof(dotManifestW) )))
|
||||||
return STATUS_NO_MEMORY;
|
return STATUS_NO_MEMORY;
|
||||||
|
|
||||||
|
if (!(directory = build_assembly_dir( ai )))
|
||||||
|
{
|
||||||
|
RtlFreeHeap( GetProcessHeap(), 0, buffer );
|
||||||
|
return STATUS_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
/* lookup in appdir\name.dll
|
/* lookup in appdir\name.dll
|
||||||
* appdir\name.manifest
|
* appdir\name.manifest
|
||||||
* appdir\name\name.dll
|
* appdir\name\name.dll
|
||||||
|
@ -1783,7 +1826,7 @@ static NTSTATUS lookup_assembly(struct actctx_loader* acl,
|
||||||
status = open_nt_file( &file, &nameW );
|
status = open_nt_file( &file, &nameW );
|
||||||
if (!status)
|
if (!status)
|
||||||
{
|
{
|
||||||
status = get_manifest_in_pe_file( acl, ai, nameW.Buffer, file,
|
status = get_manifest_in_pe_file( acl, ai, nameW.Buffer, directory, file,
|
||||||
(LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID, 0 );
|
(LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID, 0 );
|
||||||
NtClose( file );
|
NtClose( file );
|
||||||
break;
|
break;
|
||||||
|
@ -1797,15 +1840,18 @@ static NTSTATUS lookup_assembly(struct actctx_loader* acl,
|
||||||
status = open_nt_file( &file, &nameW );
|
status = open_nt_file( &file, &nameW );
|
||||||
if (!status)
|
if (!status)
|
||||||
{
|
{
|
||||||
status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, file );
|
status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, file );
|
||||||
NtClose( file );
|
NtClose( file );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
RtlFreeUnicodeString( &nameW );
|
RtlFreeUnicodeString( &nameW );
|
||||||
}
|
}
|
||||||
|
status = STATUS_SXS_ASSEMBLY_NOT_FOUND;
|
||||||
}
|
}
|
||||||
RtlFreeUnicodeString( &nameW );
|
RtlFreeUnicodeString( &nameW );
|
||||||
return STATUS_SXS_ASSEMBLY_NOT_FOUND;
|
RtlFreeHeap( GetProcessHeap(), 0, directory );
|
||||||
|
RtlFreeHeap( GetProcessHeap(), 0, buffer );
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS parse_depend_manifests(struct actctx_loader* acl)
|
static NTSTATUS parse_depend_manifests(struct actctx_loader* acl)
|
||||||
|
@ -1855,6 +1901,7 @@ void actctx_init(void)
|
||||||
NTSTATUS WINAPI RtlCreateActivationContext( HANDLE *handle, const void *ptr )
|
NTSTATUS WINAPI RtlCreateActivationContext( HANDLE *handle, const void *ptr )
|
||||||
{
|
{
|
||||||
const ACTCTXW *pActCtx = ptr; /* FIXME: not the right structure */
|
const ACTCTXW *pActCtx = ptr; /* FIXME: not the right structure */
|
||||||
|
const WCHAR *directory = NULL;
|
||||||
ACTIVATION_CONTEXT *actctx;
|
ACTIVATION_CONTEXT *actctx;
|
||||||
UNICODE_STRING nameW;
|
UNICODE_STRING nameW;
|
||||||
ULONG lang = 0;
|
ULONG lang = 0;
|
||||||
|
@ -1913,32 +1960,33 @@ NTSTATUS WINAPI RtlCreateActivationContext( HANDLE *handle, const void *ptr )
|
||||||
acl.allocated_dependencies = 0;
|
acl.allocated_dependencies = 0;
|
||||||
|
|
||||||
if (pActCtx->dwFlags & ACTCTX_FLAG_LANGID_VALID) lang = pActCtx->wLangId;
|
if (pActCtx->dwFlags & ACTCTX_FLAG_LANGID_VALID) lang = pActCtx->wLangId;
|
||||||
|
if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID) directory = pActCtx->lpAssemblyDirectory;
|
||||||
|
|
||||||
if (pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID)
|
if (pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID)
|
||||||
{
|
{
|
||||||
/* if we have a resource it's a PE file */
|
/* if we have a resource it's a PE file */
|
||||||
if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)
|
if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)
|
||||||
{
|
{
|
||||||
status = get_manifest_in_module( &acl, NULL, NULL, pActCtx->hModule,
|
status = get_manifest_in_module( &acl, NULL, NULL, directory, pActCtx->hModule,
|
||||||
pActCtx->lpResourceName, lang );
|
pActCtx->lpResourceName, lang );
|
||||||
if (status)
|
if (status)
|
||||||
/* FIXME: what to do if pActCtx->lpSource is set */
|
/* FIXME: what to do if pActCtx->lpSource is set */
|
||||||
status = get_manifest_in_associated_manifest( &acl, NULL, NULL, pActCtx->hModule,
|
status = get_manifest_in_associated_manifest( &acl, NULL, NULL, directory,
|
||||||
pActCtx->lpResourceName );
|
pActCtx->hModule, pActCtx->lpResourceName );
|
||||||
}
|
}
|
||||||
else if (pActCtx->lpSource)
|
else if (pActCtx->lpSource)
|
||||||
{
|
{
|
||||||
status = get_manifest_in_pe_file( &acl, NULL, nameW.Buffer, file,
|
status = get_manifest_in_pe_file( &acl, NULL, nameW.Buffer, directory,
|
||||||
pActCtx->lpResourceName, lang );
|
file, pActCtx->lpResourceName, lang );
|
||||||
if (status)
|
if (status)
|
||||||
status = get_manifest_in_associated_manifest( &acl, NULL, nameW.Buffer, NULL,
|
status = get_manifest_in_associated_manifest( &acl, NULL, nameW.Buffer, directory,
|
||||||
pActCtx->lpResourceName );
|
NULL, pActCtx->lpResourceName );
|
||||||
}
|
}
|
||||||
else status = STATUS_INVALID_PARAMETER;
|
else status = STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
status = get_manifest_in_manifest_file( &acl, NULL, nameW.Buffer, file );
|
status = get_manifest_in_manifest_file( &acl, NULL, nameW.Buffer, directory, file );
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file) NtClose( file );
|
if (file) NtClose( file );
|
||||||
|
|
Loading…
Reference in New Issue