From d0d472bb3e8680e286e404a73fceb29cebe85b73 Mon Sep 17 00:00:00 2001 From: Jinoh Kang Date: Mon, 29 May 2023 21:18:42 +0900 Subject: [PATCH] ntdll: Don't hard-code DLL manifest resource ID when looking up dependency assembly. This allows any manifest resource IDs (e.g., ISOLATIONAWARE_MANIFEST_RESOURCE_ID) to be recognized when looking up the assembly manifest of a dependency. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=18889 --- dlls/kernel32/tests/actctx.c | 63 +++++++++++++++++------------------- dlls/ntdll/actctx.c | 27 ++++++++++++++-- 2 files changed, 55 insertions(+), 35 deletions(-) diff --git a/dlls/kernel32/tests/actctx.c b/dlls/kernel32/tests/actctx.c index 3c1c29f2ded..c6796a1ac64 100644 --- a/dlls/kernel32/tests/actctx.c +++ b/dlls/kernel32/tests/actctx.c @@ -3754,7 +3754,6 @@ struct multiple_manifest_test struct manifest_res_spec manifest_inline; /* optional */ const struct manifest_res_spec *manifests; /* optional */ DWORD expected_error; - BOOL is_todo_wine; }; #define subtest_manifest_res(d,e,t,l) subtest_manifest_res_(__LINE__,d,e,t,l) @@ -3853,7 +3852,6 @@ static DWORD subtest_manifest_res_(int line, const char *manifest_exe, const cha ok_(__FILE__, line)(handle != NULL, "CreateActCtxA returned %p (error %lu)\n", handle, err); ReleaseActCtx(handle); } - todo_wine_if(test_data->is_todo_wine) ok_(__FILE__, line)(err == test_data->expected_error, "expected error %lu, got %lu\n", test_data->expected_error, err); @@ -3917,54 +3915,54 @@ static void test_manifest_resources(void) }; struct multiple_manifest_test tests[] = { /* Test well-known manifest resource IDs */ - { { (char *)CREATEPROCESS_MANIFEST_RESOURCE_ID }, NULL, ERROR_SUCCESS, FALSE }, - { { (char *)ISOLATIONAWARE_MANIFEST_RESOURCE_ID }, NULL, ERROR_SUCCESS, TRUE }, - { { (char *)ISOLATIONAWARE_NOSTATICIMPORT_MANIFEST_RESOURCE_ID }, NULL, ERROR_SUCCESS, TRUE }, + { { (char *)CREATEPROCESS_MANIFEST_RESOURCE_ID }, NULL, ERROR_SUCCESS }, + { { (char *)ISOLATIONAWARE_MANIFEST_RESOURCE_ID }, NULL, ERROR_SUCCESS }, + { { (char *)ISOLATIONAWARE_NOSTATICIMPORT_MANIFEST_RESOURCE_ID }, NULL, ERROR_SUCCESS }, /* Test remaining reserved manifest resource IDs */ - { { (char *)4 }, NULL, ERROR_SUCCESS, TRUE }, - { { (char *)5 }, NULL, ERROR_SUCCESS, TRUE }, - { { (char *)6 }, NULL, ERROR_SUCCESS, TRUE }, - { { (char *)7 }, NULL, ERROR_SUCCESS, TRUE }, - { { (char *)8 }, NULL, ERROR_SUCCESS, TRUE }, - { { (char *)9 }, NULL, ERROR_SUCCESS, TRUE }, - { { (char *)10 }, NULL, ERROR_SUCCESS, TRUE }, - { { (char *)11 }, NULL, ERROR_SUCCESS, TRUE }, - { { (char *)12 }, NULL, ERROR_SUCCESS, TRUE }, - { { (char *)13 }, NULL, ERROR_SUCCESS, TRUE }, - { { (char *)14 }, NULL, ERROR_SUCCESS, TRUE }, - { { (char *)15 }, NULL, ERROR_SUCCESS, TRUE }, - { { (char *)MAXIMUM_RESERVED_MANIFEST_RESOURCE_ID }, NULL, ERROR_SUCCESS, TRUE }, + { { (char *)4 }, NULL, ERROR_SUCCESS }, + { { (char *)5 }, NULL, ERROR_SUCCESS }, + { { (char *)6 }, NULL, ERROR_SUCCESS }, + { { (char *)7 }, NULL, ERROR_SUCCESS }, + { { (char *)8 }, NULL, ERROR_SUCCESS }, + { { (char *)9 }, NULL, ERROR_SUCCESS }, + { { (char *)10 }, NULL, ERROR_SUCCESS }, + { { (char *)11 }, NULL, ERROR_SUCCESS }, + { { (char *)12 }, NULL, ERROR_SUCCESS }, + { { (char *)13 }, NULL, ERROR_SUCCESS }, + { { (char *)14 }, NULL, ERROR_SUCCESS }, + { { (char *)15 }, NULL, ERROR_SUCCESS }, + { { (char *)MAXIMUM_RESERVED_MANIFEST_RESOURCE_ID }, NULL, ERROR_SUCCESS }, /* Test arbitrary resource IDs */ - { { (char *)0x1234 }, NULL, ERROR_SUCCESS, TRUE }, - { { (char *)0x89ab }, NULL, ERROR_SUCCESS, TRUE }, - { { (char *)0xffff }, NULL, ERROR_SUCCESS, TRUE }, + { { (char *)0x1234 }, NULL, ERROR_SUCCESS }, + { { (char *)0x89ab }, NULL, ERROR_SUCCESS }, + { { (char *)0xffff }, NULL, ERROR_SUCCESS }, /* Test arbitrary LANGID */ - { { (char *)2, MAKELANGID(LANG_ENGLISH,SUBLANG_DEFAULT) }, NULL, ERROR_SUCCESS, TRUE }, - { { (char *)2, MAKELANGID(LANG_FRENCH,SUBLANG_DEFAULT) }, NULL, ERROR_SUCCESS, TRUE }, - { { (char *)2, 0x1234 }, NULL, ERROR_SUCCESS, TRUE }, - { { (char *)2, 0xffff }, NULL, ERROR_SUCCESS, TRUE }, + { { (char *)2, MAKELANGID(LANG_ENGLISH,SUBLANG_DEFAULT) }, NULL, ERROR_SUCCESS }, + { { (char *)2, MAKELANGID(LANG_FRENCH,SUBLANG_DEFAULT) }, NULL, ERROR_SUCCESS }, + { { (char *)2, 0x1234 }, NULL, ERROR_SUCCESS }, + { { (char *)2, 0xffff }, NULL, ERROR_SUCCESS }, /* Test multiple manifest resources coexisting inside a module */ - { { (char *)2, 0 }, wrong_manifest_resources_numbered, ERROR_SUCCESS, TRUE }, + { { (char *)2, 0 }, wrong_manifest_resources_numbered, ERROR_SUCCESS }, { { (char *)2, 0, wrong_manifest1 }, correct_manifest_resources_numbered, - ERROR_SXS_CANT_GEN_ACTCTX, FALSE }, + ERROR_SXS_CANT_GEN_ACTCTX }, /* Test that smaller resource ID takes precedence regardless of language ID */ { { (char *)2, MAKELANGID(LANG_INVARIANT,SUBLANG_NEUTRAL) }, - wrong_manifest_resources_gte_3, ERROR_SUCCESS, TRUE }, + wrong_manifest_resources_gte_3, ERROR_SUCCESS }, { { (char *)2, MAKELANGID(LANG_INVARIANT,SUBLANG_NEUTRAL), wrong_manifest1 }, - correct_manifest_resources_gte_3, ERROR_SXS_CANT_GEN_ACTCTX, FALSE }, + correct_manifest_resources_gte_3, ERROR_SXS_CANT_GEN_ACTCTX }, /* Test multiple manifest resources (ID / name) coexisting inside a module */ - { { (char *)2, 0 }, wrong_manifest_resources_named, ERROR_SUCCESS, TRUE }, + { { (char *)2, 0 }, wrong_manifest_resources_named, ERROR_SUCCESS }, { { (char *)2, 0, wrong_manifest1 }, - correct_manifest_resources_named, ERROR_SXS_CANT_GEN_ACTCTX, FALSE }, + correct_manifest_resources_named, ERROR_SXS_CANT_GEN_ACTCTX }, /* Test name-only RT_MANIFEST resources */ - { { NULL }, correct_manifest_resources_named, ERROR_SXS_CANT_GEN_ACTCTX, FALSE }, + { { NULL }, correct_manifest_resources_named, ERROR_SXS_CANT_GEN_ACTCTX }, }; size_t i; @@ -4093,7 +4091,6 @@ static void subtest_valid_manifest_resources_locale(LANGID actctx_lang) test.manifests = specs; test.expected_error = ERROR_SUCCESS; - test.is_todo_wine = TRUE; err = subtest_manifest_res(manifest_exe, manifest_dll, &test, actctx_lang); if (winetest_debug > 1 && err != ERROR_SUCCESS) diff --git a/dlls/ntdll/actctx.c b/dlls/ntdll/actctx.c index a2e159c76ae..e2adbd3394c 100644 --- a/dlls/ntdll/actctx.c +++ b/dlls/ntdll/actctx.c @@ -2929,6 +2929,24 @@ static NTSTATUS open_nt_file( HANDLE *handle, UNICODE_STRING *name ) FILE_SHARE_READ | FILE_SHARE_DELETE, FILE_SYNCHRONOUS_IO_ALERT ); } +static NTSTATUS find_first_manifest_resource_in_module( HANDLE hModule, const WCHAR **resname ) +{ + static const LDR_RESOURCE_INFO manifest_res_info = { RT_MANIFEST }; + const IMAGE_RESOURCE_DIRECTORY_ENTRY *entry_base, *entry; + const IMAGE_RESOURCE_DIRECTORY *resdir; + NTSTATUS status; + + status = LdrFindResourceDirectory_U( hModule, &manifest_res_info, 1, &resdir ); + if (status != STATUS_SUCCESS) return status; + + if (!resdir->NumberOfIdEntries) return STATUS_RESOURCE_NAME_NOT_FOUND; + entry_base = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(resdir + 1); + entry = entry_base + resdir->NumberOfNamedEntries; + *resname = (const WCHAR *)(ULONG_PTR)entry->u.Id; + + return STATUS_SUCCESS; +} + 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 ) @@ -2951,6 +2969,12 @@ static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assemb hModule, debugstr_w(filename) ); } + if (!resname) + { + status = find_first_manifest_resource_in_module( hModule, &resname ); + if (status != STATUS_SUCCESS) return status; + } + info.Type = RT_MANIFEST; info.Language = lang; if (!((ULONG_PTR)resname >> 16)) @@ -3330,8 +3354,7 @@ static NTSTATUS lookup_assembly(struct actctx_loader* acl, status = open_nt_file( &file, &nameW ); if (!status) { - status = get_manifest_in_pe_file( acl, ai, nameW.Buffer, directory, FALSE, file, - (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID, 0 ); + status = get_manifest_in_pe_file( acl, ai, nameW.Buffer, directory, FALSE, file, NULL, 0 ); NtClose( file ); if (status == STATUS_SUCCESS) break;