Commit 2d519f5a authored by Alexandre Julliard's avatar Alexandre Julliard

ntdll: Support MaxVersionTested in the manifest compatibility element.

parent e8d87a84
......@@ -429,6 +429,8 @@ static const char compat_manifest_vista_7_8_10_81[] =
" <supportedOS Id=\"{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}\" ></supportedOS>" /* Windows 8 */
" <supportedOS Id=\"{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}\" />" /* Windows 10 */
" <supportedOS Id=\"{1f676c76-80e1-4239-95bb-83d0f6d0da78}\" />" /* Windows 8.1 */
" <maxversiontested Id=\"10.0.18358\" />"
" <maxversiontested Id=\"2.3.4.5\" />"
" </application>"
" </compatibility>"
"</assembly>";
......@@ -2818,6 +2820,20 @@ typedef struct _test_act_ctx_compat_info {
COMPATIBILITY_CONTEXT_ELEMENT Elements[10];
} test_act_ctx_compat_info;
/* Win10 versions before 1909 don't have the MaxVersionTested field */
typedef struct
{
GUID Id;
ACTCTX_COMPATIBILITY_ELEMENT_TYPE Type;
} old_win10_COMPATIBILITY_CONTEXT_ELEMENT;
typedef struct
{
DWORD ElementCount;
old_win10_COMPATIBILITY_CONTEXT_ELEMENT Elements[10];
} old_win10_test_act_ctx_compat_info;
static void test_no_compat(HANDLE handle, int line)
{
test_act_ctx_compat_info compat_info;
......@@ -2829,15 +2845,17 @@ static void test_no_compat(HANDLE handle, int line)
&compat_info, sizeof(compat_info), &size);
ok_(__FILE__, line)(b, "CompatibilityInformationInActivationContext failed\n");
ok_(__FILE__, line)(size == sizeof(DWORD), "size mismatch (got %lu, expected 4)\n", size);
ok_(__FILE__, line)(size == offsetof(test_act_ctx_compat_info,Elements[0]) ||
broken(size == offsetof(old_win10_test_act_ctx_compat_info,Elements[0])),
"size mismatch got %lu\n", size);
ok_(__FILE__, line)(compat_info.ElementCount == 0, "unexpected ElementCount %u\n", compat_info.ElementCount);
}
static void test_with_compat(HANDLE handle, DWORD num_compat, const GUID* expected_compat[], int line)
static void test_with_compat(HANDLE handle, DWORD num_compat, DWORD num_version,
const GUID *expected_compat[], const ULONGLONG expected_version[], int line)
{
test_act_ctx_compat_info compat_info;
SIZE_T size;
SIZE_T expected = sizeof(COMPATIBILITY_CONTEXT_ELEMENT) * num_compat + sizeof(DWORD);
DWORD n;
BOOL b;
......@@ -2846,18 +2864,46 @@ static void test_with_compat(HANDLE handle, DWORD num_compat, const GUID* expect
&compat_info, sizeof(compat_info), &size);
ok_(__FILE__, line)(b, "CompatibilityInformationInActivationContext failed\n");
ok_(__FILE__, line)(size == expected, "size mismatch (got %lu, expected %lu)\n", size, expected);
ok_(__FILE__, line)(compat_info.ElementCount == num_compat, "unexpected ElementCount %u\n", compat_info.ElementCount);
for (n = 0; n < num_compat; ++n)
ok_(__FILE__, line)(size == offsetof(test_act_ctx_compat_info,Elements[num_compat + num_version]) ||
broken(size == offsetof(old_win10_test_act_ctx_compat_info,Elements[num_compat])),
"size mismatch got %lu\n", size);
ok_(__FILE__, line)(compat_info.ElementCount == num_compat + num_version ||
broken(compat_info.ElementCount == num_compat),
"unexpected ElementCount %u\n", compat_info.ElementCount);
if (size == offsetof(old_win10_test_act_ctx_compat_info,Elements[num_compat]))
{
for (n = 0; n < num_compat; ++n)
{
old_win10_test_act_ctx_compat_info *info = (old_win10_test_act_ctx_compat_info *)&compat_info;
ok_(__FILE__, line)(IsEqualGUID(&info->Elements[n].Id, expected_compat[n]),
"got wrong clsid %s, expected %s for %u\n",
wine_dbgstr_guid(&info->Elements[n].Id),
wine_dbgstr_guid(expected_compat[n]),
n);
ok_(__FILE__, line)(info->Elements[n].Type == ACTCTX_COMPATIBILITY_ELEMENT_TYPE_OS,
"Wrong type, got %u for %u\n", (DWORD)info->Elements[n].Type, n);
}
}
else
{
ok_(__FILE__, line)(IsEqualGUID(&compat_info.Elements[n].Id, expected_compat[n]),
"got wrong clsid %s, expected %s for %u\n",
wine_dbgstr_guid(&compat_info.Elements[n].Id),
wine_dbgstr_guid(expected_compat[n]),
n);
ok_(__FILE__, line)(compat_info.Elements[n].Type == ACTCTX_COMPATIBILITY_ELEMENT_TYPE_OS,
"Wrong type, got %u for %u\n", (DWORD)compat_info.Elements[n].Type, n);
for (n = 0; n < num_compat; ++n)
{
ok_(__FILE__, line)(IsEqualGUID(&compat_info.Elements[n].Id, expected_compat[n]),
"got wrong clsid %s, expected %s for %u\n",
wine_dbgstr_guid(&compat_info.Elements[n].Id),
wine_dbgstr_guid(expected_compat[n]),
n);
ok_(__FILE__, line)(compat_info.Elements[n].Type == ACTCTX_COMPATIBILITY_ELEMENT_TYPE_OS,
"Wrong type, got %u for %u\n", (DWORD)compat_info.Elements[n].Type, n);
}
for (; n < num_compat + num_version; ++n)
{
ok_(__FILE__, line)(compat_info.Elements[n].Type == ACTCTX_COMPATIBILITY_ELEMENT_TYPE_MAXVERSIONTESTED,
"Wrong type, got %u for %u\n", (DWORD)compat_info.Elements[n].Type, n);
ok_(__FILE__, line)(compat_info.Elements[n].MaxVersionTested == expected_version[n - num_compat],
"Wrong version, got %s for %u\n", wine_dbgstr_longlong(compat_info.Elements[n].MaxVersionTested), n);
}
}
}
......@@ -2931,7 +2977,7 @@ static void test_compatibility(void)
&VISTA_COMPAT_GUID
};
test_basic_info(handle, __LINE__);
test_with_compat(handle, 1, expect_manifest, __LINE__);
test_with_compat(handle, 1, 0, expect_manifest, NULL, __LINE__);
ReleaseActCtx(handle);
}
......@@ -2955,8 +3001,13 @@ static void test_compatibility(void)
&WIN10_COMPAT_GUID,
&WIN81_COMPAT_GUID,
};
static const ULONGLONG expect_version[] =
{
0x000a000047b60000ull, /* 10.0.18358.0 */
0x0002000300040005ull, /* 2.3.4.5 */
};
test_basic_info(handle, __LINE__);
test_with_compat(handle, 5, expect_manifest, __LINE__);
test_with_compat(handle, 5, 2, expect_manifest, expect_version, __LINE__);
ReleaseActCtx(handle);
}
......@@ -2977,7 +3028,7 @@ static void test_compatibility(void)
&OTHER_COMPAT_GUID,
};
test_basic_info(handle, __LINE__);
test_with_compat(handle, 1, expect_manifest, __LINE__);
test_with_compat(handle, 1, 0, expect_manifest, NULL, __LINE__);
ReleaseActCtx(handle);
}
}
......
......@@ -2327,6 +2327,38 @@ static void parse_supportedos_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
if (!end) parse_expect_end_elem(xmlbuf, parent);
}
static void parse_maxversiontested_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
struct actctx_loader *acl, const struct xml_elem *parent )
{
struct xml_attr attr;
BOOL end = FALSE;
while (next_xml_attr(xmlbuf, &attr, &end))
{
if (xml_attr_cmp(&attr, L"Id"))
{
COMPATIBILITY_CONTEXT_ELEMENT *compat;
struct assembly_version version;
if (!(compat = add_compat_context(assembly)))
{
set_error( xmlbuf );
return;
}
parse_version( &attr.value, &version );
compat->Type = ACTCTX_COMPATIBILITY_ELEMENT_TYPE_MAXVERSIONTESTED;
compat->MaxVersionTested = (ULONGLONG)version.major << 48 |
(ULONGLONG)version.minor << 32 | version.build << 16 | version.revision;
}
else if (!is_xmlns_attr( &attr ))
{
WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
}
}
if (!end) parse_expect_end_elem(xmlbuf, parent);
}
static void parse_compatibility_application_elem(xmlbuf_t *xmlbuf, struct assembly *assembly,
struct actctx_loader* acl, const struct xml_elem *parent)
{
......@@ -2338,6 +2370,10 @@ static void parse_compatibility_application_elem(xmlbuf_t *xmlbuf, struct assemb
{
parse_supportedos_elem(xmlbuf, assembly, acl, &elem);
}
else if (xml_elem_cmp(&elem, L"maxversiontested", compatibilityNSW))
{
parse_maxversiontested_elem(xmlbuf, assembly, acl, &elem);
}
else
{
WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
......@@ -5328,8 +5364,11 @@ NTSTATUS WINAPI RtlQueryInformationActivationContext( ULONG flags, HANDLE handle
case CompatibilityInformationInActivationContext:
{
/*ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION*/DWORD *acci = buffer;
COMPATIBILITY_CONTEXT_ELEMENT *elements;
struct acci
{
DWORD ElementCount;
COMPATIBILITY_CONTEXT_ELEMENT Elements[1];
} *acci = buffer;
struct assembly *assembly = NULL;
ULONG num_compat_contexts = 0, n;
SIZE_T len;
......@@ -5340,16 +5379,15 @@ NTSTATUS WINAPI RtlQueryInformationActivationContext( ULONG flags, HANDLE handle
if (assembly)
num_compat_contexts = assembly->num_compat_contexts;
len = sizeof(*acci) + num_compat_contexts * sizeof(COMPATIBILITY_CONTEXT_ELEMENT);
len = offsetof( struct acci, Elements[num_compat_contexts] );
if (retlen) *retlen = len;
if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL;
*acci = num_compat_contexts;
elements = (COMPATIBILITY_CONTEXT_ELEMENT*)(acci + 1);
acci->ElementCount = num_compat_contexts;
for (n = 0; n < num_compat_contexts; ++n)
{
elements[n] = assembly->compat_contexts[n];
acci->Elements[n] = assembly->compat_contexts[n];
}
}
break;
......
......@@ -6442,6 +6442,7 @@ typedef enum {
typedef struct _COMPATIBILITY_CONTEXT_ELEMENT {
GUID Id;
ACTCTX_COMPATIBILITY_ELEMENT_TYPE Type;
ULONGLONG MaxVersionTested;
} COMPATIBILITY_CONTEXT_ELEMENT, *PCOMPATIBILITY_CONTEXT_ELEMENT;
#if !defined(__WINESRC__) && (defined(_MSC_EXTENSIONS) || ((defined(__GNUC__) && __GNUC__ >= 3)))
......
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