From a7c3e1552d69eb60fbe6aea5dfbdc5da89308675 Mon Sep 17 00:00:00 2001 From: Mark Jansen Date: Tue, 6 Feb 2018 16:32:45 +0100 Subject: [PATCH 3/3] ntdll: Parse manifest compatibility section Signed-off-by: Mark Jansen --- dlls/kernel32/tests/actctx.c | 4 -- dlls/ntdll/actctx.c | 136 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 136 insertions(+), 4 deletions(-) diff --git a/dlls/kernel32/tests/actctx.c b/dlls/kernel32/tests/actctx.c index 3ae4f0e545..8df040b3b1 100644 --- a/dlls/kernel32/tests/actctx.c +++ b/dlls/kernel32/tests/actctx.c @@ -2550,10 +2550,8 @@ static void test_no_compat(HANDLE handle, int line) CompatibilityInformationInActivationContext, buffer, sizeof(buffer), &size); -todo_wine { ok_(__FILE__, line)(b, "CompatibilityInformationInActivationContext failed\n"); ok_(__FILE__, line)(size == sizeof(DWORD), "size mismatch (got %lu, expected 4)\n", size); -} ok_(__FILE__, line)(pCompat->ElementCount == 0, "unexpected ElementCount %u\n", pCompat->ElementCount); } @@ -2571,7 +2569,6 @@ static void test_with_compat(HANDLE handle, DWORD num_compat, const GUID* expect CompatibilityInformationInActivationContext, buffer, sizeof(buffer), &size); -todo_wine { ok_(__FILE__, line)(b, "CompatibilityInformationInActivationContext failed\n"); ok_(__FILE__, line)(size == expected, "size mismatch (got %lu, expected %lu)\n", size, expected); ok_(__FILE__, line)(pCompat->ElementCount == num_compat, "unexpected ElementCount %u\n", pCompat->ElementCount); @@ -2587,7 +2584,6 @@ todo_wine { "Wrong type, got %u for %u\n", (DWORD)pCompat->Elements[n].Type, n); } } -} static void test_compatibility(void) { diff --git a/dlls/ntdll/actctx.c b/dlls/ntdll/actctx.c index b978438f6b..42339abcc7 100644 --- a/dlls/ntdll/actctx.c +++ b/dlls/ntdll/actctx.c @@ -499,6 +499,8 @@ struct assembly unsigned int num_dlls; unsigned int allocated_dlls; struct entity_array entities; + COMPATIBILITY_CONTEXT_ELEMENT* compat_contexts; + ULONG num_compat_contexts; }; enum context_sections @@ -622,6 +624,12 @@ static const WCHAR staticW[] = {'s','t','a','t','i','c',0}; static const WCHAR supportsmultilevelundoW[] = {'s','u','p','p','o','r','t','s','m','u','l','t','i','l','e','v','e','l','u','n','d','o',0}; static const WCHAR wantstomenumergeW[] = {'w','a','n','t','s','t','o','m','e','n','u','m','e','r','g','e',0}; +static const WCHAR compatibilityW[] = {'c','o','m','p','a','t','i','b','i','l','i','t','y',0}; +static const WCHAR compatibilityNSW[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','c','o','m','p','a','t','i','b','i','l','i','t','y','.','v','1',0}; +static const WCHAR applicationW[] = {'a','p','p','l','i','c','a','t','i','o','n',0}; +static const WCHAR supportedOSW[] = {'s','u','p','p','o','r','t','e','d','O','S',0}; +static const WCHAR IdW[] = {'I','d',0}; + struct olemisc_entry { const WCHAR *name; @@ -792,6 +800,25 @@ static struct dll_redirect* add_dll_redirect(struct assembly* assembly) return &assembly->dlls[assembly->num_dlls++]; } +static PCOMPATIBILITY_CONTEXT_ELEMENT add_compat_context(struct assembly* assembly) +{ + void *ptr; + if (assembly->num_compat_contexts) + { + unsigned int new_count = assembly->num_compat_contexts + 1; + ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, + assembly->compat_contexts, + new_count * sizeof(COMPATIBILITY_CONTEXT_ELEMENT) ); + } + else + { + ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(COMPATIBILITY_CONTEXT_ELEMENT) ); + } + if (!ptr) return NULL; + assembly->compat_contexts = ptr; + return &assembly->compat_contexts[assembly->num_compat_contexts++]; +} + static void free_assembly_identity(struct assembly_identity *ai) { RtlFreeHeap( GetProcessHeap(), 0, ai->name ); @@ -1075,6 +1102,7 @@ static void actctx_release( ACTIVATION_CONTEXT *actctx ) RtlFreeHeap( GetProcessHeap(), 0, assembly->dlls ); RtlFreeHeap( GetProcessHeap(), 0, assembly->manifest.info ); RtlFreeHeap( GetProcessHeap(), 0, assembly->directory ); + RtlFreeHeap( GetProcessHeap(), 0, assembly->compat_contexts ); free_entity_array( &assembly->entities ); free_assembly_identity(&assembly->id); } @@ -2211,6 +2239,84 @@ static BOOL parse_file_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct return ret; } +static BOOL parse_compatibility_application_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, + struct actctx_loader* acl) +{ + xmlstr_t attr_name, attr_value, elem; + BOOL end = FALSE, ret = TRUE, error; + + while (ret && (ret = next_xml_elem(xmlbuf, &elem))) + { + if (xmlstr_cmp_end(&elem, applicationW)) + { + ret = parse_end_element(xmlbuf); + break; + } + else if (xmlstr_cmp(&elem, supportedOSW)) + { + while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end)) + { + if (xmlstr_cmp(&attr_name, IdW)) + { + UNICODE_STRING str; + COMPATIBILITY_CONTEXT_ELEMENT* compat; + GUID compat_id; + str.Buffer = (PWSTR)attr_value.ptr; + str.Length = str.MaximumLength = (USHORT)attr_value.len * sizeof(WCHAR); + if (RtlGUIDFromString(&str, &compat_id) == STATUS_SUCCESS) + { + if (!(compat = add_compat_context(assembly))) return FALSE; + compat->Type = ACTCX_COMPATIBILITY_ELEMENT_TYPE_OS; + compat->Id = compat_id; + } + else + { + WARN("Invalid guid %s\n", debugstr_xmlstr(&attr_value)); + } + } + else + { + WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), + debugstr_xmlstr(&attr_value)); + } + } + } + else + { + WARN("unknown elem %s\n", debugstr_xmlstr(&elem)); + ret = parse_unknown_elem(xmlbuf, &elem); + } + } + + return ret; +} + +static BOOL parse_compatibility_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, + struct actctx_loader* acl) +{ + xmlstr_t elem; + BOOL ret = TRUE; + + while (ret && (ret = next_xml_elem(xmlbuf, &elem))) + { + if (xmlstr_cmp_end(&elem, compatibilityW)) + { + ret = parse_end_element(xmlbuf); + break; + } + else if (xmlstr_cmp(&elem, applicationW)) + { + ret = parse_compatibility_application_elem(xmlbuf, assembly, acl); + } + else + { + WARN("unknown elem %s\n", debugstr_xmlstr(&elem)); + ret = parse_unknown_elem(xmlbuf, &elem); + } + } + return ret; +} + static BOOL parse_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl, struct assembly* assembly, struct assembly_identity* expected_ai) @@ -2328,6 +2434,10 @@ static BOOL parse_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl, } } } + else if (xml_elem_cmp(&elem, compatibilityW, compatibilityNSW)) + { + ret = parse_compatibility_elem(xmlbuf, assembly, acl); + } else { WARN("unknown element %s\n", debugstr_xmlstr(&elem)); @@ -4987,6 +5097,32 @@ NTSTATUS WINAPI RtlQueryInformationActivationContext( ULONG flags, HANDLE handle } break; + case CompatibilityInformationInActivationContext: + { + ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION *acci = buffer; + struct assembly *assembly = NULL; + ULONG num_compat_contexts = 0, n; + SIZE_T len; + + if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER; + + if (actctx->num_assemblies) assembly = actctx->assemblies; + + if (assembly) + num_compat_contexts = assembly->num_compat_contexts; + len = sizeof(DWORD) + (num_compat_contexts) * sizeof(COMPATIBILITY_CONTEXT_ELEMENT); + + if (retlen) *retlen = len; + if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL; + + acci->ElementCount = num_compat_contexts; + for (n = 0; n < num_compat_contexts; ++n) + { + acci->Elements[n] = assembly->compat_contexts[n]; + } + } + break; + default: FIXME( "class %u not implemented\n", class ); return STATUS_NOT_IMPLEMENTED; -- 2.12.2.windows.1