[PATCH 3/3] ntdll: Parse manifest compatibility section

Mark Jansen mark.jansen at reactos.org
Thu Feb 8 12:41:22 CST 2018


-------------- next part --------------
From a7c3e1552d69eb60fbe6aea5dfbdc5da89308675 Mon Sep 17 00:00:00 2001
From: Mark Jansen <mark.jansen at reactos.org>
Date: Tue, 6 Feb 2018 16:32:45 +0100
Subject: [PATCH 3/3] ntdll: Parse manifest compatibility section

Signed-off-by: Mark Jansen <mark.jansen at reactos.org>
---
 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



More information about the wine-devel mailing list